diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed24d3ff..6c499a49 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,7 +186,21 @@ set(diag_STAT_SRCS filesystem/path.h filesystem/resolver.h - ../../lbuild-debug/src/config.h + fmtlib/posix.cc + fmtlib/fmt/time.h + fmtlib/fmt/ostream.h + fmtlib/fmt/format-inl.h + fmtlib/fmt/ranges.h + fmtlib/fmt/core.h + fmtlib/fmt/locale.h + fmtlib/fmt/chrono.h + fmtlib/fmt/color.h + fmtlib/fmt/printf.h + fmtlib/fmt/posix.h + fmtlib/fmt/format.h + fmtlib/format.cc + + ../../lbuild-debug/src/config.h ) set(lnav_SRCS lnav.cc) @@ -195,6 +209,7 @@ include_directories( ../../lbuild-debug/src /opt/local/include /usr/local/opt/sqlite3/include + fmtlib ) include_directories(SYSTEM .) add_executable(lnav ${lnav_SRCS} ${diag_STAT_SRCS}) diff --git a/src/Makefile.am b/src/Makefile.am index f908d06b..6f92ff95 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -120,6 +120,7 @@ AM_LDFLAGS = \ AM_CPPFLAGS = \ -DSYSCONFDIR='"$(sysconfdir)"' \ + -I$(srcdir)/fmtlib \ -Wall \ $(READLINE_CFLAGS) \ $(SQLITE3_CFLAGS) \ @@ -272,7 +273,18 @@ noinst_HEADERS = \ spookyhash/SpookyV2.h \ filesystem/fwd.h \ filesystem/path.h \ - filesystem/resolver.h + filesystem/resolver.h \ + fmtlib/fmt/time.h \ + fmtlib/fmt/ostream.h \ + fmtlib/fmt/format-inl.h \ + fmtlib/fmt/ranges.h \ + fmtlib/fmt/core.h \ + fmtlib/fmt/locale.h \ + fmtlib/fmt/chrono.h \ + fmtlib/fmt/color.h \ + fmtlib/fmt/printf.h \ + fmtlib/fmt/posix.h \ + fmtlib/fmt/format.h if USE_INCLUDED_YAJL noinst_HEADERS += yajl/api/yajl_common.h \ @@ -375,7 +387,9 @@ libdiag_a_SOURCES = \ xterm_mouse.cc \ xterm-palette.c \ yajlpp.cc \ - spookyhash/SpookyV2.cpp + spookyhash/SpookyV2.cpp \ + fmtlib/posix.cc \ + fmtlib/format.cc if USE_INCLUDED_YAJL libdiag_a_SOURCES += yajl/yajl.c \ diff --git a/src/lnav_config.cc b/src/lnav_config.cc index 639248f9..c12a2a68 100644 --- a/src/lnav_config.cc +++ b/src/lnav_config.cc @@ -695,6 +695,7 @@ static void load_config_from(const string &path, vector &errors) ypc.ypc_locations = &lnav_config_locations; ypc.with_obj(lnav_config); ypc.ypc_userdata = &ud; + ypc.with_error_reporter(config_error_reporter); if ((fd = open(path.c_str(), O_RDONLY)) == -1) { if (errno != ENOENT) { char errmsg[1024]; @@ -727,19 +728,12 @@ static void load_config_from(const string &path, vector &errors) break; } if (ypc.parse((const unsigned char *)buffer, rc) != yajl_status_ok) { - errors.push_back(path + - ": invalid json -- " + - string((char *)yajl_get_error(handle, 1, (unsigned char *)buffer, rc))); break; } offset += rc; } if (rc == 0) { - if (ypc.complete_parse() != yajl_status_ok) { - errors.push_back(path + - ": invalid json -- " + - string((char *)yajl_get_error(handle, 0, NULL, 0))); - } + ypc.complete_parse(); } } } @@ -760,10 +754,8 @@ static void load_default_config(yajlpp_parse_context &ypc_builtin, yajl_config(handle, yajl_allow_comments, 1); yajl_config(handle, yajl_allow_multiple_values, 1); if (ypc_builtin.parse((const unsigned char *) config_json, - strlen(config_json)) != yajl_status_ok || - ypc_builtin.complete_parse() != yajl_status_ok) { - errors.push_back("builtin: invalid json -- " + - string((char *)yajl_get_error(handle, 1, (unsigned char *) config_json, strlen(config_json)))); + strlen(config_json)) == yajl_status_ok) { + ypc_builtin.complete_parse(); } } diff --git a/src/log_format_loader.cc b/src/log_format_loader.cc index b6a99436..b8b06c84 100644 --- a/src/log_format_loader.cc +++ b/src/log_format_loader.cc @@ -769,27 +769,12 @@ std::vector load_format_file(const string &filename, std::vecto buffer[0] = buffer[1] = '/'; } if (ypc.parse((const unsigned char *)buffer, rc) != yajl_status_ok) { - errors.push_back( - "error:" + - filename + - ":" + - to_string(ypc.get_line_number()) + - ":invalid json -- " + - string((char *)yajl_get_error(handle, 1, (unsigned char *)buffer, rc))); break; } offset += rc; } if (rc == 0) { - if (ypc.complete_parse() != yajl_status_ok) { - errors.push_back( - "error:" + - filename + - ":" + - to_string(ypc.get_line_number()) + - ":invalid json -- " + - string((char *)yajl_get_error(handle, 0, NULL, 0))); - } + ypc.complete_parse(); } } diff --git a/src/yajlpp.cc b/src/yajlpp.cc index 5b7b48aa..e807fbde 100644 --- a/src/yajlpp.cc +++ b/src/yajlpp.cc @@ -31,6 +31,8 @@ #include "config.h" +#include "fmt/format.h" + #include "yajlpp.hh" #include "yajlpp_def.hh" #include "yajl/api/yajl_parse.h" @@ -498,6 +500,48 @@ const yajl_callbacks yajlpp_parse_context::DEFAULT_CALLBACKS = { yajlpp_parse_context::array_end, }; +yajl_status +yajlpp_parse_context::parse(const unsigned char *jsonText, size_t jsonTextLen) +{ + this->ypc_json_text = jsonText; + + yajl_status retval = yajl_parse(this->ypc_handle, jsonText, jsonTextLen); + + size_t consumed = yajl_get_bytes_consumed(this->ypc_handle); + + this->ypc_line_number += std::count(&jsonText[0], &jsonText[consumed], '\n'); + + this->ypc_json_text = NULL; + + if (retval != yajl_status_ok && this->ypc_error_reporter) { + this->ypc_error_reporter( + *this, LOG_LEVEL_ERROR, + fmt::format("error:{}:{}:invalid json -- {}", + this->ypc_source, + this->get_line_number(), + yajl_get_error(this->ypc_handle, 1, + jsonText, jsonTextLen)).c_str()); + } + + return retval; +} + +yajl_status yajlpp_parse_context::complete_parse() +{ + yajl_status retval = yajl_complete_parse(this->ypc_handle); + + if (retval != yajl_status_ok && this->ypc_error_reporter) { + this->ypc_error_reporter( + *this, LOG_LEVEL_ERROR, + fmt::format("error:{}:invalid json -- {}", + this->ypc_source, + yajl_get_error(this->ypc_handle, 0, + nullptr, 0)).c_str()); + } + + return retval; +} + void yajlpp_gen_context::gen() { yajlpp_map root(this->ygc_handle); diff --git a/src/yajlpp.hh b/src/yajlpp.hh index 292eb264..fc4cfdac 100644 --- a/src/yajlpp.hh +++ b/src/yajlpp.hh @@ -352,18 +352,7 @@ public: return *this; } - yajl_status parse(const unsigned char *jsonText, size_t jsonTextLen) { - this->ypc_json_text = jsonText; - - yajl_status retval = yajl_parse(this->ypc_handle, jsonText, jsonTextLen); - - size_t consumed = yajl_get_bytes_consumed(this->ypc_handle); - - this->ypc_line_number += std::count(&jsonText[0], &jsonText[consumed], '\n'); - - this->ypc_json_text = NULL; - return retval; - }; + yajl_status parse(const unsigned char *jsonText, size_t jsonTextLen);; int get_line_number() const { if (this->ypc_handle != NULL && this->ypc_json_text) { @@ -379,9 +368,7 @@ public: } }; - yajl_status complete_parse() { - return yajl_complete_parse(this->ypc_handle); - }; + yajl_status complete_parse();; void report_error(lnav_log_level_t level, const char *format, ...) { va_list args; diff --git a/test/bad-config2/formats/invalid-config/config.malformed.json b/test/bad-config2/formats/invalid-config/config.malformed.json new file mode 100644 index 00000000..0935e8b7 --- /dev/null +++ b/test/bad-config2/formats/invalid-config/config.malformed.json @@ -0,0 +1,5 @@ +{ + "ui": "theme", + "abc", + "def": "" +} \ No newline at end of file diff --git a/test/bad-config2/formats/invalid-config/config.truncated.json b/test/bad-config2/formats/invalid-config/config.truncated.json new file mode 100644 index 00000000..fc01f0dc --- /dev/null +++ b/test/bad-config2/formats/invalid-config/config.truncated.json @@ -0,0 +1,2 @@ +{ + "ui": "theme" diff --git a/test/test_config.sh b/test/test_config.sh index 6c0e73d8..9d3cf632 100755 --- a/test/test_config.sh +++ b/test/test_config.sh @@ -23,5 +23,19 @@ run_test ${lnav_test} -n \ sed -i "" -e "s|/.*/format|format|g" `test_err_filename` check_error_output "config bad theme" <