mirror of https://gitee.com/bigwinds/arangodb
upgrade velocypack library (#8926)
This commit is contained in:
parent
30e9fbafe0
commit
9c3fd26682
|
@ -28,13 +28,11 @@
|
|||
#define VELOCYPACK_ATTRIBUTETRANSLATOR_H 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
#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> _builder;
|
||||
std::unordered_map<StringRef, uint8_t const*> _keyToId;
|
||||
std::unordered_map<uint64_t, uint8_t const*> _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;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#ifndef VELOCYPACK_BASICS_H
|
||||
#define VELOCYPACK_BASICS_H 1
|
||||
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
namespace arangodb {
|
||||
|
|
|
@ -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<size_t>(that._size));
|
||||
memcpy(_buffer, that._buffer, static_cast<std::size_t>(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<size_t>(that._size));
|
||||
memcpy(_buffer, that._buffer, static_cast<std::size_t>(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<char> CharBuffer;
|
|||
|
||||
template<typename T>
|
||||
struct BufferNonDeleter {
|
||||
void operator()(Buffer<T>*) {
|
||||
}
|
||||
void operator()(Buffer<T>*) {}
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VELOCYPACK_BUILDER_H
|
||||
#define VELOCYPACK_BUILDER_H
|
||||
#define VELOCYPACK_BUILDER_H 1
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -100,131 +100,20 @@ class Builder {
|
|||
Options const* options;
|
||||
|
||||
// create an empty Builder, using default Options
|
||||
Builder()
|
||||
: _buffer(std::make_shared<Buffer<uint8_t>>()),
|
||||
_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<Buffer<uint8_t>>()),
|
||||
_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<Buffer<uint8_t>> 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<uint8_t>& buffer,
|
||||
Options const* options = &Options::Defaults)
|
||||
: _bufferPtr(nullptr),
|
||||
_pos(buffer.size()),
|
||||
_keyWritten(false),
|
||||
options(options) {
|
||||
_buffer.reset(&buffer, BufferNonDeleter<uint8_t>());
|
||||
_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<Buffer<uint8_t>>(*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<Buffer<uint8_t>>(*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<Buffer<uint8_t>> const& buffer() const { return _buffer; }
|
||||
|
@ -338,7 +227,7 @@ class Builder {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
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<Value>(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<Value>(attrName, attrLength, sub);
|
||||
}
|
||||
|
||||
|
@ -382,7 +271,7 @@ class Builder {
|
|||
inline uint8_t* add(char const* attrName, Slice const& sub) {
|
||||
return addInternal<Slice>(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<Slice>(attrName, attrLength, sub);
|
||||
}
|
||||
|
||||
|
@ -396,7 +285,7 @@ class Builder {
|
|||
inline uint8_t* add(char const* attrName, ValuePair const& sub) {
|
||||
return addInternal<ValuePair>(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<ValuePair>(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 <typename T>
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#define VELOCYPACK_ITERATOR_H 1
|
||||
|
||||
#include <iosfwd>
|
||||
#include <functional>
|
||||
|
||||
#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
|
||||
|
|
|
@ -28,10 +28,8 @@
|
|||
#define VELOCYPACK_OPTIONS_H 1
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
#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 {
|
||||
|
|
|
@ -80,8 +80,8 @@ class Parser {
|
|||
std::shared_ptr<Builder> _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<Builder> 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<Builder> 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<uint8_t const*>(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(); }
|
||||
|
||||
|
|
|
@ -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<size_t>(stringSliceLength()), seed);
|
||||
return VELOCYPACK_HASH(start(), static_cast<std::size_t>(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<typename T>
|
||||
Slice get(std::vector<T> 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<char const*>(_start + 1),
|
||||
static_cast<size_t>(length));
|
||||
static_cast<std::size_t>(length));
|
||||
}
|
||||
|
||||
if (h == 0xbf) {
|
||||
|
@ -696,7 +696,7 @@ class Slice {
|
|||
// short UTF-8 String
|
||||
ValueLength length = h - 0x40;
|
||||
return StringRef(reinterpret_cast<char const*>(_start + 1),
|
||||
static_cast<size_t>(length));
|
||||
static_cast<std::size_t>(length));
|
||||
}
|
||||
|
||||
if (h == 0xbf) {
|
||||
|
@ -746,7 +746,7 @@ class Slice {
|
|||
std::vector<uint8_t> out;
|
||||
ValueLength length = readIntegerNonEmpty<ValueLength>(_start + 1, h - 0xbf);
|
||||
checkOverflow(length);
|
||||
out.reserve(static_cast<size_t>(length));
|
||||
out.reserve(static_cast<std::size_t>(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<ValueLength>(_start + 1, offsetSize);
|
||||
|
@ -1092,7 +1091,7 @@ namespace std {
|
|||
// implementation of std::hash for a Slice object
|
||||
template <>
|
||||
struct hash<arangodb::velocypack::Slice> {
|
||||
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<arangodb::velocypack::Slice> {
|
|||
uint64_t const hash = slice.hash();
|
||||
return static_cast<uint32_t>(hash >> 32) ^ static_cast<uint32_t>(hash);
|
||||
#else
|
||||
return static_cast<size_t>(slice.hash());
|
||||
return static_cast<std::size_t>(slice.hash());
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#ifndef VELOCYPACK_STRINGREF_H
|
||||
#define VELOCYPACK_STRINGREF_H 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
@ -35,7 +34,6 @@
|
|||
#include <iosfwd>
|
||||
|
||||
#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<int>(_length) - static_cast<int>(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<int>(_length) - static_cast<int>(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<arangodb::velocypack::StringRef> {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<uint8_t const*>(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:
|
||||
|
|
|
@ -31,12 +31,11 @@
|
|||
#include <string>
|
||||
|
||||
#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; }
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef VELOCYPACK_VALUETYPE_H
|
||||
#define VELOCYPACK_VALUETYPE_H
|
||||
#define VELOCYPACK_VALUETYPE_H 1
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<Buffer<uint8_t>>()),
|
||||
_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<Buffer<uint8_t>>()),
|
||||
_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<Buffer<uint8_t>> 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<uint8_t>& buffer, Options const* options)
|
||||
: _bufferPtr(nullptr),
|
||||
_pos(buffer.size()),
|
||||
_keyWritten(false),
|
||||
options(options) {
|
||||
_buffer.reset(&buffer, BufferNonDeleter<uint8_t>());
|
||||
_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<Buffer<uint8_t>>(*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<Buffer<uint8_t>>(*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<ValueLength>& 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<ValueLength>& 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<ValueLength>& 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<ValueLength>& 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<ValueLength>& 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<ValueLength>& 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<ValueLength> 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<StringRef, LinearAttributeUniquenessCutoff> 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<StringRef> 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<size_t>(keyLength), length);
|
||||
std::size_t const compareLength =
|
||||
(std::min)(static_cast<std::size_t>(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<size_t>(keyLength), length);
|
||||
std::size_t const compareLength =
|
||||
(std::min)(static_cast<std::size_t>(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<size_t>(keyLength) != attribute.size()) {
|
||||
return false;
|
||||
}
|
||||
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
||||
return (static_cast<std::size_t>(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<size_t>(keyLength) != attribute.size()) {
|
||||
return false;
|
||||
}
|
||||
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
||||
return (static_cast<std::size_t>(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);
|
||||
}
|
||||
|
|
|
@ -24,16 +24,18 @@
|
|||
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#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<void*>(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<char const*>(memchr(static_cast<void const*>(_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<char const*>(::memrchrSwitch(static_cast<void const*>(_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<int>(_length) - static_cast<int>(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<int>(_length) - static_cast<int>(other._length);
|
||||
}
|
||||
|
||||
bool StringRef::equals(StringRef const& other) const noexcept {
|
||||
return (size() == other.size() &&
|
||||
(memcmp(data(), other.data(), size()) == 0));
|
||||
}
|
||||
|
||||
namespace arangodb {
|
||||
namespace velocypack {
|
||||
|
|
|
@ -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<std::size_t>(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<ValueLength>(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<ValueLength>(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<ValueLength>(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<size_t>(Slice(ptr).byteSize());
|
||||
void Validator::validateSliceLength(uint8_t const* ptr, std::size_t length, bool isSubPart) {
|
||||
std::size_t actual = static_cast<std::size_t>(Slice(ptr).byteSize());
|
||||
validateBufferLength(actual, length, isSubPart);
|
||||
}
|
||||
|
|
|
@ -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) {}
|
|
@ -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<ValueLength>(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<size_t>(x) > limit) {
|
||||
if (static_cast<std::size_t>(x) > limit) {
|
||||
x = static_cast<int>(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<int>(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<size_t>(-off);
|
||||
pos = size - static_cast<std::size_t>(-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<size_t>(-off);
|
||||
pos = size - static_cast<std::size_t>(-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<size_t>(-off);
|
||||
pos = size - static_cast<std::size_t>(-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;
|
||||
|
|
|
@ -29,16 +29,16 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue