From c7d2f8f8cd922f033a053723f82bb9b5bee976d9 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Mon, 13 May 2013 09:01:07 +0200 Subject: [PATCH] some json / shaped-json and string handling improvements --- UnitTests/Philadelphia/string-utf8-test.cpp | 4 +- arangod/Ahuacatl/ahuacatl-codegen.c | 17 +- arangod/Ahuacatl/ahuacatl-conversions.c | 91 +++++--- .../RestHandler/RestVocbaseBaseHandler.cpp | 2 +- lib/BasicsC/json.c | 7 +- lib/BasicsC/tri-strings.c | 20 +- lib/BasicsC/tri-strings.h | 13 +- lib/ShapedJson/shaped-json.c | 214 ++++++++++++------ 8 files changed, 255 insertions(+), 113 deletions(-) diff --git a/UnitTests/Philadelphia/string-utf8-test.cpp b/UnitTests/Philadelphia/string-utf8-test.cpp index 82ef444d7d..7d8fd77f1f 100644 --- a/UnitTests/Philadelphia/string-utf8-test.cpp +++ b/UnitTests/Philadelphia/string-utf8-test.cpp @@ -34,10 +34,10 @@ // ----------------------------------------------------------------------------- #define TEST_STRING(str) \ - TRI_EscapeUtf8String(str, strlen(str), true, &outLength); + TRI_EscapeUtf8String(str, strlen(str), true, &outLength, true); #define TEST_STRING_L(str, len) \ - TRI_EscapeUtf8String(str, len, true, &outLength); + TRI_EscapeUtf8String(str, len, true, &outLength, true); // ----------------------------------------------------------------------------- // --SECTION-- private constants diff --git a/arangod/Ahuacatl/ahuacatl-codegen.c b/arangod/Ahuacatl/ahuacatl-codegen.c index 8e5f9766cd..9ae2d7a5a6 100644 --- a/arangod/Ahuacatl/ahuacatl-codegen.c +++ b/arangod/Ahuacatl/ahuacatl-codegen.c @@ -161,6 +161,16 @@ static inline bool OutputString (TRI_string_buffer_t* const buffer, return (TRI_AppendStringStringBuffer(buffer, value) == TRI_ERROR_NO_ERROR); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief append a string to the buffer +//////////////////////////////////////////////////////////////////////////////// + +static inline bool OutputString2 (TRI_string_buffer_t* const buffer, + const char* const value, + size_t length) { + return (TRI_AppendString2StringBuffer(buffer, value, length) == TRI_ERROR_NO_ERROR); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief append a single character to the buffer //////////////////////////////////////////////////////////////////////////////// @@ -259,9 +269,10 @@ static inline void ScopeOutputQuoted2 (TRI_aql_codegen_js_t* const generator, generator->_errorCode = TRI_ERROR_OUT_OF_MEMORY; } - escaped = TRI_EscapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, value, strlen(value), false, &outLength); - if (escaped) { - if (! OutputString(scope->_buffer, escaped)) { + escaped = TRI_EscapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, value, strlen(value), false, &outLength, false); + + if (escaped != NULL) { + if (! OutputString2(scope->_buffer, escaped, outLength)) { generator->_errorCode = TRI_ERROR_OUT_OF_MEMORY; } diff --git a/arangod/Ahuacatl/ahuacatl-conversions.c b/arangod/Ahuacatl/ahuacatl-conversions.c index fd25ed79a1..a4e665ee2b 100644 --- a/arangod/Ahuacatl/ahuacatl-conversions.c +++ b/arangod/Ahuacatl/ahuacatl-conversions.c @@ -119,7 +119,7 @@ static bool AppendListValues (TRI_string_buffer_t* const buffer, n = node->_members._length; for (i = 0; i < n; ++i) { if (i > 0) { - if (TRI_AppendStringStringBuffer(buffer, ", ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, ", ", 2) != TRI_ERROR_NO_ERROR) { return false; } } @@ -327,20 +327,30 @@ bool TRI_ValueJavascriptAql (TRI_string_buffer_t* const buffer, const TRI_aql_value_t* const value, const TRI_aql_value_type_e type) { switch (type) { - case TRI_AQL_TYPE_FAIL: - return (TRI_AppendStringStringBuffer(buffer, "fail") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_FAIL: { + return (TRI_AppendString2StringBuffer(buffer, "fail", 4) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_NULL: - return (TRI_AppendStringStringBuffer(buffer, "null") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_NULL: { + return (TRI_AppendString2StringBuffer(buffer, "null", 4) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_BOOL: - return (TRI_AppendStringStringBuffer(buffer, value->_value._bool ? "true" : "false") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_BOOL: { + if (value->_value._bool) { + return (TRI_AppendString2StringBuffer(buffer, "true", 4) == TRI_ERROR_NO_ERROR); + } + else { + return (TRI_AppendString2StringBuffer(buffer, "false", 5) == TRI_ERROR_NO_ERROR); + } + } - case TRI_AQL_TYPE_INT: + case TRI_AQL_TYPE_INT: { return (TRI_AppendInt64StringBuffer(buffer, value->_value._int) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_DOUBLE: + case TRI_AQL_TYPE_DOUBLE: { return (TRI_AppendDoubleStringBuffer(buffer, value->_value._double) == TRI_ERROR_NO_ERROR); + } case TRI_AQL_TYPE_STRING: { char* escapedString; @@ -354,12 +364,13 @@ bool TRI_ValueJavascriptAql (TRI_string_buffer_t* const buffer, value->_value._string, strlen(value->_value._string), false, - &outLength); + &outLength, + false); if (escapedString == NULL) { return false; } - if (TRI_AppendStringStringBuffer(buffer, escapedString) != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, escapedString, outLength) != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, escapedString); return false; @@ -426,20 +437,30 @@ bool TRI_ValueStringAql (TRI_string_buffer_t* const buffer, const TRI_aql_value_t* const value, const TRI_aql_value_type_e type) { switch (type) { - case TRI_AQL_TYPE_FAIL: - return (TRI_AppendStringStringBuffer(buffer, "fail") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_FAIL: { + return (TRI_AppendString2StringBuffer(buffer, "fail", 4) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_NULL: - return (TRI_AppendStringStringBuffer(buffer, "null") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_NULL: { + return (TRI_AppendString2StringBuffer(buffer, "null", 4) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_BOOL: - return (TRI_AppendStringStringBuffer(buffer, value->_value._bool ? "true" : "false") == TRI_ERROR_NO_ERROR); + case TRI_AQL_TYPE_BOOL: { + if (value->_value._bool) { + return (TRI_AppendString2StringBuffer(buffer, "true", 4) == TRI_ERROR_NO_ERROR); + } + else { + return (TRI_AppendString2StringBuffer(buffer, "false", 5) == TRI_ERROR_NO_ERROR); + } + } - case TRI_AQL_TYPE_INT: + case TRI_AQL_TYPE_INT: { return (TRI_AppendInt64StringBuffer(buffer, value->_value._int) == TRI_ERROR_NO_ERROR); + } - case TRI_AQL_TYPE_DOUBLE: + case TRI_AQL_TYPE_DOUBLE: { return (TRI_AppendDoubleStringBuffer(buffer, value->_value._double) == TRI_ERROR_NO_ERROR); + } case TRI_AQL_TYPE_STRING: { if (TRI_AppendCharStringBuffer(buffer, '"') != TRI_ERROR_NO_ERROR) { @@ -473,7 +494,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, " : ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, " : ", 3) != TRI_ERROR_NO_ERROR) { return false; } @@ -481,7 +502,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, } case TRI_AQL_NODE_LIST: { - if (TRI_AppendStringStringBuffer(buffer, "[ ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, "[ ", 2) != TRI_ERROR_NO_ERROR) { return false; } @@ -489,11 +510,11 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - return (TRI_AppendStringStringBuffer(buffer, " ]") == TRI_ERROR_NO_ERROR); + return (TRI_AppendString2StringBuffer(buffer, " ]", 2) == TRI_ERROR_NO_ERROR); } case TRI_AQL_NODE_ARRAY: { - if (TRI_AppendStringStringBuffer(buffer, "{ ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, "{ ", 2) != TRI_ERROR_NO_ERROR) { return false; } @@ -501,7 +522,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - return (TRI_AppendStringStringBuffer(buffer, " }") == TRI_ERROR_NO_ERROR); + return (TRI_AppendString2StringBuffer(buffer, " }", 2) == TRI_ERROR_NO_ERROR); } case TRI_AQL_NODE_OPERATOR_UNARY_PLUS: @@ -542,7 +563,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, " ? ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, " ? ", 3) != TRI_ERROR_NO_ERROR) { return false; } @@ -550,7 +571,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, " : ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, " : ", 3) != TRI_ERROR_NO_ERROR) { return false; } @@ -562,7 +583,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, ".") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendCharStringBuffer(buffer, '.') != TRI_ERROR_NO_ERROR) { return false; } @@ -574,7 +595,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, "[") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendCharStringBuffer(buffer, '[') != TRI_ERROR_NO_ERROR) { return false; } @@ -582,7 +603,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - return TRI_AppendStringStringBuffer(buffer, "]") == TRI_ERROR_NO_ERROR; + return TRI_AppendCharStringBuffer(buffer, ']') == TRI_ERROR_NO_ERROR; } case TRI_AQL_NODE_FCALL: { @@ -592,7 +613,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, "(") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendCharStringBuffer(buffer, '(') != TRI_ERROR_NO_ERROR) { return false; } @@ -600,7 +621,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - return TRI_AppendStringStringBuffer(buffer, ")") == TRI_ERROR_NO_ERROR; + return TRI_AppendCharStringBuffer(buffer, ')') == TRI_ERROR_NO_ERROR; } case TRI_AQL_NODE_FCALL_USER: { @@ -608,7 +629,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, "(") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendCharStringBuffer(buffer, '(') != TRI_ERROR_NO_ERROR) { return false; } @@ -616,7 +637,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - return TRI_AppendStringStringBuffer(buffer, ")") == TRI_ERROR_NO_ERROR; + return TRI_AppendCharStringBuffer(buffer, ')') == TRI_ERROR_NO_ERROR; } case TRI_AQL_NODE_EXPAND: { @@ -654,7 +675,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, return false; } - if (TRI_AppendStringStringBuffer(buffer, " = ") != TRI_ERROR_NO_ERROR) { + if (TRI_AppendString2StringBuffer(buffer, " = ", 3) != TRI_ERROR_NO_ERROR) { return false; } @@ -662,7 +683,7 @@ bool TRI_NodeStringAql (TRI_string_buffer_t* const buffer, } default: { - // nadata + // nada } } diff --git a/arangod/RestHandler/RestVocbaseBaseHandler.cpp b/arangod/RestHandler/RestVocbaseBaseHandler.cpp index 632ec1dcb8..905f751ee4 100644 --- a/arangod/RestHandler/RestVocbaseBaseHandler.cpp +++ b/arangod/RestHandler/RestVocbaseBaseHandler.cpp @@ -380,7 +380,7 @@ void RestVocbaseBaseHandler::generateDocument (const TRI_voc_cid_t cid, _response->headResponse(TRI_LengthStringBuffer(&buffer)); } - TRI_AnnihilateStringBuffer(&buffer); + TRI_DestroyStringBuffer(&buffer); } //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/BasicsC/json.c b/lib/BasicsC/json.c index 2a23f98792..5693afcd03 100644 --- a/lib/BasicsC/json.c +++ b/lib/BasicsC/json.c @@ -107,7 +107,8 @@ static int StringifyJson (TRI_memory_zone_t* zone, object->_value._string.data, object->_value._string.length - 1, false, - &outLength); + &outLength, + false); if (ptr == NULL) { return TRI_ERROR_OUT_OF_MEMORY; @@ -288,7 +289,9 @@ static inline void InitArray (TRI_memory_zone_t* zone, TRI_InitVector(&result->_value._objects, zone, sizeof(TRI_json_t)); } else { - TRI_InitVector2(&result->_value._objects, zone, sizeof(TRI_json_t), initialSize); + // need to allocate twice the space because for each array entry, + // we need one object for the attribute key, and one for the attribute value + TRI_InitVector2(&result->_value._objects, zone, 2 * sizeof(TRI_json_t), initialSize); } } diff --git a/lib/BasicsC/tri-strings.c b/lib/BasicsC/tri-strings.c index 6625a18ec6..508539168f 100644 --- a/lib/BasicsC/tri-strings.c +++ b/lib/BasicsC/tri-strings.c @@ -1164,8 +1164,12 @@ char* TRI_EscapeControlsCString (char const* in, size_t inLength, size_t* outLen /// @brief escapes special characters using unicode escapes //////////////////////////////////////////////////////////////////////////////// -char* TRI_EscapeUtf8String (char const* in, size_t inLength, bool escapeSlash, size_t* outLength) { - return TRI_EscapeUtf8StringZ(TRI_CORE_MEM_ZONE, in, inLength, escapeSlash, outLength); +char* TRI_EscapeUtf8String (char const* in, + size_t inLength, + bool escapeSlash, + size_t* outLength, + bool compactResult) { + return TRI_EscapeUtf8StringZ(TRI_CORE_MEM_ZONE, in, inLength, escapeSlash, outLength, compactResult); } //////////////////////////////////////////////////////////////////////////////// @@ -1176,7 +1180,8 @@ char* TRI_EscapeUtf8StringZ (TRI_memory_zone_t* zone, char const* in, size_t inLength, bool escapeSlash, - size_t* outLength) { + size_t* outLength, + bool compactResult) { char * buffer; char * qtr; char const * ptr; @@ -1316,13 +1321,18 @@ char* TRI_EscapeUtf8StringZ (TRI_memory_zone_t* zone, *qtr = '\0'; *outLength = (size_t) (qtr - buffer); + if (! compactResult) { + return buffer; + } + qtr = TRI_Allocate(zone, *outLength + 1, false); if (qtr != NULL) { memcpy(qtr, buffer, *outLength + 1); + + TRI_Free(zone, buffer); } - - TRI_Free(zone, buffer); + return qtr; } diff --git a/lib/BasicsC/tri-strings.h b/lib/BasicsC/tri-strings.h index fc1c375c17..baedb4abd0 100644 --- a/lib/BasicsC/tri-strings.h +++ b/lib/BasicsC/tri-strings.h @@ -287,13 +287,22 @@ char* TRI_EscapeCString (char const* in, size_t inLength, size_t* outLength); /// escape the character '/'. //////////////////////////////////////////////////////////////////////////////// -char* TRI_EscapeUtf8String (char const* in, size_t inLength, bool escapeSlash, size_t* outLength); +char* TRI_EscapeUtf8String (char const* in, + size_t inLength, + bool escapeSlash, + size_t* outLength, + bool); //////////////////////////////////////////////////////////////////////////////// /// @brief escapes special characters using unicode escapes //////////////////////////////////////////////////////////////////////////////// -char* TRI_EscapeUtf8StringZ (TRI_memory_zone_t*, char const* in, size_t inLength, bool escapeSlash, size_t* outLength); +char* TRI_EscapeUtf8StringZ (TRI_memory_zone_t*, + char const* in, + size_t inLength, + bool escapeSlash, + size_t* outLength, + bool); //////////////////////////////////////////////////////////////////////////////// /// @brief unescapes unicode escape sequences diff --git a/lib/ShapedJson/shaped-json.c b/lib/ShapedJson/shaped-json.c index bfe241ecd4..490036b340 100644 --- a/lib/ShapedJson/shaped-json.c +++ b/lib/ShapedJson/shaped-json.c @@ -853,7 +853,9 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, T n = f + v; // now sort the shape entries - TRI_SortShapeValues(values, n); + if (n > 1) { + TRI_SortShapeValues(values, n); + } #ifdef DEBUG_JSON_SHAPER printf("shape values\n------------\ntotal: %u, fixed: %u, variable: %u\n", @@ -1105,17 +1107,21 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, TRI_shape_aid_t const* aids; TRI_shape_size_t const* offsetsF; TRI_shape_size_t const* offsetsV; - - array = TRI_CreateArrayJson(shaper->_memoryZone); - - if (array == NULL) { - return NULL; - } + + TRI_shape_sid_t cachedSid; + TRI_shape_t const* cachedShape; s = (TRI_array_shape_t const*) shape; f = s->_fixedEntries; v = s->_variableEntries; n = f + v; + + // create an array with the appropriate size + array = TRI_CreateArray2Json(shaper->_memoryZone, (size_t) n); + + if (array == NULL) { + return NULL; + } qtr = (char const*) shape; qtr += sizeof(TRI_array_shape_t); @@ -1127,6 +1133,9 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, qtr += n * sizeof(TRI_shape_aid_t); offsetsF = (TRI_shape_size_t const*) qtr; + + cachedSid = 0; + cachedShape = NULL; for (i = 0; i < f; ++i, ++sids, ++aids, ++offsetsF) { TRI_shape_sid_t sid = *sids; @@ -1137,8 +1146,16 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, TRI_json_t* element; offset = *offsetsF; - subshape = shaper->lookupShapeId(shaper, sid); name = shaper->lookupAttributeId(shaper, aid); + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } if (subshape == NULL) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); @@ -1172,8 +1189,16 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, TRI_json_t* element; offset = *offsetsV; - subshape = shaper->lookupShapeId(shaper, sid); name = shaper->lookupAttributeId(shaper, aid); + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } if (subshape == NULL) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); @@ -1219,21 +1244,29 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, TRI_shape_length_list_t l; TRI_shape_length_list_t i; + + TRI_shape_sid_t cachedSid; + TRI_shape_t const* cachedShape; - list = TRI_CreateListJson(shaper->_memoryZone); + ptr = data; + l = * (TRI_shape_length_list_t const*) ptr; + + // create a list with the appropriate size + list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); if (list == NULL) { return NULL; } - ptr = data; - l = * (TRI_shape_length_list_t const*) ptr; ptr += sizeof(TRI_shape_length_list_t); sids = (TRI_shape_sid_t const*) ptr; ptr += l * sizeof(TRI_shape_sid_t); offsets = (TRI_shape_size_t const*) ptr; + + cachedSid = 0; + cachedShape = NULL; for (i = 0; i < l; ++i, ++sids, ++offsets) { TRI_shape_sid_t sid = *sids; @@ -1242,7 +1275,15 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, TRI_json_t* element; offset = *offsets; - subshape = shaper->lookupShapeId(shaper, sid); + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } if (subshape == NULL) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); @@ -1281,35 +1322,38 @@ static TRI_json_t* JsonShapeDataHomogeneousList (TRI_shaper_t* shaper, TRI_shape_length_list_t l; TRI_shape_sid_t sid; TRI_shape_size_t const* offsets; + TRI_shape_t const* subshape; char const* ptr; s = (TRI_homogeneous_list_shape_t const*) shape; sid = s->_sidEntry; + + subshape = shaper->lookupShapeId(shaper, sid); + + if (subshape == NULL) { + LOG_WARNING("cannot find shape #%u", (unsigned int) sid); + + return NULL; + } ptr = data; - list = TRI_CreateListJson(shaper->_memoryZone); + l = * (TRI_shape_length_list_t const*) ptr; + + // create a list with the appropriate size + list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); if (list == NULL) { return NULL; } - l = * (TRI_shape_length_list_t const*) ptr; - ptr += sizeof(TRI_shape_length_list_t); offsets = (TRI_shape_size_t const*) ptr; for (i = 0; i < l; ++i, ++offsets) { TRI_shape_size_t offset; - TRI_shape_t const* subshape; TRI_json_t* element; offset = *offsets; - subshape = shaper->lookupShapeId(shaper, sid); - - if (subshape == NULL) { - LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - continue; - } element = JsonShapeData(shaper, subshape, data + offset, offsets[1] - offset); @@ -1344,30 +1388,36 @@ static TRI_json_t* JsonShapeDataHomogeneousSizedList (TRI_shaper_t* shaper, TRI_shape_sid_t sid; TRI_shape_size_t length; TRI_shape_size_t offset; + TRI_shape_t const* subshape; char const* ptr; s = (TRI_homogeneous_sized_list_shape_t const*) shape; sid = s->_sidEntry; + + subshape = shaper->lookupShapeId(shaper, sid); + + if (subshape == NULL) { + LOG_WARNING("cannot find shape #%u", (unsigned int) sid); + + return NULL; + } ptr = data; - list = TRI_CreateListJson(shaper->_memoryZone); + l = * (TRI_shape_length_list_t const*) ptr; + + // create a list with the appropriate size + list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); + if (list == NULL) { + return NULL; + } + length = s->_sizeEntry; offset = sizeof(TRI_shape_length_list_t); - l = * (TRI_shape_length_list_t const*) ptr; - for (i = 0; i < l; ++i, offset += length) { - TRI_shape_t const* subshape; TRI_json_t* element; - subshape = shaper->lookupShapeId(shaper, sid); - - if (subshape == NULL) { - LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - continue; - } - element = JsonShapeData(shaper, subshape, data + offset, length); if (element == NULL) { @@ -1491,15 +1541,15 @@ static bool StringifyJsonShapeDataNumber (TRI_shaper_t* shaper, if (v != v) { // NaN - res = TRI_AppendStringStringBuffer(buffer, "null"); + res = TRI_AppendString2StringBuffer(buffer, "null", 4); } else if (v == HUGE_VAL) { // +inf - res = TRI_AppendStringStringBuffer(buffer, "null"); + res = TRI_AppendString2StringBuffer(buffer, "null", 4); } else if (v == -HUGE_VAL) { // -inf - res = TRI_AppendStringStringBuffer(buffer, "null"); + res = TRI_AppendString2StringBuffer(buffer, "null", 4); } else { res = TRI_AppendDoubleStringBuffer(buffer, v); @@ -1536,7 +1586,7 @@ static bool StringifyJsonShapeDataShortString (TRI_shaper_t* shaper, } if (l > 1) { - unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, data, (size_t) (l - 1), true, &out); + unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, data, (size_t) (l - 1), true, &out, false); if (unicoded == NULL) { return false; @@ -1582,7 +1632,7 @@ static bool StringifyJsonShapeDataLongString (TRI_shaper_t* shaper, return false; } - unicoded = TRI_EscapeUtf8StringZ(buffer->_memoryZone, data, l - 1, true, &out); + unicoded = TRI_EscapeUtf8StringZ(buffer->_memoryZone, data, l - 1, true, &out, false); if (unicoded == NULL) { return false; @@ -1624,6 +1674,8 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, TRI_shape_size_t i; TRI_shape_size_t n; TRI_shape_size_t v; + TRI_shape_sid_t cachedSid; + TRI_shape_t const* cachedShape; bool first; char const* qtr; char* unicoded; @@ -1660,6 +1712,9 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, offsetsF = (TRI_shape_size_t const*) qtr; + cachedSid = 0; + cachedShape = NULL; + for (i = 0; i < f; ++i, ++sids, ++aids, ++offsetsF) { TRI_shape_aid_t aid; TRI_shape_sid_t sid; @@ -1671,7 +1726,16 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, sid = *sids; aid = *aids; offset = *offsetsF; - subshape = shaper->lookupShapeId(shaper, sid); + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } + name = shaper->lookupAttributeId(shaper, aid); if (subshape == NULL) { @@ -1701,7 +1765,7 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, return false; } - unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, name, strlen(name), true, &out); + unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, name, strlen(name), true, &out, false); if (unicoded == NULL) { return false; @@ -1747,9 +1811,18 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, sid = *sids; aid = *aids; offset = *offsetsV; - subshape = shaper->lookupShapeId(shaper, sid); - name = shaper->lookupAttributeId(shaper, aid); + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } + name = shaper->lookupAttributeId(shaper, aid); + if (subshape == NULL) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); continue; @@ -1777,7 +1850,7 @@ static bool StringifyJsonShapeDataArray (TRI_shaper_t* shaper, return false; } - unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, name, strlen(name), true, &out); + unicoded = TRI_EscapeUtf8StringZ(shaper->_memoryZone, name, strlen(name), true, &out, false); if (unicoded == NULL) { return false; @@ -1834,6 +1907,8 @@ static bool StringifyJsonShapeDataList (TRI_shaper_t* shaper, TRI_shape_length_list_t l; TRI_shape_sid_t const* sids; TRI_shape_size_t const* offsets; + TRI_shape_sid_t cachedSid; + TRI_shape_t const* cachedShape; bool first; char const* ptr; int res; @@ -1853,6 +1928,9 @@ static bool StringifyJsonShapeDataList (TRI_shaper_t* shaper, if (res != TRI_ERROR_NO_ERROR) { return false; } + + cachedSid = 0; + cachedShape = NULL; for (i = 0; i < l; ++i, ++sids, ++offsets) { TRI_shape_sid_t sid; @@ -1862,8 +1940,16 @@ static bool StringifyJsonShapeDataList (TRI_shaper_t* shaper, sid = *sids; offset = *offsets; - subshape = shaper->lookupShapeId(shaper, sid); - + + // use last sid if in cache + if (sid == cachedSid && cachedSid > 0) { + subshape = cachedShape; + } + else { + cachedShape = subshape = shaper->lookupShapeId(shaper, sid); + cachedSid = sid; + } + if (subshape == NULL) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); continue; @@ -1911,12 +1997,21 @@ static bool StringifyJsonShapeDataHomogeneousList (TRI_shaper_t* shaper, TRI_shape_length_list_t l; TRI_shape_sid_t sid; TRI_shape_size_t const* offsets; + TRI_shape_t const* subshape; bool first; char const* ptr; int res; s = (TRI_homogeneous_list_shape_t const*) shape; sid = s->_sidEntry; + + subshape = shaper->lookupShapeId(shaper, sid); + + if (subshape == NULL) { + LOG_WARNING("cannot find shape #%u", (unsigned int) sid); + + return false; + } ptr = data; first = true; @@ -1931,19 +2026,12 @@ static bool StringifyJsonShapeDataHomogeneousList (TRI_shaper_t* shaper, if (res != TRI_ERROR_NO_ERROR) { return false; } - + for (i = 0; i < l; ++i, ++offsets) { TRI_shape_size_t offset; - TRI_shape_t const* subshape; bool ok; offset = *offsets; - subshape = shaper->lookupShapeId(shaper, sid); - - if (subshape == NULL) { - LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - continue; - } if (first) { first = false; @@ -1988,12 +2076,20 @@ static bool StringifyJsonShapeDataHomogeneousSizedList (TRI_shaper_t* shaper, TRI_shape_sid_t sid; TRI_shape_size_t length; TRI_shape_size_t offset; + TRI_shape_t const* subshape; bool first; char const* ptr; int res; s = (TRI_homogeneous_sized_list_shape_t const*) shape; sid = s->_sidEntry; + subshape = shaper->lookupShapeId(shaper, sid); + + if (subshape == NULL) { + LOG_WARNING("cannot find shape #%u", (unsigned int) sid); + + return false; + } ptr = data; first = true; @@ -2008,18 +2104,10 @@ static bool StringifyJsonShapeDataHomogeneousSizedList (TRI_shaper_t* shaper, if (res != TRI_ERROR_NO_ERROR) { return false; } - + for (i = 0; i < l; ++i, offset += length) { - TRI_shape_t const* subshape = shaper->lookupShapeId(shaper, sid); bool ok; - subshape = shaper->lookupShapeId(shaper, sid); - - if (subshape == NULL) { - LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - continue; - } - if (first) { first = false; }