diff options
author | Sergei Krivonos <sergei.krivonos@mariadb.com> | 2021-10-25 00:19:37 +0300 |
---|---|---|
committer | Sergei Krivonos <sergeikrivonos@gmail.com> | 2021-11-09 12:06:49 +0200 |
commit | b17576322b600f53c7a0b74cf14830ad5bbad98e (patch) | |
tree | 53a79159fb27e2aa8a02446bdc7d5d0b21e80d36 | |
parent | cf047efd42ab64d730e2b84c7482e56b695678ef (diff) | |
download | mariadb-git-b17576322b600f53c7a0b74cf14830ad5bbad98e.tar.gz |
MDEV-23766: add Json_writer consistency asserts to check array/object sequence
-rw-r--r-- | sql/my_json_writer.cc | 138 | ||||
-rw-r--r-- | sql/my_json_writer.h | 20 |
2 files changed, 116 insertions, 42 deletions
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index f4cf8204d61..ea20854eb1e 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -18,6 +18,14 @@ #include "sql_string.h" #include "my_json_writer.h" +#ifndef NDEBUG +bool Json_writer::named_item_expected() const +{ + return named_items_expectation.size() + && named_items_expectation.back(); +} +#endif + void Json_writer::append_indent() { if (!document_start) @@ -26,9 +34,27 @@ void Json_writer::append_indent() output.append(' '); } -void Json_writer::start_object() +inline void Json_writer::on_start_object() { +#ifndef NDEBUG + if(!is_on_fmt_helper_call) + { + DBUG_ASSERT(got_name == named_item_expected()); + named_items_expectation.push_back(true); + } + + bool was_on_fmt_helper_call= is_on_fmt_helper_call; + is_on_fmt_helper_call= true; +#endif fmt_helper.on_start_object(); +#ifndef NDEBUG + is_on_fmt_helper_call= was_on_fmt_helper_call; +#endif +} + +void Json_writer::start_object() +{ + on_start_object(); if (!element_started) start_element(); @@ -38,11 +64,36 @@ void Json_writer::start_object() first_child=true; element_started= false; document_start= false; +#ifndef NDEBUG + got_name= false; +#endif +} + +bool Json_writer::on_start_array() +{ +#ifndef NDEBUG + bool was_on_fmt_helper_call= is_on_fmt_helper_call; + is_on_fmt_helper_call= true; +#endif + bool helped= fmt_helper.on_start_array(); +#ifndef NDEBUG + is_on_fmt_helper_call= was_on_fmt_helper_call; +#endif + return helped; } void Json_writer::start_array() { - if (fmt_helper.on_start_array()) +#ifndef NDEBUG + if(!is_on_fmt_helper_call) + { + DBUG_ASSERT(got_name == named_item_expected()); + named_items_expectation.push_back(false); + got_name= false; + } +#endif + + if (on_start_array()) return; if (!element_started) @@ -58,6 +109,11 @@ void Json_writer::start_array() void Json_writer::end_object() { +#ifndef NDEBUG + named_items_expectation.pop_back(); + DBUG_ASSERT(!got_name); + got_name= false; +#endif indent_level-=INDENT_SIZE; if (!first_child) append_indent(); @@ -68,6 +124,10 @@ void Json_writer::end_object() void Json_writer::end_array() { +#ifndef NDEBUG + named_items_expectation.pop_back(); + got_name= false; +#endif if (fmt_helper.on_end_array()) return; indent_level-=INDENT_SIZE; @@ -80,31 +140,25 @@ void Json_writer::end_array() Json_writer& Json_writer::add_member(const char *name) { size_t len= strlen(name); - if (fmt_helper.on_add_member(name, len)) - return *this; // handled - - // assert that we are in an object - DBUG_ASSERT(!element_started); - start_element(); - - output.append('"'); - output.append(name, len); - output.append("\": ", 3); - return *this; + return add_member(name, len); } Json_writer& Json_writer::add_member(const char *name, size_t len) { - if (fmt_helper.on_add_member(name, len)) - return *this; // handled - - // assert that we are in an object - DBUG_ASSERT(!element_started); - start_element(); + if (!fmt_helper.on_add_member(name, len)) + { + // assert that we are in an object + DBUG_ASSERT(!element_started); + start_element(); - output.append('"'); - output.append(name, len); - output.append("\": "); + output.append('"'); + output.append(name, len); + output.append("\": ", 3); + } +#ifndef NDEBUG + if (!is_on_fmt_helper_call) + got_name= true; +#endif return *this; } @@ -200,19 +254,13 @@ void Json_writer::add_null() void Json_writer::add_unquoted_str(const char* str) { size_t len= strlen(str); - if (fmt_helper.on_add_str(str, len)) - return; - - if (!element_started) - start_element(); - - output.append(str, len); - element_started= false; + add_unquoted_str(str, len); } void Json_writer::add_unquoted_str(const char* str, size_t len) { - if (fmt_helper.on_add_str(str, len)) + DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected()); + if (on_add_str(str, len)) return; if (!element_started) @@ -222,19 +270,24 @@ void Json_writer::add_unquoted_str(const char* str, size_t len) element_started= false; } +inline bool Json_writer::on_add_str(const char *str, size_t num_bytes) +{ +#ifndef NDEBUG + got_name= false; + bool was_on_fmt_helper_call= is_on_fmt_helper_call; + is_on_fmt_helper_call= true; +#endif + bool helped= fmt_helper.on_add_str(str, num_bytes); +#ifndef NDEBUG + is_on_fmt_helper_call= was_on_fmt_helper_call; +#endif + return helped; +} + void Json_writer::add_str(const char *str) { size_t len= strlen(str); - if (fmt_helper.on_add_str(str, len)) - return; - - if (!element_started) - start_element(); - - output.append('"'); - output.append(str, len); - output.append('"'); - element_started= false; + add_str(str, len); } /* @@ -243,7 +296,8 @@ void Json_writer::add_str(const char *str) void Json_writer::add_str(const char* str, size_t num_bytes) { - if (fmt_helper.on_add_str(str, num_bytes)) + DBUG_ASSERT(is_on_fmt_helper_call || got_name == named_item_expected()); + if (on_add_str(str, num_bytes)) return; if (!element_started) diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index bc8002de529..94cd438bbb0 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -181,6 +181,17 @@ private: class Json_writer { +#ifndef NDEBUG + + std::vector<bool> named_items_expectation; + + bool named_item_expected() const; + + bool got_name; + bool is_on_fmt_helper_call; + +#endif + public: /* Add a member. We must be in an object. */ Json_writer& add_member(const char *name); @@ -204,6 +215,11 @@ public: private: void add_unquoted_str(const char* val); void add_unquoted_str(const char* val, size_t len); + + bool on_add_str(const char *str, size_t num_bytes); + bool on_start_array(); + void on_start_object(); + public: /* Start a child object */ void start_object(); @@ -221,6 +237,10 @@ public: size_t get_truncated_bytes() { return output.get_truncated_bytes(); } Json_writer() : +#ifndef NDEBUG + got_name(false), + is_on_fmt_helper_call(false), +#endif indent_level(0), document_start(true), element_started(false), first_child(true) { |