diff --git a/backend/Makefile b/backend/Makefile index d3cbc27..5428056 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -18,7 +18,7 @@ GDB = 0 ifeq ($(RELEASE),1) CXXFLAGS += -O3 else - CXXFLAGS += -g -Wno-unused + CXXFLAGS += -O0 -g -Wno-unused ifeq ($(GDB),1) CXXFLAGS += -ggdb @@ -26,8 +26,17 @@ else endif ASAN = 0 +UBSAN = 0 ifeq ($(ASAN),1) - CXXFLAGS += -fsanitize=address + ifeq ($(UBSAN),1) + CXXFLAGS += -fsanitize=address,undefined + else + CXXFLAGS += -fsanitize=address + endif +else + ifeq ($(UBSAN),1) + CXXFLAGS += -fsanitize=undefined + endif endif MQTT_HOST= diff --git a/backend/src/json.cpp b/backend/src/json.cpp index efca07d..2694aa8 100644 --- a/backend/src/json.cpp +++ b/backend/src/json.cpp @@ -50,14 +50,14 @@ public: return Tok { TokTy::Eof, std::string_view(nullptr, 0), loc }; } bool matched = false; - while (*i < m_len && std::strchr(" \t\r\n", m_text[*i]) != NULL) { + while (*i < m_len && std::strchr(" \t\r\n", m_text[*i]) != nullptr) { matched = true; step(); } if (matched) { return next(); } - if (strchr(",:[]{}0", m_text[*i]) != NULL) { + if (strchr(",:[]{}", m_text[*i]) != nullptr) { auto ty = (TokTy)m_text[*i]; step(); return tok(ty, loc); @@ -69,7 +69,7 @@ public: if (matched) { return make_ident_tok(loc, i); } - if (m_text[*i] >= '1' && m_text[*i] <= '9') { + if (m_text[*i] == '-' || (m_text[*i] >= '0' && m_text[*i] <= '9')) { return make_number_tok(loc, i); } if (m_text[*i] == '\"') { @@ -114,6 +114,7 @@ private: auto make_number_tok(Loc loc, size_t* i) -> Tok { + step(); while (*i < m_len && m_text[*i] >= '0' && m_text[*i] <= '9') { step(); } @@ -220,12 +221,12 @@ public: CHECK(step()); return val; } else if (*ty == TokTy::Int) { - int64_t value = std::strtol(m_tok.text.data(), NULL, 10); + int64_t value = std::strtol(m_tok.text.data(), nullptr, 10); auto val = std::make_unique(Type::I64, value); CHECK(step()); return val; } else if (*ty == TokTy::Float) { - double value = std::strtod(m_tok.text.data(), NULL); + double value = std::strtod(m_tok.text.data(), nullptr); auto val = std::make_unique(Type::F64, value); CHECK(step()); return val; @@ -347,17 +348,17 @@ public: size_t idx = m_idx; size_t* i = &m_idx; if (*i >= m_text.size()) { - return tok(TokTy::Eof, idx); + return Tok { TokTy::Eof, std::string_view(nullptr, 0), idx }; } bool matched = false; - while (*i < m_text.size() && strchr(" \t\r\n", m_text[*i]) != NULL) { + while (*i < m_text.size() && strchr(" \t\r\n", m_text[*i]) != nullptr) { matched = true; step(); } if (matched) { return next(); } - if (strchr(".[]0", m_text[*i]) != NULL) { + if (strchr(".[]0", m_text[*i]) != nullptr) { auto ty = static_cast(m_text[*i]); step(); return tok(ty, idx); @@ -407,7 +408,7 @@ private: auto tok(TokTy ty, size_t idx) -> Tok { - return { ty, std::string_view(&m_text[idx], this->m_idx - idx), idx }; + return { ty, std::string_view(&m_text[idx], m_idx - idx), idx }; } void step() @@ -437,6 +438,7 @@ class Parser { public: Parser(std::string_view text) : m_tokenizer(text) + , m_tok(m_tokenizer.next().value()) { } @@ -522,7 +524,7 @@ auto resolve(Parser& parser, ValueT& node) -> Result case PathSegTy::Idx: { if (!node.is(Type::Array)) return std::unexpected("expected array"); - auto idx = strtoull(seg->tok.text.data(), NULL, 10); + auto idx = strtoull(seg->tok.text.data(), nullptr, 10); if (!node.has(idx)) return std::unexpected(std::format( "array index {} out of bounds {}", idx, node.size())); diff --git a/backend/src/main.cpp b/backend/src/main.cpp index 4d06c0e..46265b6 100644 --- a/backend/src/main.cpp +++ b/backend/src/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -36,10 +37,22 @@ int main(void) mqtt_client.subscribe("/skateboard/update", [&](std::string_view text) { // std::println("Skateboard: {}", text); - // auto parsed = mst::json::parse(text).value(); + auto result = mst::json::parse(text); - // std::println(".acceleration[0]", - // parsed->query(".acceleration[0]").value()->get_i64()); + if (!result) { + std::println(stderr, + "error: {} at {}", + result.error().message, + result.error().loc.idx); + return; + } + try { + auto parsed = std::move(result.value()); + std::println(".rotation = {}", + parsed->query(".rotation").value()->get_f64()); + } catch (std::runtime_error& ex) { + std::println(stderr, "exception: {}", ex.what()); + } }); auto mqtt_thread = std::thread([&]() { @@ -64,5 +77,7 @@ int main(void) { auto x = mgr.start(); } + + mqtt_thread.join(); return 0; } diff --git a/backend/tests/json.cpp b/backend/tests/json.cpp index 4fd9d90..736a300 100644 --- a/backend/tests/json.cpp +++ b/backend/tests/json.cpp @@ -13,4 +13,12 @@ int main() ASSERT_EQ(**json::parse("3.14"), *json::Value::make_f64(3.14)); ASSERT_EQ(**json::parse("\"hello world\""), *json::Value::make_string("hello world")); + + + { + auto object = *json::parse(R"({"rotation":-0.0123})"); + auto query_result = object->query(std::string_view(".rotation")); + auto f64_value = query_result.value()->get_f64(); + ASSERT_EQ(f64_value, -0.0123); + } }