예제 #1
0
TRI_json_t* TRI_BetweenListJson (const TRI_json_t* const list,
                                 const TRI_json_t* const lower,
                                 const bool includeLower,
                                 const TRI_json_t* const upper,
                                 const bool includeUpper) {
  TRI_json_t* result;
  size_t i, n;

  TRI_ASSERT(list);
  TRI_ASSERT(list->_type == TRI_JSON_LIST);
  TRI_ASSERT(lower || upper);

  // create result list
  result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);

  if (result == NULL) {
    return NULL;
  }

  n = list->_value._objects._length;

  for (i = 0; i < n; ++i) {
    TRI_json_t* p = TRI_AtVector(&list->_value._objects, i);

    if (lower) {
      // lower bound is set
      int compareResult = TRI_CompareValuesJson(lower, p);
      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);
      if (compareResult > 0 || (compareResult == 0 && ! includeUpper)) {
        // element is smaller than upper bound
        continue;
      }
    }

    // element is between lower and upper bound

    TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p);
  }

  return result;
}
예제 #2
0
TRI_json_t* TRI_UniquifyListJson (const TRI_json_t* const list) {
  TRI_json_t* last = NULL;
  TRI_json_t* result;
  size_t i, n;

  assert(list);
  assert(list->_type == TRI_JSON_LIST);
  
  // create result list
  result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
  if (!result) {
    return NULL;
  }

  n = list->_value._objects._length;
  for (i = 0; i < n; ++i) {
    TRI_json_t* p = TRI_AtVector(&list->_value._objects, i);
 
    // don't push value if it is the same as the last value
    if (!last || TRI_CompareValuesJson(p, last) > 0) {
      TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p);
      // remember last element
      last = p;
    }
  }

  return result;
}
예제 #3
0
TRI_json_t* TRI_UniquifyArrayJson (TRI_json_t const* array) {
    TRI_ASSERT(array != nullptr);
    TRI_ASSERT(array->_type == TRI_JSON_ARRAY);

    // 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) {
        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, false) != 0) {
            TRI_PushBackArrayJson(TRI_UNKNOWN_MEM_ZONE, result.get(), p);

            // remember last element
            last = p;
        }
    }

    return result.release();
}
예제 #4
0
static int CompareJson (TRI_json_t* lhs, TRI_json_t* rhs, size_t size) {
  return TRI_CompareValuesJson((TRI_json_t*) lhs, (TRI_json_t*) rhs);
}
예제 #5
0
TRI_json_t* TRI_IntersectListsJson (const TRI_json_t* const list1, 
                                    const TRI_json_t* const list2,
                                    const bool unique) {
  TRI_json_t* last = NULL;
  TRI_json_t* result;
  size_t i1, i2;
  size_t n1, n2;

  assert(list1);
  assert(list1->_type == TRI_JSON_LIST);
  assert(list2);
  assert(list2->_type == TRI_JSON_LIST);
  
  // create result list
  result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
  if (!result) {
    return NULL;
  }
  
  n1 = list1->_value._objects._length;
  n2 = list2->_value._objects._length;

  // 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
    TRI_json_t* p1 = TRI_AtVector(&list1->_value._objects, i1);
    TRI_json_t* p2 = TRI_AtVector(&list2->_value._objects, i2);

    int compareResult = TRI_CompareValuesJson(p1, p2);

    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 || TRI_CompareValuesJson(p1, last) > 0) {
        TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
        last = p1;
        if (!unique) {
          TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
        }
      }
      ++i1;
      ++i2;
    }
  }

  return result;
}
예제 #6
0
TRI_json_t* TRI_UnionizeListsJson (const TRI_json_t* const list1, 
                                   const TRI_json_t* const list2,
                                   const bool unique) {
  TRI_json_t* last = NULL;
  TRI_json_t* result;
  size_t i1, i2;
  size_t n1, n2;

  assert(list1);
  assert(list1->_type == TRI_JSON_LIST);
  assert(list2);
  assert(list2->_type == TRI_JSON_LIST);
  
  n1 = list1->_value._objects._length;
  n2 = list2->_value._objects._length;

  // 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_CreateListJson(TRI_UNKNOWN_MEM_ZONE);
  if (!result) {
    return NULL;
  }

  // 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 = TRI_AtVector(&list1->_value._objects, i1);
      p2 = TRI_AtVector(&list2->_value._objects, i2);
      compareResult = TRI_CompareValuesJson(p1, p2);

      if (compareResult < 0) {
        // left element is smaller
        if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) {
          TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
          last = p1;
        }
        ++i1;
      } 
      else if (compareResult > 0) {
        // right element is smaller
        if (!unique || !last || TRI_CompareValuesJson(p2, last) > 0) {
          TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
          last = p2;
        }
        ++i2;
      }
      else {
        // both elements are equal
        if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) {
          TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
          last = p1;
          if (!unique) {
            TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
          }
        }
        ++i1;
        ++i2;
      }
    }
    else if (i1 < n1 && i2 >= n2) {
      // only right list is exhausted
      p1 = TRI_AtVector(&list1->_value._objects, i1);

      if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) {
        TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1);
        last = p1;
      }
      ++i1;
    }
    else if (i1 >= n1 && i2 < n2) {
      // only left list is exhausted
      p2 = TRI_AtVector(&list2->_value._objects, i2);

      if (!unique || !last || TRI_CompareValuesJson(p2, last) > 0) {
        TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2);
        last = p2;
      }
      ++i2;
    }
    else {
      // both lists exhausted, stop!
      break;
    }
  }

  return result;
}
예제 #7
0
bool TRI_CheckSameValueJson (const TRI_json_t* const lhs, 
                             const TRI_json_t* const rhs) {
  return (TRI_CompareValuesJson(lhs, rhs) == 0);
}
예제 #8
0
int TRI_CompareValuesJson (const TRI_json_t* const lhs, 
                           const TRI_json_t* const rhs) {
  // note: both lhs and rhs may be NULL!
  int lWeight = TypeWeight(lhs);
  int rWeight = TypeWeight(rhs);
  
  if (lWeight < rWeight) {
    return -1;
  }

  if (lWeight > rWeight) {
    return 1;
  }

  // lhs and rhs have equal weights
  if (lhs == NULL) {
    // both lhs and rhs are NULL, so they are equal
    return 0;
  }

  switch (lhs->_type) {
    case TRI_JSON_UNUSED:
    case TRI_JSON_NULL:
      return 0; // null == null;

    case TRI_JSON_BOOLEAN:
      if (lhs->_value._boolean == rhs->_value._boolean) {
        return 0;
      }

      if (!lhs->_value._boolean && rhs->_value._boolean) {
        return -1;
      }

      return 1;

    case TRI_JSON_NUMBER:
      if (lhs->_value._number == rhs->_value._number) {
        return 0;
      }

      if (lhs->_value._number < rhs->_value._number) {
        return -1;
      }

      return 1;

    case TRI_JSON_STRING:
      return strcmp(lhs->_value._string.data, rhs->_value._string.data);

    case TRI_JSON_LIST: {
      size_t nl = lhs->_value._objects._length;
      size_t nr = rhs->_value._objects._length;
      size_t n;
      size_t i;

      if (nl > nr) {
        n = nl;
      }
      else {
        n = nr;
      }

      for (i = 0; i < n; ++i) {
        TRI_json_t* lhsValue;
        TRI_json_t* rhsValue;
        int result;

        lhsValue = (i >= nl) ? NULL : TRI_AtVector(&lhs->_value._objects, i);
        rhsValue = (i >= nr) ? NULL : TRI_AtVector(&rhs->_value._objects, i);
        result = TRI_CompareValuesJson(lhsValue, rhsValue);
        if (result != 0) {
          return result;
        }
      }

      return 0;
    }

    case TRI_JSON_ARRAY: {
      TRI_json_t* keys;
          
      assert(lhs->_type == TRI_JSON_ARRAY);
      assert(rhs->_type == TRI_JSON_ARRAY);

      keys = GetMergedKeyList(lhs, rhs);
      if (keys != NULL) {
        size_t i, n;

        n = keys->_value._objects._length;
        for (i = 0; i < n; ++i) {
          TRI_json_t* keyElement;
          TRI_json_t* lhsValue;
          TRI_json_t* rhsValue;
          int result;

          keyElement = TRI_AtVector(&keys->_value._objects, i);
          assert(keyElement->_type == TRI_JSON_STRING);
          assert(keyElement->_value._string.data);

          lhsValue = TRI_LookupArrayJson((TRI_json_t*) lhs, keyElement->_value._string.data); // may be NULL
          rhsValue = TRI_LookupArrayJson((TRI_json_t*) rhs, keyElement->_value._string.data); // may be NULL
        
          result = TRI_CompareValuesJson(lhsValue, rhsValue);
          if (result != 0) {
            TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, keys);
            return result;
          }
        }

        TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, keys);
      }

      return 0;
    }

    default:
      return 0;
  }
}
예제 #9
0
bool TRI_CheckSameValueJson (TRI_json_t const* lhs,
                             TRI_json_t const* rhs) {
    return (TRI_CompareValuesJson(lhs, rhs, false) == 0);
}
예제 #10
0
int TRI_CompareValuesJson (TRI_json_t const* lhs,
                           TRI_json_t const* rhs,
                           bool useUTF8) {
    // note: both lhs and rhs may be NULL!
    {
        int lWeight = TypeWeight(lhs);
        int rWeight = TypeWeight(rhs);

        if (lWeight < rWeight) {
            return -1;
        }

        if (lWeight > rWeight) {
            return 1;
        }

        TRI_ASSERT_EXPENSIVE(lWeight == rWeight);
    }

    // lhs and rhs have equal weights

    if (lhs == nullptr || rhs == nullptr) {
        // either lhs or rhs is a nullptr. we cannot be sure here that both are nullptrs.
        // there can also exist the situation that lhs is a nullptr and rhs is a JSON null value
        // (or vice versa). Anyway, the compare value is the same for both,
        return 0;
    }

    switch (lhs->_type) {
    case TRI_JSON_UNUSED:
    case TRI_JSON_NULL: {
        return 0; // null == null;
    }

    case TRI_JSON_BOOLEAN: {
        if (lhs->_value._boolean == rhs->_value._boolean) {
            return 0;
        }

        if (! lhs->_value._boolean && rhs->_value._boolean) {
            return -1;
        }

        return 1;
    }

    case TRI_JSON_NUMBER: {
        if (lhs->_value._number == rhs->_value._number) {
            return 0;
        }

        if (lhs->_value._number < rhs->_value._number) {
            return -1;
        }

        return 1;
    }

    case TRI_JSON_STRING:
    case TRI_JSON_STRING_REFERENCE: {
        // same for STRING and STRING_REFERENCE
        TRI_ASSERT(lhs->_value._string.data != nullptr);
        TRI_ASSERT(rhs->_value._string.data != nullptr);

        int res;
        size_t const nl = lhs->_value._string.length - 1;
        size_t const nr = rhs->_value._string.length - 1;
        if (useUTF8) {
            res = TRI_compare_utf8(lhs->_value._string.data,
                                   nl,
                                   rhs->_value._string.data,
                                   nr);
        }
        else {
            // beware of strings containing NUL bytes
            size_t len = nl < nr ? nl : nr;
            res = memcmp(lhs->_value._string.data, rhs->_value._string.data, len);
        }
        if (res < 0) {
            return -1;
        }
        else if (res > 0) {
            return 1;
        }
        // res == 0
        if (nl == nr) {
            return 0;
        }
        // res == 0, but different string lengths
        return nl < nr ? -1 : 1;
    }

    case TRI_JSON_ARRAY: {
        size_t const nl = TRI_LengthVector(&lhs->_value._objects);
        size_t const nr = TRI_LengthVector(&rhs->_value._objects);
        size_t n;

        if (nl > nr) {
            n = nl;
        }
        else {
            n = nr;
        }

        for (size_t i = 0; i < n; ++i) {
            auto lhsValue = (i >= nl) ? nullptr : static_cast<TRI_json_t const*>(TRI_AtVector(&lhs->_value._objects, i));
            auto rhsValue = (i >= nr) ? nullptr : static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i));

            int result = TRI_CompareValuesJson(lhsValue, rhsValue, useUTF8);

            if (result != 0) {
                return result;
            }
        }

        return 0;
    }

    case TRI_JSON_OBJECT: {
        TRI_ASSERT(lhs->_type == TRI_JSON_OBJECT);
        TRI_ASSERT(rhs->_type == TRI_JSON_OBJECT);

        std::unique_ptr<TRI_json_t> keys(GetMergedKeyArray(lhs, rhs));

        if (keys != nullptr) {
            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(&json->_value._objects, i));
                TRI_ASSERT(TRI_IsStringJson(keyElement));

                TRI_json_t const* lhsValue = TRI_LookupObjectJson(lhs, keyElement->_value._string.data); // may be NULL
                TRI_json_t const* rhsValue = TRI_LookupObjectJson(rhs, keyElement->_value._string.data); // may be NULL

                int result = TRI_CompareValuesJson(lhsValue, rhsValue, useUTF8);

                if (result != 0) {
                    return result;
                }
            }
        }
        // fall-through to returning 0
    }

    }

    return 0;
}
예제 #11
0
static int CompareJson (void const* lhs,
                        void const* rhs) {
    return TRI_CompareValuesJson(static_cast<TRI_json_t const*>(lhs), static_cast<TRI_json_t const*>(rhs), true);
}