uint64_t TRI_HashJsonByAttributes (TRI_json_t const* json, char const *attributes[], int nrAttributes, bool docComplete, int* error) { uint64_t hash; if (NULL != error) { *error = TRI_ERROR_NO_ERROR; } hash = TRI_FnvHashBlockInitial(); if (TRI_IsArrayJson(json)) { int i; for (i = 0; i < nrAttributes; i++) { TRI_json_t const* subjson = TRI_LookupArrayJson(json, attributes[i]); if (NULL == subjson && !docComplete && NULL != error) { *error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN; } hash = HashJsonRecursive(hash, subjson); } } return hash; }
uint64_t TRI_HashJsonByAttributes (TRI_json_t const* json, char const *attributes[], int nrAttributes, bool docComplete, int* error) { if (error != nullptr) { *error = TRI_ERROR_NO_ERROR; } uint64_t hash = TRI_FnvHashBlockInitial(); if (TRI_IsObjectJson(json)) { for (int i = 0; i < nrAttributes; i++) { TRI_json_t const* subjson = TRI_LookupObjectJson(json, attributes[i]); if (subjson == nullptr && ! docComplete && error != nullptr) { *error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN; } hash = HashJsonRecursive(hash, subjson); } } return hash; }
uint64_t TRI_HashJson (TRI_json_t const* json) { return HashJsonRecursive(TRI_FnvHashBlockInitial(), json); }
static uint64_t HashJsonRecursive (uint64_t hash, TRI_json_t const* object) { size_t n; size_t i; uint64_t tmphash; TRI_json_t const* subjson; if (0 == object) { return HashBlock(hash, "null", 4); // strlen("null") } switch (object->_type) { case TRI_JSON_UNUSED: { return hash; } case TRI_JSON_NULL: { return HashBlock(hash, "null", 4); // strlen("null") } case TRI_JSON_BOOLEAN: { if (object->_value._boolean) { return HashBlock(hash, "true", 4); // strlen("true") } else { return HashBlock(hash, "false", 5); // strlen("true") } } case TRI_JSON_NUMBER: { return HashBlock(hash, (char const*) &(object->_value._number), sizeof(object->_value._number)); } case TRI_JSON_STRING: case TRI_JSON_STRING_REFERENCE: { return HashBlock(hash, object->_value._string.data, object->_value._string.length); } case TRI_JSON_ARRAY: { hash = HashBlock(hash, "array", 5); // strlen("array") n = object->_value._objects._length; tmphash = hash; for (i = 0; i < n; i += 2) { subjson = (const TRI_json_t*) TRI_AtVector(&object->_value._objects, i); TRI_ASSERT(TRI_IsStringJson(subjson)); tmphash ^= HashJsonRecursive(hash, subjson); subjson = (const TRI_json_t*) TRI_AtVector(&object->_value._objects, i+1); tmphash ^= HashJsonRecursive(hash, subjson); } return tmphash; } case TRI_JSON_LIST: { hash = HashBlock(hash, "list", 4); // strlen("list") n = object->_value._objects._length; for (i = 0; i < n; ++i) { subjson = (const TRI_json_t*) TRI_AtVector(&object->_value._objects, i); hash = HashJsonRecursive(hash, subjson); } return hash; } } return hash; // never reached }
static uint64_t HashJsonRecursive (uint64_t hash, TRI_json_t const* object) { if (nullptr == object) { return HashBlock(hash, "null", 4); // strlen("null") } switch (object->_type) { case TRI_JSON_UNUSED: { return hash; } case TRI_JSON_NULL: { return HashBlock(hash, "null", 4); // strlen("null") } case TRI_JSON_BOOLEAN: { if (object->_value._boolean) { return HashBlock(hash, "true", 4); // strlen("true") } else { return HashBlock(hash, "false", 5); // strlen("true") } } case TRI_JSON_NUMBER: { return HashBlock(hash, (char const*) &(object->_value._number), sizeof(object->_value._number)); } case TRI_JSON_STRING: case TRI_JSON_STRING_REFERENCE: { return HashBlock(hash, object->_value._string.data, object->_value._string.length); } case TRI_JSON_OBJECT: { hash = HashBlock(hash, "array", 5); // strlen("array") size_t const n = TRI_LengthVector(&object->_value._objects); uint64_t tmphash = hash; for (size_t i = 0; i < n; i += 2) { auto subjson = static_cast<TRI_json_t const*>(TRI_AddressVector(&object->_value._objects, i)); TRI_ASSERT(TRI_IsStringJson(subjson)); tmphash ^= HashJsonRecursive(hash, subjson); subjson = static_cast<TRI_json_t const*>(TRI_AddressVector(&object->_value._objects, i + 1)); tmphash ^= HashJsonRecursive(hash, subjson); } return tmphash; } case TRI_JSON_ARRAY: { hash = HashBlock(hash, "list", 4); // strlen("list") size_t const n = TRI_LengthVector(&object->_value._objects); for (size_t i = 0; i < n; ++i) { auto subjson = static_cast<TRI_json_t const*>(TRI_AddressVector(&object->_value._objects, i)); hash = HashJsonRecursive(hash, subjson); } return hash; } } return hash; // never reached }