app: propagate errors from layout parsing, more thorough checking
authorMarcus Fritzsch <marcus_fritzsch@mentor.com>
Tue, 25 Jul 2017 11:03:47 +0000 (13:03 +0200)
committerMarcus Fritzsch <marcus_fritzsch@mentor.com>
Tue, 8 Aug 2017 15:24:00 +0000 (17:24 +0200)
Signed-off-by: Marcus Fritzsch <marcus_fritzsch@mentor.com>
src/app.cpp

index ee3a600..00a8211 100644 (file)
 namespace wm {
 
 #ifndef NDEBUG
-#define DB(expr)                                                               \
-   std::cerr << __FILE__ << ":" << __LINE__ << ":" << __func__ << ": " << expr \
-             << "\n"
+#define DB(expr)                                                           \
+   do {                                                                    \
+      std::ostringstream o;                                                \
+      o << __FILE__ << ":" << __LINE__ << ":" << __func__ << ": " << expr; \
+      logdebug(o.str().c_str());                                           \
+   } while (0)
 #else
 #define DB(expr)
 #endif
@@ -36,49 +39,56 @@ using json = nlohmann::json;
 // We ned to manually unwrap numbers
 template <typename T>
 result<T> get(json const &j) {
+   DB(j);
    T r;
    std::istringstream s(j.get<std::string>());
    s >> r;
-   return s.fail() ? Err<T>("Could not read int") : Ok(r);
+   return !s.eof() || s.fail() ? Err<T>("Could not read int") : Ok(r);
 }
 
 struct wm::area area_from_json(json const &j) {
+   DB(j);
    return wm::area{
       j["name"].get<std::string>(),
       {
-         get<uint32_t>(j["width"]).unwrap(),
-         get<uint32_t>(j["height"]).unwrap(),
-         get<int32_t>(j["x"]).unwrap(),
-         get<int32_t>(j["y"]).unwrap(),
+         get<uint32_t>(j["width"]),
+         get<uint32_t>(j["height"]),
+         get<int32_t>(j["x"]),
+         get<int32_t>(j["y"]),
       },
-      get<uint32_t>(j["zorder"]).unwrap(),
+      get<uint32_t>(j["zorder"]),
    };
 }
 
-struct layout layout_from_json(json const &j) {
+result<struct layout> layout_from_json(json const &j) {
+   DB(j);
    auto &ja = j["areas"];
 
    auto l = wm::layout{j["name"].get<std::string>(), uint32_t(ja.size()), {}};
 
+   if (ja.size() > layout::MAX_N_AREAS) {
+      return Err<struct layout>("Invalid number of areas in layout");
+   }
+
    logdebug("Loading layout '%s' with %u areas", l.name.c_str(),
             unsigned(ja.size()));
 
    std::transform(std::cbegin(ja), std::cend(ja), std::begin(l.areas),
                   area_from_json);
 
-   return l;
+   return Ok(l);
 }
 
 struct result<layouts_type> load_layout(char const *filename) {
+   DB("loading layout from " << filename);
+
    json jlayouts;
    std::ifstream i(filename);
    i >> jlayouts;
 
-   size_t nlayouts = jlayouts.size();
-   auto layouts = layouts_type(nlayouts);
-
+   auto layouts = layouts_type();
    std::transform(std::cbegin(jlayouts), std::cend(jlayouts),
-                  std::begin(layouts), layout_from_json);
+                  std::back_inserter(layouts), layout_from_json);
 
    return Ok(layouts);
 }
@@ -94,6 +104,11 @@ App::App(wl::display *d)
      // layouts(load_layout("../layout.json").unwrap()) {
    assert(g_app == nullptr);
    g_app = this;
+
+   auto l = load_layout("../layout.json");
+   if (l.is_err()) {
+      DB("Could not load layout: " << l.unwrap_err());
+   }
 }
 
 App::~App() { g_app = nullptr; }