From 92704ae8f0773d4f57e8b56e76db5d3e60885132 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Thu, 9 Apr 2020 13:06:53 -0700 Subject: [PATCH] Add parse error handling to rjp++ --- rjp++/include/parse.hpp | 40 ++++++++++++++++++++++++++-------------- rjp++/src/rjp.cpp | 39 ++++++++++++++++++++++++++++++--------- rjp++/src/string.cpp | 2 +- rjp++/tests/parse.cpp | 8 ++++---- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/rjp++/include/parse.hpp b/rjp++/include/parse.hpp index e54cec5..b5fd932 100644 --- a/rjp++/include/parse.hpp +++ b/rjp++/include/parse.hpp @@ -28,11 +28,29 @@ namespace rjp{ + class parse_res + { + private: + RJP_value* m_value; + RJP_parse_error m_err; + + public: + parse_res(RJP_value* val, const RJP_parse_error& err); + parse_res(const parse_res*) = delete; + parse_res(parse_res&& p); + + ~parse_res(void); + + operator bool(void)const; + bool valid(void)const; + + value get_value(void); + string errstr(void)const; + }; + string to_json(const value& val, int format = RJP_FORMAT_PRETTY); - value parse_json(const rexy::string_base& str, RJP_parse_flag = RJP_PARSE_NONE); - value parse_json(const rexy::string_base& str, RJP_parse_flag, RJP_parse_error&); - value parse_json(const char* str, RJP_parse_flag = RJP_PARSE_NONE); - value parse_json(const char* str, RJP_parse_flag, RJP_parse_error&); + parse_res parse_json(const rexy::string_base& str, RJP_parse_flag = RJP_PARSE_NONE); + parse_res parse_json(const char* str, RJP_parse_flag = RJP_PARSE_NONE); namespace detail{ template struct sequence_tup{}; @@ -73,20 +91,14 @@ namespace rjp{ int irjp_parse_callback(char* dest, int size, void* userdata); } template - value parse_json(RJP_parse_flag f, Func&& func, Args&&... args){ + parse_res parse_json(RJP_parse_flag f, Func&& func, Args&&... args){ RJP_parse_callback cb; detail::invoker_impl inv(std::forward(func), std::forward(args)...); cb.data = static_cast(&inv); cb.read = detail::irjp_parse_callback; - return value(detail::parse_cback(f, &cb), true); - } - template - value parse_json(RJP_parse_flag f, RJP_parse_error& err, Func&& func, Args&&... args){ - RJP_parse_callback cb; - detail::invoker_impl inv(std::forward(func), std::forward(args)...); - cb.data = static_cast(&inv); - cb.read = detail::irjp_parse_callback; - return value(detail::parse_cback(f, &cb, err), true); + RJP_parse_error err = {}; + RJP_value* v = detail::parse_cback(f, &cb, err); + return parse_res(v, err); } } diff --git a/rjp++/src/rjp.cpp b/rjp++/src/rjp.cpp index 9fb84fc..a16595f 100644 --- a/rjp++/src/rjp.cpp +++ b/rjp++/src/rjp.cpp @@ -27,22 +27,43 @@ namespace rjp{ + parse_res::parse_res(RJP_value* val, const RJP_parse_error& err): + m_value(val), m_err(err){} + parse_res::parse_res(parse_res&& p): + m_value(std::exchange(p.m_value, nullptr)), m_err(std::move(p.m_err)){} + + parse_res::~parse_res(void){ + rjp_free_value(m_value); + if(m_err.parsestate) + rjp_delete_parse_error(&m_err); + } + + parse_res::operator bool(void)const{ + return valid(); + } + bool parse_res::valid(void)const{ + return m_value != nullptr; + } + + value parse_res::get_value(void){ + return value(std::exchange(m_value, nullptr), true); + } + string parse_res::errstr(void)const{ + return string(rexy::steal(rjp_parse_error_to_string(&m_err))); + } + string to_json(const value& val, int format){ string s; s.reset(rjp_to_json(val.raw(), format)); return s; } - value parse_json(const rexy::string_base& str, RJP_parse_flag flags, RJP_parse_error& err){ - return parse_json(str.get(), flags, err); - } - value parse_json(const rexy::string_base& str, RJP_parse_flag flags){ + parse_res parse_json(const rexy::string_base& str, RJP_parse_flag flags){ return parse_json(str.get(), flags); } - value parse_json(const char* str, RJP_parse_flag flags){ - return value(rjp_parse(str, flags, NULL), true); - } - value parse_json(const char* str, RJP_parse_flag flags, RJP_parse_error& err){ - return value(rjp_parse(str, flags, &err), true); + parse_res parse_json(const char* str, RJP_parse_flag flags){ + RJP_parse_error err = {}; + RJP_value* v = rjp_parse(str, flags, &err); + return parse_res(v, err); } namespace detail{ int irjp_parse_callback(char* dest, int size, void* userdata){ diff --git a/rjp++/src/string.cpp b/rjp++/src/string.cpp index 4c6af1e..11b2c4f 100644 --- a/rjp++/src/string.cpp +++ b/rjp++/src/string.cpp @@ -24,7 +24,7 @@ namespace rjp{ string::string(RJP_value* r): - rexy::string_intermediary(r ? rjp_get_string(r)->value : nullptr, + rexy::string_intermediary(rexy::steal(r ? rjp_get_string(r)->value : nullptr), r ? rjp_get_string(r)->length : 0, r ? rjp_get_string(r)->length : 0) { diff --git a/rjp++/tests/parse.cpp b/rjp++/tests/parse.cpp index 31782e8..e941b62 100644 --- a/rjp++/tests/parse.cpp +++ b/rjp++/tests/parse.cpp @@ -16,22 +16,22 @@ int read_callback(char* c, int size, const char* data, int datalen, int& datapos return i; } -int handle_res(const rjp::value& res){ +int handle_res(const rjp::parse_res& res){ if(res.valid()){ fprintf(stderr, "Accepted\n"); }else{ - fprintf(stderr, "Rejected\n"); + fprintf(stderr, "%s\n", res.errstr().get()); } return !res.valid(); } int test_cbacks(const char* str, RJP_parse_flag flags){ int pos = 0; - rjp::value res = rjp::parse_json(flags, read_callback, str, strlen(str), pos); + rjp::parse_res res = rjp::parse_json(flags, read_callback, str, strlen(str), pos); return handle_res(res); } int test(const char* str, RJP_parse_flag flags){ - rjp::value res = rjp::parse_json(str, flags); + rjp::parse_res res = rjp::parse_json(str, flags); return handle_res(res); }