Commit b1757632 authored by Sergei Krivonos's avatar Sergei Krivonos Committed by Sergei Krivonos

MDEV-23766: add Json_writer consistency asserts to check array/object sequence

parent cf047efd
...@@ -18,6 +18,14 @@ ...@@ -18,6 +18,14 @@
#include "sql_string.h" #include "sql_string.h"
#include "my_json_writer.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() void Json_writer::append_indent()
{ {
if (!document_start) if (!document_start)
...@@ -26,9 +34,27 @@ void Json_writer::append_indent() ...@@ -26,9 +34,27 @@ void Json_writer::append_indent()
output.append(' '); 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(); 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) if (!element_started)
start_element(); start_element();
...@@ -38,11 +64,36 @@ void Json_writer::start_object() ...@@ -38,11 +64,36 @@ void Json_writer::start_object()
first_child=true; first_child=true;
element_started= false; element_started= false;
document_start= 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() 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; return;
if (!element_started) if (!element_started)
...@@ -58,6 +109,11 @@ void Json_writer::start_array() ...@@ -58,6 +109,11 @@ void Json_writer::start_array()
void Json_writer::end_object() void Json_writer::end_object()
{ {
#ifndef NDEBUG
named_items_expectation.pop_back();
DBUG_ASSERT(!got_name);
got_name= false;
#endif
indent_level-=INDENT_SIZE; indent_level-=INDENT_SIZE;
if (!first_child) if (!first_child)
append_indent(); append_indent();
...@@ -68,6 +124,10 @@ void Json_writer::end_object() ...@@ -68,6 +124,10 @@ void Json_writer::end_object()
void Json_writer::end_array() void Json_writer::end_array()
{ {
#ifndef NDEBUG
named_items_expectation.pop_back();
got_name= false;
#endif
if (fmt_helper.on_end_array()) if (fmt_helper.on_end_array())
return; return;
indent_level-=INDENT_SIZE; indent_level-=INDENT_SIZE;
...@@ -80,31 +140,25 @@ void Json_writer::end_array() ...@@ -80,31 +140,25 @@ void Json_writer::end_array()
Json_writer& Json_writer::add_member(const char *name) Json_writer& Json_writer::add_member(const char *name)
{ {
size_t len= strlen(name); size_t len= strlen(name);
if (fmt_helper.on_add_member(name, len)) return 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;
} }
Json_writer& Json_writer::add_member(const char *name, size_t len) Json_writer& Json_writer::add_member(const char *name, size_t len)
{ {
if (fmt_helper.on_add_member(name, len)) if (!fmt_helper.on_add_member(name, len))
return *this; // handled {
// assert that we are in an object
// assert that we are in an object DBUG_ASSERT(!element_started);
DBUG_ASSERT(!element_started); start_element();
start_element();
output.append('"'); output.append('"');
output.append(name, len); output.append(name, len);
output.append("\": "); output.append("\": ", 3);
}
#ifndef NDEBUG
if (!is_on_fmt_helper_call)
got_name= true;
#endif
return *this; return *this;
} }
...@@ -200,19 +254,13 @@ void Json_writer::add_null() ...@@ -200,19 +254,13 @@ void Json_writer::add_null()
void Json_writer::add_unquoted_str(const char* str) void Json_writer::add_unquoted_str(const char* str)
{ {
size_t len= strlen(str); size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len)) add_unquoted_str(str, len);
return;
if (!element_started)
start_element();
output.append(str, len);
element_started= false;
} }
void Json_writer::add_unquoted_str(const char* str, size_t 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; return;
if (!element_started) if (!element_started)
...@@ -222,19 +270,24 @@ void Json_writer::add_unquoted_str(const char* str, size_t len) ...@@ -222,19 +270,24 @@ void Json_writer::add_unquoted_str(const char* str, size_t len)
element_started= false; 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) void Json_writer::add_str(const char *str)
{ {
size_t len= strlen(str); size_t len= strlen(str);
if (fmt_helper.on_add_str(str, len)) add_str(str, len);
return;
if (!element_started)
start_element();
output.append('"');
output.append(str, len);
output.append('"');
element_started= false;
} }
/* /*
...@@ -243,7 +296,8 @@ void Json_writer::add_str(const char *str) ...@@ -243,7 +296,8 @@ void Json_writer::add_str(const char *str)
void Json_writer::add_str(const char* str, size_t num_bytes) 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; return;
if (!element_started) if (!element_started)
......
...@@ -181,6 +181,17 @@ class String_with_limit ...@@ -181,6 +181,17 @@ class String_with_limit
class Json_writer 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: public:
/* Add a member. We must be in an object. */ /* Add a member. We must be in an object. */
Json_writer& add_member(const char *name); Json_writer& add_member(const char *name);
...@@ -204,6 +215,11 @@ class Json_writer ...@@ -204,6 +215,11 @@ class Json_writer
private: private:
void add_unquoted_str(const char* val); void add_unquoted_str(const char* val);
void add_unquoted_str(const char* val, size_t len); 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: public:
/* Start a child object */ /* Start a child object */
void start_object(); void start_object();
...@@ -221,6 +237,10 @@ class Json_writer ...@@ -221,6 +237,10 @@ class Json_writer
size_t get_truncated_bytes() { return output.get_truncated_bytes(); } size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
Json_writer() : Json_writer() :
#ifndef NDEBUG
got_name(false),
is_on_fmt_helper_call(false),
#endif
indent_level(0), document_start(true), element_started(false), indent_level(0), document_start(true), element_started(false),
first_child(true) first_child(true)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment