mirror of https://gitee.com/bigwinds/arangodb
updated vpack library
This commit is contained in:
parent
e4a3c462c7
commit
d24b46bb71
|
@ -39,30 +39,21 @@ namespace arangodb {
|
|||
class Builder;
|
||||
|
||||
class AttributeTranslator {
|
||||
|
||||
public:
|
||||
|
||||
AttributeTranslator(AttributeTranslator const&) = delete;
|
||||
AttributeTranslator& operator=(AttributeTranslator const&) = delete;
|
||||
|
||||
AttributeTranslator ()
|
||||
: _builder(), _count(0) {
|
||||
}
|
||||
AttributeTranslator() : _builder(), _count(0) {}
|
||||
|
||||
~AttributeTranslator () {
|
||||
}
|
||||
~AttributeTranslator() {}
|
||||
|
||||
size_t count () const {
|
||||
return _count;
|
||||
}
|
||||
size_t count() const { return _count; }
|
||||
|
||||
void add(std::string const& key, uint64_t id);
|
||||
|
||||
void seal();
|
||||
|
||||
Builder* builder () {
|
||||
return _builder.get();
|
||||
}
|
||||
Builder* builder() { return _builder.get(); }
|
||||
|
||||
// translate from string to id
|
||||
uint8_t const* translate(std::string const& key) const;
|
||||
|
@ -74,7 +65,6 @@ namespace arangodb {
|
|||
uint8_t const* translate(uint64_t id) const;
|
||||
|
||||
private:
|
||||
|
||||
std::unique_ptr<Builder> _builder;
|
||||
std::unordered_map<std::string, uint8_t const*> _keyToId;
|
||||
std::unordered_map<uint64_t, uint8_t const*> _idToKey;
|
||||
|
|
|
@ -37,27 +37,19 @@ namespace arangodb {
|
|||
|
||||
template <typename T>
|
||||
class Buffer {
|
||||
|
||||
public:
|
||||
|
||||
Buffer ()
|
||||
: _buffer(_local),
|
||||
_alloc(sizeof(_local)),
|
||||
_pos(0) {
|
||||
Buffer() : _buffer(_local), _alloc(sizeof(_local)), _pos(0) {
|
||||
#ifdef VELOCYPACK_DEBUG
|
||||
// poison memory
|
||||
memset(_buffer, 0xa5, _alloc);
|
||||
#endif
|
||||
}
|
||||
|
||||
explicit Buffer (ValueLength expectedLength)
|
||||
: Buffer() {
|
||||
explicit Buffer(ValueLength expectedLength) : Buffer() {
|
||||
reserve(expectedLength);
|
||||
}
|
||||
|
||||
Buffer (Buffer const& that)
|
||||
: Buffer() {
|
||||
|
||||
Buffer(Buffer const& that) : Buffer() {
|
||||
if (that._pos > 0) {
|
||||
if (that._pos > sizeof(_local)) {
|
||||
_buffer = new T[that._pos];
|
||||
|
@ -84,15 +76,12 @@ namespace arangodb {
|
|||
return *this;
|
||||
}
|
||||
|
||||
Buffer (Buffer&& that)
|
||||
: Buffer() {
|
||||
|
||||
Buffer(Buffer&& that) : Buffer() {
|
||||
if (that._buffer == that._local) {
|
||||
memcpy(_buffer, that._buffer, that._pos);
|
||||
_pos = that._pos;
|
||||
that._pos = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_buffer = that._buffer;
|
||||
_alloc = that._alloc;
|
||||
_pos = that._pos;
|
||||
|
@ -102,34 +91,22 @@ namespace arangodb {
|
|||
}
|
||||
}
|
||||
|
||||
~Buffer () {
|
||||
reset();
|
||||
}
|
||||
~Buffer() { reset(); }
|
||||
|
||||
inline T* data () {
|
||||
return _buffer;
|
||||
}
|
||||
inline T* data() { return _buffer; }
|
||||
|
||||
inline T const* data () const {
|
||||
return _buffer;
|
||||
}
|
||||
inline T const* data() const { return _buffer; }
|
||||
|
||||
inline ValueLength size () const {
|
||||
return _pos;
|
||||
}
|
||||
inline ValueLength size() const { return _pos; }
|
||||
|
||||
inline ValueLength length () const {
|
||||
return _pos;
|
||||
}
|
||||
inline ValueLength length() const { return _pos; }
|
||||
|
||||
std::string toString() const {
|
||||
std::string result(reinterpret_cast<char const*>(_buffer), _pos);
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
void clear () {
|
||||
reset();
|
||||
}
|
||||
void clear() { reset(); }
|
||||
|
||||
void reset() {
|
||||
if (_buffer != _local) {
|
||||
|
@ -199,11 +176,7 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
inline ValueLength capacity () const {
|
||||
return _alloc;
|
||||
}
|
||||
|
||||
inline ValueLength capacity() const { return _alloc; }
|
||||
|
||||
T* _buffer;
|
||||
ValueLength _alloc;
|
||||
|
@ -211,7 +184,6 @@ namespace arangodb {
|
|||
|
||||
// an already initialized space for small values
|
||||
T _local[192];
|
||||
|
||||
};
|
||||
|
||||
typedef Buffer<char> CharBuffer;
|
||||
|
|
|
@ -46,7 +46,6 @@ namespace arangodb {
|
|||
namespace velocypack {
|
||||
|
||||
class Builder {
|
||||
|
||||
friend class Parser; // The parser needs access to internals.
|
||||
|
||||
public:
|
||||
|
@ -57,12 +56,9 @@ namespace arangodb {
|
|||
uint64_t offset;
|
||||
};
|
||||
|
||||
void reserve (ValueLength len) {
|
||||
reserveSpace(len);
|
||||
}
|
||||
void reserve(ValueLength len) { reserveSpace(len); }
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<Buffer<uint8_t>> _buffer; // Here we collect the result
|
||||
uint8_t* _start; // Always points to the start of _buffer
|
||||
ValueLength _size; // Always contains the size of _buffer
|
||||
|
@ -126,33 +122,28 @@ namespace arangodb {
|
|||
std::vector<ValueLength>& offsets);
|
||||
|
||||
public:
|
||||
|
||||
Options const* options;
|
||||
|
||||
// Constructor and destructor:
|
||||
explicit Builder (std::shared_ptr<Buffer<uint8_t>>& buffer, Options const* options = &Options::Defaults)
|
||||
: _buffer(buffer),
|
||||
_pos(0),
|
||||
options(options) {
|
||||
explicit Builder(std::shared_ptr<Buffer<uint8_t>>& buffer,
|
||||
Options const* options = &Options::Defaults)
|
||||
: _buffer(buffer), _pos(0), options(options) {
|
||||
if (_buffer.get() == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer cannot be a nullptr");
|
||||
}
|
||||
_start = _buffer->data();
|
||||
_size = _buffer->size();
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
explicit Builder(Options const* options = &Options::Defaults)
|
||||
: _buffer(new Buffer<uint8_t>()),
|
||||
_pos(0),
|
||||
options(options) {
|
||||
: _buffer(new Buffer<uint8_t>()), _pos(0), options(options) {
|
||||
_start = _buffer->data();
|
||||
_size = _buffer->size();
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
|
@ -160,21 +151,26 @@ namespace arangodb {
|
|||
|
||||
// The rule of five:
|
||||
|
||||
~Builder () {
|
||||
}
|
||||
~Builder() {}
|
||||
|
||||
Builder(Builder const& that)
|
||||
: _buffer(that._buffer), _start(_buffer->data()), _size(_buffer->size()), _pos(that._pos),
|
||||
_stack(that._stack), _index(that._index), options(that.options) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
: _buffer(that._buffer),
|
||||
_start(_buffer->data()),
|
||||
_size(_buffer->size()),
|
||||
_pos(that._pos),
|
||||
_stack(that._stack),
|
||||
_index(that._index),
|
||||
options(that.options) {
|
||||
if (that._buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
}
|
||||
|
||||
Builder& operator=(Builder const& that) {
|
||||
if (that._buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
_buffer = that._buffer;
|
||||
_start = _buffer->data();
|
||||
|
@ -183,13 +179,13 @@ namespace arangodb {
|
|||
_stack = that._stack;
|
||||
_index = that._index;
|
||||
options = that.options;
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Builder(Builder&& that) {
|
||||
if (that._buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
_buffer = that._buffer;
|
||||
that._buffer.reset();
|
||||
|
@ -201,7 +197,6 @@ namespace arangodb {
|
|||
_index.clear();
|
||||
_index.swap(that._index);
|
||||
options = that.options;
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
that._start = nullptr;
|
||||
that._size = 0;
|
||||
that._pos = 0;
|
||||
|
@ -209,7 +204,8 @@ namespace arangodb {
|
|||
|
||||
Builder& operator=(Builder&& that) {
|
||||
if (that._buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
_buffer = that._buffer;
|
||||
that._buffer.reset();
|
||||
|
@ -221,7 +217,6 @@ namespace arangodb {
|
|||
_index.clear();
|
||||
_index.swap(that._index);
|
||||
options = that.options;
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
that._start = nullptr;
|
||||
that._size = 0;
|
||||
that._pos = 0;
|
||||
|
@ -229,13 +224,12 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
// get a const reference to the Builder's Buffer object
|
||||
std::shared_ptr<Buffer<uint8_t>> const& buffer () const {
|
||||
return _buffer;
|
||||
}
|
||||
std::shared_ptr<Buffer<uint8_t>> const& buffer() const { return _buffer; }
|
||||
|
||||
uint8_t const* data() const {
|
||||
if (_buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
|
||||
return _buffer.get()->data();
|
||||
|
@ -244,12 +238,13 @@ namespace arangodb {
|
|||
std::string toString() const;
|
||||
|
||||
// get a non-const reference to the Builder's Buffer object
|
||||
std::shared_ptr<Buffer<uint8_t>>& buffer () {
|
||||
return _buffer;
|
||||
}
|
||||
std::shared_ptr<Buffer<uint8_t>>& buffer() { return _buffer; }
|
||||
|
||||
static Builder clone (Slice const& slice, Options const* options = &Options::Defaults) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
static Builder clone(Slice const& slice,
|
||||
Options const* options = &Options::Defaults) {
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
|
||||
Builder b(options);
|
||||
b.add(slice);
|
||||
|
@ -271,9 +266,7 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
// Return a Slice of the result:
|
||||
Slice slice () const {
|
||||
return Slice(start(), options);
|
||||
}
|
||||
Slice slice() const { return Slice(start(), options); }
|
||||
|
||||
// Compute the actual size here, but only when sealed
|
||||
ValueLength size() const {
|
||||
|
@ -283,9 +276,7 @@ namespace arangodb {
|
|||
return _pos;
|
||||
}
|
||||
|
||||
bool isClosed () const throw() {
|
||||
return _stack.empty();
|
||||
}
|
||||
bool isClosed() const throw() { return _stack.empty(); }
|
||||
|
||||
// Add a subvalue into an object from a Value:
|
||||
uint8_t* add(std::string const& attrName, Value const& sub);
|
||||
|
@ -391,12 +382,10 @@ namespace arangodb {
|
|||
if (v >= 0 && v <= 9) {
|
||||
reserveSpace(1);
|
||||
_start[_pos++] = static_cast<uint8_t>(0x30 + v);
|
||||
}
|
||||
else if (v < 0 && v >= -6) {
|
||||
} else if (v < 0 && v >= -6) {
|
||||
reserveSpace(1);
|
||||
_start[_pos++] = static_cast<uint8_t>(0x40 + v);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
appendInt(v, 0x1f);
|
||||
}
|
||||
}
|
||||
|
@ -405,8 +394,7 @@ namespace arangodb {
|
|||
if (v <= 9) {
|
||||
reserveSpace(1);
|
||||
_start[_pos++] = static_cast<uint8_t>(0x30 + v);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
appendUInt(v, 0x27);
|
||||
}
|
||||
}
|
||||
|
@ -426,8 +414,7 @@ namespace arangodb {
|
|||
_start[_pos++] = 0xbf;
|
||||
// write string length
|
||||
appendLength(strLen, 8);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// short string
|
||||
_start[_pos++] = static_cast<uint8_t>(0x40 + strLen);
|
||||
}
|
||||
|
@ -440,40 +427,64 @@ namespace arangodb {
|
|||
addCompoundValue(unindexed ? 0x13 : 0x06);
|
||||
}
|
||||
|
||||
// this is an alias for addArray()
|
||||
inline void openArray(bool unindexed = false) {
|
||||
addCompoundValue(unindexed ? 0x13 : 0x06);
|
||||
}
|
||||
|
||||
inline void addObject(bool unindexed = false) {
|
||||
addCompoundValue(unindexed ? 0x14 : 0x0b);
|
||||
}
|
||||
|
||||
private:
|
||||
// this is an alias for addObject()
|
||||
inline void openObject(bool unindexed = false) {
|
||||
addCompoundValue(unindexed ? 0x14 : 0x0b);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
uint8_t* addInternal(T const& sub) {
|
||||
bool haveReported = false;
|
||||
if (!_stack.empty()) {
|
||||
ValueLength& tos = _stack.back();
|
||||
if (_start[tos] != 0x06 && _start[tos] != 0x13) {
|
||||
throw Exception(Exception::BuilderNeedOpenArray);
|
||||
}
|
||||
reportAdd(tos);
|
||||
haveReported = true;
|
||||
}
|
||||
try {
|
||||
return set(sub);
|
||||
} catch (...) {
|
||||
// clean up in case of an exception
|
||||
if (haveReported) {
|
||||
cleanupAdd();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint8_t* addInternal(std::string const& attrName, T const& sub) {
|
||||
bool haveReported = false;
|
||||
if (!_stack.empty()) {
|
||||
ValueLength& tos = _stack.back();
|
||||
if (_start[tos] != 0x0b && _start[tos] != 0x14) {
|
||||
throw Exception(Exception::BuilderNeedOpenObject);
|
||||
}
|
||||
reportAdd(tos);
|
||||
haveReported = true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (options->attributeTranslator != nullptr) {
|
||||
// check if a translation for the attribute name exists
|
||||
uint8_t const* translated = options->attributeTranslator->translate(attrName);
|
||||
uint8_t const* translated =
|
||||
options->attributeTranslator->translate(attrName);
|
||||
|
||||
if (translated != nullptr) {
|
||||
set(Slice(options->attributeTranslator->translate(attrName), options));
|
||||
set(Slice(options->attributeTranslator->translate(attrName),
|
||||
options));
|
||||
return set(sub);
|
||||
}
|
||||
// otherwise fall through to regular behavior
|
||||
|
@ -481,6 +492,13 @@ namespace arangodb {
|
|||
|
||||
set(Value(attrName, ValueType::String));
|
||||
return set(sub);
|
||||
} catch (...) {
|
||||
// clean up in case of an exception
|
||||
if (haveReported) {
|
||||
cleanupAdd();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void addCompoundValue(uint8_t type) {
|
||||
|
@ -502,6 +520,11 @@ namespace arangodb {
|
|||
|
||||
uint8_t* set(Slice const& item);
|
||||
|
||||
void cleanupAdd() {
|
||||
size_t depth = _stack.size() - 1;
|
||||
_index[depth].pop_back();
|
||||
}
|
||||
|
||||
void reportAdd(ValueLength base) {
|
||||
size_t depth = _stack.size() - 1;
|
||||
_index[depth].push_back(_pos - base);
|
||||
|
@ -523,8 +546,7 @@ namespace arangodb {
|
|||
vSize++;
|
||||
_start[_pos++] = static_cast<uint8_t>(v & 0xff);
|
||||
v >>= 8;
|
||||
}
|
||||
while (v != 0);
|
||||
} while (v != 0);
|
||||
_start[save] = base + vSize;
|
||||
}
|
||||
|
||||
|
@ -540,8 +562,7 @@ namespace arangodb {
|
|||
do {
|
||||
xSize++;
|
||||
x >>= 8;
|
||||
}
|
||||
while (x >= 0x80);
|
||||
} while (x >= 0x80);
|
||||
return xSize + 1;
|
||||
}
|
||||
|
||||
|
@ -550,8 +571,7 @@ namespace arangodb {
|
|||
uint64_t x;
|
||||
if (vSize == 8) {
|
||||
x = toUInt64(v);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int64_t shift = 1LL << (vSize * 8 - 1); // will never overflow!
|
||||
x = v >= 0 ? static_cast<uint64_t>(v)
|
||||
: static_cast<uint64_t>(v + shift) + shift;
|
||||
|
|
|
@ -40,51 +40,63 @@ namespace arangodb {
|
|||
namespace velocypack {
|
||||
|
||||
class Collection {
|
||||
|
||||
public:
|
||||
|
||||
enum VisitationOrder {
|
||||
PreOrder = 1,
|
||||
PostOrder = 2
|
||||
};
|
||||
enum VisitationOrder { PreOrder = 1, PostOrder = 2 };
|
||||
|
||||
Collection() = delete;
|
||||
Collection(Collection const&) = delete;
|
||||
Collection& operator=(Collection const&) = delete;
|
||||
|
||||
static void forEach (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static void forEach(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static void forEach (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static void forEach(
|
||||
Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return forEach(*slice, cb);
|
||||
}
|
||||
|
||||
static Builder filter (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static Builder filter(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static Builder filter (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static Builder filter(
|
||||
Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return filter(*slice, cb);
|
||||
}
|
||||
|
||||
static Slice find (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static Slice find(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static Slice find (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static Slice find(Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return find(*slice, cb);
|
||||
}
|
||||
|
||||
static bool contains (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static bool contains(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static bool contains (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static bool contains(
|
||||
Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return contains(*slice, cb);
|
||||
}
|
||||
|
||||
static bool all (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static bool all(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static bool all (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static bool all(Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return all(*slice, cb);
|
||||
}
|
||||
|
||||
static bool any (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
static bool any(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
static bool any (Slice const* slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
static bool any(Slice const* slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
return any(*slice, cb);
|
||||
}
|
||||
|
||||
|
@ -102,49 +114,60 @@ namespace arangodb {
|
|||
|
||||
static void keys(Slice const& slice, std::unordered_set<std::string>& result);
|
||||
|
||||
static void keys (Slice const* slice, std::unordered_set<std::string>& result) {
|
||||
static void keys(Slice const* slice,
|
||||
std::unordered_set<std::string>& result) {
|
||||
return keys(*slice, result);
|
||||
}
|
||||
|
||||
static Builder values(Slice const& slice);
|
||||
|
||||
static Builder values (Slice const* slice) {
|
||||
return values(*slice);
|
||||
}
|
||||
static Builder values(Slice const* slice) { return values(*slice); }
|
||||
|
||||
static Builder keep(Slice const& slice, std::vector<std::string> const& keys);
|
||||
|
||||
static Builder keep (Slice const& slice, std::unordered_set<std::string> const& keys);
|
||||
static Builder keep(Slice const& slice,
|
||||
std::unordered_set<std::string> const& keys);
|
||||
|
||||
static Builder keep (Slice const* slice, std::vector<std::string> const& keys) {
|
||||
static Builder keep(Slice const* slice,
|
||||
std::vector<std::string> const& keys) {
|
||||
return keep(*slice, keys);
|
||||
}
|
||||
|
||||
static Builder keep (Slice const* slice, std::unordered_set<std::string> const& keys) {
|
||||
static Builder keep(Slice const* slice,
|
||||
std::unordered_set<std::string> const& keys) {
|
||||
return keep(*slice, keys);
|
||||
}
|
||||
|
||||
static Builder remove (Slice const& slice, std::vector<std::string> const& keys);
|
||||
static Builder remove(Slice const& slice,
|
||||
std::vector<std::string> const& keys);
|
||||
|
||||
static Builder remove (Slice const& slice, std::unordered_set<std::string> const& keys);
|
||||
static Builder remove(Slice const& slice,
|
||||
std::unordered_set<std::string> const& keys);
|
||||
|
||||
static Builder remove (Slice const* slice, std::vector<std::string> const& keys) {
|
||||
static Builder remove(Slice const* slice,
|
||||
std::vector<std::string> const& keys) {
|
||||
return remove(*slice, keys);
|
||||
}
|
||||
|
||||
static Builder remove (Slice const* slice, std::unordered_set<std::string> const& keys) {
|
||||
static Builder remove(Slice const* slice,
|
||||
std::unordered_set<std::string> const& keys) {
|
||||
return remove(*slice, keys);
|
||||
}
|
||||
|
||||
static Builder merge(Slice const& left, Slice const& right, bool mergeValues);
|
||||
|
||||
static Builder merge (Slice const* left, Slice const* right, bool mergeValues) {
|
||||
static Builder merge(Slice const* left, Slice const* right,
|
||||
bool mergeValues) {
|
||||
return merge(*left, *right, mergeValues);
|
||||
}
|
||||
|
||||
static void visitRecursive (Slice const& slice, VisitationOrder order, std::function<bool(Slice const&, Slice const&)> const& func);
|
||||
static void visitRecursive(
|
||||
Slice const& slice, VisitationOrder order,
|
||||
std::function<bool(Slice const&, Slice const&)> const& func);
|
||||
|
||||
static void visitRecursive (Slice const* slice, VisitationOrder order, std::function<bool(Slice const&, Slice const&)> const& func) {
|
||||
static void visitRecursive(
|
||||
Slice const* slice, VisitationOrder order,
|
||||
std::function<bool(Slice const&, Slice const&)> const& func) {
|
||||
visitRecursive(*slice, order, func);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -40,9 +40,7 @@ namespace arangodb {
|
|||
|
||||
// Dumps VPack into a JSON output string
|
||||
class Dumper {
|
||||
|
||||
public:
|
||||
|
||||
Options const* options;
|
||||
|
||||
Dumper(Dumper const&) = delete;
|
||||
|
@ -50,18 +48,17 @@ namespace arangodb {
|
|||
|
||||
Dumper(Sink* sink, Options const* options = &Options::Defaults)
|
||||
: options(options), _sink(sink), _indentation(0) {
|
||||
|
||||
if (sink == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Sink cannot be a nullptr");
|
||||
}
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
~Dumper () {
|
||||
}
|
||||
~Dumper() {}
|
||||
|
||||
Sink* sink () const {
|
||||
return _sink;
|
||||
}
|
||||
Sink* sink() const { return _sink; }
|
||||
|
||||
void dump(Slice const& slice) {
|
||||
_indentation = 0;
|
||||
|
@ -69,37 +66,35 @@ namespace arangodb {
|
|||
dumpValue(&slice);
|
||||
}
|
||||
|
||||
void dump (Slice const* slice) {
|
||||
dump(*slice);
|
||||
}
|
||||
void dump(Slice const* slice) { dump(*slice); }
|
||||
|
||||
static void dump (Slice const& slice, Sink* sink, Options const* options = &Options::Defaults) {
|
||||
static void dump(Slice const& slice, Sink* sink,
|
||||
Options const* options = &Options::Defaults) {
|
||||
Dumper dumper(sink, options);
|
||||
dumper.dump(slice);
|
||||
}
|
||||
|
||||
static void dump (Slice const* slice, Sink* sink, Options const* options = &Options::Defaults) {
|
||||
static void dump(Slice const* slice, Sink* sink,
|
||||
Options const* options = &Options::Defaults) {
|
||||
dump(*slice, sink, options);
|
||||
}
|
||||
|
||||
static std::string toString (Slice const& slice, Options const* options = &Options::Defaults) {
|
||||
static std::string toString(Slice const& slice,
|
||||
Options const* options = &Options::Defaults) {
|
||||
std::string buffer;
|
||||
StringSink sink(&buffer);
|
||||
dump(slice, &sink, options);
|
||||
return std::move(buffer);
|
||||
}
|
||||
|
||||
static std::string toString (Slice const* slice, Options const* options = &Options::Defaults) {
|
||||
static std::string toString(Slice const* slice,
|
||||
Options const* options = &Options::Defaults) {
|
||||
return std::move(toString(*slice, options));
|
||||
}
|
||||
|
||||
void append (Slice const& slice) {
|
||||
dumpValue(&slice);
|
||||
}
|
||||
void append(Slice const& slice) { dumpValue(&slice); }
|
||||
|
||||
void append (Slice const* slice) {
|
||||
dumpValue(slice);
|
||||
}
|
||||
void append(Slice const* slice) { dumpValue(slice); }
|
||||
|
||||
void appendString(char const* src, ValueLength len) {
|
||||
_sink->reserve(2 + len);
|
||||
|
@ -118,7 +113,6 @@ namespace arangodb {
|
|||
void appendUInt(uint64_t);
|
||||
|
||||
private:
|
||||
|
||||
void dumpInteger(Slice const*);
|
||||
|
||||
void dumpString(char const*, ValueLength);
|
||||
|
@ -147,11 +141,9 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
Sink* _sink;
|
||||
|
||||
int _indentation;
|
||||
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace arangodb {
|
|||
BuilderUnexpectedType = 34,
|
||||
BuilderUnexpectedValue = 35,
|
||||
BuilderNeedSubvalue = 36,
|
||||
BuilderExternalsDisallowed = 37,
|
||||
|
||||
UnknownError = 999
|
||||
};
|
||||
|
@ -73,23 +74,16 @@ namespace arangodb {
|
|||
std::string _msg;
|
||||
|
||||
public:
|
||||
Exception(ExceptionType type, std::string const& msg)
|
||||
: _type(type), _msg(msg) {}
|
||||
|
||||
Exception (ExceptionType type, std::string const& msg) : _type(type), _msg(msg) {
|
||||
}
|
||||
Exception(ExceptionType type, char const* msg) : _type(type), _msg(msg) {}
|
||||
|
||||
Exception (ExceptionType type, char const* msg) : _type(type), _msg(msg) {
|
||||
}
|
||||
explicit Exception(ExceptionType type) : Exception(type, message(type)) {}
|
||||
|
||||
explicit Exception (ExceptionType type) : Exception(type, message(type)) {
|
||||
}
|
||||
char const* what() const throw() { return _msg.c_str(); }
|
||||
|
||||
char const* what() const throw() {
|
||||
return _msg.c_str();
|
||||
}
|
||||
|
||||
ExceptionType errorCode () const throw() {
|
||||
return _type;
|
||||
}
|
||||
ExceptionType errorCode() const throw() { return _type; }
|
||||
|
||||
static char const* message(ExceptionType type) throw() {
|
||||
switch (type) {
|
||||
|
@ -137,13 +131,14 @@ namespace arangodb {
|
|||
return "Unexpected type";
|
||||
case BuilderUnexpectedValue:
|
||||
return "Unexpected value";
|
||||
case BuilderExternalsDisallowed:
|
||||
return "Externals are not allowed in this configuration";
|
||||
|
||||
case UnknownError:
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -40,13 +40,13 @@ namespace arangodb {
|
|||
struct HexDump {
|
||||
HexDump() = delete;
|
||||
|
||||
HexDump (Slice const& slice, int valuesPerLine = 16, std::string const& separator = " ")
|
||||
: slice(slice), valuesPerLine(valuesPerLine), separator(separator) {
|
||||
}
|
||||
HexDump(Slice const& slice, int valuesPerLine = 16,
|
||||
std::string const& separator = " ")
|
||||
: slice(slice), valuesPerLine(valuesPerLine), separator(separator) {}
|
||||
|
||||
HexDump (Slice const* slice, int valuesPerLine = 16, std::string const& separator = " ")
|
||||
: HexDump(*slice, valuesPerLine, separator) {
|
||||
}
|
||||
HexDump(Slice const* slice, int valuesPerLine = 16,
|
||||
std::string const& separator = " ")
|
||||
: HexDump(*slice, valuesPerLine, separator) {}
|
||||
|
||||
static std::string toHex(uint8_t value);
|
||||
|
||||
|
|
|
@ -39,14 +39,11 @@ namespace arangodb {
|
|||
namespace velocypack {
|
||||
|
||||
class ArrayIterator {
|
||||
|
||||
public:
|
||||
|
||||
ArrayIterator() = delete;
|
||||
|
||||
ArrayIterator(Slice const& slice)
|
||||
: _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) {
|
||||
|
||||
if (slice.type() != ValueType::Array) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Array slice");
|
||||
}
|
||||
|
@ -57,8 +54,10 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
ArrayIterator(ArrayIterator const& other)
|
||||
: _slice(other._slice), _size(other._size), _position(other._position), _current(other._current) {
|
||||
}
|
||||
: _slice(other._slice),
|
||||
_size(other._size),
|
||||
_position(other._position),
|
||||
_current(other._current) {}
|
||||
|
||||
ArrayIterator& operator=(ArrayIterator const& other) {
|
||||
_slice = other._slice;
|
||||
|
@ -73,8 +72,7 @@ namespace arangodb {
|
|||
++_position;
|
||||
if (_position <= _size && _current != nullptr) {
|
||||
_current += Slice(_current, _slice.options).byteSize();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_current = nullptr;
|
||||
}
|
||||
return *this;
|
||||
|
@ -98,13 +96,9 @@ namespace arangodb {
|
|||
return _slice.at(_position);
|
||||
}
|
||||
|
||||
ArrayIterator begin () {
|
||||
return ArrayIterator(_slice);
|
||||
}
|
||||
ArrayIterator begin() { return ArrayIterator(_slice); }
|
||||
|
||||
ArrayIterator begin () const {
|
||||
return ArrayIterator(_slice);
|
||||
}
|
||||
ArrayIterator begin() const { return ArrayIterator(_slice); }
|
||||
|
||||
ArrayIterator end() {
|
||||
auto it = ArrayIterator(_slice);
|
||||
|
@ -118,9 +112,7 @@ namespace arangodb {
|
|||
return it;
|
||||
}
|
||||
|
||||
inline bool valid () const throw() {
|
||||
return (_position < _size);
|
||||
}
|
||||
inline bool valid() const throw() { return (_position < _size); }
|
||||
|
||||
inline Slice value() const {
|
||||
if (_position >= _size) {
|
||||
|
@ -134,24 +126,15 @@ namespace arangodb {
|
|||
return valid();
|
||||
}
|
||||
|
||||
inline ValueLength index () const throw() {
|
||||
return _position;
|
||||
}
|
||||
inline ValueLength index() const throw() { return _position; }
|
||||
|
||||
inline ValueLength size () const throw() {
|
||||
return _size;
|
||||
}
|
||||
inline ValueLength size() const throw() { return _size; }
|
||||
|
||||
inline bool isFirst () const throw() {
|
||||
return (_position == 0);
|
||||
}
|
||||
inline bool isFirst() const throw() { return (_position == 0); }
|
||||
|
||||
inline bool isLast () const throw() {
|
||||
return (_position + 1 >= _size);
|
||||
}
|
||||
inline bool isLast() const throw() { return (_position + 1 >= _size); }
|
||||
|
||||
private:
|
||||
|
||||
Slice _slice;
|
||||
ValueLength _size;
|
||||
ValueLength _position;
|
||||
|
@ -159,13 +142,9 @@ namespace arangodb {
|
|||
};
|
||||
|
||||
class ObjectIterator {
|
||||
|
||||
public:
|
||||
|
||||
struct ObjectPair {
|
||||
ObjectPair (Slice const& key, Slice const& value)
|
||||
: key(key), value(value) {
|
||||
}
|
||||
ObjectPair(Slice const& key, Slice const& value) : key(key), value(value) {}
|
||||
Slice const key;
|
||||
Slice const value;
|
||||
};
|
||||
|
@ -174,7 +153,6 @@ namespace arangodb {
|
|||
|
||||
ObjectIterator(Slice const& slice)
|
||||
: _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) {
|
||||
|
||||
if (slice.type() != ValueType::Object) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Object slice");
|
||||
}
|
||||
|
@ -185,8 +163,10 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
ObjectIterator(ObjectIterator const& other)
|
||||
: _slice(other._slice), _size(other._size), _position(other._position), _current(other._current) {
|
||||
}
|
||||
: _slice(other._slice),
|
||||
_size(other._size),
|
||||
_position(other._position),
|
||||
_current(other._current) {}
|
||||
|
||||
ObjectIterator& operator=(ObjectIterator const& other) {
|
||||
_slice = other._slice;
|
||||
|
@ -204,8 +184,7 @@ namespace arangodb {
|
|||
_current += Slice(_current, _slice.options).byteSize();
|
||||
// skip over value
|
||||
_current += Slice(_current, _slice.options).byteSize();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_current = nullptr;
|
||||
}
|
||||
return *this;
|
||||
|
@ -230,13 +209,9 @@ namespace arangodb {
|
|||
return ObjectPair(_slice.keyAt(_position), _slice.valueAt(_position));
|
||||
}
|
||||
|
||||
ObjectIterator begin () {
|
||||
return ObjectIterator(_slice);
|
||||
}
|
||||
ObjectIterator begin() { return ObjectIterator(_slice); }
|
||||
|
||||
ObjectIterator begin () const {
|
||||
return ObjectIterator(_slice);
|
||||
}
|
||||
ObjectIterator begin() const { return ObjectIterator(_slice); }
|
||||
|
||||
ObjectIterator end() {
|
||||
auto it = ObjectIterator(_slice);
|
||||
|
@ -250,9 +225,7 @@ namespace arangodb {
|
|||
return it;
|
||||
}
|
||||
|
||||
inline bool valid () const throw() {
|
||||
return (_position < _size);
|
||||
}
|
||||
inline bool valid() const throw() { return (_position < _size); }
|
||||
|
||||
inline Slice key() const {
|
||||
if (_position >= _size) {
|
||||
|
@ -280,24 +253,15 @@ namespace arangodb {
|
|||
return valid();
|
||||
}
|
||||
|
||||
inline ValueLength index () const throw() {
|
||||
return _position;
|
||||
}
|
||||
inline ValueLength index() const throw() { return _position; }
|
||||
|
||||
inline ValueLength size () const throw() {
|
||||
return _size;
|
||||
}
|
||||
inline ValueLength size() const throw() { return _size; }
|
||||
|
||||
inline bool isFirst () const throw() {
|
||||
return (_position == 0);
|
||||
}
|
||||
inline bool isFirst() const throw() { return (_position == 0); }
|
||||
|
||||
inline bool isLast () const throw() {
|
||||
return (_position + 1 >= _size);
|
||||
}
|
||||
inline bool isLast() const throw() { return (_position + 1 >= _size); }
|
||||
|
||||
private:
|
||||
|
||||
Slice _slice;
|
||||
ValueLength _size;
|
||||
ValueLength _position;
|
||||
|
@ -307,12 +271,16 @@ namespace arangodb {
|
|||
} // namespace arangodb::velocypack
|
||||
} // namespace arangodb
|
||||
|
||||
std::ostream& operator<< (std::ostream&, arangodb::velocypack::ArrayIterator const*);
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
arangodb::velocypack::ArrayIterator const*);
|
||||
|
||||
std::ostream& operator<< (std::ostream&, arangodb::velocypack::ArrayIterator const&);
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
arangodb::velocypack::ArrayIterator const&);
|
||||
|
||||
std::ostream& operator<< (std::ostream&, arangodb::velocypack::ObjectIterator const*);
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
arangodb::velocypack::ObjectIterator const*);
|
||||
|
||||
std::ostream& operator<< (std::ostream&, arangodb::velocypack::ObjectIterator const&);
|
||||
std::ostream& operator<<(std::ostream&,
|
||||
arangodb::velocypack::ObjectIterator const&);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,17 +39,16 @@ namespace arangodb {
|
|||
class Slice;
|
||||
|
||||
struct AttributeExcludeHandler {
|
||||
virtual ~AttributeExcludeHandler () {
|
||||
}
|
||||
virtual ~AttributeExcludeHandler() {}
|
||||
|
||||
virtual bool shouldExclude(Slice const& key, int nesting) = 0;
|
||||
};
|
||||
|
||||
struct CustomTypeHandler {
|
||||
virtual ~CustomTypeHandler () {
|
||||
}
|
||||
virtual ~CustomTypeHandler() {}
|
||||
|
||||
virtual void toJson (Slice const& value, Dumper* dumper, Slice const& base) = 0;
|
||||
virtual void toJson(Slice const& value, Dumper* dumper,
|
||||
Slice const& base) = 0;
|
||||
virtual ValueLength byteSize(Slice const& value) = 0;
|
||||
};
|
||||
|
||||
|
@ -59,8 +58,7 @@ namespace arangodb {
|
|||
FailOnUnsupportedType
|
||||
};
|
||||
|
||||
Options () {
|
||||
}
|
||||
Options() {}
|
||||
|
||||
// Dumper behavior when a VPack value is serialized to JSON that
|
||||
// has no JSON equivalent
|
||||
|
@ -103,6 +101,10 @@ namespace arangodb {
|
|||
// JSON with a Dumper
|
||||
bool escapeForwardSlashes = false;
|
||||
|
||||
// disallow using type External (to prevent injection of arbitrary pointer
|
||||
// values as a security precaution)
|
||||
bool disallowExternals = false;
|
||||
|
||||
// default options with the above settings
|
||||
static Options Defaults;
|
||||
};
|
||||
|
|
|
@ -41,16 +41,11 @@ namespace arangodb {
|
|||
namespace velocypack {
|
||||
|
||||
class Parser {
|
||||
|
||||
// This class can parse JSON very rapidly, but only from contiguous
|
||||
// blocks of memory. It builds the result using the Builder.
|
||||
|
||||
struct ParsedNumber {
|
||||
ParsedNumber ()
|
||||
: intValue(0),
|
||||
doubleValue(0.0),
|
||||
isInteger(true) {
|
||||
}
|
||||
ParsedNumber() : intValue(0), doubleValue(0.0), isInteger(true) {}
|
||||
|
||||
void addDigit(int i) {
|
||||
if (isInteger) {
|
||||
|
@ -91,7 +86,6 @@ namespace arangodb {
|
|||
int _nesting;
|
||||
|
||||
public:
|
||||
|
||||
Options const* options;
|
||||
|
||||
Parser(Parser const&) = delete;
|
||||
|
@ -99,7 +93,6 @@ namespace arangodb {
|
|||
|
||||
Parser(Options const* options = &Options::Defaults)
|
||||
: _start(nullptr), _size(0), _pos(0), _nesting(0), options(options) {
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
|
@ -108,29 +101,30 @@ namespace arangodb {
|
|||
_b.options = options;
|
||||
}
|
||||
|
||||
static Builder fromJson (std::string const& json, Options const* options = &Options::Defaults) {
|
||||
static Builder fromJson(std::string const& json,
|
||||
Options const* options = &Options::Defaults) {
|
||||
Parser parser(options);
|
||||
parser.parse(json);
|
||||
return parser.steal();
|
||||
}
|
||||
|
||||
static Builder fromJson (uint8_t const* start, size_t size, Options const* options = &Options::Defaults) {
|
||||
static Builder fromJson(uint8_t const* start, size_t size,
|
||||
Options const* options = &Options::Defaults) {
|
||||
Parser parser(options);
|
||||
parser.parse(start, size);
|
||||
return parser.steal();
|
||||
}
|
||||
|
||||
ValueLength parse(std::string const& json, bool multi = false) {
|
||||
return parse(reinterpret_cast<uint8_t const*>(json.c_str()), json.size(), multi);
|
||||
return parse(reinterpret_cast<uint8_t const*>(json.c_str()), json.size(),
|
||||
multi);
|
||||
}
|
||||
|
||||
ValueLength parse (char const* start, size_t size,
|
||||
bool multi = false) {
|
||||
ValueLength parse(char const* start, 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, size_t size, bool multi = false) {
|
||||
_start = start;
|
||||
_size = size;
|
||||
_pos = 0;
|
||||
|
@ -144,29 +138,23 @@ namespace arangodb {
|
|||
|
||||
Builder&& steal() {
|
||||
if (_b._buffer == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Buffer of Builder is already gone");
|
||||
throw Exception(Exception::InternalError,
|
||||
"Buffer of Builder is already gone");
|
||||
}
|
||||
return std::move(_b);
|
||||
}
|
||||
|
||||
// Beware, only valid as long as you do not parse more, use steal
|
||||
// to move the data out!
|
||||
uint8_t const* start () {
|
||||
return _b.start();
|
||||
}
|
||||
uint8_t const* start() { return _b.start(); }
|
||||
|
||||
// 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;
|
||||
}
|
||||
size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; }
|
||||
|
||||
void clear () {
|
||||
_b.clear();
|
||||
}
|
||||
void clear() { _b.clear(); }
|
||||
|
||||
private:
|
||||
|
||||
inline int peek() const {
|
||||
if (_pos >= _size) {
|
||||
return -1;
|
||||
|
@ -181,13 +169,9 @@ namespace arangodb {
|
|||
return static_cast<int>(_start[_pos++]);
|
||||
}
|
||||
|
||||
inline void unconsume () {
|
||||
--_pos;
|
||||
}
|
||||
inline void unconsume() { --_pos; }
|
||||
|
||||
inline void reset () {
|
||||
_pos = 0;
|
||||
}
|
||||
inline void reset() { _pos = 0; }
|
||||
|
||||
ValueLength parseInternal(bool multi);
|
||||
|
||||
|
@ -263,13 +247,9 @@ namespace arangodb {
|
|||
return i;
|
||||
}
|
||||
|
||||
inline void increaseNesting () {
|
||||
++_nesting;
|
||||
}
|
||||
inline void increaseNesting() { ++_nesting; }
|
||||
|
||||
inline void decreaseNesting () {
|
||||
--_nesting;
|
||||
}
|
||||
inline void decreaseNesting() { --_nesting; }
|
||||
|
||||
void parseNumber();
|
||||
|
||||
|
@ -280,7 +260,6 @@ namespace arangodb {
|
|||
void parseObject();
|
||||
|
||||
void parseJson();
|
||||
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -38,13 +38,11 @@ namespace arangodb {
|
|||
namespace velocypack {
|
||||
|
||||
struct Sink {
|
||||
Sink () {
|
||||
}
|
||||
Sink() {}
|
||||
Sink(Sink const&) = delete;
|
||||
Sink& operator=(Sink const&) = delete;
|
||||
|
||||
virtual ~Sink () {
|
||||
}
|
||||
virtual ~Sink() {}
|
||||
virtual void push_back(char c) = 0;
|
||||
virtual void append(std::string const& p) = 0;
|
||||
virtual void append(char const* p) = 0;
|
||||
|
@ -54,29 +52,21 @@ namespace arangodb {
|
|||
|
||||
template <typename T>
|
||||
struct ByteBufferSinkImpl final : public Sink {
|
||||
explicit ByteBufferSinkImpl (Buffer<T>* buffer)
|
||||
: buffer(buffer) {
|
||||
}
|
||||
explicit ByteBufferSinkImpl(Buffer<T>* buffer) : buffer(buffer) {}
|
||||
|
||||
void push_back (char c) override final {
|
||||
buffer->push_back(c);
|
||||
}
|
||||
void push_back(char c) override final { buffer->push_back(c); }
|
||||
|
||||
void append(std::string const& p) override final {
|
||||
buffer->append(p.c_str(), p.size());
|
||||
}
|
||||
|
||||
void append (char const* p) override final {
|
||||
buffer->append(p, strlen(p));
|
||||
}
|
||||
void append(char const* p) override final { buffer->append(p, strlen(p)); }
|
||||
|
||||
void append(char const* p, ValueLength len) override final {
|
||||
buffer->append(p, len);
|
||||
}
|
||||
|
||||
void reserve (ValueLength len) override final {
|
||||
buffer->reserve(len);
|
||||
}
|
||||
void reserve(ValueLength len) override final { buffer->reserve(len); }
|
||||
|
||||
Buffer<T>* buffer;
|
||||
};
|
||||
|
@ -85,29 +75,19 @@ namespace arangodb {
|
|||
|
||||
template <typename T>
|
||||
struct StringSinkImpl final : public Sink {
|
||||
explicit StringSinkImpl (T* buffer)
|
||||
: buffer(buffer) {
|
||||
}
|
||||
explicit StringSinkImpl(T* buffer) : buffer(buffer) {}
|
||||
|
||||
void push_back (char c) override final {
|
||||
buffer->push_back(c);
|
||||
}
|
||||
void push_back(char c) override final { buffer->push_back(c); }
|
||||
|
||||
void append (std::string const& p) override final {
|
||||
buffer->append(p);
|
||||
}
|
||||
void append(std::string const& p) override final { buffer->append(p); }
|
||||
|
||||
void append (char const* p) override final {
|
||||
buffer->append(p, strlen(p));
|
||||
}
|
||||
void append(char const* p) override final { buffer->append(p, strlen(p)); }
|
||||
|
||||
void append(char const* p, ValueLength len) override final {
|
||||
buffer->append(p, len);
|
||||
}
|
||||
|
||||
void reserve (ValueLength len) override final {
|
||||
buffer->reserve(len);
|
||||
}
|
||||
void reserve(ValueLength len) override final { buffer->reserve(len); }
|
||||
|
||||
T* buffer;
|
||||
};
|
||||
|
@ -116,17 +96,11 @@ namespace arangodb {
|
|||
|
||||
template <typename T>
|
||||
struct StreamSinkImpl final : public Sink {
|
||||
explicit StreamSinkImpl (T* stream)
|
||||
: stream(stream) {
|
||||
}
|
||||
explicit StreamSinkImpl(T* stream) : stream(stream) {}
|
||||
|
||||
void push_back (char c) override final {
|
||||
*stream << c;
|
||||
}
|
||||
void push_back(char c) override final { *stream << c; }
|
||||
|
||||
void append (std::string const& p) override final {
|
||||
*stream << p;
|
||||
}
|
||||
void append(std::string const& p) override final { *stream << p; }
|
||||
|
||||
void append(char const* p) override final {
|
||||
stream->write(p, static_cast<std::streamsize>(strlen(p)));
|
||||
|
@ -136,8 +110,7 @@ namespace arangodb {
|
|||
stream->write(p, static_cast<std::streamsize>(len));
|
||||
}
|
||||
|
||||
void reserve (ValueLength) override final {
|
||||
}
|
||||
void reserve(ValueLength) override final {}
|
||||
|
||||
T* stream;
|
||||
};
|
||||
|
|
|
@ -48,7 +48,6 @@ namespace arangodb {
|
|||
uint64_t fasthash64(void const*, size_t, uint64_t);
|
||||
|
||||
class Slice {
|
||||
|
||||
// This class provides read only access to a VPack value, it is
|
||||
// intentionally light-weight (only one pointer value), such that
|
||||
// it can easily be used to traverse larger VPack values.
|
||||
|
@ -58,15 +57,13 @@ namespace arangodb {
|
|||
uint8_t const* _start;
|
||||
|
||||
public:
|
||||
|
||||
Options const* options;
|
||||
|
||||
// constructor for an empty Value of type None
|
||||
Slice ()
|
||||
: Slice("\x00", &Options::Defaults) {
|
||||
}
|
||||
Slice() : Slice("\x00", &Options::Defaults) {}
|
||||
|
||||
explicit Slice (uint8_t const* start, Options const* options = &Options::Defaults)
|
||||
explicit Slice(uint8_t const* start,
|
||||
Options const* options = &Options::Defaults)
|
||||
: _start(start), options(options) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
}
|
||||
|
@ -76,13 +73,11 @@ namespace arangodb {
|
|||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
}
|
||||
|
||||
Slice (Slice const& other)
|
||||
: _start(other._start), options(other.options) {
|
||||
Slice(Slice const& other) : _start(other._start), options(other.options) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
}
|
||||
|
||||
Slice (Slice&& other)
|
||||
: _start(other._start), options(other.options) {
|
||||
Slice(Slice&& other) : _start(other._start), options(other.options) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
}
|
||||
|
||||
|
@ -100,37 +95,23 @@ namespace arangodb {
|
|||
return *this;
|
||||
}
|
||||
|
||||
uint8_t const* begin () {
|
||||
return _start;
|
||||
}
|
||||
uint8_t const* begin() { return _start; }
|
||||
|
||||
uint8_t const* begin () const {
|
||||
return _start;
|
||||
}
|
||||
uint8_t const* begin() const { return _start; }
|
||||
|
||||
uint8_t const* end () {
|
||||
return _start + byteSize();
|
||||
}
|
||||
uint8_t const* end() { return _start + byteSize(); }
|
||||
|
||||
uint8_t const* end () const {
|
||||
return _start + byteSize();
|
||||
}
|
||||
uint8_t const* end() const { return _start + byteSize(); }
|
||||
|
||||
// No destructor, does not take part in memory management,
|
||||
|
||||
// get the type for the slice
|
||||
inline ValueType type () const {
|
||||
return TypeMap[head()];
|
||||
}
|
||||
inline ValueType type() const { return TypeMap[head()]; }
|
||||
|
||||
char const* typeName () const {
|
||||
return valueTypeName(type());
|
||||
}
|
||||
char const* typeName() const { return valueTypeName(type()); }
|
||||
|
||||
// pointer to the head byte
|
||||
uint8_t const* start () const {
|
||||
return _start;
|
||||
}
|
||||
uint8_t const* start() const { return _start; }
|
||||
|
||||
// pointer to the head byte
|
||||
template <typename T>
|
||||
|
@ -139,118 +120,83 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
// value of the head byte
|
||||
inline uint8_t head () const {
|
||||
return *_start;
|
||||
}
|
||||
inline uint8_t head() const { return *_start; }
|
||||
|
||||
inline uint64_t hash() const {
|
||||
return fasthash64(start(), byteSize(), 0xdeadbeef);
|
||||
}
|
||||
|
||||
// check if slice is of the specified type
|
||||
inline bool isType (ValueType t) const {
|
||||
return type() == t;
|
||||
}
|
||||
inline bool isType(ValueType t) const { return type() == t; }
|
||||
|
||||
// check if slice is a None object
|
||||
bool isNone () const {
|
||||
return isType(ValueType::None);
|
||||
}
|
||||
bool isNone() const { return isType(ValueType::None); }
|
||||
|
||||
// check if slice is a Null object
|
||||
bool isNull () const {
|
||||
return isType(ValueType::Null);
|
||||
}
|
||||
bool isNull() const { return isType(ValueType::Null); }
|
||||
|
||||
// check if slice is a Bool object
|
||||
bool isBool () const {
|
||||
return isType(ValueType::Bool);
|
||||
}
|
||||
bool isBool() const { return isType(ValueType::Bool); }
|
||||
|
||||
// check if slice is a Bool object - this is an alias for isBool()
|
||||
bool isBoolean () const {
|
||||
return isBool();
|
||||
}
|
||||
bool isBoolean() const { return isBool(); }
|
||||
|
||||
// check if slice is the Boolean value true
|
||||
bool isTrue() const { return head() == 0x1a; }
|
||||
|
||||
// check if slice is the Boolean value false
|
||||
bool isFalse() const { return head() == 0x19; }
|
||||
|
||||
// check if slice is an Array object
|
||||
bool isArray () const {
|
||||
return isType(ValueType::Array);
|
||||
}
|
||||
bool isArray() const { return isType(ValueType::Array); }
|
||||
|
||||
// check if slice is an Object object
|
||||
bool isObject () const {
|
||||
return isType(ValueType::Object);
|
||||
}
|
||||
bool isObject() const { return isType(ValueType::Object); }
|
||||
|
||||
// check if slice is a Double object
|
||||
bool isDouble () const {
|
||||
return isType(ValueType::Double);
|
||||
}
|
||||
bool isDouble() const { return isType(ValueType::Double); }
|
||||
|
||||
// check if slice is a UTCDate object
|
||||
bool isUTCDate () const {
|
||||
return isType(ValueType::UTCDate);
|
||||
}
|
||||
bool isUTCDate() const { return isType(ValueType::UTCDate); }
|
||||
|
||||
// check if slice is an External object
|
||||
bool isExternal () const {
|
||||
return isType(ValueType::External);
|
||||
}
|
||||
bool isExternal() const { return isType(ValueType::External); }
|
||||
|
||||
// check if slice is a MinKey object
|
||||
bool isMinKey () const {
|
||||
return isType(ValueType::MinKey);
|
||||
}
|
||||
bool isMinKey() const { return isType(ValueType::MinKey); }
|
||||
|
||||
// check if slice is a MaxKey object
|
||||
bool isMaxKey () const {
|
||||
return isType(ValueType::MaxKey);
|
||||
}
|
||||
bool isMaxKey() const { return isType(ValueType::MaxKey); }
|
||||
|
||||
// check if slice is an Int object
|
||||
bool isInt () const {
|
||||
return isType(ValueType::Int);
|
||||
}
|
||||
bool isInt() const { return isType(ValueType::Int); }
|
||||
|
||||
// check if slice is a UInt object
|
||||
bool isUInt () const {
|
||||
return isType(ValueType::UInt);
|
||||
}
|
||||
bool isUInt() const { return isType(ValueType::UInt); }
|
||||
|
||||
// check if slice is a SmallInt object
|
||||
bool isSmallInt () const {
|
||||
return isType(ValueType::SmallInt);
|
||||
}
|
||||
bool isSmallInt() const { return isType(ValueType::SmallInt); }
|
||||
|
||||
// check if slice is a String object
|
||||
bool isString () const {
|
||||
return isType(ValueType::String);
|
||||
}
|
||||
bool isString() const { return isType(ValueType::String); }
|
||||
|
||||
// check if slice is a Binary object
|
||||
bool isBinary () const {
|
||||
return isType(ValueType::Binary);
|
||||
}
|
||||
bool isBinary() const { return isType(ValueType::Binary); }
|
||||
|
||||
// check if slice is a BCD
|
||||
bool isBCD () const {
|
||||
return isType(ValueType::BCD);
|
||||
}
|
||||
bool isBCD() const { return isType(ValueType::BCD); }
|
||||
|
||||
// check if slice is a Custom type
|
||||
bool isCustom () const {
|
||||
return isType(ValueType::Custom);
|
||||
}
|
||||
bool isCustom() const { return isType(ValueType::Custom); }
|
||||
|
||||
// check if a slice is any number type
|
||||
bool isInteger() const {
|
||||
return isType(ValueType::Int) || isType(ValueType::UInt) || isType(ValueType::SmallInt);
|
||||
return isType(ValueType::Int) || isType(ValueType::UInt) ||
|
||||
isType(ValueType::SmallInt);
|
||||
}
|
||||
|
||||
// check if slice is any Number-type object
|
||||
bool isNumber () const {
|
||||
return isInteger() || isDouble();
|
||||
}
|
||||
bool isNumber() const { return isInteger() || isDouble(); }
|
||||
|
||||
bool isSorted() const {
|
||||
auto const h = head();
|
||||
|
@ -259,18 +205,20 @@ namespace arangodb {
|
|||
|
||||
// return the value for a Bool object
|
||||
bool getBool() const {
|
||||
assertType(ValueType::Bool);
|
||||
if (type() != ValueType::Bool) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Bool");
|
||||
}
|
||||
return (head() == 0x1a); // 0x19 == false, 0x1a == true
|
||||
}
|
||||
|
||||
// return the value for a Bool object - this is an alias for getBool()
|
||||
bool getBoolean () const {
|
||||
return getBool();
|
||||
}
|
||||
bool getBoolean() const { return getBool(); }
|
||||
|
||||
// return the value for a Double object
|
||||
double getDouble() const {
|
||||
assertType(ValueType::Double);
|
||||
if (type() != ValueType::Double) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Double");
|
||||
}
|
||||
union {
|
||||
uint64_t dv;
|
||||
double d;
|
||||
|
@ -294,20 +242,19 @@ namespace arangodb {
|
|||
// - 0x09 : array with 8-byte index table entries
|
||||
Slice at(ValueLength index) const {
|
||||
if (!isType(ValueType::Array)) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Array");
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Array");
|
||||
}
|
||||
|
||||
return getNth(index);
|
||||
}
|
||||
|
||||
Slice operator[] (ValueLength index) const {
|
||||
return at(index);
|
||||
}
|
||||
Slice operator[](ValueLength index) const { return at(index); }
|
||||
|
||||
// return the number of members for an Array or Object object
|
||||
ValueLength length() const {
|
||||
if (type() != ValueType::Array && type() != ValueType::Object) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Array or Object");
|
||||
throw Exception(Exception::InvalidValueType,
|
||||
"Expecting type Array or Object");
|
||||
}
|
||||
|
||||
auto const h = head();
|
||||
|
@ -330,8 +277,7 @@ namespace arangodb {
|
|||
ValueLength firstSubOffset = findDataOffset(h);
|
||||
Slice first(_start + firstSubOffset, options);
|
||||
return (end - firstSubOffset) / first.byteSize();
|
||||
}
|
||||
else if (offsetSize < 8) {
|
||||
} else if (offsetSize < 8) {
|
||||
return readInteger<ValueLength>(_start + offsetSize + 1, offsetSize);
|
||||
}
|
||||
|
||||
|
@ -340,17 +286,25 @@ namespace arangodb {
|
|||
|
||||
// extract a key from an Object at the specified index
|
||||
// - 0x0a : empty object
|
||||
// - 0x0b : object with 1-byte index table entries, sorted by attribute name
|
||||
// - 0x0c : object with 2-byte index table entries, sorted by attribute name
|
||||
// - 0x0d : object with 4-byte index table entries, sorted by attribute name
|
||||
// - 0x0e : object with 8-byte index table entries, sorted by attribute name
|
||||
// - 0x0f : object with 1-byte index table entries, not sorted by attribute name
|
||||
// - 0x10 : object with 2-byte index table entries, not sorted by attribute name
|
||||
// - 0x11 : object with 4-byte index table entries, not sorted by attribute name
|
||||
// - 0x12 : object with 8-byte index table entries, not sorted by attribute name
|
||||
// - 0x0b : object with 1-byte index table entries, sorted by attribute
|
||||
// name
|
||||
// - 0x0c : object with 2-byte index table entries, sorted by attribute
|
||||
// name
|
||||
// - 0x0d : object with 4-byte index table entries, sorted by attribute
|
||||
// name
|
||||
// - 0x0e : object with 8-byte index table entries, sorted by attribute
|
||||
// name
|
||||
// - 0x0f : object with 1-byte index table entries, not sorted by
|
||||
// attribute name
|
||||
// - 0x10 : object with 2-byte index table entries, not sorted by
|
||||
// attribute name
|
||||
// - 0x11 : object with 4-byte index table entries, not sorted by
|
||||
// attribute name
|
||||
// - 0x12 : object with 8-byte index table entries, not sorted by
|
||||
// attribute name
|
||||
Slice keyAt(ValueLength index) const {
|
||||
if (!isType(ValueType::Object)) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Object");
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Object");
|
||||
}
|
||||
|
||||
return getNthKey(index, true);
|
||||
|
@ -358,7 +312,7 @@ namespace arangodb {
|
|||
|
||||
Slice valueAt(ValueLength index) const {
|
||||
if (!isType(ValueType::Object)) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Object");
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Object");
|
||||
}
|
||||
|
||||
Slice key = getNthKey(index, false);
|
||||
|
@ -408,7 +362,9 @@ namespace arangodb {
|
|||
|
||||
// return the pointer to the data for an External object
|
||||
char const* getExternal() const {
|
||||
assertType(ValueType::External);
|
||||
if (type() != ValueType::External) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type External");
|
||||
}
|
||||
return extractValue<char const*>();
|
||||
}
|
||||
|
||||
|
@ -444,13 +400,11 @@ namespace arangodb {
|
|||
throw Exception(Exception::NumberOutOfRange);
|
||||
}
|
||||
return static_cast<T>(v);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// unsigned integral type
|
||||
if (isDouble()) {
|
||||
auto v = getDouble();
|
||||
if (v < 0.0 ||
|
||||
v > static_cast<double>(UINT64_MAX) ||
|
||||
if (v < 0.0 || v > static_cast<double>(UINT64_MAX) ||
|
||||
v > static_cast<double>(std::numeric_limits<T>::max())) {
|
||||
throw Exception(Exception::NumberOutOfRange);
|
||||
}
|
||||
|
@ -488,6 +442,9 @@ namespace arangodb {
|
|||
|
||||
// return the value for a UTCDate object
|
||||
int64_t getUTCDate() const {
|
||||
if (type() != ValueType::UTCDate) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type UTCDate");
|
||||
}
|
||||
assertType(ValueType::UTCDate);
|
||||
uint64_t v = readInteger<uint64_t>(_start + 1, sizeof(uint64_t));
|
||||
return toInt64(v);
|
||||
|
@ -518,7 +475,8 @@ namespace arangodb {
|
|||
if (h >= 0x40 && h <= 0xbe) {
|
||||
// short UTF-8 String
|
||||
ValueLength length = h - 0x40;
|
||||
return std::string(reinterpret_cast<char const*>(_start + 1), static_cast<size_t>(length));
|
||||
return std::string(reinterpret_cast<char const*>(_start + 1),
|
||||
static_cast<size_t>(length));
|
||||
}
|
||||
|
||||
if (h == 0xbf) {
|
||||
|
@ -532,7 +490,9 @@ namespace arangodb {
|
|||
|
||||
// return the value for a Binary object
|
||||
uint8_t const* getBinary(ValueLength& length) const {
|
||||
assertType(ValueType::Binary);
|
||||
if (type() != ValueType::Binary) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Binary");
|
||||
}
|
||||
uint8_t const h = head();
|
||||
|
||||
if (h >= 0xc0 && h <= 0xc7) {
|
||||
|
@ -546,7 +506,9 @@ namespace arangodb {
|
|||
|
||||
// return a copy of the value for a Binary object
|
||||
std::vector<uint8_t> copyBinary() const {
|
||||
assertType(ValueType::Binary);
|
||||
if (type() != ValueType::Binary) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Binary");
|
||||
}
|
||||
uint8_t const h = head();
|
||||
|
||||
if (h >= 0xc0 && h <= 0xc7) {
|
||||
|
@ -554,8 +516,9 @@ namespace arangodb {
|
|||
ValueLength length = readInteger<ValueLength>(_start + 1, h - 0xbf);
|
||||
checkValueLength(length);
|
||||
out.reserve(static_cast<size_t>(length));
|
||||
out.insert(out.end(), _start + 1 + h - 0xbf, _start + 1 + h - 0xbf + length);
|
||||
return out;
|
||||
out.insert(out.end(), _start + 1 + h - 0xbf,
|
||||
_start + 1 + h - 0xbf + length);
|
||||
return std::move(out);
|
||||
}
|
||||
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Binary");
|
||||
|
@ -614,7 +577,8 @@ namespace arangodb {
|
|||
auto const h = head();
|
||||
if (h == 0xbf) {
|
||||
// long UTF-8 String
|
||||
return static_cast<ValueLength>(1 + 8 + readInteger<ValueLength>(_start + 1, 8));
|
||||
return static_cast<ValueLength>(
|
||||
1 + 8 + readInteger<ValueLength>(_start + 1, 8));
|
||||
}
|
||||
|
||||
// short UTF-8 String
|
||||
|
@ -623,18 +587,21 @@ namespace arangodb {
|
|||
|
||||
case ValueType::Binary: {
|
||||
auto const h = head();
|
||||
return static_cast<ValueLength>(1 + h - 0xbf + readInteger<ValueLength>(_start + 1, h - 0xbf));
|
||||
return static_cast<ValueLength>(
|
||||
1 + h - 0xbf + readInteger<ValueLength>(_start + 1, h - 0xbf));
|
||||
}
|
||||
|
||||
case ValueType::BCD: {
|
||||
auto const h = head();
|
||||
if (h <= 0xcf) {
|
||||
// positive BCD
|
||||
return static_cast<ValueLength>(1 + h - 0xc7 + readInteger<ValueLength>(_start + 1, h - 0xc7));
|
||||
return static_cast<ValueLength>(
|
||||
1 + h - 0xc7 + readInteger<ValueLength>(_start + 1, h - 0xc7));
|
||||
}
|
||||
|
||||
// negative BCD
|
||||
return static_cast<ValueLength>(1 + h - 0xcf + readInteger<ValueLength>(_start + 1, h - 0xcf));
|
||||
return static_cast<ValueLength>(
|
||||
1 + h - 0xcf + readInteger<ValueLength>(_start + 1, h - 0xcf));
|
||||
}
|
||||
|
||||
case ValueType::Custom: {
|
||||
|
@ -660,7 +627,6 @@ namespace arangodb {
|
|||
std::string hexType() const;
|
||||
|
||||
private:
|
||||
|
||||
Slice getFromCompactObject(std::string const& attribute) const;
|
||||
|
||||
ValueLength findDataOffset(uint8_t head) const {
|
||||
|
@ -705,22 +671,17 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
// perform a linear search for the specified attribute inside an Object
|
||||
Slice searchObjectKeyLinear (std::string const& attribute,
|
||||
ValueLength ieBase,
|
||||
ValueLength offsetSize,
|
||||
ValueLength n) const;
|
||||
Slice searchObjectKeyLinear(std::string const& attribute, ValueLength ieBase,
|
||||
ValueLength offsetSize, ValueLength n) const;
|
||||
|
||||
// perform a binary search for the specified attribute inside an Object
|
||||
Slice searchObjectKeyBinary (std::string const& attribute,
|
||||
ValueLength ieBase,
|
||||
ValueLength offsetSize,
|
||||
ValueLength n) const;
|
||||
Slice searchObjectKeyBinary(std::string const& attribute, ValueLength ieBase,
|
||||
ValueLength offsetSize, ValueLength n) const;
|
||||
|
||||
// assert that the slice is of a specific type
|
||||
// can be used for debugging and removed in production
|
||||
#ifdef VELOCYPACK_ASSERT
|
||||
inline void assertType (ValueType) const {
|
||||
}
|
||||
inline void assertType(ValueType) const {}
|
||||
#else
|
||||
inline void assertType(ValueType type) const {
|
||||
VELOCYPACK_ASSERT(this->type() == type);
|
||||
|
@ -729,7 +690,8 @@ namespace arangodb {
|
|||
|
||||
// extracts a value from the slice and converts it into a
|
||||
// built-in type
|
||||
template<typename T> T extractValue () const {
|
||||
template <typename T>
|
||||
T extractValue() const {
|
||||
union {
|
||||
T value;
|
||||
char binary[sizeof(T)];
|
||||
|
@ -739,7 +701,6 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
static ValueType const TypeMap[256];
|
||||
static unsigned int const WidthMap[32];
|
||||
static unsigned int const FirstSubMap[32];
|
||||
|
@ -749,13 +710,15 @@ namespace arangodb {
|
|||
} // namespace arangodb
|
||||
|
||||
namespace std {
|
||||
template<> struct hash<arangodb::velocypack::Slice> {
|
||||
template <>
|
||||
struct hash<arangodb::velocypack::Slice> {
|
||||
size_t operator()(arangodb::velocypack::Slice const& slice) const {
|
||||
return slice.hash();
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct equal_to<arangodb::velocypack::Slice> {
|
||||
template <>
|
||||
struct equal_to<arangodb::velocypack::Slice> {
|
||||
bool operator()(arangodb::velocypack::Slice const& a,
|
||||
arangodb::velocypack::Slice const& b) const {
|
||||
if (*a.start() != *b.start()) {
|
||||
|
|
|
@ -42,7 +42,6 @@ namespace arangodb {
|
|||
friend class Builder;
|
||||
|
||||
public:
|
||||
|
||||
enum class CType {
|
||||
None = 0,
|
||||
Bool = 1,
|
||||
|
@ -55,7 +54,6 @@ namespace arangodb {
|
|||
};
|
||||
|
||||
private:
|
||||
|
||||
ValueType _valueType;
|
||||
CType _cType; // denotes variant used, 0: none
|
||||
|
||||
|
@ -67,17 +65,14 @@ namespace arangodb {
|
|||
std::string const* s; // 5: std::string
|
||||
char const* c; // 6: char const*
|
||||
void const* e; // external
|
||||
}
|
||||
_value;
|
||||
} _value;
|
||||
|
||||
bool _unindexed;
|
||||
|
||||
public:
|
||||
|
||||
#ifdef SWIG
|
||||
Value () : _valueType(ValueType::None), _cType(CType::None),
|
||||
_unindexed(false) {
|
||||
}
|
||||
Value()
|
||||
: _valueType(ValueType::None), _cType(CType::None), _unindexed(false) {}
|
||||
#else
|
||||
Value() = delete;
|
||||
#endif
|
||||
|
@ -85,7 +80,6 @@ namespace arangodb {
|
|||
// 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");
|
||||
|
@ -153,17 +147,11 @@ namespace arangodb {
|
|||
_value.s = &s;
|
||||
}
|
||||
|
||||
ValueType valueType () const {
|
||||
return _valueType;
|
||||
}
|
||||
ValueType valueType() const { return _valueType; }
|
||||
|
||||
CType cType () const {
|
||||
return _cType;
|
||||
}
|
||||
CType cType() const { return _cType; }
|
||||
|
||||
bool isString () const {
|
||||
return _valueType == ValueType::String;
|
||||
}
|
||||
bool isString() const { return _valueType == ValueType::String; }
|
||||
|
||||
bool getBool() const {
|
||||
VELOCYPACK_ASSERT(_cType == CType::Bool);
|
||||
|
@ -199,7 +187,6 @@ namespace arangodb {
|
|||
VELOCYPACK_ASSERT(_cType == CType::CharPtr);
|
||||
return _value.c;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ValuePair {
|
||||
|
@ -208,38 +195,26 @@ namespace arangodb {
|
|||
ValueType _type;
|
||||
|
||||
public:
|
||||
|
||||
ValuePair(uint8_t const* start, uint64_t size,
|
||||
ValueType type = ValueType::Binary)
|
||||
: _start(start), _size(size), _type(type) {
|
||||
}
|
||||
: _start(start), _size(size), _type(type) {}
|
||||
|
||||
ValuePair(char const* start, uint64_t size,
|
||||
ValueType type = ValueType::Binary)
|
||||
: _start(reinterpret_cast<uint8_t const*>(start)),
|
||||
_size(size), _type(type) {
|
||||
}
|
||||
_size(size),
|
||||
_type(type) {}
|
||||
|
||||
explicit ValuePair (uint64_t size,
|
||||
ValueType type = ValueType::Binary)
|
||||
: _start(nullptr), _size(size), _type(type) {
|
||||
}
|
||||
explicit ValuePair(uint64_t size, ValueType type = ValueType::Binary)
|
||||
: _start(nullptr), _size(size), _type(type) {}
|
||||
|
||||
uint8_t const* getStart () const {
|
||||
return _start;
|
||||
}
|
||||
uint8_t const* getStart() const { return _start; }
|
||||
|
||||
uint64_t getSize () const {
|
||||
return _size;
|
||||
}
|
||||
uint64_t getSize() const { return _size; }
|
||||
|
||||
ValueType valueType () const {
|
||||
return _type;
|
||||
}
|
||||
ValueType valueType() const { return _type; }
|
||||
|
||||
bool isString () const {
|
||||
return _type == ValueType::String;
|
||||
}
|
||||
bool isString() const { return _type == ValueType::String; }
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -40,8 +40,9 @@ namespace arangodb {
|
|||
Version& operator=(Version const&) = delete;
|
||||
|
||||
Version(int majorValue, int minorValue, int patchValue)
|
||||
: majorValue(majorValue), minorValue(minorValue), patchValue(patchValue) {
|
||||
}
|
||||
: majorValue(majorValue),
|
||||
minorValue(minorValue),
|
||||
patchValue(patchValue) {}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ namespace {
|
|||
using VPackValueLength = arangodb::velocypack::ValueLength;
|
||||
#endif
|
||||
|
||||
// conditional typedefs, only used when the respective headers are already included
|
||||
// conditional typedefs, only used when the respective headers are already
|
||||
// included
|
||||
|
||||
#ifdef VELOCYPACK_ITERATOR_H
|
||||
#ifndef VELOCYPACK_ALIAS_ITERATOR
|
||||
|
@ -108,7 +109,8 @@ namespace {
|
|||
#ifndef VELOCYPACK_ALIAS_OPTIONS
|
||||
#define VELOCYPACK_ALIAS_OPTIONS
|
||||
using VPackOptions = arangodb::velocypack::Options;
|
||||
using VPackAttributeExcludeHandler = arangodb::velocypack::AttributeExcludeHandler;
|
||||
using VPackAttributeExcludeHandler =
|
||||
arangodb::velocypack::AttributeExcludeHandler;
|
||||
using VPackCustomTypeHandler = arangodb::velocypack::CustomTypeHandler;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -149,4 +151,3 @@ namespace {
|
|||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -104,12 +104,10 @@ namespace arangodb {
|
|||
p += 7;
|
||||
if (reverse) {
|
||||
--source;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
++source;
|
||||
}
|
||||
}
|
||||
while (v & 0x80);
|
||||
} while (v & 0x80);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -124,8 +122,7 @@ namespace arangodb {
|
|||
value >>= 7;
|
||||
}
|
||||
*dst-- = static_cast<uint8_t>(value & 0x7f);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
while (value >= 0x80) {
|
||||
*dst++ = static_cast<uint8_t>(value | 0x80);
|
||||
value >>= 7;
|
||||
|
@ -166,8 +163,7 @@ namespace arangodb {
|
|||
do {
|
||||
value += static_cast<T>(*start++) << x;
|
||||
x += 8;
|
||||
}
|
||||
while (start < end);
|
||||
} while (start < end);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -180,8 +176,7 @@ namespace arangodb {
|
|||
do {
|
||||
*start++ = static_cast<uint8_t>(value & 0xff);
|
||||
value >>= 8;
|
||||
}
|
||||
while (start < end);
|
||||
} while (start < end);
|
||||
}
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -73,7 +73,8 @@ uint8_t const* AttributeTranslator::translate (std::string const& key) const {
|
|||
}
|
||||
|
||||
// translate from string to id
|
||||
uint8_t const* AttributeTranslator::translate (char const* key, ValueLength length) const {
|
||||
uint8_t const* AttributeTranslator::translate(char const* key,
|
||||
ValueLength length) const {
|
||||
auto it = _keyToId.find(std::string(key, length));
|
||||
|
||||
if (it == _keyToId.end()) {
|
||||
|
@ -93,4 +94,3 @@ uint8_t const* AttributeTranslator::translate (uint64_t id) const {
|
|||
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,7 @@ void Builder::doActualSort (std::vector<SortEntry>& entries) {
|
|||
uint64_t sizea = a.nameSize;
|
||||
uint8_t const* pb = b.nameStart;
|
||||
uint64_t sizeb = b.nameSize;
|
||||
size_t const compareLength
|
||||
= static_cast<size_t>((std::min)(sizea, sizeb));
|
||||
size_t const compareLength = static_cast<size_t>((std::min)(sizea, sizeb));
|
||||
int res = memcmp(pa, pb, compareLength);
|
||||
|
||||
return (res < 0 || (res == 0 && sizea < sizeb));
|
||||
|
@ -81,14 +80,12 @@ void Builder::sortObjectIndexShort (uint8_t* objBase,
|
|||
auto cmp = [&](ValueLength a, ValueLength b) -> bool {
|
||||
uint8_t const* aa = objBase + a;
|
||||
uint8_t const* bb = objBase + b;
|
||||
if (*aa >= 0x40 && *aa <= 0xbe &&
|
||||
*bb >= 0x40 && *bb <= 0xbe) {
|
||||
if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) {
|
||||
// The fast path, short strings:
|
||||
uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40);
|
||||
int c = memcmp(aa + 1, bb + 1, static_cast<size_t>(m));
|
||||
return (c < 0 || (c == 0 && *aa < *bb));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
uint64_t lena;
|
||||
uint64_t lenb;
|
||||
aa = findAttrName(aa, lena);
|
||||
|
@ -103,7 +100,6 @@ void Builder::sortObjectIndexShort (uint8_t* objBase,
|
|||
|
||||
void Builder::sortObjectIndexLong(uint8_t* objBase,
|
||||
std::vector<ValueLength>& offsets) {
|
||||
|
||||
// on some platforms we can use a thread-local vector
|
||||
#if __llvm__ == 1
|
||||
// nono thread local
|
||||
|
@ -136,8 +132,7 @@ void Builder::sortObjectIndex (uint8_t* objBase,
|
|||
std::vector<ValueLength>& offsets) {
|
||||
if (offsets.size() > 32) {
|
||||
sortObjectIndexLong(objBase, offsets);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sortObjectIndexShort(objBase, offsets);
|
||||
}
|
||||
}
|
||||
|
@ -182,12 +177,12 @@ void Builder::close () {
|
|||
VELOCYPACK_ASSERT(index.size() > 0);
|
||||
|
||||
// check if we can use the compact Array / Object format
|
||||
if (index.size() > 1 &&
|
||||
((head == 0x13 || head == 0x14) ||
|
||||
if (index.size() > 1 && ((head == 0x13 || head == 0x14) ||
|
||||
(head == 0x06 && options->buildUnindexedArrays) ||
|
||||
(head == 0x0b && options->buildUnindexedObjects))) {
|
||||
// use compact notation
|
||||
ValueLength nLen = getVariableValueLength(static_cast<ValueLength>(index.size()));
|
||||
ValueLength nLen =
|
||||
getVariableValueLength(static_cast<ValueLength>(index.size()));
|
||||
VELOCYPACK_ASSERT(nLen > 0);
|
||||
ValueLength byteSize = _pos - (tos + 8) + nLen;
|
||||
VELOCYPACK_ASSERT(byteSize > 0);
|
||||
|
@ -199,13 +194,13 @@ void Builder::close () {
|
|||
}
|
||||
|
||||
if (bLen < 9) {
|
||||
// can only use compact notation if total byte length is at most 8 bytes long
|
||||
// can only use compact notation if total byte length is at most 8 bytes
|
||||
// long
|
||||
_start[tos] = (isArray ? 0x13 : 0x14);
|
||||
ValueLength targetPos = 1 + bLen;
|
||||
|
||||
if (_pos > (tos + 9)) {
|
||||
memmove(_start + tos + targetPos, _start + tos + 9,
|
||||
_pos - (tos + 9));
|
||||
memmove(_start + tos + targetPos, _start + tos + 9, _pos - (tos + 9));
|
||||
}
|
||||
|
||||
// store byte length
|
||||
|
@ -216,7 +211,8 @@ void Builder::close () {
|
|||
if (nLen > 8 - bLen) {
|
||||
reserveSpace(nLen);
|
||||
}
|
||||
storeVariableValueLength<true>(_start + tos + byteSize - 1, static_cast<ValueLength>(index.size()));
|
||||
storeVariableValueLength<true>(_start + tos + byteSize - 1,
|
||||
static_cast<ValueLength>(index.size()));
|
||||
|
||||
_pos -= 8;
|
||||
_pos += nLen + bLen;
|
||||
|
@ -237,8 +233,7 @@ void Builder::close () {
|
|||
needNrSubs = false;
|
||||
}
|
||||
// For objects we leave needNrSubs at true here!
|
||||
}
|
||||
else if (_start[tos] == 0x06 && // an Array
|
||||
} else if (_start[tos] == 0x06 && // an Array
|
||||
(_pos - tos) - index[0] == index.size() * (index[1] - index[0])) {
|
||||
// In this case it could be that all entries have the same length
|
||||
// and we do not need an offset table at all:
|
||||
|
@ -246,8 +241,7 @@ void Builder::close () {
|
|||
ValueLength const subLen = index[1] - index[0];
|
||||
if ((_pos - tos) - index[index.size() - 1] != subLen) {
|
||||
noTable = false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
for (size_t i = 1; i < index.size() - 1; i++) {
|
||||
if (index[i + 1] - index[i] != subLen) {
|
||||
noTable = false;
|
||||
|
@ -265,21 +259,19 @@ void Builder::close () {
|
|||
unsigned int offsetSize;
|
||||
// can be 1, 2, 4 or 8 for the byte width of the offsets,
|
||||
// the byte length and the number of subvalues:
|
||||
if (_pos - tos + (needIndexTable ? index.size() : 0)
|
||||
- (needNrSubs ? 6 : 7) <= 0xff) {
|
||||
if (_pos - tos + (needIndexTable ? index.size() : 0) - (needNrSubs ? 6 : 7) <=
|
||||
0xff) {
|
||||
// We have so far used _pos - tos bytes, including the reserved 8
|
||||
// bytes for byte length and number of subvalues. In the 1-byte number
|
||||
// case we would win back 6 bytes but would need one byte per subvalue
|
||||
// for the index table
|
||||
offsetSize = 1;
|
||||
}
|
||||
else if (_pos - tos + (needIndexTable ? 2 * index.size() : 0) <= 0xffff) {
|
||||
} else if (_pos - tos + (needIndexTable ? 2 * index.size() : 0) <= 0xffff) {
|
||||
offsetSize = 2;
|
||||
}
|
||||
else if (_pos - tos + (needIndexTable ? 4 * index.size() : 0) <= 0xffffffffu) {
|
||||
} else if (_pos - tos + (needIndexTable ? 4 * index.size() : 0) <=
|
||||
0xffffffffu) {
|
||||
offsetSize = 4;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
offsetSize = 8;
|
||||
}
|
||||
|
||||
|
@ -290,8 +282,7 @@ void Builder::close () {
|
|||
targetPos = 2;
|
||||
}
|
||||
if (_pos > (tos + 9)) {
|
||||
memmove(_start + tos + targetPos, _start + tos + 9,
|
||||
_pos - (tos + 9));
|
||||
memmove(_start + tos + targetPos, _start + tos + 9, _pos - (tos + 9));
|
||||
}
|
||||
_pos -= (9 - targetPos);
|
||||
for (size_t i = 0; i < index.size(); i++) {
|
||||
|
@ -312,9 +303,7 @@ void Builder::close () {
|
|||
// Object
|
||||
if (!options->sortAttributeNames) {
|
||||
_start[tos] = 0x0f; // unsorted
|
||||
}
|
||||
else if (index.size() >= 2 &&
|
||||
options->sortAttributeNames) {
|
||||
} else if (index.size() >= 2 && options->sortAttributeNames) {
|
||||
sortObjectIndex(_start + tos, index);
|
||||
}
|
||||
}
|
||||
|
@ -325,8 +314,7 @@ void Builder::close () {
|
|||
x >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // no index table
|
||||
} else { // no index table
|
||||
if (_start[tos] == 0x06) {
|
||||
_start[tos] = 0x02;
|
||||
}
|
||||
|
@ -335,11 +323,9 @@ void Builder::close () {
|
|||
if (offsetSize > 1) {
|
||||
if (offsetSize == 2) {
|
||||
_start[tos] += 1;
|
||||
}
|
||||
else if (offsetSize == 4) {
|
||||
} else if (offsetSize == 4) {
|
||||
_start[tos] += 2;
|
||||
}
|
||||
else { // offsetSize == 8
|
||||
} else { // offsetSize == 8
|
||||
_start[tos] += 3;
|
||||
if (needNrSubs) {
|
||||
appendLength(index.size(), 8);
|
||||
|
@ -397,7 +383,7 @@ bool Builder::hasKey (std::string const& key) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// return an attribute from an Object value
|
||||
// return the value for a specific key of an Object value
|
||||
Slice Builder::getKey(std::string const& key) const {
|
||||
if (_stack.empty()) {
|
||||
throw Exception(Exception::BuilderNeedOpenObject);
|
||||
|
@ -412,8 +398,11 @@ Slice Builder::getKey (std::string const& key) const {
|
|||
}
|
||||
for (size_t i = 0; i < index.size(); ++i) {
|
||||
Slice s(_start + tos + index[i], options);
|
||||
if (!s.isString()) {
|
||||
s = s.makeKey();
|
||||
}
|
||||
if (s.isString() && s.isEqualString(key)) {
|
||||
return s;
|
||||
return Slice(s.start() + s.byteSize(), options);
|
||||
}
|
||||
}
|
||||
return Slice();
|
||||
|
@ -428,7 +417,8 @@ uint8_t* Builder::set (Value const& item) {
|
|||
// table is created and a new ValueLength is pushed onto the stack.
|
||||
switch (item.valueType()) {
|
||||
case ValueType::None: {
|
||||
throw Exception(Exception::BuilderUnexpectedType, "Cannot set a ValueType::None");
|
||||
throw Exception(Exception::BuilderUnexpectedType,
|
||||
"Cannot set a ValueType::None");
|
||||
}
|
||||
case ValueType::Null: {
|
||||
reserveSpace(1);
|
||||
|
@ -437,13 +427,13 @@ uint8_t* Builder::set (Value const& item) {
|
|||
}
|
||||
case ValueType::Bool: {
|
||||
if (ctype != Value::CType::Bool) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give bool for ValueType::Bool");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give bool for ValueType::Bool");
|
||||
}
|
||||
reserveSpace(1);
|
||||
if (item.getBool()) {
|
||||
_start[_pos++] = 0x1a;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_start[_pos++] = 0x19;
|
||||
}
|
||||
break;
|
||||
|
@ -464,7 +454,8 @@ uint8_t* Builder::set (Value const& item) {
|
|||
v = static_cast<double>(item.getUInt64());
|
||||
break;
|
||||
default:
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::Double");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give number for ValueType::Double");
|
||||
}
|
||||
reserveSpace(1 + sizeof(double));
|
||||
_start[_pos++] = 0x1b;
|
||||
|
@ -473,8 +464,14 @@ uint8_t* Builder::set (Value const& item) {
|
|||
break;
|
||||
}
|
||||
case ValueType::External: {
|
||||
if (options->disallowExternals) {
|
||||
// External values explicitly disallowed as a security
|
||||
// precaution
|
||||
throw Exception(Exception::BuilderExternalsDisallowed);
|
||||
}
|
||||
if (ctype != Value::CType::VoidPtr) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give void pointer for ValueType::External");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give void pointer for ValueType::External");
|
||||
}
|
||||
reserveSpace(1 + sizeof(void*));
|
||||
// store pointer. this doesn't need to be portable
|
||||
|
@ -497,16 +494,17 @@ uint8_t* Builder::set (Value const& item) {
|
|||
vv = static_cast<int64_t>(item.getUInt64());
|
||||
break;
|
||||
default:
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::SmallInt");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give number for ValueType::SmallInt");
|
||||
}
|
||||
if (vv < -6 || vv > 9) {
|
||||
throw Exception(Exception::NumberOutOfRange, "Number out of range of ValueType::SmallInt");
|
||||
throw Exception(Exception::NumberOutOfRange,
|
||||
"Number out of range of ValueType::SmallInt");
|
||||
}
|
||||
reserveSpace(1);
|
||||
if (vv >= 0) {
|
||||
_start[_pos++] = static_cast<uint8_t>(vv + 0x30);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_start[_pos++] = static_cast<uint8_t>(vv + 0x40);
|
||||
}
|
||||
break;
|
||||
|
@ -524,7 +522,8 @@ uint8_t* Builder::set (Value const& item) {
|
|||
v = toInt64(item.getUInt64());
|
||||
break;
|
||||
default:
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::Int");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give number for ValueType::Int");
|
||||
}
|
||||
addInt(v);
|
||||
break;
|
||||
|
@ -534,13 +533,17 @@ uint8_t* Builder::set (Value const& item) {
|
|||
switch (ctype) {
|
||||
case Value::CType::Double:
|
||||
if (item.getDouble() < 0.0) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give non-negative number for ValueType::UInt");
|
||||
throw Exception(
|
||||
Exception::BuilderUnexpectedValue,
|
||||
"Must give non-negative number for ValueType::UInt");
|
||||
}
|
||||
v = static_cast<uint64_t>(item.getDouble());
|
||||
break;
|
||||
case Value::CType::Int64:
|
||||
if (item.getInt64() < 0) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give non-negative number for ValueType::UInt");
|
||||
throw Exception(
|
||||
Exception::BuilderUnexpectedValue,
|
||||
"Must give non-negative number for ValueType::UInt");
|
||||
}
|
||||
v = static_cast<uint64_t>(item.getInt64());
|
||||
break;
|
||||
|
@ -548,7 +551,8 @@ uint8_t* Builder::set (Value const& item) {
|
|||
v = item.getUInt64();
|
||||
break;
|
||||
default:
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::UInt");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give number for ValueType::UInt");
|
||||
}
|
||||
addUInt(v);
|
||||
break;
|
||||
|
@ -566,22 +570,23 @@ uint8_t* Builder::set (Value const& item) {
|
|||
v = toInt64(item.getUInt64());
|
||||
break;
|
||||
default:
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::UTCDate");
|
||||
throw Exception(Exception::BuilderUnexpectedValue,
|
||||
"Must give number for ValueType::UTCDate");
|
||||
}
|
||||
addUTCDate(v);
|
||||
break;
|
||||
}
|
||||
case ValueType::String: {
|
||||
if (ctype != Value::CType::String &&
|
||||
ctype != Value::CType::CharPtr) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must give a string or char const* for ValueType::String");
|
||||
if (ctype != Value::CType::String && ctype != Value::CType::CharPtr) {
|
||||
throw Exception(
|
||||
Exception::BuilderUnexpectedValue,
|
||||
"Must give a string or char const* for ValueType::String");
|
||||
}
|
||||
std::string const* s;
|
||||
std::string value;
|
||||
if (ctype == Value::CType::String) {
|
||||
s = item.getString();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
value = item.getCharPtr();
|
||||
s = &value;
|
||||
}
|
||||
|
@ -591,8 +596,7 @@ uint8_t* Builder::set (Value const& item) {
|
|||
reserveSpace(1 + size);
|
||||
_start[_pos++] = static_cast<uint8_t>(0x40 + size);
|
||||
memcpy(_start + _pos, s->c_str(), size);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// long string
|
||||
reserveSpace(1 + 8 + size);
|
||||
_start[_pos++] = 0xbf;
|
||||
|
@ -611,16 +615,16 @@ uint8_t* Builder::set (Value const& item) {
|
|||
break;
|
||||
}
|
||||
case ValueType::Binary: {
|
||||
if (ctype != Value::CType::String &&
|
||||
ctype != Value::CType::CharPtr) {
|
||||
throw Exception(Exception::BuilderUnexpectedValue, "Must provide std::string or char const* for ValueType::Binary");
|
||||
if (ctype != Value::CType::String && ctype != Value::CType::CharPtr) {
|
||||
throw Exception(
|
||||
Exception::BuilderUnexpectedValue,
|
||||
"Must provide std::string or char const* for ValueType::Binary");
|
||||
}
|
||||
std::string const* s;
|
||||
std::string value;
|
||||
if (ctype == Value::CType::String) {
|
||||
s = item.getString();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
value = item.getCharPtr();
|
||||
s = &value;
|
||||
}
|
||||
|
@ -644,7 +648,8 @@ uint8_t* Builder::set (Value const& item) {
|
|||
throw Exception(Exception::NotImplemented);
|
||||
}
|
||||
case ValueType::Custom: {
|
||||
throw Exception(Exception::BuilderUnexpectedType, "Cannot set a ValueType::Custom with this method");
|
||||
throw Exception(Exception::BuilderUnexpectedType,
|
||||
"Cannot set a ValueType::Custom with this method");
|
||||
}
|
||||
}
|
||||
return oldPos;
|
||||
|
@ -669,8 +674,7 @@ uint8_t* Builder::set (ValuePair const& pair) {
|
|||
memcpy(_start + _pos, pair.getStart(), v);
|
||||
_pos += v;
|
||||
return nullptr; // unused here
|
||||
}
|
||||
else if (pair.valueType() == ValueType::String) {
|
||||
} else if (pair.valueType() == ValueType::String) {
|
||||
uint64_t size = pair.getSize();
|
||||
if (size > 126) {
|
||||
// long string
|
||||
|
@ -678,8 +682,7 @@ uint8_t* Builder::set (ValuePair const& pair) {
|
|||
_start[_pos++] = 0xbf;
|
||||
appendLength(size, 8);
|
||||
_pos += size;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// short string
|
||||
reserveSpace(1 + size);
|
||||
_start[_pos++] = static_cast<uint8_t>(0x40 + size);
|
||||
|
@ -690,8 +693,7 @@ uint8_t* Builder::set (ValuePair const& pair) {
|
|||
// _start + _pos - size .. _start + _pos - 1
|
||||
// with valid UTF-8!
|
||||
return _start + _pos - size;
|
||||
}
|
||||
else if (pair.valueType() == ValueType::Custom) {
|
||||
} else if (pair.valueType() == ValueType::Custom) {
|
||||
// We only reserve space here, the caller has to fill in the custom type
|
||||
uint64_t size = pair.getSize();
|
||||
reserveSpace(size);
|
||||
|
@ -702,7 +704,9 @@ uint8_t* Builder::set (ValuePair const& pair) {
|
|||
_pos += size;
|
||||
return _start + _pos - size;
|
||||
}
|
||||
throw Exception(Exception::BuilderUnexpectedType, "Only ValueType::Binary, ValueType::String and ValueType::Custom are valid for ValuePair argument");
|
||||
throw Exception(Exception::BuilderUnexpectedType,
|
||||
"Only ValueType::Binary, ValueType::String and "
|
||||
"ValueType::Custom are valid for ValuePair argument");
|
||||
}
|
||||
|
||||
void Builder::checkAttributeUniqueness(Slice const& obj) const {
|
||||
|
@ -719,7 +723,8 @@ void Builder::checkAttributeUniqueness (Slice const& obj) const {
|
|||
for (ValueLength i = 1; i < n; ++i) {
|
||||
Slice current = obj.keyAt(i);
|
||||
if (!current.isString()) {
|
||||
throw Exception(Exception::BuilderUnexpectedType, "Expecting String key");
|
||||
throw Exception(Exception::BuilderUnexpectedType,
|
||||
"Expecting String key");
|
||||
}
|
||||
|
||||
ValueLength len2;
|
||||
|
@ -733,14 +738,14 @@ void Builder::checkAttributeUniqueness (Slice const& obj) const {
|
|||
len = len2;
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::unordered_set<std::string> keys;
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
Slice key = obj.keyAt(i);
|
||||
if (!key.isString()) {
|
||||
throw Exception(Exception::BuilderUnexpectedType, "Expecting String key");
|
||||
throw Exception(Exception::BuilderUnexpectedType,
|
||||
"Expecting String key");
|
||||
}
|
||||
|
||||
if (!keys.emplace(key.copyString()).second) {
|
||||
|
@ -762,17 +767,12 @@ uint8_t* Builder::add (std::string const& attrName, Slice const& sub) {
|
|||
return addInternal<Slice>(attrName, sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (Value const& sub) {
|
||||
return addInternal<Value>(sub);
|
||||
}
|
||||
uint8_t* Builder::add(Value const& sub) { return addInternal<Value>(sub); }
|
||||
|
||||
uint8_t* Builder::add(ValuePair const& sub) {
|
||||
return addInternal<ValuePair>(sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (Slice const& sub) {
|
||||
return addInternal<Slice>(sub);
|
||||
}
|
||||
uint8_t* Builder::add(Slice const& sub) { return addInternal<Slice>(sub); }
|
||||
|
||||
static_assert(sizeof(double) == 8, "double is not 8 bytes");
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
using namespace arangodb::velocypack;
|
||||
|
||||
// convert a vector of strings into an unordered_set of strings
|
||||
static inline std::unordered_set<std::string> ToSet (std::vector<std::string> const& keys) {
|
||||
static inline std::unordered_set<std::string> ToSet(
|
||||
std::vector<std::string> const& keys) {
|
||||
std::unordered_set<std::string> s;
|
||||
for (auto const& it : keys) {
|
||||
s.emplace(it);
|
||||
|
@ -44,7 +45,9 @@ static inline std::unordered_set<std::string> ToSet (std::vector<std::string> co
|
|||
return s;
|
||||
}
|
||||
|
||||
void Collection::forEach (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
void Collection::forEach(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
ArrayIterator it(slice);
|
||||
ValueLength index = 0;
|
||||
|
||||
|
@ -58,7 +61,9 @@ void Collection::forEach (Slice const& slice, std::function<bool(Slice const&, V
|
|||
}
|
||||
}
|
||||
|
||||
Builder Collection::filter (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
Builder Collection::filter(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
// construct a new Array
|
||||
Builder b;
|
||||
b.add(Value(ValueType::Array));
|
||||
|
@ -78,7 +83,9 @@ Builder Collection::filter (Slice const& slice, std::function<bool(Slice const&,
|
|||
return b;
|
||||
}
|
||||
|
||||
Slice Collection::find (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
Slice Collection::find(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
ArrayIterator it(slice);
|
||||
ValueLength index = 0;
|
||||
|
||||
|
@ -94,7 +101,9 @@ Slice Collection::find (Slice const& slice, std::function<bool(Slice const&, Val
|
|||
return Slice();
|
||||
}
|
||||
|
||||
bool Collection::contains (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
bool Collection::contains(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
ArrayIterator it(slice);
|
||||
ValueLength index = 0;
|
||||
|
||||
|
@ -110,7 +119,8 @@ bool Collection::contains (Slice const& slice, std::function<bool(Slice const&,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Collection::all (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
bool Collection::all(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
ArrayIterator it(slice);
|
||||
ValueLength index = 0;
|
||||
|
||||
|
@ -126,7 +136,8 @@ bool Collection::all (Slice const& slice, std::function<bool(Slice const&, Value
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Collection::any (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
bool Collection::any(Slice const& slice,
|
||||
std::function<bool(Slice const&, ValueLength)> const& cb) {
|
||||
ArrayIterator it(slice);
|
||||
ValueLength index = 0;
|
||||
|
||||
|
@ -162,7 +173,8 @@ void Collection::keys (Slice const& slice, std::vector<std::string>& result) {
|
|||
}
|
||||
}
|
||||
|
||||
void Collection::keys (Slice const& slice, std::unordered_set<std::string>& result) {
|
||||
void Collection::keys(Slice const& slice,
|
||||
std::unordered_set<std::string>& result) {
|
||||
ObjectIterator it(slice);
|
||||
|
||||
while (it.valid()) {
|
||||
|
@ -186,7 +198,8 @@ Builder Collection::values (Slice const& slice) {
|
|||
return b;
|
||||
}
|
||||
|
||||
Builder Collection::keep (Slice const& slice, std::vector<std::string> const& keys) {
|
||||
Builder Collection::keep(Slice const& slice,
|
||||
std::vector<std::string> const& keys) {
|
||||
// check if there are so many keys that we want to use the hash-based version
|
||||
// cut-off values are arbitrary...
|
||||
if (keys.size() >= 4 && slice.length() > 10) {
|
||||
|
@ -210,7 +223,8 @@ Builder Collection::keep (Slice const& slice, std::vector<std::string> const& ke
|
|||
return b;
|
||||
}
|
||||
|
||||
Builder Collection::keep (Slice const& slice, std::unordered_set<std::string> const& keys) {
|
||||
Builder Collection::keep(Slice const& slice,
|
||||
std::unordered_set<std::string> const& keys) {
|
||||
Builder b;
|
||||
b.add(Value(ValueType::Object));
|
||||
|
||||
|
@ -228,7 +242,8 @@ Builder Collection::keep (Slice const& slice, std::unordered_set<std::string> co
|
|||
return b;
|
||||
}
|
||||
|
||||
Builder Collection::remove (Slice const& slice, std::vector<std::string> const& keys) {
|
||||
Builder Collection::remove(Slice const& slice,
|
||||
std::vector<std::string> const& keys) {
|
||||
// check if there are so many keys that we want to use the hash-based version
|
||||
// cut-off values are arbitrary...
|
||||
if (keys.size() >= 4 && slice.length() > 10) {
|
||||
|
@ -252,7 +267,8 @@ Builder Collection::remove (Slice const& slice, std::vector<std::string> const&
|
|||
return b;
|
||||
}
|
||||
|
||||
Builder Collection::remove (Slice const& slice, std::unordered_set<std::string> const& keys) {
|
||||
Builder Collection::remove(Slice const& slice,
|
||||
std::unordered_set<std::string> const& keys) {
|
||||
Builder b;
|
||||
b.add(Value(ValueType::Object));
|
||||
|
||||
|
@ -270,7 +286,8 @@ Builder Collection::remove (Slice const& slice, std::unordered_set<std::string>
|
|||
return b;
|
||||
}
|
||||
|
||||
Builder Collection::merge (Slice const& left, Slice const& right, bool mergeValues) {
|
||||
Builder Collection::merge(Slice const& left, Slice const& right,
|
||||
bool mergeValues) {
|
||||
if (!left.isObject() || !right.isObject()) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Object");
|
||||
}
|
||||
|
@ -297,13 +314,12 @@ Builder Collection::merge (Slice const& left, Slice const& right, bool mergeValu
|
|||
if (found == rightValues.end()) {
|
||||
// use left value
|
||||
b.add(key, it.value());
|
||||
}
|
||||
else if (mergeValues && it.value().isObject() && (*found).second.isObject()) {
|
||||
} else if (mergeValues && it.value().isObject() &&
|
||||
(*found).second.isObject()) {
|
||||
// merge both values
|
||||
Builder sub = Collection::merge(it.value(), (*found).second, true);
|
||||
b.add(key, sub.slice());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// use right value
|
||||
b.add(key, (*found).second);
|
||||
// clear the value in the map so its not added again
|
||||
|
@ -326,10 +342,14 @@ Builder Collection::merge (Slice const& left, Slice const& right, bool mergeValu
|
|||
}
|
||||
|
||||
template <Collection::VisitationOrder order>
|
||||
static bool doVisit (Slice const& slice, std::function<bool(Slice const& key, Slice const& value)> const& func);
|
||||
static bool doVisit(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const& key, Slice const& value)> const& func);
|
||||
|
||||
template <Collection::VisitationOrder order>
|
||||
static bool visitObject (Slice const& value, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
static bool visitObject(
|
||||
Slice const& value,
|
||||
std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
ObjectIterator it(value);
|
||||
|
||||
while (it.valid()) {
|
||||
|
@ -359,7 +379,9 @@ static bool visitObject (Slice const& value, std::function<bool(Slice const& key
|
|||
}
|
||||
|
||||
template <Collection::VisitationOrder order>
|
||||
static bool visitArray (Slice const& value, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
static bool visitArray(
|
||||
Slice const& value,
|
||||
std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
ArrayIterator it(value);
|
||||
|
||||
while (it.valid()) {
|
||||
|
@ -390,7 +412,9 @@ static bool visitArray (Slice const& value, std::function<bool(Slice const& key,
|
|||
}
|
||||
|
||||
template <Collection::VisitationOrder order>
|
||||
static bool doVisit (Slice const& slice, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
static bool doVisit(
|
||||
Slice const& slice,
|
||||
std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
if (slice.isObject()) {
|
||||
return visitObject<order>(slice, func);
|
||||
}
|
||||
|
@ -398,15 +422,16 @@ static bool doVisit (Slice const& slice, std::function<bool(Slice const& key, Sl
|
|||
return visitArray<order>(slice, func);
|
||||
}
|
||||
|
||||
throw Exception(Exception::InvalidValueType, "Expecting type Object or Array");
|
||||
throw Exception(Exception::InvalidValueType,
|
||||
"Expecting type Object or Array");
|
||||
}
|
||||
|
||||
void Collection::visitRecursive (Slice const& slice, Collection::VisitationOrder order, std::function<bool(Slice const&, Slice const&)> const& func) {
|
||||
void Collection::visitRecursive(
|
||||
Slice const& slice, Collection::VisitationOrder order,
|
||||
std::function<bool(Slice const&, Slice const&)> const& func) {
|
||||
if (order == Collection::PreOrder) {
|
||||
doVisit<Collection::PreOrder>(slice, func);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
doVisit<Collection::PostOrder>(slice, func);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,25 +41,63 @@ namespace arangodb {
|
|||
};
|
||||
|
||||
void Dumper::appendUInt(uint64_t v) {
|
||||
if (10000000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000000ULL) % 10); }
|
||||
if ( 1000000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000000ULL) % 10); }
|
||||
if ( 100000000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000000ULL) % 10); }
|
||||
if ( 10000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000ULL) % 10); }
|
||||
if ( 1000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000ULL) % 10); }
|
||||
if ( 100000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000ULL) % 10); }
|
||||
if ( 10000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000ULL) % 10); }
|
||||
if ( 1000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000ULL) % 10); }
|
||||
if ( 100000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000ULL) % 10); }
|
||||
if ( 10000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000ULL) % 10); }
|
||||
if ( 1000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000ULL) % 10); }
|
||||
if ( 100000000ULL <= v) { _sink->push_back('0' + (v / 100000000ULL) % 10); }
|
||||
if ( 10000000ULL <= v) { _sink->push_back('0' + (v / 10000000ULL) % 10); }
|
||||
if ( 1000000ULL <= v) { _sink->push_back('0' + (v / 1000000ULL) % 10); }
|
||||
if ( 100000ULL <= v) { _sink->push_back('0' + (v / 100000ULL) % 10); }
|
||||
if ( 10000ULL <= v) { _sink->push_back('0' + (v / 10000ULL) % 10); }
|
||||
if ( 1000ULL <= v) { _sink->push_back('0' + (v / 1000ULL) % 10); }
|
||||
if ( 100ULL <= v) { _sink->push_back('0' + (v / 100ULL) % 10); }
|
||||
if ( 10ULL <= v) { _sink->push_back('0' + (v / 10ULL) % 10); }
|
||||
if (10000000000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000000000000ULL) % 10);
|
||||
}
|
||||
if (1000000000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000000000ULL) % 10);
|
||||
}
|
||||
if (100000000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000000000ULL) % 10);
|
||||
}
|
||||
if (10000000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000000000ULL) % 10);
|
||||
}
|
||||
if (1000000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000000ULL) % 10);
|
||||
}
|
||||
if (100000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000000ULL) % 10);
|
||||
}
|
||||
if (10000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000000ULL) % 10);
|
||||
}
|
||||
if (1000000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000ULL) % 10);
|
||||
}
|
||||
if (100000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000ULL) % 10);
|
||||
}
|
||||
if (10000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000ULL) % 10);
|
||||
}
|
||||
if (1000000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000ULL) % 10);
|
||||
}
|
||||
if (100000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000ULL) % 10);
|
||||
}
|
||||
if (10000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000ULL) % 10);
|
||||
}
|
||||
if (1000000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000ULL) % 10);
|
||||
}
|
||||
if (100000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100000ULL) % 10);
|
||||
}
|
||||
if (10000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10000ULL) % 10);
|
||||
}
|
||||
if (1000ULL <= v) {
|
||||
_sink->push_back('0' + (v / 1000ULL) % 10);
|
||||
}
|
||||
if (100ULL <= v) {
|
||||
_sink->push_back('0' + (v / 100ULL) % 10);
|
||||
}
|
||||
if (10ULL <= v) {
|
||||
_sink->push_back('0' + (v / 10ULL) % 10);
|
||||
}
|
||||
|
||||
_sink->push_back('0' + (v % 10));
|
||||
}
|
||||
|
@ -69,8 +107,7 @@ void Dumper::dumpInteger (Slice const* slice) {
|
|||
uint64_t v = slice->getUInt();
|
||||
|
||||
appendUInt(v);
|
||||
}
|
||||
else if (slice->isType(ValueType::Int)) {
|
||||
} else if (slice->isType(ValueType::Int)) {
|
||||
int64_t v = slice->getInt();
|
||||
if (v == INT64_MIN) {
|
||||
_sink->append("-9223372036854775808", 20);
|
||||
|
@ -81,60 +118,108 @@ void Dumper::dumpInteger (Slice const* slice) {
|
|||
v = -v;
|
||||
}
|
||||
|
||||
if (1000000000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000000000LL) % 10); }
|
||||
if ( 100000000000000000LL <= v) { _sink->push_back('0' + (v / 100000000000000000LL) % 10); }
|
||||
if ( 10000000000000000LL <= v) { _sink->push_back('0' + (v / 10000000000000000LL) % 10); }
|
||||
if ( 1000000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000000LL) % 10); }
|
||||
if ( 100000000000000LL <= v) { _sink->push_back('0' + (v / 100000000000000LL) % 10); }
|
||||
if ( 10000000000000LL <= v) { _sink->push_back('0' + (v / 10000000000000LL) % 10); }
|
||||
if ( 1000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000LL) % 10); }
|
||||
if ( 100000000000LL <= v) { _sink->push_back('0' + (v / 100000000000LL) % 10); }
|
||||
if ( 10000000000LL <= v) { _sink->push_back('0' + (v / 10000000000LL) % 10); }
|
||||
if ( 1000000000LL <= v) { _sink->push_back('0' + (v / 1000000000LL) % 10); }
|
||||
if ( 100000000LL <= v) { _sink->push_back('0' + (v / 100000000LL) % 10); }
|
||||
if ( 10000000LL <= v) { _sink->push_back('0' + (v / 10000000LL) % 10); }
|
||||
if ( 1000000LL <= v) { _sink->push_back('0' + (v / 1000000LL) % 10); }
|
||||
if ( 100000LL <= v) { _sink->push_back('0' + (v / 100000LL) % 10); }
|
||||
if ( 10000LL <= v) { _sink->push_back('0' + (v / 10000LL) % 10); }
|
||||
if ( 1000LL <= v) { _sink->push_back('0' + (v / 1000LL) % 10); }
|
||||
if ( 100LL <= v) { _sink->push_back('0' + (v / 100LL) % 10); }
|
||||
if ( 10LL <= v) { _sink->push_back('0' + (v / 10LL) % 10); }
|
||||
if (1000000000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000000000LL) % 10);
|
||||
}
|
||||
if (100000000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000000000LL) % 10);
|
||||
}
|
||||
if (10000000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000000000LL) % 10);
|
||||
}
|
||||
if (1000000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000000LL) % 10);
|
||||
}
|
||||
if (100000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000000LL) % 10);
|
||||
}
|
||||
if (10000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000000LL) % 10);
|
||||
}
|
||||
if (1000000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000000LL) % 10);
|
||||
}
|
||||
if (100000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000000LL) % 10);
|
||||
}
|
||||
if (10000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000000LL) % 10);
|
||||
}
|
||||
if (1000000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000000LL) % 10);
|
||||
}
|
||||
if (100000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 100000000LL) % 10);
|
||||
}
|
||||
if (10000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 10000000LL) % 10);
|
||||
}
|
||||
if (1000000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000000LL) % 10);
|
||||
}
|
||||
if (100000LL <= v) {
|
||||
_sink->push_back('0' + (v / 100000LL) % 10);
|
||||
}
|
||||
if (10000LL <= v) {
|
||||
_sink->push_back('0' + (v / 10000LL) % 10);
|
||||
}
|
||||
if (1000LL <= v) {
|
||||
_sink->push_back('0' + (v / 1000LL) % 10);
|
||||
}
|
||||
if (100LL <= v) {
|
||||
_sink->push_back('0' + (v / 100LL) % 10);
|
||||
}
|
||||
if (10LL <= v) {
|
||||
_sink->push_back('0' + (v / 10LL) % 10);
|
||||
}
|
||||
|
||||
_sink->push_back('0' + (v % 10));
|
||||
}
|
||||
else if (slice->isType(ValueType::SmallInt)) {
|
||||
} else if (slice->isType(ValueType::SmallInt)) {
|
||||
int64_t v = slice->getSmallInt();
|
||||
if (v < 0) {
|
||||
_sink->push_back('-');
|
||||
v = -v;
|
||||
}
|
||||
_sink->push_back('0' + static_cast<char>(v));
|
||||
}
|
||||
else {
|
||||
throw Exception(Exception::InternalError, "Unexpected number type");
|
||||
} else {
|
||||
// we should never get here
|
||||
throw Exception(Exception::InvalidValueType, "Unexpected number type");
|
||||
}
|
||||
}
|
||||
|
||||
void Dumper::dumpString(char const* src, ValueLength len) {
|
||||
static char const EscapeTable[256] = {
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
|
||||
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', // 20
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30~4F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60~FF
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E
|
||||
// F
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r',
|
||||
'u',
|
||||
'u', // 00
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
'u',
|
||||
'u', // 10
|
||||
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
'/', // 20
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, // 30~4F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'\\', 0, 0, 0, // 50
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, // 60~FF
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0};
|
||||
|
||||
uint8_t const* p = reinterpret_cast<uint8_t const*>(src);
|
||||
uint8_t const* e = p + len;
|
||||
|
@ -157,15 +242,15 @@ void Dumper::dumpString (char const* src, ValueLength len) {
|
|||
uint16_t i2 = (((uint16_t)c) & 0x0f);
|
||||
|
||||
_sink->append("00", 2);
|
||||
_sink->push_back(static_cast<char>((i1 < 10) ? ('0' + i1) : ('A' + i1 - 10)));
|
||||
_sink->push_back(static_cast<char>((i2 < 10) ? ('0' + i2) : ('A' + i2 - 10)));
|
||||
_sink->push_back(
|
||||
static_cast<char>((i1 < 10) ? ('0' + i1) : ('A' + i1 - 10)));
|
||||
_sink->push_back(
|
||||
static_cast<char>((i2 < 10) ? ('0' + i2) : ('A' + i2 - 10)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_sink->push_back(static_cast<char>(c));
|
||||
}
|
||||
}
|
||||
else if ((c & 0xe0) == 0xc0) {
|
||||
} else if ((c & 0xe0) == 0xc0) {
|
||||
// two-byte sequence
|
||||
if (p + 1 >= e) {
|
||||
throw Exception(Exception::InvalidUtf8Sequence);
|
||||
|
@ -173,8 +258,7 @@ void Dumper::dumpString (char const* src, ValueLength len) {
|
|||
|
||||
_sink->append(reinterpret_cast<char const*>(p), 2);
|
||||
++p;
|
||||
}
|
||||
else if ((c & 0xf0) == 0xe0) {
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
// three-byte sequence
|
||||
if (p + 2 >= e) {
|
||||
throw Exception(Exception::InvalidUtf8Sequence);
|
||||
|
@ -182,8 +266,7 @@ void Dumper::dumpString (char const* src, ValueLength len) {
|
|||
|
||||
_sink->append(reinterpret_cast<char const*>(p), 3);
|
||||
p += 2;
|
||||
}
|
||||
else if ((c & 0xf8) == 0xf0) {
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
// four-byte sequence
|
||||
if (p + 3 >= e) {
|
||||
throw Exception(Exception::InvalidUtf8Sequence);
|
||||
|
@ -217,8 +300,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
|
|||
case ValueType::Bool: {
|
||||
if (slice->getBool()) {
|
||||
_sink->append("true", 4);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_sink->append("false", 5);
|
||||
}
|
||||
break;
|
||||
|
@ -241,8 +323,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
|
|||
}
|
||||
--_indentation;
|
||||
indent();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
while (it.valid()) {
|
||||
if (!it.isFirst()) {
|
||||
_sink->push_back(',');
|
||||
|
@ -274,8 +355,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
|
|||
}
|
||||
--_indentation;
|
||||
indent();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
while (it.valid()) {
|
||||
if (!it.isFirst()) {
|
||||
_sink->push_back(',');
|
||||
|
@ -294,8 +374,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
|
|||
double const v = slice->getDouble();
|
||||
if (std::isnan(v) || !std::isfinite(v)) {
|
||||
handleUnsupportedType(slice);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
char temp[24];
|
||||
int len = fpconv_dtoa(v, &temp[0]);
|
||||
_sink->append(&temp[0], static_cast<ValueLength>(len));
|
||||
|
@ -350,8 +429,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
|
|||
case ValueType::Custom: {
|
||||
if (options->customTypeHandler == nullptr) {
|
||||
handleUnsupportedType(slice);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
options->customTypeHandler->toJson(*slice, this, *base);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -39,4 +39,3 @@ std::ostream& operator<< (std::ostream& stream, Exception const* ex) {
|
|||
std::ostream& operator<<(std::ostream& stream, Exception const& ex) {
|
||||
return operator<<(stream, &ex);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,4 +65,3 @@ std::ostream& operator<< (std::ostream& stream, HexDump const* hexdump) {
|
|||
std::ostream& operator<<(std::ostream& stream, HexDump const& hexdump) {
|
||||
return operator<<(stream, &hexdump);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,4 +48,3 @@ std::ostream& operator<< (std::ostream& stream, ObjectIterator const* it) {
|
|||
std::ostream& operator<<(std::ostream& stream, ObjectIterator const& it) {
|
||||
return operator<<(stream, &it);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,4 +31,3 @@ using namespace arangodb::velocypack;
|
|||
|
||||
// default options instance
|
||||
Options Options::Defaults;
|
||||
|
||||
|
|
|
@ -41,9 +41,7 @@ ValueLength Parser::parseInternal (bool multi) {
|
|||
_b.options = options; // copy over options
|
||||
|
||||
// skip over optional BOM
|
||||
if (_size >= 3 &&
|
||||
_start[0] == 0xef &&
|
||||
_start[1] == 0xbb &&
|
||||
if (_size >= 3 && _start[0] == 0xef && _start[1] == 0xbb &&
|
||||
_start[2] == 0xbf) {
|
||||
// found UTF-8 BOM. simply skip over it
|
||||
_pos += 3;
|
||||
|
@ -53,16 +51,14 @@ ValueLength Parser::parseInternal (bool multi) {
|
|||
do {
|
||||
parseJson();
|
||||
nr++;
|
||||
while (_pos < _size &&
|
||||
isWhiteSpace(_start[_pos])) {
|
||||
while (_pos < _size && isWhiteSpace(_start[_pos])) {
|
||||
++_pos;
|
||||
}
|
||||
if (!multi && _pos != _size) {
|
||||
consume(); // to get error reporting right
|
||||
throw Exception(Exception::ParseError, "Expecting EOF");
|
||||
}
|
||||
}
|
||||
while (multi && _pos < _size);
|
||||
} while (multi && _pos < _size);
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
@ -123,23 +119,18 @@ void Parser::parseNumber () {
|
|||
if (!numberValue.isInteger) {
|
||||
if (negative) {
|
||||
_b.addDouble(-numberValue.doubleValue);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_b.addDouble(numberValue.doubleValue);
|
||||
}
|
||||
}
|
||||
else if (negative) {
|
||||
} else if (negative) {
|
||||
if (numberValue.intValue <= static_cast<uint64_t>(INT64_MAX)) {
|
||||
_b.addInt(-static_cast<int64_t>(numberValue.intValue));
|
||||
}
|
||||
else if (numberValue.intValue == toUInt64(INT64_MIN)) {
|
||||
} else if (numberValue.intValue == toUInt64(INT64_MIN)) {
|
||||
_b.addInt(INT64_MIN);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_b.addDouble(-static_cast<double>(numberValue.intValue));
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_b.addUInt(numberValue.intValue);
|
||||
}
|
||||
return;
|
||||
|
@ -156,8 +147,7 @@ void Parser::parseNumber () {
|
|||
fractionalPart = scanDigitsFractional();
|
||||
if (negative) {
|
||||
fractionalPart = -numberValue.asDouble() - fractionalPart;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fractionalPart = numberValue.asDouble() + fractionalPart;
|
||||
}
|
||||
i = consume();
|
||||
|
@ -165,12 +155,10 @@ void Parser::parseNumber () {
|
|||
_b.addDouble(fractionalPart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (negative) {
|
||||
fractionalPart = -numberValue.asDouble();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fractionalPart = numberValue.asDouble();
|
||||
}
|
||||
}
|
||||
|
@ -193,8 +181,7 @@ void Parser::parseNumber () {
|
|||
scanDigits(exponent);
|
||||
if (negative) {
|
||||
fractionalPart *= pow(10, -exponent.asDouble());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fractionalPart *= pow(10, exponent.asDouble());
|
||||
}
|
||||
if (std::isnan(fractionalPart) || !std::isfinite(fractionalPart)) {
|
||||
|
@ -225,8 +212,7 @@ void Parser::parseString () {
|
|||
if (options->validateUtf8Strings) {
|
||||
count = JSONStringCopyCheckUtf8(_b._start + _b._pos, _start + _pos,
|
||||
remainder);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
count = JSONStringCopy(_b._start + _b._pos, _start + _pos, remainder);
|
||||
}
|
||||
_pos += count;
|
||||
|
@ -236,8 +222,7 @@ void Parser::parseString () {
|
|||
if (!large && _b._pos - (base + 1) > 126) {
|
||||
large = true;
|
||||
_b.reserveSpace(8);
|
||||
memmove(_b._start + base + 9, _b._start + base + 1,
|
||||
_b._pos - (base + 1));
|
||||
memmove(_b._start + base + 9, _b._start + base + 1, _b._pos - (base + 1));
|
||||
_b._pos += 8;
|
||||
}
|
||||
switch (i) {
|
||||
|
@ -247,8 +232,7 @@ void Parser::parseString () {
|
|||
len = _b._pos - (base + 1);
|
||||
_b._start[base] = 0x40 + static_cast<uint8_t>(len);
|
||||
// String is ready
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
len = _b._pos - (base + 9);
|
||||
_b._start[base] = 0xbf;
|
||||
for (ValueLength i = 1; i <= 8; i++) {
|
||||
|
@ -301,37 +285,32 @@ void Parser::parseString () {
|
|||
for (int j = 0; j < 4; j++) {
|
||||
i = consume();
|
||||
if (i < 0) {
|
||||
throw Exception(Exception::ParseError, "Unfinished \\uXXXX escape sequence");
|
||||
throw Exception(Exception::ParseError,
|
||||
"Unfinished \\uXXXX escape sequence");
|
||||
}
|
||||
if (i >= '0' && i <= '9') {
|
||||
v = (v << 4) + i - '0';
|
||||
}
|
||||
else if (i >= 'a' && i <= 'f') {
|
||||
} else if (i >= 'a' && i <= 'f') {
|
||||
v = (v << 4) + i - 'a' + 10;
|
||||
}
|
||||
else if (i >= 'A' && i <= 'F') {
|
||||
} else if (i >= 'A' && i <= 'F') {
|
||||
v = (v << 4) + i - 'A' + 10;
|
||||
}
|
||||
else {
|
||||
throw Exception(Exception::ParseError, "Illegal \\uXXXX escape sequence");
|
||||
} else {
|
||||
throw Exception(Exception::ParseError,
|
||||
"Illegal \\uXXXX escape sequence");
|
||||
}
|
||||
}
|
||||
if (v < 0x80) {
|
||||
_b.reserveSpace(1);
|
||||
_b._start[_b._pos++] = static_cast<uint8_t>(v);
|
||||
highSurrogate = 0;
|
||||
}
|
||||
else if (v < 0x800) {
|
||||
} else if (v < 0x800) {
|
||||
_b.reserveSpace(2);
|
||||
_b._start[_b._pos++] = 0xc0 + (v >> 6);
|
||||
_b._start[_b._pos++] = 0x80 + (v & 0x3f);
|
||||
highSurrogate = 0;
|
||||
}
|
||||
else if (v >= 0xdc00 && v < 0xe000 &&
|
||||
highSurrogate != 0) {
|
||||
} else if (v >= 0xdc00 && v < 0xe000 && highSurrogate != 0) {
|
||||
// Low surrogate, put the two together:
|
||||
v = 0x10000 + ((highSurrogate - 0xd800) << 10)
|
||||
+ v - 0xdc00;
|
||||
v = 0x10000 + ((highSurrogate - 0xd800) << 10) + v - 0xdc00;
|
||||
_b._pos -= 3;
|
||||
_b.reserveSpace(4);
|
||||
_b._start[_b._pos++] = 0xf0 + (v >> 18);
|
||||
|
@ -339,13 +318,11 @@ void Parser::parseString () {
|
|||
_b._start[_b._pos++] = 0x80 + ((v >> 6) & 0x3f);
|
||||
_b._start[_b._pos++] = 0x80 + (v & 0x3f);
|
||||
highSurrogate = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (v >= 0xd800 && v < 0xdc00) {
|
||||
// High surrogate:
|
||||
highSurrogate = v;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
highSurrogate = 0;
|
||||
}
|
||||
_b.reserveSpace(3);
|
||||
|
@ -369,32 +346,26 @@ void Parser::parseString () {
|
|||
highSurrogate = 0;
|
||||
_b.reserveSpace(1);
|
||||
_b._start[_b._pos++] = static_cast<uint8_t>(i);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!options->validateUtf8Strings) {
|
||||
highSurrogate = 0;
|
||||
_b.reserveSpace(1);
|
||||
_b._start[_b._pos++] = static_cast<uint8_t>(i);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// multi-byte UTF-8 sequence!
|
||||
int follow = 0;
|
||||
if ((i & 0xe0) == 0x80) {
|
||||
throw Exception(Exception::InvalidUtf8Sequence);
|
||||
}
|
||||
else if ((i & 0xe0) == 0xc0) {
|
||||
} else if ((i & 0xe0) == 0xc0) {
|
||||
// two-byte sequence
|
||||
follow = 1;
|
||||
}
|
||||
else if ((i & 0xf0) == 0xe0) {
|
||||
} else if ((i & 0xf0) == 0xe0) {
|
||||
// three-byte sequence
|
||||
follow = 2;
|
||||
}
|
||||
else if ((i & 0xf8) == 0xf0) {
|
||||
} else if ((i & 0xf8) == 0xf0) {
|
||||
// four-byte sequence
|
||||
follow = 3;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw Exception(Exception::InvalidUtf8Sequence);
|
||||
}
|
||||
|
||||
|
@ -483,10 +454,10 @@ void Parser::parseObject () {
|
|||
auto const lastPos = _b._pos;
|
||||
if (options->attributeExcludeHandler == nullptr) {
|
||||
parseString();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parseString();
|
||||
if (options->attributeExcludeHandler->shouldExclude(Slice(_b._start + lastPos, options), _nesting)) {
|
||||
if (options->attributeExcludeHandler->shouldExclude(
|
||||
Slice(_b._start + lastPos, options), _nesting)) {
|
||||
excludeAttribute = true;
|
||||
}
|
||||
}
|
||||
|
@ -498,11 +469,13 @@ void Parser::parseObject () {
|
|||
if (key.isString()) {
|
||||
ValueLength keyLength;
|
||||
char const* p = key.getString(keyLength);
|
||||
uint8_t const* translated = options->attributeTranslator->translate(p, keyLength);
|
||||
uint8_t const* translated =
|
||||
options->attributeTranslator->translate(p, keyLength);
|
||||
|
||||
if (translated != nullptr) {
|
||||
// found translation... now reset position to old key position
|
||||
// and simply overwrite the existing key with the numeric translation id
|
||||
// and simply overwrite the existing key with the numeric translation
|
||||
// id
|
||||
_b._pos = lastPos;
|
||||
_b.addUInt(Slice(translated, options).getUInt());
|
||||
}
|
||||
|
@ -581,4 +554,3 @@ void Parser::parseJson () {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,71 +39,134 @@ using namespace arangodb::velocypack;
|
|||
using VT = arangodb::velocypack::ValueType;
|
||||
|
||||
VT const Slice::TypeMap[256] = {
|
||||
/* 0x00 */ VT::None, /* 0x01 */ VT::Array, /* 0x02 */ VT::Array, /* 0x03 */ VT::Array,
|
||||
/* 0x04 */ VT::Array, /* 0x05 */ VT::Array, /* 0x06 */ VT::Array, /* 0x07 */ VT::Array,
|
||||
/* 0x08 */ VT::Array, /* 0x09 */ VT::Array, /* 0x0a */ VT::Object, /* 0x0b */ VT::Object,
|
||||
/* 0x0c */ VT::Object, /* 0x0d */ VT::Object, /* 0x0e */ VT::Object, /* 0x0f */ VT::Object,
|
||||
/* 0x10 */ VT::Object, /* 0x11 */ VT::Object, /* 0x12 */ VT::Object, /* 0x13 */ VT::Array,
|
||||
/* 0x14 */ VT::Object, /* 0x15 */ VT::None, /* 0x16 */ VT::None, /* 0x17 */ VT::None,
|
||||
/* 0x18 */ VT::Null, /* 0x19 */ VT::Bool, /* 0x1a */ VT::Bool, /* 0x1b */ VT::Double,
|
||||
/* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External, /* 0x1e */ VT::MinKey, /* 0x1f */ VT::MaxKey,
|
||||
/* 0x20 */ VT::Int, /* 0x21 */ VT::Int, /* 0x22 */ VT::Int, /* 0x23 */ VT::Int,
|
||||
/* 0x24 */ VT::Int, /* 0x25 */ VT::Int, /* 0x26 */ VT::Int, /* 0x27 */ VT::Int,
|
||||
/* 0x28 */ VT::UInt, /* 0x29 */ VT::UInt, /* 0x2a */ VT::UInt, /* 0x2b */ VT::UInt,
|
||||
/* 0x2c */ VT::UInt, /* 0x2d */ VT::UInt, /* 0x2e */ VT::UInt, /* 0x2f */ VT::UInt,
|
||||
/* 0x30 */ VT::SmallInt, /* 0x31 */ VT::SmallInt, /* 0x32 */ VT::SmallInt, /* 0x33 */ VT::SmallInt,
|
||||
/* 0x34 */ VT::SmallInt, /* 0x35 */ VT::SmallInt, /* 0x36 */ VT::SmallInt, /* 0x37 */ VT::SmallInt,
|
||||
/* 0x38 */ VT::SmallInt, /* 0x39 */ VT::SmallInt, /* 0x3a */ VT::SmallInt, /* 0x3b */ VT::SmallInt,
|
||||
/* 0x3c */ VT::SmallInt, /* 0x3d */ VT::SmallInt, /* 0x3e */ VT::SmallInt, /* 0x3f */ VT::SmallInt,
|
||||
/* 0x40 */ VT::String, /* 0x41 */ VT::String, /* 0x42 */ VT::String, /* 0x43 */ VT::String,
|
||||
/* 0x44 */ VT::String, /* 0x45 */ VT::String, /* 0x46 */ VT::String, /* 0x47 */ VT::String,
|
||||
/* 0x48 */ VT::String, /* 0x49 */ VT::String, /* 0x4a */ VT::String, /* 0x4b */ VT::String,
|
||||
/* 0x4c */ VT::String, /* 0x4d */ VT::String, /* 0x4e */ VT::String, /* 0x4f */ VT::String,
|
||||
/* 0x50 */ VT::String, /* 0x51 */ VT::String, /* 0x52 */ VT::String, /* 0x53 */ VT::String,
|
||||
/* 0x54 */ VT::String, /* 0x55 */ VT::String, /* 0x56 */ VT::String, /* 0x57 */ VT::String,
|
||||
/* 0x58 */ VT::String, /* 0x59 */ VT::String, /* 0x5a */ VT::String, /* 0x5b */ VT::String,
|
||||
/* 0x5c */ VT::String, /* 0x5d */ VT::String, /* 0x5e */ VT::String, /* 0x5f */ VT::String,
|
||||
/* 0x60 */ VT::String, /* 0x61 */ VT::String, /* 0x62 */ VT::String, /* 0x63 */ VT::String,
|
||||
/* 0x64 */ VT::String, /* 0x65 */ VT::String, /* 0x66 */ VT::String, /* 0x67 */ VT::String,
|
||||
/* 0x68 */ VT::String, /* 0x69 */ VT::String, /* 0x6a */ VT::String, /* 0x6b */ VT::String,
|
||||
/* 0x6c */ VT::String, /* 0x6d */ VT::String, /* 0x6e */ VT::String, /* 0x6f */ VT::String,
|
||||
/* 0x70 */ VT::String, /* 0x71 */ VT::String, /* 0x72 */ VT::String, /* 0x73 */ VT::String,
|
||||
/* 0x74 */ VT::String, /* 0x75 */ VT::String, /* 0x76 */ VT::String, /* 0x77 */ VT::String,
|
||||
/* 0x78 */ VT::String, /* 0x79 */ VT::String, /* 0x7a */ VT::String, /* 0x7b */ VT::String,
|
||||
/* 0x7c */ VT::String, /* 0x7d */ VT::String, /* 0x7e */ VT::String, /* 0x7f */ VT::String,
|
||||
/* 0x80 */ VT::String, /* 0x81 */ VT::String, /* 0x82 */ VT::String, /* 0x83 */ VT::String,
|
||||
/* 0x84 */ VT::String, /* 0x85 */ VT::String, /* 0x86 */ VT::String, /* 0x87 */ VT::String,
|
||||
/* 0x88 */ VT::String, /* 0x89 */ VT::String, /* 0x8a */ VT::String, /* 0x8b */ VT::String,
|
||||
/* 0x8c */ VT::String, /* 0x8d */ VT::String, /* 0x8e */ VT::String, /* 0x8f */ VT::String,
|
||||
/* 0x90 */ VT::String, /* 0x91 */ VT::String, /* 0x92 */ VT::String, /* 0x93 */ VT::String,
|
||||
/* 0x94 */ VT::String, /* 0x95 */ VT::String, /* 0x96 */ VT::String, /* 0x97 */ VT::String,
|
||||
/* 0x98 */ VT::String, /* 0x99 */ VT::String, /* 0x9a */ VT::String, /* 0x9b */ VT::String,
|
||||
/* 0x9c */ VT::String, /* 0x9d */ VT::String, /* 0x9e */ VT::String, /* 0x9f */ VT::String,
|
||||
/* 0xa0 */ VT::String, /* 0xa1 */ VT::String, /* 0xa2 */ VT::String, /* 0xa3 */ VT::String,
|
||||
/* 0xa4 */ VT::String, /* 0xa5 */ VT::String, /* 0xa6 */ VT::String, /* 0xa7 */ VT::String,
|
||||
/* 0xa8 */ VT::String, /* 0xa9 */ VT::String, /* 0xaa */ VT::String, /* 0xab */ VT::String,
|
||||
/* 0xac */ VT::String, /* 0xad */ VT::String, /* 0xae */ VT::String, /* 0xaf */ VT::String,
|
||||
/* 0xb0 */ VT::String, /* 0xb1 */ VT::String, /* 0xb2 */ VT::String, /* 0xb3 */ VT::String,
|
||||
/* 0xb4 */ VT::String, /* 0xb5 */ VT::String, /* 0xb6 */ VT::String, /* 0xb7 */ VT::String,
|
||||
/* 0xb8 */ VT::String, /* 0xb9 */ VT::String, /* 0xba */ VT::String, /* 0xbb */ VT::String,
|
||||
/* 0xbc */ VT::String, /* 0xbd */ VT::String, /* 0xbe */ VT::String, /* 0xbf */ VT::String,
|
||||
/* 0xc0 */ VT::Binary, /* 0xc1 */ VT::Binary, /* 0xc2 */ VT::Binary, /* 0xc3 */ VT::Binary,
|
||||
/* 0xc4 */ VT::Binary, /* 0xc5 */ VT::Binary, /* 0xc6 */ VT::Binary, /* 0xc7 */ VT::Binary,
|
||||
/* 0xc8 */ VT::BCD, /* 0xc9 */ VT::BCD, /* 0xca */ VT::BCD, /* 0xcb */ VT::BCD,
|
||||
/* 0xcc */ VT::BCD, /* 0xcd */ VT::BCD, /* 0xce */ VT::BCD, /* 0xcf */ VT::BCD,
|
||||
/* 0xd0 */ VT::BCD, /* 0xd1 */ VT::BCD, /* 0xd2 */ VT::BCD, /* 0xd3 */ VT::BCD,
|
||||
/* 0xd4 */ VT::BCD, /* 0xd5 */ VT::BCD, /* 0xd6 */ VT::BCD, /* 0xd7 */ VT::BCD,
|
||||
/* 0xd8 */ VT::None, /* 0xd9 */ VT::None, /* 0xda */ VT::None, /* 0xdb */ VT::None,
|
||||
/* 0xdc */ VT::None, /* 0xdd */ VT::None, /* 0xde */ VT::None, /* 0xdf */ VT::None,
|
||||
/* 0xe0 */ VT::None, /* 0xe1 */ VT::None, /* 0xe2 */ VT::None, /* 0xe3 */ VT::None,
|
||||
/* 0xe4 */ VT::None, /* 0xe5 */ VT::None, /* 0xe6 */ VT::None, /* 0xe7 */ VT::None,
|
||||
/* 0xe8 */ VT::None, /* 0xe9 */ VT::None, /* 0xea */ VT::None, /* 0xeb */ VT::None,
|
||||
/* 0xec */ VT::None, /* 0xed */ VT::None, /* 0xee */ VT::None, /* 0xef */ VT::None,
|
||||
/* 0xf0 */ VT::Custom, /* 0xf1 */ VT::Custom, /* 0xf2 */ VT::Custom, /* 0xf3 */ VT::Custom,
|
||||
/* 0xf4 */ VT::Custom, /* 0xf5 */ VT::Custom, /* 0xf6 */ VT::Custom, /* 0xf7 */ VT::Custom,
|
||||
/* 0xf8 */ VT::Custom, /* 0xf9 */ VT::Custom, /* 0xfa */ VT::Custom, /* 0xfb */ VT::Custom,
|
||||
/* 0xfc */ VT::Custom, /* 0xfd */ VT::Custom, /* 0xfe */ VT::Custom, /* 0xff */ VT::Custom
|
||||
};
|
||||
/* 0x00 */ VT::None, /* 0x01 */ VT::Array,
|
||||
/* 0x02 */ VT::Array, /* 0x03 */ VT::Array,
|
||||
/* 0x04 */ VT::Array, /* 0x05 */ VT::Array,
|
||||
/* 0x06 */ VT::Array, /* 0x07 */ VT::Array,
|
||||
/* 0x08 */ VT::Array, /* 0x09 */ VT::Array,
|
||||
/* 0x0a */ VT::Object, /* 0x0b */ VT::Object,
|
||||
/* 0x0c */ VT::Object, /* 0x0d */ VT::Object,
|
||||
/* 0x0e */ VT::Object, /* 0x0f */ VT::Object,
|
||||
/* 0x10 */ VT::Object, /* 0x11 */ VT::Object,
|
||||
/* 0x12 */ VT::Object, /* 0x13 */ VT::Array,
|
||||
/* 0x14 */ VT::Object, /* 0x15 */ VT::None,
|
||||
/* 0x16 */ VT::None, /* 0x17 */ VT::None,
|
||||
/* 0x18 */ VT::Null, /* 0x19 */ VT::Bool,
|
||||
/* 0x1a */ VT::Bool, /* 0x1b */ VT::Double,
|
||||
/* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External,
|
||||
/* 0x1e */ VT::MinKey, /* 0x1f */ VT::MaxKey,
|
||||
/* 0x20 */ VT::Int, /* 0x21 */ VT::Int,
|
||||
/* 0x22 */ VT::Int, /* 0x23 */ VT::Int,
|
||||
/* 0x24 */ VT::Int, /* 0x25 */ VT::Int,
|
||||
/* 0x26 */ VT::Int, /* 0x27 */ VT::Int,
|
||||
/* 0x28 */ VT::UInt, /* 0x29 */ VT::UInt,
|
||||
/* 0x2a */ VT::UInt, /* 0x2b */ VT::UInt,
|
||||
/* 0x2c */ VT::UInt, /* 0x2d */ VT::UInt,
|
||||
/* 0x2e */ VT::UInt, /* 0x2f */ VT::UInt,
|
||||
/* 0x30 */ VT::SmallInt, /* 0x31 */ VT::SmallInt,
|
||||
/* 0x32 */ VT::SmallInt, /* 0x33 */ VT::SmallInt,
|
||||
/* 0x34 */ VT::SmallInt, /* 0x35 */ VT::SmallInt,
|
||||
/* 0x36 */ VT::SmallInt, /* 0x37 */ VT::SmallInt,
|
||||
/* 0x38 */ VT::SmallInt, /* 0x39 */ VT::SmallInt,
|
||||
/* 0x3a */ VT::SmallInt, /* 0x3b */ VT::SmallInt,
|
||||
/* 0x3c */ VT::SmallInt, /* 0x3d */ VT::SmallInt,
|
||||
/* 0x3e */ VT::SmallInt, /* 0x3f */ VT::SmallInt,
|
||||
/* 0x40 */ VT::String, /* 0x41 */ VT::String,
|
||||
/* 0x42 */ VT::String, /* 0x43 */ VT::String,
|
||||
/* 0x44 */ VT::String, /* 0x45 */ VT::String,
|
||||
/* 0x46 */ VT::String, /* 0x47 */ VT::String,
|
||||
/* 0x48 */ VT::String, /* 0x49 */ VT::String,
|
||||
/* 0x4a */ VT::String, /* 0x4b */ VT::String,
|
||||
/* 0x4c */ VT::String, /* 0x4d */ VT::String,
|
||||
/* 0x4e */ VT::String, /* 0x4f */ VT::String,
|
||||
/* 0x50 */ VT::String, /* 0x51 */ VT::String,
|
||||
/* 0x52 */ VT::String, /* 0x53 */ VT::String,
|
||||
/* 0x54 */ VT::String, /* 0x55 */ VT::String,
|
||||
/* 0x56 */ VT::String, /* 0x57 */ VT::String,
|
||||
/* 0x58 */ VT::String, /* 0x59 */ VT::String,
|
||||
/* 0x5a */ VT::String, /* 0x5b */ VT::String,
|
||||
/* 0x5c */ VT::String, /* 0x5d */ VT::String,
|
||||
/* 0x5e */ VT::String, /* 0x5f */ VT::String,
|
||||
/* 0x60 */ VT::String, /* 0x61 */ VT::String,
|
||||
/* 0x62 */ VT::String, /* 0x63 */ VT::String,
|
||||
/* 0x64 */ VT::String, /* 0x65 */ VT::String,
|
||||
/* 0x66 */ VT::String, /* 0x67 */ VT::String,
|
||||
/* 0x68 */ VT::String, /* 0x69 */ VT::String,
|
||||
/* 0x6a */ VT::String, /* 0x6b */ VT::String,
|
||||
/* 0x6c */ VT::String, /* 0x6d */ VT::String,
|
||||
/* 0x6e */ VT::String, /* 0x6f */ VT::String,
|
||||
/* 0x70 */ VT::String, /* 0x71 */ VT::String,
|
||||
/* 0x72 */ VT::String, /* 0x73 */ VT::String,
|
||||
/* 0x74 */ VT::String, /* 0x75 */ VT::String,
|
||||
/* 0x76 */ VT::String, /* 0x77 */ VT::String,
|
||||
/* 0x78 */ VT::String, /* 0x79 */ VT::String,
|
||||
/* 0x7a */ VT::String, /* 0x7b */ VT::String,
|
||||
/* 0x7c */ VT::String, /* 0x7d */ VT::String,
|
||||
/* 0x7e */ VT::String, /* 0x7f */ VT::String,
|
||||
/* 0x80 */ VT::String, /* 0x81 */ VT::String,
|
||||
/* 0x82 */ VT::String, /* 0x83 */ VT::String,
|
||||
/* 0x84 */ VT::String, /* 0x85 */ VT::String,
|
||||
/* 0x86 */ VT::String, /* 0x87 */ VT::String,
|
||||
/* 0x88 */ VT::String, /* 0x89 */ VT::String,
|
||||
/* 0x8a */ VT::String, /* 0x8b */ VT::String,
|
||||
/* 0x8c */ VT::String, /* 0x8d */ VT::String,
|
||||
/* 0x8e */ VT::String, /* 0x8f */ VT::String,
|
||||
/* 0x90 */ VT::String, /* 0x91 */ VT::String,
|
||||
/* 0x92 */ VT::String, /* 0x93 */ VT::String,
|
||||
/* 0x94 */ VT::String, /* 0x95 */ VT::String,
|
||||
/* 0x96 */ VT::String, /* 0x97 */ VT::String,
|
||||
/* 0x98 */ VT::String, /* 0x99 */ VT::String,
|
||||
/* 0x9a */ VT::String, /* 0x9b */ VT::String,
|
||||
/* 0x9c */ VT::String, /* 0x9d */ VT::String,
|
||||
/* 0x9e */ VT::String, /* 0x9f */ VT::String,
|
||||
/* 0xa0 */ VT::String, /* 0xa1 */ VT::String,
|
||||
/* 0xa2 */ VT::String, /* 0xa3 */ VT::String,
|
||||
/* 0xa4 */ VT::String, /* 0xa5 */ VT::String,
|
||||
/* 0xa6 */ VT::String, /* 0xa7 */ VT::String,
|
||||
/* 0xa8 */ VT::String, /* 0xa9 */ VT::String,
|
||||
/* 0xaa */ VT::String, /* 0xab */ VT::String,
|
||||
/* 0xac */ VT::String, /* 0xad */ VT::String,
|
||||
/* 0xae */ VT::String, /* 0xaf */ VT::String,
|
||||
/* 0xb0 */ VT::String, /* 0xb1 */ VT::String,
|
||||
/* 0xb2 */ VT::String, /* 0xb3 */ VT::String,
|
||||
/* 0xb4 */ VT::String, /* 0xb5 */ VT::String,
|
||||
/* 0xb6 */ VT::String, /* 0xb7 */ VT::String,
|
||||
/* 0xb8 */ VT::String, /* 0xb9 */ VT::String,
|
||||
/* 0xba */ VT::String, /* 0xbb */ VT::String,
|
||||
/* 0xbc */ VT::String, /* 0xbd */ VT::String,
|
||||
/* 0xbe */ VT::String, /* 0xbf */ VT::String,
|
||||
/* 0xc0 */ VT::Binary, /* 0xc1 */ VT::Binary,
|
||||
/* 0xc2 */ VT::Binary, /* 0xc3 */ VT::Binary,
|
||||
/* 0xc4 */ VT::Binary, /* 0xc5 */ VT::Binary,
|
||||
/* 0xc6 */ VT::Binary, /* 0xc7 */ VT::Binary,
|
||||
/* 0xc8 */ VT::BCD, /* 0xc9 */ VT::BCD,
|
||||
/* 0xca */ VT::BCD, /* 0xcb */ VT::BCD,
|
||||
/* 0xcc */ VT::BCD, /* 0xcd */ VT::BCD,
|
||||
/* 0xce */ VT::BCD, /* 0xcf */ VT::BCD,
|
||||
/* 0xd0 */ VT::BCD, /* 0xd1 */ VT::BCD,
|
||||
/* 0xd2 */ VT::BCD, /* 0xd3 */ VT::BCD,
|
||||
/* 0xd4 */ VT::BCD, /* 0xd5 */ VT::BCD,
|
||||
/* 0xd6 */ VT::BCD, /* 0xd7 */ VT::BCD,
|
||||
/* 0xd8 */ VT::None, /* 0xd9 */ VT::None,
|
||||
/* 0xda */ VT::None, /* 0xdb */ VT::None,
|
||||
/* 0xdc */ VT::None, /* 0xdd */ VT::None,
|
||||
/* 0xde */ VT::None, /* 0xdf */ VT::None,
|
||||
/* 0xe0 */ VT::None, /* 0xe1 */ VT::None,
|
||||
/* 0xe2 */ VT::None, /* 0xe3 */ VT::None,
|
||||
/* 0xe4 */ VT::None, /* 0xe5 */ VT::None,
|
||||
/* 0xe6 */ VT::None, /* 0xe7 */ VT::None,
|
||||
/* 0xe8 */ VT::None, /* 0xe9 */ VT::None,
|
||||
/* 0xea */ VT::None, /* 0xeb */ VT::None,
|
||||
/* 0xec */ VT::None, /* 0xed */ VT::None,
|
||||
/* 0xee */ VT::None, /* 0xef */ VT::None,
|
||||
/* 0xf0 */ VT::Custom, /* 0xf1 */ VT::Custom,
|
||||
/* 0xf2 */ VT::Custom, /* 0xf3 */ VT::Custom,
|
||||
/* 0xf4 */ VT::Custom, /* 0xf5 */ VT::Custom,
|
||||
/* 0xf6 */ VT::Custom, /* 0xf7 */ VT::Custom,
|
||||
/* 0xf8 */ VT::Custom, /* 0xf9 */ VT::Custom,
|
||||
/* 0xfa */ VT::Custom, /* 0xfb */ VT::Custom,
|
||||
/* 0xfc */ VT::Custom, /* 0xfd */ VT::Custom,
|
||||
/* 0xfe */ VT::Custom, /* 0xff */ VT::Custom};
|
||||
|
||||
unsigned int const Slice::WidthMap[32] = {
|
||||
0, // 0x00, None
|
||||
|
@ -125,8 +188,7 @@ unsigned int const Slice::WidthMap[32] = {
|
|||
2, // 0x10, object with unsorted index table
|
||||
4, // 0x11, object with unsorted index table
|
||||
8, // 0x12, object with unsorted index table
|
||||
0
|
||||
};
|
||||
0};
|
||||
|
||||
unsigned int const Slice::FirstSubMap[32] = {
|
||||
0, // 0x00, None
|
||||
|
@ -148,8 +210,7 @@ unsigned int const Slice::FirstSubMap[32] = {
|
|||
5, // 0x10, object with unsorted index table
|
||||
8, // 0x11, object with unsorted index table
|
||||
8, // 0x12, object with unsorted index table
|
||||
0
|
||||
};
|
||||
0};
|
||||
|
||||
// translates an integer key into a string
|
||||
Slice Slice::translate() const {
|
||||
|
@ -182,9 +243,7 @@ std::string Slice::toString () const {
|
|||
return std::move(buffer);
|
||||
}
|
||||
|
||||
std::string Slice::hexType () const {
|
||||
return std::move(HexDump::toHex(head()));
|
||||
}
|
||||
std::string Slice::hexType() const { return std::move(HexDump::toHex(head())); }
|
||||
|
||||
// look for the specified attribute inside an Object
|
||||
// returns a Slice(ValueType::None) if not found
|
||||
|
@ -210,15 +269,9 @@ Slice Slice::get (std::string const& attribute) const {
|
|||
|
||||
// read number of items
|
||||
ValueLength n;
|
||||
if (h <= 0x05) { // No offset table or length, need to compute:
|
||||
dataOffset = findDataOffset(h);
|
||||
Slice first(_start + dataOffset, options);
|
||||
n = (end - dataOffset) / first.byteSize();
|
||||
}
|
||||
else if (offsetSize < 8) {
|
||||
if (offsetSize < 8) {
|
||||
n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize);
|
||||
}
|
||||
|
||||
|
@ -234,14 +287,12 @@ Slice Slice::get (std::string const& attribute) const {
|
|||
if (!key.isEqualString(attribute)) {
|
||||
return Slice();
|
||||
}
|
||||
}
|
||||
else if (key.isInteger()) {
|
||||
} else if (key.isInteger()) {
|
||||
// translate key
|
||||
if (!key.translate().isEqualString(attribute)) {
|
||||
return Slice();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// invalid key
|
||||
return Slice();
|
||||
}
|
||||
|
@ -249,8 +300,8 @@ Slice Slice::get (std::string const& attribute) const {
|
|||
return Slice(key.start() + key.byteSize(), options);
|
||||
}
|
||||
|
||||
ValueLength const ieBase = end - n * offsetSize
|
||||
- (offsetSize == 8 ? offsetSize : 0);
|
||||
ValueLength const ieBase =
|
||||
end - n * offsetSize - (offsetSize == 8 ? offsetSize : 0);
|
||||
|
||||
// only use binary search for attributes if we have at least this many entries
|
||||
// otherwise we'll always use the linear search
|
||||
|
@ -273,8 +324,7 @@ int64_t Slice::getInt () const {
|
|||
uint64_t v = readInteger<uint64_t>(_start + 1, h - 0x1f);
|
||||
if (h == 0x27) {
|
||||
return toInt64(v);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int64_t vv = static_cast<int64_t>(v);
|
||||
int64_t shift = 1LL << ((h - 0x1f) * 8 - 1);
|
||||
return vv < shift ? vv : vv - (shift << 1);
|
||||
|
@ -342,10 +392,10 @@ int64_t Slice::getSmallInt () const {
|
|||
return static_cast<int64_t>(h - 0x3a) - 6;
|
||||
}
|
||||
|
||||
if ((h >= 0x20 && h <= 0x27) ||
|
||||
(h >= 0x28 && h <= 0x2f)) {
|
||||
if ((h >= 0x20 && h <= 0x27) || (h >= 0x28 && h <= 0x2f)) {
|
||||
// Int and UInt
|
||||
// we'll leave it to the compiler to detect the two ranges above are adjacent
|
||||
// we'll leave it to the compiler to detect the two ranges above are
|
||||
// adjacent
|
||||
return getInt();
|
||||
}
|
||||
|
||||
|
@ -356,7 +406,8 @@ int Slice::compareString (std::string const& attribute) const {
|
|||
ValueLength keyLength;
|
||||
char const* k = getString(keyLength);
|
||||
size_t const attributeLength = attribute.size();
|
||||
size_t const compareLength = (std::min)(static_cast<size_t>(keyLength), attributeLength);
|
||||
size_t const compareLength =
|
||||
(std::min)(static_cast<size_t>(keyLength), attributeLength);
|
||||
int res = memcmp(k, attribute.c_str(), compareLength);
|
||||
|
||||
if (res == 0) {
|
||||
|
@ -384,8 +435,7 @@ Slice Slice::getFromCompactObject (std::string const& attribute) const {
|
|||
if (key.isEqualString(attribute)) {
|
||||
return Slice(key.start() + key.byteSize(), options);
|
||||
}
|
||||
}
|
||||
else if (key.isInteger()) {
|
||||
} else if (key.isInteger()) {
|
||||
if (key.translate().isEqualString(attribute)) {
|
||||
return Slice(key.start() + key.byteSize(), options);
|
||||
}
|
||||
|
@ -422,11 +472,9 @@ ValueLength Slice::getNthOffset (ValueLength index) const {
|
|||
if (h <= 0x05) { // No offset table or length, need to compute:
|
||||
Slice first(_start + dataOffset, options);
|
||||
n = (end - dataOffset) / first.byteSize();
|
||||
}
|
||||
else if (offsetSize < 8) {
|
||||
} else if (offsetSize < 8) {
|
||||
n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize);
|
||||
}
|
||||
|
||||
|
@ -447,8 +495,8 @@ ValueLength Slice::getNthOffset (ValueLength index) const {
|
|||
return dataOffset + index * firstItem.byteSize();
|
||||
}
|
||||
|
||||
ValueLength const ieBase = end - n * offsetSize + index * offsetSize
|
||||
- (offsetSize == 8 ? 8 : 0);
|
||||
ValueLength const ieBase =
|
||||
end - n * offsetSize + index * offsetSize - (offsetSize == 8 ? 8 : 0);
|
||||
return readInteger<ValueLength>(_start + ieBase, offsetSize);
|
||||
}
|
||||
|
||||
|
@ -521,25 +569,23 @@ ValueLength Slice::getNthOffsetFromCompact (ValueLength index) const {
|
|||
|
||||
// perform a linear search for the specified attribute inside an Object
|
||||
Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||
ValueLength ieBase,
|
||||
ValueLength offsetSize,
|
||||
ValueLength ieBase, ValueLength offsetSize,
|
||||
ValueLength n) const {
|
||||
for (ValueLength index = 0; index < n; ++index) {
|
||||
ValueLength offset = ieBase + index * offsetSize;
|
||||
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize), options);
|
||||
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize),
|
||||
options);
|
||||
|
||||
if (key.isString()) {
|
||||
if (!key.isEqualString(attribute)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (key.isInteger()) {
|
||||
} else if (key.isInteger()) {
|
||||
// translate key
|
||||
if (!key.translate().isEqualString(attribute)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// invalid key type
|
||||
return Slice();
|
||||
}
|
||||
|
@ -554,8 +600,7 @@ Slice Slice::searchObjectKeyLinear (std::string const& attribute,
|
|||
|
||||
// perform a binary search for the specified attribute inside an Object
|
||||
Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
||||
ValueLength ieBase,
|
||||
ValueLength offsetSize,
|
||||
ValueLength ieBase, ValueLength offsetSize,
|
||||
ValueLength n) const {
|
||||
VELOCYPACK_ASSERT(n > 0);
|
||||
|
||||
|
@ -567,17 +612,16 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
|
|||
ValueLength index = l + ((r - l) / 2);
|
||||
|
||||
ValueLength offset = ieBase + index * offsetSize;
|
||||
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize), options);
|
||||
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize),
|
||||
options);
|
||||
|
||||
int res;
|
||||
if (key.isString()) {
|
||||
res = key.compareString(attribute);
|
||||
}
|
||||
else if (key.isInteger()) {
|
||||
} else if (key.isInteger()) {
|
||||
// translate key
|
||||
res = key.translate().compareString(attribute);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// invalid key
|
||||
return Slice();
|
||||
}
|
||||
|
@ -592,8 +636,7 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
|
|||
return Slice();
|
||||
}
|
||||
r = index - 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
l = index + 1;
|
||||
}
|
||||
if (r < l) {
|
||||
|
@ -603,7 +646,8 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
|
|||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, Slice const* slice) {
|
||||
stream << "[Slice " << valueTypeName(slice->type()) << " (" << slice->hexType() << "), byteSize: " << slice->byteSize() << "]";
|
||||
stream << "[Slice " << valueTypeName(slice->type()) << " ("
|
||||
<< slice->hexType() << "), byteSize: " << slice->byteSize() << "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
@ -611,5 +655,6 @@ std::ostream& operator<< (std::ostream& stream, Slice const& slice) {
|
|||
return operator<<(stream, &slice);
|
||||
}
|
||||
|
||||
static_assert(sizeof(arangodb::velocypack::Slice) == sizeof(void*) + sizeof(void*),
|
||||
static_assert(sizeof(arangodb::velocypack::Slice) ==
|
||||
sizeof(void*) + sizeof(void*),
|
||||
"Slice has an unexpected size");
|
||||
|
|
|
@ -32,23 +32,40 @@ using namespace arangodb::velocypack;
|
|||
|
||||
char const* arangodb::velocypack::valueTypeName(ValueType type) {
|
||||
switch (type) {
|
||||
case ValueType::None: return "none";
|
||||
case ValueType::Null: return "null";
|
||||
case ValueType::Bool: return "bool";
|
||||
case ValueType::Array: return "array";
|
||||
case ValueType::Object: return "object";
|
||||
case ValueType::Double: return "double";
|
||||
case ValueType::UTCDate: return "utc-date";
|
||||
case ValueType::External: return "external";
|
||||
case ValueType::MinKey: return "min-key";
|
||||
case ValueType::MaxKey: return "max-key";
|
||||
case ValueType::Int: return "int";
|
||||
case ValueType::UInt: return "uint";
|
||||
case ValueType::SmallInt: return "smallint";
|
||||
case ValueType::String: return "string";
|
||||
case ValueType::Binary: return "binary";
|
||||
case ValueType::BCD: return "bcd";
|
||||
case ValueType::Custom: return "custom";
|
||||
case ValueType::None:
|
||||
return "none";
|
||||
case ValueType::Null:
|
||||
return "null";
|
||||
case ValueType::Bool:
|
||||
return "bool";
|
||||
case ValueType::Array:
|
||||
return "array";
|
||||
case ValueType::Object:
|
||||
return "object";
|
||||
case ValueType::Double:
|
||||
return "double";
|
||||
case ValueType::UTCDate:
|
||||
return "utc-date";
|
||||
case ValueType::External:
|
||||
return "external";
|
||||
case ValueType::MinKey:
|
||||
return "min-key";
|
||||
case ValueType::MaxKey:
|
||||
return "max-key";
|
||||
case ValueType::Int:
|
||||
return "int";
|
||||
case ValueType::UInt:
|
||||
return "uint";
|
||||
case ValueType::SmallInt:
|
||||
return "smallint";
|
||||
case ValueType::String:
|
||||
return "string";
|
||||
case ValueType::Binary:
|
||||
return "binary";
|
||||
case ValueType::BCD:
|
||||
return "bcd";
|
||||
case ValueType::Custom:
|
||||
return "custom";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
|
|
|
@ -55,4 +55,3 @@ int Version::compare (Version const& other) const {
|
|||
int Version::compare(Version const& lhs, Version const& rhs) {
|
||||
return lhs.compare(rhs);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,19 +53,18 @@ static bool HasSSE42 () {
|
|||
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
|
||||
if ((ecx & 0x100000) != 0) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t JSONStringCopySSE42 (uint8_t* dst, uint8_t const* src, size_t limit) {
|
||||
alignas(16) static char const ranges[17]
|
||||
= "\x20\x21\x23\x5b\x5d\xff ";
|
||||
static size_t JSONStringCopySSE42(uint8_t* dst, uint8_t const* src,
|
||||
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;
|
||||
|
@ -74,8 +73,7 @@ static size_t JSONStringCopySSE42 (uint8_t* dst, uint8_t const* src, size_t limi
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
|
||||
x = _mm_cmpistri(r, /* 6, */ s, /* 16, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (x < 16) {
|
||||
memcpy(dst, src, x);
|
||||
dst += x;
|
||||
|
@ -95,8 +93,7 @@ static size_t JSONStringCopySSE42 (uint8_t* dst, uint8_t const* src, size_t limi
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
|
||||
x = _mm_cmpistri(r, /* 6, */ s, /* limit, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (x > static_cast<int>(limit)) {
|
||||
x = static_cast<int>(limit);
|
||||
}
|
||||
|
@ -110,18 +107,16 @@ static size_t JSONStringCopySSE42 (uint8_t* dst, uint8_t const* src, size_t limi
|
|||
static size_t DoInitCopy(uint8_t* dst, uint8_t const* src, size_t limit) {
|
||||
if (HasSSE42()) {
|
||||
JSONStringCopy = JSONStringCopySSE42;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
JSONStringCopy = JSONStringCopyC;
|
||||
}
|
||||
return (*JSONStringCopy)(dst, src, limit);
|
||||
}
|
||||
|
||||
static size_t JSONStringCopyCheckUtf8SSE42 (uint8_t* dst,
|
||||
uint8_t const* src,
|
||||
static size_t JSONStringCopyCheckUtf8SSE42(uint8_t* dst, uint8_t const* src,
|
||||
size_t limit) {
|
||||
alignas(16) static unsigned char const ranges[17]
|
||||
= "\x20\x21\x23\x5b\x5d\x7f ";
|
||||
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;
|
||||
|
@ -130,8 +125,7 @@ static size_t JSONStringCopyCheckUtf8SSE42 (uint8_t* dst,
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
|
||||
x = _mm_cmpistri(r, /* 8, */ s, /* 16, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (x < 16) {
|
||||
memcpy(dst, src, x);
|
||||
dst += x;
|
||||
|
@ -151,8 +145,7 @@ static size_t JSONStringCopyCheckUtf8SSE42 (uint8_t* dst,
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
|
||||
x = _mm_cmpistri(r, /* 8, */ s, /* limit, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (x > static_cast<int>(limit)) {
|
||||
x = static_cast<int>(limit);
|
||||
}
|
||||
|
@ -167,8 +160,7 @@ static size_t DoInitCopyCheckUtf8 (uint8_t* dst, uint8_t const* src,
|
|||
size_t limit) {
|
||||
if (HasSSE42()) {
|
||||
JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8SSE42;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8C;
|
||||
}
|
||||
return (*JSONStringCopyCheckUtf8)(dst, src, limit);
|
||||
|
@ -183,8 +175,7 @@ static size_t JSONSkipWhiteSpaceSSE42 (uint8_t const* ptr, size_t limit) {
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(ptr));
|
||||
x = _mm_cmpistri(w, /* 4, */ s, /* 16, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (x < 16) {
|
||||
ptr += x;
|
||||
count += x;
|
||||
|
@ -200,8 +191,7 @@ static size_t JSONSkipWhiteSpaceSSE42 (uint8_t const* ptr, size_t limit) {
|
|||
__m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(ptr));
|
||||
x = _mm_cmpistri(w, /* 4, */ s, /* limit, */
|
||||
_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY |
|
||||
_SIDD_NEGATIVE_POLARITY |
|
||||
_SIDD_LEAST_SIGNIFICANT);
|
||||
_SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
|
||||
if (static_cast<size_t>(x) > limit) {
|
||||
x = static_cast<int>(limit);
|
||||
}
|
||||
|
@ -213,8 +203,7 @@ static size_t JSONSkipWhiteSpaceSSE42 (uint8_t const* ptr, size_t limit) {
|
|||
static size_t DoInitSkip(uint8_t const* ptr, size_t limit) {
|
||||
if (HasSSE42()) {
|
||||
JSONSkipWhiteSpace = JSONSkipWhiteSpaceSSE42;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
JSONSkipWhiteSpace = JSONSkipWhiteSpaceC;
|
||||
}
|
||||
return (*JSONSkipWhiteSpace)(ptr, limit);
|
||||
|
@ -240,19 +229,18 @@ static size_t DoInitSkip (uint8_t const* ptr, 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 (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*,
|
||||
size_t) = DoInitCopyCheckUtf8;
|
||||
size_t (*JSONSkipWhiteSpace)(uint8_t const*, size_t) = DoInitSkip;
|
||||
|
||||
#if defined(COMPILE_VELOCYPACK_ASM_UNITTESTS)
|
||||
|
||||
int testPositions[] = { 0, 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,
|
||||
-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 };
|
||||
int testPositions[] = {
|
||||
0, 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,
|
||||
-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;
|
||||
|
@ -272,8 +260,7 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
size_t pos;
|
||||
if (off >= 0) {
|
||||
pos = off;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pos = size - static_cast<size_t>(-off);
|
||||
}
|
||||
if (pos >= size) {
|
||||
|
@ -281,11 +268,12 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
}
|
||||
|
||||
// Test a quote character:
|
||||
merk = src[pos]; src[pos] = '"';
|
||||
merk = src[pos];
|
||||
src[pos] = '"';
|
||||
copied = JSONStringCopy(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -293,8 +281,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
src[pos] = '\\';
|
||||
copied = JSONStringCopy(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -302,8 +290,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
src[pos] = 1;
|
||||
copied = JSONStringCopy(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -311,8 +299,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
src[pos] = 31;
|
||||
copied = JSONStringCopy(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
}
|
||||
|
@ -322,8 +310,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
|
|||
}
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
std::chrono::duration<double> totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
std::cout << "Tests took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -340,15 +328,14 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
src += salign;
|
||||
for (int dalign = 0; dalign < 16; dalign++) {
|
||||
dst += dalign;
|
||||
for (int i = 0;
|
||||
i < static_cast<int>(sizeof(testPositions) / sizeof(int)); i++) {
|
||||
for (int i = 0; i < static_cast<int>(sizeof(testPositions) / sizeof(int));
|
||||
i++) {
|
||||
uint8_t merk;
|
||||
int off = testPositions[i];
|
||||
size_t pos;
|
||||
if (off >= 0) {
|
||||
pos = off;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pos = size - static_cast<size_t>(-off);
|
||||
}
|
||||
if (pos >= size) {
|
||||
|
@ -356,11 +343,12 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
}
|
||||
|
||||
// Test a quote character:
|
||||
merk = src[pos]; src[pos] = '"';
|
||||
merk = src[pos];
|
||||
src[pos] = '"';
|
||||
copied = JSONStringCopyCheckUtf8(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -368,8 +356,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
src[pos] = '\\';
|
||||
copied = JSONStringCopyCheckUtf8(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -377,8 +365,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
src[pos] = 1;
|
||||
copied = JSONStringCopyCheckUtf8(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -386,8 +374,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
src[pos] = 31;
|
||||
copied = JSONStringCopyCheckUtf8(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
|
||||
|
@ -395,8 +383,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
src[pos] = 0x80;
|
||||
copied = JSONStringCopyCheckUtf8(dst, src, size);
|
||||
if (copied != pos || memcmp(dst, src, copied) != 0) {
|
||||
std::cout << "Error: " << salign << " " << dalign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << dalign << " " << i << " "
|
||||
<< pos << " " << copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
}
|
||||
|
@ -406,8 +394,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
|
|||
}
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
std::chrono::duration<double> totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
std::cout << "Tests took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -422,15 +410,14 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
|
|||
|
||||
for (int salign = 0; salign < 16; salign++) {
|
||||
src += salign;
|
||||
for (int i = 0;
|
||||
i < static_cast<int>(sizeof(testPositions) / sizeof(int)); i++) {
|
||||
for (int i = 0; i < static_cast<int>(sizeof(testPositions) / sizeof(int));
|
||||
i++) {
|
||||
uint8_t merk;
|
||||
int off = testPositions[i];
|
||||
size_t pos;
|
||||
if (off >= 0) {
|
||||
pos = off;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pos = size - static_cast<size_t>(-off);
|
||||
}
|
||||
if (pos >= size) {
|
||||
|
@ -438,11 +425,12 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
|
|||
}
|
||||
|
||||
// Test a non-whitespace character:
|
||||
merk = src[pos]; src[pos] = 'x';
|
||||
merk = src[pos];
|
||||
src[pos] = 'x';
|
||||
copied = JSONSkipWhiteSpace(src, size);
|
||||
if (copied != pos) {
|
||||
std::cout << "Error: " << salign << " "
|
||||
<< i << " " << pos << " " << copied << std::endl;
|
||||
std::cout << "Error: " << salign << " " << i << " " << pos << " "
|
||||
<< copied << std::endl;
|
||||
}
|
||||
src[pos] = merk;
|
||||
}
|
||||
|
@ -450,13 +438,14 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
|
|||
}
|
||||
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now-start);
|
||||
std::chrono::duration<double> totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
std::cout << "Whitespace tests took altogether " << totalTime.count()
|
||||
<< " seconds." << std::endl;
|
||||
}
|
||||
|
||||
void RaceStringCopy (uint8_t* dst, uint8_t* src, size_t size, int repeat, int&akku) {
|
||||
void RaceStringCopy(uint8_t* dst, uint8_t* src, size_t size, int repeat,
|
||||
int& akku) {
|
||||
size_t copied;
|
||||
|
||||
std::cout << "\nNow racing for the repeated full string, "
|
||||
|
@ -471,8 +460,8 @@ void RaceStringCopy (uint8_t* dst, uint8_t* src, size_t size, int repeat, int&ak
|
|||
auto now = std::chrono::high_resolution_clock::now();
|
||||
src[size] = 'a' + (size % 26);
|
||||
|
||||
auto totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
auto totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -480,8 +469,7 @@ void RaceStringCopy (uint8_t* dst, uint8_t* src, size_t size, int repeat, int&ak
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes copied per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
|
||||
std::cout << "\nNow racing for the repeated full string, "
|
||||
<< "now unaligned target...\n" << std::endl;
|
||||
|
@ -495,8 +483,8 @@ void RaceStringCopy (uint8_t* dst, uint8_t* src, size_t size, int repeat, int&ak
|
|||
now = std::chrono::high_resolution_clock::now();
|
||||
dst--;
|
||||
|
||||
totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -504,12 +492,11 @@ void RaceStringCopy (uint8_t* dst, uint8_t* src, size_t size, int repeat, int&ak
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes copied per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
}
|
||||
|
||||
void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
||||
size_t size, int repeat, int& akku) {
|
||||
void RaceStringCopyCheckUtf8(uint8_t* dst, uint8_t* src, size_t size,
|
||||
int repeat, int& akku) {
|
||||
size_t copied;
|
||||
|
||||
std::cout << "\nNow racing for the repeated (check UTF8) full string, "
|
||||
|
@ -524,8 +511,8 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
auto now = std::chrono::high_resolution_clock::now();
|
||||
src[size] = 'a' + (size % 26);
|
||||
|
||||
auto totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
auto totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -533,10 +520,11 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes copied per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
|
||||
std::cout << "\nNow racing for the repeated full string, now unaligned target...\n" << std::endl;
|
||||
std::cout
|
||||
<< "\nNow racing for the repeated full string, now unaligned target...\n"
|
||||
<< std::endl;
|
||||
|
||||
dst++;
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
|
@ -547,8 +535,8 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
now = std::chrono::high_resolution_clock::now();
|
||||
dst--;
|
||||
|
||||
totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -556,8 +544,7 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes copied per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
|
||||
std::cout << "\nNow comparing with strcpy...\n" << std::endl;
|
||||
|
||||
|
@ -565,12 +552,11 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
for (int j = 0; j < repeat; j++) {
|
||||
// strcpy((char*) dst, (char*) src);
|
||||
memcpy((char*)dst, (char*)src, size);
|
||||
|
||||
}
|
||||
now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -578,8 +564,7 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes copied per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
}
|
||||
|
||||
void RaceSkipWhiteSpace(uint8_t* src, size_t size, int repeat, int& akku) {
|
||||
|
@ -596,8 +581,8 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
|
|||
}
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now-start);
|
||||
auto totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -605,8 +590,7 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes skipped per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
|
||||
std::cout << "\nNow comparing with strlen...\n" << std::endl;
|
||||
|
||||
|
@ -619,8 +603,8 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
|
|||
}
|
||||
now = std::chrono::high_resolution_clock::now();
|
||||
|
||||
totalTime
|
||||
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
totalTime =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
|
||||
|
||||
std::cout << "Race took altogether " << totalTime.count() << " seconds."
|
||||
<< std::endl;
|
||||
|
@ -628,13 +612,13 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
|
|||
<< " on average is: " << totalTime.count() / repeat << "."
|
||||
<< std::endl;
|
||||
std::cout << "Bytes scanned per second: "
|
||||
<< (double) size * (double) repeat / totalTime.count()
|
||||
<< std::endl;
|
||||
<< (double)size * (double)repeat / totalTime.count() << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 4) {
|
||||
std::cout << "Usage: " << argv[0] << " SIZE REPEAT CORRECTNESS" << std::endl;
|
||||
std::cout << "Usage: " << argv[0] << " SIZE REPEAT CORRECTNESS"
|
||||
<< std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,7 @@ static inline size_t JSONStringCopyInline (uint8_t* dst, uint8_t const* src,
|
|||
// Report the number of bytes copied. May copy less bytes, for example
|
||||
// for alignment reasons.
|
||||
size_t count = limit;
|
||||
while (count > 0 &&
|
||||
*src >= 32 &&
|
||||
*src != '\\' &&
|
||||
*src != '"') {
|
||||
while (count > 0 && *src >= 32 && *src != '\\' && *src != '"') {
|
||||
*dst++ = *src++;
|
||||
count--;
|
||||
}
|
||||
|
@ -61,10 +58,7 @@ static inline size_t JSONStringCopyCheckUtf8Inline (uint8_t* dst,
|
|||
// Report the number of bytes copied. May copy less bytes, for example
|
||||
// for alignment reasons.
|
||||
size_t count = limit;
|
||||
while (count > 0 &&
|
||||
*src >= 32 &&
|
||||
*src != '\\' &&
|
||||
*src != '"' &&
|
||||
while (count > 0 && *src >= 32 && *src != '\\' && *src != '"' &&
|
||||
*src < 0x80) {
|
||||
*dst++ = *src++;
|
||||
count--;
|
||||
|
@ -72,8 +66,7 @@ static inline size_t JSONStringCopyCheckUtf8Inline (uint8_t* dst,
|
|||
return limit - count;
|
||||
}
|
||||
|
||||
size_t JSONStringCopyCheckUtf8C (uint8_t* dst, uint8_t const* src,
|
||||
size_t limit);
|
||||
size_t JSONStringCopyCheckUtf8C(uint8_t* dst, uint8_t const* src, size_t limit);
|
||||
extern size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t);
|
||||
|
||||
// White space skipping:
|
||||
|
@ -84,10 +77,7 @@ static inline size_t JSONSkipWhiteSpaceInline (uint8_t const* ptr,
|
|||
// Advance ptr and return the number of skipped bytes.
|
||||
size_t count = limit;
|
||||
while (count > 0 &&
|
||||
(*ptr == ' ' ||
|
||||
*ptr == '\t' ||
|
||||
*ptr == '\n' ||
|
||||
*ptr == '\r')) {
|
||||
(*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')) {
|
||||
ptr++;
|
||||
count--;
|
||||
}
|
||||
|
|
|
@ -39,8 +39,7 @@ namespace arangodb {
|
|||
return h;
|
||||
}
|
||||
|
||||
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
|
||||
{
|
||||
uint64_t fasthash64(const void *buf, size_t len, uint64_t seed) {
|
||||
const uint64_t m = 0x880355f21e6d1965ULL;
|
||||
const uint64_t *pos = (const uint64_t *)buf;
|
||||
const uint64_t *end = pos + (len / 8);
|
||||
|
@ -58,13 +57,20 @@ namespace arangodb {
|
|||
v = 0;
|
||||
|
||||
switch (len & 7) {
|
||||
case 7: v ^= (uint64_t)pos2[6] << 48;
|
||||
case 6: v ^= (uint64_t)pos2[5] << 40;
|
||||
case 5: v ^= (uint64_t)pos2[4] << 32;
|
||||
case 4: v ^= (uint64_t)pos2[3] << 24;
|
||||
case 3: v ^= (uint64_t)pos2[2] << 16;
|
||||
case 2: v ^= (uint64_t)pos2[1] << 8;
|
||||
case 1: v ^= (uint64_t)pos2[0];
|
||||
case 7:
|
||||
v ^= (uint64_t)pos2[6] << 48;
|
||||
case 6:
|
||||
v ^= (uint64_t)pos2[5] << 40;
|
||||
case 5:
|
||||
v ^= (uint64_t)pos2[4] << 32;
|
||||
case 4:
|
||||
v ^= (uint64_t)pos2[3] << 24;
|
||||
case 3:
|
||||
v ^= (uint64_t)pos2[2] << 16;
|
||||
case 2:
|
||||
v ^= (uint64_t)pos2[1] << 8;
|
||||
case 1:
|
||||
v ^= (uint64_t)pos2[0];
|
||||
h ^= mix(v);
|
||||
h *= m;
|
||||
}
|
||||
|
@ -74,4 +80,3 @@ namespace arangodb {
|
|||
|
||||
} // namespace arangodb::velocypack
|
||||
} // namespace arangodb
|
||||
|
||||
|
|
|
@ -52,11 +52,9 @@ static uint64_t tens[] = {
|
|||
10000000000U, 1000000000U, 100000000U,
|
||||
10000000U, 1000000U, 100000U,
|
||||
10000U, 1000U, 100U,
|
||||
10U, 1U
|
||||
};
|
||||
10U, 1U};
|
||||
|
||||
static inline uint64_t get_dbits(double d)
|
||||
{
|
||||
static inline uint64_t get_dbits(double d) {
|
||||
union {
|
||||
double dbl;
|
||||
uint64_t i;
|
||||
|
@ -65,8 +63,7 @@ static inline uint64_t get_dbits(double d)
|
|||
return dbl_bits.i;
|
||||
}
|
||||
|
||||
static Fp build_fp(double d)
|
||||
{
|
||||
static Fp build_fp(double d) {
|
||||
uint64_t bits = get_dbits(d);
|
||||
|
||||
Fp fp;
|
||||
|
@ -84,8 +81,7 @@ static Fp build_fp(double d)
|
|||
return fp;
|
||||
}
|
||||
|
||||
static void normalize(Fp* fp)
|
||||
{
|
||||
static void normalize(Fp* fp) {
|
||||
while ((fp->frac & hiddenbit) == 0) {
|
||||
fp->frac <<= 1;
|
||||
fp->exp--;
|
||||
|
@ -96,8 +92,7 @@ static void normalize(Fp* fp)
|
|||
fp->exp -= shift;
|
||||
}
|
||||
|
||||
static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
|
||||
{
|
||||
static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper) {
|
||||
upper->frac = (fp->frac << 1) + 1;
|
||||
upper->exp = fp->exp - 1;
|
||||
|
||||
|
@ -111,19 +106,16 @@ static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
|
|||
upper->frac <<= u_shift;
|
||||
upper->exp = upper->exp - u_shift;
|
||||
|
||||
|
||||
int l_shift = fp->frac == hiddenbit ? 2 : 1;
|
||||
|
||||
lower->frac = (fp->frac << l_shift) - 1;
|
||||
lower->exp = fp->exp - l_shift;
|
||||
|
||||
|
||||
lower->frac <<= lower->exp - upper->exp;
|
||||
lower->exp = upper->exp;
|
||||
}
|
||||
|
||||
static Fp multiply(Fp* a, Fp* b)
|
||||
{
|
||||
static Fp multiply(Fp* a, Fp* b) {
|
||||
const uint64_t lomask = 0x00000000FFFFFFFF;
|
||||
|
||||
uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
|
||||
|
@ -135,26 +127,22 @@ static Fp multiply(Fp* a, Fp* b)
|
|||
/* round up */
|
||||
tmp += 1U << 31;
|
||||
|
||||
Fp fp = {
|
||||
ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
|
||||
a->exp + b->exp + 64
|
||||
};
|
||||
Fp fp = {ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
|
||||
a->exp + b->exp + 64};
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
|
||||
{
|
||||
static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem,
|
||||
uint64_t kappa, uint64_t frac) {
|
||||
while (rem < frac && delta - rem >= kappa &&
|
||||
(rem + kappa < frac || frac - rem > rem + kappa - frac)) {
|
||||
|
||||
digits[ndigits - 1]--;
|
||||
rem += kappa;
|
||||
}
|
||||
}
|
||||
|
||||
static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
|
||||
{
|
||||
static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K) {
|
||||
uint64_t wfrac = upper->frac - fp->frac;
|
||||
uint64_t delta = upper->frac - lower->frac;
|
||||
|
||||
|
@ -169,7 +157,6 @@ static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
|
|||
uint64_t* divp;
|
||||
/* 1000000000 */
|
||||
for (divp = tens + 10; kappa > 0; divp++) {
|
||||
|
||||
uint64_t div = *divp;
|
||||
unsigned digit = static_cast<unsigned>(part1 / div);
|
||||
|
||||
|
@ -214,8 +201,7 @@ static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
|
|||
}
|
||||
}
|
||||
|
||||
static int grisu2(double d, char* digits, int* K)
|
||||
{
|
||||
static int grisu2(double d, char* digits, int* K) {
|
||||
Fp w = build_fp(d);
|
||||
|
||||
Fp lower, upper;
|
||||
|
@ -238,8 +224,7 @@ static int grisu2(double d, char* digits, int* K)
|
|||
return generate_digits(&w, &upper, &lower, digits, K);
|
||||
}
|
||||
|
||||
static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
|
||||
{
|
||||
static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg) {
|
||||
int exp = absv(K + ndigits - 1);
|
||||
|
||||
/* write plain integer */
|
||||
|
@ -311,8 +296,7 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int filter_special(double fp, char* dest)
|
||||
{
|
||||
static int filter_special(double fp, char* dest) {
|
||||
if (fp == 0.0) {
|
||||
dest[0] = '0';
|
||||
return 1;
|
||||
|
@ -327,17 +311,20 @@ static int filter_special(double fp, char* dest)
|
|||
}
|
||||
|
||||
if (bits & fracmask) {
|
||||
dest[0] = 'N'; dest[1] = 'a'; dest[2] = 'N';
|
||||
dest[0] = 'N';
|
||||
dest[1] = 'a';
|
||||
dest[2] = 'N';
|
||||
|
||||
} else {
|
||||
dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
|
||||
dest[0] = 'i';
|
||||
dest[1] = 'n';
|
||||
dest[2] = 'f';
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int arangodb::velocypack::fpconv_dtoa (double d, char dest[24])
|
||||
{
|
||||
int arangodb::velocypack::fpconv_dtoa(double d, char dest[24]) {
|
||||
char digits[18];
|
||||
|
||||
int str_len = 0;
|
||||
|
|
|
@ -12,61 +12,100 @@
|
|||
#define expmax -32
|
||||
#define expmin -60
|
||||
|
||||
|
||||
typedef struct Fp {
|
||||
uint64_t frac;
|
||||
int exp;
|
||||
} Fp;
|
||||
|
||||
static Fp powers_ten[] = {
|
||||
{ 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
|
||||
{ 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
|
||||
{ 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
|
||||
{ 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
|
||||
{ 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
|
||||
{ 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
|
||||
{ 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
|
||||
{ 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
|
||||
{ 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
|
||||
{ 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
|
||||
{ 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
|
||||
{ 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
|
||||
{ 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
|
||||
{ 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
|
||||
{ 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
|
||||
{ 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
|
||||
{ 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
|
||||
{ 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
|
||||
{ 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
|
||||
{ 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
|
||||
{ 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
|
||||
{ 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
|
||||
{ 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
|
||||
{ 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
|
||||
{ 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
|
||||
{ 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
|
||||
{ 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
|
||||
{ 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
|
||||
{ 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
|
||||
{ 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
|
||||
{ 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
|
||||
{ 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
|
||||
{ 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
|
||||
{ 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
|
||||
{ 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
|
||||
{ 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
|
||||
{ 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
|
||||
{ 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
|
||||
{ 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
|
||||
{ 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
|
||||
{ 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
|
||||
{ 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
|
||||
{ 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
|
||||
{ 12648080533535911531U, 1066 }
|
||||
};
|
||||
static Fp powers_ten[] = {{18054884314459144840U, -1220},
|
||||
{13451937075301367670U, -1193},
|
||||
{10022474136428063862U, -1166},
|
||||
{14934650266808366570U, -1140},
|
||||
{11127181549972568877U, -1113},
|
||||
{16580792590934885855U, -1087},
|
||||
{12353653155963782858U, -1060},
|
||||
{18408377700990114895U, -1034},
|
||||
{13715310171984221708U, -1007},
|
||||
{10218702384817765436U, -980},
|
||||
{15227053142812498563U, -954},
|
||||
{11345038669416679861U, -927},
|
||||
{16905424996341287883U, -901},
|
||||
{12595523146049147757U, -874},
|
||||
{9384396036005875287U, -847},
|
||||
{13983839803942852151U, -821},
|
||||
{10418772551374772303U, -794},
|
||||
{15525180923007089351U, -768},
|
||||
{11567161174868858868U, -741},
|
||||
{17236413322193710309U, -715},
|
||||
{12842128665889583758U, -688},
|
||||
{9568131466127621947U, -661},
|
||||
{14257626930069360058U, -635},
|
||||
{10622759856335341974U, -608},
|
||||
{15829145694278690180U, -582},
|
||||
{11793632577567316726U, -555},
|
||||
{17573882009934360870U, -529},
|
||||
{13093562431584567480U, -502},
|
||||
{9755464219737475723U, -475},
|
||||
{14536774485912137811U, -449},
|
||||
{10830740992659433045U, -422},
|
||||
{16139061738043178685U, -396},
|
||||
{12024538023802026127U, -369},
|
||||
{17917957937422433684U, -343},
|
||||
{13349918974505688015U, -316},
|
||||
{9946464728195732843U, -289},
|
||||
{14821387422376473014U, -263},
|
||||
{11042794154864902060U, -236},
|
||||
{16455045573212060422U, -210},
|
||||
{12259964326927110867U, -183},
|
||||
{18268770466636286478U, -157},
|
||||
{13611294676837538539U, -130},
|
||||
{10141204801825835212U, -103},
|
||||
{15111572745182864684U, -77},
|
||||
{11258999068426240000U, -50},
|
||||
{16777216000000000000U, -24},
|
||||
{12500000000000000000U, 3},
|
||||
{9313225746154785156U, 30},
|
||||
{13877787807814456755U, 56},
|
||||
{10339757656912845936U, 83},
|
||||
{15407439555097886824U, 109},
|
||||
{11479437019748901445U, 136},
|
||||
{17105694144590052135U, 162},
|
||||
{12744735289059618216U, 189},
|
||||
{9495567745759798747U, 216},
|
||||
{14149498560666738074U, 242},
|
||||
{10542197943230523224U, 269},
|
||||
{15709099088952724970U, 295},
|
||||
{11704190886730495818U, 322},
|
||||
{17440603504673385349U, 348},
|
||||
{12994262207056124023U, 375},
|
||||
{9681479787123295682U, 402},
|
||||
{14426529090290212157U, 428},
|
||||
{10748601772107342003U, 455},
|
||||
{16016664761464807395U, 481},
|
||||
{11933345169920330789U, 508},
|
||||
{17782069995880619868U, 534},
|
||||
{13248674568444952270U, 561},
|
||||
{9871031767461413346U, 588},
|
||||
{14708983551653345445U, 614},
|
||||
{10959046745042015199U, 641},
|
||||
{16330252207878254650U, 667},
|
||||
{12166986024289022870U, 694},
|
||||
{18130221999122236476U, 720},
|
||||
{13508068024458167312U, 747},
|
||||
{10064294952495520794U, 774},
|
||||
{14996968138956309548U, 800},
|
||||
{11173611982879273257U, 827},
|
||||
{16649979327439178909U, 853},
|
||||
{12405201291620119593U, 880},
|
||||
{9242595204427927429U, 907},
|
||||
{13772540099066387757U, 933},
|
||||
{10261342003245940623U, 960},
|
||||
{15290591125556738113U, 986},
|
||||
{11392378155556871081U, 1013},
|
||||
{16975966327722178521U, 1039},
|
||||
{12648080533535911531U, 1066}};
|
||||
|
||||
static Fp find_cachedpow10(int exp, int* k)
|
||||
{
|
||||
static Fp find_cachedpow10(int exp, int* k) {
|
||||
const double one_log_ten = 0.30102999566398114;
|
||||
|
||||
int approx = static_cast<int>(-(exp + npowers) * one_log_ten);
|
||||
|
|
|
@ -41,9 +41,10 @@ void checkValueLength (ValueLength length) {
|
|||
#endif
|
||||
|
||||
int64_t arangodb::velocypack::currentUTCDateValue() {
|
||||
return static_cast<int64_t>(std::chrono::system_clock::now().time_since_epoch().count() / std::chrono::milliseconds(1).count());
|
||||
return static_cast<int64_t>(
|
||||
std::chrono::system_clock::now().time_since_epoch().count() /
|
||||
std::chrono::milliseconds(1).count());
|
||||
}
|
||||
|
||||
static_assert(sizeof(arangodb::velocypack::ValueLength) >= sizeof(SIZE_MAX),
|
||||
"invalid value for SIZE_MAX");
|
||||
|
||||
|
|
Loading…
Reference in New Issue