From 099ec8db606c33d5298df1a65928b896d1918a63 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 7 Aug 2014 15:52:58 +0200 Subject: [PATCH] reallow attribute names starting with underscores --- .../Books/Users/Arangoimp/README.mdpp | 5 - .../NamingConventions/AttributeNames.mdpp | 13 +- .../HttpInterface/api-attributes-spec.rb | 11 +- arangod/V8Server/v8-vocbase.cpp | 26 ++- js/common/tests/shell-attributes.js | 34 +++- lib/ShapedJson/shaped-json.cpp | 156 ++++++++++-------- lib/V8/v8-conv.cpp | 111 +++++++------ 7 files changed, 199 insertions(+), 157 deletions(-) diff --git a/Documentation/Books/Users/Arangoimp/README.mdpp b/Documentation/Books/Users/Arangoimp/README.mdpp index c9e2893f8c..083d1ad68a 100644 --- a/Documentation/Books/Users/Arangoimp/README.mdpp +++ b/Documentation/Books/Users/Arangoimp/README.mdpp @@ -220,14 +220,9 @@ ArangoDB: - *_rev*: this attribute contains the revision number of a document. However, the revision numbers are managed by ArangoDB and cannot be specified on import. Thus any value in this attribute is ignored on import. -- all other attributes starting with an underscore are discarded on import without - any warnings. If you import values into *_key*, you should make sure they are valid and unique. When importing data into an edge collection, you should make sure that all import documents can *_from* and *_to* and that their values point to existing documents. -Finally you should make sure that all other attributes in the import file do not -start with an underscore - otherwise they might be discarded. - diff --git a/Documentation/Books/Users/NamingConventions/AttributeNames.mdpp b/Documentation/Books/Users/NamingConventions/AttributeNames.mdpp index f46a9bb467..99bded4e9c 100644 --- a/Documentation/Books/Users/NamingConventions/AttributeNames.mdpp +++ b/Documentation/Books/Users/NamingConventions/AttributeNames.mdpp @@ -15,8 +15,8 @@ following attribute naming constraints are not violated: attributes are used to reference other documents. More system attributes may be added in the future without further notice so - end users should not use attribute names starting with an underscore for their - own attributes. + end users should try to avoid using their own attribute names starting with + underscores. * Attribute names should not start with the at-mark (*@*). The at-mark at the start of attribute names is reserved in ArangoDB for future use cases. @@ -39,16 +39,15 @@ following attribute naming constraints are not violated: length is variable and depends on the number and data types of attributes used. * Attribute names are case-sensitive. -* Attributes with empty names (the empty string) and attributes with names that - start with an underscore and don't have a special meaning (system attributes) - are removed from the document when saving it. +* Attributes with empty names (the empty string) are removed from the document + when saving it. When the document is later requested, it will be returned without these attributes. For example, if this document is saved: - { "a" : 1, "" : 2, "_test" : 3, "b": 4 } + { "a" : 1, "" : 2, "b": 3 } and later requested, it will be returned like this: - { "a" : 1, "b": 4 } + { "a" : 1, "b": 3 } diff --git a/UnitTests/HttpInterface/api-attributes-spec.rb b/UnitTests/HttpInterface/api-attributes-spec.rb index ad081b76b0..9648a1cf81 100644 --- a/UnitTests/HttpInterface/api-attributes-spec.rb +++ b/UnitTests/HttpInterface/api-attributes-spec.rb @@ -89,7 +89,8 @@ describe ArangoDB do doc.parsed_response['_rev'].should_not eq('99') doc.parsed_response.should_not have_key('_from') doc.parsed_response.should_not have_key('_to') - doc.parsed_response.should_not have_key('_test') + doc.parsed_response.should have_key('_test') + doc.parsed_response['_test'].should eq('c') doc.parsed_response.should have_key('meow') doc.parsed_response['meow'].should eq('d') doc.parsed_response['foo'].should eq('002') @@ -101,7 +102,7 @@ describe ArangoDB do it "creates a document with nested attribute names" do cmd = api + "?collection=" + @cn - body = "{ \"a\" : \"1\", \"b\" : { \"b\" : \"2\" , \"a\" : \"3\", \"\": \"4\", \"_from\": \"5\", \"c\" : 6 } }" + body = "{ \"a\" : \"1\", \"b\" : { \"b\" : \"2\" , \"a\" : \"3\", \"\": \"4\", \"_key\": \"moetoer\", \"_from\": \"5\", \"_lol\" : false, \"c\" : 6 } }" doc = ArangoDB.log_post("#{prefix}-create-duplicate-names", cmd, :body => body) doc.code.should eq(201) @@ -118,11 +119,13 @@ describe ArangoDB do doc.parsed_response.should have_key('b') doc.parsed_response['b'].should_not have_key('') - doc.parsed_response['b'].should_not have_key('_from') + doc.parsed_response['b'].should have_key('_from') + doc.parsed_response['b'].should have_key('_key') + doc.parsed_response['b'].should have_key('_lol') doc.parsed_response['b'].should have_key('b') doc.parsed_response['b'].should have_key('a') doc.parsed_response['b'].should have_key('c') - doc.parsed_response['b'].should eq({ "b" => "2", "a" => "3", "c" => 6 }) + doc.parsed_response['b'].should eq({ "b" => "2", "a" => "3", "_key" => "moetoer", "_from" => "5", "_lol" => false, "c" => 6 }) end ################################################################################ diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 68f6e43a88..6e8f428518 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -933,7 +933,7 @@ int ProcessBitarrayIndexFields (v8::Handle const obj, // "fields" is a list of fields v8::Handle fieldList = v8::Handle::Cast(obj->Get(TRI_V8_SYMBOL("fields"))); - const uint32_t n = fieldList->Length(); + uint32_t const n = fieldList->Length(); for (uint32_t i = 0; i < n; ++i) { if (! fieldList->Get(i)->IsArray()) { @@ -948,7 +948,7 @@ int ProcessBitarrayIndexFields (v8::Handle const obj, break; } - const string f = TRI_ObjectToString(fieldPair->Get(0)); + string const f = TRI_ObjectToString(fieldPair->Get(0)); if (f.empty() || (create && f[0] == '_')) { // accessing internal attributes is disallowed @@ -9903,7 +9903,17 @@ static v8::Handle MapGetNamedShapedJson (v8::Local name, v8::String::Utf8Value const str(name); string const key(*str, (size_t) str.length()); - if (key.empty() || key[0] == '_' || strchr(key.c_str(), '.') != 0) { + if (key.empty()) { + return scope.Close(v8::Handle()); + } + + if (key[0] == '_' && + (key == "_key" || key == "_rev" || key == "_id" || key == "_from" || key == "_to")) { + // strip reserved attributes + return scope.Close(v8::Handle()); + } + + if (strchr(key.c_str(), '.') != nullptr) { return scope.Close(v8::Handle()); } @@ -9954,7 +9964,7 @@ static v8::Handle KeysOfShapedJson (const v8::AccessorInfo& info) { // get shaped json void* marker = TRI_UnwrapClass(self, WRP_SHAPED_JSON_TYPE); - if (marker == 0) { + if (marker == nullptr) { return scope.Close(v8::Array::New()); } @@ -10000,7 +10010,7 @@ static v8::Handle KeysOfShapedJson (const v8::AccessorInfo& info) { } } - TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData(); + TRI_v8_global_t* v8g = static_cast(v8::Isolate::GetCurrent()->GetData()); result->Set(count++, v8g->_IdKey); result->Set(count++, v8g->_RevKey); result->Set(count++, v8g->_KeyKey); @@ -10038,7 +10048,7 @@ static v8::Handle PropertyQueryShapedJson (v8::Local na } if (key[0] == '_') { - if (key == "_id" || key == TRI_VOC_ATTRIBUTE_REV || key == TRI_VOC_ATTRIBUTE_KEY) { + if (key == "_key" || key == "_rev" || key == "_id" || key == "_from" || key == "_to") { return scope.Close(v8::Handle(v8::Integer::New(v8::ReadOnly))); } } @@ -10069,7 +10079,7 @@ static v8::Handle PropertyQueryShapedJson (v8::Local na TRI_shape_access_t const* acc = TRI_FindAccessorVocShaper(shaper, sid, pid); // key not found - if (acc == 0 || acc->_resultSid == TRI_SHAPE_ILLEGAL) { + if (acc == nullptr || acc->_resultSid == TRI_SHAPE_ILLEGAL) { return scope.Close(v8::Handle()); } @@ -10172,7 +10182,7 @@ TRI_index_t* TRI_LookupIndexByHandle (CollectionNameResolver const* resolver, // extract the index identifier from an object else if (val->IsObject()) { - TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData(); + TRI_v8_global_t* v8g = static_cast(v8::Isolate::GetCurrent()->GetData()); v8::Handle obj = val->ToObject(); v8::Handle iidVal = obj->Get(v8g->IdKey); diff --git a/js/common/tests/shell-attributes.js b/js/common/tests/shell-attributes.js index 7f7198e401..8c6faabdf3 100644 --- a/js/common/tests/shell-attributes.js +++ b/js/common/tests/shell-attributes.js @@ -151,7 +151,7 @@ function AttributesSuite () { //////////////////////////////////////////////////////////////////////////////// testReservedAttributes : function () { - var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false }; + var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false, "_boom" : "bang" }; var d1 = c.save(doc); var d2 = c.document(d1._id); @@ -161,17 +161,33 @@ function AttributesSuite () { assertEqual(cn + "/meow", d1._id); assertEqual(cn + "/meow", d2._id); assertEqual(d1._rev, d2._rev); + assertFalse(d2._test); + assertEqual("bang", d2._boom); + assertFalse(d2.hasOwnProperty("_from")); + assertFalse(d2.hasOwnProperty("_to")); // user specified _rev value must have been ignored assertTrue(d1._rev !== "99"); - - // test attributes - var i; - for (i in d2) { - if (d2.hasOwnProperty(i)) { - assertTrue(i !== "_from" && i !== "_to" && i !== "_test"); - } - } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reserved attribute names +//////////////////////////////////////////////////////////////////////////////// + + testEmbeddedReservedAttributes : function () { + var doc = { "_id" : "foo", "_rev": "99", "_key" : "meow", "_from" : "33", "_to": "99", "_test" : false }; + + c.save({ _key: "mydoc", _embedded: doc }); + var d = c.document("mydoc"); + + assertEqual(cn + "/mydoc", d._id); + assertEqual("mydoc", d._key); + assertEqual("foo", d._embedded._id); + assertEqual("99", d._embedded._rev); + assertEqual("meow", d._embedded._key); + assertEqual("33", d._embedded._from); + assertEqual("99", d._embedded._to); + assertFalse(d._embedded._test); }, //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/ShapedJson/shaped-json.cpp b/lib/ShapedJson/shaped-json.cpp index 325c197f27..59d34ed60b 100644 --- a/lib/ShapedJson/shaped-json.cpp +++ b/lib/ShapedJson/shaped-json.cpp @@ -44,7 +44,7 @@ // --SECTION-- forward declarations // ----------------------------------------------------------------------------- -static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, bool, bool); +static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, size_t, bool, bool); static TRI_json_t* JsonShapeData (TRI_shaper_t* shaper, TRI_shape_t const* shape, char const* data, uint64_t size); static bool StringifyJsonShapeData (TRI_shaper_t* shaper, TRI_string_buffer_t* buffer, TRI_shape_t const* shape, char const* data, uint64_t size); @@ -470,6 +470,7 @@ static bool FillShapeValueString (TRI_shaper_t* shaper, TRI_shape_value_t* dst, static bool FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, + size_t level, bool create, bool isLocked) { size_t i, n; @@ -506,7 +507,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, dst->_size = sizeof(TRI_shape_length_list_t); dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, false))); - if (dst->_value == NULL) { + if (dst->_value == nullptr) { return false; } @@ -518,7 +519,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, // convert into TRI_shape_value_t array p = (values = static_cast(TRI_Allocate(shaper->_memoryZone, sizeof(TRI_shape_value_t) * n, true))); - if (p == NULL) { + if (p == nullptr) { return false; } @@ -526,12 +527,12 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, e = values + n; for (i = 0; i < n; ++i, ++p) { - TRI_json_t const* el = (TRI_json_t const*) TRI_AtVector(&json->_value._objects, i); - bool ok = FillShapeValueJson(shaper, p, el, create, isLocked); + TRI_json_t const* el = static_cast(TRI_AtVector(&json->_value._objects, i)); + bool ok = FillShapeValueJson(shaper, p, el, level + 1, create, isLocked); if (! ok) { for (e = p, p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -774,6 +775,7 @@ static bool FillShapeValueList (TRI_shaper_t* shaper, static bool FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, + size_t level, bool create, bool isLocked) { size_t i, n; @@ -808,7 +810,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, // convert into TRI_shape_value_t array p = (values = static_cast(TRI_Allocate(shaper->_memoryZone, n * sizeof(TRI_shape_value_t), true))); - if (p == NULL) { + if (p == nullptr) { return false; } @@ -817,36 +819,49 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, v = 0; for (i = 0; i < n; ++i, ++p) { - bool ok; + TRI_json_t const* key = static_cast(TRI_AtVector(&json->_value._objects, 2 * i)); + TRI_ASSERT(key != nullptr); - TRI_json_t* key = static_cast(TRI_AtVector(&json->_value._objects, 2 * i)); - TRI_json_t* val = static_cast(TRI_AtVector(&json->_value._objects, 2 * i + 1)); + char const* k = key->_value._string.data; - TRI_ASSERT(key != NULL); - TRI_ASSERT(val != NULL); - - if (key->_value._string.data == NULL || - key->_value._string.length == 1 || - key->_value._string.data[0] == '_') { - // empty or reserved attribute name + if (k == nullptr || + key->_value._string.length == 1) { + // empty attribute name p--; continue; } + if (*k == '_' && level == 0) { + // on top level, strip reserved attributes before shaping + if (strcmp(k, "_key") == 0 || + strcmp(k, "_rev") == 0 || + strcmp(k, "_id") == 0 || + strcmp(k, "_from") == 0 || + strcmp(k, "_to") == 0) { + // found a reserved attribute - discard it + --p; + continue; + } + } + // first find an identifier for the name - p->_aid = shaper->findOrCreateAttributeByName(shaper, key->_value._string.data); + p->_aid = shaper->findOrCreateAttributeByName(shaper, k); // convert value + bool ok; if (p->_aid == 0) { ok = false; } else { - ok = FillShapeValueJson(shaper, p, val, create, isLocked); + TRI_json_t const* val = static_cast(TRI_AtVector(&json->_value._objects, 2 * i + 1)); + TRI_ASSERT(val != nullptr); + + ok = FillShapeValueJson(shaper, p, val, level + 1, create, isLocked); } if (! ok) { for (e = p, p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -893,13 +908,13 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, + n * sizeof(TRI_shape_aid_t) + (f + 1) * sizeof(TRI_shape_size_t); - a = (TRI_array_shape_t*) (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, i, true))); + a = reinterpret_cast(ptr = static_cast(TRI_Allocate(shaper->_memoryZone, i, true))); - if (ptr == NULL) { + if (ptr == nullptr) { e = values + n; for (p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -937,11 +952,11 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, dst->_size = total; dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, true))); - if (ptr == NULL) { + if (ptr == nullptr) { e = values + n; for (p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -982,7 +997,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, // free TRI_shape_value_t array for (p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -992,7 +1007,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, // lookup this shape found = shaper->findShape(shaper, &a->base, create); - if (found == NULL) { + if (found == nullptr) { TRI_Free(shaper->_memoryZone, a); return false; } @@ -1009,6 +1024,7 @@ static bool FillShapeValueArray (TRI_shaper_t* shaper, static bool FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, TRI_json_t const* json, + size_t level, bool create, bool isLocked) { switch (json->_type) { @@ -1029,10 +1045,10 @@ static bool FillShapeValueJson (TRI_shaper_t* shaper, return FillShapeValueString(shaper, dst, json); case TRI_JSON_ARRAY: - return FillShapeValueArray(shaper, dst, json, create, isLocked); + return FillShapeValueArray(shaper, dst, json, level, create, isLocked); case TRI_JSON_LIST: - return FillShapeValueList(shaper, dst, json, create, isLocked); + return FillShapeValueList(shaper, dst, json, level, create, isLocked); } return false; @@ -1143,8 +1159,8 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, // create an array with the appropriate size array = TRI_CreateArray2Json(shaper->_memoryZone, (size_t) n); - if (array == NULL) { - return NULL; + if (array == nullptr) { + return nullptr; } qtr = (char const*) shape; @@ -1159,7 +1175,7 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, offsetsF = (TRI_shape_size_t const*) qtr; shapeCache._sid = 0; - shapeCache._shape = NULL; + shapeCache._shape = nullptr; for (i = 0; i < f; ++i, ++sids, ++aids, ++offsetsF) { TRI_shape_sid_t sid = *sids; @@ -1180,21 +1196,21 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, shapeCache._sid = sid; } - if (subshape == NULL) { + if (subshape == nullptr) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); continue; } name = shaper->lookupAttributeId(shaper, aid); - if (name == NULL) { + if (name == nullptr) { LOG_WARNING("cannot find attribute #%u", (unsigned int) aid); continue; } element = JsonShapeData(shaper, subshape, data + offset, offsetsF[1] - offset); - if (element == NULL) { + if (element == nullptr) { LOG_WARNING("cannot decode element for shape #%u", (unsigned int) sid); continue; } @@ -1224,21 +1240,21 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, shapeCache._sid = sid; } - if (subshape == NULL) { + if (subshape == nullptr) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); continue; } name = shaper->lookupAttributeId(shaper, aid); - if (name == NULL) { + if (name == nullptr) { LOG_WARNING("cannot find attribute #%u", (unsigned int) aid); continue; } element = JsonShapeData(shaper, subshape, data + offset, offsetsV[1] - offset); - if (element == NULL) { + if (element == nullptr) { LOG_WARNING("cannot decode element for shape #%u", (unsigned int) sid); continue; } @@ -1250,7 +1266,7 @@ static TRI_json_t* JsonShapeDataArray (TRI_shaper_t* shaper, if (shaper->_memoryZone->_failed) { TRI_FreeJson(shaper->_memoryZone, array); - return NULL; + return nullptr; } return array; @@ -1265,7 +1281,6 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, char const* data, uint64_t size) { char const* ptr; - TRI_json_t* list; TRI_shape_sid_t const* sids; TRI_shape_size_t const* offsets; TRI_shape_length_list_t l; @@ -1276,10 +1291,10 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, l = * (TRI_shape_length_list_t const*) ptr; // create a list with the appropriate size - list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); + TRI_json_t* list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); - if (list == NULL) { - return NULL; + if (list == nullptr) { + return nullptr; } ptr += sizeof(TRI_shape_length_list_t); @@ -1289,7 +1304,7 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, offsets = (TRI_shape_size_t const*) ptr; shapeCache._sid = 0; - shapeCache._shape = NULL; + shapeCache._shape = nullptr; for (i = 0; i < l; ++i, ++sids, ++offsets) { TRI_shape_sid_t sid = *sids; @@ -1308,14 +1323,14 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, shapeCache._sid = sid; } - if (subshape == NULL) { + if (subshape == nullptr) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); continue; } element = JsonShapeData(shaper, subshape, data + offset, offsets[1] - offset); - if (element == NULL) { + if (element == nullptr) { LOG_WARNING("cannot decode element for shape #%u", (unsigned int) sid); continue; } @@ -1327,7 +1342,7 @@ static TRI_json_t* JsonShapeDataList (TRI_shaper_t* shaper, if (shaper->_memoryZone->_failed) { TRI_FreeJson(shaper->_memoryZone, list); - return NULL; + return nullptr; } return list; @@ -1342,33 +1357,31 @@ static TRI_json_t* JsonShapeDataHomogeneousList (TRI_shaper_t* shaper, char const* data, uint64_t size) { TRI_homogeneous_list_shape_t const* s; - TRI_json_t* list; TRI_shape_length_list_t i; 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); + TRI_shape_t const* subshape = shaper->lookupShapeId(shaper, sid); - if (subshape == NULL) { + if (subshape == nullptr) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - return NULL; + return nullptr; } 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); + TRI_json_t* list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); - if (list == NULL) { - return NULL; + if (list == nullptr) { + return nullptr; } ptr += sizeof(TRI_shape_length_list_t); @@ -1382,7 +1395,7 @@ static TRI_json_t* JsonShapeDataHomogeneousList (TRI_shaper_t* shaper, element = JsonShapeData(shaper, subshape, data + offset, offsets[1] - offset); - if (element == NULL) { + if (element == nullptr) { LOG_WARNING("cannot decode element for shape #%u", (unsigned int) sid); continue; } @@ -1394,7 +1407,7 @@ static TRI_json_t* JsonShapeDataHomogeneousList (TRI_shaper_t* shaper, if (shaper->_memoryZone->_failed) { TRI_FreeJson(shaper->_memoryZone, list); - return NULL; + return nullptr; } return list; @@ -1409,34 +1422,32 @@ static TRI_json_t* JsonShapeDataHomogeneousSizedList (TRI_shaper_t* shaper, char const* data, uint64_t size) { TRI_homogeneous_sized_list_shape_t const* s; - TRI_json_t* list; TRI_shape_length_list_t i; TRI_shape_length_list_t l; 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); + TRI_shape_t const* subshape = shaper->lookupShapeId(shaper, sid); - if (subshape == NULL) { + if (subshape == nullptr) { LOG_WARNING("cannot find shape #%u", (unsigned int) sid); - return NULL; + return nullptr; } 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); + TRI_json_t* list = TRI_CreateList2Json(shaper->_memoryZone, (size_t) l); - if (list == NULL) { - return NULL; + if (list == nullptr) { + return nullptr; } length = s->_sizeEntry; @@ -1447,7 +1458,7 @@ static TRI_json_t* JsonShapeDataHomogeneousSizedList (TRI_shaper_t* shaper, element = JsonShapeData(shaper, subshape, data + offset, length); - if (element == NULL) { + if (element == nullptr) { LOG_WARNING("cannot decode element for shape #%u", (unsigned int) sid); continue; } @@ -1467,8 +1478,8 @@ static TRI_json_t* JsonShapeData (TRI_shaper_t* shaper, TRI_shape_t const* shape, char const* data, uint64_t size) { - if (shape == NULL) { - return NULL; + if (shape == nullptr) { + return nullptr; } switch (shape->_type) { @@ -2226,13 +2237,12 @@ TRI_shaped_json_t* TRI_ShapedJsonJson (TRI_shaper_t* shaper, bool create, bool isLocked) { TRI_shape_value_t dst; - bool ok; dst._value = 0; - ok = FillShapeValueJson(shaper, &dst, json, create, isLocked); + bool ok = FillShapeValueJson(shaper, &dst, json, 0, create, isLocked); if (! ok) { - return NULL; + return nullptr; } #ifdef DEBUG_JSON_SHAPER @@ -2244,9 +2254,9 @@ TRI_shaped_json_t* TRI_ShapedJsonJson (TRI_shaper_t* shaper, // no need to prefill shaped with 0's as all attributes are set directly afterwards TRI_shaped_json_t* shaped = static_cast(TRI_Allocate(shaper->_memoryZone, sizeof(TRI_shaped_json_t), false)); - if (shaped == NULL) { + if (shaped == nullptr) { TRI_Free(shaper->_memoryZone, dst._value); - return NULL; + return nullptr; } shaped->_sid = dst._sid; diff --git a/lib/V8/v8-conv.cpp b/lib/V8/v8-conv.cpp index 3e42de97e4..fd0af2ffda 100644 --- a/lib/V8/v8-conv.cpp +++ b/lib/V8/v8-conv.cpp @@ -51,6 +51,7 @@ using namespace triagens::basics; static int FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, v8::Handle const json, + size_t level, set& seenHashes, vector< v8::Handle >& seenObjects, bool create); @@ -261,6 +262,7 @@ static int FillShapeValueString (TRI_shaper_t* shaper, static int FillShapeValueList (TRI_shaper_t* shaper, TRI_shape_value_t* dst, v8::Handle const json, + size_t level, set& seenHashes, vector< v8::Handle >& seenObjects, bool create) { @@ -292,9 +294,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, dst->_fixedSized = false; dst->_size = sizeof(TRI_shape_length_list_t); - dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, false)); + dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, false))); - if (dst->_value == 0) { + if (dst->_value == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } @@ -304,9 +306,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, } // convert into TRI_shape_value_t array - p = (values = (TRI_shape_value_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_shape_value_t) * n, true)); + p = (values = static_cast(TRI_Allocate(shaper->_memoryZone, sizeof(TRI_shape_value_t) * n, true))); - if (p == 0) { + if (p == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } @@ -315,11 +317,11 @@ static int FillShapeValueList (TRI_shaper_t* shaper, for (uint32_t i = 0; i < n; ++i, ++p) { v8::Handle el = json->Get(i); - int res = FillShapeValueJson(shaper, p, el, seenHashes, seenObjects, create); + int res = FillShapeValueJson(shaper, p, el, level + 1, seenHashes, seenObjects, create); if (res != TRI_ERROR_NO_ERROR) { for (e = p, p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -356,9 +358,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, shape = (TRI_homogeneous_sized_list_shape_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_homogeneous_sized_list_shape_t), true); - if (shape == 0) { + if (shape == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -375,9 +377,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, found = shaper->findShape(shaper, &shape->base, create); - if (found == 0) { + if (found == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -394,18 +396,18 @@ static int FillShapeValueList (TRI_shaper_t* shaper, return TRI_ERROR_INTERNAL; } - TRI_ASSERT(found != 0); + TRI_ASSERT(found != nullptr); dst->_type = found->_type; dst->_sid = found->_sid; dst->_fixedSized = false; dst->_size = sizeof(TRI_shape_length_list_t) + total; - dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, false)); + dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, false))); if (dst->_value == NULL) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -431,9 +433,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, shape = (TRI_homogeneous_list_shape_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_homogeneous_list_shape_t), true); - if (shape == NULL) { + if (shape == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -451,9 +453,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, // if found returns non-NULL, it will free the shape!! found = shaper->findShape(shaper, &shape->base, create); - if (found == 0) { + if (found == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -470,7 +472,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper, return TRI_ERROR_INTERNAL; } - TRI_ASSERT(found != 0); + TRI_ASSERT(found != nullptr); dst->_type = found->_type; dst->_sid = found->_sid; @@ -479,11 +481,11 @@ static int FillShapeValueList (TRI_shaper_t* shaper, dst->_fixedSized = false; dst->_size = offset + total; - dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true)); + dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, true))); - if (dst->_value == 0) { + if (dst->_value == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -525,9 +527,9 @@ static int FillShapeValueList (TRI_shaper_t* shaper, dst->_size = offset + total; dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true)); - if (dst->_value == NULL) { + if (dst->_value == nullptr) { for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -561,7 +563,7 @@ static int FillShapeValueList (TRI_shaper_t* shaper, // free TRI_shape_value_t array for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -577,14 +579,10 @@ static int FillShapeValueList (TRI_shaper_t* shaper, static int FillShapeValueArray (TRI_shaper_t* shaper, TRI_shape_value_t* dst, v8::Handle const json, + size_t level, set& seenHashes, vector< v8::Handle >& seenObjects, bool create) { - size_t total; - - size_t f; - size_t v; - TRI_shape_value_t* values; TRI_shape_value_t* p; TRI_shape_value_t* e; @@ -606,19 +604,19 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, uint32_t n = names->Length(); // convert into TRI_shape_value_t array - p = (values = (TRI_shape_value_t*) TRI_Allocate(shaper->_memoryZone, n * sizeof(TRI_shape_value_t), true)); + p = (values = static_cast(TRI_Allocate(shaper->_memoryZone, n * sizeof(TRI_shape_value_t), true))); - if (p == 0) { + if (p == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } + + size_t total = 0; - total = 0; - f = 0; - v = 0; + size_t f = 0; + size_t v = 0; for (uint32_t i = 0; i < n; ++i, ++p) { v8::Handle key = names->Get(i); - v8::Handle val = json->Get(key); // first find an identifier for the name TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key); @@ -628,9 +626,18 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, continue; } - if ((*keyStr)[0] == '_') { - --p; - continue; + if ((*keyStr)[0] == '_' && level == 0) { + // on top level, strip reserved attributes before shaping + char const* k = (*keyStr); + if (strcmp(k, "_key") == 0 || + strcmp(k, "_rev") == 0 || + strcmp(k, "_id") == 0 || + strcmp(k, "_from") == 0 || + strcmp(k, "_to") == 0) { + // found a reserved attribute - discard it + --p; + continue; + } } if (create) { @@ -652,12 +659,13 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, } } else { - res = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects, create); + v8::Handle val = json->Get(key); + res = FillShapeValueJson(shaper, p, val, level + 1, seenHashes, seenObjects, create); } if (res != TRI_ERROR_NO_ERROR) { for (e = p, p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -706,11 +714,11 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, a = (TRI_array_shape_t*) (ptr = (char*) TRI_Allocate(shaper->_memoryZone, totalSize, true)); - if (ptr == NULL) { + if (ptr == nullptr) { e = values + n; for (p = values; p < e; ++p) { - if (p->_value != NULL) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -746,13 +754,13 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, dst->_fixedSized = true; dst->_size = total; - dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true)); + dst->_value = (ptr = static_cast(TRI_Allocate(shaper->_memoryZone, dst->_size, true))); - if (ptr == 0) { + if (ptr == nullptr) { e = values + n; for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -793,7 +801,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, // free TRI_shape_value_t array for (p = values; p < e; ++p) { - if (p->_value != 0) { + if (p->_value != nullptr) { TRI_Free(shaper->_memoryZone, p->_value); } } @@ -803,7 +811,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, // lookup this shape found = shaper->findShape(shaper, &a->base, create); - if (found == 0) { + if (found == nullptr) { LOG_TRACE("shaper failed to find shape %d", (int) a->base._type); TRI_Free(shaper->_memoryZone, a); @@ -826,6 +834,7 @@ static int FillShapeValueArray (TRI_shaper_t* shaper, static int FillShapeValueJson (TRI_shaper_t* shaper, TRI_shape_value_t* dst, v8::Handle const json, + size_t level, set& seenHashes, vector< v8::Handle >& seenObjects, bool create) { @@ -885,11 +894,11 @@ static int FillShapeValueJson (TRI_shaper_t* shaper, } else if (json->IsArray()) { - return FillShapeValueList(shaper, dst, v8::Handle::Cast(json), seenHashes, seenObjects, create); + return FillShapeValueList(shaper, dst, v8::Handle::Cast(json), level, seenHashes, seenObjects, create); } else if (json->IsObject()) { - int res = FillShapeValueArray(shaper, dst, json->ToObject(), seenHashes, seenObjects, create); + int res = FillShapeValueArray(shaper, dst, json->ToObject(), level, seenHashes, seenObjects, create); seenObjects.pop_back(); return res; } @@ -1436,7 +1445,7 @@ TRI_shaped_json_t* TRI_ShapedJsonV8Object (v8::Handle const object, set seenHashes; vector< v8::Handle > seenObjects; - int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create); + int res = FillShapeValueJson(shaper, &dst, object, 0, seenHashes, seenObjects, create); if (res != TRI_ERROR_NO_ERROR) { if (res == TRI_RESULT_ELEMENT_NOT_FOUND) { @@ -1473,7 +1482,7 @@ int TRI_FillShapedJsonV8Object (v8::Handle const object, set seenHashes; vector< v8::Handle > seenObjects; - int res = FillShapeValueJson(shaper, &dst, object, seenHashes, seenObjects, create); + int res = FillShapeValueJson(shaper, &dst, object, 0, seenHashes, seenObjects, create); if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_RESULT_ELEMENT_NOT_FOUND) {