1
0
Fork 0

upgrade velocypack library (#8926)

This commit is contained in:
Jan 2019-05-08 16:34:20 +02:00 committed by GitHub
parent 30e9fbafe0
commit 9c3fd26682
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 540 additions and 535 deletions

View File

@ -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;

View File

@ -27,7 +27,6 @@
#ifndef VELOCYPACK_BASICS_H
#define VELOCYPACK_BASICS_H 1
#include <cstring>
#include <new>
namespace arangodb {

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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; }

View File

@ -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

View File

@ -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 {

View File

@ -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(); }

View File

@ -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
}
};

View File

@ -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);
}
};

View File

@ -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:

View File

@ -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; }

View File

@ -25,7 +25,7 @@
////////////////////////////////////////////////////////////////////////////////
#ifndef VELOCYPACK_VALUETYPE_H
#define VELOCYPACK_VALUETYPE_H
#define VELOCYPACK_VALUETYPE_H 1
#include <iosfwd>

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);
}

43
3rdParty/velocypack/src/Value.cpp vendored Normal file
View File

@ -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) {}

View File

@ -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;

View File

@ -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 {

View File

@ -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(),

View File

@ -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

View File

@ -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);

View File

@ -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