1
0
Fork 0

updated vpack library

This commit is contained in:
Jan Steemann 2015-11-24 10:32:58 +01:00
parent e4a3c462c7
commit d24b46bb71
35 changed files with 3807 additions and 3820 deletions

View File

@ -39,30 +39,21 @@ namespace arangodb {
class Builder; class Builder;
class AttributeTranslator { class AttributeTranslator {
public: public:
AttributeTranslator(AttributeTranslator const&) = delete; AttributeTranslator(AttributeTranslator const&) = delete;
AttributeTranslator& operator=(AttributeTranslator const&) = delete; AttributeTranslator& operator=(AttributeTranslator const&) = delete;
AttributeTranslator () AttributeTranslator() : _builder(), _count(0) {}
: _builder(), _count(0) {
}
~AttributeTranslator () { ~AttributeTranslator() {}
}
size_t count () const { size_t count() const { return _count; }
return _count;
}
void add(std::string const& key, uint64_t id); void add(std::string const& key, uint64_t id);
void seal(); void seal();
Builder* builder () { Builder* builder() { return _builder.get(); }
return _builder.get();
}
// translate from string to id // translate from string to id
uint8_t const* translate(std::string const& key) const; uint8_t const* translate(std::string const& key) const;
@ -74,7 +65,6 @@ namespace arangodb {
uint8_t const* translate(uint64_t id) const; uint8_t const* translate(uint64_t id) const;
private: private:
std::unique_ptr<Builder> _builder; std::unique_ptr<Builder> _builder;
std::unordered_map<std::string, uint8_t const*> _keyToId; std::unordered_map<std::string, uint8_t const*> _keyToId;
std::unordered_map<uint64_t, uint8_t const*> _idToKey; std::unordered_map<uint64_t, uint8_t const*> _idToKey;

View File

@ -37,27 +37,19 @@ namespace arangodb {
template <typename T> template <typename T>
class Buffer { class Buffer {
public: public:
Buffer() : _buffer(_local), _alloc(sizeof(_local)), _pos(0) {
Buffer ()
: _buffer(_local),
_alloc(sizeof(_local)),
_pos(0) {
#ifdef VELOCYPACK_DEBUG #ifdef VELOCYPACK_DEBUG
// poison memory // poison memory
memset(_buffer, 0xa5, _alloc); memset(_buffer, 0xa5, _alloc);
#endif #endif
} }
explicit Buffer (ValueLength expectedLength) explicit Buffer(ValueLength expectedLength) : Buffer() {
: Buffer() {
reserve(expectedLength); reserve(expectedLength);
} }
Buffer (Buffer const& that) Buffer(Buffer const& that) : Buffer() {
: Buffer() {
if (that._pos > 0) { if (that._pos > 0) {
if (that._pos > sizeof(_local)) { if (that._pos > sizeof(_local)) {
_buffer = new T[that._pos]; _buffer = new T[that._pos];
@ -84,15 +76,12 @@ namespace arangodb {
return *this; return *this;
} }
Buffer (Buffer&& that) Buffer(Buffer&& that) : Buffer() {
: Buffer() {
if (that._buffer == that._local) { if (that._buffer == that._local) {
memcpy(_buffer, that._buffer, that._pos); memcpy(_buffer, that._buffer, that._pos);
_pos = that._pos; _pos = that._pos;
that._pos = 0; that._pos = 0;
} } else {
else {
_buffer = that._buffer; _buffer = that._buffer;
_alloc = that._alloc; _alloc = that._alloc;
_pos = that._pos; _pos = that._pos;
@ -102,34 +91,22 @@ namespace arangodb {
} }
} }
~Buffer () { ~Buffer() { reset(); }
reset();
}
inline T* data () { inline T* data() { return _buffer; }
return _buffer;
}
inline T const* data () const { inline T const* data() const { return _buffer; }
return _buffer;
}
inline ValueLength size () const { inline ValueLength size() const { return _pos; }
return _pos;
}
inline ValueLength length () const { inline ValueLength length() const { return _pos; }
return _pos;
}
std::string toString() const { std::string toString() const {
std::string result(reinterpret_cast<char const*>(_buffer), _pos); std::string result(reinterpret_cast<char const*>(_buffer), _pos);
return std::move(result); return std::move(result);
} }
void clear () { void clear() { reset(); }
reset();
}
void reset() { void reset() {
if (_buffer != _local) { if (_buffer != _local) {
@ -199,11 +176,7 @@ namespace arangodb {
} }
private: private:
inline ValueLength capacity() const { return _alloc; }
inline ValueLength capacity () const {
return _alloc;
}
T* _buffer; T* _buffer;
ValueLength _alloc; ValueLength _alloc;
@ -211,7 +184,6 @@ namespace arangodb {
// an already initialized space for small values // an already initialized space for small values
T _local[192]; T _local[192];
}; };
typedef Buffer<char> CharBuffer; typedef Buffer<char> CharBuffer;

View File

@ -46,7 +46,6 @@ namespace arangodb {
namespace velocypack { namespace velocypack {
class Builder { class Builder {
friend class Parser; // The parser needs access to internals. friend class Parser; // The parser needs access to internals.
public: public:
@ -57,12 +56,9 @@ namespace arangodb {
uint64_t offset; uint64_t offset;
}; };
void reserve (ValueLength len) { void reserve(ValueLength len) { reserveSpace(len); }
reserveSpace(len);
}
private: private:
std::shared_ptr<Buffer<uint8_t>> _buffer; // Here we collect the result std::shared_ptr<Buffer<uint8_t>> _buffer; // Here we collect the result
uint8_t* _start; // Always points to the start of _buffer uint8_t* _start; // Always points to the start of _buffer
ValueLength _size; // Always contains the size of _buffer ValueLength _size; // Always contains the size of _buffer
@ -126,33 +122,28 @@ namespace arangodb {
std::vector<ValueLength>& offsets); std::vector<ValueLength>& offsets);
public: public:
Options const* options; Options const* options;
// Constructor and destructor: // Constructor and destructor:
explicit Builder (std::shared_ptr<Buffer<uint8_t>>& buffer, Options const* options = &Options::Defaults) explicit Builder(std::shared_ptr<Buffer<uint8_t>>& buffer,
: _buffer(buffer), Options const* options = &Options::Defaults)
_pos(0), : _buffer(buffer), _pos(0), options(options) {
options(options) { if (_buffer.get() == nullptr) {
throw Exception(Exception::InternalError, "Buffer cannot be a nullptr");
}
_start = _buffer->data(); _start = _buffer->data();
_size = _buffer->size(); _size = _buffer->size();
VELOCYPACK_ASSERT(options != nullptr);
if (options == nullptr) { if (options == nullptr) {
throw Exception(Exception::InternalError, "Options cannot be a nullptr"); throw Exception(Exception::InternalError, "Options cannot be a nullptr");
} }
} }
explicit Builder(Options const* options = &Options::Defaults) explicit Builder(Options const* options = &Options::Defaults)
: _buffer(new Buffer<uint8_t>()), : _buffer(new Buffer<uint8_t>()), _pos(0), options(options) {
_pos(0),
options(options) {
_start = _buffer->data(); _start = _buffer->data();
_size = _buffer->size(); _size = _buffer->size();
VELOCYPACK_ASSERT(options != nullptr);
if (options == nullptr) { if (options == nullptr) {
throw Exception(Exception::InternalError, "Options cannot be a nullptr"); throw Exception(Exception::InternalError, "Options cannot be a nullptr");
} }
@ -160,21 +151,26 @@ namespace arangodb {
// The rule of five: // The rule of five:
~Builder () { ~Builder() {}
}
Builder(Builder const& that) Builder(Builder const& that)
: _buffer(that._buffer), _start(_buffer->data()), _size(_buffer->size()), _pos(that._pos), : _buffer(that._buffer),
_stack(that._stack), _index(that._index), options(that.options) { _start(_buffer->data()),
VELOCYPACK_ASSERT(options != nullptr); _size(_buffer->size()),
_pos(that._pos),
_stack(that._stack),
_index(that._index),
options(that.options) {
if (that._buffer == nullptr) { 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) { Builder& operator=(Builder const& that) {
if (that._buffer == nullptr) { 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; _buffer = that._buffer;
_start = _buffer->data(); _start = _buffer->data();
@ -183,13 +179,13 @@ namespace arangodb {
_stack = that._stack; _stack = that._stack;
_index = that._index; _index = that._index;
options = that.options; options = that.options;
VELOCYPACK_ASSERT(options != nullptr);
return *this; return *this;
} }
Builder(Builder&& that) { Builder(Builder&& that) {
if (that._buffer == nullptr) { 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; _buffer = that._buffer;
that._buffer.reset(); that._buffer.reset();
@ -201,7 +197,6 @@ namespace arangodb {
_index.clear(); _index.clear();
_index.swap(that._index); _index.swap(that._index);
options = that.options; options = that.options;
VELOCYPACK_ASSERT(options != nullptr);
that._start = nullptr; that._start = nullptr;
that._size = 0; that._size = 0;
that._pos = 0; that._pos = 0;
@ -209,7 +204,8 @@ namespace arangodb {
Builder& operator=(Builder&& that) { Builder& operator=(Builder&& that) {
if (that._buffer == nullptr) { 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; _buffer = that._buffer;
that._buffer.reset(); that._buffer.reset();
@ -221,7 +217,6 @@ namespace arangodb {
_index.clear(); _index.clear();
_index.swap(that._index); _index.swap(that._index);
options = that.options; options = that.options;
VELOCYPACK_ASSERT(options != nullptr);
that._start = nullptr; that._start = nullptr;
that._size = 0; that._size = 0;
that._pos = 0; that._pos = 0;
@ -229,13 +224,12 @@ namespace arangodb {
} }
// get a const reference to the Builder's Buffer object // get a const reference to the Builder's Buffer object
std::shared_ptr<Buffer<uint8_t>> const& buffer () const { std::shared_ptr<Buffer<uint8_t>> const& buffer() const { return _buffer; }
return _buffer;
}
uint8_t const* data() const { uint8_t const* data() const {
if (_buffer == nullptr) { 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(); return _buffer.get()->data();
@ -244,12 +238,13 @@ namespace arangodb {
std::string toString() const; std::string toString() const;
// get a non-const reference to the Builder's Buffer object // get a non-const reference to the Builder's Buffer object
std::shared_ptr<Buffer<uint8_t>>& buffer () { std::shared_ptr<Buffer<uint8_t>>& buffer() { return _buffer; }
return _buffer;
}
static Builder clone (Slice const& slice, Options const* options = &Options::Defaults) { static Builder clone(Slice const& slice,
VELOCYPACK_ASSERT(options != nullptr); Options const* options = &Options::Defaults) {
if (options == nullptr) {
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
}
Builder b(options); Builder b(options);
b.add(slice); b.add(slice);
@ -271,9 +266,7 @@ namespace arangodb {
} }
// Return a Slice of the result: // Return a Slice of the result:
Slice slice () const { Slice slice() const { return Slice(start(), options); }
return Slice(start(), options);
}
// Compute the actual size here, but only when sealed // Compute the actual size here, but only when sealed
ValueLength size() const { ValueLength size() const {
@ -283,9 +276,7 @@ namespace arangodb {
return _pos; return _pos;
} }
bool isClosed () const throw() { bool isClosed() const throw() { return _stack.empty(); }
return _stack.empty();
}
// Add a subvalue into an object from a Value: // Add a subvalue into an object from a Value:
uint8_t* add(std::string const& attrName, Value const& sub); uint8_t* add(std::string const& attrName, Value const& sub);
@ -391,12 +382,10 @@ namespace arangodb {
if (v >= 0 && v <= 9) { if (v >= 0 && v <= 9) {
reserveSpace(1); reserveSpace(1);
_start[_pos++] = static_cast<uint8_t>(0x30 + v); _start[_pos++] = static_cast<uint8_t>(0x30 + v);
} } else if (v < 0 && v >= -6) {
else if (v < 0 && v >= -6) {
reserveSpace(1); reserveSpace(1);
_start[_pos++] = static_cast<uint8_t>(0x40 + v); _start[_pos++] = static_cast<uint8_t>(0x40 + v);
} } else {
else {
appendInt(v, 0x1f); appendInt(v, 0x1f);
} }
} }
@ -405,8 +394,7 @@ namespace arangodb {
if (v <= 9) { if (v <= 9) {
reserveSpace(1); reserveSpace(1);
_start[_pos++] = static_cast<uint8_t>(0x30 + v); _start[_pos++] = static_cast<uint8_t>(0x30 + v);
} } else {
else {
appendUInt(v, 0x27); appendUInt(v, 0x27);
} }
} }
@ -426,8 +414,7 @@ namespace arangodb {
_start[_pos++] = 0xbf; _start[_pos++] = 0xbf;
// write string length // write string length
appendLength(strLen, 8); appendLength(strLen, 8);
} } else {
else {
// short string // short string
_start[_pos++] = static_cast<uint8_t>(0x40 + strLen); _start[_pos++] = static_cast<uint8_t>(0x40 + strLen);
} }
@ -440,40 +427,64 @@ namespace arangodb {
addCompoundValue(unindexed ? 0x13 : 0x06); 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) { inline void addObject(bool unindexed = false) {
addCompoundValue(unindexed ? 0x14 : 0x0b); 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> template <typename T>
uint8_t* addInternal(T const& sub) { uint8_t* addInternal(T const& sub) {
bool haveReported = false;
if (!_stack.empty()) { if (!_stack.empty()) {
ValueLength& tos = _stack.back(); ValueLength& tos = _stack.back();
if (_start[tos] != 0x06 && _start[tos] != 0x13) { if (_start[tos] != 0x06 && _start[tos] != 0x13) {
throw Exception(Exception::BuilderNeedOpenArray); throw Exception(Exception::BuilderNeedOpenArray);
} }
reportAdd(tos); reportAdd(tos);
haveReported = true;
} }
try {
return set(sub); return set(sub);
} catch (...) {
// clean up in case of an exception
if (haveReported) {
cleanupAdd();
}
throw;
}
} }
template <typename T> template <typename T>
uint8_t* addInternal(std::string const& attrName, T const& sub) { uint8_t* addInternal(std::string const& attrName, T const& sub) {
bool haveReported = false;
if (!_stack.empty()) { if (!_stack.empty()) {
ValueLength& tos = _stack.back(); ValueLength& tos = _stack.back();
if (_start[tos] != 0x0b && _start[tos] != 0x14) { if (_start[tos] != 0x0b && _start[tos] != 0x14) {
throw Exception(Exception::BuilderNeedOpenObject); throw Exception(Exception::BuilderNeedOpenObject);
} }
reportAdd(tos); reportAdd(tos);
haveReported = true;
} }
try {
if (options->attributeTranslator != nullptr) { if (options->attributeTranslator != nullptr) {
// check if a translation for the attribute name exists // 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) { if (translated != nullptr) {
set(Slice(options->attributeTranslator->translate(attrName), options)); set(Slice(options->attributeTranslator->translate(attrName),
options));
return set(sub); return set(sub);
} }
// otherwise fall through to regular behavior // otherwise fall through to regular behavior
@ -481,6 +492,13 @@ namespace arangodb {
set(Value(attrName, ValueType::String)); set(Value(attrName, ValueType::String));
return set(sub); return set(sub);
} catch (...) {
// clean up in case of an exception
if (haveReported) {
cleanupAdd();
}
throw;
}
} }
void addCompoundValue(uint8_t type) { void addCompoundValue(uint8_t type) {
@ -502,6 +520,11 @@ namespace arangodb {
uint8_t* set(Slice const& item); uint8_t* set(Slice const& item);
void cleanupAdd() {
size_t depth = _stack.size() - 1;
_index[depth].pop_back();
}
void reportAdd(ValueLength base) { void reportAdd(ValueLength base) {
size_t depth = _stack.size() - 1; size_t depth = _stack.size() - 1;
_index[depth].push_back(_pos - base); _index[depth].push_back(_pos - base);
@ -523,8 +546,7 @@ namespace arangodb {
vSize++; vSize++;
_start[_pos++] = static_cast<uint8_t>(v & 0xff); _start[_pos++] = static_cast<uint8_t>(v & 0xff);
v >>= 8; v >>= 8;
} } while (v != 0);
while (v != 0);
_start[save] = base + vSize; _start[save] = base + vSize;
} }
@ -540,8 +562,7 @@ namespace arangodb {
do { do {
xSize++; xSize++;
x >>= 8; x >>= 8;
} } while (x >= 0x80);
while (x >= 0x80);
return xSize + 1; return xSize + 1;
} }
@ -550,8 +571,7 @@ namespace arangodb {
uint64_t x; uint64_t x;
if (vSize == 8) { if (vSize == 8) {
x = toUInt64(v); x = toUInt64(v);
} } else {
else {
int64_t shift = 1LL << (vSize * 8 - 1); // will never overflow! int64_t shift = 1LL << (vSize * 8 - 1); // will never overflow!
x = v >= 0 ? static_cast<uint64_t>(v) x = v >= 0 ? static_cast<uint64_t>(v)
: static_cast<uint64_t>(v + shift) + shift; : static_cast<uint64_t>(v + shift) + shift;

View File

@ -40,51 +40,63 @@ namespace arangodb {
namespace velocypack { namespace velocypack {
class Collection { class Collection {
public: public:
enum VisitationOrder { PreOrder = 1, PostOrder = 2 };
enum VisitationOrder {
PreOrder = 1,
PostOrder = 2
};
Collection() = delete; Collection() = delete;
Collection(Collection const&) = delete; Collection(Collection const&) = delete;
Collection& operator=(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); 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); 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); 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); 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); 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); 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) { static void keys(Slice const* slice,
std::unordered_set<std::string>& result) {
return keys(*slice, result); return keys(*slice, result);
} }
static Builder values(Slice const& slice); static Builder values(Slice const& slice);
static Builder values (Slice const* slice) { static Builder values(Slice const* slice) { return values(*slice); }
return values(*slice);
}
static Builder keep(Slice const& slice, std::vector<std::string> const& keys); 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); 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); 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); 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); 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) { static Builder merge(Slice const* left, Slice const* right,
bool mergeValues) {
return merge(*left, *right, 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); visitRecursive(*slice, order, func);
} }
}; };

View File

@ -40,9 +40,7 @@ namespace arangodb {
// Dumps VPack into a JSON output string // Dumps VPack into a JSON output string
class Dumper { class Dumper {
public: public:
Options const* options; Options const* options;
Dumper(Dumper const&) = delete; Dumper(Dumper const&) = delete;
@ -50,18 +48,17 @@ namespace arangodb {
Dumper(Sink* sink, Options const* options = &Options::Defaults) Dumper(Sink* sink, Options const* options = &Options::Defaults)
: options(options), _sink(sink), _indentation(0) { : options(options), _sink(sink), _indentation(0) {
if (sink == nullptr) {
throw Exception(Exception::InternalError, "Sink cannot be a nullptr");
}
if (options == nullptr) { if (options == nullptr) {
throw Exception(Exception::InternalError, "Options cannot be a nullptr"); throw Exception(Exception::InternalError, "Options cannot be a nullptr");
} }
} }
~Dumper () { ~Dumper() {}
}
Sink* sink () const { Sink* sink() const { return _sink; }
return _sink;
}
void dump(Slice const& slice) { void dump(Slice const& slice) {
_indentation = 0; _indentation = 0;
@ -69,37 +66,35 @@ namespace arangodb {
dumpValue(&slice); dumpValue(&slice);
} }
void dump (Slice const* slice) { void dump(Slice const* slice) { dump(*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 dumper(sink, options);
dumper.dump(slice); 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); 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; std::string buffer;
StringSink sink(&buffer); StringSink sink(&buffer);
dump(slice, &sink, options); dump(slice, &sink, options);
return std::move(buffer); 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)); return std::move(toString(*slice, options));
} }
void append (Slice const& slice) { void append(Slice const& slice) { dumpValue(&slice); }
dumpValue(&slice);
}
void append (Slice const* slice) { void append(Slice const* slice) { dumpValue(slice); }
dumpValue(slice);
}
void appendString(char const* src, ValueLength len) { void appendString(char const* src, ValueLength len) {
_sink->reserve(2 + len); _sink->reserve(2 + len);
@ -118,7 +113,6 @@ namespace arangodb {
void appendUInt(uint64_t); void appendUInt(uint64_t);
private: private:
void dumpInteger(Slice const*); void dumpInteger(Slice const*);
void dumpString(char const*, ValueLength); void dumpString(char const*, ValueLength);
@ -147,11 +141,9 @@ namespace arangodb {
} }
private: private:
Sink* _sink; Sink* _sink;
int _indentation; int _indentation;
}; };
} // namespace arangodb::velocypack } // namespace arangodb::velocypack

View File

@ -64,6 +64,7 @@ namespace arangodb {
BuilderUnexpectedType = 34, BuilderUnexpectedType = 34,
BuilderUnexpectedValue = 35, BuilderUnexpectedValue = 35,
BuilderNeedSubvalue = 36, BuilderNeedSubvalue = 36,
BuilderExternalsDisallowed = 37,
UnknownError = 999 UnknownError = 999
}; };
@ -73,23 +74,16 @@ namespace arangodb {
std::string _msg; std::string _msg;
public: 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() { ExceptionType errorCode() const throw() { return _type; }
return _msg.c_str();
}
ExceptionType errorCode () const throw() {
return _type;
}
static char const* message(ExceptionType type) throw() { static char const* message(ExceptionType type) throw() {
switch (type) { switch (type) {
@ -137,13 +131,14 @@ namespace arangodb {
return "Unexpected type"; return "Unexpected type";
case BuilderUnexpectedValue: case BuilderUnexpectedValue:
return "Unexpected value"; return "Unexpected value";
case BuilderExternalsDisallowed:
return "Externals are not allowed in this configuration";
case UnknownError: case UnknownError:
default: default:
return "Unknown error"; return "Unknown error";
} }
} }
}; };
} // namespace arangodb::velocypack } // namespace arangodb::velocypack

View File

@ -40,13 +40,13 @@ namespace arangodb {
struct HexDump { struct HexDump {
HexDump() = delete; HexDump() = delete;
HexDump (Slice const& slice, int valuesPerLine = 16, std::string const& separator = " ") HexDump(Slice const& slice, int valuesPerLine = 16,
: slice(slice), valuesPerLine(valuesPerLine), separator(separator) { std::string const& separator = " ")
} : slice(slice), valuesPerLine(valuesPerLine), separator(separator) {}
HexDump (Slice const* slice, int valuesPerLine = 16, std::string const& separator = " ") HexDump(Slice const* slice, int valuesPerLine = 16,
: HexDump(*slice, valuesPerLine, separator) { std::string const& separator = " ")
} : HexDump(*slice, valuesPerLine, separator) {}
static std::string toHex(uint8_t value); static std::string toHex(uint8_t value);

View File

@ -39,14 +39,11 @@ namespace arangodb {
namespace velocypack { namespace velocypack {
class ArrayIterator { class ArrayIterator {
public: public:
ArrayIterator() = delete; ArrayIterator() = delete;
ArrayIterator(Slice const& slice) ArrayIterator(Slice const& slice)
: _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) { : _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) {
if (slice.type() != ValueType::Array) { if (slice.type() != ValueType::Array) {
throw Exception(Exception::InvalidValueType, "Expecting Array slice"); throw Exception(Exception::InvalidValueType, "Expecting Array slice");
} }
@ -57,8 +54,10 @@ namespace arangodb {
} }
ArrayIterator(ArrayIterator const& other) 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) { ArrayIterator& operator=(ArrayIterator const& other) {
_slice = other._slice; _slice = other._slice;
@ -73,8 +72,7 @@ namespace arangodb {
++_position; ++_position;
if (_position <= _size && _current != nullptr) { if (_position <= _size && _current != nullptr) {
_current += Slice(_current, _slice.options).byteSize(); _current += Slice(_current, _slice.options).byteSize();
} } else {
else {
_current = nullptr; _current = nullptr;
} }
return *this; return *this;
@ -98,13 +96,9 @@ namespace arangodb {
return _slice.at(_position); return _slice.at(_position);
} }
ArrayIterator begin () { ArrayIterator begin() { return ArrayIterator(_slice); }
return ArrayIterator(_slice);
}
ArrayIterator begin () const { ArrayIterator begin() const { return ArrayIterator(_slice); }
return ArrayIterator(_slice);
}
ArrayIterator end() { ArrayIterator end() {
auto it = ArrayIterator(_slice); auto it = ArrayIterator(_slice);
@ -118,9 +112,7 @@ namespace arangodb {
return it; return it;
} }
inline bool valid () const throw() { inline bool valid() const throw() { return (_position < _size); }
return (_position < _size);
}
inline Slice value() const { inline Slice value() const {
if (_position >= _size) { if (_position >= _size) {
@ -134,24 +126,15 @@ namespace arangodb {
return valid(); return valid();
} }
inline ValueLength index () const throw() { inline ValueLength index() const throw() { return _position; }
return _position;
}
inline ValueLength size () const throw() { inline ValueLength size() const throw() { return _size; }
return _size;
}
inline bool isFirst () const throw() { inline bool isFirst() const throw() { return (_position == 0); }
return (_position == 0);
}
inline bool isLast () const throw() { inline bool isLast() const throw() { return (_position + 1 >= _size); }
return (_position + 1 >= _size);
}
private: private:
Slice _slice; Slice _slice;
ValueLength _size; ValueLength _size;
ValueLength _position; ValueLength _position;
@ -159,13 +142,9 @@ namespace arangodb {
}; };
class ObjectIterator { class ObjectIterator {
public: public:
struct ObjectPair { struct ObjectPair {
ObjectPair (Slice const& key, Slice const& value) ObjectPair(Slice const& key, Slice const& value) : key(key), value(value) {}
: key(key), value(value) {
}
Slice const key; Slice const key;
Slice const value; Slice const value;
}; };
@ -174,7 +153,6 @@ namespace arangodb {
ObjectIterator(Slice const& slice) ObjectIterator(Slice const& slice)
: _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) { : _slice(slice), _size(_slice.length()), _position(0), _current(nullptr) {
if (slice.type() != ValueType::Object) { if (slice.type() != ValueType::Object) {
throw Exception(Exception::InvalidValueType, "Expecting Object slice"); throw Exception(Exception::InvalidValueType, "Expecting Object slice");
} }
@ -185,8 +163,10 @@ namespace arangodb {
} }
ObjectIterator(ObjectIterator const& other) 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) { ObjectIterator& operator=(ObjectIterator const& other) {
_slice = other._slice; _slice = other._slice;
@ -204,8 +184,7 @@ namespace arangodb {
_current += Slice(_current, _slice.options).byteSize(); _current += Slice(_current, _slice.options).byteSize();
// skip over value // skip over value
_current += Slice(_current, _slice.options).byteSize(); _current += Slice(_current, _slice.options).byteSize();
} } else {
else {
_current = nullptr; _current = nullptr;
} }
return *this; return *this;
@ -230,13 +209,9 @@ namespace arangodb {
return ObjectPair(_slice.keyAt(_position), _slice.valueAt(_position)); return ObjectPair(_slice.keyAt(_position), _slice.valueAt(_position));
} }
ObjectIterator begin () { ObjectIterator begin() { return ObjectIterator(_slice); }
return ObjectIterator(_slice);
}
ObjectIterator begin () const { ObjectIterator begin() const { return ObjectIterator(_slice); }
return ObjectIterator(_slice);
}
ObjectIterator end() { ObjectIterator end() {
auto it = ObjectIterator(_slice); auto it = ObjectIterator(_slice);
@ -250,9 +225,7 @@ namespace arangodb {
return it; return it;
} }
inline bool valid () const throw() { inline bool valid() const throw() { return (_position < _size); }
return (_position < _size);
}
inline Slice key() const { inline Slice key() const {
if (_position >= _size) { if (_position >= _size) {
@ -280,24 +253,15 @@ namespace arangodb {
return valid(); return valid();
} }
inline ValueLength index () const throw() { inline ValueLength index() const throw() { return _position; }
return _position;
}
inline ValueLength size () const throw() { inline ValueLength size() const throw() { return _size; }
return _size;
}
inline bool isFirst () const throw() { inline bool isFirst() const throw() { return (_position == 0); }
return (_position == 0);
}
inline bool isLast () const throw() { inline bool isLast() const throw() { return (_position + 1 >= _size); }
return (_position + 1 >= _size);
}
private: private:
Slice _slice; Slice _slice;
ValueLength _size; ValueLength _size;
ValueLength _position; ValueLength _position;
@ -307,12 +271,16 @@ namespace arangodb {
} // namespace arangodb::velocypack } // namespace arangodb::velocypack
} // namespace arangodb } // 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 #endif

View File

@ -39,17 +39,16 @@ namespace arangodb {
class Slice; class Slice;
struct AttributeExcludeHandler { struct AttributeExcludeHandler {
virtual ~AttributeExcludeHandler () { virtual ~AttributeExcludeHandler() {}
}
virtual bool shouldExclude(Slice const& key, int nesting) = 0; virtual bool shouldExclude(Slice const& key, int nesting) = 0;
}; };
struct CustomTypeHandler { 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; virtual ValueLength byteSize(Slice const& value) = 0;
}; };
@ -59,8 +58,7 @@ namespace arangodb {
FailOnUnsupportedType FailOnUnsupportedType
}; };
Options () { Options() {}
}
// Dumper behavior when a VPack value is serialized to JSON that // Dumper behavior when a VPack value is serialized to JSON that
// has no JSON equivalent // has no JSON equivalent
@ -103,6 +101,10 @@ namespace arangodb {
// JSON with a Dumper // JSON with a Dumper
bool escapeForwardSlashes = false; 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 // default options with the above settings
static Options Defaults; static Options Defaults;
}; };

View File

@ -41,16 +41,11 @@ namespace arangodb {
namespace velocypack { namespace velocypack {
class Parser { class Parser {
// This class can parse JSON very rapidly, but only from contiguous // This class can parse JSON very rapidly, but only from contiguous
// blocks of memory. It builds the result using the Builder. // blocks of memory. It builds the result using the Builder.
struct ParsedNumber { struct ParsedNumber {
ParsedNumber () ParsedNumber() : intValue(0), doubleValue(0.0), isInteger(true) {}
: intValue(0),
doubleValue(0.0),
isInteger(true) {
}
void addDigit(int i) { void addDigit(int i) {
if (isInteger) { if (isInteger) {
@ -91,7 +86,6 @@ namespace arangodb {
int _nesting; int _nesting;
public: public:
Options const* options; Options const* options;
Parser(Parser const&) = delete; Parser(Parser const&) = delete;
@ -99,7 +93,6 @@ namespace arangodb {
Parser(Options const* options = &Options::Defaults) Parser(Options const* options = &Options::Defaults)
: _start(nullptr), _size(0), _pos(0), _nesting(0), options(options) { : _start(nullptr), _size(0), _pos(0), _nesting(0), options(options) {
VELOCYPACK_ASSERT(options != nullptr); VELOCYPACK_ASSERT(options != nullptr);
if (options == nullptr) { if (options == nullptr) {
@ -108,29 +101,30 @@ namespace arangodb {
_b.options = options; _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 parser(options);
parser.parse(json); parser.parse(json);
return parser.steal(); 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 parser(options);
parser.parse(start, size); parser.parse(start, size);
return parser.steal(); return parser.steal();
} }
ValueLength parse(std::string const& json, bool multi = false) { 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, ValueLength parse(char const* start, size_t size, bool multi = false) {
bool multi = false) {
return parse(reinterpret_cast<uint8_t const*>(start), size, multi); return parse(reinterpret_cast<uint8_t const*>(start), size, multi);
} }
ValueLength parse (uint8_t const* start, size_t size, ValueLength parse(uint8_t const* start, size_t size, bool multi = false) {
bool multi = false) {
_start = start; _start = start;
_size = size; _size = size;
_pos = 0; _pos = 0;
@ -144,29 +138,23 @@ namespace arangodb {
Builder&& steal() { Builder&& steal() {
if (_b._buffer == nullptr) { 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); return std::move(_b);
} }
// Beware, only valid as long as you do not parse more, use steal // Beware, only valid as long as you do not parse more, use steal
// to move the data out! // to move the data out!
uint8_t const* start () { uint8_t const* start() { return _b.start(); }
return _b.start();
}
// Returns the position at the time when the just reported error // Returns the position at the time when the just reported error
// occurred, only use when handling an exception. // occurred, only use when handling an exception.
size_t errorPos () const { size_t errorPos() const { return _pos > 0 ? _pos - 1 : _pos; }
return _pos > 0 ? _pos - 1 : _pos;
}
void clear () { void clear() { _b.clear(); }
_b.clear();
}
private: private:
inline int peek() const { inline int peek() const {
if (_pos >= _size) { if (_pos >= _size) {
return -1; return -1;
@ -181,13 +169,9 @@ namespace arangodb {
return static_cast<int>(_start[_pos++]); return static_cast<int>(_start[_pos++]);
} }
inline void unconsume () { inline void unconsume() { --_pos; }
--_pos;
}
inline void reset () { inline void reset() { _pos = 0; }
_pos = 0;
}
ValueLength parseInternal(bool multi); ValueLength parseInternal(bool multi);
@ -263,13 +247,9 @@ namespace arangodb {
return i; return i;
} }
inline void increaseNesting () { inline void increaseNesting() { ++_nesting; }
++_nesting;
}
inline void decreaseNesting () { inline void decreaseNesting() { --_nesting; }
--_nesting;
}
void parseNumber(); void parseNumber();
@ -280,7 +260,6 @@ namespace arangodb {
void parseObject(); void parseObject();
void parseJson(); void parseJson();
}; };
} // namespace arangodb::velocypack } // namespace arangodb::velocypack

View File

@ -38,13 +38,11 @@ namespace arangodb {
namespace velocypack { namespace velocypack {
struct Sink { struct Sink {
Sink () { Sink() {}
}
Sink(Sink const&) = delete; Sink(Sink const&) = delete;
Sink& operator=(Sink const&) = delete; Sink& operator=(Sink const&) = delete;
virtual ~Sink () { virtual ~Sink() {}
}
virtual void push_back(char c) = 0; virtual void push_back(char c) = 0;
virtual void append(std::string const& p) = 0; virtual void append(std::string const& p) = 0;
virtual void append(char const* p) = 0; virtual void append(char const* p) = 0;
@ -54,29 +52,21 @@ namespace arangodb {
template <typename T> template <typename T>
struct ByteBufferSinkImpl final : public Sink { struct ByteBufferSinkImpl final : public Sink {
explicit ByteBufferSinkImpl (Buffer<T>* buffer) explicit ByteBufferSinkImpl(Buffer<T>* buffer) : buffer(buffer) {}
: buffer(buffer) {
}
void push_back (char c) override final { void push_back(char c) override final { buffer->push_back(c); }
buffer->push_back(c);
}
void append(std::string const& p) override final { void append(std::string const& p) override final {
buffer->append(p.c_str(), p.size()); buffer->append(p.c_str(), p.size());
} }
void append (char const* p) override final { void append(char const* p) override final { buffer->append(p, strlen(p)); }
buffer->append(p, strlen(p));
}
void append(char const* p, ValueLength len) override final { void append(char const* p, ValueLength len) override final {
buffer->append(p, len); buffer->append(p, len);
} }
void reserve (ValueLength len) override final { void reserve(ValueLength len) override final { buffer->reserve(len); }
buffer->reserve(len);
}
Buffer<T>* buffer; Buffer<T>* buffer;
}; };
@ -85,29 +75,19 @@ namespace arangodb {
template <typename T> template <typename T>
struct StringSinkImpl final : public Sink { struct StringSinkImpl final : public Sink {
explicit StringSinkImpl (T* buffer) explicit StringSinkImpl(T* buffer) : buffer(buffer) {}
: buffer(buffer) {
}
void push_back (char c) override final { void push_back(char c) override final { buffer->push_back(c); }
buffer->push_back(c);
}
void append (std::string const& p) override final { void append(std::string const& p) override final { buffer->append(p); }
buffer->append(p);
}
void append (char const* p) override final { void append(char const* p) override final { buffer->append(p, strlen(p)); }
buffer->append(p, strlen(p));
}
void append(char const* p, ValueLength len) override final { void append(char const* p, ValueLength len) override final {
buffer->append(p, len); buffer->append(p, len);
} }
void reserve (ValueLength len) override final { void reserve(ValueLength len) override final { buffer->reserve(len); }
buffer->reserve(len);
}
T* buffer; T* buffer;
}; };
@ -116,17 +96,11 @@ namespace arangodb {
template <typename T> template <typename T>
struct StreamSinkImpl final : public Sink { struct StreamSinkImpl final : public Sink {
explicit StreamSinkImpl (T* stream) explicit StreamSinkImpl(T* stream) : stream(stream) {}
: stream(stream) {
}
void push_back (char c) override final { void push_back(char c) override final { *stream << c; }
*stream << c;
}
void append (std::string const& p) override final { void append(std::string const& p) override final { *stream << p; }
*stream << p;
}
void append(char const* p) override final { void append(char const* p) override final {
stream->write(p, static_cast<std::streamsize>(strlen(p))); stream->write(p, static_cast<std::streamsize>(strlen(p)));
@ -136,8 +110,7 @@ namespace arangodb {
stream->write(p, static_cast<std::streamsize>(len)); stream->write(p, static_cast<std::streamsize>(len));
} }
void reserve (ValueLength) override final { void reserve(ValueLength) override final {}
}
T* stream; T* stream;
}; };

View File

@ -48,7 +48,6 @@ namespace arangodb {
uint64_t fasthash64(void const*, size_t, uint64_t); uint64_t fasthash64(void const*, size_t, uint64_t);
class Slice { class Slice {
// This class provides read only access to a VPack value, it is // This class provides read only access to a VPack value, it is
// intentionally light-weight (only one pointer value), such that // intentionally light-weight (only one pointer value), such that
// it can easily be used to traverse larger VPack values. // it can easily be used to traverse larger VPack values.
@ -58,15 +57,13 @@ namespace arangodb {
uint8_t const* _start; uint8_t const* _start;
public: public:
Options const* options; Options const* options;
// constructor for an empty Value of type None // constructor for an empty Value of type None
Slice () Slice() : Slice("\x00", &Options::Defaults) {}
: 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) { : _start(start), options(options) {
VELOCYPACK_ASSERT(options != nullptr); VELOCYPACK_ASSERT(options != nullptr);
} }
@ -76,13 +73,11 @@ namespace arangodb {
VELOCYPACK_ASSERT(options != nullptr); VELOCYPACK_ASSERT(options != nullptr);
} }
Slice (Slice const& other) Slice(Slice const& other) : _start(other._start), options(other.options) {
: _start(other._start), options(other.options) {
VELOCYPACK_ASSERT(options != nullptr); VELOCYPACK_ASSERT(options != nullptr);
} }
Slice (Slice&& other) Slice(Slice&& other) : _start(other._start), options(other.options) {
: _start(other._start), options(other.options) {
VELOCYPACK_ASSERT(options != nullptr); VELOCYPACK_ASSERT(options != nullptr);
} }
@ -100,37 +95,23 @@ namespace arangodb {
return *this; return *this;
} }
uint8_t const* begin () { uint8_t const* begin() { return _start; }
return _start;
}
uint8_t const* begin () const { uint8_t const* begin() const { return _start; }
return _start;
}
uint8_t const* end () { uint8_t const* end() { return _start + byteSize(); }
return _start + byteSize();
}
uint8_t const* end () const { uint8_t const* end() const { return _start + byteSize(); }
return _start + byteSize();
}
// No destructor, does not take part in memory management, // No destructor, does not take part in memory management,
// get the type for the slice // get the type for the slice
inline ValueType type () const { inline ValueType type() const { return TypeMap[head()]; }
return TypeMap[head()];
}
char const* typeName () const { char const* typeName() const { return valueTypeName(type()); }
return valueTypeName(type());
}
// pointer to the head byte // pointer to the head byte
uint8_t const* start () const { uint8_t const* start() const { return _start; }
return _start;
}
// pointer to the head byte // pointer to the head byte
template <typename T> template <typename T>
@ -139,118 +120,83 @@ namespace arangodb {
} }
// value of the head byte // value of the head byte
inline uint8_t head () const { inline uint8_t head() const { return *_start; }
return *_start;
}
inline uint64_t hash() const { inline uint64_t hash() const {
return fasthash64(start(), byteSize(), 0xdeadbeef); return fasthash64(start(), byteSize(), 0xdeadbeef);
} }
// check if slice is of the specified type // check if slice is of the specified type
inline bool isType (ValueType t) const { inline bool isType(ValueType t) const { return type() == t; }
return type() == t;
}
// check if slice is a None object // check if slice is a None object
bool isNone () const { bool isNone() const { return isType(ValueType::None); }
return isType(ValueType::None);
}
// check if slice is a Null object // check if slice is a Null object
bool isNull () const { bool isNull() const { return isType(ValueType::Null); }
return isType(ValueType::Null);
}
// check if slice is a Bool object // check if slice is a Bool object
bool isBool () const { bool isBool() const { return isType(ValueType::Bool); }
return isType(ValueType::Bool);
}
// check if slice is a Bool object - this is an alias for isBool() // check if slice is a Bool object - this is an alias for isBool()
bool isBoolean () const { bool isBoolean() const { return isBool(); }
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 // check if slice is an Array object
bool isArray () const { bool isArray() const { return isType(ValueType::Array); }
return isType(ValueType::Array);
}
// check if slice is an Object object // check if slice is an Object object
bool isObject () const { bool isObject() const { return isType(ValueType::Object); }
return isType(ValueType::Object);
}
// check if slice is a Double object // check if slice is a Double object
bool isDouble () const { bool isDouble() const { return isType(ValueType::Double); }
return isType(ValueType::Double);
}
// check if slice is a UTCDate object // check if slice is a UTCDate object
bool isUTCDate () const { bool isUTCDate() const { return isType(ValueType::UTCDate); }
return isType(ValueType::UTCDate);
}
// check if slice is an External object // check if slice is an External object
bool isExternal () const { bool isExternal() const { return isType(ValueType::External); }
return isType(ValueType::External);
}
// check if slice is a MinKey object // check if slice is a MinKey object
bool isMinKey () const { bool isMinKey() const { return isType(ValueType::MinKey); }
return isType(ValueType::MinKey);
}
// check if slice is a MaxKey object // check if slice is a MaxKey object
bool isMaxKey () const { bool isMaxKey() const { return isType(ValueType::MaxKey); }
return isType(ValueType::MaxKey);
}
// check if slice is an Int object // check if slice is an Int object
bool isInt () const { bool isInt() const { return isType(ValueType::Int); }
return isType(ValueType::Int);
}
// check if slice is a UInt object // check if slice is a UInt object
bool isUInt () const { bool isUInt() const { return isType(ValueType::UInt); }
return isType(ValueType::UInt);
}
// check if slice is a SmallInt object // check if slice is a SmallInt object
bool isSmallInt () const { bool isSmallInt() const { return isType(ValueType::SmallInt); }
return isType(ValueType::SmallInt);
}
// check if slice is a String object // check if slice is a String object
bool isString () const { bool isString() const { return isType(ValueType::String); }
return isType(ValueType::String);
}
// check if slice is a Binary object // check if slice is a Binary object
bool isBinary () const { bool isBinary() const { return isType(ValueType::Binary); }
return isType(ValueType::Binary);
}
// check if slice is a BCD // check if slice is a BCD
bool isBCD () const { bool isBCD() const { return isType(ValueType::BCD); }
return isType(ValueType::BCD);
}
// check if slice is a Custom type // check if slice is a Custom type
bool isCustom () const { bool isCustom() const { return isType(ValueType::Custom); }
return isType(ValueType::Custom);
}
// check if a slice is any number type // check if a slice is any number type
bool isInteger() const { 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 // check if slice is any Number-type object
bool isNumber () const { bool isNumber() const { return isInteger() || isDouble(); }
return isInteger() || isDouble();
}
bool isSorted() const { bool isSorted() const {
auto const h = head(); auto const h = head();
@ -259,18 +205,20 @@ namespace arangodb {
// return the value for a Bool object // return the value for a Bool object
bool getBool() const { 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 (head() == 0x1a); // 0x19 == false, 0x1a == true
} }
// return the value for a Bool object - this is an alias for getBool() // return the value for a Bool object - this is an alias for getBool()
bool getBoolean () const { bool getBoolean() const { return getBool(); }
return getBool();
}
// return the value for a Double object // return the value for a Double object
double getDouble() const { double getDouble() const {
assertType(ValueType::Double); if (type() != ValueType::Double) {
throw Exception(Exception::InvalidValueType, "Expecting type Double");
}
union { union {
uint64_t dv; uint64_t dv;
double d; double d;
@ -294,20 +242,19 @@ namespace arangodb {
// - 0x09 : array with 8-byte index table entries // - 0x09 : array with 8-byte index table entries
Slice at(ValueLength index) const { Slice at(ValueLength index) const {
if (!isType(ValueType::Array)) { if (!isType(ValueType::Array)) {
throw Exception(Exception::InvalidValueType, "Expecting Array"); throw Exception(Exception::InvalidValueType, "Expecting type Array");
} }
return getNth(index); return getNth(index);
} }
Slice operator[] (ValueLength index) const { Slice operator[](ValueLength index) const { return at(index); }
return at(index);
}
// return the number of members for an Array or Object object // return the number of members for an Array or Object object
ValueLength length() const { ValueLength length() const {
if (type() != ValueType::Array && type() != ValueType::Object) { 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(); auto const h = head();
@ -330,8 +277,7 @@ namespace arangodb {
ValueLength firstSubOffset = findDataOffset(h); ValueLength firstSubOffset = findDataOffset(h);
Slice first(_start + firstSubOffset, options); Slice first(_start + firstSubOffset, options);
return (end - firstSubOffset) / first.byteSize(); return (end - firstSubOffset) / first.byteSize();
} } else if (offsetSize < 8) {
else if (offsetSize < 8) {
return readInteger<ValueLength>(_start + offsetSize + 1, offsetSize); return readInteger<ValueLength>(_start + offsetSize + 1, offsetSize);
} }
@ -340,17 +286,25 @@ namespace arangodb {
// extract a key from an Object at the specified index // extract a key from an Object at the specified index
// - 0x0a : empty object // - 0x0a : empty object
// - 0x0b : object with 1-byte index table entries, sorted by attribute name // - 0x0b : object with 1-byte index table entries, sorted by attribute
// - 0x0c : object with 2-byte index table entries, sorted by attribute name // name
// - 0x0d : object with 4-byte index table entries, sorted by attribute name // - 0x0c : object with 2-byte index table entries, sorted by attribute
// - 0x0e : object with 8-byte index table entries, sorted by attribute name // name
// - 0x0f : object with 1-byte index table entries, not sorted by attribute name // - 0x0d : object with 4-byte index table entries, sorted by attribute
// - 0x10 : object with 2-byte index table entries, not sorted by attribute name // name
// - 0x11 : object with 4-byte index table entries, not sorted by attribute name // - 0x0e : object with 8-byte index table entries, sorted by attribute
// - 0x12 : object with 8-byte index table entries, not sorted by attribute name // 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 { Slice keyAt(ValueLength index) const {
if (!isType(ValueType::Object)) { if (!isType(ValueType::Object)) {
throw Exception(Exception::InvalidValueType, "Expecting Object"); throw Exception(Exception::InvalidValueType, "Expecting type Object");
} }
return getNthKey(index, true); return getNthKey(index, true);
@ -358,7 +312,7 @@ namespace arangodb {
Slice valueAt(ValueLength index) const { Slice valueAt(ValueLength index) const {
if (!isType(ValueType::Object)) { if (!isType(ValueType::Object)) {
throw Exception(Exception::InvalidValueType, "Expecting Object"); throw Exception(Exception::InvalidValueType, "Expecting type Object");
} }
Slice key = getNthKey(index, false); Slice key = getNthKey(index, false);
@ -408,7 +362,9 @@ namespace arangodb {
// return the pointer to the data for an External object // return the pointer to the data for an External object
char const* getExternal() const { char const* getExternal() const {
assertType(ValueType::External); if (type() != ValueType::External) {
throw Exception(Exception::InvalidValueType, "Expecting type External");
}
return extractValue<char const*>(); return extractValue<char const*>();
} }
@ -444,13 +400,11 @@ namespace arangodb {
throw Exception(Exception::NumberOutOfRange); throw Exception(Exception::NumberOutOfRange);
} }
return static_cast<T>(v); return static_cast<T>(v);
} } else {
else {
// unsigned integral type // unsigned integral type
if (isDouble()) { if (isDouble()) {
auto v = getDouble(); auto v = getDouble();
if (v < 0.0 || if (v < 0.0 || v > static_cast<double>(UINT64_MAX) ||
v > static_cast<double>(UINT64_MAX) ||
v > static_cast<double>(std::numeric_limits<T>::max())) { v > static_cast<double>(std::numeric_limits<T>::max())) {
throw Exception(Exception::NumberOutOfRange); throw Exception(Exception::NumberOutOfRange);
} }
@ -488,6 +442,9 @@ namespace arangodb {
// return the value for a UTCDate object // return the value for a UTCDate object
int64_t getUTCDate() const { int64_t getUTCDate() const {
if (type() != ValueType::UTCDate) {
throw Exception(Exception::InvalidValueType, "Expecting type UTCDate");
}
assertType(ValueType::UTCDate); assertType(ValueType::UTCDate);
uint64_t v = readInteger<uint64_t>(_start + 1, sizeof(uint64_t)); uint64_t v = readInteger<uint64_t>(_start + 1, sizeof(uint64_t));
return toInt64(v); return toInt64(v);
@ -518,7 +475,8 @@ namespace arangodb {
if (h >= 0x40 && h <= 0xbe) { if (h >= 0x40 && h <= 0xbe) {
// short UTF-8 String // short UTF-8 String
ValueLength length = h - 0x40; 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) { if (h == 0xbf) {
@ -532,7 +490,9 @@ namespace arangodb {
// return the value for a Binary object // return the value for a Binary object
uint8_t const* getBinary(ValueLength& length) const { 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(); uint8_t const h = head();
if (h >= 0xc0 && h <= 0xc7) { if (h >= 0xc0 && h <= 0xc7) {
@ -546,7 +506,9 @@ namespace arangodb {
// return a copy of the value for a Binary object // return a copy of the value for a Binary object
std::vector<uint8_t> copyBinary() const { 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(); uint8_t const h = head();
if (h >= 0xc0 && h <= 0xc7) { if (h >= 0xc0 && h <= 0xc7) {
@ -554,8 +516,9 @@ namespace arangodb {
ValueLength length = readInteger<ValueLength>(_start + 1, h - 0xbf); ValueLength length = readInteger<ValueLength>(_start + 1, h - 0xbf);
checkValueLength(length); checkValueLength(length);
out.reserve(static_cast<size_t>(length)); out.reserve(static_cast<size_t>(length));
out.insert(out.end(), _start + 1 + h - 0xbf, _start + 1 + h - 0xbf + length); out.insert(out.end(), _start + 1 + h - 0xbf,
return out; _start + 1 + h - 0xbf + length);
return std::move(out);
} }
throw Exception(Exception::InvalidValueType, "Expecting type Binary"); throw Exception(Exception::InvalidValueType, "Expecting type Binary");
@ -614,7 +577,8 @@ namespace arangodb {
auto const h = head(); auto const h = head();
if (h == 0xbf) { if (h == 0xbf) {
// long UTF-8 String // 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 // short UTF-8 String
@ -623,18 +587,21 @@ namespace arangodb {
case ValueType::Binary: { case ValueType::Binary: {
auto const h = head(); 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: { case ValueType::BCD: {
auto const h = head(); auto const h = head();
if (h <= 0xcf) { if (h <= 0xcf) {
// positive BCD // 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 // 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: { case ValueType::Custom: {
@ -660,7 +627,6 @@ namespace arangodb {
std::string hexType() const; std::string hexType() const;
private: private:
Slice getFromCompactObject(std::string const& attribute) const; Slice getFromCompactObject(std::string const& attribute) const;
ValueLength findDataOffset(uint8_t head) const { ValueLength findDataOffset(uint8_t head) const {
@ -705,22 +671,17 @@ namespace arangodb {
} }
// perform a linear search for the specified attribute inside an Object // perform a linear search for the specified attribute inside an Object
Slice searchObjectKeyLinear (std::string const& attribute, Slice searchObjectKeyLinear(std::string const& attribute, ValueLength ieBase,
ValueLength ieBase, ValueLength offsetSize, ValueLength n) const;
ValueLength offsetSize,
ValueLength n) const;
// perform a binary search for the specified attribute inside an Object // perform a binary search for the specified attribute inside an Object
Slice searchObjectKeyBinary (std::string const& attribute, Slice searchObjectKeyBinary(std::string const& attribute, ValueLength ieBase,
ValueLength ieBase, ValueLength offsetSize, ValueLength n) const;
ValueLength offsetSize,
ValueLength n) const;
// assert that the slice is of a specific type // assert that the slice is of a specific type
// can be used for debugging and removed in production // can be used for debugging and removed in production
#ifdef VELOCYPACK_ASSERT #ifdef VELOCYPACK_ASSERT
inline void assertType (ValueType) const { inline void assertType(ValueType) const {}
}
#else #else
inline void assertType(ValueType type) const { inline void assertType(ValueType type) const {
VELOCYPACK_ASSERT(this->type() == type); VELOCYPACK_ASSERT(this->type() == type);
@ -729,7 +690,8 @@ namespace arangodb {
// extracts a value from the slice and converts it into a // extracts a value from the slice and converts it into a
// built-in type // built-in type
template<typename T> T extractValue () const { template <typename T>
T extractValue() const {
union { union {
T value; T value;
char binary[sizeof(T)]; char binary[sizeof(T)];
@ -739,7 +701,6 @@ namespace arangodb {
} }
private: private:
static ValueType const TypeMap[256]; static ValueType const TypeMap[256];
static unsigned int const WidthMap[32]; static unsigned int const WidthMap[32];
static unsigned int const FirstSubMap[32]; static unsigned int const FirstSubMap[32];
@ -749,13 +710,15 @@ namespace arangodb {
} // namespace arangodb } // namespace arangodb
namespace std { namespace std {
template<> struct hash<arangodb::velocypack::Slice> { template <>
struct hash<arangodb::velocypack::Slice> {
size_t operator()(arangodb::velocypack::Slice const& slice) const { size_t operator()(arangodb::velocypack::Slice const& slice) const {
return slice.hash(); return slice.hash();
} }
}; };
template<> struct equal_to<arangodb::velocypack::Slice> { template <>
struct equal_to<arangodb::velocypack::Slice> {
bool operator()(arangodb::velocypack::Slice const& a, bool operator()(arangodb::velocypack::Slice const& a,
arangodb::velocypack::Slice const& b) const { arangodb::velocypack::Slice const& b) const {
if (*a.start() != *b.start()) { if (*a.start() != *b.start()) {

View File

@ -42,7 +42,6 @@ namespace arangodb {
friend class Builder; friend class Builder;
public: public:
enum class CType { enum class CType {
None = 0, None = 0,
Bool = 1, Bool = 1,
@ -55,7 +54,6 @@ namespace arangodb {
}; };
private: private:
ValueType _valueType; ValueType _valueType;
CType _cType; // denotes variant used, 0: none CType _cType; // denotes variant used, 0: none
@ -67,17 +65,14 @@ namespace arangodb {
std::string const* s; // 5: std::string std::string const* s; // 5: std::string
char const* c; // 6: char const* char const* c; // 6: char const*
void const* e; // external void const* e; // external
} } _value;
_value;
bool _unindexed; bool _unindexed;
public: public:
#ifdef SWIG #ifdef SWIG
Value () : _valueType(ValueType::None), _cType(CType::None), Value()
_unindexed(false) { : _valueType(ValueType::None), _cType(CType::None), _unindexed(false) {}
}
#else #else
Value() = delete; Value() = delete;
#endif #endif
@ -85,7 +80,6 @@ namespace arangodb {
// creates a Value with the specified type Array or Object // creates a Value with the specified type Array or Object
explicit Value(ValueType t, bool allowUnindexed = false) explicit Value(ValueType t, bool allowUnindexed = false)
: _valueType(t), _cType(CType::None), _unindexed(allowUnindexed) { : _valueType(t), _cType(CType::None), _unindexed(allowUnindexed) {
if (allowUnindexed && if (allowUnindexed &&
(_valueType != ValueType::Array && _valueType != ValueType::Object)) { (_valueType != ValueType::Array && _valueType != ValueType::Object)) {
throw Exception(Exception::InvalidValueType, "Expecting compound type"); throw Exception(Exception::InvalidValueType, "Expecting compound type");
@ -153,17 +147,11 @@ namespace arangodb {
_value.s = &s; _value.s = &s;
} }
ValueType valueType () const { ValueType valueType() const { return _valueType; }
return _valueType;
}
CType cType () const { CType cType() const { return _cType; }
return _cType;
}
bool isString () const { bool isString() const { return _valueType == ValueType::String; }
return _valueType == ValueType::String;
}
bool getBool() const { bool getBool() const {
VELOCYPACK_ASSERT(_cType == CType::Bool); VELOCYPACK_ASSERT(_cType == CType::Bool);
@ -199,7 +187,6 @@ namespace arangodb {
VELOCYPACK_ASSERT(_cType == CType::CharPtr); VELOCYPACK_ASSERT(_cType == CType::CharPtr);
return _value.c; return _value.c;
} }
}; };
class ValuePair { class ValuePair {
@ -208,38 +195,26 @@ namespace arangodb {
ValueType _type; ValueType _type;
public: public:
ValuePair(uint8_t const* start, uint64_t size, ValuePair(uint8_t const* start, uint64_t size,
ValueType type = ValueType::Binary) ValueType type = ValueType::Binary)
: _start(start), _size(size), _type(type) { : _start(start), _size(size), _type(type) {}
}
ValuePair(char const* start, uint64_t size, ValuePair(char const* start, uint64_t size,
ValueType type = ValueType::Binary) ValueType type = ValueType::Binary)
: _start(reinterpret_cast<uint8_t const*>(start)), : _start(reinterpret_cast<uint8_t const*>(start)),
_size(size), _type(type) { _size(size),
} _type(type) {}
explicit ValuePair (uint64_t size, explicit ValuePair(uint64_t size, ValueType type = ValueType::Binary)
ValueType type = ValueType::Binary) : _start(nullptr), _size(size), _type(type) {}
: _start(nullptr), _size(size), _type(type) {
}
uint8_t const* getStart () const { uint8_t const* getStart() const { return _start; }
return _start;
}
uint64_t getSize () const { uint64_t getSize() const { return _size; }
return _size;
}
ValueType valueType () const { ValueType valueType() const { return _type; }
return _type;
}
bool isString () const { bool isString() const { return _type == ValueType::String; }
return _type == ValueType::String;
}
}; };
} // namespace arangodb::velocypack } // namespace arangodb::velocypack

View File

@ -40,8 +40,9 @@ namespace arangodb {
Version& operator=(Version const&) = delete; Version& operator=(Version const&) = delete;
Version(int majorValue, int minorValue, int patchValue) Version(int majorValue, int minorValue, int patchValue)
: majorValue(majorValue), minorValue(minorValue), patchValue(patchValue) { : majorValue(majorValue),
} minorValue(minorValue),
patchValue(patchValue) {}
std::string toString() const; std::string toString() const;

View File

@ -35,7 +35,8 @@ namespace {
using VPackValueLength = arangodb::velocypack::ValueLength; using VPackValueLength = arangodb::velocypack::ValueLength;
#endif #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 #ifdef VELOCYPACK_ITERATOR_H
#ifndef VELOCYPACK_ALIAS_ITERATOR #ifndef VELOCYPACK_ALIAS_ITERATOR
@ -108,7 +109,8 @@ namespace {
#ifndef VELOCYPACK_ALIAS_OPTIONS #ifndef VELOCYPACK_ALIAS_OPTIONS
#define VELOCYPACK_ALIAS_OPTIONS #define VELOCYPACK_ALIAS_OPTIONS
using VPackOptions = arangodb::velocypack::Options; using VPackOptions = arangodb::velocypack::Options;
using VPackAttributeExcludeHandler = arangodb::velocypack::AttributeExcludeHandler; using VPackAttributeExcludeHandler =
arangodb::velocypack::AttributeExcludeHandler;
using VPackCustomTypeHandler = arangodb::velocypack::CustomTypeHandler; using VPackCustomTypeHandler = arangodb::velocypack::CustomTypeHandler;
#endif #endif
#endif #endif
@ -149,4 +151,3 @@ namespace {
#endif #endif
#endif #endif
} }

View File

@ -104,12 +104,10 @@ namespace arangodb {
p += 7; p += 7;
if (reverse) { if (reverse) {
--source; --source;
} } else {
else {
++source; ++source;
} }
} } while (v & 0x80);
while (v & 0x80);
return len; return len;
} }
@ -124,8 +122,7 @@ namespace arangodb {
value >>= 7; value >>= 7;
} }
*dst-- = static_cast<uint8_t>(value & 0x7f); *dst-- = static_cast<uint8_t>(value & 0x7f);
} } else {
else {
while (value >= 0x80) { while (value >= 0x80) {
*dst++ = static_cast<uint8_t>(value | 0x80); *dst++ = static_cast<uint8_t>(value | 0x80);
value >>= 7; value >>= 7;
@ -166,8 +163,7 @@ namespace arangodb {
do { do {
value += static_cast<T>(*start++) << x; value += static_cast<T>(*start++) << x;
x += 8; x += 8;
} } while (start < end);
while (start < end);
return value; return value;
} }
@ -180,8 +176,7 @@ namespace arangodb {
do { do {
*start++ = static_cast<uint8_t>(value & 0xff); *start++ = static_cast<uint8_t>(value & 0xff);
value >>= 8; value >>= 8;
} } while (start < end);
while (start < end);
} }
} // namespace arangodb::velocypack } // namespace arangodb::velocypack

View File

@ -73,7 +73,8 @@ uint8_t const* AttributeTranslator::translate (std::string const& key) const {
} }
// translate from string to id // 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)); auto it = _keyToId.find(std::string(key, length));
if (it == _keyToId.end()) { if (it == _keyToId.end()) {
@ -93,4 +94,3 @@ uint8_t const* AttributeTranslator::translate (uint64_t id) const {
return (*it).second; return (*it).second;
} }

View File

@ -49,8 +49,7 @@ void Builder::doActualSort (std::vector<SortEntry>& entries) {
uint64_t sizea = a.nameSize; uint64_t sizea = a.nameSize;
uint8_t const* pb = b.nameStart; uint8_t const* pb = b.nameStart;
uint64_t sizeb = b.nameSize; uint64_t sizeb = b.nameSize;
size_t const compareLength size_t const compareLength = static_cast<size_t>((std::min)(sizea, sizeb));
= static_cast<size_t>((std::min)(sizea, sizeb));
int res = memcmp(pa, pb, compareLength); int res = memcmp(pa, pb, compareLength);
return (res < 0 || (res == 0 && sizea < sizeb)); return (res < 0 || (res == 0 && sizea < sizeb));
@ -81,14 +80,12 @@ void Builder::sortObjectIndexShort (uint8_t* objBase,
auto cmp = [&](ValueLength a, ValueLength b) -> bool { auto cmp = [&](ValueLength a, ValueLength b) -> bool {
uint8_t const* aa = objBase + a; uint8_t const* aa = objBase + a;
uint8_t const* bb = objBase + b; uint8_t const* bb = objBase + b;
if (*aa >= 0x40 && *aa <= 0xbe && if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) {
*bb >= 0x40 && *bb <= 0xbe) {
// The fast path, short strings: // The fast path, short strings:
uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40); uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40);
int c = memcmp(aa + 1, bb + 1, static_cast<size_t>(m)); int c = memcmp(aa + 1, bb + 1, static_cast<size_t>(m));
return (c < 0 || (c == 0 && *aa < *bb)); return (c < 0 || (c == 0 && *aa < *bb));
} } else {
else {
uint64_t lena; uint64_t lena;
uint64_t lenb; uint64_t lenb;
aa = findAttrName(aa, lena); aa = findAttrName(aa, lena);
@ -103,7 +100,6 @@ void Builder::sortObjectIndexShort (uint8_t* objBase,
void Builder::sortObjectIndexLong(uint8_t* objBase, void Builder::sortObjectIndexLong(uint8_t* objBase,
std::vector<ValueLength>& offsets) { std::vector<ValueLength>& offsets) {
// on some platforms we can use a thread-local vector // on some platforms we can use a thread-local vector
#if __llvm__ == 1 #if __llvm__ == 1
// nono thread local // nono thread local
@ -136,8 +132,7 @@ void Builder::sortObjectIndex (uint8_t* objBase,
std::vector<ValueLength>& offsets) { std::vector<ValueLength>& offsets) {
if (offsets.size() > 32) { if (offsets.size() > 32) {
sortObjectIndexLong(objBase, offsets); sortObjectIndexLong(objBase, offsets);
} } else {
else {
sortObjectIndexShort(objBase, offsets); sortObjectIndexShort(objBase, offsets);
} }
} }
@ -182,12 +177,12 @@ void Builder::close () {
VELOCYPACK_ASSERT(index.size() > 0); VELOCYPACK_ASSERT(index.size() > 0);
// check if we can use the compact Array / Object format // check if we can use the compact Array / Object format
if (index.size() > 1 && if (index.size() > 1 && ((head == 0x13 || head == 0x14) ||
((head == 0x13 || head == 0x14) ||
(head == 0x06 && options->buildUnindexedArrays) || (head == 0x06 && options->buildUnindexedArrays) ||
(head == 0x0b && options->buildUnindexedObjects))) { (head == 0x0b && options->buildUnindexedObjects))) {
// use compact notation // use compact notation
ValueLength nLen = getVariableValueLength(static_cast<ValueLength>(index.size())); ValueLength nLen =
getVariableValueLength(static_cast<ValueLength>(index.size()));
VELOCYPACK_ASSERT(nLen > 0); VELOCYPACK_ASSERT(nLen > 0);
ValueLength byteSize = _pos - (tos + 8) + nLen; ValueLength byteSize = _pos - (tos + 8) + nLen;
VELOCYPACK_ASSERT(byteSize > 0); VELOCYPACK_ASSERT(byteSize > 0);
@ -199,13 +194,13 @@ void Builder::close () {
} }
if (bLen < 9) { 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); _start[tos] = (isArray ? 0x13 : 0x14);
ValueLength targetPos = 1 + bLen; ValueLength targetPos = 1 + bLen;
if (_pos > (tos + 9)) { if (_pos > (tos + 9)) {
memmove(_start + tos + targetPos, _start + tos + 9, memmove(_start + tos + targetPos, _start + tos + 9, _pos - (tos + 9));
_pos - (tos + 9));
} }
// store byte length // store byte length
@ -216,7 +211,8 @@ void Builder::close () {
if (nLen > 8 - bLen) { if (nLen > 8 - bLen) {
reserveSpace(nLen); 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 -= 8;
_pos += nLen + bLen; _pos += nLen + bLen;
@ -237,8 +233,7 @@ void Builder::close () {
needNrSubs = false; needNrSubs = false;
} }
// For objects we leave needNrSubs at true here! // 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])) { (_pos - tos) - index[0] == index.size() * (index[1] - index[0])) {
// In this case it could be that all entries have the same length // In this case it could be that all entries have the same length
// and we do not need an offset table at all: // and we do not need an offset table at all:
@ -246,8 +241,7 @@ void Builder::close () {
ValueLength const subLen = index[1] - index[0]; ValueLength const subLen = index[1] - index[0];
if ((_pos - tos) - index[index.size() - 1] != subLen) { if ((_pos - tos) - index[index.size() - 1] != subLen) {
noTable = false; noTable = false;
} } else {
else {
for (size_t i = 1; i < index.size() - 1; i++) { for (size_t i = 1; i < index.size() - 1; i++) {
if (index[i + 1] - index[i] != subLen) { if (index[i + 1] - index[i] != subLen) {
noTable = false; noTable = false;
@ -265,21 +259,19 @@ void Builder::close () {
unsigned int offsetSize; unsigned int offsetSize;
// can be 1, 2, 4 or 8 for the byte width of the offsets, // can be 1, 2, 4 or 8 for the byte width of the offsets,
// the byte length and the number of subvalues: // the byte length and the number of subvalues:
if (_pos - tos + (needIndexTable ? index.size() : 0) if (_pos - tos + (needIndexTable ? index.size() : 0) - (needNrSubs ? 6 : 7) <=
- (needNrSubs ? 6 : 7) <= 0xff) { 0xff) {
// We have so far used _pos - tos bytes, including the reserved 8 // 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 // 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 // case we would win back 6 bytes but would need one byte per subvalue
// for the index table // for the index table
offsetSize = 1; offsetSize = 1;
} } else if (_pos - tos + (needIndexTable ? 2 * index.size() : 0) <= 0xffff) {
else if (_pos - tos + (needIndexTable ? 2 * index.size() : 0) <= 0xffff) {
offsetSize = 2; offsetSize = 2;
} } else if (_pos - tos + (needIndexTable ? 4 * index.size() : 0) <=
else if (_pos - tos + (needIndexTable ? 4 * index.size() : 0) <= 0xffffffffu) { 0xffffffffu) {
offsetSize = 4; offsetSize = 4;
} } else {
else {
offsetSize = 8; offsetSize = 8;
} }
@ -290,8 +282,7 @@ void Builder::close () {
targetPos = 2; targetPos = 2;
} }
if (_pos > (tos + 9)) { if (_pos > (tos + 9)) {
memmove(_start + tos + targetPos, _start + tos + 9, memmove(_start + tos + targetPos, _start + tos + 9, _pos - (tos + 9));
_pos - (tos + 9));
} }
_pos -= (9 - targetPos); _pos -= (9 - targetPos);
for (size_t i = 0; i < index.size(); i++) { for (size_t i = 0; i < index.size(); i++) {
@ -312,9 +303,7 @@ void Builder::close () {
// Object // Object
if (!options->sortAttributeNames) { if (!options->sortAttributeNames) {
_start[tos] = 0x0f; // unsorted _start[tos] = 0x0f; // unsorted
} } else if (index.size() >= 2 && options->sortAttributeNames) {
else if (index.size() >= 2 &&
options->sortAttributeNames) {
sortObjectIndex(_start + tos, index); sortObjectIndex(_start + tos, index);
} }
} }
@ -325,8 +314,7 @@ void Builder::close () {
x >>= 8; x >>= 8;
} }
} }
} } else { // no index table
else { // no index table
if (_start[tos] == 0x06) { if (_start[tos] == 0x06) {
_start[tos] = 0x02; _start[tos] = 0x02;
} }
@ -335,11 +323,9 @@ void Builder::close () {
if (offsetSize > 1) { if (offsetSize > 1) {
if (offsetSize == 2) { if (offsetSize == 2) {
_start[tos] += 1; _start[tos] += 1;
} } else if (offsetSize == 4) {
else if (offsetSize == 4) {
_start[tos] += 2; _start[tos] += 2;
} } else { // offsetSize == 8
else { // offsetSize == 8
_start[tos] += 3; _start[tos] += 3;
if (needNrSubs) { if (needNrSubs) {
appendLength(index.size(), 8); appendLength(index.size(), 8);
@ -397,7 +383,7 @@ bool Builder::hasKey (std::string const& key) const {
return false; 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 { Slice Builder::getKey(std::string const& key) const {
if (_stack.empty()) { if (_stack.empty()) {
throw Exception(Exception::BuilderNeedOpenObject); 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) { for (size_t i = 0; i < index.size(); ++i) {
Slice s(_start + tos + index[i], options); Slice s(_start + tos + index[i], options);
if (!s.isString()) {
s = s.makeKey();
}
if (s.isString() && s.isEqualString(key)) { if (s.isString() && s.isEqualString(key)) {
return s; return Slice(s.start() + s.byteSize(), options);
} }
} }
return Slice(); 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. // table is created and a new ValueLength is pushed onto the stack.
switch (item.valueType()) { switch (item.valueType()) {
case ValueType::None: { case ValueType::None: {
throw Exception(Exception::BuilderUnexpectedType, "Cannot set a ValueType::None"); throw Exception(Exception::BuilderUnexpectedType,
"Cannot set a ValueType::None");
} }
case ValueType::Null: { case ValueType::Null: {
reserveSpace(1); reserveSpace(1);
@ -437,13 +427,13 @@ uint8_t* Builder::set (Value const& item) {
} }
case ValueType::Bool: { case ValueType::Bool: {
if (ctype != Value::CType::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); reserveSpace(1);
if (item.getBool()) { if (item.getBool()) {
_start[_pos++] = 0x1a; _start[_pos++] = 0x1a;
} } else {
else {
_start[_pos++] = 0x19; _start[_pos++] = 0x19;
} }
break; break;
@ -464,7 +454,8 @@ uint8_t* Builder::set (Value const& item) {
v = static_cast<double>(item.getUInt64()); v = static_cast<double>(item.getUInt64());
break; break;
default: 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)); reserveSpace(1 + sizeof(double));
_start[_pos++] = 0x1b; _start[_pos++] = 0x1b;
@ -473,8 +464,14 @@ uint8_t* Builder::set (Value const& item) {
break; break;
} }
case ValueType::External: { case ValueType::External: {
if (options->disallowExternals) {
// External values explicitly disallowed as a security
// precaution
throw Exception(Exception::BuilderExternalsDisallowed);
}
if (ctype != Value::CType::VoidPtr) { 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*)); reserveSpace(1 + sizeof(void*));
// store pointer. this doesn't need to be portable // 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()); vv = static_cast<int64_t>(item.getUInt64());
break; break;
default: 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) { 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); reserveSpace(1);
if (vv >= 0) { if (vv >= 0) {
_start[_pos++] = static_cast<uint8_t>(vv + 0x30); _start[_pos++] = static_cast<uint8_t>(vv + 0x30);
} } else {
else {
_start[_pos++] = static_cast<uint8_t>(vv + 0x40); _start[_pos++] = static_cast<uint8_t>(vv + 0x40);
} }
break; break;
@ -524,7 +522,8 @@ uint8_t* Builder::set (Value const& item) {
v = toInt64(item.getUInt64()); v = toInt64(item.getUInt64());
break; break;
default: default:
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::Int"); throw Exception(Exception::BuilderUnexpectedValue,
"Must give number for ValueType::Int");
} }
addInt(v); addInt(v);
break; break;
@ -534,13 +533,17 @@ uint8_t* Builder::set (Value const& item) {
switch (ctype) { switch (ctype) {
case Value::CType::Double: case Value::CType::Double:
if (item.getDouble() < 0.0) { 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()); v = static_cast<uint64_t>(item.getDouble());
break; break;
case Value::CType::Int64: case Value::CType::Int64:
if (item.getInt64() < 0) { 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()); v = static_cast<uint64_t>(item.getInt64());
break; break;
@ -548,7 +551,8 @@ uint8_t* Builder::set (Value const& item) {
v = item.getUInt64(); v = item.getUInt64();
break; break;
default: default:
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::UInt"); throw Exception(Exception::BuilderUnexpectedValue,
"Must give number for ValueType::UInt");
} }
addUInt(v); addUInt(v);
break; break;
@ -566,22 +570,23 @@ uint8_t* Builder::set (Value const& item) {
v = toInt64(item.getUInt64()); v = toInt64(item.getUInt64());
break; break;
default: default:
throw Exception(Exception::BuilderUnexpectedValue, "Must give number for ValueType::UTCDate"); throw Exception(Exception::BuilderUnexpectedValue,
"Must give number for ValueType::UTCDate");
} }
addUTCDate(v); addUTCDate(v);
break; break;
} }
case ValueType::String: { case ValueType::String: {
if (ctype != Value::CType::String && if (ctype != Value::CType::String && ctype != Value::CType::CharPtr) {
ctype != Value::CType::CharPtr) { throw Exception(
throw Exception(Exception::BuilderUnexpectedValue, "Must give a string or char const* for ValueType::String"); Exception::BuilderUnexpectedValue,
"Must give a string or char const* for ValueType::String");
} }
std::string const* s; std::string const* s;
std::string value; std::string value;
if (ctype == Value::CType::String) { if (ctype == Value::CType::String) {
s = item.getString(); s = item.getString();
} } else {
else {
value = item.getCharPtr(); value = item.getCharPtr();
s = &value; s = &value;
} }
@ -591,8 +596,7 @@ uint8_t* Builder::set (Value const& item) {
reserveSpace(1 + size); reserveSpace(1 + size);
_start[_pos++] = static_cast<uint8_t>(0x40 + size); _start[_pos++] = static_cast<uint8_t>(0x40 + size);
memcpy(_start + _pos, s->c_str(), size); memcpy(_start + _pos, s->c_str(), size);
} } else {
else {
// long string // long string
reserveSpace(1 + 8 + size); reserveSpace(1 + 8 + size);
_start[_pos++] = 0xbf; _start[_pos++] = 0xbf;
@ -611,16 +615,16 @@ uint8_t* Builder::set (Value const& item) {
break; break;
} }
case ValueType::Binary: { case ValueType::Binary: {
if (ctype != Value::CType::String && if (ctype != Value::CType::String && ctype != Value::CType::CharPtr) {
ctype != Value::CType::CharPtr) { throw Exception(
throw Exception(Exception::BuilderUnexpectedValue, "Must provide std::string or char const* for ValueType::Binary"); Exception::BuilderUnexpectedValue,
"Must provide std::string or char const* for ValueType::Binary");
} }
std::string const* s; std::string const* s;
std::string value; std::string value;
if (ctype == Value::CType::String) { if (ctype == Value::CType::String) {
s = item.getString(); s = item.getString();
} } else {
else {
value = item.getCharPtr(); value = item.getCharPtr();
s = &value; s = &value;
} }
@ -644,7 +648,8 @@ uint8_t* Builder::set (Value const& item) {
throw Exception(Exception::NotImplemented); throw Exception(Exception::NotImplemented);
} }
case ValueType::Custom: { 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; return oldPos;
@ -669,8 +674,7 @@ uint8_t* Builder::set (ValuePair const& pair) {
memcpy(_start + _pos, pair.getStart(), v); memcpy(_start + _pos, pair.getStart(), v);
_pos += v; _pos += v;
return nullptr; // unused here return nullptr; // unused here
} } else if (pair.valueType() == ValueType::String) {
else if (pair.valueType() == ValueType::String) {
uint64_t size = pair.getSize(); uint64_t size = pair.getSize();
if (size > 126) { if (size > 126) {
// long string // long string
@ -678,8 +682,7 @@ uint8_t* Builder::set (ValuePair const& pair) {
_start[_pos++] = 0xbf; _start[_pos++] = 0xbf;
appendLength(size, 8); appendLength(size, 8);
_pos += size; _pos += size;
} } else {
else {
// short string // short string
reserveSpace(1 + size); reserveSpace(1 + size);
_start[_pos++] = static_cast<uint8_t>(0x40 + 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 // _start + _pos - size .. _start + _pos - 1
// with valid UTF-8! // with valid UTF-8!
return _start + _pos - size; 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 // We only reserve space here, the caller has to fill in the custom type
uint64_t size = pair.getSize(); uint64_t size = pair.getSize();
reserveSpace(size); reserveSpace(size);
@ -702,7 +704,9 @@ uint8_t* Builder::set (ValuePair const& pair) {
_pos += size; _pos += size;
return _start + _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 { 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) { for (ValueLength i = 1; i < n; ++i) {
Slice current = obj.keyAt(i); Slice current = obj.keyAt(i);
if (!current.isString()) { if (!current.isString()) {
throw Exception(Exception::BuilderUnexpectedType, "Expecting String key"); throw Exception(Exception::BuilderUnexpectedType,
"Expecting String key");
} }
ValueLength len2; ValueLength len2;
@ -733,14 +738,14 @@ void Builder::checkAttributeUniqueness (Slice const& obj) const {
len = len2; len = len2;
p = q; p = q;
} }
} } else {
else {
std::unordered_set<std::string> keys; std::unordered_set<std::string> keys;
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
Slice key = obj.keyAt(i); Slice key = obj.keyAt(i);
if (!key.isString()) { if (!key.isString()) {
throw Exception(Exception::BuilderUnexpectedType, "Expecting String key"); throw Exception(Exception::BuilderUnexpectedType,
"Expecting String key");
} }
if (!keys.emplace(key.copyString()).second) { 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); return addInternal<Slice>(attrName, sub);
} }
uint8_t* Builder::add (Value const& sub) { uint8_t* Builder::add(Value const& sub) { return addInternal<Value>(sub); }
return addInternal<Value>(sub);
}
uint8_t* Builder::add(ValuePair const& sub) { uint8_t* Builder::add(ValuePair const& sub) {
return addInternal<ValuePair>(sub); return addInternal<ValuePair>(sub);
} }
uint8_t* Builder::add (Slice const& sub) { uint8_t* Builder::add(Slice const& sub) { return addInternal<Slice>(sub); }
return addInternal<Slice>(sub);
}
static_assert(sizeof(double) == 8, "double is not 8 bytes"); static_assert(sizeof(double) == 8, "double is not 8 bytes");

View File

@ -36,7 +36,8 @@
using namespace arangodb::velocypack; using namespace arangodb::velocypack;
// convert a vector of strings into an unordered_set of strings // 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; std::unordered_set<std::string> s;
for (auto const& it : keys) { for (auto const& it : keys) {
s.emplace(it); s.emplace(it);
@ -44,7 +45,9 @@ static inline std::unordered_set<std::string> ToSet (std::vector<std::string> co
return s; 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); ArrayIterator it(slice);
ValueLength index = 0; 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 // construct a new Array
Builder b; Builder b;
b.add(Value(ValueType::Array)); b.add(Value(ValueType::Array));
@ -78,7 +83,9 @@ Builder Collection::filter (Slice const& slice, std::function<bool(Slice const&,
return b; 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); ArrayIterator it(slice);
ValueLength index = 0; ValueLength index = 0;
@ -94,7 +101,9 @@ Slice Collection::find (Slice const& slice, std::function<bool(Slice const&, Val
return Slice(); 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); ArrayIterator it(slice);
ValueLength index = 0; ValueLength index = 0;
@ -110,7 +119,8 @@ bool Collection::contains (Slice const& slice, std::function<bool(Slice const&,
return false; 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); ArrayIterator it(slice);
ValueLength index = 0; ValueLength index = 0;
@ -126,7 +136,8 @@ bool Collection::all (Slice const& slice, std::function<bool(Slice const&, Value
return true; 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); ArrayIterator it(slice);
ValueLength index = 0; 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); ObjectIterator it(slice);
while (it.valid()) { while (it.valid()) {
@ -186,7 +198,8 @@ Builder Collection::values (Slice const& slice) {
return b; 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 // check if there are so many keys that we want to use the hash-based version
// cut-off values are arbitrary... // cut-off values are arbitrary...
if (keys.size() >= 4 && slice.length() > 10) { 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; 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; Builder b;
b.add(Value(ValueType::Object)); b.add(Value(ValueType::Object));
@ -228,7 +242,8 @@ Builder Collection::keep (Slice const& slice, std::unordered_set<std::string> co
return b; 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 // check if there are so many keys that we want to use the hash-based version
// cut-off values are arbitrary... // cut-off values are arbitrary...
if (keys.size() >= 4 && slice.length() > 10) { if (keys.size() >= 4 && slice.length() > 10) {
@ -252,7 +267,8 @@ Builder Collection::remove (Slice const& slice, std::vector<std::string> const&
return b; 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; Builder b;
b.add(Value(ValueType::Object)); b.add(Value(ValueType::Object));
@ -270,7 +286,8 @@ Builder Collection::remove (Slice const& slice, std::unordered_set<std::string>
return b; 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()) { if (!left.isObject() || !right.isObject()) {
throw Exception(Exception::InvalidValueType, "Expecting type Object"); 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()) { if (found == rightValues.end()) {
// use left value // use left value
b.add(key, it.value()); b.add(key, it.value());
} } else if (mergeValues && it.value().isObject() &&
else if (mergeValues && it.value().isObject() && (*found).second.isObject()) { (*found).second.isObject()) {
// merge both values // merge both values
Builder sub = Collection::merge(it.value(), (*found).second, true); Builder sub = Collection::merge(it.value(), (*found).second, true);
b.add(key, sub.slice()); b.add(key, sub.slice());
} } else {
else {
// use right value // use right value
b.add(key, (*found).second); b.add(key, (*found).second);
// clear the value in the map so its not added again // 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> 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> 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); ObjectIterator it(value);
while (it.valid()) { while (it.valid()) {
@ -359,7 +379,9 @@ static bool visitObject (Slice const& value, std::function<bool(Slice const& key
} }
template <Collection::VisitationOrder order> 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); ArrayIterator it(value);
while (it.valid()) { while (it.valid()) {
@ -390,7 +412,9 @@ static bool visitArray (Slice const& value, std::function<bool(Slice const& key,
} }
template <Collection::VisitationOrder order> 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()) { if (slice.isObject()) {
return visitObject<order>(slice, func); 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); 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) { if (order == Collection::PreOrder) {
doVisit<Collection::PreOrder>(slice, func); doVisit<Collection::PreOrder>(slice, func);
} } else {
else {
doVisit<Collection::PostOrder>(slice, func); doVisit<Collection::PostOrder>(slice, func);
} }
} }

View File

@ -41,25 +41,63 @@ namespace arangodb {
}; };
void Dumper::appendUInt(uint64_t v) { void Dumper::appendUInt(uint64_t v) {
if (10000000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000000ULL) % 10); } if (10000000000000000000ULL <= v) {
if ( 1000000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000000ULL) % 10); } _sink->push_back('0' + (v / 10000000000000000000ULL) % 10);
if ( 100000000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000000ULL) % 10); } }
if ( 10000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000ULL) % 10); } if (1000000000000000000ULL <= v) {
if ( 1000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000ULL) % 10); } _sink->push_back('0' + (v / 1000000000000000000ULL) % 10);
if ( 100000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000ULL) % 10); } }
if ( 10000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000ULL) % 10); } if (100000000000000000ULL <= v) {
if ( 1000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000ULL) % 10); } _sink->push_back('0' + (v / 100000000000000000ULL) % 10);
if ( 100000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000ULL) % 10); } }
if ( 10000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000ULL) % 10); } if (10000000000000000ULL <= v) {
if ( 1000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000ULL) % 10); } _sink->push_back('0' + (v / 10000000000000000ULL) % 10);
if ( 100000000ULL <= v) { _sink->push_back('0' + (v / 100000000ULL) % 10); } }
if ( 10000000ULL <= v) { _sink->push_back('0' + (v / 10000000ULL) % 10); } if (1000000000000000ULL <= v) {
if ( 1000000ULL <= v) { _sink->push_back('0' + (v / 1000000ULL) % 10); } _sink->push_back('0' + (v / 1000000000000000ULL) % 10);
if ( 100000ULL <= v) { _sink->push_back('0' + (v / 100000ULL) % 10); } }
if ( 10000ULL <= v) { _sink->push_back('0' + (v / 10000ULL) % 10); } if (100000000000000ULL <= v) {
if ( 1000ULL <= v) { _sink->push_back('0' + (v / 1000ULL) % 10); } _sink->push_back('0' + (v / 100000000000000ULL) % 10);
if ( 100ULL <= v) { _sink->push_back('0' + (v / 100ULL) % 10); } }
if ( 10ULL <= v) { _sink->push_back('0' + (v / 10ULL) % 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)); _sink->push_back('0' + (v % 10));
} }
@ -69,8 +107,7 @@ void Dumper::dumpInteger (Slice const* slice) {
uint64_t v = slice->getUInt(); uint64_t v = slice->getUInt();
appendUInt(v); appendUInt(v);
} } else if (slice->isType(ValueType::Int)) {
else if (slice->isType(ValueType::Int)) {
int64_t v = slice->getInt(); int64_t v = slice->getInt();
if (v == INT64_MIN) { if (v == INT64_MIN) {
_sink->append("-9223372036854775808", 20); _sink->append("-9223372036854775808", 20);
@ -81,60 +118,108 @@ void Dumper::dumpInteger (Slice const* slice) {
v = -v; v = -v;
} }
if (1000000000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000000000LL) % 10); } if (1000000000000000000LL <= v) {
if ( 100000000000000000LL <= v) { _sink->push_back('0' + (v / 100000000000000000LL) % 10); } _sink->push_back('0' + (v / 1000000000000000000LL) % 10);
if ( 10000000000000000LL <= v) { _sink->push_back('0' + (v / 10000000000000000LL) % 10); } }
if ( 1000000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000000LL) % 10); } if (100000000000000000LL <= v) {
if ( 100000000000000LL <= v) { _sink->push_back('0' + (v / 100000000000000LL) % 10); } _sink->push_back('0' + (v / 100000000000000000LL) % 10);
if ( 10000000000000LL <= v) { _sink->push_back('0' + (v / 10000000000000LL) % 10); } }
if ( 1000000000000LL <= v) { _sink->push_back('0' + (v / 1000000000000LL) % 10); } if (10000000000000000LL <= v) {
if ( 100000000000LL <= v) { _sink->push_back('0' + (v / 100000000000LL) % 10); } _sink->push_back('0' + (v / 10000000000000000LL) % 10);
if ( 10000000000LL <= v) { _sink->push_back('0' + (v / 10000000000LL) % 10); } }
if ( 1000000000LL <= v) { _sink->push_back('0' + (v / 1000000000LL) % 10); } if (1000000000000000LL <= v) {
if ( 100000000LL <= v) { _sink->push_back('0' + (v / 100000000LL) % 10); } _sink->push_back('0' + (v / 1000000000000000LL) % 10);
if ( 10000000LL <= v) { _sink->push_back('0' + (v / 10000000LL) % 10); } }
if ( 1000000LL <= v) { _sink->push_back('0' + (v / 1000000LL) % 10); } if (100000000000000LL <= v) {
if ( 100000LL <= v) { _sink->push_back('0' + (v / 100000LL) % 10); } _sink->push_back('0' + (v / 100000000000000LL) % 10);
if ( 10000LL <= v) { _sink->push_back('0' + (v / 10000LL) % 10); } }
if ( 1000LL <= v) { _sink->push_back('0' + (v / 1000LL) % 10); } if (10000000000000LL <= v) {
if ( 100LL <= v) { _sink->push_back('0' + (v / 100LL) % 10); } _sink->push_back('0' + (v / 10000000000000LL) % 10);
if ( 10LL <= v) { _sink->push_back('0' + (v / 10LL) % 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)); _sink->push_back('0' + (v % 10));
} } else if (slice->isType(ValueType::SmallInt)) {
else if (slice->isType(ValueType::SmallInt)) {
int64_t v = slice->getSmallInt(); int64_t v = slice->getSmallInt();
if (v < 0) { if (v < 0) {
_sink->push_back('-'); _sink->push_back('-');
v = -v; v = -v;
} }
_sink->push_back('0' + static_cast<char>(v)); _sink->push_back('0' + static_cast<char>(v));
} } else {
else { // we should never get here
throw Exception(Exception::InternalError, "Unexpected number type"); throw Exception(Exception::InvalidValueType, "Unexpected number type");
} }
} }
void Dumper::dumpString(char const* src, ValueLength len) { void Dumper::dumpString(char const* src, ValueLength len) {
static char const EscapeTable[256] = { static char const EscapeTable[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F // 0 1 2 3 4 5 6 7 8 9 A B C D E
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 // F
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r',
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', // 20 'u',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30~4F 'u', // 00
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 'u',
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60~FF 'u', // 10
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, '/', // 20
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, // 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, 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, // 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* p = reinterpret_cast<uint8_t const*>(src);
uint8_t const* e = p + len; 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); uint16_t i2 = (((uint16_t)c) & 0x0f);
_sink->append("00", 2); _sink->append("00", 2);
_sink->push_back(static_cast<char>((i1 < 10) ? ('0' + i1) : ('A' + i1 - 10))); _sink->push_back(
_sink->push_back(static_cast<char>((i2 < 10) ? ('0' + i2) : ('A' + i2 - 10))); 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)); _sink->push_back(static_cast<char>(c));
} }
} } else if ((c & 0xe0) == 0xc0) {
else if ((c & 0xe0) == 0xc0) {
// two-byte sequence // two-byte sequence
if (p + 1 >= e) { if (p + 1 >= e) {
throw Exception(Exception::InvalidUtf8Sequence); throw Exception(Exception::InvalidUtf8Sequence);
@ -173,8 +258,7 @@ void Dumper::dumpString (char const* src, ValueLength len) {
_sink->append(reinterpret_cast<char const*>(p), 2); _sink->append(reinterpret_cast<char const*>(p), 2);
++p; ++p;
} } else if ((c & 0xf0) == 0xe0) {
else if ((c & 0xf0) == 0xe0) {
// three-byte sequence // three-byte sequence
if (p + 2 >= e) { if (p + 2 >= e) {
throw Exception(Exception::InvalidUtf8Sequence); throw Exception(Exception::InvalidUtf8Sequence);
@ -182,8 +266,7 @@ void Dumper::dumpString (char const* src, ValueLength len) {
_sink->append(reinterpret_cast<char const*>(p), 3); _sink->append(reinterpret_cast<char const*>(p), 3);
p += 2; p += 2;
} } else if ((c & 0xf8) == 0xf0) {
else if ((c & 0xf8) == 0xf0) {
// four-byte sequence // four-byte sequence
if (p + 3 >= e) { if (p + 3 >= e) {
throw Exception(Exception::InvalidUtf8Sequence); throw Exception(Exception::InvalidUtf8Sequence);
@ -217,8 +300,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
case ValueType::Bool: { case ValueType::Bool: {
if (slice->getBool()) { if (slice->getBool()) {
_sink->append("true", 4); _sink->append("true", 4);
} } else {
else {
_sink->append("false", 5); _sink->append("false", 5);
} }
break; break;
@ -241,8 +323,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
} }
--_indentation; --_indentation;
indent(); indent();
} } else {
else {
while (it.valid()) { while (it.valid()) {
if (!it.isFirst()) { if (!it.isFirst()) {
_sink->push_back(','); _sink->push_back(',');
@ -274,8 +355,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
} }
--_indentation; --_indentation;
indent(); indent();
} } else {
else {
while (it.valid()) { while (it.valid()) {
if (!it.isFirst()) { if (!it.isFirst()) {
_sink->push_back(','); _sink->push_back(',');
@ -294,8 +374,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
double const v = slice->getDouble(); double const v = slice->getDouble();
if (std::isnan(v) || !std::isfinite(v)) { if (std::isnan(v) || !std::isfinite(v)) {
handleUnsupportedType(slice); handleUnsupportedType(slice);
} } else {
else {
char temp[24]; char temp[24];
int len = fpconv_dtoa(v, &temp[0]); int len = fpconv_dtoa(v, &temp[0]);
_sink->append(&temp[0], static_cast<ValueLength>(len)); _sink->append(&temp[0], static_cast<ValueLength>(len));
@ -350,8 +429,7 @@ void Dumper::dumpValue (Slice const* slice, Slice const* base) {
case ValueType::Custom: { case ValueType::Custom: {
if (options->customTypeHandler == nullptr) { if (options->customTypeHandler == nullptr) {
handleUnsupportedType(slice); handleUnsupportedType(slice);
} } else {
else {
options->customTypeHandler->toJson(*slice, this, *base); options->customTypeHandler->toJson(*slice, this, *base);
} }
break; break;

View File

@ -39,4 +39,3 @@ std::ostream& operator<< (std::ostream& stream, Exception const* ex) {
std::ostream& operator<<(std::ostream& stream, Exception const& ex) { std::ostream& operator<<(std::ostream& stream, Exception const& ex) {
return operator<<(stream, &ex); return operator<<(stream, &ex);
} }

View File

@ -65,4 +65,3 @@ std::ostream& operator<< (std::ostream& stream, HexDump const* hexdump) {
std::ostream& operator<<(std::ostream& stream, HexDump const& hexdump) { std::ostream& operator<<(std::ostream& stream, HexDump const& hexdump) {
return operator<<(stream, &hexdump); return operator<<(stream, &hexdump);
} }

View File

@ -48,4 +48,3 @@ std::ostream& operator<< (std::ostream& stream, ObjectIterator const* it) {
std::ostream& operator<<(std::ostream& stream, ObjectIterator const& it) { std::ostream& operator<<(std::ostream& stream, ObjectIterator const& it) {
return operator<<(stream, &it); return operator<<(stream, &it);
} }

View File

@ -31,4 +31,3 @@ using namespace arangodb::velocypack;
// default options instance // default options instance
Options Options::Defaults; Options Options::Defaults;

View File

@ -41,9 +41,7 @@ ValueLength Parser::parseInternal (bool multi) {
_b.options = options; // copy over options _b.options = options; // copy over options
// skip over optional BOM // skip over optional BOM
if (_size >= 3 && if (_size >= 3 && _start[0] == 0xef && _start[1] == 0xbb &&
_start[0] == 0xef &&
_start[1] == 0xbb &&
_start[2] == 0xbf) { _start[2] == 0xbf) {
// found UTF-8 BOM. simply skip over it // found UTF-8 BOM. simply skip over it
_pos += 3; _pos += 3;
@ -53,16 +51,14 @@ ValueLength Parser::parseInternal (bool multi) {
do { do {
parseJson(); parseJson();
nr++; nr++;
while (_pos < _size && while (_pos < _size && isWhiteSpace(_start[_pos])) {
isWhiteSpace(_start[_pos])) {
++_pos; ++_pos;
} }
if (!multi && _pos != _size) { if (!multi && _pos != _size) {
consume(); // to get error reporting right consume(); // to get error reporting right
throw Exception(Exception::ParseError, "Expecting EOF"); throw Exception(Exception::ParseError, "Expecting EOF");
} }
} } while (multi && _pos < _size);
while (multi && _pos < _size);
return nr; return nr;
} }
@ -123,23 +119,18 @@ void Parser::parseNumber () {
if (!numberValue.isInteger) { if (!numberValue.isInteger) {
if (negative) { if (negative) {
_b.addDouble(-numberValue.doubleValue); _b.addDouble(-numberValue.doubleValue);
} } else {
else {
_b.addDouble(numberValue.doubleValue); _b.addDouble(numberValue.doubleValue);
} }
} } else if (negative) {
else if (negative) {
if (numberValue.intValue <= static_cast<uint64_t>(INT64_MAX)) { if (numberValue.intValue <= static_cast<uint64_t>(INT64_MAX)) {
_b.addInt(-static_cast<int64_t>(numberValue.intValue)); _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); _b.addInt(INT64_MIN);
} } else {
else {
_b.addDouble(-static_cast<double>(numberValue.intValue)); _b.addDouble(-static_cast<double>(numberValue.intValue));
} }
} } else {
else {
_b.addUInt(numberValue.intValue); _b.addUInt(numberValue.intValue);
} }
return; return;
@ -156,8 +147,7 @@ void Parser::parseNumber () {
fractionalPart = scanDigitsFractional(); fractionalPart = scanDigitsFractional();
if (negative) { if (negative) {
fractionalPart = -numberValue.asDouble() - fractionalPart; fractionalPart = -numberValue.asDouble() - fractionalPart;
} } else {
else {
fractionalPart = numberValue.asDouble() + fractionalPart; fractionalPart = numberValue.asDouble() + fractionalPart;
} }
i = consume(); i = consume();
@ -165,12 +155,10 @@ void Parser::parseNumber () {
_b.addDouble(fractionalPart); _b.addDouble(fractionalPart);
return; return;
} }
} } else {
else {
if (negative) { if (negative) {
fractionalPart = -numberValue.asDouble(); fractionalPart = -numberValue.asDouble();
} } else {
else {
fractionalPart = numberValue.asDouble(); fractionalPart = numberValue.asDouble();
} }
} }
@ -193,8 +181,7 @@ void Parser::parseNumber () {
scanDigits(exponent); scanDigits(exponent);
if (negative) { if (negative) {
fractionalPart *= pow(10, -exponent.asDouble()); fractionalPart *= pow(10, -exponent.asDouble());
} } else {
else {
fractionalPart *= pow(10, exponent.asDouble()); fractionalPart *= pow(10, exponent.asDouble());
} }
if (std::isnan(fractionalPart) || !std::isfinite(fractionalPart)) { if (std::isnan(fractionalPart) || !std::isfinite(fractionalPart)) {
@ -225,8 +212,7 @@ void Parser::parseString () {
if (options->validateUtf8Strings) { if (options->validateUtf8Strings) {
count = JSONStringCopyCheckUtf8(_b._start + _b._pos, _start + _pos, count = JSONStringCopyCheckUtf8(_b._start + _b._pos, _start + _pos,
remainder); remainder);
} } else {
else {
count = JSONStringCopy(_b._start + _b._pos, _start + _pos, remainder); count = JSONStringCopy(_b._start + _b._pos, _start + _pos, remainder);
} }
_pos += count; _pos += count;
@ -236,8 +222,7 @@ void Parser::parseString () {
if (!large && _b._pos - (base + 1) > 126) { if (!large && _b._pos - (base + 1) > 126) {
large = true; large = true;
_b.reserveSpace(8); _b.reserveSpace(8);
memmove(_b._start + base + 9, _b._start + base + 1, memmove(_b._start + base + 9, _b._start + base + 1, _b._pos - (base + 1));
_b._pos - (base + 1));
_b._pos += 8; _b._pos += 8;
} }
switch (i) { switch (i) {
@ -247,8 +232,7 @@ void Parser::parseString () {
len = _b._pos - (base + 1); len = _b._pos - (base + 1);
_b._start[base] = 0x40 + static_cast<uint8_t>(len); _b._start[base] = 0x40 + static_cast<uint8_t>(len);
// String is ready // String is ready
} } else {
else {
len = _b._pos - (base + 9); len = _b._pos - (base + 9);
_b._start[base] = 0xbf; _b._start[base] = 0xbf;
for (ValueLength i = 1; i <= 8; i++) { for (ValueLength i = 1; i <= 8; i++) {
@ -301,37 +285,32 @@ void Parser::parseString () {
for (int j = 0; j < 4; j++) { for (int j = 0; j < 4; j++) {
i = consume(); i = consume();
if (i < 0) { if (i < 0) {
throw Exception(Exception::ParseError, "Unfinished \\uXXXX escape sequence"); throw Exception(Exception::ParseError,
"Unfinished \\uXXXX escape sequence");
} }
if (i >= '0' && i <= '9') { if (i >= '0' && i <= '9') {
v = (v << 4) + i - '0'; v = (v << 4) + i - '0';
} } else if (i >= 'a' && i <= 'f') {
else if (i >= 'a' && i <= 'f') {
v = (v << 4) + i - 'a' + 10; v = (v << 4) + i - 'a' + 10;
} } else if (i >= 'A' && i <= 'F') {
else if (i >= 'A' && i <= 'F') {
v = (v << 4) + i - 'A' + 10; v = (v << 4) + i - 'A' + 10;
} } else {
else { throw Exception(Exception::ParseError,
throw Exception(Exception::ParseError, "Illegal \\uXXXX escape sequence"); "Illegal \\uXXXX escape sequence");
} }
} }
if (v < 0x80) { if (v < 0x80) {
_b.reserveSpace(1); _b.reserveSpace(1);
_b._start[_b._pos++] = static_cast<uint8_t>(v); _b._start[_b._pos++] = static_cast<uint8_t>(v);
highSurrogate = 0; highSurrogate = 0;
} } else if (v < 0x800) {
else if (v < 0x800) {
_b.reserveSpace(2); _b.reserveSpace(2);
_b._start[_b._pos++] = 0xc0 + (v >> 6); _b._start[_b._pos++] = 0xc0 + (v >> 6);
_b._start[_b._pos++] = 0x80 + (v & 0x3f); _b._start[_b._pos++] = 0x80 + (v & 0x3f);
highSurrogate = 0; highSurrogate = 0;
} } else if (v >= 0xdc00 && v < 0xe000 && highSurrogate != 0) {
else if (v >= 0xdc00 && v < 0xe000 &&
highSurrogate != 0) {
// Low surrogate, put the two together: // Low surrogate, put the two together:
v = 0x10000 + ((highSurrogate - 0xd800) << 10) v = 0x10000 + ((highSurrogate - 0xd800) << 10) + v - 0xdc00;
+ v - 0xdc00;
_b._pos -= 3; _b._pos -= 3;
_b.reserveSpace(4); _b.reserveSpace(4);
_b._start[_b._pos++] = 0xf0 + (v >> 18); _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 >> 6) & 0x3f);
_b._start[_b._pos++] = 0x80 + (v & 0x3f); _b._start[_b._pos++] = 0x80 + (v & 0x3f);
highSurrogate = 0; highSurrogate = 0;
} } else {
else {
if (v >= 0xd800 && v < 0xdc00) { if (v >= 0xd800 && v < 0xdc00) {
// High surrogate: // High surrogate:
highSurrogate = v; highSurrogate = v;
} } else {
else {
highSurrogate = 0; highSurrogate = 0;
} }
_b.reserveSpace(3); _b.reserveSpace(3);
@ -369,32 +346,26 @@ void Parser::parseString () {
highSurrogate = 0; highSurrogate = 0;
_b.reserveSpace(1); _b.reserveSpace(1);
_b._start[_b._pos++] = static_cast<uint8_t>(i); _b._start[_b._pos++] = static_cast<uint8_t>(i);
} } else {
else {
if (!options->validateUtf8Strings) { if (!options->validateUtf8Strings) {
highSurrogate = 0; highSurrogate = 0;
_b.reserveSpace(1); _b.reserveSpace(1);
_b._start[_b._pos++] = static_cast<uint8_t>(i); _b._start[_b._pos++] = static_cast<uint8_t>(i);
} } else {
else {
// multi-byte UTF-8 sequence! // multi-byte UTF-8 sequence!
int follow = 0; int follow = 0;
if ((i & 0xe0) == 0x80) { if ((i & 0xe0) == 0x80) {
throw Exception(Exception::InvalidUtf8Sequence); throw Exception(Exception::InvalidUtf8Sequence);
} } else if ((i & 0xe0) == 0xc0) {
else if ((i & 0xe0) == 0xc0) {
// two-byte sequence // two-byte sequence
follow = 1; follow = 1;
} } else if ((i & 0xf0) == 0xe0) {
else if ((i & 0xf0) == 0xe0) {
// three-byte sequence // three-byte sequence
follow = 2; follow = 2;
} } else if ((i & 0xf8) == 0xf0) {
else if ((i & 0xf8) == 0xf0) {
// four-byte sequence // four-byte sequence
follow = 3; follow = 3;
} } else {
else {
throw Exception(Exception::InvalidUtf8Sequence); throw Exception(Exception::InvalidUtf8Sequence);
} }
@ -483,10 +454,10 @@ void Parser::parseObject () {
auto const lastPos = _b._pos; auto const lastPos = _b._pos;
if (options->attributeExcludeHandler == nullptr) { if (options->attributeExcludeHandler == nullptr) {
parseString(); parseString();
} } else {
else {
parseString(); parseString();
if (options->attributeExcludeHandler->shouldExclude(Slice(_b._start + lastPos, options), _nesting)) { if (options->attributeExcludeHandler->shouldExclude(
Slice(_b._start + lastPos, options), _nesting)) {
excludeAttribute = true; excludeAttribute = true;
} }
} }
@ -498,11 +469,13 @@ void Parser::parseObject () {
if (key.isString()) { if (key.isString()) {
ValueLength keyLength; ValueLength keyLength;
char const* p = key.getString(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) { if (translated != nullptr) {
// found translation... now reset position to old key position // 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._pos = lastPos;
_b.addUInt(Slice(translated, options).getUInt()); _b.addUInt(Slice(translated, options).getUInt());
} }
@ -581,4 +554,3 @@ void Parser::parseJson () {
} }
} }
} }

View File

@ -39,71 +39,134 @@ using namespace arangodb::velocypack;
using VT = arangodb::velocypack::ValueType; using VT = arangodb::velocypack::ValueType;
VT const Slice::TypeMap[256] = { VT const Slice::TypeMap[256] = {
/* 0x00 */ VT::None, /* 0x01 */ VT::Array, /* 0x02 */ VT::Array, /* 0x03 */ VT::Array, /* 0x00 */ VT::None, /* 0x01 */ VT::Array,
/* 0x04 */ VT::Array, /* 0x05 */ VT::Array, /* 0x06 */ VT::Array, /* 0x07 */ VT::Array, /* 0x02 */ VT::Array, /* 0x03 */ VT::Array,
/* 0x08 */ VT::Array, /* 0x09 */ VT::Array, /* 0x0a */ VT::Object, /* 0x0b */ VT::Object, /* 0x04 */ VT::Array, /* 0x05 */ VT::Array,
/* 0x0c */ VT::Object, /* 0x0d */ VT::Object, /* 0x0e */ VT::Object, /* 0x0f */ VT::Object, /* 0x06 */ VT::Array, /* 0x07 */ VT::Array,
/* 0x10 */ VT::Object, /* 0x11 */ VT::Object, /* 0x12 */ VT::Object, /* 0x13 */ VT::Array, /* 0x08 */ VT::Array, /* 0x09 */ VT::Array,
/* 0x14 */ VT::Object, /* 0x15 */ VT::None, /* 0x16 */ VT::None, /* 0x17 */ VT::None, /* 0x0a */ VT::Object, /* 0x0b */ VT::Object,
/* 0x18 */ VT::Null, /* 0x19 */ VT::Bool, /* 0x1a */ VT::Bool, /* 0x1b */ VT::Double, /* 0x0c */ VT::Object, /* 0x0d */ VT::Object,
/* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External, /* 0x1e */ VT::MinKey, /* 0x1f */ VT::MaxKey, /* 0x0e */ VT::Object, /* 0x0f */ VT::Object,
/* 0x20 */ VT::Int, /* 0x21 */ VT::Int, /* 0x22 */ VT::Int, /* 0x23 */ VT::Int, /* 0x10 */ VT::Object, /* 0x11 */ VT::Object,
/* 0x24 */ VT::Int, /* 0x25 */ VT::Int, /* 0x26 */ VT::Int, /* 0x27 */ VT::Int, /* 0x12 */ VT::Object, /* 0x13 */ VT::Array,
/* 0x28 */ VT::UInt, /* 0x29 */ VT::UInt, /* 0x2a */ VT::UInt, /* 0x2b */ VT::UInt, /* 0x14 */ VT::Object, /* 0x15 */ VT::None,
/* 0x2c */ VT::UInt, /* 0x2d */ VT::UInt, /* 0x2e */ VT::UInt, /* 0x2f */ VT::UInt, /* 0x16 */ VT::None, /* 0x17 */ VT::None,
/* 0x30 */ VT::SmallInt, /* 0x31 */ VT::SmallInt, /* 0x32 */ VT::SmallInt, /* 0x33 */ VT::SmallInt, /* 0x18 */ VT::Null, /* 0x19 */ VT::Bool,
/* 0x34 */ VT::SmallInt, /* 0x35 */ VT::SmallInt, /* 0x36 */ VT::SmallInt, /* 0x37 */ VT::SmallInt, /* 0x1a */ VT::Bool, /* 0x1b */ VT::Double,
/* 0x38 */ VT::SmallInt, /* 0x39 */ VT::SmallInt, /* 0x3a */ VT::SmallInt, /* 0x3b */ VT::SmallInt, /* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External,
/* 0x3c */ VT::SmallInt, /* 0x3d */ VT::SmallInt, /* 0x3e */ VT::SmallInt, /* 0x3f */ VT::SmallInt, /* 0x1e */ VT::MinKey, /* 0x1f */ VT::MaxKey,
/* 0x40 */ VT::String, /* 0x41 */ VT::String, /* 0x42 */ VT::String, /* 0x43 */ VT::String, /* 0x20 */ VT::Int, /* 0x21 */ VT::Int,
/* 0x44 */ VT::String, /* 0x45 */ VT::String, /* 0x46 */ VT::String, /* 0x47 */ VT::String, /* 0x22 */ VT::Int, /* 0x23 */ VT::Int,
/* 0x48 */ VT::String, /* 0x49 */ VT::String, /* 0x4a */ VT::String, /* 0x4b */ VT::String, /* 0x24 */ VT::Int, /* 0x25 */ VT::Int,
/* 0x4c */ VT::String, /* 0x4d */ VT::String, /* 0x4e */ VT::String, /* 0x4f */ VT::String, /* 0x26 */ VT::Int, /* 0x27 */ VT::Int,
/* 0x50 */ VT::String, /* 0x51 */ VT::String, /* 0x52 */ VT::String, /* 0x53 */ VT::String, /* 0x28 */ VT::UInt, /* 0x29 */ VT::UInt,
/* 0x54 */ VT::String, /* 0x55 */ VT::String, /* 0x56 */ VT::String, /* 0x57 */ VT::String, /* 0x2a */ VT::UInt, /* 0x2b */ VT::UInt,
/* 0x58 */ VT::String, /* 0x59 */ VT::String, /* 0x5a */ VT::String, /* 0x5b */ VT::String, /* 0x2c */ VT::UInt, /* 0x2d */ VT::UInt,
/* 0x5c */ VT::String, /* 0x5d */ VT::String, /* 0x5e */ VT::String, /* 0x5f */ VT::String, /* 0x2e */ VT::UInt, /* 0x2f */ VT::UInt,
/* 0x60 */ VT::String, /* 0x61 */ VT::String, /* 0x62 */ VT::String, /* 0x63 */ VT::String, /* 0x30 */ VT::SmallInt, /* 0x31 */ VT::SmallInt,
/* 0x64 */ VT::String, /* 0x65 */ VT::String, /* 0x66 */ VT::String, /* 0x67 */ VT::String, /* 0x32 */ VT::SmallInt, /* 0x33 */ VT::SmallInt,
/* 0x68 */ VT::String, /* 0x69 */ VT::String, /* 0x6a */ VT::String, /* 0x6b */ VT::String, /* 0x34 */ VT::SmallInt, /* 0x35 */ VT::SmallInt,
/* 0x6c */ VT::String, /* 0x6d */ VT::String, /* 0x6e */ VT::String, /* 0x6f */ VT::String, /* 0x36 */ VT::SmallInt, /* 0x37 */ VT::SmallInt,
/* 0x70 */ VT::String, /* 0x71 */ VT::String, /* 0x72 */ VT::String, /* 0x73 */ VT::String, /* 0x38 */ VT::SmallInt, /* 0x39 */ VT::SmallInt,
/* 0x74 */ VT::String, /* 0x75 */ VT::String, /* 0x76 */ VT::String, /* 0x77 */ VT::String, /* 0x3a */ VT::SmallInt, /* 0x3b */ VT::SmallInt,
/* 0x78 */ VT::String, /* 0x79 */ VT::String, /* 0x7a */ VT::String, /* 0x7b */ VT::String, /* 0x3c */ VT::SmallInt, /* 0x3d */ VT::SmallInt,
/* 0x7c */ VT::String, /* 0x7d */ VT::String, /* 0x7e */ VT::String, /* 0x7f */ VT::String, /* 0x3e */ VT::SmallInt, /* 0x3f */ VT::SmallInt,
/* 0x80 */ VT::String, /* 0x81 */ VT::String, /* 0x82 */ VT::String, /* 0x83 */ VT::String, /* 0x40 */ VT::String, /* 0x41 */ VT::String,
/* 0x84 */ VT::String, /* 0x85 */ VT::String, /* 0x86 */ VT::String, /* 0x87 */ VT::String, /* 0x42 */ VT::String, /* 0x43 */ VT::String,
/* 0x88 */ VT::String, /* 0x89 */ VT::String, /* 0x8a */ VT::String, /* 0x8b */ VT::String, /* 0x44 */ VT::String, /* 0x45 */ VT::String,
/* 0x8c */ VT::String, /* 0x8d */ VT::String, /* 0x8e */ VT::String, /* 0x8f */ VT::String, /* 0x46 */ VT::String, /* 0x47 */ VT::String,
/* 0x90 */ VT::String, /* 0x91 */ VT::String, /* 0x92 */ VT::String, /* 0x93 */ VT::String, /* 0x48 */ VT::String, /* 0x49 */ VT::String,
/* 0x94 */ VT::String, /* 0x95 */ VT::String, /* 0x96 */ VT::String, /* 0x97 */ VT::String, /* 0x4a */ VT::String, /* 0x4b */ VT::String,
/* 0x98 */ VT::String, /* 0x99 */ VT::String, /* 0x9a */ VT::String, /* 0x9b */ VT::String, /* 0x4c */ VT::String, /* 0x4d */ VT::String,
/* 0x9c */ VT::String, /* 0x9d */ VT::String, /* 0x9e */ VT::String, /* 0x9f */ VT::String, /* 0x4e */ VT::String, /* 0x4f */ VT::String,
/* 0xa0 */ VT::String, /* 0xa1 */ VT::String, /* 0xa2 */ VT::String, /* 0xa3 */ VT::String, /* 0x50 */ VT::String, /* 0x51 */ VT::String,
/* 0xa4 */ VT::String, /* 0xa5 */ VT::String, /* 0xa6 */ VT::String, /* 0xa7 */ VT::String, /* 0x52 */ VT::String, /* 0x53 */ VT::String,
/* 0xa8 */ VT::String, /* 0xa9 */ VT::String, /* 0xaa */ VT::String, /* 0xab */ VT::String, /* 0x54 */ VT::String, /* 0x55 */ VT::String,
/* 0xac */ VT::String, /* 0xad */ VT::String, /* 0xae */ VT::String, /* 0xaf */ VT::String, /* 0x56 */ VT::String, /* 0x57 */ VT::String,
/* 0xb0 */ VT::String, /* 0xb1 */ VT::String, /* 0xb2 */ VT::String, /* 0xb3 */ VT::String, /* 0x58 */ VT::String, /* 0x59 */ VT::String,
/* 0xb4 */ VT::String, /* 0xb5 */ VT::String, /* 0xb6 */ VT::String, /* 0xb7 */ VT::String, /* 0x5a */ VT::String, /* 0x5b */ VT::String,
/* 0xb8 */ VT::String, /* 0xb9 */ VT::String, /* 0xba */ VT::String, /* 0xbb */ VT::String, /* 0x5c */ VT::String, /* 0x5d */ VT::String,
/* 0xbc */ VT::String, /* 0xbd */ VT::String, /* 0xbe */ VT::String, /* 0xbf */ VT::String, /* 0x5e */ VT::String, /* 0x5f */ VT::String,
/* 0xc0 */ VT::Binary, /* 0xc1 */ VT::Binary, /* 0xc2 */ VT::Binary, /* 0xc3 */ VT::Binary, /* 0x60 */ VT::String, /* 0x61 */ VT::String,
/* 0xc4 */ VT::Binary, /* 0xc5 */ VT::Binary, /* 0xc6 */ VT::Binary, /* 0xc7 */ VT::Binary, /* 0x62 */ VT::String, /* 0x63 */ VT::String,
/* 0xc8 */ VT::BCD, /* 0xc9 */ VT::BCD, /* 0xca */ VT::BCD, /* 0xcb */ VT::BCD, /* 0x64 */ VT::String, /* 0x65 */ VT::String,
/* 0xcc */ VT::BCD, /* 0xcd */ VT::BCD, /* 0xce */ VT::BCD, /* 0xcf */ VT::BCD, /* 0x66 */ VT::String, /* 0x67 */ VT::String,
/* 0xd0 */ VT::BCD, /* 0xd1 */ VT::BCD, /* 0xd2 */ VT::BCD, /* 0xd3 */ VT::BCD, /* 0x68 */ VT::String, /* 0x69 */ VT::String,
/* 0xd4 */ VT::BCD, /* 0xd5 */ VT::BCD, /* 0xd6 */ VT::BCD, /* 0xd7 */ VT::BCD, /* 0x6a */ VT::String, /* 0x6b */ VT::String,
/* 0xd8 */ VT::None, /* 0xd9 */ VT::None, /* 0xda */ VT::None, /* 0xdb */ VT::None, /* 0x6c */ VT::String, /* 0x6d */ VT::String,
/* 0xdc */ VT::None, /* 0xdd */ VT::None, /* 0xde */ VT::None, /* 0xdf */ VT::None, /* 0x6e */ VT::String, /* 0x6f */ VT::String,
/* 0xe0 */ VT::None, /* 0xe1 */ VT::None, /* 0xe2 */ VT::None, /* 0xe3 */ VT::None, /* 0x70 */ VT::String, /* 0x71 */ VT::String,
/* 0xe4 */ VT::None, /* 0xe5 */ VT::None, /* 0xe6 */ VT::None, /* 0xe7 */ VT::None, /* 0x72 */ VT::String, /* 0x73 */ VT::String,
/* 0xe8 */ VT::None, /* 0xe9 */ VT::None, /* 0xea */ VT::None, /* 0xeb */ VT::None, /* 0x74 */ VT::String, /* 0x75 */ VT::String,
/* 0xec */ VT::None, /* 0xed */ VT::None, /* 0xee */ VT::None, /* 0xef */ VT::None, /* 0x76 */ VT::String, /* 0x77 */ VT::String,
/* 0xf0 */ VT::Custom, /* 0xf1 */ VT::Custom, /* 0xf2 */ VT::Custom, /* 0xf3 */ VT::Custom, /* 0x78 */ VT::String, /* 0x79 */ VT::String,
/* 0xf4 */ VT::Custom, /* 0xf5 */ VT::Custom, /* 0xf6 */ VT::Custom, /* 0xf7 */ VT::Custom, /* 0x7a */ VT::String, /* 0x7b */ VT::String,
/* 0xf8 */ VT::Custom, /* 0xf9 */ VT::Custom, /* 0xfa */ VT::Custom, /* 0xfb */ VT::Custom, /* 0x7c */ VT::String, /* 0x7d */ VT::String,
/* 0xfc */ VT::Custom, /* 0xfd */ VT::Custom, /* 0xfe */ VT::Custom, /* 0xff */ VT::Custom /* 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] = { unsigned int const Slice::WidthMap[32] = {
0, // 0x00, None 0, // 0x00, None
@ -125,8 +188,7 @@ unsigned int const Slice::WidthMap[32] = {
2, // 0x10, object with unsorted index table 2, // 0x10, object with unsorted index table
4, // 0x11, object with unsorted index table 4, // 0x11, object with unsorted index table
8, // 0x12, object with unsorted index table 8, // 0x12, object with unsorted index table
0 0};
};
unsigned int const Slice::FirstSubMap[32] = { unsigned int const Slice::FirstSubMap[32] = {
0, // 0x00, None 0, // 0x00, None
@ -148,8 +210,7 @@ unsigned int const Slice::FirstSubMap[32] = {
5, // 0x10, object with unsorted index table 5, // 0x10, object with unsorted index table
8, // 0x11, object with unsorted index table 8, // 0x11, object with unsorted index table
8, // 0x12, object with unsorted index table 8, // 0x12, object with unsorted index table
0 0};
};
// translates an integer key into a string // translates an integer key into a string
Slice Slice::translate() const { Slice Slice::translate() const {
@ -182,9 +243,7 @@ std::string Slice::toString () const {
return std::move(buffer); return std::move(buffer);
} }
std::string Slice::hexType () const { std::string Slice::hexType() const { return std::move(HexDump::toHex(head())); }
return std::move(HexDump::toHex(head()));
}
// look for the specified attribute inside an Object // look for the specified attribute inside an Object
// returns a Slice(ValueType::None) if not found // returns a Slice(ValueType::None) if not found
@ -210,15 +269,9 @@ Slice Slice::get (std::string const& attribute) const {
// read number of items // read number of items
ValueLength n; ValueLength n;
if (h <= 0x05) { // No offset table or length, need to compute: if (offsetSize < 8) {
dataOffset = findDataOffset(h);
Slice first(_start + dataOffset, options);
n = (end - dataOffset) / first.byteSize();
}
else if (offsetSize < 8) {
n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize); n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
} } else {
else {
n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize); n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize);
} }
@ -234,14 +287,12 @@ Slice Slice::get (std::string const& attribute) const {
if (!key.isEqualString(attribute)) { if (!key.isEqualString(attribute)) {
return Slice(); return Slice();
} }
} } else if (key.isInteger()) {
else if (key.isInteger()) {
// translate key // translate key
if (!key.translate().isEqualString(attribute)) { if (!key.translate().isEqualString(attribute)) {
return Slice(); return Slice();
} }
} } else {
else {
// invalid key // invalid key
return Slice(); return Slice();
} }
@ -249,8 +300,8 @@ Slice Slice::get (std::string const& attribute) const {
return Slice(key.start() + key.byteSize(), options); return Slice(key.start() + key.byteSize(), options);
} }
ValueLength const ieBase = end - n * offsetSize ValueLength const ieBase =
- (offsetSize == 8 ? offsetSize : 0); end - n * offsetSize - (offsetSize == 8 ? offsetSize : 0);
// only use binary search for attributes if we have at least this many entries // only use binary search for attributes if we have at least this many entries
// otherwise we'll always use the linear search // 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); uint64_t v = readInteger<uint64_t>(_start + 1, h - 0x1f);
if (h == 0x27) { if (h == 0x27) {
return toInt64(v); return toInt64(v);
} } else {
else {
int64_t vv = static_cast<int64_t>(v); int64_t vv = static_cast<int64_t>(v);
int64_t shift = 1LL << ((h - 0x1f) * 8 - 1); int64_t shift = 1LL << ((h - 0x1f) * 8 - 1);
return vv < shift ? vv : vv - (shift << 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; return static_cast<int64_t>(h - 0x3a) - 6;
} }
if ((h >= 0x20 && h <= 0x27) || if ((h >= 0x20 && h <= 0x27) || (h >= 0x28 && h <= 0x2f)) {
(h >= 0x28 && h <= 0x2f)) {
// Int and UInt // 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(); return getInt();
} }
@ -356,7 +406,8 @@ int Slice::compareString (std::string const& attribute) const {
ValueLength keyLength; ValueLength keyLength;
char const* k = getString(keyLength); char const* k = getString(keyLength);
size_t const attributeLength = attribute.size(); 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); int res = memcmp(k, attribute.c_str(), compareLength);
if (res == 0) { if (res == 0) {
@ -384,8 +435,7 @@ Slice Slice::getFromCompactObject (std::string const& attribute) const {
if (key.isEqualString(attribute)) { if (key.isEqualString(attribute)) {
return Slice(key.start() + key.byteSize(), options); return Slice(key.start() + key.byteSize(), options);
} }
} } else if (key.isInteger()) {
else if (key.isInteger()) {
if (key.translate().isEqualString(attribute)) { if (key.translate().isEqualString(attribute)) {
return Slice(key.start() + key.byteSize(), options); 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: if (h <= 0x05) { // No offset table or length, need to compute:
Slice first(_start + dataOffset, options); Slice first(_start + dataOffset, options);
n = (end - dataOffset) / first.byteSize(); n = (end - dataOffset) / first.byteSize();
} } else if (offsetSize < 8) {
else if (offsetSize < 8) {
n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize); n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
} } else {
else {
n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize); n = readInteger<ValueLength>(_start + end - offsetSize, offsetSize);
} }
@ -447,8 +495,8 @@ ValueLength Slice::getNthOffset (ValueLength index) const {
return dataOffset + index * firstItem.byteSize(); return dataOffset + index * firstItem.byteSize();
} }
ValueLength const ieBase = end - n * offsetSize + index * offsetSize ValueLength const ieBase =
- (offsetSize == 8 ? 8 : 0); end - n * offsetSize + index * offsetSize - (offsetSize == 8 ? 8 : 0);
return readInteger<ValueLength>(_start + ieBase, offsetSize); 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 // perform a linear search for the specified attribute inside an Object
Slice Slice::searchObjectKeyLinear(std::string const& attribute, Slice Slice::searchObjectKeyLinear(std::string const& attribute,
ValueLength ieBase, ValueLength ieBase, ValueLength offsetSize,
ValueLength offsetSize,
ValueLength n) const { ValueLength n) const {
for (ValueLength index = 0; index < n; ++index) { for (ValueLength index = 0; index < n; ++index) {
ValueLength offset = ieBase + index * offsetSize; 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.isString()) {
if (!key.isEqualString(attribute)) { if (!key.isEqualString(attribute)) {
continue; continue;
} }
} } else if (key.isInteger()) {
else if (key.isInteger()) {
// translate key // translate key
if (!key.translate().isEqualString(attribute)) { if (!key.translate().isEqualString(attribute)) {
continue; continue;
} }
} } else {
else {
// invalid key type // invalid key type
return Slice(); return Slice();
} }
@ -554,8 +600,7 @@ Slice Slice::searchObjectKeyLinear (std::string const& attribute,
// perform a binary search for the specified attribute inside an Object // perform a binary search for the specified attribute inside an Object
Slice Slice::searchObjectKeyBinary(std::string const& attribute, Slice Slice::searchObjectKeyBinary(std::string const& attribute,
ValueLength ieBase, ValueLength ieBase, ValueLength offsetSize,
ValueLength offsetSize,
ValueLength n) const { ValueLength n) const {
VELOCYPACK_ASSERT(n > 0); VELOCYPACK_ASSERT(n > 0);
@ -567,17 +612,16 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
ValueLength index = l + ((r - l) / 2); ValueLength index = l + ((r - l) / 2);
ValueLength offset = ieBase + index * offsetSize; 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; int res;
if (key.isString()) { if (key.isString()) {
res = key.compareString(attribute); res = key.compareString(attribute);
} } else if (key.isInteger()) {
else if (key.isInteger()) {
// translate key // translate key
res = key.translate().compareString(attribute); res = key.translate().compareString(attribute);
} } else {
else {
// invalid key // invalid key
return Slice(); return Slice();
} }
@ -592,8 +636,7 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
return Slice(); return Slice();
} }
r = index - 1; r = index - 1;
} } else {
else {
l = index + 1; l = index + 1;
} }
if (r < l) { if (r < l) {
@ -603,7 +646,8 @@ Slice Slice::searchObjectKeyBinary (std::string const& attribute,
} }
std::ostream& operator<<(std::ostream& stream, Slice const* slice) { 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; return stream;
} }
@ -611,5 +655,6 @@ std::ostream& operator<< (std::ostream& stream, Slice const& slice) {
return operator<<(stream, &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"); "Slice has an unexpected size");

View File

@ -32,23 +32,40 @@ using namespace arangodb::velocypack;
char const* arangodb::velocypack::valueTypeName(ValueType type) { char const* arangodb::velocypack::valueTypeName(ValueType type) {
switch (type) { switch (type) {
case ValueType::None: return "none"; case ValueType::None:
case ValueType::Null: return "null"; return "none";
case ValueType::Bool: return "bool"; case ValueType::Null:
case ValueType::Array: return "array"; return "null";
case ValueType::Object: return "object"; case ValueType::Bool:
case ValueType::Double: return "double"; return "bool";
case ValueType::UTCDate: return "utc-date"; case ValueType::Array:
case ValueType::External: return "external"; return "array";
case ValueType::MinKey: return "min-key"; case ValueType::Object:
case ValueType::MaxKey: return "max-key"; return "object";
case ValueType::Int: return "int"; case ValueType::Double:
case ValueType::UInt: return "uint"; return "double";
case ValueType::SmallInt: return "smallint"; case ValueType::UTCDate:
case ValueType::String: return "string"; return "utc-date";
case ValueType::Binary: return "binary"; case ValueType::External:
case ValueType::BCD: return "bcd"; return "external";
case ValueType::Custom: return "custom"; 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"; return "unknown";

View File

@ -55,4 +55,3 @@ int Version::compare (Version const& other) const {
int Version::compare(Version const& lhs, Version const& rhs) { int Version::compare(Version const& lhs, Version const& rhs) {
return lhs.compare(rhs); return lhs.compare(rhs);
} }

View File

@ -53,19 +53,18 @@ static bool HasSSE42 () {
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
if ((ecx & 0x100000) != 0) { if ((ecx & 0x100000) != 0) {
return true; return true;
} } else {
else {
return false; return false;
} }
} } else {
else {
return false; return false;
} }
} }
static size_t JSONStringCopySSE42 (uint8_t* dst, uint8_t const* src, size_t limit) { static size_t JSONStringCopySSE42(uint8_t* dst, uint8_t const* src,
alignas(16) static char const ranges[17] size_t limit) {
= "\x20\x21\x23\x5b\x5d\xff "; alignas(16) static char const ranges[17] =
"\x20\x21\x23\x5b\x5d\xff ";
//= "\x01\x1f\"\"\\\\\"\"\"\"\"\"\"\"\"\""; //= "\x01\x1f\"\"\\\\\"\"\"\"\"\"\"\"\"\"";
__m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges)); __m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges));
size_t count = 0; 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
x = _mm_cmpistri(r, /* 6, */ s, /* 16, */ x = _mm_cmpistri(r, /* 6, */ s, /* 16, */
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (x < 16) { if (x < 16) {
memcpy(dst, src, x); memcpy(dst, src, x);
dst += 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
x = _mm_cmpistri(r, /* 6, */ s, /* limit, */ x = _mm_cmpistri(r, /* 6, */ s, /* limit, */
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (x > static_cast<int>(limit)) { if (x > static_cast<int>(limit)) {
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) { static size_t DoInitCopy(uint8_t* dst, uint8_t const* src, size_t limit) {
if (HasSSE42()) { if (HasSSE42()) {
JSONStringCopy = JSONStringCopySSE42; JSONStringCopy = JSONStringCopySSE42;
} } else {
else {
JSONStringCopy = JSONStringCopyC; JSONStringCopy = JSONStringCopyC;
} }
return (*JSONStringCopy)(dst, src, limit); return (*JSONStringCopy)(dst, src, limit);
} }
static size_t JSONStringCopyCheckUtf8SSE42 (uint8_t* dst, static size_t JSONStringCopyCheckUtf8SSE42(uint8_t* dst, uint8_t const* src,
uint8_t const* src,
size_t limit) { size_t limit) {
alignas(16) static unsigned char const ranges[17] alignas(16) static unsigned char const ranges[17] =
= "\x20\x21\x23\x5b\x5d\x7f "; "\x20\x21\x23\x5b\x5d\x7f ";
//= "\x01\x1f\x80\xff\"\"\\\\\"\"\"\"\"\"\"\""; //= "\x01\x1f\x80\xff\"\"\\\\\"\"\"\"\"\"\"\"";
__m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges)); __m128i const r = _mm_load_si128(reinterpret_cast<__m128i const*>(ranges));
size_t count = 0; 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
x = _mm_cmpistri(r, /* 8, */ s, /* 16, */ x = _mm_cmpistri(r, /* 8, */ s, /* 16, */
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (x < 16) { if (x < 16) {
memcpy(dst, src, x); memcpy(dst, src, x);
dst += 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(src));
x = _mm_cmpistri(r, /* 8, */ s, /* limit, */ x = _mm_cmpistri(r, /* 8, */ s, /* limit, */
_SIDD_UBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS | _SIDD_CMP_RANGES |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (x > static_cast<int>(limit)) { if (x > static_cast<int>(limit)) {
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) { size_t limit) {
if (HasSSE42()) { if (HasSSE42()) {
JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8SSE42; JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8SSE42;
} } else {
else {
JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8C; JSONStringCopyCheckUtf8 = JSONStringCopyCheckUtf8C;
} }
return (*JSONStringCopyCheckUtf8)(dst, src, limit); 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(ptr));
x = _mm_cmpistri(w, /* 4, */ s, /* 16, */ x = _mm_cmpistri(w, /* 4, */ s, /* 16, */
_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (x < 16) { if (x < 16) {
ptr += x; ptr += x;
count += 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)); __m128i const s = _mm_loadu_si128(reinterpret_cast<__m128i const*>(ptr));
x = _mm_cmpistri(w, /* 4, */ s, /* limit, */ x = _mm_cmpistri(w, /* 4, */ s, /* limit, */
_SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY |
_SIDD_NEGATIVE_POLARITY | _SIDD_NEGATIVE_POLARITY | _SIDD_LEAST_SIGNIFICANT);
_SIDD_LEAST_SIGNIFICANT);
if (static_cast<size_t>(x) > limit) { if (static_cast<size_t>(x) > limit) {
x = static_cast<int>(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) { static size_t DoInitSkip(uint8_t const* ptr, size_t limit) {
if (HasSSE42()) { if (HasSSE42()) {
JSONSkipWhiteSpace = JSONSkipWhiteSpaceSSE42; JSONSkipWhiteSpace = JSONSkipWhiteSpaceSSE42;
} } else {
else {
JSONSkipWhiteSpace = JSONSkipWhiteSpaceC; JSONSkipWhiteSpace = JSONSkipWhiteSpaceC;
} }
return (*JSONSkipWhiteSpace)(ptr, limit); return (*JSONSkipWhiteSpace)(ptr, limit);
@ -240,19 +229,18 @@ static size_t DoInitSkip (uint8_t const* ptr, size_t limit) {
#endif #endif
size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, size_t) = DoInitCopy; size_t (*JSONStringCopy)(uint8_t*, uint8_t const*, size_t) = DoInitCopy;
size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t) size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*,
= DoInitCopyCheckUtf8; size_t) = DoInitCopyCheckUtf8;
size_t (*JSONSkipWhiteSpace)(uint8_t const*, size_t) = DoInitSkip; size_t (*JSONSkipWhiteSpace)(uint8_t const*, size_t) = DoInitSkip;
#if defined(COMPILE_VELOCYPACK_ASM_UNITTESTS) #if defined(COMPILE_VELOCYPACK_ASM_UNITTESTS)
int testPositions[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, int testPositions[] = {
16, 23, 31, 32, 67, 103, 178, 210, 234, 247, 254, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, 14, 15, 16, 23, 31, 32, 67, 103, 178, 210, 234, 247, 254, 255,
-13, -14, -15, -16, -23, -31, -32, -67, -103, -178, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14,
-210, -234, -247, -254, -255 }; -15, -16, -23, -31, -32, -67, -103, -178, -210, -234, -247, -254, -255};
void TestStringCopyCorrectness(uint8_t* src, uint8_t* dst, size_t size) { void TestStringCopyCorrectness(uint8_t* src, uint8_t* dst, size_t size) {
size_t copied; size_t copied;
@ -272,8 +260,7 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
size_t pos; size_t pos;
if (off >= 0) { if (off >= 0) {
pos = off; pos = off;
} } else {
else {
pos = size - static_cast<size_t>(-off); pos = size - static_cast<size_t>(-off);
} }
if (pos >= size) { if (pos >= size) {
@ -281,11 +268,12 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
} }
// Test a quote character: // Test a quote character:
merk = src[pos]; src[pos] = '"'; merk = src[pos];
src[pos] = '"';
copied = JSONStringCopy(dst, src, size); copied = JSONStringCopy(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -293,8 +281,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
src[pos] = '\\'; src[pos] = '\\';
copied = JSONStringCopy(dst, src, size); copied = JSONStringCopy(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -302,8 +290,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
src[pos] = 1; src[pos] = 1;
copied = JSONStringCopy(dst, src, size); copied = JSONStringCopy(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -311,8 +299,8 @@ void TestStringCopyCorrectness (uint8_t* src, uint8_t* dst, size_t size) {
src[pos] = 31; src[pos] = 31;
copied = JSONStringCopy(dst, src, size); copied = JSONStringCopy(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; 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(); auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> totalTime std::chrono::duration<double> totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Tests took altogether " << totalTime.count() << " seconds." std::cout << "Tests took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
} }
@ -340,15 +328,14 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
src += salign; src += salign;
for (int dalign = 0; dalign < 16; dalign++) { for (int dalign = 0; dalign < 16; dalign++) {
dst += dalign; dst += dalign;
for (int i = 0; for (int i = 0; i < static_cast<int>(sizeof(testPositions) / sizeof(int));
i < static_cast<int>(sizeof(testPositions) / sizeof(int)); i++) { i++) {
uint8_t merk; uint8_t merk;
int off = testPositions[i]; int off = testPositions[i];
size_t pos; size_t pos;
if (off >= 0) { if (off >= 0) {
pos = off; pos = off;
} } else {
else {
pos = size - static_cast<size_t>(-off); pos = size - static_cast<size_t>(-off);
} }
if (pos >= size) { if (pos >= size) {
@ -356,11 +343,12 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
} }
// Test a quote character: // Test a quote character:
merk = src[pos]; src[pos] = '"'; merk = src[pos];
src[pos] = '"';
copied = JSONStringCopyCheckUtf8(dst, src, size); copied = JSONStringCopyCheckUtf8(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -368,8 +356,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
src[pos] = '\\'; src[pos] = '\\';
copied = JSONStringCopyCheckUtf8(dst, src, size); copied = JSONStringCopyCheckUtf8(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -377,8 +365,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
src[pos] = 1; src[pos] = 1;
copied = JSONStringCopyCheckUtf8(dst, src, size); copied = JSONStringCopyCheckUtf8(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -386,8 +374,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
src[pos] = 31; src[pos] = 31;
copied = JSONStringCopyCheckUtf8(dst, src, size); copied = JSONStringCopyCheckUtf8(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
@ -395,8 +383,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
src[pos] = 0x80; src[pos] = 0x80;
copied = JSONStringCopyCheckUtf8(dst, src, size); copied = JSONStringCopyCheckUtf8(dst, src, size);
if (copied != pos || memcmp(dst, src, copied) != 0) { if (copied != pos || memcmp(dst, src, copied) != 0) {
std::cout << "Error: " << salign << " " << dalign << " " std::cout << "Error: " << salign << " " << dalign << " " << i << " "
<< i << " " << pos << " " << copied << std::endl; << pos << " " << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
} }
@ -406,8 +394,8 @@ void TestStringCopyCorrectnessCheckUtf8 (uint8_t* src, uint8_t* dst,
} }
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> totalTime std::chrono::duration<double> totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Tests took altogether " << totalTime.count() << " seconds." std::cout << "Tests took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
} }
@ -422,15 +410,14 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
for (int salign = 0; salign < 16; salign++) { for (int salign = 0; salign < 16; salign++) {
src += salign; src += salign;
for (int i = 0; for (int i = 0; i < static_cast<int>(sizeof(testPositions) / sizeof(int));
i < static_cast<int>(sizeof(testPositions) / sizeof(int)); i++) { i++) {
uint8_t merk; uint8_t merk;
int off = testPositions[i]; int off = testPositions[i];
size_t pos; size_t pos;
if (off >= 0) { if (off >= 0) {
pos = off; pos = off;
} } else {
else {
pos = size - static_cast<size_t>(-off); pos = size - static_cast<size_t>(-off);
} }
if (pos >= size) { if (pos >= size) {
@ -438,11 +425,12 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
} }
// Test a non-whitespace character: // Test a non-whitespace character:
merk = src[pos]; src[pos] = 'x'; merk = src[pos];
src[pos] = 'x';
copied = JSONSkipWhiteSpace(src, size); copied = JSONSkipWhiteSpace(src, size);
if (copied != pos) { if (copied != pos) {
std::cout << "Error: " << salign << " " std::cout << "Error: " << salign << " " << i << " " << pos << " "
<< i << " " << pos << " " << copied << std::endl; << copied << std::endl;
} }
src[pos] = merk; src[pos] = merk;
} }
@ -450,13 +438,14 @@ void TestSkipWhiteSpaceCorrectness (uint8_t* src, size_t size) {
} }
auto now = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> totalTime std::chrono::duration<double> totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now-start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Whitespace tests took altogether " << totalTime.count() std::cout << "Whitespace tests took altogether " << totalTime.count()
<< " seconds." << std::endl; << " 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; size_t copied;
std::cout << "\nNow racing for the repeated full string, " 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(); auto now = std::chrono::high_resolution_clock::now();
src[size] = 'a' + (size % 26); src[size] = 'a' + (size % 26);
auto totalTime auto totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << 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 << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes copied per second: " std::cout << "Bytes copied per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
std::cout << "\nNow racing for the repeated full string, " std::cout << "\nNow racing for the repeated full string, "
<< "now unaligned target...\n" << std::endl; << "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(); now = std::chrono::high_resolution_clock::now();
dst--; dst--;
totalTime totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << 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 << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes copied per second: " std::cout << "Bytes copied per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
} }
void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src, void RaceStringCopyCheckUtf8(uint8_t* dst, uint8_t* src, size_t size,
size_t size, int repeat, int& akku) { int repeat, int& akku) {
size_t copied; size_t copied;
std::cout << "\nNow racing for the repeated (check UTF8) full string, " 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(); auto now = std::chrono::high_resolution_clock::now();
src[size] = 'a' + (size % 26); src[size] = 'a' + (size % 26);
auto totalTime auto totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
@ -533,10 +520,11 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
<< " on average is: " << totalTime.count() / repeat << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes copied per second: " std::cout << "Bytes copied per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< 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++; dst++;
start = std::chrono::high_resolution_clock::now(); 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(); now = std::chrono::high_resolution_clock::now();
dst--; dst--;
totalTime totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
@ -556,8 +544,7 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
<< " on average is: " << totalTime.count() / repeat << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes copied per second: " std::cout << "Bytes copied per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
std::cout << "\nNow comparing with strcpy...\n" << 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++) { for (int j = 0; j < repeat; j++) {
// strcpy((char*) dst, (char*) src); // strcpy((char*) dst, (char*) src);
memcpy((char*)dst, (char*)src, size); memcpy((char*)dst, (char*)src, size);
} }
now = std::chrono::high_resolution_clock::now(); now = std::chrono::high_resolution_clock::now();
totalTime totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
@ -578,8 +564,7 @@ void RaceStringCopyCheckUtf8 (uint8_t* dst, uint8_t* src,
<< " on average is: " << totalTime.count() / repeat << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes copied per second: " std::cout << "Bytes copied per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
} }
void RaceSkipWhiteSpace(uint8_t* src, size_t size, int repeat, int& akku) { 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 now = std::chrono::high_resolution_clock::now();
auto totalTime auto totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now-start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
@ -605,8 +590,7 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
<< " on average is: " << totalTime.count() / repeat << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes skipped per second: " std::cout << "Bytes skipped per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
std::cout << "\nNow comparing with strlen...\n" << 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(); now = std::chrono::high_resolution_clock::now();
totalTime totalTime =
= std::chrono::duration_cast<std::chrono::duration<double>>(now - start); std::chrono::duration_cast<std::chrono::duration<double>>(now - start);
std::cout << "Race took altogether " << totalTime.count() << " seconds." std::cout << "Race took altogether " << totalTime.count() << " seconds."
<< std::endl; << std::endl;
@ -628,13 +612,13 @@ void RaceSkipWhiteSpace (uint8_t* src, size_t size, int repeat, int& akku) {
<< " on average is: " << totalTime.count() / repeat << "." << " on average is: " << totalTime.count() / repeat << "."
<< std::endl; << std::endl;
std::cout << "Bytes scanned per second: " std::cout << "Bytes scanned per second: "
<< (double) size * (double) repeat / totalTime.count() << (double)size * (double)repeat / totalTime.count() << std::endl;
<< std::endl;
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc < 4) { 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; return 0;
} }

View File

@ -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 // Report the number of bytes copied. May copy less bytes, for example
// for alignment reasons. // for alignment reasons.
size_t count = limit; size_t count = limit;
while (count > 0 && while (count > 0 && *src >= 32 && *src != '\\' && *src != '"') {
*src >= 32 &&
*src != '\\' &&
*src != '"') {
*dst++ = *src++; *dst++ = *src++;
count--; 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 // Report the number of bytes copied. May copy less bytes, for example
// for alignment reasons. // for alignment reasons.
size_t count = limit; size_t count = limit;
while (count > 0 && while (count > 0 && *src >= 32 && *src != '\\' && *src != '"' &&
*src >= 32 &&
*src != '\\' &&
*src != '"' &&
*src < 0x80) { *src < 0x80) {
*dst++ = *src++; *dst++ = *src++;
count--; count--;
@ -72,8 +66,7 @@ static inline size_t JSONStringCopyCheckUtf8Inline (uint8_t* dst,
return limit - count; return limit - count;
} }
size_t JSONStringCopyCheckUtf8C (uint8_t* dst, uint8_t const* src, size_t JSONStringCopyCheckUtf8C(uint8_t* dst, uint8_t const* src, size_t limit);
size_t limit);
extern size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t); extern size_t (*JSONStringCopyCheckUtf8)(uint8_t*, uint8_t const*, size_t);
// White space skipping: // 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. // Advance ptr and return the number of skipped bytes.
size_t count = limit; size_t count = limit;
while (count > 0 && while (count > 0 &&
(*ptr == ' ' || (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')) {
*ptr == '\t' ||
*ptr == '\n' ||
*ptr == '\r')) {
ptr++; ptr++;
count--; count--;
} }

View File

@ -39,8 +39,7 @@ namespace arangodb {
return h; 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 m = 0x880355f21e6d1965ULL;
const uint64_t *pos = (const uint64_t *)buf; const uint64_t *pos = (const uint64_t *)buf;
const uint64_t *end = pos + (len / 8); const uint64_t *end = pos + (len / 8);
@ -58,13 +57,20 @@ namespace arangodb {
v = 0; v = 0;
switch (len & 7) { switch (len & 7) {
case 7: v ^= (uint64_t)pos2[6] << 48; case 7:
case 6: v ^= (uint64_t)pos2[5] << 40; v ^= (uint64_t)pos2[6] << 48;
case 5: v ^= (uint64_t)pos2[4] << 32; case 6:
case 4: v ^= (uint64_t)pos2[3] << 24; v ^= (uint64_t)pos2[5] << 40;
case 3: v ^= (uint64_t)pos2[2] << 16; case 5:
case 2: v ^= (uint64_t)pos2[1] << 8; v ^= (uint64_t)pos2[4] << 32;
case 1: v ^= (uint64_t)pos2[0]; 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 ^= mix(v);
h *= m; h *= m;
} }
@ -74,4 +80,3 @@ namespace arangodb {
} // namespace arangodb::velocypack } // namespace arangodb::velocypack
} // namespace arangodb } // namespace arangodb

View File

@ -52,11 +52,9 @@ static uint64_t tens[] = {
10000000000U, 1000000000U, 100000000U, 10000000000U, 1000000000U, 100000000U,
10000000U, 1000000U, 100000U, 10000000U, 1000000U, 100000U,
10000U, 1000U, 100U, 10000U, 1000U, 100U,
10U, 1U 10U, 1U};
};
static inline uint64_t get_dbits(double d) static inline uint64_t get_dbits(double d) {
{
union { union {
double dbl; double dbl;
uint64_t i; uint64_t i;
@ -65,8 +63,7 @@ static inline uint64_t get_dbits(double d)
return dbl_bits.i; return dbl_bits.i;
} }
static Fp build_fp(double d) static Fp build_fp(double d) {
{
uint64_t bits = get_dbits(d); uint64_t bits = get_dbits(d);
Fp fp; Fp fp;
@ -84,8 +81,7 @@ static Fp build_fp(double d)
return fp; return fp;
} }
static void normalize(Fp* fp) static void normalize(Fp* fp) {
{
while ((fp->frac & hiddenbit) == 0) { while ((fp->frac & hiddenbit) == 0) {
fp->frac <<= 1; fp->frac <<= 1;
fp->exp--; fp->exp--;
@ -96,8 +92,7 @@ static void normalize(Fp* fp)
fp->exp -= shift; 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->frac = (fp->frac << 1) + 1;
upper->exp = fp->exp - 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->frac <<= u_shift;
upper->exp = upper->exp - u_shift; upper->exp = upper->exp - u_shift;
int l_shift = fp->frac == hiddenbit ? 2 : 1; int l_shift = fp->frac == hiddenbit ? 2 : 1;
lower->frac = (fp->frac << l_shift) - 1; lower->frac = (fp->frac << l_shift) - 1;
lower->exp = fp->exp - l_shift; lower->exp = fp->exp - l_shift;
lower->frac <<= lower->exp - upper->exp; lower->frac <<= lower->exp - upper->exp;
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; const uint64_t lomask = 0x00000000FFFFFFFF;
uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask); uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
@ -135,26 +127,22 @@ static Fp multiply(Fp* a, Fp* b)
/* round up */ /* round up */
tmp += 1U << 31; tmp += 1U << 31;
Fp fp = { Fp fp = {ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32), a->exp + b->exp + 64};
a->exp + b->exp + 64
};
return fp; 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 && while (rem < frac && delta - rem >= kappa &&
(rem + kappa < frac || frac - rem > rem + kappa - frac)) { (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
digits[ndigits - 1]--; digits[ndigits - 1]--;
rem += kappa; 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 wfrac = upper->frac - fp->frac;
uint64_t delta = upper->frac - lower->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; uint64_t* divp;
/* 1000000000 */ /* 1000000000 */
for (divp = tens + 10; kappa > 0; divp++) { for (divp = tens + 10; kappa > 0; divp++) {
uint64_t div = *divp; uint64_t div = *divp;
unsigned digit = static_cast<unsigned>(part1 / div); 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 w = build_fp(d);
Fp lower, upper; Fp lower, upper;
@ -238,8 +224,7 @@ static int grisu2(double d, char* digits, int* K)
return generate_digits(&w, &upper, &lower, digits, 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); int exp = absv(K + ndigits - 1);
/* write plain integer */ /* write plain integer */
@ -311,8 +296,7 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
return idx; return idx;
} }
static int filter_special(double fp, char* dest) static int filter_special(double fp, char* dest) {
{
if (fp == 0.0) { if (fp == 0.0) {
dest[0] = '0'; dest[0] = '0';
return 1; return 1;
@ -327,17 +311,20 @@ static int filter_special(double fp, char* dest)
} }
if (bits & fracmask) { if (bits & fracmask) {
dest[0] = 'N'; dest[1] = 'a'; dest[2] = 'N'; dest[0] = 'N';
dest[1] = 'a';
dest[2] = 'N';
} else { } else {
dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f'; dest[0] = 'i';
dest[1] = 'n';
dest[2] = 'f';
} }
return 3; 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]; char digits[18];
int str_len = 0; int str_len = 0;

View File

@ -12,61 +12,100 @@
#define expmax -32 #define expmax -32
#define expmin -60 #define expmin -60
typedef struct Fp { typedef struct Fp {
uint64_t frac; uint64_t frac;
int exp; int exp;
} Fp; } Fp;
static Fp powers_ten[] = { static Fp powers_ten[] = {{18054884314459144840U, -1220},
{ 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 }, {13451937075301367670U, -1193},
{ 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 }, {10022474136428063862U, -1166},
{ 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 }, {14934650266808366570U, -1140},
{ 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 }, {11127181549972568877U, -1113},
{ 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 }, {16580792590934885855U, -1087},
{ 15227053142812498563U, -954 }, { 11345038669416679861U, -927 }, {12353653155963782858U, -1060},
{ 16905424996341287883U, -901 }, { 12595523146049147757U, -874 }, {18408377700990114895U, -1034},
{ 9384396036005875287U, -847 }, { 13983839803942852151U, -821 }, {13715310171984221708U, -1007},
{ 10418772551374772303U, -794 }, { 15525180923007089351U, -768 }, {10218702384817765436U, -980},
{ 11567161174868858868U, -741 }, { 17236413322193710309U, -715 }, {15227053142812498563U, -954},
{ 12842128665889583758U, -688 }, { 9568131466127621947U, -661 }, {11345038669416679861U, -927},
{ 14257626930069360058U, -635 }, { 10622759856335341974U, -608 }, {16905424996341287883U, -901},
{ 15829145694278690180U, -582 }, { 11793632577567316726U, -555 }, {12595523146049147757U, -874},
{ 17573882009934360870U, -529 }, { 13093562431584567480U, -502 }, {9384396036005875287U, -847},
{ 9755464219737475723U, -475 }, { 14536774485912137811U, -449 }, {13983839803942852151U, -821},
{ 10830740992659433045U, -422 }, { 16139061738043178685U, -396 }, {10418772551374772303U, -794},
{ 12024538023802026127U, -369 }, { 17917957937422433684U, -343 }, {15525180923007089351U, -768},
{ 13349918974505688015U, -316 }, { 9946464728195732843U, -289 }, {11567161174868858868U, -741},
{ 14821387422376473014U, -263 }, { 11042794154864902060U, -236 }, {17236413322193710309U, -715},
{ 16455045573212060422U, -210 }, { 12259964326927110867U, -183 }, {12842128665889583758U, -688},
{ 18268770466636286478U, -157 }, { 13611294676837538539U, -130 }, {9568131466127621947U, -661},
{ 10141204801825835212U, -103 }, { 15111572745182864684U, -77 }, {14257626930069360058U, -635},
{ 11258999068426240000U, -50 }, { 16777216000000000000U, -24 }, {10622759856335341974U, -608},
{ 12500000000000000000U, 3 }, { 9313225746154785156U, 30 }, {15829145694278690180U, -582},
{ 13877787807814456755U, 56 }, { 10339757656912845936U, 83 }, {11793632577567316726U, -555},
{ 15407439555097886824U, 109 }, { 11479437019748901445U, 136 }, {17573882009934360870U, -529},
{ 17105694144590052135U, 162 }, { 12744735289059618216U, 189 }, {13093562431584567480U, -502},
{ 9495567745759798747U, 216 }, { 14149498560666738074U, 242 }, {9755464219737475723U, -475},
{ 10542197943230523224U, 269 }, { 15709099088952724970U, 295 }, {14536774485912137811U, -449},
{ 11704190886730495818U, 322 }, { 17440603504673385349U, 348 }, {10830740992659433045U, -422},
{ 12994262207056124023U, 375 }, { 9681479787123295682U, 402 }, {16139061738043178685U, -396},
{ 14426529090290212157U, 428 }, { 10748601772107342003U, 455 }, {12024538023802026127U, -369},
{ 16016664761464807395U, 481 }, { 11933345169920330789U, 508 }, {17917957937422433684U, -343},
{ 17782069995880619868U, 534 }, { 13248674568444952270U, 561 }, {13349918974505688015U, -316},
{ 9871031767461413346U, 588 }, { 14708983551653345445U, 614 }, {9946464728195732843U, -289},
{ 10959046745042015199U, 641 }, { 16330252207878254650U, 667 }, {14821387422376473014U, -263},
{ 12166986024289022870U, 694 }, { 18130221999122236476U, 720 }, {11042794154864902060U, -236},
{ 13508068024458167312U, 747 }, { 10064294952495520794U, 774 }, {16455045573212060422U, -210},
{ 14996968138956309548U, 800 }, { 11173611982879273257U, 827 }, {12259964326927110867U, -183},
{ 16649979327439178909U, 853 }, { 12405201291620119593U, 880 }, {18268770466636286478U, -157},
{ 9242595204427927429U, 907 }, { 13772540099066387757U, 933 }, {13611294676837538539U, -130},
{ 10261342003245940623U, 960 }, { 15290591125556738113U, 986 }, {10141204801825835212U, -103},
{ 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 }, {15111572745182864684U, -77},
{ 12648080533535911531U, 1066 } {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; const double one_log_ten = 0.30102999566398114;
int approx = static_cast<int>(-(exp + npowers) * one_log_ten); int approx = static_cast<int>(-(exp + npowers) * one_log_ten);

View File

@ -41,9 +41,10 @@ void checkValueLength (ValueLength length) {
#endif #endif
int64_t arangodb::velocypack::currentUTCDateValue() { 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), static_assert(sizeof(arangodb::velocypack::ValueLength) >= sizeof(SIZE_MAX),
"invalid value for SIZE_MAX"); "invalid value for SIZE_MAX");