From 2f90f5ec4945e9dde35544d7261dfaac85abb453 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 3 Jul 2019 12:14:52 +0200 Subject: [PATCH] update velocypack version (#9379) --- .../velocypack/include/velocypack/Builder.h | 71 +++++--- .../velocypack/include/velocypack/Compare.h | 153 +++++------------ .../include/velocypack/Serializable.h | 52 ++++++ .../velocypack/include/velocypack/Value.h | 2 +- .../include/velocypack/velocypack-aliases.h | 8 + 3rdParty/velocypack/src/Compare.cpp | 161 ++++++++++++++++++ 3rdParty/velocypack/src/Serializable.cpp | 36 ++++ arangod/RestHandler/RestRepairHandler.cpp | 3 + lib/CMakeLists.txt | 2 + 9 files changed, 361 insertions(+), 127 deletions(-) create mode 100644 3rdParty/velocypack/include/velocypack/Serializable.h create mode 100644 3rdParty/velocypack/src/Compare.cpp create mode 100644 3rdParty/velocypack/src/Serializable.cpp diff --git a/3rdParty/velocypack/include/velocypack/Builder.h b/3rdParty/velocypack/include/velocypack/Builder.h index ec983ba7a8..21079fb1ac 100644 --- a/3rdParty/velocypack/include/velocypack/Builder.h +++ b/3rdParty/velocypack/include/velocypack/Builder.h @@ -40,6 +40,7 @@ #include "velocypack/Buffer.h" #include "velocypack/Exception.h" #include "velocypack/Options.h" +#include "velocypack/Serializable.h" #include "velocypack/Slice.h" #include "velocypack/StringRef.h" #include "velocypack/Value.h" @@ -74,7 +75,7 @@ class Builder { // buffer. Whenever the stack is empty, one can use the start, // size and slice methods to get out the ready built VPack // object(s). - + private: std::shared_ptr> _buffer; // Here we collect the result Buffer* _bufferPtr; // used for quicker access than shared_ptr @@ -89,10 +90,10 @@ class Builder { public: Options const* options; - - // create an empty Builder, using default Options + + // create an empty Builder, using default Options Builder(); - + explicit Builder(Options const* options); explicit Builder(std::shared_ptr> const& buffer, Options const* options = &Options::Defaults); @@ -208,7 +209,7 @@ class Builder { ValueLength const tos = _stack.back(); return _start[tos] == 0x0b || _start[tos] == 0x14; } - + inline void openArray(bool unindexed = false) { openCompoundValue(unindexed ? 0x13 : 0x06); } @@ -216,7 +217,7 @@ class Builder { inline void openObject(bool unindexed = false) { openCompoundValue(unindexed ? 0x14 : 0x0b); } - + template uint8_t* addUnchecked(char const* attrName, std::size_t attrLength, T const& sub) { bool haveReported = false; @@ -251,7 +252,7 @@ class Builder { inline uint8_t* add(char const* attrName, std::size_t attrLength, Value const& sub) { return addInternal(attrName, attrLength, sub); } - + // Add a subvalue into an object from a Slice: inline uint8_t* add(std::string const& attrName, Slice const& sub) { return addInternal(attrName, sub); @@ -265,7 +266,7 @@ class Builder { inline uint8_t* add(char const* attrName, std::size_t attrLength, Slice const& sub) { return addInternal(attrName, attrLength, sub); } - + // Add a subvalue into an object from a ValuePair: inline uint8_t* add(std::string const& attrName, ValuePair const& sub) { return addInternal(attrName, sub); @@ -279,15 +280,29 @@ class Builder { inline uint8_t* add(char const* attrName, std::size_t attrLength, ValuePair const& sub) { return addInternal(attrName, attrLength, sub); } - + + // Add a subvalue into an object from a Serializable: + inline uint8_t* add(std::string const& attrName, Serialize const& sub) { + return addInternal(attrName, sub._sable); + } + inline uint8_t* add(StringRef const& attrName, Serialize const& sub) { + return addInternal(attrName, sub._sable); + } + inline uint8_t* add(char const* attrName, Serialize const& sub) { + return addInternal(attrName, sub._sable); + } + inline uint8_t* add(char const* attrName, std::size_t attrLength, Serialize const& sub) { + return addInternal(attrName, attrLength, sub._sable); + } + // Add a subvalue into an array from a Value: inline uint8_t* add(Value const& sub) { - return addInternal(sub); + return addInternal(sub); } - + // Add a slice to an array inline uint8_t* add(Slice const& sub) { - return addInternal(sub); + return addInternal(sub); } // Add a subvalue into an array from a ValuePair: @@ -295,6 +310,11 @@ class Builder { return addInternal(sub); } + // Add a subvalue into an array from a Serializable: + inline uint8_t* add(Serialize const& sub) { + return addInternal(sub._sable); + } + // Add an External slice to an array uint8_t* addExternal(uint8_t const* sub) { if (options->disallowExternals) { @@ -327,7 +347,7 @@ class Builder { throw; } } - + // Add all subkeys and subvalues into an object from an ObjectIterator // and leaves open the object intentionally uint8_t* add(ObjectIterator&& sub); @@ -445,18 +465,23 @@ class Builder { void addInt(int64_t v) { if (v >= 0 && v <= 9) { + // SmallInt appendByte(static_cast(0x30 + v)); } else if (v < 0 && v >= -6) { + // SmallInt appendByte(static_cast(0x40 + v)); } else { + // regular int appendInt(v, 0x1f); } } void addUInt(uint64_t v) { if (v <= 9) { + // SmallInt appendByte(static_cast(0x30 + v)); } else { + // regular UInt appendUInt(v, 0x27); } } @@ -524,7 +549,7 @@ class Builder { uint8_t* addInternal(std::string const& attrName, T const& sub) { return addInternal(attrName.data(), attrName.size(), sub); } - + template uint8_t* addInternal(StringRef const& attrName, T const& sub) { return addInternal(attrName.data(), attrName.size(), sub); @@ -579,7 +604,7 @@ class Builder { throw; } } - + void addCompoundValue(uint8_t type) { reserve(9); // an Array or Object is started: @@ -624,6 +649,12 @@ class Builder { uint8_t* set(Slice const& item); + uint8_t* set(Serializable const& sable) { + auto const oldPos = _pos; + sable.toVelocyPack(*this); + return _start + oldPos; + } + void cleanupAdd() noexcept { std::size_t depth = _stack.size() - 1; VELOCYPACK_ASSERT(!_index[depth].empty()); @@ -640,7 +671,7 @@ class Builder { reserve(n); appendLengthUnchecked(v); } - + template void appendLengthUnchecked(ValueLength v) { for (uint64_t i = 0; i < n; ++i) { @@ -695,18 +726,18 @@ class Builder { x >>= 8; } } - + inline void appendByte(uint8_t value) { reserve(1); appendByteUnchecked(value); } - + inline void appendByteUnchecked(uint8_t value) { _start[_pos++] = value; VELOCYPACK_ASSERT(_bufferPtr != nullptr); _bufferPtr->advance(); } - + inline void resetTo(std::size_t value) { _pos = value; VELOCYPACK_ASSERT(_bufferPtr != nullptr); @@ -719,7 +750,7 @@ class Builder { VELOCYPACK_ASSERT(_bufferPtr != nullptr); _bufferPtr->advance(value); } - + // move byte position x bytes back inline void rollback(std::size_t value) noexcept { _pos -= value; diff --git a/3rdParty/velocypack/include/velocypack/Compare.h b/3rdParty/velocypack/include/velocypack/Compare.h index 2fb24d15ca..240dd31ad6 100644 --- a/3rdParty/velocypack/include/velocypack/Compare.h +++ b/3rdParty/velocypack/include/velocypack/Compare.h @@ -28,122 +28,63 @@ #define VELOCYPACK_COMPARE_H 1 #include "velocypack/velocypack-common.h" -#include "velocypack/Collection.h" -#include "velocypack/Exception.h" -#include "velocypack/Iterator.h" -#include "velocypack/Slice.h" -#include "velocypack/ValueType.h" - -#include namespace arangodb { namespace velocypack { -struct NormalizedCompare { +struct Options; +class Slice; -static bool equalsNumbers(Slice lhs, Slice rhs) { - auto lhsType = lhs.type(); - if (lhsType == rhs.type()) { - // both types are equal - if (lhsType == ValueType::Int || lhsType == ValueType::SmallInt) { - // use exact comparisons. no need to cast to double - return (lhs.getIntUnchecked() == rhs.getIntUnchecked()); - } +// helper struct for comparing VelocyPack Slices on a binary level +struct BinaryCompare { +// returns true if the two Slices are identical on the binary level +static bool equals(Slice lhs, Slice rhs); - if (lhsType == ValueType::UInt) { - // use exact comparisons. no need to cast to double - return (lhs.getUIntUnchecked() == rhs.getUIntUnchecked()); - } - // fallthrough to double comparison - } - - return (lhs.getNumericValue() == rhs.getNumericValue()); -} - -static bool equalsStrings(Slice lhs, Slice rhs) { - ValueLength nl; - char const* left = lhs.getString(nl); - VELOCYPACK_ASSERT(left != nullptr); - ValueLength nr; - char const* right = rhs.getString(nr); - VELOCYPACK_ASSERT(right != nullptr); - return (nl == nr && (memcmp(left, right, nl) == 0)); -} - -static bool equals(Slice lhs, Slice rhs) { - lhs = lhs.resolveExternals(); - rhs = rhs.resolveExternals(); - ValueType lhsType = valueTypeGroup(lhs.type()); - ValueType rhsType = valueTypeGroup(rhs.type()); - - if (lhsType != rhsType) { - // unequal types => not equal - return false; - } +struct Hash { + size_t operator()(arangodb::velocypack::Slice const&) const; +}; - switch (lhsType) { - case ValueType::Illegal: - case ValueType::None: - case ValueType::Null: - // Null equals Null - case ValueType::MinKey: - case ValueType::MaxKey: { - return true; - } - case ValueType::Bool: { - return (lhs.getBoolean() == rhs.getBoolean()); - } - case ValueType::Double: - case ValueType::Int: - case ValueType::UInt: - case ValueType::SmallInt: { - return equalsNumbers(lhs, rhs); - } - case ValueType::String: { - return equalsStrings(lhs, rhs); - } - case ValueType::Array: { - ArrayIterator lhsValue(lhs); - ArrayIterator rhsValue(rhs); +struct Equal { + arangodb::velocypack::Options const* _options; - ValueLength const n = lhsValue.size(); - if (n != rhsValue.size()) { - // unequal array lengths - return false; - } - for (ValueLength i = 0; i < n; ++i) { - // recurse - if (!equals(lhsValue.value(), rhsValue.value())) { - return false; - } - lhsValue.next(); - rhsValue.next(); - } - return true; - } - case ValueType::Object: { - std::set keys; - // get all keys and bring them in order - Collection::unorderedKeys(lhs, keys); - Collection::unorderedKeys(rhs, keys); - for (auto const& key : keys) { - // recurse - if (!equals(lhs.get(key), rhs.get(key))) { - return false; - } - } - return true; - } - case ValueType::Custom: { - throw Exception(Exception::NotImplemented, "equals comparison for Custom type is not implemented"); - } - default: { - throw Exception(Exception::InternalError, "invalid value type for equals comparison"); - } - } -} + Equal() : _options(nullptr) {} + explicit Equal(arangodb::velocypack::Options const* opts) + : _options(opts) {} + + bool operator()(arangodb::velocypack::Slice const&, + arangodb::velocypack::Slice const&) const; +}; }; +// helper struct for comparing VelocyPack Slices in a normalized way +struct NormalizedCompare { + +// function to compare two numeric values +static bool equalsNumbers(Slice lhs, Slice rhs); + +// function to compare two string values +static bool equalsStrings(Slice lhs, Slice rhs); + +// function to compare two arbitrary Slices +static bool equals(Slice lhs, Slice rhs); + +struct Hash { + size_t operator()(arangodb::velocypack::Slice const&) const; +}; + +struct Equal { + arangodb::velocypack::Options const* _options; + + Equal() : _options(nullptr) {} + explicit Equal(arangodb::velocypack::Options const* opts) + : _options(opts) {} + + bool operator()(arangodb::velocypack::Slice const&, + arangodb::velocypack::Slice const&) const; +}; + +}; + } } diff --git a/3rdParty/velocypack/include/velocypack/Serializable.h b/3rdParty/velocypack/include/velocypack/Serializable.h new file mode 100644 index 0000000000..20a5f60dcd --- /dev/null +++ b/3rdParty/velocypack/include/velocypack/Serializable.h @@ -0,0 +1,52 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Library to build up VPack documents. +/// +/// DISCLAIMER +/// +/// Copyright 2015 ArangoDB GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef VELOCYPACK_SERIALIZABLE_H +#define VELOCYPACK_SERIALIZABLE_H 1 + +#include + +#include "velocypack/velocypack-common.h" + +namespace arangodb { +namespace velocypack { +class Builder; + +class Serializable { + public: + virtual void toVelocyPack(Builder&) const = 0; + + // convenience method + std::shared_ptr toVelocyPack() const; +}; + +struct Serialize { + Serialize(Serializable const& sable) : _sable(sable) {} + Serializable const& _sable; +}; + +} +} + +#endif diff --git a/3rdParty/velocypack/include/velocypack/Value.h b/3rdParty/velocypack/include/velocypack/Value.h index c083e52e79..f99783b046 100644 --- a/3rdParty/velocypack/include/velocypack/Value.h +++ b/3rdParty/velocypack/include/velocypack/Value.h @@ -200,7 +200,7 @@ class ValuePair { explicit ValuePair(uint64_t size, ValueType type = ValueType::Binary) noexcept : _start(nullptr), _size(size), _type(type) {} - + explicit ValuePair(StringRef const& value, ValueType type = ValueType::Binary) noexcept; uint8_t const* getStart() const { return _start; } diff --git a/3rdParty/velocypack/include/velocypack/velocypack-aliases.h b/3rdParty/velocypack/include/velocypack/velocypack-aliases.h index a112e7c64a..ba8ba8b73e 100644 --- a/3rdParty/velocypack/include/velocypack/velocypack-aliases.h +++ b/3rdParty/velocypack/include/velocypack/velocypack-aliases.h @@ -135,6 +135,14 @@ using VPackParser = arangodb::velocypack::Parser; #endif #endif +#ifdef VELOCYPACK_SERIALIZABLE_H +#ifndef VELOCYPACK_ALIAS_SERIALIZABLE +#define VELOCYPACK_ALIAS_SERIALIZABLE +using VPackSerializable = arangodb::velocypack::Serializable; +using VPackSerialize = arangodb::velocypack::Serialize; +#endif +#endif + #ifdef VELOCYPACK_SLICE_H #ifndef VELOCYPACK_ALIAS_SLICE #define VELOCYPACK_ALIAS_SLICE diff --git a/3rdParty/velocypack/src/Compare.cpp b/3rdParty/velocypack/src/Compare.cpp new file mode 100644 index 0000000000..f429ddf630 --- /dev/null +++ b/3rdParty/velocypack/src/Compare.cpp @@ -0,0 +1,161 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Library to build up VPack documents. +/// +/// DISCLAIMER +/// +/// Copyright 2015 ArangoDB GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Max Neunhoeffer +/// @author Jan Steemann +/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "velocypack/Compare.h" +#include "velocypack/Collection.h" +#include "velocypack/Exception.h" +#include "velocypack/Iterator.h" +#include "velocypack/Options.h" +#include "velocypack/Slice.h" +#include "velocypack/ValueType.h" + +#include + +using namespace arangodb::velocypack; + +bool BinaryCompare::equals(Slice lhs, Slice rhs) { + return lhs.binaryEquals(rhs); +} + +size_t BinaryCompare::Hash::operator()(arangodb::velocypack::Slice const& slice) const { + return static_cast(slice.hash()); +} + +bool BinaryCompare::Equal::operator()(arangodb::velocypack::Slice const& lhs, + arangodb::velocypack::Slice const& rhs) const { + return lhs.binaryEquals(rhs); +} + +bool NormalizedCompare::equalsNumbers(Slice lhs, Slice rhs) { + auto lhsType = lhs.type(); + if (lhsType == rhs.type()) { + // both types are equal + if (lhsType == ValueType::Int || lhsType == ValueType::SmallInt) { + // use exact comparisons. no need to cast to double + return (lhs.getIntUnchecked() == rhs.getIntUnchecked()); + } + + if (lhsType == ValueType::UInt) { + // use exact comparisons. no need to cast to double + return (lhs.getUIntUnchecked() == rhs.getUIntUnchecked()); + } + // fallthrough to double comparison + } + + return (lhs.getNumericValue() == rhs.getNumericValue()); +} + +bool NormalizedCompare::equalsStrings(Slice lhs, Slice rhs) { + ValueLength nl; + char const* left = lhs.getString(nl); + VELOCYPACK_ASSERT(left != nullptr); + ValueLength nr; + char const* right = rhs.getString(nr); + VELOCYPACK_ASSERT(right != nullptr); + return (nl == nr && (memcmp(left, right, nl) == 0)); +} + +bool NormalizedCompare::equals(Slice lhs, Slice rhs) { + lhs = lhs.resolveExternals(); + rhs = rhs.resolveExternals(); + ValueType lhsType = valueTypeGroup(lhs.type()); + ValueType rhsType = valueTypeGroup(rhs.type()); + + if (lhsType != rhsType) { + // unequal types => not equal + return false; + } + + switch (lhsType) { + case ValueType::Illegal: + case ValueType::None: + case ValueType::Null: + // Null equals Null + case ValueType::MinKey: + case ValueType::MaxKey: { + return true; + } + case ValueType::Bool: { + return (lhs.getBoolean() == rhs.getBoolean()); + } + case ValueType::Double: + case ValueType::Int: + case ValueType::UInt: + case ValueType::SmallInt: { + return equalsNumbers(lhs, rhs); + } + case ValueType::String: { + return equalsStrings(lhs, rhs); + } + case ValueType::Array: { + ArrayIterator lhsValue(lhs); + ArrayIterator rhsValue(rhs); + + ValueLength const n = lhsValue.size(); + if (n != rhsValue.size()) { + // unequal array lengths + return false; + } + for (ValueLength i = 0; i < n; ++i) { + // recurse + if (!equals(lhsValue.value(), rhsValue.value())) { + return false; + } + lhsValue.next(); + rhsValue.next(); + } + return true; + } + case ValueType::Object: { + std::set keys; + // get all keys and bring them in order + Collection::unorderedKeys(lhs, keys); + Collection::unorderedKeys(rhs, keys); + for (auto const& key : keys) { + // recurse + if (!equals(lhs.get(key), rhs.get(key))) { + return false; + } + } + return true; + } + case ValueType::Custom: { + throw Exception(Exception::NotImplemented, "equals comparison for Custom type is not implemented"); + } + default: { + throw Exception(Exception::InternalError, "invalid value type for equals comparison"); + } + } +} + +size_t NormalizedCompare::Hash::operator()(arangodb::velocypack::Slice const& slice) const { + return static_cast(slice.normalizedHash()); +} + +bool NormalizedCompare::Equal::operator()(arangodb::velocypack::Slice const& lhs, + arangodb::velocypack::Slice const& rhs) const { + return NormalizedCompare::equals(lhs, rhs); +} diff --git a/3rdParty/velocypack/src/Serializable.cpp b/3rdParty/velocypack/src/Serializable.cpp new file mode 100644 index 0000000000..17b22394f3 --- /dev/null +++ b/3rdParty/velocypack/src/Serializable.cpp @@ -0,0 +1,36 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Library to build up VPack documents. +/// +/// DISCLAIMER +/// +/// Copyright 2015 ArangoDB GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "velocypack/velocypack-common.h" +#include "velocypack/Serializable.h" +#include "velocypack/Builder.h" + +using namespace arangodb::velocypack; + +// convenience method +std::shared_ptr Serializable::toVelocyPack() const { + auto builder = std::make_shared(); + this->toVelocyPack(*builder); + return builder; +} diff --git a/arangod/RestHandler/RestRepairHandler.cpp b/arangod/RestHandler/RestRepairHandler.cpp index e219fc6485..59e4b27a1a 100644 --- a/arangod/RestHandler/RestRepairHandler.cpp +++ b/arangod/RestHandler/RestRepairHandler.cpp @@ -34,6 +34,9 @@ #include "Scheduler/SchedulerFeature.h" #include "VocBase/LogicalCollection.h" +#include +#include + using namespace arangodb; using namespace arangodb::basics; using namespace arangodb::rest; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8be9ce4abf..88bb897c04 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -68,12 +68,14 @@ set(LIB_ARANGO_VPACK ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/AttributeTranslator.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Builder.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Collection.cpp + ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Compare.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Dumper.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Exception.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/HexDump.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Iterator.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Options.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Parser.cpp + ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Serializable.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Slice.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/SliceStaticData.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/StringRef.cpp