Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions sql/json_dom.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,16 @@ void Json_array::clear()
delete_container_pointers(m_v);
}

/**
Reserve space in a string buffer. If reallocation is needed,
increase the size of the buffer exponentially.
@param buffer the string buffer
@param needed the number of bytes needed
@return true on error, false on success
*/
static bool reserve(String *buffer, size_t needed) {
return buffer->reserve(needed, buffer->length());
}

/**
Perform quoting on a JSON string to make an external representation
Expand Down Expand Up @@ -1605,8 +1615,8 @@ void Json_array::clear()
*/
bool double_quote(const char *cptr, size_t length, String *buf)
{
if (buf->append('"'))
return true; /* purecov: inspected */
if (reserve(buf, length + 2) || buf->append('"'))
return true; /* purecov: inspected */

for (size_t i= 0; i < length; i++)
{
Expand Down Expand Up @@ -2004,6 +2014,18 @@ static bool newline_and_indent(String *buffer, size_t level)
buffer->fill(buffer->length() + level * 2, ' ');
}

/**
Append a comma to separate elements in JSON arrays and objects.
@param buffer the string buffer
@param pretty true if pretty printing is enabled
@return true on error, false on success
*/
static bool append_comma(String *buffer, bool pretty) {
// Append a comma followed by a blank space. If pretty printing is
// enabled, a newline will be added in front of the next element, so
// the blank space can be omitted.
return buffer->append(',') || (!pretty && buffer->append(' '));
}

/**
Helper function which does all the heavy lifting for
Expand Down Expand Up @@ -2037,7 +2059,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
case Json_dom::J_TIMESTAMP:
{
// Make sure the buffer has space for the datetime and the quotes.
if (buffer->reserve(MAX_DATE_STRING_REP_LENGTH + 2))
if (reserve(buffer, MAX_DATE_STRING_REP_LENGTH + 2))
return true; /* purecov: inspected */
MYSQL_TIME t;
wr.get_datetime(&t);
Expand All @@ -2058,7 +2080,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
size_t array_len= wr.length();
for (uint32 i= 0; i < array_len; ++i)
{
if (i > 0 && buffer->append(pretty ? "," : ", "))
if (i > 0 && append_comma(buffer, pretty))
return true; /* purecov: inspected */

if (pretty && newline_and_indent(buffer, depth))
Expand All @@ -2077,14 +2099,14 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
break;
}
case Json_dom::J_BOOLEAN:
if (buffer->append(wr.get_boolean() ? "true" : "false"))
if (wr.get_boolean() ? buffer->append(STRING_WITH_LEN("true"))
: buffer->append(STRING_WITH_LEN("false")))
return true; /* purecov: inspected */
break;
case Json_dom::J_DECIMAL:
{
int length= DECIMAL_MAX_STR_LENGTH + 1;
if (buffer->reserve(length))
return true; /* purecov: inspected */
if (reserve(buffer, length)) return true;
char *ptr= const_cast<char *>(buffer->ptr()) + buffer->length();
my_decimal m;
if (wr.get_decimal_data(&m) ||
Expand All @@ -2095,7 +2117,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
}
case Json_dom::J_DOUBLE:
{
if (buffer->reserve(MY_GCVT_MAX_FIELD_WIDTH + 1))
if (reserve(buffer, MY_GCVT_MAX_FIELD_WIDTH + 1))
return true; /* purecov: inspected */
double d= wr.get_double();
size_t len= my_gcvt(d, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
Expand All @@ -2111,7 +2133,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
break;
}
case Json_dom::J_NULL:
if (buffer->append("null"))
if (buffer->append(STRING_WITH_LEN("null")))
return true; /* purecov: inspected */
break;
case Json_dom::J_OBJECT:
Expand All @@ -2123,7 +2145,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
for (Json_wrapper_object_iterator iter= wr.object_iterator();
!iter.empty(); iter.next())
{
if (!first && buffer->append(pretty ? "," : ", "))
if (!first && append_comma(buffer, pretty))
return true; /* purecov: inspected */

first= false;
Expand All @@ -2135,7 +2157,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
const char *key_data= key.c_str();
size_t key_length= key.length();
if (print_string(buffer, true, key_data, key_length) ||
buffer->append(": ") ||
buffer->append(':') || buffer->append(' ') ||
wrapper_to_string(iter.elt().second, buffer, true, pretty,
func_name, depth))
return true; /* purecov: inspected */
Expand All @@ -2154,7 +2176,6 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,
if (wr.get_data_length() > base64_encode_max_arg_length())
{
/* purecov: begin inspected */
buffer->append("\"<data too long to decode - unexpected error>\"");
my_error(ER_INTERNAL_ERROR, MYF(0),
"JSON: could not decode opaque data");
return true;
Expand All @@ -2172,7 +2193,7 @@ static bool wrapper_to_string(const Json_wrapper &wr, String *buffer,

// "base64:typeXX:<binary data>"
size_t pos= buffer->length();
if (buffer->reserve(needed) ||
if (reserve(buffer, needed) ||
base64_encode(wr.get_data(), wr.get_data_length(),
const_cast<char*>(buffer->ptr() + pos)))
return true; /* purecov: inspected */
Expand Down