From 9c3fd26682cca5fa2acd1f032d30eaf12ad8abf7 Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 8 May 2019 16:34:20 +0200 Subject: [PATCH] upgrade velocypack library (#8926) --- .../include/velocypack/AttributeTranslator.h | 23 +- .../velocypack/include/velocypack/Basics.h | 1 - .../velocypack/include/velocypack/Buffer.h | 19 +- .../velocypack/include/velocypack/Builder.h | 171 ++----------- .../velocypack/include/velocypack/Dumper.h | 4 +- .../velocypack/include/velocypack/Exception.h | 12 +- .../velocypack/include/velocypack/Iterator.h | 48 +--- .../velocypack/include/velocypack/Options.h | 19 +- .../velocypack/include/velocypack/Parser.h | 14 +- .../velocypack/include/velocypack/Slice.h | 43 ++-- .../velocypack/include/velocypack/StringRef.h | 63 ++--- .../velocypack/include/velocypack/Validator.h | 30 +-- .../velocypack/include/velocypack/Value.h | 14 +- .../velocypack/include/velocypack/ValueType.h | 2 +- .../include/velocypack/velocypack-aliases.h | 6 +- .../include/velocypack/velocypack-common.h | 4 +- .../velocypack/src/AttributeTranslator.cpp | 16 ++ 3rdParty/velocypack/src/Builder.cpp | 231 +++++++++++++----- 3rdParty/velocypack/src/Collection.cpp | 17 +- 3rdParty/velocypack/src/Dumper.cpp | 10 +- 3rdParty/velocypack/src/Options.cpp | 9 + 3rdParty/velocypack/src/Parser.cpp | 10 +- 3rdParty/velocypack/src/Slice.cpp | 36 ++- 3rdParty/velocypack/src/StringRef.cpp | 48 +++- 3rdParty/velocypack/src/Validator.cpp | 33 ++- 3rdParty/velocypack/src/Value.cpp | 43 ++++ 3rdParty/velocypack/src/asm-functions.cpp | 107 ++++---- 3rdParty/velocypack/src/asm-functions.h | 8 +- 3rdParty/velocypack/src/asm-utf8check.cpp | 12 +- 3rdParty/velocypack/src/asm-utf8check.h | 6 +- arangod/Cluster/ClusterTrxMethods.cpp | 15 +- lib/CMakeLists.txt | 1 + 32 files changed, 540 insertions(+), 535 deletions(-) create mode 100644 3rdParty/velocypack/src/Value.cpp diff --git a/3rdParty/velocypack/include/velocypack/AttributeTranslator.h b/3rdParty/velocypack/include/velocypack/AttributeTranslator.h index cd50202c77..44e24c79aa 100644 --- a/3rdParty/velocypack/include/velocypack/AttributeTranslator.h +++ b/3rdParty/velocypack/include/velocypack/AttributeTranslator.h @@ -28,13 +28,11 @@ #define VELOCYPACK_ATTRIBUTETRANSLATOR_H 1 #include +#include #include #include -#include #include "velocypack/velocypack-common.h" -#include "velocypack/Options.h" -#include "velocypack/Slice.h" #include "velocypack/StringRef.h" namespace arangodb { @@ -50,7 +48,7 @@ class AttributeTranslator { ~AttributeTranslator(); - size_t count() const { return _count; } + std::size_t count() const { return _count; } void add(std::string const& key, uint64_t id); @@ -94,7 +92,7 @@ class AttributeTranslator { std::unique_ptr _builder; std::unordered_map _keyToId; std::unordered_map _idToKey; - size_t _count; + std::size_t _count; }; class AttributeTranslatorScope { @@ -103,19 +101,10 @@ class AttributeTranslatorScope { AttributeTranslatorScope& operator= (AttributeTranslatorScope const&) = delete; public: - explicit AttributeTranslatorScope(AttributeTranslator* translator) - : _old(Options::Defaults.attributeTranslator) { - Options::Defaults.attributeTranslator = translator; - } + explicit AttributeTranslatorScope(AttributeTranslator* translator); + ~AttributeTranslatorScope(); - ~AttributeTranslatorScope() { - revert(); - } - - // prematurely revert the change - void revert() { - Options::Defaults.attributeTranslator = _old; - } + void revert() noexcept; private: AttributeTranslator* _old; diff --git a/3rdParty/velocypack/include/velocypack/Basics.h b/3rdParty/velocypack/include/velocypack/Basics.h index 5bf057acc9..5fe650cc5b 100644 --- a/3rdParty/velocypack/include/velocypack/Basics.h +++ b/3rdParty/velocypack/include/velocypack/Basics.h @@ -27,7 +27,6 @@ #ifndef VELOCYPACK_BASICS_H #define VELOCYPACK_BASICS_H 1 -#include #include namespace arangodb { diff --git a/3rdParty/velocypack/include/velocypack/Buffer.h b/3rdParty/velocypack/include/velocypack/Buffer.h index b30a5d844e..2443a5fd47 100644 --- a/3rdParty/velocypack/include/velocypack/Buffer.h +++ b/3rdParty/velocypack/include/velocypack/Buffer.h @@ -90,7 +90,7 @@ class Buffer { Buffer(Buffer&& that) noexcept : _buffer(_local), _capacity(sizeof(_local)) { if (that._buffer == that._local) { - memcpy(_buffer, that._buffer, static_cast(that._size)); + memcpy(_buffer, that._buffer, static_cast(that._size)); } else { _buffer = that._buffer; _capacity = that._capacity; @@ -104,7 +104,7 @@ class Buffer { Buffer& operator=(Buffer&& that) noexcept { if (this != &that) { if (that._buffer == that._local) { - memcpy(_buffer, that._buffer, static_cast(that._size)); + memcpy(_buffer, that._buffer, static_cast(that._size)); } else { if (_buffer != _local) { delete[] _buffer; @@ -158,14 +158,14 @@ class Buffer { } // move internal buffer position n bytes ahead - inline void advance(size_t value) noexcept { + inline void advance(std::size_t value) noexcept { VELOCYPACK_ASSERT(_size <= _capacity); VELOCYPACK_ASSERT(_size + value <= _capacity); _size += value; } // move internal buffer position n bytes backward - inline void rollback(size_t value) noexcept { + inline void rollback(std::size_t value) noexcept { VELOCYPACK_ASSERT(_size <= _capacity); VELOCYPACK_ASSERT(_size >= value); _size -= value; @@ -182,22 +182,22 @@ class Buffer { initWithNone(); } - inline T& operator[](size_t position) noexcept { + inline T& operator[](std::size_t position) noexcept { return _buffer[position]; } - inline T const& operator[](size_t position) const noexcept { + inline T const& operator[](std::size_t position) const noexcept { return _buffer[position]; } - inline T& at(size_t position) { + inline T& at(std::size_t position) { if (position >= _size) { throw Exception(Exception::IndexOutOfBounds); } return operator[](position); } - inline T const& at(size_t position) const { + inline T const& at(std::size_t position) const { if (position >= _size) { throw Exception(Exception::IndexOutOfBounds); } @@ -290,8 +290,7 @@ typedef Buffer CharBuffer; template struct BufferNonDeleter { - void operator()(Buffer*) { - } + void operator()(Buffer*) {} }; } // namespace arangodb::velocypack diff --git a/3rdParty/velocypack/include/velocypack/Builder.h b/3rdParty/velocypack/include/velocypack/Builder.h index d7e1b28183..6eb080a525 100644 --- a/3rdParty/velocypack/include/velocypack/Builder.h +++ b/3rdParty/velocypack/include/velocypack/Builder.h @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #ifndef VELOCYPACK_BUILDER_H -#define VELOCYPACK_BUILDER_H +#define VELOCYPACK_BUILDER_H 1 #include #include @@ -100,131 +100,20 @@ class Builder { Options const* options; // create an empty Builder, using default Options - Builder() - : _buffer(std::make_shared>()), - _bufferPtr(_buffer.get()), - _start(_bufferPtr->data()), - _pos(0), - _keyWritten(false), - options(&Options::Defaults) {} - - // create an empty Builder, with custom Options - explicit Builder(Options const* options) - : _buffer(std::make_shared>()), - _bufferPtr(_buffer.get()), - _start(_bufferPtr->data()), - _pos(0), - _keyWritten(false), - options(options) { - if (VELOCYPACK_UNLIKELY(options == nullptr)) { - throw Exception(Exception::InternalError, "Options cannot be a nullptr"); - } - } + Builder(); + explicit Builder(Options const* options); explicit Builder(std::shared_ptr> const& buffer, - Options const* options = &Options::Defaults) - : _buffer(buffer), - _bufferPtr(_buffer.get()), - _pos(0), - _keyWritten(false), - options(options) { - if (VELOCYPACK_UNLIKELY(_bufferPtr == nullptr)) { - throw Exception(Exception::InternalError, "Buffer cannot be a nullptr"); - } - _start = _bufferPtr->data(); - - if (VELOCYPACK_UNLIKELY(options == nullptr)) { - throw Exception(Exception::InternalError, "Options cannot be a nullptr"); - } - } - + Options const* options = &Options::Defaults); explicit Builder(Buffer& buffer, - Options const* options = &Options::Defaults) - : _bufferPtr(nullptr), - _pos(buffer.size()), - _keyWritten(false), - options(options) { - _buffer.reset(&buffer, BufferNonDeleter()); - _bufferPtr = _buffer.get(); - _start = _bufferPtr->data(); + Options const* options = &Options::Defaults); + explicit Builder(Slice slice, Options const* options = &Options::Defaults); + ~Builder() = default; - if (VELOCYPACK_UNLIKELY(options == nullptr)) { - throw Exception(Exception::InternalError, "Options cannot be a nullptr"); - } - } - - explicit Builder(Slice slice, Options const* options = &Options::Defaults) - : Builder(options) { - add(slice); - } - - ~Builder() {} - - Builder(Builder const& that) - : _buffer(std::make_shared>(*that._buffer)), - _bufferPtr(_buffer.get()), - _start(_bufferPtr->data()), - _pos(that._pos), - _stack(that._stack), - _index(that._index), - _keyWritten(that._keyWritten), - options(that.options) { - VELOCYPACK_ASSERT(options != nullptr); - } - - Builder& operator=(Builder const& that) { - if (this != &that) { - _buffer = std::make_shared>(*that._buffer); - _bufferPtr = _buffer.get(); - _start = _bufferPtr->data(); - _pos = that._pos; - _stack = that._stack; - _index = that._index; - _keyWritten = that._keyWritten; - options = that.options; - } - VELOCYPACK_ASSERT(options != nullptr); - return *this; - } - - Builder(Builder&& that) { - if (!that.isClosed()) { - throw Exception(Exception::InternalError, "Cannot move an open Builder"); - } - _buffer = that._buffer; - _bufferPtr = _buffer.get(); - _start = _bufferPtr->data(); - _pos = that._pos; - _stack.clear(); - _stack.swap(that._stack); - _index.clear(); - _index.swap(that._index); - _keyWritten = that._keyWritten; - options = that.options; - that._pos = 0; - that._keyWritten = false; - } - - Builder& operator=(Builder&& that) { - if (!that.isClosed()) { - throw Exception(Exception::InternalError, "Cannot move an open Builder"); - } - if (this != &that) { - _buffer = that._buffer; - _bufferPtr = _buffer.get(); - _start = _bufferPtr->data(); - _pos = that._pos; - _stack.clear(); - _stack.swap(that._stack); - _index.clear(); - _index.swap(that._index); - _keyWritten = that._keyWritten; - options = that.options; - that._pos = 0; - that._keyWritten = false; - } - return *this; - } + Builder(Builder const& that); + Builder& operator=(Builder const& that); + Builder(Builder&& that); + Builder& operator=(Builder&& that); // get a const reference to the Builder's Buffer object std::shared_ptr> const& buffer() const { return _buffer; } @@ -338,7 +227,7 @@ class Builder { } template - uint8_t* addUnchecked(char const* attrName, size_t attrLength, T const& sub) { + uint8_t* addUnchecked(char const* attrName, std::size_t attrLength, T const& sub) { bool haveReported = false; if (!_stack.empty()) { reportAdd(); @@ -368,7 +257,7 @@ class Builder { inline uint8_t* add(char const* attrName, Value const& sub) { return addInternal(attrName, sub); } - inline uint8_t* add(char const* attrName, size_t attrLength, Value const& sub) { + inline uint8_t* add(char const* attrName, std::size_t attrLength, Value const& sub) { return addInternal(attrName, attrLength, sub); } @@ -382,7 +271,7 @@ class Builder { inline uint8_t* add(char const* attrName, Slice const& sub) { return addInternal(attrName, sub); } - inline uint8_t* add(char const* attrName, size_t attrLength, Slice const& sub) { + inline uint8_t* add(char const* attrName, std::size_t attrLength, Slice const& sub) { return addInternal(attrName, attrLength, sub); } @@ -396,7 +285,7 @@ class Builder { inline uint8_t* add(char const* attrName, ValuePair const& sub) { return addInternal(attrName, sub); } - inline uint8_t* add(char const* attrName, size_t attrLength, ValuePair const& sub) { + inline uint8_t* add(char const* attrName, std::size_t attrLength, ValuePair const& sub) { return addInternal(attrName, attrLength, sub); } @@ -450,21 +339,15 @@ class Builder { // Add all subkeys and subvalues into an object from an ObjectIterator // and leaves open the object intentionally - uint8_t* add(ObjectIterator& sub); - uint8_t* add(ObjectIterator&& sub); + uint8_t* add(ObjectIterator const& sub); // Add all subvalues into an array from an ArrayIterator // and leaves open the array intentionally - uint8_t* add(ArrayIterator& sub); - uint8_t* add(ArrayIterator&& sub); + uint8_t* add(ArrayIterator const& sub); // Seal the innermost array or object: Builder& close(); - // Remove last subvalue written to an (unclosed) object or array: - // Throws if an error occurs. - void removeLast(); - // whether or not a specific key is present in an Object value bool hasKey(std::string const& key) const; @@ -592,7 +475,7 @@ class Builder { if (!_stack.empty()) { ValueLength const& tos = _stack.back(); if (_start[tos] == 0x0b || _start[tos] == 0x14) { - if (!_keyWritten && !isString) { + if (VELOCYPACK_UNLIKELY(!_keyWritten && !isString)) { throw Exception(Exception::BuilderKeyMustBeString); } _keyWritten = !_keyWritten; @@ -604,7 +487,7 @@ class Builder { if (!_stack.empty()) { ValueLength const& tos = _stack.back(); if (_start[tos] == 0x0b || _start[tos] == 0x14) { - if (!_keyWritten && !item.isString()) { + if (VELOCYPACK_UNLIKELY(!_keyWritten && !item.isString())) { throw Exception(Exception::BuilderKeyMustBeString); } _keyWritten = !_keyWritten; @@ -656,11 +539,11 @@ class Builder { } template - uint8_t* addInternal(char const* attrName, size_t attrLength, T const& sub) { + uint8_t* addInternal(char const* attrName, std::size_t attrLength, T const& sub) { bool haveReported = false; if (!_stack.empty()) { ValueLength& tos = _stack.back(); - if (_start[tos] != 0x0b && _start[tos] != 0x14) { + if (VELOCYPACK_UNLIKELY(_start[tos] != 0x0b && _start[tos] != 0x14)) { throw Exception(Exception::BuilderNeedOpenObject); } if (VELOCYPACK_UNLIKELY(_keyWritten)) { @@ -718,7 +601,7 @@ class Builder { if (!_stack.empty()) { ValueLength& tos = _stack.back(); if (!_keyWritten) { - if (_start[tos] != 0x06 && _start[tos] != 0x13) { + if (VELOCYPACK_UNLIKELY(_start[tos] != 0x06 && _start[tos] != 0x13)) { throw Exception(Exception::BuilderNeedOpenArray); } reportAdd(); @@ -745,13 +628,13 @@ class Builder { uint8_t* set(Slice const& item); void cleanupAdd() noexcept { - size_t depth = _stack.size() - 1; + std::size_t depth = _stack.size() - 1; VELOCYPACK_ASSERT(!_index[depth].empty()); _index[depth].pop_back(); } inline void reportAdd() { - size_t depth = _stack.size() - 1; + std::size_t depth = _stack.size() - 1; _index[depth].push_back(_pos - _stack[depth]); } @@ -827,21 +710,21 @@ class Builder { _bufferPtr->advance(); } - inline void resetTo(size_t value) { + inline void resetTo(std::size_t value) { _pos = value; VELOCYPACK_ASSERT(_bufferPtr != nullptr); _bufferPtr->resetTo(value); } // move byte position x bytes ahead - inline void advance(size_t value) noexcept { + inline void advance(std::size_t value) noexcept { _pos += value; VELOCYPACK_ASSERT(_bufferPtr != nullptr); _bufferPtr->advance(value); } // move byte position x bytes back - inline void rollback(size_t value) noexcept { + inline void rollback(std::size_t value) noexcept { _pos -= value; VELOCYPACK_ASSERT(_bufferPtr != nullptr); _bufferPtr->rollback(value); diff --git a/3rdParty/velocypack/include/velocypack/Dumper.h b/3rdParty/velocypack/include/velocypack/Dumper.h index 83e4eaed72..6603bc0761 100644 --- a/3rdParty/velocypack/include/velocypack/Dumper.h +++ b/3rdParty/velocypack/include/velocypack/Dumper.h @@ -128,9 +128,9 @@ class Dumper { void dumpValue(Slice const*, Slice const* = nullptr); void indent() { - size_t n = _indentation; + std::size_t n = _indentation; _sink->reserve(2 * n); - for (size_t i = 0; i < n; ++i) { + for (std::size_t i = 0; i < n; ++i) { _sink->append(" ", 2); } } diff --git a/3rdParty/velocypack/include/velocypack/Exception.h b/3rdParty/velocypack/include/velocypack/Exception.h index 7bfa5fa36a..f51c42bb8e 100644 --- a/3rdParty/velocypack/include/velocypack/Exception.h +++ b/3rdParty/velocypack/include/velocypack/Exception.h @@ -36,7 +36,7 @@ namespace arangodb { namespace velocypack { // base exception class -struct Exception : std::exception { +class Exception : public virtual std::exception { public: enum ExceptionType { InternalError = 1, @@ -75,15 +75,17 @@ struct Exception : std::exception { }; private: - ExceptionType _type; + ExceptionType const _type; char const* _msg; public: - Exception(ExceptionType type, char const* msg) noexcept : _type(type), _msg(msg) {} + Exception(ExceptionType type, char const* msg) : _type(type), _msg(msg) {} - explicit Exception(ExceptionType type) noexcept : Exception(type, message(type)) {} + explicit Exception(ExceptionType type) : Exception(type, message(type)) {} - Exception(Exception const& other) noexcept : _type(other._type), _msg(other._msg) {} + Exception(Exception const& other) : _type(other._type), _msg(other._msg) {} + + ~Exception() = default; char const* what() const noexcept { return _msg; } diff --git a/3rdParty/velocypack/include/velocypack/Iterator.h b/3rdParty/velocypack/include/velocypack/Iterator.h index 3c7ef710ce..a8682f1aa7 100644 --- a/3rdParty/velocypack/include/velocypack/Iterator.h +++ b/3rdParty/velocypack/include/velocypack/Iterator.h @@ -28,7 +28,6 @@ #define VELOCYPACK_ITERATOR_H 1 #include -#include #include "velocypack/velocypack-common.h" #include "velocypack/Exception.h" @@ -47,7 +46,7 @@ class ArrayIterator { uint8_t const head = slice.head(); - if (slice.type(head) != ValueType::Array) { + if (VELOCYPACK_UNLIKELY(slice.type(head) != ValueType::Array)) { throw Exception(Exception::InvalidValueType, "Expecting Array slice"); } @@ -99,25 +98,13 @@ class ArrayIterator { // be performed by Slice::getNthOffset() return Slice(_slice.begin() + _slice.getNthOffset(_position)); } - - ArrayIterator begin() { - auto it = ArrayIterator(*this); - it._position = 0; - return it; - } - + ArrayIterator begin() const { auto it = ArrayIterator(*this); it._position = 0; return it; } - - ArrayIterator end() { - auto it = ArrayIterator(*this); - it._position = it._size; - return it; - } - + ArrayIterator end() const { auto it = ArrayIterator(*this); it._position = it._size; @@ -185,7 +172,7 @@ class ArrayIterator { class ObjectIterator { public: struct ObjectPair { - ObjectPair(Slice key, Slice value) : key(key), value(value) {} + ObjectPair(Slice key, Slice value) noexcept : key(key), value(value) {} Slice const key; Slice const value; }; @@ -196,12 +183,11 @@ class ObjectIterator { // simply jumps from key/value pair to key/value pair without using the // index. The default `false` is to use the index if it is there. explicit ObjectIterator(Slice slice, bool useSequentialIteration = false) - : _slice(slice), _size(0), _position(0), _current(nullptr), - _useSequentialIteration(useSequentialIteration) { + : _slice(slice), _size(0), _position(0), _current(nullptr) { uint8_t const head = slice.head(); - if (slice.type(head) != ValueType::Object) { + if (VELOCYPACK_UNLIKELY(slice.type(head) != ValueType::Object)) { throw Exception(Exception::InvalidValueType, "Expecting Object slice"); } @@ -250,30 +236,19 @@ class ObjectIterator { ObjectPair operator*() const { if (_current != nullptr) { - Slice key = Slice(_current); + Slice key(_current); return ObjectPair(key.makeKey(), Slice(_current + key.byteSize())); } - return ObjectPair(_slice.getNthKey(_position, true), _slice.getNthValue(_position)); + Slice key(_slice.getNthKeyUntranslated(_position)); + return ObjectPair(key.makeKey(), Slice(key.begin() + key.byteSize())); } - - ObjectIterator begin() { - auto it = ObjectIterator(*this); - it._position = 0; - return it; - } - + ObjectIterator begin() const { auto it = ObjectIterator(*this); it._position = 0; return it; } - ObjectIterator end() { - auto it = ObjectIterator(*this); - it._position = it._size; - return it; - } - ObjectIterator end() const { auto it = ObjectIterator(*this); it._position = it._size; @@ -298,7 +273,7 @@ class ObjectIterator { throw Exception(Exception::IndexOutOfBounds); } if (_current != nullptr) { - Slice key = Slice(_current); + Slice key(_current); return Slice(_current + key.byteSize()); } return _slice.getNthValue(_position); @@ -321,7 +296,6 @@ class ObjectIterator { ValueLength _size; ValueLength _position; uint8_t const* _current; - bool _useSequentialIteration; }; } // namespace arangodb::velocypack diff --git a/3rdParty/velocypack/include/velocypack/Options.h b/3rdParty/velocypack/include/velocypack/Options.h index d43e849699..00042fd723 100644 --- a/3rdParty/velocypack/include/velocypack/Options.h +++ b/3rdParty/velocypack/include/velocypack/Options.h @@ -28,10 +28,8 @@ #define VELOCYPACK_OPTIONS_H 1 #include -#include #include "velocypack/velocypack-common.h" -#include "velocypack/Exception.h" namespace arangodb { namespace velocypack { @@ -40,23 +38,10 @@ class Dumper; struct Options; class Slice; -struct AttributeExcludeHandler { - virtual ~AttributeExcludeHandler() {} - - virtual bool shouldExclude(Slice const& key, int nesting) = 0; -}; - struct CustomTypeHandler { virtual ~CustomTypeHandler() {} - - virtual void dump(Slice const&, Dumper*, Slice const&) { - throw Exception(Exception::NotImplemented); - } - - virtual std::string toString(Slice const&, Options const*, Slice const&) { - throw Exception(Exception::NotImplemented); - } - + virtual void dump(Slice const&, Dumper*, Slice const&); + virtual std::string toString(Slice const&, Options const*, Slice const&); }; struct Options { diff --git a/3rdParty/velocypack/include/velocypack/Parser.h b/3rdParty/velocypack/include/velocypack/Parser.h index 835646dc86..748f9e02cf 100644 --- a/3rdParty/velocypack/include/velocypack/Parser.h +++ b/3rdParty/velocypack/include/velocypack/Parser.h @@ -80,8 +80,8 @@ class Parser { std::shared_ptr _builder; Builder* _builderPtr; uint8_t const* _start; - size_t _size; - size_t _pos; + std::size_t _size; + std::size_t _pos; int _nesting; public: @@ -158,7 +158,7 @@ class Parser { } static std::shared_ptr fromJson( - char const* start, size_t size, + char const* start, std::size_t size, Options const* options = &Options::Defaults) { Parser parser(options); parser.parse(start, size); @@ -166,7 +166,7 @@ class Parser { } static std::shared_ptr fromJson( - uint8_t const* start, size_t size, + uint8_t const* start, std::size_t size, Options const* options = &Options::Defaults) { Parser parser(options); parser.parse(start, size); @@ -178,11 +178,11 @@ class Parser { multi); } - ValueLength parse(char const* start, size_t size, bool multi = false) { + ValueLength parse(char const* start, std::size_t size, bool multi = false) { return parse(reinterpret_cast(start), size, multi); } - ValueLength parse(uint8_t const* start, size_t size, bool multi = false) { + ValueLength parse(uint8_t const* start, std::size_t size, bool multi = false) { _start = start; _size = size; _pos = 0; @@ -209,7 +209,7 @@ class Parser { // Returns the position at the time when the just reported error // occurred, only use when handling an exception. - size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; } + std::size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; } void clear() { _builderPtr->clear(); } diff --git a/3rdParty/velocypack/include/velocypack/Slice.h b/3rdParty/velocypack/include/velocypack/Slice.h index cabbb2f897..bf1333a5c2 100644 --- a/3rdParty/velocypack/include/velocypack/Slice.h +++ b/3rdParty/velocypack/include/velocypack/Slice.h @@ -154,7 +154,7 @@ class Slice { // hashes the binary representation of a value inline uint64_t hash(uint64_t seed = defaultSeed) const { - size_t const size = checkOverflow(byteSize()); + std::size_t const size = checkOverflow(byteSize()); if (seed == defaultSeed && size == 1) { uint64_t h = SliceStaticData::PrecalculatedHashesForDefaultSeed[head()]; VELOCYPACK_ASSERT(h != 0); @@ -166,7 +166,7 @@ class Slice { // 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()); + std::size_t const size = checkOverflow(byteSize()); return VELOCYPACK_HASH(start(), size, seed); } @@ -178,7 +178,7 @@ class Slice { // hashes the binary representation of a String slice. No check // is done if the Slice value is actually of type String inline uint64_t hashString(uint64_t seed = defaultSeed) const noexcept { - return VELOCYPACK_HASH(start(), static_cast(stringSliceLength()), seed); + return VELOCYPACK_HASH(start(), static_cast(stringSliceLength()), seed); } // check if slice is of the specified type @@ -338,7 +338,7 @@ class Slice { // - 0x08 : array with 4-byte index table entries // - 0x09 : array with 8-byte index table entries Slice at(ValueLength index) const { - if (!isArray()) { + if (VELOCYPACK_UNLIKELY(!isArray())) { throw Exception(Exception::InvalidValueType, "Expecting type Array"); } @@ -349,7 +349,7 @@ class Slice { // return the number of members for an Array or Object object ValueLength length() const { - if (!isArray() && !isObject()) { + if (VELOCYPACK_UNLIKELY(!isArray() && !isObject())) { throw Exception(Exception::InvalidValueType, "Expecting type Array or Object"); } @@ -406,7 +406,7 @@ class Slice { // - 0x12 : object with 8-byte index table entries, not sorted by // attribute name Slice keyAt(ValueLength index, bool translate = true) const { - if (!isObject()) { + if (VELOCYPACK_UNLIKELY(!isObject())) { throw Exception(Exception::InvalidValueType, "Expecting type Object"); } @@ -414,7 +414,7 @@ class Slice { } Slice valueAt(ValueLength index) const { - if (!isObject()) { + if (VELOCYPACK_UNLIKELY(!isObject())) { throw Exception(Exception::InvalidValueType, "Expecting type Object"); } @@ -433,17 +433,17 @@ class Slice { template Slice get(std::vector const& attributes, bool resolveExternals = false) const { - size_t const n = attributes.size(); + std::size_t const n = attributes.size(); if (n == 0) { throw Exception(Exception::InvalidAttributePath); } // use ourselves as the starting point - Slice last = Slice(start()); + Slice last(start()); if (resolveExternals) { last = last.resolveExternal(); } - for (size_t i = 0; i < attributes.size(); ++i) { + for (std::size_t i = 0; i < attributes.size(); ++i) { // fetch subattribute last = last.get(attributes[i]); @@ -472,7 +472,7 @@ class Slice { return get(StringRef(attribute)); } - Slice get(char const* attribute, size_t length) const { + Slice get(char const* attribute, std::size_t length) const { return get(StringRef(attribute, length)); } @@ -497,7 +497,7 @@ class Slice { return hasKey(StringRef(attribute)); } - bool hasKey(char const* attribute, size_t length) const { + bool hasKey(char const* attribute, std::size_t length) const { return hasKey(StringRef(attribute, length)); } @@ -677,7 +677,7 @@ class Slice { // short UTF-8 String ValueLength length = h - 0x40; return std::string(reinterpret_cast(_start + 1), - static_cast(length)); + static_cast(length)); } if (h == 0xbf) { @@ -696,7 +696,7 @@ class Slice { // short UTF-8 String ValueLength length = h - 0x40; return StringRef(reinterpret_cast(_start + 1), - static_cast(length)); + static_cast(length)); } if (h == 0xbf) { @@ -746,7 +746,7 @@ class Slice { std::vector out; ValueLength length = readIntegerNonEmpty(_start + 1, h - 0xbf); checkOverflow(length); - out.reserve(static_cast(length)); + out.reserve(static_cast(length)); out.insert(out.end(), _start + 1 + h - 0xbf, _start + 1 + h - 0xbf + length); return out; @@ -887,7 +887,7 @@ class Slice { return compareString(StringRef(value.data(), value.size())); } - int compareString(char const* value, size_t length) const { + int compareString(char const* value, std::size_t length) const { return compareString(StringRef(value, length)); } @@ -897,7 +897,7 @@ class Slice { return compareStringUnchecked(StringRef(value.data(), value.size())); } - int compareStringUnchecked(char const* value, size_t length) const noexcept { + int compareStringUnchecked(char const* value, std::size_t length) const noexcept { return compareStringUnchecked(StringRef(value, length)); } @@ -925,8 +925,7 @@ class Slice { return false; } - return (memcmp(start(), other.start(), - arangodb::velocypack::checkOverflow(size)) == 0); + return (memcmp(start(), other.start(), checkOverflow(size)) == 0); } bool operator==(Slice const& other) const { return equals(other); } @@ -977,7 +976,7 @@ class Slice { ValueLength firstSubOffset = findDataOffset(head); Slice first(_start + firstSubOffset); ValueLength s = first.byteSize(); - if (s == 0) { + if (VELOCYPACK_UNLIKELY(s == 0)) { throw Exception(Exception::InternalError, "Invalid data for Array"); } ValueLength end = readIntegerNonEmpty(_start + 1, offsetSize); @@ -1092,7 +1091,7 @@ namespace std { // implementation of std::hash for a Slice object template <> struct hash { - size_t operator()(arangodb::velocypack::Slice const& slice) const { + std::size_t operator()(arangodb::velocypack::Slice const& slice) const { #ifdef VELOCYPACK_32BIT // size_t is only 32 bits wide here... so don't simply truncate the // 64 bit hash value but convert it into a 32 bit value using data @@ -1100,7 +1099,7 @@ struct hash { uint64_t const hash = slice.hash(); return static_cast(hash >> 32) ^ static_cast(hash); #else - return static_cast(slice.hash()); + return static_cast(slice.hash()); #endif } }; diff --git a/3rdParty/velocypack/include/velocypack/StringRef.h b/3rdParty/velocypack/include/velocypack/StringRef.h index 206bc5113c..5fc35fa385 100644 --- a/3rdParty/velocypack/include/velocypack/StringRef.h +++ b/3rdParty/velocypack/include/velocypack/StringRef.h @@ -27,7 +27,6 @@ #ifndef VELOCYPACK_STRINGREF_H #define VELOCYPACK_STRINGREF_H 1 -#include #include #include #include @@ -35,7 +34,6 @@ #include #include "velocypack/velocypack-common.h" -#include "velocypack/Exception.h" namespace arangodb { namespace velocypack { @@ -50,7 +48,7 @@ class StringRef { explicit StringRef(std::string const& str) noexcept : StringRef(str.data(), str.size()) {} /// @brief create a StringRef from a C string plus length - constexpr StringRef(char const* data, size_t length) noexcept : _data(data), _length(length) {} + constexpr StringRef(char const* data, std::size_t length) noexcept : _data(data), _length(length) {} /// @brief create a StringRef from a null-terminated C string #if __cplusplus >= 201703 @@ -101,47 +99,19 @@ class StringRef { /// @brief create a StringRef from a VPack slice of type String StringRef& operator=(Slice slice); - StringRef substr(size_t pos = 0, size_t count = std::string::npos) const { - if (pos >= _length) { - throw Exception(Exception::IndexOutOfBounds, "substr index out of bounds"); - } - if (count == std::string::npos || (count + pos >= _length)) { - count = _length - pos; - } - return StringRef(_data + pos, count); - } + StringRef substr(std::size_t pos = 0, std::size_t count = std::string::npos) const; - char at(size_t index) const { - if (index >= _length) { - throw Exception(Exception::IndexOutOfBounds, "index out of bounds"); - } - return operator[](index); - } + char at(std::size_t index) const; - size_t find(char c) const; + std::size_t find(char c) const; - size_t rfind(char c) const; + std::size_t rfind(char c) const; - int compare(std::string const& other) const noexcept { - int res = memcmp(_data, other.data(), (std::min)(_length, other.size())); - if (res != 0) { - return res; - } - return static_cast(_length) - static_cast(other.size()); - } + int compare(std::string const& other) const noexcept; - int compare(StringRef const& other) const noexcept { - int res = memcmp(_data, other._data, (std::min)(_length, other._length)); - if (res != 0) { - return res; - } - return static_cast(_length) - static_cast(other._length); - } + int compare(StringRef const& other) const noexcept; - bool equals(StringRef const& other) const noexcept { - return (size() == other.size() && - (memcmp(data(), other.data(), size()) == 0)); - } + bool equals(StringRef const& other) const noexcept; inline std::string toString() const { return std::string(_data, _length); @@ -163,7 +133,7 @@ class StringRef { inline char back() const noexcept { return _data[_length - 1]; } - inline char operator[](size_t index) const noexcept { + inline char operator[](std::size_t index) const noexcept { return _data[index]; } @@ -171,23 +141,22 @@ class StringRef { return _data; } - constexpr inline size_t size() const noexcept { + constexpr inline std::size_t size() const noexcept { return _length; } - constexpr inline size_t length() const noexcept { + constexpr inline std::size_t length() const noexcept { return _length; } private: char const* _data; - size_t _length; + std::size_t _length; }; std::ostream& operator<<(std::ostream& stream, StringRef const& ref); -} -} - +} // namespace velocypack +} // namespace arangodb inline bool operator==(arangodb::velocypack::StringRef const& lhs, arangodb::velocypack::StringRef const& rhs) { return (lhs.size() == rhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0); @@ -206,7 +175,7 @@ inline bool operator!=(arangodb::velocypack::StringRef const& lhs, std::string c } inline bool operator==(arangodb::velocypack::StringRef const& lhs, char const* rhs) { - size_t const len = strlen(rhs); + std::size_t const len = strlen(rhs); return (lhs.size() == len && memcmp(lhs.data(), rhs, lhs.size()) == 0); } @@ -226,7 +195,7 @@ namespace std { template <> struct hash { - size_t operator()(arangodb::velocypack::StringRef const& value) const noexcept { + std::size_t operator()(arangodb::velocypack::StringRef const& value) const noexcept { return VELOCYPACK_HASH(value.data(), value.size(), 0xdeadbeef); } }; diff --git a/3rdParty/velocypack/include/velocypack/Validator.h b/3rdParty/velocypack/include/velocypack/Validator.h index 60c42af5f5..1a4d68d72b 100644 --- a/3rdParty/velocypack/include/velocypack/Validator.h +++ b/3rdParty/velocypack/include/velocypack/Validator.h @@ -38,36 +38,30 @@ class Validator { // This class can validate a binary VelocyPack value. public: - explicit Validator(Options const* options = &Options::Defaults) - : options(options), _level(0) { - if (options == nullptr) { - throw Exception(Exception::InternalError, "Options cannot be a nullptr"); - } - } - + explicit Validator(Options const* options = &Options::Defaults); ~Validator() = default; public: // validates a VelocyPack Slice value starting at ptr, with length bytes length // throws if the data is invalid - bool validate(char const* ptr, size_t length, bool isSubPart = false) { + bool validate(char const* ptr, std::size_t length, bool isSubPart = false) { return validate(reinterpret_cast(ptr), length, isSubPart); } // validates a VelocyPack Slice value starting at ptr, with length bytes length // throws if the data is invalid - bool validate(uint8_t const* ptr, size_t length, bool isSubPart = false); + bool validate(uint8_t const* ptr, std::size_t length, bool isSubPart = false); private: - void validateArray(uint8_t const* ptr, size_t length); - void validateCompactArray(uint8_t const* ptr, size_t length); - void validateUnindexedArray(uint8_t const* ptr, size_t length); - void validateIndexedArray(uint8_t const* ptr, size_t length); - void validateObject(uint8_t const* ptr, size_t length); - void validateCompactObject(uint8_t const* ptr, size_t length); - void validateIndexedObject(uint8_t const* ptr, size_t length); - void validateBufferLength(size_t expected, size_t actual, bool isSubPart); - void validateSliceLength(uint8_t const* ptr, size_t length, bool isSubPart); + void validateArray(uint8_t const* ptr, std::size_t length); + void validateCompactArray(uint8_t const* ptr, std::size_t length); + void validateUnindexedArray(uint8_t const* ptr, std::size_t length); + void validateIndexedArray(uint8_t const* ptr, std::size_t length); + void validateObject(uint8_t const* ptr, std::size_t length); + void validateCompactObject(uint8_t const* ptr, std::size_t length); + void validateIndexedObject(uint8_t const* ptr, std::size_t length); + void validateBufferLength(std::size_t expected, std::size_t actual, bool isSubPart); + void validateSliceLength(uint8_t const* ptr, std::size_t length, bool isSubPart); ValueLength readByteSize(uint8_t const*& ptr, uint8_t const* end); public: diff --git a/3rdParty/velocypack/include/velocypack/Value.h b/3rdParty/velocypack/include/velocypack/Value.h index 4c4abf9810..c083e52e79 100644 --- a/3rdParty/velocypack/include/velocypack/Value.h +++ b/3rdParty/velocypack/include/velocypack/Value.h @@ -31,12 +31,11 @@ #include #include "velocypack/velocypack-common.h" -#include "velocypack/Exception.h" -#include "velocypack/StringRef.h" #include "velocypack/ValueType.h" namespace arangodb { namespace velocypack { +class StringRef; class Value { // Convenience class for more compact notation @@ -80,13 +79,7 @@ class Value { #endif // creates a Value with the specified type Array or Object - explicit Value(ValueType t, bool allowUnindexed = false) - : _valueType(t), _cType(CType::None), _unindexed(allowUnindexed) { - if (allowUnindexed && - (_valueType != ValueType::Array && _valueType != ValueType::Object)) { - throw Exception(Exception::InvalidValueType, "Expecting compound type"); - } - } + explicit Value(ValueType t, bool allowUnindexed = false); explicit Value(bool b, ValueType t = ValueType::Bool) noexcept : _valueType(t), _cType(CType::Bool), _unindexed(false) { @@ -208,8 +201,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 - : ValuePair(value.data(), value.size(), 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/ValueType.h b/3rdParty/velocypack/include/velocypack/ValueType.h index e80e71f59f..f51e124fcf 100644 --- a/3rdParty/velocypack/include/velocypack/ValueType.h +++ b/3rdParty/velocypack/include/velocypack/ValueType.h @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #ifndef VELOCYPACK_VALUETYPE_H -#define VELOCYPACK_VALUETYPE_H +#define VELOCYPACK_VALUETYPE_H 1 #include diff --git a/3rdParty/velocypack/include/velocypack/velocypack-aliases.h b/3rdParty/velocypack/include/velocypack/velocypack-aliases.h index 48186ab65f..a112e7c64a 100644 --- a/3rdParty/velocypack/include/velocypack/velocypack-aliases.h +++ b/3rdParty/velocypack/include/velocypack/velocypack-aliases.h @@ -53,10 +53,10 @@ using VPackObjectIterator = arangodb::velocypack::ObjectIterator; #ifndef VELOCYPACK_ALIAS_BUILDER #define VELOCYPACK_ALIAS_BUILDER using VPackBuilder = arangodb::velocypack::Builder; -using VPackObjectBuilder = arangodb::velocypack::ObjectBuilder; -using VPackArrayBuilder = arangodb::velocypack::ArrayBuilder; using VPackBuilderNonDeleter = arangodb::velocypack::BuilderNonDeleter; using VPackBuilderContainer = arangodb::velocypack::BuilderContainer; +using VPackObjectBuilder = arangodb::velocypack::ObjectBuilder; +using VPackArrayBuilder = arangodb::velocypack::ArrayBuilder; #endif #endif @@ -124,8 +124,6 @@ using VPackHexDump = arangodb::velocypack::HexDump; #ifndef VELOCYPACK_ALIAS_OPTIONS #define VELOCYPACK_ALIAS_OPTIONS using VPackOptions = arangodb::velocypack::Options; -using VPackAttributeExcludeHandler = - arangodb::velocypack::AttributeExcludeHandler; using VPackCustomTypeHandler = arangodb::velocypack::CustomTypeHandler; #endif #endif diff --git a/3rdParty/velocypack/include/velocypack/velocypack-common.h b/3rdParty/velocypack/include/velocypack/velocypack-common.h index b424abd378..25a9a8cd05 100644 --- a/3rdParty/velocypack/include/velocypack/velocypack-common.h +++ b/3rdParty/velocypack/include/velocypack/velocypack-common.h @@ -86,14 +86,14 @@ #ifdef VELOCYPACK_XXHASH // forward for XXH64 function declared elsewhere -extern "C" unsigned long long XXH64(void const*, size_t, unsigned long long); +extern "C" unsigned long long XXH64(void const*, std::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); +uint64_t fasthash64(void const*, std::size_t, uint64_t); #define VELOCYPACK_HASH(mem, size, seed) fasthash64(mem, size, seed) #endif diff --git a/3rdParty/velocypack/src/AttributeTranslator.cpp b/3rdParty/velocypack/src/AttributeTranslator.cpp index 8d41767e25..dde2d12e03 100644 --- a/3rdParty/velocypack/src/AttributeTranslator.cpp +++ b/3rdParty/velocypack/src/AttributeTranslator.cpp @@ -27,6 +27,8 @@ #include "velocypack/AttributeTranslator.h" #include "velocypack/Builder.h" #include "velocypack/Iterator.h" +#include "velocypack/Options.h" +#include "velocypack/Slice.h" #include "velocypack/Value.h" using namespace arangodb::velocypack; @@ -68,3 +70,17 @@ void AttributeTranslator::seal() { it.next(); } } + +AttributeTranslatorScope::AttributeTranslatorScope(AttributeTranslator* translator) + : _old(Options::Defaults.attributeTranslator) { + Options::Defaults.attributeTranslator = translator; +} + +AttributeTranslatorScope::~AttributeTranslatorScope() { + revert(); +} + +// prematurely revert the change +void AttributeTranslatorScope::revert() noexcept { + Options::Defaults.attributeTranslator = _old; +} diff --git a/3rdParty/velocypack/src/Builder.cpp b/3rdParty/velocypack/src/Builder.cpp index 4245fe29b0..05410e9168 100644 --- a/3rdParty/velocypack/src/Builder.cpp +++ b/3rdParty/velocypack/src/Builder.cpp @@ -41,7 +41,7 @@ namespace { // 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* findAttrName(uint8_t const* base, uint64_t& len) { uint8_t const b = *base; if (b >= 0x40 && b <= 0xbe) { // short UTF-8 string @@ -52,7 +52,7 @@ static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len) { // long UTF-8 string len = 0; // read string length - for (size_t i = 8; i >= 1; i--) { + for (std::size_t i = 8; i >= 1; i--) { len = (len << 8) + base[i]; } return base + 1 + 8; // string starts here @@ -63,8 +63,130 @@ static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len) { } } // namespace - +// create an empty Builder, using default Options +Builder::Builder() + : _buffer(std::make_shared>()), + _bufferPtr(_buffer.get()), + _start(_bufferPtr->data()), + _pos(0), + _keyWritten(false), + options(&Options::Defaults) {} + +// create an empty Builder, with custom Options +Builder::Builder(Options const* options) + : _buffer(std::make_shared>()), + _bufferPtr(_buffer.get()), + _start(_bufferPtr->data()), + _pos(0), + _keyWritten(false), + options(options) { + if (VELOCYPACK_UNLIKELY(options == nullptr)) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } +} + +Builder::Builder(std::shared_ptr> const& buffer, Options const* options) + : _buffer(buffer), + _bufferPtr(_buffer.get()), + _pos(0), + _keyWritten(false), + options(options) { + if (VELOCYPACK_UNLIKELY(_bufferPtr == nullptr)) { + throw Exception(Exception::InternalError, "Buffer cannot be a nullptr"); + } + _start = _bufferPtr->data(); + + if (VELOCYPACK_UNLIKELY(options == nullptr)) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } +} + +Builder::Builder(Buffer& buffer, Options const* options) + : _bufferPtr(nullptr), + _pos(buffer.size()), + _keyWritten(false), + options(options) { + _buffer.reset(&buffer, BufferNonDeleter()); + _bufferPtr = _buffer.get(); + _start = _bufferPtr->data(); + + if (VELOCYPACK_UNLIKELY(options == nullptr)) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } +} + +Builder::Builder(Slice slice, Options const* options) + : Builder(options) { + add(slice); +} + +Builder::Builder(Builder const& that) + : _buffer(std::make_shared>(*that._buffer)), + _bufferPtr(_buffer.get()), + _start(_bufferPtr->data()), + _pos(that._pos), + _stack(that._stack), + _index(that._index), + _keyWritten(that._keyWritten), + options(that.options) { + VELOCYPACK_ASSERT(options != nullptr); +} + +Builder& Builder::operator=(Builder const& that) { + if (this != &that) { + _buffer = std::make_shared>(*that._buffer); + _bufferPtr = _buffer.get(); + _start = _bufferPtr->data(); + _pos = that._pos; + _stack = that._stack; + _index = that._index; + _keyWritten = that._keyWritten; + options = that.options; + } + VELOCYPACK_ASSERT(options != nullptr); + return *this; +} + +Builder::Builder(Builder&& that) { + if (VELOCYPACK_UNLIKELY(!that.isClosed())) { + throw Exception(Exception::InternalError, "Cannot move an open Builder"); + } + _buffer = that._buffer; + _bufferPtr = _buffer.get(); + _start = _bufferPtr->data(); + _pos = that._pos; + _stack.clear(); + _stack.swap(that._stack); + _index.clear(); + _index.swap(that._index); + _keyWritten = that._keyWritten; + options = that.options; + that._pos = 0; + that._keyWritten = false; +} + +Builder& Builder::operator=(Builder&& that) { + if (VELOCYPACK_UNLIKELY(!that.isClosed())) { + throw Exception(Exception::InternalError, "Cannot move an open Builder"); + } + if (this != &that) { + _buffer = that._buffer; + _bufferPtr = _buffer.get(); + _start = _bufferPtr->data(); + _pos = that._pos; + _stack.clear(); + _stack.swap(that._stack); + _index.clear(); + _index.swap(that._index); + _keyWritten = that._keyWritten; + options = that.options; + that._pos = 0; + that._keyWritten = false; + } + return *this; +} + std::string Builder::toString() const { Options options; options.prettyPrint = true; @@ -109,10 +231,10 @@ void Builder::sortObjectIndexLong(uint8_t* objBase, std::vector& offsets) { _sortEntries.clear(); - size_t const n = offsets.size(); + std::size_t const n = offsets.size(); VELOCYPACK_ASSERT(n > 1); _sortEntries.reserve(n); - for (size_t i = 0; i < n; i++) { + for (std::size_t i = 0; i < n; i++) { SortEntry e; e.offset = offsets[i]; e.nameStart = ::findAttrName(objBase + e.offset, e.nameSize); @@ -128,32 +250,19 @@ void Builder::sortObjectIndexLong(uint8_t* objBase, // return true iff a < b: uint64_t sizea = a.nameSize; uint64_t sizeb = b.nameSize; - size_t const compareLength = checkOverflow((std::min)(sizea, sizeb)); + std::size_t const compareLength = checkOverflow((std::min)(sizea, sizeb)); int res = memcmp(a.nameStart, b.nameStart, compareLength); return (res < 0 || (res == 0 && sizea < sizeb)); }); // copy back the sorted offsets - for (size_t i = 0; i < n; i++) { + for (std::size_t i = 0; i < n; i++) { offsets[i] = _sortEntries[i].offset; } _sortEntries.clear(); } -void Builder::removeLast() { - if (_stack.empty()) { - throw Exception(Exception::BuilderNeedOpenCompound); - } - ValueLength& tos = _stack.back(); - std::vector& index = _index[_stack.size() - 1]; - if (index.empty()) { - throw Exception(Exception::BuilderNeedSubvalue); - } - resetTo(tos + index.back()); - index.pop_back(); -} - Builder& Builder::closeEmptyArrayOrObject(ValueLength tos, bool isArray) { // empty Array or Object _start[tos] = (isArray ? 0x01 : 0x0a); @@ -232,7 +341,7 @@ Builder& Builder::closeArray(ValueLength tos, std::vector& index) { if ((_pos - tos) - index[index.size() - 1] != subLen) { buildIndexTable = true; } else { - for (size_t i = 1; i < index.size() - 1; i++) { + for (std::size_t i = 1; i < index.size() - 1; i++) { if (index[i + 1] - index[i] != subLen) { // different lengths buildIndexTable = true; @@ -273,8 +382,8 @@ Builder& Builder::closeArray(ValueLength tos, std::vector& index) { // (0x00). in this case, we could not distinguish between a None (0x00) // and the optional padding. so we must prevent the memmove here bool allowMemMove = true; - size_t const n = (std::min)(size_t(6), index.size()); - for (size_t i = 0; i < n; i++) { + std::size_t const n = (std::min)(std::size_t(6), index.size()); + for (std::size_t i = 0; i < n; i++) { if (_start[tos + index[i]] == 0x00) { allowMemMove = false; break; @@ -292,8 +401,8 @@ Builder& Builder::closeArray(ValueLength tos, std::vector& index) { ValueLength const diff = 9 - targetPos; rollback(diff); if (needIndexTable) { - size_t const n = index.size(); - for (size_t i = 0; i < n; i++) { + std::size_t const n = index.size(); + for (std::size_t i = 0; i < n; i++) { index[i] -= diff; } } // Note: if !needIndexTable the index array is now wrong! @@ -309,9 +418,9 @@ Builder& Builder::closeArray(ValueLength tos, std::vector& index) { reserve(offsetSize * index.size() + (offsetSize == 8 ? 8 : 0)); tableBase = _pos; advance(offsetSize * index.size()); - for (size_t i = 0; i < index.size(); i++) { + for (std::size_t i = 0; i < index.size(); i++) { uint64_t x = index[i]; - for (size_t j = 0; j < offsetSize; j++) { + for (std::size_t j = 0; j < offsetSize; j++) { _start[tableBase + offsetSize * i + j] = x & 0xff; x >>= 8; } @@ -415,8 +524,8 @@ Builder& Builder::close() { } ValueLength const diff = 9 - targetPos; rollback(diff); - size_t const n = index.size(); - for (size_t i = 0; i < n; i++) { + std::size_t const n = index.size(); + for (std::size_t i = 0; i < n; i++) { index[i] -= diff; } @@ -437,9 +546,9 @@ Builder& Builder::close() { if (index.size() >= 2) { sortObjectIndex(_start + tos, index); } - for (size_t i = 0; i < index.size(); ++i) { + for (std::size_t i = 0; i < index.size(); ++i) { uint64_t x = index[i]; - for (size_t j = 0; j < offsetSize; ++j) { + for (std::size_t j = 0; j < offsetSize; ++j) { _start[tableBase + offsetSize * i + j] = x & 0xff; x >>= 8; } @@ -492,14 +601,14 @@ bool Builder::hasKey(std::string const& key) const { throw Exception(Exception::BuilderNeedOpenObject); } ValueLength const& tos = _stack.back(); - if (_start[tos] != 0x0b && _start[tos] != 0x14) { + if (VELOCYPACK_UNLIKELY(_start[tos] != 0x0b && _start[tos] != 0x14)) { throw Exception(Exception::BuilderNeedOpenObject); } std::vector const& index = _index[_stack.size() - 1]; if (index.empty()) { return false; } - for (size_t i = 0; i < index.size(); ++i) { + for (std::size_t i = 0; i < index.size(); ++i) { Slice s(_start + tos + index[i]); if (s.makeKey().isEqualString(key)) { return true; @@ -521,7 +630,7 @@ Slice Builder::getKey(std::string const& key) const { if (index.empty()) { return Slice(); } - for (size_t i = 0; i < index.size(); ++i) { + for (std::size_t i = 0; i < index.size(); ++i) { Slice s(_start + tos + index[i]); if (s.makeKey().isEqualString(key)) { return Slice(s.start() + s.byteSize()); @@ -677,7 +786,7 @@ uint8_t* Builder::set(Value const& item) { case ValueType::String: { if (ctype == Value::CType::String) { std::string const* s = item.getString(); - size_t const size = s->size(); + std::size_t const size = s->size(); if (size <= 126) { // short string reserve(1 + size); @@ -693,7 +802,7 @@ uint8_t* Builder::set(Value const& item) { advance(size); } else if (ctype == Value::CType::CharPtr) { char const* p = item.getCharPtr(); - size_t const size = strlen(p); + std::size_t const size = strlen(p); if (size <= 126) { // short string reserve(1 + size); @@ -920,15 +1029,13 @@ bool Builder::checkAttributeUniquenessUnsorted(Slice obj) const { if (it.size() <= LinearAttributeUniquenessCutoff) { std::array keys; do { - // key() guarantees a String as returned type + // key(true) guarantees a String as returned type StringRef key = it.key(true).stringRef(); ValueLength index = it.index(); - if (index > 0) { - // compare with all other already looked-at keys - for (ValueLength i = 0; i < index; ++i) { - if (keys[i].equals(key)) { - return false; - } + // compare with all other already looked-at keys + for (ValueLength i = 0; i < index; ++i) { + if (VELOCYPACK_UNLIKELY(keys[i].equals(key))) { + return false; } } keys[index] = key; @@ -938,9 +1045,9 @@ bool Builder::checkAttributeUniquenessUnsorted(Slice obj) const { std::unordered_set keys; do { Slice const key = it.key(true); - // key() guarantees a String as returned type + // key(true) guarantees a String as returned type VELOCYPACK_ASSERT(key.isString()); - if (!keys.emplace(key).second) { + if (VELOCYPACK_UNLIKELY(!keys.emplace(key).second)) { // identical key return false; } @@ -954,48 +1061,38 @@ bool Builder::checkAttributeUniquenessUnsorted(Slice obj) const { // Add all subkeys and subvalues into an object from an ObjectIterator // and leaves open the object intentionally -uint8_t* Builder::add(ObjectIterator& sub) { - return add(std::move(sub)); -} - -uint8_t* Builder::add(ObjectIterator&& sub) { - if (_stack.empty()) { +uint8_t* Builder::add(ObjectIterator const& sub) { + if (VELOCYPACK_UNLIKELY(_stack.empty())) { throw Exception(Exception::BuilderNeedOpenObject); } ValueLength& tos = _stack.back(); - if (_start[tos] != 0x0b && _start[tos] != 0x14) { + if (VELOCYPACK_UNLIKELY(_start[tos] != 0x0b && _start[tos] != 0x14)) { throw Exception(Exception::BuilderNeedOpenObject); } - if (_keyWritten) { + if (VELOCYPACK_UNLIKELY(_keyWritten)) { throw Exception(Exception::BuilderKeyAlreadyWritten); } auto const oldPos = _pos; - while (sub.valid()) { - add(sub.key(true)); - add(sub.value()); - sub.next(); + for (auto const& it : sub) { + add(it.key); + add(it.value); } return _start + oldPos; } // Add all subkeys and subvalues into an object from an ArrayIterator // and leaves open the array intentionally -uint8_t* Builder::add(ArrayIterator& sub) { - return add(std::move(sub)); -} - -uint8_t* Builder::add(ArrayIterator&& sub) { - if (_stack.empty()) { +uint8_t* Builder::add(ArrayIterator const& sub) { + if (VELOCYPACK_UNLIKELY(_stack.empty())) { throw Exception(Exception::BuilderNeedOpenArray); } ValueLength& tos = _stack.back(); - if (_start[tos] != 0x06 && _start[tos] != 0x13) { + if (VELOCYPACK_UNLIKELY(_start[tos] != 0x06 && _start[tos] != 0x13)) { throw Exception(Exception::BuilderNeedOpenArray); } auto const oldPos = _pos; - while (sub.valid()) { - add(sub.value()); - sub.next(); + for (auto const& it : sub) { + add(it); } return _start + oldPos; } diff --git a/3rdParty/velocypack/src/Collection.cpp b/3rdParty/velocypack/src/Collection.cpp index af163ff7a6..17de56e1d6 100644 --- a/3rdParty/velocypack/src/Collection.cpp +++ b/3rdParty/velocypack/src/Collection.cpp @@ -359,7 +359,8 @@ Builder& Collection::merge(Builder& builder, Slice const& left, Slice const& rig { ObjectIterator it(right); while (it.valid()) { - rightValues.emplace(it.key(true).stringRef(), it.value()); + auto current = (*it); + rightValues.emplace(current.key.stringRef(), current.value); it.next(); } } @@ -368,19 +369,20 @@ Builder& Collection::merge(Builder& builder, Slice const& left, Slice const& rig ObjectIterator it(left); while (it.valid()) { - auto key = it.key(true).stringRef(); + auto current = (*it); + auto key = current.key.stringRef(); auto found = rightValues.find(key); if (found == rightValues.end()) { // use left value - builder.add(key, it.value()); - } else if (mergeValues && it.value().isObject() && + builder.add(key, current.value); + } else if (mergeValues && current.value.isObject() && (*found).second.isObject()) { // merge both values auto& value = (*found).second; if (!nullMeansRemove || (!value.isNone() && !value.isNull())) { builder.add(ValuePair(key, ValueType::String)); - Collection::merge(builder, it.value(), value, true, nullMeansRemove); + Collection::merge(builder, current.value, value, true, nullMeansRemove); } // clear the value in the map so its not added again (*found).second = Slice(); @@ -425,8 +427,9 @@ static bool visitObject( ObjectIterator it(value); while (it.valid()) { + auto current = (*it); // sub-object? - Slice v = it.value(); + Slice v = current.value; bool const isCompound = (v.isObject() || v.isArray()); if (isCompound && order == Collection::PreOrder) { @@ -435,7 +438,7 @@ static bool visitObject( } } - if (!func(it.key(true), v)) { + if (!func(current.key, v)) { return false; } diff --git a/3rdParty/velocypack/src/Dumper.cpp b/3rdParty/velocypack/src/Dumper.cpp index 980ab346a5..65ae1e4ea6 100644 --- a/3rdParty/velocypack/src/Dumper.cpp +++ b/3rdParty/velocypack/src/Dumper.cpp @@ -382,10 +382,11 @@ void Dumper::dumpValue(Slice const* slice, Slice const* base) { _sink->push_back('\n'); ++_indentation; while (it.valid()) { + auto current = (*it); indent(); - dumpValue(it.key(true), slice); + dumpValue(current.key, slice); _sink->append(" : ", 3); - dumpValue(it.value(), slice); + dumpValue(current.value, slice); if (!it.isLast()) { _sink->push_back(','); } @@ -399,9 +400,10 @@ void Dumper::dumpValue(Slice const* slice, Slice const* base) { if (!it.isFirst()) { _sink->push_back(','); } - dumpValue(it.key(true), slice); + auto current = (*it); + dumpValue(current.key, slice); _sink->push_back(':'); - dumpValue(it.value(), slice); + dumpValue(current.value, slice); it.next(); } } diff --git a/3rdParty/velocypack/src/Options.cpp b/3rdParty/velocypack/src/Options.cpp index bc458ce692..ba69bbba4f 100644 --- a/3rdParty/velocypack/src/Options.cpp +++ b/3rdParty/velocypack/src/Options.cpp @@ -25,9 +25,18 @@ //////////////////////////////////////////////////////////////////////////////// #include "velocypack/velocypack-common.h" +#include "velocypack/Exception.h" #include "velocypack/Options.h" using namespace arangodb::velocypack; + +void CustomTypeHandler::dump(Slice const&, Dumper*, Slice const&) { + throw Exception(Exception::NotImplemented); +} + +std::string CustomTypeHandler::toString(Slice const&, Options const*, Slice const&) { + throw Exception(Exception::NotImplemented); +} // default options instance Options Options::Defaults; diff --git a/3rdParty/velocypack/src/Parser.cpp b/3rdParty/velocypack/src/Parser.cpp index 4f83664e13..89633c665c 100644 --- a/3rdParty/velocypack/src/Parser.cpp +++ b/3rdParty/velocypack/src/Parser.cpp @@ -109,9 +109,9 @@ int Parser::skipWhiteSpace(char const* err) { return c; } } - size_t remaining = _size - _pos; + std::size_t remaining = _size - _pos; if (remaining >= 16) { - size_t count = JSONSkipWhiteSpace(_start + _pos, remaining - 15); + std::size_t count = JSONSkipWhiteSpace(_start + _pos, remaining - 15); _pos += count; } do { @@ -125,7 +125,7 @@ int Parser::skipWhiteSpace(char const* err) { // parses a number value void Parser::parseNumber() { - size_t startPos = _pos; + std::size_t startPos = _pos; ParsedNumber numberValue; bool negative = false; int i = consume(); @@ -241,10 +241,10 @@ void Parser::parseString() { uint32_t highSurrogate = 0; // non-zero if high-surrogate was seen while (true) { - size_t remainder = _size - _pos; + std::size_t remainder = _size - _pos; if (remainder >= 16) { _builderPtr->reserve(remainder); - size_t count; + std::size_t count; // Note that the SSE4.2 accelerated string copying functions might // peek up to 15 bytes over the given end, because they use 128bit // registers. Therefore, we have to subtract 15 from remainder diff --git a/3rdParty/velocypack/src/Slice.cpp b/3rdParty/velocypack/src/Slice.cpp index 55121481a2..b0bd0af86a 100644 --- a/3rdParty/velocypack/src/Slice.cpp +++ b/3rdParty/velocypack/src/Slice.cpp @@ -220,7 +220,7 @@ Slice Slice::get(StringRef const& attribute) const { if (n == 1) { // Just one attribute, there is no index table! - Slice key = Slice(_start + findDataOffset(h)); + Slice key(_start + findDataOffset(h)); if (key.isString()) { if (key.isEqualStringUnchecked(attribute)) { @@ -376,11 +376,11 @@ int64_t Slice::getSmallInt() const { } int Slice::compareString(StringRef const& value) const { - size_t const length = value.size(); + std::size_t const length = value.size(); ValueLength keyLength; char const* k = getString(keyLength); - size_t const compareLength = - (std::min)(static_cast(keyLength), length); + std::size_t const compareLength = + (std::min)(static_cast(keyLength), length); int res = memcmp(k, value.data(), compareLength); if (res == 0) { @@ -392,11 +392,11 @@ int Slice::compareString(StringRef const& value) const { } int Slice::compareStringUnchecked(StringRef const& value) const noexcept { - size_t const length = value.size(); + std::size_t const length = value.size(); ValueLength keyLength; char const* k = getStringUnchecked(keyLength); - size_t const compareLength = - (std::min)(static_cast(keyLength), length); + std::size_t const compareLength = + (std::min)(static_cast(keyLength), length); int res = memcmp(k, value.data(), compareLength); if (res == 0) { @@ -410,19 +410,15 @@ int Slice::compareStringUnchecked(StringRef const& value) const noexcept { bool Slice::isEqualString(StringRef const& attribute) const { ValueLength keyLength; char const* k = getString(keyLength); - if (static_cast(keyLength) != attribute.size()) { - return false; - } - return (memcmp(k, attribute.data(), attribute.size()) == 0); + return (static_cast(keyLength) == attribute.size()) && + (memcmp(k, attribute.data(), attribute.size()) == 0); } bool Slice::isEqualStringUnchecked(StringRef const& attribute) const noexcept { ValueLength keyLength; char const* k = getStringUnchecked(keyLength); - if (static_cast(keyLength) != attribute.size()) { - return false; - } - return (memcmp(k, attribute.data(), attribute.size()) == 0); + return (static_cast(keyLength) == attribute.size()) && + (memcmp(k, attribute.data(), attribute.size()) == 0); } Slice Slice::getFromCompactObject(StringRef const& attribute) const { @@ -450,7 +446,7 @@ ValueLength Slice::getNthOffset(ValueLength index) const { return getNthOffsetFromCompact(index); } - if (h == 0x01 || h == 0x0a) { + if (VELOCYPACK_UNLIKELY(h == 0x01 || h == 0x0a)) { // special case: empty Array or empty Object throw Exception(Exception::IndexOutOfBounds); } @@ -467,7 +463,7 @@ ValueLength Slice::getNthOffset(ValueLength index) const { dataOffset = findDataOffset(h); Slice first(_start + dataOffset); ValueLength s = first.byteSize(); - if (s == 0) { + if (VELOCYPACK_UNLIKELY(s == 0)) { throw Exception(Exception::InternalError, "Invalid data for compact object"); } n = (end - dataOffset) / s; @@ -524,7 +520,7 @@ Slice Slice::makeKey() const { return *this; } if (isSmallInt() || isUInt()) { - if (Options::Defaults.attributeTranslator == nullptr) { + if (VELOCYPACK_UNLIKELY(Options::Defaults.attributeTranslator == nullptr)) { throw Exception(Exception::NeedAttributeTranslator); } return translateUnchecked(); @@ -574,7 +570,7 @@ Slice Slice::searchObjectKeyLinear(StringRef const& attribute, } } else if (key.isSmallInt() || key.isUInt()) { // translate key - if (!useTranslator) { + if (VELOCYPACK_UNLIKELY(!useTranslator)) { // no attribute translator throw Exception(Exception::NeedAttributeTranslator); } @@ -615,7 +611,7 @@ Slice Slice::searchObjectKeyBinary(StringRef const& attribute, res = key.compareStringUnchecked(attribute.data(), attribute.size()); } else if (key.isSmallInt() || key.isUInt()) { // translate key - if (!useTranslator) { + if (VELOCYPACK_UNLIKELY(!useTranslator)) { // no attribute translator throw Exception(Exception::NeedAttributeTranslator); } diff --git a/3rdParty/velocypack/src/StringRef.cpp b/3rdParty/velocypack/src/StringRef.cpp index 7e079a5fff..56b8f4cc44 100644 --- a/3rdParty/velocypack/src/StringRef.cpp +++ b/3rdParty/velocypack/src/StringRef.cpp @@ -24,16 +24,18 @@ /// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// +#include #include -#include "velocypack/StringRef.h" +#include "velocypack/Exception.h" #include "velocypack/Slice.h" +#include "velocypack/StringRef.h" using namespace arangodb::velocypack; namespace { -void* memrchrSwitch(void const* block, int c, size_t size) { +void* memrchrSwitch(void const* block, int c, std::size_t size) { #ifdef __linux__ return const_cast(memrchr(block, c, size)); #else @@ -69,7 +71,24 @@ StringRef& StringRef::operator=(Slice slice) { return *this; } -size_t StringRef::find(char c) const { +StringRef StringRef::substr(std::size_t pos, std::size_t count) const { + if (pos >= _length) { + throw Exception(Exception::IndexOutOfBounds, "substr index out of bounds"); + } + if (count == std::string::npos || (count + pos >= _length)) { + count = _length - pos; + } + return StringRef(_data + pos, count); +} + +char StringRef::at(std::size_t index) const { + if (index >= _length) { + throw Exception(Exception::IndexOutOfBounds, "index out of bounds"); + } + return operator[](index); +} + +std::size_t StringRef::find(char c) const { char const* p = static_cast(memchr(static_cast(_data), c, _length)); @@ -80,7 +99,7 @@ size_t StringRef::find(char c) const { return (p - _data); } -size_t StringRef::rfind(char c) const { +std::size_t StringRef::rfind(char c) const { char const* p = static_cast(::memrchrSwitch(static_cast(_data), c, _length)); @@ -90,6 +109,27 @@ size_t StringRef::rfind(char c) const { return (p - _data); } + +int StringRef::compare(std::string const& other) const noexcept { + int res = memcmp(_data, other.data(), (std::min)(_length, other.size())); + if (res != 0) { + return res; + } + return static_cast(_length) - static_cast(other.size()); +} + +int StringRef::compare(StringRef const& other) const noexcept { + int res = memcmp(_data, other._data, (std::min)(_length, other._length)); + if (res != 0) { + return res; + } + return static_cast(_length) - static_cast(other._length); +} + +bool StringRef::equals(StringRef const& other) const noexcept { + return (size() == other.size() && + (memcmp(data(), other.data(), size()) == 0)); +} namespace arangodb { namespace velocypack { diff --git a/3rdParty/velocypack/src/Validator.cpp b/3rdParty/velocypack/src/Validator.cpp index ed773245d1..71e6d70012 100644 --- a/3rdParty/velocypack/src/Validator.cpp +++ b/3rdParty/velocypack/src/Validator.cpp @@ -31,7 +31,6 @@ #include "velocypack/Validator.h" #include "velocypack/Exception.h" #include "velocypack/Slice.h" -#include "velocypack/Utf8Helper.h" #include "velocypack/ValueType.h" #include "asm-functions.h" @@ -60,8 +59,15 @@ static ValueLength ReadVariableLengthValue(uint8_t const*& p, uint8_t const* end } return value; } + +Validator::Validator(Options const* options) + : options(options), _level(0) { + if (options == nullptr) { + throw Exception(Exception::InternalError, "Options cannot be a nullptr"); + } +} -bool Validator::validate(uint8_t const* ptr, size_t length, bool isSubPart) { +bool Validator::validate(uint8_t const* ptr, std::size_t length, bool isSubPart) { if (length == 0) { throw Exception(Exception::ValidatorInvalidLength, "length 0 is invalid for any VelocyPack value"); } @@ -109,7 +115,8 @@ bool Validator::validate(uint8_t const* ptr, size_t length, bool isSubPart) { validateBufferLength(len + 1, length, true); } - if (options->validateUtf8Strings && !Utf8Helper::isValidUtf8(p, len)) { + if (options->validateUtf8Strings && + !ValidateUtf8String(p, static_cast(len))) { throw Exception(Exception::InvalidUtf8Sequence); } break; @@ -191,7 +198,7 @@ bool Validator::validate(uint8_t const* ptr, size_t length, bool isSubPart) { return true; } -void Validator::validateArray(uint8_t const* ptr, size_t length) { +void Validator::validateArray(uint8_t const* ptr, std::size_t length) { uint8_t head = *ptr; if (head == 0x13U) { @@ -208,7 +215,7 @@ void Validator::validateArray(uint8_t const* ptr, size_t length) { } } -void Validator::validateCompactArray(uint8_t const* ptr, size_t length) { +void Validator::validateCompactArray(uint8_t const* ptr, std::size_t length) { // compact Array without index table validateBufferLength(4, length, true); @@ -237,7 +244,7 @@ void Validator::validateCompactArray(uint8_t const* ptr, size_t length) { } } -void Validator::validateUnindexedArray(uint8_t const* ptr, size_t length) { +void Validator::validateUnindexedArray(uint8_t const* ptr, std::size_t length) { // Array without index table, with 1-8 bytes lengths, all values with same length uint8_t head = *ptr; ValueLength const byteSizeLength = 1ULL << (static_cast(head) - 0x02U); @@ -299,7 +306,7 @@ void Validator::validateUnindexedArray(uint8_t const* ptr, size_t length) { } } -void Validator::validateIndexedArray(uint8_t const* ptr, size_t length) { +void Validator::validateIndexedArray(uint8_t const* ptr, std::size_t length) { // Array with index table, with 1-8 bytes lengths uint8_t head = *ptr; ValueLength const byteSizeLength = 1ULL << (static_cast(head) - 0x06U); @@ -381,7 +388,7 @@ void Validator::validateIndexedArray(uint8_t const* ptr, size_t length) { } } -void Validator::validateObject(uint8_t const* ptr, size_t length) { +void Validator::validateObject(uint8_t const* ptr, std::size_t length) { uint8_t head = *ptr; if (head == 0x14U) { @@ -395,7 +402,7 @@ void Validator::validateObject(uint8_t const* ptr, size_t length) { } } -void Validator::validateCompactObject(uint8_t const* ptr, size_t length) { +void Validator::validateCompactObject(uint8_t const* ptr, std::size_t length) { // compact Object without index table validateBufferLength(5, length, true); @@ -438,7 +445,7 @@ void Validator::validateCompactObject(uint8_t const* ptr, size_t length) { } } -void Validator::validateIndexedObject(uint8_t const* ptr, size_t length) { +void Validator::validateIndexedObject(uint8_t const* ptr, std::size_t length) { // Object with index table, with 1-8 bytes lengths uint8_t head = *ptr; ValueLength const byteSizeLength = 1ULL << (static_cast(head) - 0x0bU); @@ -588,14 +595,14 @@ void Validator::validateIndexedObject(uint8_t const* ptr, size_t length) { } } -void Validator::validateBufferLength(size_t expected, size_t actual, bool isSubPart) { +void Validator::validateBufferLength(std::size_t expected, std::size_t actual, bool isSubPart) { if ((expected > actual) || (expected != actual && !isSubPart)) { throw Exception(Exception::ValidatorInvalidLength, "given buffer length is unequal to actual length of Slice in buffer"); } } -void Validator::validateSliceLength(uint8_t const* ptr, size_t length, bool isSubPart) { - size_t actual = static_cast(Slice(ptr).byteSize()); +void Validator::validateSliceLength(uint8_t const* ptr, std::size_t length, bool isSubPart) { + std::size_t actual = static_cast(Slice(ptr).byteSize()); validateBufferLength(actual, length, isSubPart); } diff --git a/3rdParty/velocypack/src/Value.cpp b/3rdParty/velocypack/src/Value.cpp new file mode 100644 index 0000000000..132fcc9974 --- /dev/null +++ b/3rdParty/velocypack/src/Value.cpp @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @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/Exception.h" +#include "velocypack/StringRef.h" +#include "velocypack/Value.h" + +using namespace arangodb::velocypack; + +// creates a Value with the specified type Array or Object +Value::Value(ValueType t, bool allowUnindexed) + : _valueType(t), _cType(CType::None), _unindexed(allowUnindexed) { + if (allowUnindexed && + (_valueType != ValueType::Array && _valueType != ValueType::Object)) { + throw Exception(Exception::InvalidValueType, "Expecting compound type"); + } +} + +ValuePair::ValuePair(StringRef const& value, ValueType type) noexcept + : ValuePair(value.data(), value.size(), type) {} diff --git a/3rdParty/velocypack/src/asm-functions.cpp b/3rdParty/velocypack/src/asm-functions.cpp index 3eebfdc506..305e2b5fcf 100644 --- a/3rdParty/velocypack/src/asm-functions.cpp +++ b/3rdParty/velocypack/src/asm-functions.cpp @@ -37,7 +37,7 @@ using namespace arangodb::velocypack; namespace { -inline size_t JSONStringCopyC(uint8_t* dst, uint8_t const* src, size_t limit) { +inline std::size_t JSONStringCopyC(uint8_t* dst, uint8_t const* src, std::size_t limit) { // Copy up to limit uint8_t from src to dst. // Stop at the first control character or backslash or double quote. // Report the number of bytes copied. May copy less bytes, for example @@ -49,7 +49,7 @@ inline size_t JSONStringCopyC(uint8_t* dst, uint8_t const* src, size_t limit) { return limit - (end - src); } -inline size_t JSONStringCopyCheckUtf8C(uint8_t* dst, uint8_t const* src, size_t limit) { +inline std::size_t JSONStringCopyCheckUtf8C(uint8_t* dst, uint8_t const* src, std::size_t limit) { // Copy up to limit uint8_t from src to dst. // Stop at the first control character or backslash or double quote. // Also stop at byte with high bit set. @@ -63,7 +63,7 @@ inline size_t JSONStringCopyCheckUtf8C(uint8_t* dst, uint8_t const* src, size_t return limit - (end - src); } -inline size_t JSONSkipWhiteSpaceC(uint8_t const* src, size_t limit) { +inline std::size_t JSONSkipWhiteSpaceC(uint8_t const* src, std::size_t limit) { // Skip up to limit uint8_t from src as long as they are whitespace. // Advance ptr and return the number of skipped bytes. uint8_t const* end = src + limit; @@ -73,7 +73,7 @@ inline size_t JSONSkipWhiteSpaceC(uint8_t const* src, size_t limit) { return limit - (end - src); } -inline bool ValidateUtf8StringC(uint8_t const* src, size_t limit) { +inline bool ValidateUtf8StringC(uint8_t const* src, std::size_t limit) { return Utf8Helper::isValidUtf8(src, static_cast(limit)); } @@ -109,12 +109,13 @@ bool hasAVX2() { } #endif -size_t JSONStringCopySSE42(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t JSONStringCopySSE42(uint8_t* dst, uint8_t const* src, std::size_t limit) { alignas(16) static char const ranges[17] = "\x20\x21\x23\x5b\x5d\xff "; //= "\x01\x1f\"\"\\\\\"\"\"\"\"\"\"\"\"\""; + __m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges)); - size_t count = 0; + std::size_t count = 0; int x = 0; while (limit >= 16) { __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src)); @@ -147,7 +148,7 @@ size_t JSONStringCopySSE42(uint8_t* dst, uint8_t const* src, size_t limit) { return count; } -size_t doInitCopy(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t doInitCopy(uint8_t* dst, uint8_t const* src, std::size_t limit) { if (assemblerFunctionsEnabled() && ::hasSSE42()) { JSONStringCopy = ::JSONStringCopySSE42; } else { @@ -156,12 +157,12 @@ size_t doInitCopy(uint8_t* dst, uint8_t const* src, size_t limit) { return (*JSONStringCopy)(dst, src, limit); } -size_t JSONStringCopyCheckUtf8SSE42(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t JSONStringCopyCheckUtf8SSE42(uint8_t* dst, uint8_t const* src, std::size_t limit) { alignas(16) static unsigned char const ranges[17] = "\x20\x21\x23\x5b\x5d\x7f "; //= "\x01\x1f\x80\xff\"\"\\\\\"\"\"\"\"\"\"\""; __m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges)); - size_t count = 0; + std::size_t count = 0; int x = 0; while (limit >= 16) { __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src)); @@ -194,7 +195,7 @@ size_t JSONStringCopyCheckUtf8SSE42(uint8_t* dst, uint8_t const* src, size_t lim return count; } -size_t doInitCopyCheckUtf8(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t doInitCopyCheckUtf8(uint8_t* dst, uint8_t const* src, std::size_t limit) { if (assemblerFunctionsEnabled() && ::hasSSE42()) { JSONStringCopyCheckUtf8 = ::JSONStringCopyCheckUtf8SSE42; } else { @@ -203,10 +204,10 @@ size_t doInitCopyCheckUtf8(uint8_t* dst, uint8_t const* src, size_t limit) { return (*JSONStringCopyCheckUtf8)(dst, src, limit); } -size_t JSONSkipWhiteSpaceSSE42(uint8_t const* ptr, size_t limit) { +std::size_t JSONSkipWhiteSpaceSSE42(uint8_t const* ptr, std::size_t limit) { alignas(16) static char const white[17] = " \t\n\r "; __m128i const w = _mm_load_si128(reinterpret_cast<__m128i const*>(white)); - size_t count = 0; + std::size_t count = 0; int x = 0; while (limit >= 16) { __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(ptr)); @@ -228,14 +229,14 @@ size_t JSONSkipWhiteSpaceSSE42(uint8_t const* ptr, size_t limit) { x = _mm_cmpistri(w, /* 4, */ s, /* limit, */ _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT); - if (static_cast(x) > limit) { + if (static_cast(x) > limit) { x = static_cast(limit); } count += x; return count; } -size_t doInitSkip(uint8_t const* src, size_t limit) { +std::size_t doInitSkip(uint8_t const* src, std::size_t limit) { if (assemblerFunctionsEnabled() && ::hasSSE42()) { JSONSkipWhiteSpace = ::JSONSkipWhiteSpaceSSE42; } else { @@ -245,7 +246,7 @@ size_t doInitSkip(uint8_t const* src, size_t limit) { } #ifdef __AVX2__ -bool ValidateUtf8StringAVX(uint8_t const* src, size_t len) { +bool ValidateUtf8StringAVX(uint8_t const* src, std::size_t len) { if (len >= 32) { return validate_utf8_fast_avx(src, len); } @@ -253,14 +254,14 @@ bool ValidateUtf8StringAVX(uint8_t const* src, size_t len) { } #endif -bool ValidateUtf8StringSSE42(uint8_t const* src, size_t len) { +bool ValidateUtf8StringSSE42(uint8_t const* src, std::size_t len) { if (len >= 16) { return validate_utf8_fast_sse42(src, len); } return Utf8Helper::isValidUtf8(src, len); } -bool doInitValidateUtf8String(uint8_t const* src, size_t limit) { +bool doInitValidateUtf8String(uint8_t const* src, std::size_t limit) { #ifdef __AVX2__ if (assemblerFunctionsEnabled() && ::hasAVX2()) { ValidateUtf8String = ValidateUtf8StringAVX; @@ -280,22 +281,22 @@ bool doInitValidateUtf8String(uint8_t const* src, size_t limit) { namespace { -size_t doInitCopy(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t doInitCopy(uint8_t* dst, uint8_t const* src, std::size_t limit) { JSONStringCopy = ::JSONStringCopyC; return ::JSONStringCopyC(dst, src, limit); } -size_t doInitCopyCheckUtf8(uint8_t* dst, uint8_t const* src, size_t limit) { +std::size_t doInitCopyCheckUtf8(uint8_t* dst, uint8_t const* src, std::size_t limit) { JSONStringCopyCheckUtf8 = ::JSONStringCopyCheckUtf8C; return ::JSONStringCopyCheckUtf8C(dst, src, limit); } -size_t doInitSkip(uint8_t const* src, size_t limit) { +std::size_t doInitSkip(uint8_t const* src, std::size_t limit) { JSONSkipWhiteSpace = ::JSONSkipWhiteSpaceC; return JSONSkipWhiteSpace(src, limit); } -bool doInitValidateUtf8String(uint8_t const* src, size_t limit) { +bool doInitValidateUtf8String(uint8_t const* src, std::size_t limit) { ValidateUtf8String = ::ValidateUtf8StringC; return ValidateUtf8StringC(src, limit); } @@ -304,10 +305,10 @@ bool doInitValidateUtf8String(uint8_t const* src, size_t limit) { #endif -size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, size_t) = ::doInitCopy; -size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t) = ::doInitCopyCheckUtf8; -size_t (*JSONSkipWhiteSpace)(uint8_t const*, size_t) = ::doInitSkip; -bool (*ValidateUtf8String)(uint8_t const*, size_t) = ::doInitValidateUtf8String; +std::size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, std::size_t) = ::doInitCopy; +std::size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, std::size_t) = ::doInitCopyCheckUtf8; +std::size_t (*JSONSkipWhiteSpace)(uint8_t const*, std::size_t) = ::doInitSkip; +bool (*ValidateUtf8String)(uint8_t const*, std::size_t) = ::doInitValidateUtf8String; void arangodb::velocypack::enableNativeStringFunctions() { JSONStringCopy = ::doInitCopy; @@ -330,26 +331,26 @@ int testPositions[] = { -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -23, -31, -32, -67, -103, -178, -210, -234, -247, -254, -255}; -void TestStringCopyCorrectness(uint8_t* src, uint8_t* dst, size_t size) { - size_t copied; +void TestStringCopyCorrectness(uint8_t* src, uint8_t* dst, std::size_t size) { + std::size_t copied; std::cout << "Performing correctness tests..." << std::endl; auto start = std::chrono::high_resolution_clock::now(); - for (size_t salign = 0; salign < 16; salign++) { + for (std::size_t salign = 0; salign < 16; salign++) { src += salign; - for (size_t dalign = 0; dalign < 16; dalign++) { + for (std::size_t dalign = 0; dalign < 16; dalign++) { dst += dalign; - for (size_t i = 0; + for (std::size_t i = 0; i < static_cast(sizeof(testPositions) / sizeof(int)); i++) { uint8_t merk; int off = testPositions[i]; - size_t pos; + std::size_t pos; if (off >= 0) { pos = off; } else { - pos = size - static_cast(-off); + pos = size - static_cast(-off); } if (pos >= size) { continue; @@ -405,8 +406,8 @@ void TestStringCopyCorrectness(uint8_t* src, uint8_t* dst, size_t size) { } void TestStringCopyCorrectnessCheckUtf8(uint8_t* src, uint8_t* dst, - size_t size) { - size_t copied; + std::size_t size) { + std::size_t copied; std::cout << "Performing correctness tests (check UTF8)..." << std::endl; @@ -420,11 +421,11 @@ void TestStringCopyCorrectnessCheckUtf8(uint8_t* src, uint8_t* dst, i++) { uint8_t merk; int off = testPositions[i]; - size_t pos; + std::size_t pos; if (off >= 0) { pos = off; } else { - pos = size - static_cast(-off); + pos = size - static_cast(-off); } if (pos >= size) { continue; @@ -488,8 +489,8 @@ void TestStringCopyCorrectnessCheckUtf8(uint8_t* src, uint8_t* dst, << std::endl; } -void TestSkipWhiteSpaceCorrectness(uint8_t* src, size_t size) { - size_t copied; +void TestSkipWhiteSpaceCorrectness(uint8_t* src, std::size_t size) { + std::size_t copied; std::cout << "Performing correctness tests for whitespace skipping..." << std::endl; @@ -502,11 +503,11 @@ void TestSkipWhiteSpaceCorrectness(uint8_t* src, size_t size) { i++) { uint8_t merk; int off = testPositions[i]; - size_t pos; + std::size_t pos; if (off >= 0) { pos = off; } else { - pos = size - static_cast(-off); + pos = size - static_cast(-off); } if (pos >= size) { continue; @@ -532,9 +533,9 @@ void TestSkipWhiteSpaceCorrectness(uint8_t* src, size_t size) { << " seconds." << std::endl; } -void RaceStringCopy(uint8_t* dst, uint8_t* src, size_t size, int repeat, - int& akku) { - size_t copied; +void RaceStringCopy(uint8_t* dst, uint8_t* src, std::size_t size, int repeat, + uint64_t& akku) { + std::size_t copied; std::cout << "\nNow racing for the repeated full string, " << "first target aligned...\n" << std::endl; @@ -582,9 +583,9 @@ void RaceStringCopy(uint8_t* dst, uint8_t* src, size_t size, int repeat, << (double)size * (double)repeat / totalTime.count() << std::endl; } -void RaceStringCopyCheckUtf8(uint8_t* dst, uint8_t* src, size_t size, - int repeat, int& akku) { - size_t copied; +void RaceStringCopyCheckUtf8(uint8_t* dst, uint8_t* src, std::size_t size, + int repeat, uint64_t& akku) { + std::size_t copied; std::cout << "\nNow racing for the repeated (check UTF8) full string, " << "first target aligned...\n" << std::endl; @@ -654,8 +655,8 @@ void RaceStringCopyCheckUtf8(uint8_t* dst, uint8_t* src, size_t size, << (double)size * (double)repeat / totalTime.count() << std::endl; } -void RaceSkipWhiteSpace(uint8_t* src, size_t size, int repeat, int& akku) { - size_t copied; +void RaceSkipWhiteSpace(uint8_t* src, std::size_t size, int repeat, uint64_t& akku) { + std::size_t copied; std::cout << "\nNow racing for the repeated full string...\n" << std::endl; @@ -709,18 +710,18 @@ int main(int argc, char* argv[]) { return 0; } - size_t size = atol(argv[1]); + std::size_t size = atol(argv[1]); int repeat = atoi(argv[2]); int docorrectness = atoi(argv[3]); - int akku = 0; + uint64_t akku = 0; std::cout << "Size: " << size << std::endl; std::cout << "Repeat:" << repeat << std::endl; - uint8_t* src = new uint8_t[size + 17]; + uint8_t* src = new uint8_t[size + 17 + 16]; uint8_t* dst = new uint8_t[size + 17]; std::cout << "Src pointer: " << (void*)src << std::endl; std::cout << "Dst pointer: " << (void*)dst << std::endl; - for (size_t i = 0; i < size + 16; i++) { + for (std::size_t i = 0; i < size + 16; i++) { src[i] = 'a' + (i % 26); } src[size + 16] = 0; @@ -741,7 +742,7 @@ int main(int argc, char* argv[]) { // Now do the whitespace skipping tests/measurements: static char const whitetab[17] = " \t \n \r"; - for (size_t i = 0; i < size + 16; i++) { + for (std::size_t i = 0; i < size + 16; i++) { src[i] = whitetab[i % 16]; } src[size + 16] = 0; diff --git a/3rdParty/velocypack/src/asm-functions.h b/3rdParty/velocypack/src/asm-functions.h index b4ed7a6b2e..15b01e2322 100644 --- a/3rdParty/velocypack/src/asm-functions.h +++ b/3rdParty/velocypack/src/asm-functions.h @@ -29,16 +29,16 @@ #include -extern size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, size_t); +extern std::size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, std::size_t); // Now a version which also stops at high bit set bytes: -extern size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t); +extern std::size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, std::size_t); // White space skipping: -extern size_t (*JSONSkipWhiteSpace)(uint8_t const*, size_t); +extern std::size_t (*JSONSkipWhiteSpace)(uint8_t const*, std::size_t); // check string for invalid utf-8 sequences -extern bool (*ValidateUtf8String)(uint8_t const*, size_t); +extern bool (*ValidateUtf8String)(uint8_t const*, std::size_t); namespace arangodb { namespace velocypack { diff --git a/3rdParty/velocypack/src/asm-utf8check.cpp b/3rdParty/velocypack/src/asm-utf8check.cpp index 6888e26d4b..cd3c900d5f 100644 --- a/3rdParty/velocypack/src/asm-utf8check.cpp +++ b/3rdParty/velocypack/src/asm-utf8check.cpp @@ -176,8 +176,8 @@ checkUTF8Bytes(__m128i current_bytes, struct processed_utf_bytes *previous, return pb; } -bool validate_utf8_fast_sse42(uint8_t const* src, size_t len) { - size_t i = 0; +bool validate_utf8_fast_sse42(uint8_t const* src, std::size_t len) { + std::size_t i = 0; __m128i has_error = _mm_setzero_si128(); struct processed_utf_bytes previous = {.rawbytes = _mm_setzero_si128(), .high_nibbles = _mm_setzero_si128(), @@ -408,8 +408,8 @@ avxcheckUTF8Bytes_asciipath(__m256i current_bytes, return pb; } -bool validate_utf8_fast_avx_asciipath(const char *src, size_t len) { - size_t i = 0; +bool validate_utf8_fast_avx_asciipath(const char *src, std::size_t len) { + std::size_t i = 0; __m256i has_error = _mm256_setzero_si256(); struct avx_processed_utf_bytes previous = { .rawbytes = _mm256_setzero_si256(), @@ -442,8 +442,8 @@ bool validate_utf8_fast_avx_asciipath(const char *src, size_t len) { return _mm256_testz_si256(has_error, has_error); } -bool validate_utf8_fast_avx(uint8_t const* src, size_t len) { - size_t i = 0; +bool validate_utf8_fast_avx(uint8_t const* src, std::size_t len) { + std::size_t i = 0; __m256i has_error = _mm256_setzero_si256(); struct avx_processed_utf_bytes previous = { .rawbytes = _mm256_setzero_si256(), diff --git a/3rdParty/velocypack/src/asm-utf8check.h b/3rdParty/velocypack/src/asm-utf8check.h index e1a3655bc9..d424660ac1 100644 --- a/3rdParty/velocypack/src/asm-utf8check.h +++ b/3rdParty/velocypack/src/asm-utf8check.h @@ -28,10 +28,10 @@ namespace arangodb { namespace velocypack { #if ASM_OPTIMIZATIONS == 1 -bool validate_utf8_fast_sse42(uint8_t const* src, size_t len); +bool validate_utf8_fast_sse42(uint8_t const* src, std::size_t len); #ifdef __AVX2__ -bool validate_utf8_fast_avx_asciipath(const char *src, size_t len); -bool validate_utf8_fast_avx(uint8_t const* src, size_t len); +bool validate_utf8_fast_avx_asciipath(const char *src, std::size_t len); +bool validate_utf8_fast_avx(uint8_t const* src, std::size_t len); #endif // __AVX2__ #endif // ASM_OPTIMIZATIONS diff --git a/arangod/Cluster/ClusterTrxMethods.cpp b/arangod/Cluster/ClusterTrxMethods.cpp index a5614a7fab..0446ed1455 100644 --- a/arangod/Cluster/ClusterTrxMethods.cpp +++ b/arangod/Cluster/ClusterTrxMethods.cpp @@ -59,13 +59,15 @@ void buildTransactionBody(TransactionState& state, ServerID const& server, builder.add("collections", VPackValue(VPackValueType::Object)); auto addCollections = [&](const char* key, AccessMode::Type t) { size_t numCollections = 0; - builder.add(key, VPackValue(VPackValueType::Array)); state.allCollections([&](TransactionCollection& col) { if (col.accessType() != t) { return true; } if (!state.isCoordinator()) { if (col.collection()->followers()->contains(server)) { + if (numCollections == 0) { + builder.add(key, VPackValue(VPackValueType::Array)); + } builder.add(VPackValue(col.collectionName())); numCollections++; } @@ -86,6 +88,9 @@ void buildTransactionBody(TransactionState& state, ServerID const& server, for (ShardID const& shard : *shards) { auto sss = ci->getResponsibleServer(shard); if (server == sss->at(0)) { + if (numCollections == 0) { + builder.add(key, VPackValue(VPackValueType::Array)); + } builder.add(VPackValue(shard)); numCollections++; } @@ -99,15 +104,17 @@ void buildTransactionBody(TransactionState& state, ServerID const& server, TRI_ASSERT(!pair.second.empty()); // only add shard where server is leader if (!pair.second.empty() && pair.second[0] == server) { + if (numCollections == 0) { + builder.add(key, VPackValue(VPackValueType::Array)); + } builder.add(VPackValue(pair.first)); numCollections++; } } return true; }); - builder.close(); - if (numCollections == 0) { - builder.removeLast(); // no need to keep empty vals + if (numCollections != 0) { + builder.close(); } }; addCollections("read", AccessMode::Type::READ); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5deb66e799..5426c66d30 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -78,6 +78,7 @@ set(LIB_ARANGO_VPACK ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/SliceStaticData.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/StringRef.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Utf8Helper.cpp + ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Value.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/ValueType.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Validator.cpp ${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Version.cpp