1
0
Fork 0

simplifications

This commit is contained in:
Jan Steemann 2015-06-10 11:53:31 +02:00
parent bd055a3b1d
commit b5896be10b
5 changed files with 103 additions and 636 deletions

View File

@ -186,240 +186,9 @@ BOOST_AUTO_TEST_CASE (tst_compare_values_unequal) {
// TODO: add tests for
// TRI_CheckSameValueJson
// TRI_BetweenArrayJson
// TRI_UniquifyArrayJson
// TRI_UnionizeListsJson
// TRI_IntersectListsJson
// TRI_SortArrayJson
////////////////////////////////////////////////////////////////////////////////
/// @brief test check in list
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_check_in_list) {
TRI_json_t* l;
TRI_json_t* r;
JSON_CHECK(true, TRI_CheckInArrayJson, "null", "[1,2,3,null]");
JSON_CHECK(true, TRI_CheckInArrayJson, "false", "[false]");
JSON_CHECK(true, TRI_CheckInArrayJson, "true", "[false,true]");
JSON_CHECK(true, TRI_CheckInArrayJson, "0", "[0]");
JSON_CHECK(true, TRI_CheckInArrayJson, "0", "[0,1]");
JSON_CHECK(true, TRI_CheckInArrayJson, "0", "[0,1,2]");
JSON_CHECK(true, TRI_CheckInArrayJson, "0", "[2,1,0]");
JSON_CHECK(true, TRI_CheckInArrayJson, "1", "[1,0]");
JSON_CHECK(true, TRI_CheckInArrayJson, "1", "[2,1,0]");
JSON_CHECK(true, TRI_CheckInArrayJson, "1", "[12,12,12,12,1]");
JSON_CHECK(true, TRI_CheckInArrayJson, "12", "[0,9,100,7,12,8]");
JSON_CHECK(true, TRI_CheckInArrayJson, "15", "[12,13,14,16,17,15]");
JSON_CHECK(true, TRI_CheckInArrayJson, "\"\"", "[1,2,3,\"\"]");
JSON_CHECK(true, TRI_CheckInArrayJson, "\"a\"", "[1,2,3,\"a\"]");
JSON_CHECK(true, TRI_CheckInArrayJson, "\"A\"", "[1,2,\"A\"]");
JSON_CHECK(true, TRI_CheckInArrayJson, "\"the fox\"", "[1,\"the fox\"]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[]", "[[]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[]", "[2,3,[]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[null]", "[[null]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[false]", "[[false]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[true]", "[[true]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[true]", "[[false],[true]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[0]", "[1,2,3,[0]]");
JSON_CHECK(true, TRI_CheckInArrayJson, "[\"a\"]", "[\"b\",\"\",[\"a\"]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "null", "[0,1,2,3,\"\",false,\"null\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "null", "[[null]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "false", "[0,1,2,3,\"\",\"false\",\"null\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "false", "[[false]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "true", "[\"true\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "true", "[[true]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "0", "[null,false,\"\",\" \"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "0", "[[0]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "15", "[12,13,14,16,17]");
JSON_CHECK(false, TRI_CheckInArrayJson, "15", "[[15]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "120", "[12,121,1200]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"a\"", "[\"A\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"A\"", "[\"a\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"a\"", "[\"abc\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"a\"", "[\"a \"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"the fox\"", "[\"the\",\"fox\"]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"a\"", "[[\"a\"]]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[]", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[]", "[5,4,3,2,1]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[0]", "[0,1,2,3]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[]", "[0,1,2,3]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[false]", "[false,true]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[\"a\"]", "[\"a\"]");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test check in list with an empty list
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_check_in_list_empty) {
TRI_json_t* l;
TRI_json_t* r;
JSON_CHECK(false, TRI_CheckInArrayJson, "null", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "false", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "true", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "0", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "1", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"fox\"", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\"\"", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "\" \"", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "[]", "[]");
JSON_CHECK(false, TRI_CheckInArrayJson, "{}", "[]");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists union
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_unionize_lists_empty) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
json = TRI_UnionizeListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists intersection
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_intersect_lists_empty1) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
json = TRI_IntersectListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists intersection
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_intersect_lists_empty2) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[1]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
json = TRI_IntersectListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists intersection
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_intersect_lists_empty3) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[0]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[]");
json = TRI_IntersectListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists intersection
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_intersect_lists_values1) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[0,1,2,3]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[2,3,4]");
json = TRI_IntersectListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[2,3]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test lists intersection
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (tst_intersect_lists_values2) {
INIT_BUFFER
TRI_json_t* json;
TRI_json_t* list1;
TRI_json_t* list2;
list1 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[null,false,true,0,1,2,3,99,99.5,\"fox\",\"zoo\"]");
list2 = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, "[false,2,99,99.2,\"Fox\",\"zoo\"]");
json = TRI_IntersectListsJson(list1, list2, true);
STRINGIFY
BOOST_CHECK_EQUAL("[false,2,99,\"zoo\"]", STRING_VALUE);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list1);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, list2);
FREE_JSON
FREE_BUFFER
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test duplicate keys
////////////////////////////////////////////////////////////////////////////////

View File

@ -42,56 +42,57 @@ static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone,
TRI_json_t const* rhs,
bool nullMeansRemove,
bool mergeObjects) {
TRI_json_t* result = TRI_CopyJson(zone, lhs);
std::unique_ptr<TRI_json_t> result(TRI_CopyJson(zone, lhs));
if (result == nullptr) {
return nullptr;
}
auto r = result.get(); // shortcut variable
size_t const n = TRI_LengthVector(&rhs->_value._objects);
for (size_t i = 0; i < n; i += 2) {
// enumerate all the replacement values
auto key = static_cast<TRI_json_t*>(TRI_AtVector(&rhs->_value._objects, i));
auto value = static_cast<TRI_json_t*>(TRI_AtVector(&rhs->_value._objects, i + 1));
auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i));
auto value = static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i + 1));
if (value->_type == TRI_JSON_NULL && nullMeansRemove) {
// replacement value is a null and we don't want to store nulls => delete attribute from the result
TRI_DeleteObjectJson(zone, result, key->_value._string.data);
TRI_DeleteObjectJson(zone, r, key->_value._string.data);
}
else {
// replacement value is not a null or we want to store nulls
TRI_json_t* lhsValue = TRI_LookupObjectJson(lhs, key->_value._string.data);
TRI_json_t const* lhsValue = TRI_LookupObjectJson(lhs, key->_value._string.data);
if (lhsValue == nullptr) {
// existing array does not have the attribute => append new attribute
if (value->_type == TRI_JSON_OBJECT) {
TRI_json_t* empty = TRI_CreateObjectJson(zone);
TRI_json_t* merged = MergeRecursive(zone, empty, value, nullMeansRemove, mergeObjects);
TRI_Insert3ObjectJson(zone, result, key->_value._string.data, merged);
TRI_FreeJson(zone, empty);
if (value->_type == TRI_JSON_OBJECT && nullMeansRemove) {
TRI_json_t empty;
TRI_InitObjectJson(TRI_UNKNOWN_MEM_ZONE, &empty);
TRI_json_t* merged = MergeRecursive(zone, &empty, value, nullMeansRemove, mergeObjects);
TRI_Insert3ObjectJson(zone, r, key->_value._string.data, merged);
}
else {
TRI_Insert3ObjectJson(zone, result, key->_value._string.data, TRI_CopyJson(zone, value));
TRI_Insert3ObjectJson(zone, r, key->_value._string.data, TRI_CopyJson(zone, value));
}
}
else {
// existing array already has the attribute => replace attribute
if (lhsValue->_type == TRI_JSON_OBJECT && value->_type == TRI_JSON_OBJECT && mergeObjects) {
TRI_json_t* merged = MergeRecursive(zone, lhsValue, value, nullMeansRemove, mergeObjects);
TRI_ReplaceObjectJson(zone, result, key->_value._string.data, merged);
TRI_ReplaceObjectJson(zone, r, key->_value._string.data, merged);
TRI_FreeJson(zone, merged);
}
else {
TRI_ReplaceObjectJson(zone, result, key->_value._string.data, value);
TRI_ReplaceObjectJson(zone, r, key->_value._string.data, value);
}
}
}
}
return result;
return result.release();
}
////////////////////////////////////////////////////////////////////////////////
@ -131,21 +132,17 @@ static int CompareJson (void const* lhs,
}
////////////////////////////////////////////////////////////////////////////////
/// @brief merge two list of array keys, sort them and return a combined list
/// @brief merge two arrays of array keys, sort them and return a combined array
////////////////////////////////////////////////////////////////////////////////
static TRI_json_t* GetMergedKeyList (TRI_json_t const* lhs,
TRI_json_t const* rhs) {
TRI_json_t* keys;
TRI_json_t* unique;
size_t i, n;
static TRI_json_t* GetMergedKeyArray (TRI_json_t const* lhs,
TRI_json_t const* rhs) {
TRI_ASSERT(lhs->_type == TRI_JSON_OBJECT);
TRI_ASSERT(rhs->_type == TRI_JSON_OBJECT);
n = TRI_LengthVector(&lhs->_value._objects) + TRI_LengthVector(&rhs->_value._objects);
size_t n = TRI_LengthVector(&lhs->_value._objects) + TRI_LengthVector(&rhs->_value._objects);
keys = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, n);
std::unique_ptr<TRI_json_t> keys(TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, n));
if (keys == nullptr) {
return nullptr;
@ -153,32 +150,28 @@ static TRI_json_t* GetMergedKeyList (TRI_json_t const* lhs,
n = TRI_LengthVector(&lhs->_value._objects);
for (i = 0 ; i < n; i += 2) {
auto key = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&lhs->_value._objects, i));
for (size_t i = 0 ; i < n; i += 2) {
auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&lhs->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(key));
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys, key);
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
}
n = TRI_LengthVector(&rhs->_value._objects);
for (i = 0 ; i < n; i += 2) {
auto key = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&rhs->_value._objects, i));
for (size_t i = 0 ; i < n; i += 2) {
auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(key));
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys, key);
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, keys.get(), key);
}
// sort the key list in place
TRI_SortArrayJson(keys);
// sort the key array in place
TRI_SortArrayJson(keys.get());
// list is now sorted
unique = TRI_UniquifyArrayJson(keys);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, keys);
return unique; // might be NULL
// array is now sorted
return TRI_UniquifyArrayJson(keys.get());
}
// -----------------------------------------------------------------------------
@ -297,13 +290,14 @@ int TRI_CompareValuesJson (TRI_json_t const* lhs,
TRI_ASSERT(lhs->_type == TRI_JSON_OBJECT);
TRI_ASSERT(rhs->_type == TRI_JSON_OBJECT);
TRI_json_t* keys = GetMergedKeyList(lhs, rhs);
std::unique_ptr<TRI_json_t> keys(GetMergedKeyArray(lhs, rhs));
if (keys != nullptr) {
size_t const n = TRI_LengthVector(&keys->_value._objects);
auto json = keys.get();
size_t const n = TRI_LengthVector(&json->_value._objects);
for (size_t i = 0; i < n; ++i) {
auto keyElement = static_cast<TRI_json_t const*>(TRI_AtVector(&keys->_value._objects, i));
auto keyElement = static_cast<TRI_json_t const*>(TRI_AtVector(&json->_value._objects, i));
TRI_ASSERT(TRI_IsStringJson(keyElement));
TRI_json_t const* lhsValue = TRI_LookupObjectJson(lhs, keyElement->_value._string.data); // may be NULL
@ -312,12 +306,9 @@ int TRI_CompareValuesJson (TRI_json_t const* lhs,
int result = TRI_CompareValuesJson(lhsValue, rhsValue, useUTF8);
if (result != 0) {
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, keys);
return result;
}
}
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, keys);
}
// fall-through to returning 0
}
@ -337,320 +328,54 @@ bool TRI_CheckSameValueJson (TRI_json_t const* lhs,
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a json value is contained in a json list
/// @brief uniquify a sorted json list into a new array
////////////////////////////////////////////////////////////////////////////////
bool TRI_CheckInArrayJson (TRI_json_t const* search,
TRI_json_t const* list) {
TRI_ASSERT(search);
TRI_ASSERT(list);
TRI_ASSERT(list->_type == TRI_JSON_ARRAY);
TRI_json_t* TRI_UniquifyArrayJson (TRI_json_t const* array) {
TRI_ASSERT(array != nullptr);
TRI_ASSERT(array->_type == TRI_JSON_ARRAY);
// iterate over list
size_t const n = TRI_LengthVector(&list->_value._objects);
// create result array
std::unique_ptr<TRI_json_t> result(TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE));
if (result == nullptr) {
return nullptr;
}
size_t const n = TRI_LengthVector(&array->_value._objects);
TRI_json_t const* last = nullptr;
for (size_t i = 0; i < n; ++i) {
TRI_json_t const* listValue = static_cast<TRI_json_t const*>(TRI_AtVector(&list->_value._objects, i));
if (TRI_CheckSameValueJson(search, listValue)) {
// value is contained in list, exit
return true;
}
}
// finished list iteration, value not contained
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the elements of a list that are between the specified bounds
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_BetweenArrayJson (TRI_json_t const* list,
TRI_json_t const* lower,
bool includeLower,
TRI_json_t const* upper,
bool includeUpper) {
TRI_json_t* result;
size_t i, n;
TRI_ASSERT(list);
TRI_ASSERT(list->_type == TRI_JSON_ARRAY);
TRI_ASSERT(lower || upper);
// create result list
result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
if (result == nullptr) {
return nullptr;
}
n = TRI_LengthVector(&list->_value._objects);
for (i = 0; i < n; ++i) {
auto p = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list->_value._objects, i));
if (lower) {
// lower bound is set
int compareResult = TRI_CompareValuesJson(lower, p, true);
if (compareResult > 0 || (compareResult == 0 && ! includeLower)) {
// element is bigger than lower bound
continue;
}
}
if (upper) {
// upper bound is set
int compareResult = TRI_CompareValuesJson(p, upper, true);
if (compareResult > 0 || (compareResult == 0 && ! includeUpper)) {
// element is smaller than upper bound
continue;
}
}
// element is between lower and upper bound
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p);
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief uniquify a sorted json list into a new list
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_UniquifyArrayJson (TRI_json_t const* list) {
TRI_json_t* last = nullptr;
TRI_json_t* result;
size_t i, n;
TRI_ASSERT(list);
TRI_ASSERT(list->_type == TRI_JSON_ARRAY);
// create result list
result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
if (result == nullptr) {
return nullptr;
}
n = TRI_LengthVector(&list->_value._objects);
for (i = 0; i < n; ++i) {
auto p = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list->_value._objects, i));
auto p = static_cast<TRI_json_t const*>(TRI_AtVector(&array->_value._objects, i));
// don't push value if it is the same as the last value
if (last == nullptr || TRI_CompareValuesJson(p, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p);
if (last == nullptr || TRI_CompareValuesJson(p, last, false) != 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result.get(), p);
// remember last element
last = p;
}
}
return result;
return result.release();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the union of two sorted json lists into a new list
/// @brief sorts a json array in place
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_UnionizeListsJson (TRI_json_t const* list1,
TRI_json_t const* list2,
bool unique) {
TRI_json_t* last = nullptr;
TRI_json_t* result;
size_t i1, i2;
size_t n1, n2;
TRI_ASSERT(list1);
TRI_ASSERT(list1->_type == TRI_JSON_ARRAY);
TRI_ASSERT(list2);
TRI_ASSERT(list2->_type == TRI_JSON_ARRAY);
n1 = TRI_LengthVector(&list1->_value._objects);
n2 = TRI_LengthVector(&list2->_value._objects);
// special cases for empty lists
if (n1 == 0 && ! unique) {
return TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) list2);
}
if (n2 == 0 && ! unique) {
return TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) list1);
}
// create result list
result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, n1 > n2 ? n1 : n2);
if (result == nullptr) {
return nullptr;
}
// reset positions
i1 = 0;
i2 = 0;
// iterate over lists
while (true) {
// pointers to elements in both lists
TRI_json_t* p1;
TRI_json_t* p2;
if (i1 < n1 && i2 < n2) {
int compareResult;
// both lists not yet exhausted
p1 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list1->_value._objects, i1));
p2 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list2->_value._objects, i2));
compareResult = TRI_CompareValuesJson(p1, p2, true);
if (compareResult < 0) {
// left element is smaller
if (! unique || last == nullptr || TRI_CompareValuesJson(p1, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
last = p1;
}
++i1;
}
else if (compareResult > 0) {
// right element is smaller
if (! unique || last == nullptr || TRI_CompareValuesJson(p2, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
last = p2;
}
++i2;
}
else {
// both elements are equal
if (! unique || last == nullptr || TRI_CompareValuesJson(p1, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
last = p1;
if (! unique) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
}
}
++i1;
++i2;
}
}
else if (i1 < n1 && i2 >= n2) {
// only right list is exhausted
p1 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list1->_value._objects, i1));
if (! unique || last == nullptr || TRI_CompareValuesJson(p1, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
last = p1;
}
++i1;
}
else if (i1 >= n1 && i2 < n2) {
// only left list is exhausted
p2 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list2->_value._objects, i2));
if (! unique || last == nullptr || TRI_CompareValuesJson(p2, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
last = p2;
}
++i2;
}
else {
// both lists exhausted, stop!
break;
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create the intersection of two sorted json lists into a new list
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_IntersectListsJson (TRI_json_t const* list1,
TRI_json_t const* list2,
bool unique) {
TRI_json_t* last = nullptr;
TRI_json_t* result;
size_t i1, i2;
size_t n1, n2;
TRI_ASSERT(list1);
TRI_ASSERT(list1->_type == TRI_JSON_ARRAY);
TRI_ASSERT(list2);
TRI_ASSERT(list2->_type == TRI_JSON_ARRAY);
n1 = TRI_LengthVector(&list1->_value._objects);
n2 = TRI_LengthVector(&list2->_value._objects);
// create result list
result = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, n1 > n2 ? n1 : n2);
if (result == nullptr) {
return nullptr;
}
// special case for empty lists
if (n1 == 0 || n2 == 0) {
return result;
}
// reset positions
i1 = 0;
i2 = 0;
// iterate over lists
while (i1 < n1 && i2 < n2) {
// pointers to elements in both lists
auto p1 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list1->_value._objects, i1));
auto p2 = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&list2->_value._objects, i2));
int compareResult = TRI_CompareValuesJson(p1, p2, true);
if (compareResult < 0) {
// left element is smaller
++i1;
}
else if (compareResult > 0) {
// right element is smaller
++i2;
}
else {
// both elements are equal
if (! unique || last == nullptr || TRI_CompareValuesJson(p1, last, true) > 0) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
last = p1;
if (! unique) {
TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
}
}
++i1;
++i2;
}
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief sorts a json list in place
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_SortArrayJson (TRI_json_t* list) {
TRI_ASSERT(list != nullptr);
TRI_ASSERT(list->_type == TRI_JSON_ARRAY);
TRI_json_t* TRI_SortArrayJson (TRI_json_t* array) {
TRI_ASSERT(array != nullptr);
TRI_ASSERT(array->_type == TRI_JSON_ARRAY);
size_t const n = TRI_LengthVector(&list->_value._objects);
size_t const n = TRI_LengthVector(&array->_value._objects);
if (n > 1) {
// only sort if more than one value in list
qsort(TRI_BeginVector(&list->_value._objects), n, sizeof(TRI_json_t), &CompareJson);
// only sort if more than one value in array
qsort(TRI_BeginVector(&array->_value._objects), n, sizeof(TRI_json_t), &CompareJson);
}
return list;
return array;
}
////////////////////////////////////////////////////////////////////////////////
@ -680,16 +405,13 @@ bool TRI_HasDuplicateKeyJson (TRI_json_t const* object) {
}
for (i = 0; i < n; i += 2) {
TRI_json_t* key;
TRI_json_t* value;
key = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i));
auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&object->_value._objects, i));
if (! TRI_IsStringJson(key)) {
continue;
}
value = reinterpret_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i + 1));
auto value = static_cast<TRI_json_t const*>(TRI_AtVector(&object->_value._objects, i + 1));
// recursively check sub-array elements
if (value->_type == TRI_JSON_OBJECT && TRI_HasDuplicateKeyJson(value)) {
@ -735,9 +457,7 @@ TRI_json_t* TRI_MergeJson (TRI_memory_zone_t* zone,
TRI_ASSERT(lhs->_type == TRI_JSON_OBJECT);
TRI_ASSERT(rhs->_type == TRI_JSON_OBJECT);
TRI_json_t* result = MergeRecursive(zone, lhs, rhs, nullMeansRemove, mergeObjects);
return result;
return MergeRecursive(zone, lhs, rhs, nullMeansRemove, mergeObjects);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -63,32 +63,7 @@ bool TRI_CheckSameValueJson (TRI_json_t const*,
TRI_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief checks if a json value is contained in a json list
////////////////////////////////////////////////////////////////////////////////
bool TRI_CheckInArrayJson (TRI_json_t const*,
TRI_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief return the elements of a list that are between the specified bounds
///
/// lower and upper are the bounds values. if both lower and upper have a value,
/// then each list element is checked against the range (lower ... uppper).
/// if either lower or upper are null, then the comparison is done as either
/// (-inf ... upper) or (lower ... +inf).
///
/// using the boolean flags includeLower and includeUpper it can be specified
/// whether the bounds values are part of the range (true) or not (false)
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_BetweenArrayJson (TRI_json_t const*,
TRI_json_t const*,
bool,
TRI_json_t const*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief uniquify a sorted json list into a new list
/// @brief uniquify a sorted json list into a new array
///
/// it is a prerequisite that the input list is already sorted.
/// otherwise the result is unpredictable.
@ -97,29 +72,7 @@ TRI_json_t* TRI_BetweenArrayJson (TRI_json_t const*,
TRI_json_t* TRI_UniquifyArrayJson (TRI_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief create the union of two sorted json lists into a new list
///
/// the result list can be made unique or non-unique. it is a prerequisite that
/// both input lists are already sorted. otherwise the result is unpredictable.
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_UnionizeListsJson (TRI_json_t const*,
TRI_json_t const*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief create the intersection of two sorted json lists into a new list
///
/// the result list can be made unique or non-unique. it is a prerequisite that
/// both input lists are already sorted. otherwise the result is unpredictable.
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_IntersectListsJson (TRI_json_t const*,
TRI_json_t const*,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief sorts a json list in place
/// @brief sorts a json array in place
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_SortArrayJson (TRI_json_t*);

View File

@ -718,7 +718,7 @@ void TRI_InsertObjectJson (TRI_memory_zone_t* zone,
void TRI_Insert2ObjectJson (TRI_memory_zone_t* zone,
TRI_json_t* object,
char const* name,
TRI_json_t* subobject) {
TRI_json_t const* subobject) {
TRI_ASSERT(object->_type == TRI_JSON_OBJECT);
if (subobject == nullptr) {
@ -858,7 +858,10 @@ bool TRI_DeleteObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char con
/// @brief replaces an element in a json array
////////////////////////////////////////////////////////////////////////////////
bool TRI_ReplaceObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t* replacement) {
bool TRI_ReplaceObjectJson (TRI_memory_zone_t* zone,
TRI_json_t* object,
char const* name,
TRI_json_t const* replacement) {
TRI_ASSERT(object->_type == TRI_JSON_OBJECT);
TRI_ASSERT(name != nullptr);

View File

@ -266,67 +266,89 @@ bool TRI_IsStringJson (TRI_json_t const* json);
/// @brief adds a new sub-object to an array, copying it
////////////////////////////////////////////////////////////////////////////////
void TRI_PushBackArrayJson (TRI_memory_zone_t*, TRI_json_t* array, TRI_json_t const* object);
void TRI_PushBackArrayJson (TRI_memory_zone_t*,
TRI_json_t* array,
TRI_json_t const* object);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new sub-object to an array, not copying it
////////////////////////////////////////////////////////////////////////////////
int TRI_PushBack2ArrayJson (TRI_json_t* array, TRI_json_t const* object);
int TRI_PushBack2ArrayJson (TRI_json_t* array,
TRI_json_t const* object);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new sub-object, not copying it but freeing the pointer
////////////////////////////////////////////////////////////////////////////////
int TRI_PushBack3ArrayJson (TRI_memory_zone_t*, TRI_json_t* array, TRI_json_t* object);
int TRI_PushBack3ArrayJson (TRI_memory_zone_t*,
TRI_json_t* array,
TRI_json_t* object);
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a value in a json array
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_LookupArrayJson (TRI_json_t const*, size_t);
TRI_json_t* TRI_LookupArrayJson (TRI_json_t const*,
size_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new attribute to an object, using copy
////////////////////////////////////////////////////////////////////////////////
void TRI_InsertObjectJson (TRI_memory_zone_t*, TRI_json_t* object, char const* name, TRI_json_t const* subobject);
void TRI_InsertObjectJson (TRI_memory_zone_t*,
TRI_json_t* object,
char const* name,
TRI_json_t const* subobject);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new attribute to an object, not copying it
////////////////////////////////////////////////////////////////////////////////
void TRI_Insert2ObjectJson (TRI_memory_zone_t*, TRI_json_t* object, char const* name, TRI_json_t* subobject);
void TRI_Insert2ObjectJson (TRI_memory_zone_t*,
TRI_json_t* object,
char const* name,
TRI_json_t const* subobject);
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a new attribute, not copying it but freeing the pointer
////////////////////////////////////////////////////////////////////////////////
void TRI_Insert3ObjectJson (TRI_memory_zone_t*, TRI_json_t* object, char const* name, TRI_json_t* subobject);
void TRI_Insert3ObjectJson (TRI_memory_zone_t*,
TRI_json_t* object,
char const* name,
TRI_json_t* subobject);
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up an attribute in a json object
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* TRI_LookupObjectJson (TRI_json_t const* object, char const* name);
TRI_json_t* TRI_LookupObjectJson (TRI_json_t const* object,
char const* name);
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes an element from a json object
////////////////////////////////////////////////////////////////////////////////
bool TRI_DeleteObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name);
bool TRI_DeleteObjectJson (TRI_memory_zone_t* zone,
TRI_json_t* object,
char const* name);
////////////////////////////////////////////////////////////////////////////////
/// @brief replaces an element in a json object
////////////////////////////////////////////////////////////////////////////////
bool TRI_ReplaceObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t* replacement);
bool TRI_ReplaceObjectJson (TRI_memory_zone_t* zone,
TRI_json_t* object,
char const* name,
TRI_json_t const* replacement);
////////////////////////////////////////////////////////////////////////////////
/// @brief stringifies a json object
////////////////////////////////////////////////////////////////////////////////
int TRI_StringifyJson (struct TRI_string_buffer_s*, TRI_json_t const* object);
int TRI_StringifyJson (struct TRI_string_buffer_s*,
TRI_json_t const* object);
////////////////////////////////////////////////////////////////////////////////
/// @brief stringifies a json object skiping the outer braces