diff --git a/3rdParty/velocypack/include/velocypack/Buffer.h b/3rdParty/velocypack/include/velocypack/Buffer.h index a80c7143e4..b30a5d844e 100644 --- a/3rdParty/velocypack/include/velocypack/Buffer.h +++ b/3rdParty/velocypack/include/velocypack/Buffer.h @@ -229,6 +229,8 @@ class Buffer { return append(value.data(), value.size()); } + // reserves len *extra* bytes of storage space + // this should probably be renamed to reserveExtra inline void reserve(ValueLength len) { VELOCYPACK_ASSERT(_size <= _capacity); @@ -255,8 +257,8 @@ class Buffer { // need reallocation ValueLength newLen = _size + len; - static constexpr double growthFactor = 1.25; - if (_size > 0 && newLen < growthFactor * _size) { + constexpr double growthFactor = 1.25; + if (newLen < growthFactor * _size) { // ensure the buffer grows sensibly and not by 1 byte only newLen = static_cast(growthFactor * _size); } diff --git a/3rdParty/velocypack/include/velocypack/Builder.h b/3rdParty/velocypack/include/velocypack/Builder.h index 60aca02810..6406e4d06a 100644 --- a/3rdParty/velocypack/include/velocypack/Builder.h +++ b/3rdParty/velocypack/include/velocypack/Builder.h @@ -114,15 +114,6 @@ class Builder { bool _keyWritten; // indicates that in the current object the key // has been written but the value not yet - // Sort the indices by attribute name: - static void doActualSort(std::vector& entries); - - // Find the actual bytes of the attribute name of the VPack value - // at position base, also determine the length len of the attribute. - // This takes into account the different possibilities for the format - // of attribute names: - static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len); - void sortObjectIndexShort(uint8_t* objBase, std::vector& offsets) const; @@ -130,7 +121,13 @@ class Builder { std::vector& offsets); void sortObjectIndex(uint8_t* objBase, - std::vector& offsets); + std::vector& offsets) { + if (offsets.size() > 32) { + sortObjectIndexLong(objBase, offsets); + } else { + sortObjectIndexShort(objBase, offsets); + } + } public: Options const* options; @@ -573,7 +570,7 @@ class Builder { private: inline void checkKeyIsString(bool isString) { if (!_stack.empty()) { - ValueLength const tos = _stack.back(); + ValueLength const& tos = _stack.back(); if (_start[tos] == 0x0b || _start[tos] == 0x14) { if (!_keyWritten && !isString) { throw Exception(Exception::BuilderKeyMustBeString); @@ -615,7 +612,7 @@ class Builder { uint8_t* addInternal(std::string const& attrName, T const& sub) { bool haveReported = false; if (!_stack.empty()) { - ValueLength& tos = _stack.back(); + ValueLength const& tos = _stack.back(); if (_start[tos] != 0x0b && _start[tos] != 0x14) { throw Exception(Exception::BuilderNeedOpenObject); } diff --git a/3rdParty/velocypack/include/velocypack/Slice.h b/3rdParty/velocypack/include/velocypack/Slice.h index 4c0e9cbaa8..206dbb7add 100644 --- a/3rdParty/velocypack/include/velocypack/Slice.h +++ b/3rdParty/velocypack/include/velocypack/Slice.h @@ -39,29 +39,10 @@ #include "velocypack/velocypack-common.h" #include "velocypack/Exception.h" #include "velocypack/Options.h" +#include "velocypack/StringRef.h" #include "velocypack/Value.h" #include "velocypack/ValueType.h" -#ifndef VELOCYPACK_XXHASH -#ifndef VELOCYPACK_FASTHASH -#define VELOCYPACK_XXHASH -#endif -#endif - -#ifdef VELOCYPACK_XXHASH -// forward for XXH64 function declared elsewhere -extern "C" unsigned long long XXH64(void const*, size_t, unsigned long long); - -#define VELOCYPACK_HASH(mem, size, seed) XXH64(mem, size, seed) -#endif - -#ifdef VELOCYPACK_FASTHASH -// forward for fasthash64 function declared elsewhere -uint64_t fasthash64(void const*, size_t, uint64_t); - -#define VELOCYPACK_HASH(mem, size, seed) fasthash64(mem, size, seed) -#endif - namespace arangodb { namespace velocypack { @@ -185,6 +166,13 @@ class Slice { return VELOCYPACK_HASH(start(), size, seed); } + // hashes the binary representation of a value, not using precalculated hash values + // this is mainly here for testing purposes + inline uint64_t hashSlow(uint64_t seed = defaultSeed) const { + size_t const size = checkOverflow(byteSize()); + return VELOCYPACK_HASH(start(), size, seed); + } + // hashes the value, normalizing different representations of // arrays, objects and numbers. this function may produce different // hash values than the binary hash() function @@ -447,7 +435,8 @@ class Slice { // look for the specified attribute path inside an Object // returns a Slice(ValueType::None) if not found - Slice get(std::vector const& attributes, + template + Slice get(std::vector const& attributes, bool resolveExternals = false) const { size_t const n = attributes.size(); if (n == 0) { @@ -476,48 +465,47 @@ class Slice { return last; } - // look for the specified attribute path inside an Object + // look for the specified attribute inside an Object // returns a Slice(ValueType::None) if not found - Slice get(std::vector const& attributes) const { - size_t const n = attributes.size(); - if (n == 0) { - throw Exception(Exception::InvalidAttributePath); - } + Slice get(StringRef const& attribute) const; - // use ourselves as the starting point - Slice last = Slice(start()); - for (size_t i = 0; i < attributes.size(); ++i) { - // fetch subattribute - last = last.get(attributes[i]); - - // abort as early as possible - if (last.isNone() || (i + 1 < n && !last.isObject())) { - return Slice(); - } - } - - return last; + Slice get(std::string const& attribute) const { + return get(StringRef(attribute.data(), attribute.size())); } - // look for the specified attribute inside an Object - // returns a Slice(ValueType::None) if not found - Slice get(std::string const& attribute) const; - - // look for the specified attribute inside an Object - // returns a Slice(ValueType::None) if not found Slice get(char const* attribute) const { - return get(std::string(attribute)); + return get(StringRef(attribute)); } - Slice operator[](std::string const& attribute) const { + Slice get(char const* attribute, size_t length) const { + return get(StringRef(attribute, length)); + } + + Slice operator[](StringRef const& attribute) const { return get(attribute); } + Slice operator[](std::string const& attribute) const { + return get(attribute.data(), attribute.size()); + } + // whether or not an Object has a specific key - bool hasKey(std::string const& attribute) const { + bool hasKey(StringRef const& attribute) const { return !get(attribute).isNone(); } + bool hasKey(std::string const& attribute) const { + return hasKey(StringRef(attribute)); + } + + bool hasKey(char const* attribute) const { + return hasKey(StringRef(attribute)); + } + + bool hasKey(char const* attribute, size_t length) const { + return hasKey(StringRef(attribute, length)); + } + // whether or not an Object has a specific sub-key bool hasKey(std::vector const& attributes) const { return !get(attributes).isNone(); @@ -705,6 +693,25 @@ class Slice { throw Exception(Exception::InvalidValueType, "Expecting type String"); } + + // return a copy of the value for a String object + StringRef stringRef() const { + uint8_t h = head(); + if (h >= 0x40 && h <= 0xbe) { + // short UTF-8 String + ValueLength length = h - 0x40; + return StringRef(reinterpret_cast(_start + 1), + static_cast(length)); + } + + if (h == 0xbf) { + ValueLength length = readIntegerFixed(_start + 1); + return StringRef(reinterpret_cast(_start + 1 + 8), + checkOverflow(length)); + } + + throw Exception(Exception::InvalidValueType, "Expecting type String"); + } // return the value for a Binary object uint8_t const* getBinary(ValueLength& length) const { @@ -879,15 +886,37 @@ class Slice { Slice makeKey() const; - int compareString(char const* value, size_t length) const; - int compareStringUnchecked(char const* value, size_t length) const noexcept; + int compareString(StringRef const& value) const; - inline int compareString(std::string const& attribute) const { - return compareString(attribute.data(), attribute.size()); + inline int compareString(std::string const& value) const { + return compareString(StringRef(value.data(), value.size())); + } + + int compareString(char const* value, size_t length) const { + return compareString(StringRef(value, length)); + } + + int compareStringUnchecked(StringRef const& value) const noexcept; + + int compareStringUnchecked(std::string const& value) const noexcept { + return compareStringUnchecked(StringRef(value.data(), value.size())); } - bool isEqualString(std::string const& attribute) const; - bool isEqualStringUnchecked(std::string const& attribute) const noexcept; + int compareStringUnchecked(char const* value, size_t length) const noexcept { + return compareStringUnchecked(StringRef(value, length)); + } + + bool isEqualString(StringRef const& attribute) const; + + bool isEqualString(std::string const& attribute) const { + return isEqualString(StringRef(attribute.data(), attribute.size())); + } + + bool isEqualStringUnchecked(StringRef const& attribute) const noexcept; + + bool isEqualStringUnchecked(std::string const& attribute) const noexcept { + return isEqualStringUnchecked(StringRef(attribute.data(), attribute.size())); + } // check if two Slices are equal on the binary level bool equals(Slice const& other) const { @@ -944,7 +973,7 @@ class Slice { // translates an integer key into a string, without checks Slice translateUnchecked() const; - Slice getFromCompactObject(std::string const& attribute) const; + Slice getFromCompactObject(StringRef const& attribute) const; // extract the nth member from an Array Slice getNth(ValueLength index) const; @@ -968,12 +997,12 @@ class Slice { } // perform a linear search for the specified attribute inside an Object - Slice searchObjectKeyLinear(std::string const& attribute, ValueLength ieBase, + Slice searchObjectKeyLinear(StringRef const& attribute, ValueLength ieBase, ValueLength offsetSize, ValueLength n) const; // perform a binary search for the specified attribute inside an Object template - Slice searchObjectKeyBinary(std::string const& attribute, ValueLength ieBase, ValueLength n) const; + Slice searchObjectKeyBinary(StringRef const& attribute, ValueLength ieBase, ValueLength n) const; // assert that the slice is of a specific type // can be used for debugging and removed in production diff --git a/3rdParty/velocypack/include/velocypack/StringRef.h b/3rdParty/velocypack/include/velocypack/StringRef.h index 0bbaa1a1d6..3b3df694b7 100644 --- a/3rdParty/velocypack/include/velocypack/StringRef.h +++ b/3rdParty/velocypack/include/velocypack/StringRef.h @@ -29,12 +29,15 @@ #include #include +#include +#include +#include #include "velocypack/velocypack-common.h" -#include "velocypack/Slice.h" namespace arangodb { namespace velocypack { +class Slice; class StringRef { public: @@ -44,19 +47,18 @@ class StringRef { /// @brief create a StringRef from an std::string explicit StringRef(std::string const& str) noexcept : StringRef(str.data(), str.size()) {} - /// @brief create a StringRef from a null-terminated C string - explicit StringRef(char const* data) noexcept : StringRef(data, strlen(data)) {} - - /// @brief create a StringRef from a VPack slice (must be of type String) - explicit StringRef(arangodb::velocypack::Slice const& slice) { - VELOCYPACK_ASSERT(slice.isString()); - arangodb::velocypack::ValueLength l; - _data = slice.getString(l); - _length = l; - } - /// @brief create a StringRef from a C string plus length - StringRef(char const* data, size_t length) noexcept : _data(data), _length(length) {} + constexpr StringRef(char const* data, size_t length) noexcept : _data(data), _length(length) {} + + /// @brief create a StringRef from a null-terminated C string +#if __cplusplus >= 201703 + constexpr explicit StringRef(char const* data) noexcept : StringRef(data, std::char_traits::length(data)) {} +#else + explicit StringRef(char const* data) noexcept : StringRef(data, strlen(data)) {} +#endif + + /// @brief create a StringRef from a VPack slice (must be of type String) + explicit StringRef(arangodb::velocypack::Slice const& slice); /// @brief create a StringRef from another StringRef StringRef(StringRef const& other) noexcept @@ -95,12 +97,7 @@ class StringRef { } /// @brief create a StringRef from a VPack slice of type String - StringRef& operator=(arangodb::velocypack::Slice const& slice) { - arangodb::velocypack::ValueLength l; - _data = slice.getString(l); - _length = l; - return *this; - } + StringRef& operator=(arangodb::velocypack::Slice const& slice); int compare(std::string const& other) const noexcept { int res = memcmp(_data, other.data(), (std::min)(_length, other.size())); @@ -126,17 +123,17 @@ class StringRef { return (_length == 0); } - inline char const* begin() const { + inline char const* begin() const noexcept { return _data; } - inline char const* end() const { + inline char const* end() const noexcept { return _data + _length; } - inline char front() const { return _data[0]; } + inline char front() const noexcept { return _data[0]; } - inline char back() const { return _data[_length - 1]; } + inline char back() const noexcept { return _data[_length - 1]; } inline char operator[](size_t index) const noexcept { return _data[index]; diff --git a/3rdParty/velocypack/include/velocypack/velocypack-common.h b/3rdParty/velocypack/include/velocypack/velocypack-common.h index dd12c373aa..b424abd378 100644 --- a/3rdParty/velocypack/include/velocypack/velocypack-common.h +++ b/3rdParty/velocypack/include/velocypack/velocypack-common.h @@ -30,6 +30,7 @@ #include // for size_t: #include +#include #if defined(__GNUC__) || defined(__GNUG__) #define VELOCYPACK_LIKELY(v) __builtin_expect(!!(v), 1) @@ -77,6 +78,26 @@ #define VELOCYPACK_UNUSED /* unused */ #endif +#ifndef VELOCYPACK_XXHASH +#ifndef VELOCYPACK_FASTHASH +#define VELOCYPACK_XXHASH +#endif +#endif + +#ifdef VELOCYPACK_XXHASH +// forward for XXH64 function declared elsewhere +extern "C" unsigned long long XXH64(void const*, size_t, unsigned long long); + +#define VELOCYPACK_HASH(mem, size, seed) XXH64(mem, size, seed) +#endif + +#ifdef VELOCYPACK_FASTHASH +// forward for fasthash64 function declared elsewhere +uint64_t fasthash64(void const*, size_t, uint64_t); + +#define VELOCYPACK_HASH(mem, size, seed) fasthash64(mem, size, seed) +#endif + namespace arangodb { namespace velocypack { @@ -177,10 +198,12 @@ static inline int64_t toInt64(uint64_t v) noexcept { // specified length, starting at the specified byte offset template static inline T readIntegerFixed(uint8_t const* start) noexcept { + static_assert(std::is_unsigned::value, "result type must be unsigned"); static_assert(length > 0, "length must be > 0"); + static_assert(length <= sizeof(T), "length must be <= sizeof(T)"); uint64_t x = 8; uint8_t const* end = start + length; - uint64_t value = static_cast(*start++); + T value = static_cast(*start++); while (start < end) { value += static_cast(*start++) << x; x += 8; @@ -189,13 +212,15 @@ static inline T readIntegerFixed(uint8_t const* start) noexcept { } // read an unsigned little endian integer value of the -// specified length, starting at the specified byte offset +// specified, non-0 length, starting at the specified byte offset template static inline T readIntegerNonEmpty(uint8_t const* start, ValueLength length) noexcept { + static_assert(std::is_unsigned::value, "result type must be unsigned"); VELOCYPACK_ASSERT(length > 0); + VELOCYPACK_ASSERT(length <= sizeof(T)); uint64_t x = 8; uint8_t const* end = start + length; - uint64_t value = static_cast(*start++); + T value = static_cast(*start++); while (start < end) { value += static_cast(*start++) << x; x += 8; diff --git a/3rdParty/velocypack/include/velocypack/velocypack-version-number.h b/3rdParty/velocypack/include/velocypack/velocypack-version-number.h index d61d6a7c57..2ffe7c7a88 100644 --- a/3rdParty/velocypack/include/velocypack/velocypack-version-number.h +++ b/3rdParty/velocypack/include/velocypack/velocypack-version-number.h @@ -3,10 +3,10 @@ #ifndef VELOCYPACK_VERSION_NUMBER_H #define VELOCYPACK_VERSION_NUMBER_H 1 -#define VELOCYPACK_VERSION "0.1.31" +#define VELOCYPACK_VERSION "0.1.32" #define VELOCYPACK_VERSION_MAJOR 0 #define VELOCYPACK_VERSION_MINOR 1 -#define VELOCYPACK_VERSION_PATCH 31 +#define VELOCYPACK_VERSION_PATCH 32 #endif diff --git a/3rdParty/velocypack/src/Builder.cpp b/3rdParty/velocypack/src/Builder.cpp index b02830dc9f..6ac1664f13 100644 --- a/3rdParty/velocypack/src/Builder.cpp +++ b/3rdParty/velocypack/src/Builder.cpp @@ -34,6 +34,76 @@ #include "velocypack/StringRef.h" using namespace arangodb::velocypack; + +namespace { +// Find the actual bytes of the attribute name of the VPack value +// at position base, also determine the length len of the attribute. +// This takes into account the different possibilities for the format +// of attribute names: +static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len) { + uint8_t const b = *base; + if (b >= 0x40 && b <= 0xbe) { + // short UTF-8 string + len = b - 0x40; + return base + 1; + } + if (b == 0xbf) { + // long UTF-8 string + len = 0; + // read string length + for (size_t i = 8; i >= 1; i--) { + len = (len << 8) + base[i]; + } + return base + 1 + 8; // string starts here + } + + // translate attribute name + return findAttrName(arangodb::velocypack::Slice(base).makeKey().start(), len); +} + +struct ObjectIndexSorterShort { + explicit ObjectIndexSorterShort(uint8_t const* objBase) : objBase(objBase) {} + + bool operator()(arangodb::velocypack::ValueLength const& a, + arangodb::velocypack::ValueLength const& b) const { + uint8_t const* aa = objBase + a; + uint8_t const* bb = objBase + b; + if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) { + // The fast path, short strings: + uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40); + int c = memcmp(aa + 1, bb + 1, arangodb::velocypack::checkOverflow(m)); + return (c < 0 || (c == 0 && *aa < *bb)); + } else { + uint64_t lena; + uint64_t lenb; + aa = findAttrName(aa, lena); + bb = findAttrName(bb, lenb); + uint64_t m = (std::min)(lena, lenb); + int c = memcmp(aa, bb, arangodb::velocypack::checkOverflow(m)); + return (c < 0 || (c == 0 && lena < lenb)); + } + } + + uint8_t const* objBase; +}; + +struct ObjectIndexSorterLong { + bool operator()(arangodb::velocypack::Builder::SortEntry const& a, + arangodb::velocypack::Builder::SortEntry const& b) const { + // return true iff a < b: + uint8_t const* pa = a.nameStart; + uint64_t sizea = a.nameSize; + uint8_t const* pb = b.nameStart; + uint64_t sizeb = b.nameSize; + size_t const compareLength = arangodb::velocypack::checkOverflow((std::min)(sizea, sizeb)); + int res = memcmp(pa, pb, compareLength); + + return (res < 0 || (res == 0 && sizea < sizeb)); + } +}; + +} // namespace + std::string Builder::toString() const { Options options; @@ -52,63 +122,9 @@ std::string Builder::toJson() const { return buffer; } -void Builder::doActualSort(std::vector& entries) { - VELOCYPACK_ASSERT(entries.size() > 1); - std::sort(entries.begin(), entries.end(), - [](SortEntry const& a, SortEntry const& b) { - // return true iff a < b: - uint8_t const* pa = a.nameStart; - uint64_t sizea = a.nameSize; - uint8_t const* pb = b.nameStart; - uint64_t sizeb = b.nameSize; - size_t const compareLength = checkOverflow((std::min)(sizea, sizeb)); - int res = memcmp(pa, pb, compareLength); - - return (res < 0 || (res == 0 && sizea < sizeb)); - }); -}; - -uint8_t const* Builder::findAttrName(uint8_t const* base, uint64_t& len) { - uint8_t const b = *base; - if (b >= 0x40 && b <= 0xbe) { - // short UTF-8 string - len = b - 0x40; - return base + 1; - } - if (b == 0xbf) { - // long UTF-8 string - len = 0; - // read string length - for (size_t i = 8; i >= 1; i--) { - len = (len << 8) + base[i]; - } - return base + 1 + 8; // string starts here - } - - // translate attribute name - return findAttrName(Slice(base).makeKey().start(), len); -} - void Builder::sortObjectIndexShort(uint8_t* objBase, std::vector& offsets) const { - std::sort(offsets.begin(), offsets.end(), [&objBase](ValueLength a, ValueLength b) -> bool { - uint8_t const* aa = objBase + a; - uint8_t const* bb = objBase + b; - if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) { - // The fast path, short strings: - uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40); - int c = memcmp(aa + 1, bb + 1, checkOverflow(m)); - return (c < 0 || (c == 0 && *aa < *bb)); - } else { - uint64_t lena; - uint64_t lenb; - aa = findAttrName(aa, lena); - bb = findAttrName(bb, lenb); - uint64_t m = (std::min)(lena, lenb); - int c = memcmp(aa, bb, checkOverflow(m)); - return (c < 0 || (c == 0 && lena < lenb)); - } - }); + std::sort(offsets.begin(), offsets.end(), ::ObjectIndexSorterShort(objBase)); } void Builder::sortObjectIndexLong(uint8_t* objBase, @@ -116,15 +132,16 @@ void Builder::sortObjectIndexLong(uint8_t* objBase, _sortEntries.clear(); size_t const n = offsets.size(); + VELOCYPACK_ASSERT(n > 1); _sortEntries.reserve(n); for (size_t i = 0; i < n; i++) { SortEntry e; e.offset = offsets[i]; - e.nameStart = findAttrName(objBase + e.offset, e.nameSize); + e.nameStart = ::findAttrName(objBase + e.offset, e.nameSize); _sortEntries.push_back(e); } VELOCYPACK_ASSERT(_sortEntries.size() == n); - doActualSort(_sortEntries); + std::sort(_sortEntries.begin(), _sortEntries.end(), ::ObjectIndexSorterLong()); // copy back the sorted offsets for (size_t i = 0; i < n; i++) { @@ -133,15 +150,6 @@ void Builder::sortObjectIndexLong(uint8_t* objBase, _sortEntries.clear(); } -void Builder::sortObjectIndex(uint8_t* objBase, - std::vector& offsets) { - if (offsets.size() > 32) { - sortObjectIndexLong(objBase, offsets); - } else { - sortObjectIndexShort(objBase, offsets); - } -} - void Builder::removeLast() { if (_stack.empty()) { throw Exception(Exception::BuilderNeedOpenCompound); diff --git a/3rdParty/velocypack/src/Slice.cpp b/3rdParty/velocypack/src/Slice.cpp index c65f57fda5..58d1665381 100644 --- a/3rdParty/velocypack/src/Slice.cpp +++ b/3rdParty/velocypack/src/Slice.cpp @@ -746,7 +746,7 @@ uint64_t Slice::normalizedHash(uint64_t seed) const { // look for the specified attribute inside an Object // returns a Slice(ValueType::None) if not found -Slice Slice::get(std::string const& attribute) const { +Slice Slice::get(StringRef const& attribute) const { if (VELOCYPACK_UNLIKELY(!isObject())) { throw Exception(Exception::InvalidValueType, "Expecting Object"); } @@ -934,12 +934,13 @@ int64_t Slice::getSmallInt() const { throw Exception(Exception::InvalidValueType, "Expecting type SmallInt"); } -int Slice::compareString(char const* value, size_t length) const { +int Slice::compareString(StringRef const& value) const { + size_t const length = value.size(); ValueLength keyLength; char const* k = getString(keyLength); size_t const compareLength = - (std::min)(static_cast(keyLength), length); - int res = memcmp(k, value, compareLength); + (std::min)(checkOverflow(keyLength), length); + int res = memcmp(k, value.data(), compareLength); if (res == 0) { if (keyLength != length) { @@ -949,12 +950,13 @@ int Slice::compareString(char const* value, size_t length) const { return res; } -int Slice::compareStringUnchecked(char const* value, size_t length) const noexcept { +int Slice::compareStringUnchecked(StringRef const& value) const noexcept { + size_t const length = value.size(); ValueLength keyLength; char const* k = getStringUnchecked(keyLength); size_t const compareLength = (std::min)(static_cast(keyLength), length); - int res = memcmp(k, value, compareLength); + int res = memcmp(k, value.data(), compareLength); if (res == 0) { if (keyLength != length) { @@ -964,7 +966,7 @@ int Slice::compareStringUnchecked(char const* value, size_t length) const noexce return res; } -bool Slice::isEqualString(std::string const& attribute) const { +bool Slice::isEqualString(StringRef const& attribute) const { ValueLength keyLength; char const* k = getString(keyLength); if (static_cast(keyLength) != attribute.size()) { @@ -973,7 +975,7 @@ bool Slice::isEqualString(std::string const& attribute) const { return (memcmp(k, attribute.data(), attribute.size()) == 0); } -bool Slice::isEqualStringUnchecked(std::string const& attribute) const noexcept { +bool Slice::isEqualStringUnchecked(StringRef const& attribute) const noexcept { ValueLength keyLength; char const* k = getStringUnchecked(keyLength); if (static_cast(keyLength) != attribute.size()) { @@ -982,7 +984,7 @@ bool Slice::isEqualStringUnchecked(std::string const& attribute) const noexcept return (memcmp(k, attribute.data(), attribute.size()) == 0); } -Slice Slice::getFromCompactObject(std::string const& attribute) const { +Slice Slice::getFromCompactObject(StringRef const& attribute) const { ObjectIterator it(*this); while (it.valid()) { Slice key = it.key(false); @@ -1116,7 +1118,7 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const { } // perform a linear search for the specified attribute inside an Object -Slice Slice::searchObjectKeyLinear(std::string const& attribute, +Slice Slice::searchObjectKeyLinear(StringRef const& attribute, ValueLength ieBase, ValueLength offsetSize, ValueLength n) const { bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr); @@ -1128,7 +1130,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute, if (key.isString()) { if (!key.isEqualStringUnchecked(attribute)) { continue; - } + } } else if (key.isSmallInt() || key.isUInt()) { // translate key if (!useTranslator) { @@ -1153,7 +1155,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute, // perform a binary search for the specified attribute inside an Object template -Slice Slice::searchObjectKeyBinary(std::string const& attribute, +Slice Slice::searchObjectKeyBinary(StringRef const& attribute, ValueLength ieBase, ValueLength n) const { bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr); @@ -1205,10 +1207,10 @@ Slice Slice::searchObjectKeyBinary(std::string const& attribute, } // template instanciations for searchObjectKeyBinary -template Slice Slice::searchObjectKeyBinary<1>(std::string const& attribute, ValueLength ieBase, ValueLength n) const; -template Slice Slice::searchObjectKeyBinary<2>(std::string const& attribute, ValueLength ieBase, ValueLength n) const; -template Slice Slice::searchObjectKeyBinary<4>(std::string const& attribute, ValueLength ieBase, ValueLength n) const; -template Slice Slice::searchObjectKeyBinary<8>(std::string const& attribute, ValueLength ieBase, ValueLength n) const; +template Slice Slice::searchObjectKeyBinary<1>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const; +template Slice Slice::searchObjectKeyBinary<2>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const; +template Slice Slice::searchObjectKeyBinary<4>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const; +template Slice Slice::searchObjectKeyBinary<8>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const; SliceScope::SliceScope() : _allocations() {} diff --git a/3rdParty/velocypack/src/StringRef.cpp b/3rdParty/velocypack/src/StringRef.cpp new file mode 100644 index 0000000000..00c2c278af --- /dev/null +++ b/3rdParty/velocypack/src/StringRef.cpp @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @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/StringRef.h" +#include "velocypack/Slice.h" + +using namespace arangodb::velocypack; + +StringRef::StringRef(arangodb::velocypack::Slice const& slice) { + VELOCYPACK_ASSERT(slice.isString()); + arangodb::velocypack::ValueLength l; + _data = slice.getString(l); + _length = l; +} + +/// @brief create a StringRef from a VPack slice of type String +StringRef& StringRef::operator=(arangodb::velocypack::Slice const& slice) { + arangodb::velocypack::ValueLength l; + _data = slice.getString(l); + _length = l; + return *this; +} diff --git a/arangod/Agency/ActiveFailoverJob.cpp b/arangod/Agency/ActiveFailoverJob.cpp index be4ae43cfa..7b9298fb1f 100644 --- a/arangod/Agency/ActiveFailoverJob.cpp +++ b/arangod/Agency/ActiveFailoverJob.cpp @@ -279,7 +279,7 @@ std::string ActiveFailoverJob::findBestFollower() { return ""; } - VPackSlice obj = resp.at(0).get({ Job::agencyPrefix, "AsyncReplication"}); + VPackSlice obj = resp.at(0).get({ Job::agencyPrefix, std::string("AsyncReplication")}); for (VPackObjectIterator::ObjectPair pair : VPackObjectIterator(obj)) { std::string srvUUID = pair.key.copyString(); bool isAvailable = std::find(healthy.begin(), healthy.end(), srvUUID) != healthy.end(); diff --git a/arangod/Cluster/ClusterInfo.cpp b/arangod/Cluster/ClusterInfo.cpp index 319274330a..9bae7ad8de 100644 --- a/arangod/Cluster/ClusterInfo.cpp +++ b/arangod/Cluster/ClusterInfo.cpp @@ -2257,7 +2257,7 @@ Result ClusterInfo::setViewPropertiesCoordinator( return { TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND }; } - auto const view = res.slice()[0].get( + auto const view = res.slice()[0].get( { AgencyCommManager::path(), "Plan", "Views", databaseName, viewID } ); diff --git a/arangod/Cluster/HeartbeatThread.cpp b/arangod/Cluster/HeartbeatThread.cpp index 4569cb95f0..7296fb434c 100644 --- a/arangod/Cluster/HeartbeatThread.cpp +++ b/arangod/Cluster/HeartbeatThread.cpp @@ -614,14 +614,14 @@ void HeartbeatThread::runSingleServer() { VPackSlice agentPool = response.get(".agency"); updateAgentPool(agentPool); - VPackSlice shutdownSlice = response.get({AgencyCommManager::path(), "Shutdown"}); + VPackSlice shutdownSlice = response.get({AgencyCommManager::path(), "Shutdown"}); if (shutdownSlice.isBool() && shutdownSlice.getBool()) { ApplicationServer::server->beginShutdown(); break; } // performing failover checks - VPackSlice async = response.get({AgencyCommManager::path(), "Plan", "AsyncReplication"}); + VPackSlice async = response.get({AgencyCommManager::path(), "Plan", "AsyncReplication"}); if (!async.isObject()) { LOG_TOPIC(WARN, Logger::HEARTBEAT) << "Heartbeat: Could not read async-replication metadata from agency!"; diff --git a/arangod/VocBase/Methods/Databases.cpp b/arangod/VocBase/Methods/Databases.cpp index bc06c5dd44..b21cc40f21 100644 --- a/arangod/VocBase/Methods/Databases.cpp +++ b/arangod/VocBase/Methods/Databases.cpp @@ -91,7 +91,7 @@ arangodb::Result Databases::info(TRI_vocbase_t* vocbase, VPackBuilder& result) { return Result(commRes.errorCode(), commRes.errorMessage()); } - VPackSlice value = commRes.slice()[0].get( + VPackSlice value = commRes.slice()[0].get( {AgencyCommManager::path(), "Plan", "Databases", vocbase->name()}); if (value.isObject() && value.hasKey("name")) { VPackValueLength l = 0; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 7e67664bcc..7aaaac51bc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -75,6 +75,7 @@ set(LIB_ARANGO_VPACK ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Options.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Parser.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Slice.cpp + ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/StringRef.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Utf8Helper.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/ValueType.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Validator.cpp diff --git a/tests/IResearch/common.cpp b/tests/IResearch/common.cpp index 426cd67d0d..06bb9e45e1 100644 --- a/tests/IResearch/common.cpp +++ b/tests/IResearch/common.cpp @@ -261,7 +261,7 @@ std::unique_ptr planFromQuery( uint64_t getCurrentPlanVersion() { auto const result = arangodb::AgencyComm().getValues("Plan"); - auto const planVersionSlice = result.slice()[0].get( + auto const planVersionSlice = result.slice()[0].get( { arangodb::AgencyCommManager::path(), "Plan", "Version" } ); return planVersionSlice.getNumber(); @@ -574,4 +574,4 @@ void assertFilterParseFail( // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE -// ----------------------------------------------------------------------------- \ No newline at end of file +// -----------------------------------------------------------------------------