mirror of https://gitee.com/bigwinds/arangodb
updated library
This commit is contained in:
parent
f604f1d434
commit
560206557b
|
@ -45,12 +45,16 @@ namespace arangodb {
|
|||
AttributeTranslator& operator= (AttributeTranslator const&) = delete;
|
||||
|
||||
AttributeTranslator ()
|
||||
: _builder() {
|
||||
: _builder(), _count(0) {
|
||||
}
|
||||
|
||||
~AttributeTranslator () {
|
||||
}
|
||||
|
||||
size_t count () const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
void add (std::string const& key, uint64_t id);
|
||||
|
||||
void seal ();
|
||||
|
@ -58,6 +62,9 @@ namespace arangodb {
|
|||
// translate from string to id
|
||||
uint8_t const* translate (std::string const& key) const;
|
||||
|
||||
// translate from string to id
|
||||
uint8_t const* translate (char const* key, ValueLength length) const;
|
||||
|
||||
// translate from id to string
|
||||
uint8_t const* translate (uint64_t id) const;
|
||||
|
||||
|
@ -66,6 +73,7 @@ namespace arangodb {
|
|||
std::unique_ptr<Builder> _builder;
|
||||
std::unordered_map<std::string, uint8_t const*> _keyToId;
|
||||
std::unordered_map<uint64_t, uint8_t const*> _idToKey;
|
||||
size_t _count;
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -138,6 +138,7 @@ namespace arangodb {
|
|||
_size = _buffer->size();
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
|
@ -151,6 +152,7 @@ namespace arangodb {
|
|||
_size = _buffer->size();
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
|
@ -238,11 +240,8 @@ namespace arangodb {
|
|||
|
||||
static Builder clone (Slice const& slice, Options const* options = &Options::Defaults) {
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
Builder b;
|
||||
b.options = options;
|
||||
|
||||
Builder b(options);
|
||||
b.add(slice);
|
||||
return std::move(b);
|
||||
}
|
||||
|
@ -310,25 +309,37 @@ namespace arangodb {
|
|||
Slice getKey (std::string const& key) const;
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (std::string const& attrName, Value sub) {
|
||||
Builder& operator() (std::string const& attrName, Value const& sub) {
|
||||
add(attrName, sub);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (std::string const& attrName, ValuePair sub) {
|
||||
Builder& operator() (std::string const& attrName, ValuePair const& sub) {
|
||||
add(attrName, sub);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (Value sub) {
|
||||
Builder& operator() (std::string const& attrName, Slice const& sub) {
|
||||
add(attrName, sub);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (Value const& sub) {
|
||||
add(sub);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (ValuePair sub) {
|
||||
Builder& operator() (ValuePair const& sub) {
|
||||
add(sub);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Syntactic sugar for add:
|
||||
Builder& operator() (Slice const& sub) {
|
||||
add(sub);
|
||||
return *this;
|
||||
}
|
||||
|
@ -450,6 +461,7 @@ namespace arangodb {
|
|||
if (options->attributeTranslator != nullptr) {
|
||||
// check if a translation for the attribute name exists
|
||||
uint8_t const* translated = options->attributeTranslator->translate(attrName);
|
||||
|
||||
if (translated != nullptr) {
|
||||
set(Slice(options->attributeTranslator->translate(attrName), options));
|
||||
return set(sub);
|
||||
|
|
|
@ -43,7 +43,14 @@ namespace arangodb {
|
|||
|
||||
public:
|
||||
|
||||
enum VisitationOrder {
|
||||
PreOrder = 1,
|
||||
PostOrder = 2
|
||||
};
|
||||
|
||||
Collection () = delete;
|
||||
Collection (Collection const&) = delete;
|
||||
Collection& operator= (Collection const&) = delete;
|
||||
|
||||
static void forEach (Slice const& slice, std::function<bool(Slice const&, ValueLength)> const& cb);
|
||||
|
||||
|
@ -134,6 +141,12 @@ namespace arangodb {
|
|||
static Builder merge (Slice const* left, Slice const* right, bool mergeValues) {
|
||||
return merge(*left, *right, mergeValues);
|
||||
}
|
||||
|
||||
static void visitRecursive (Slice const& slice, VisitationOrder order, std::function<bool(Slice const&, Slice const&)> const& func);
|
||||
|
||||
static void visitRecursive (Slice const* slice, VisitationOrder order, std::function<bool(Slice const&, Slice const&)> const& func) {
|
||||
visitRecursive(*slice, order, func);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -124,13 +124,13 @@ namespace arangodb {
|
|||
case KeyNotFound:
|
||||
return "Key not found";
|
||||
case BuilderNotSealed:
|
||||
return "Builder object not yet sealed";
|
||||
return "Builder value not yet sealed";
|
||||
case BuilderNeedOpenObject:
|
||||
return "Need open Object";
|
||||
case BuilderNeedOpenArray:
|
||||
return "Need open Array";
|
||||
case BuilderNeedSubvalue:
|
||||
return "Need subvalue in current object or array";
|
||||
return "Need subvalue in current Object or Array";
|
||||
case BuilderNeedOpenCompound:
|
||||
return "Need open compound value (Array or Object)";
|
||||
case BuilderUnexpectedType:
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define VELOCYPACK_ITERATOR_H 1
|
||||
|
||||
#include <iosfwd>
|
||||
#include <functional>
|
||||
|
||||
#include "velocypack/velocypack-common.h"
|
||||
#include "velocypack/Exception.h"
|
||||
|
|
|
@ -101,21 +101,21 @@ namespace arangodb {
|
|||
: _start(nullptr), _size(0), _pos(0), _nesting(0), options(options) {
|
||||
|
||||
VELOCYPACK_ASSERT(options != nullptr);
|
||||
|
||||
if (options == nullptr) {
|
||||
throw Exception(Exception::InternalError, "Options cannot be a nullptr");
|
||||
}
|
||||
_b.options = options;
|
||||
}
|
||||
|
||||
static Builder fromJson (std::string const& json, Options const* options = &Options::Defaults) {
|
||||
Parser parser;
|
||||
parser.options = options;
|
||||
Parser parser(options);
|
||||
parser.parse(json);
|
||||
return parser.steal();
|
||||
}
|
||||
|
||||
static Builder fromJson (uint8_t const* start, size_t size, Options const* options = &Options::Defaults) {
|
||||
Parser parser;
|
||||
parser.options = options;
|
||||
Parser parser(options);
|
||||
parser.parse(start, size);
|
||||
return parser.steal();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <vector>
|
||||
#include <iosfwd>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
#include "velocypack/velocypack-common.h"
|
||||
#include "velocypack/Exception.h"
|
||||
|
@ -720,24 +721,6 @@ namespace arangodb {
|
|||
}
|
||||
#endif
|
||||
|
||||
// read an unsigned little endian integer value of the
|
||||
// specified length, starting at the specified byte offset
|
||||
template <typename T>
|
||||
T readInteger (uint8_t const* start, ValueLength numBytes) const {
|
||||
T value = 0;
|
||||
uint8_t const* p = start;
|
||||
uint8_t const* e = p + numBytes;
|
||||
T digit = 0;
|
||||
|
||||
while (p < e) {
|
||||
value += static_cast<T>(*p) << (digit * 8);
|
||||
++digit;
|
||||
++p;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// extracts a value from the slice and converts it into a
|
||||
// built-in type
|
||||
template<typename T> T extractValue () const {
|
||||
|
|
|
@ -156,18 +156,25 @@ namespace arangodb {
|
|||
: static_cast<int64_t>(v);
|
||||
}
|
||||
|
||||
static inline uint64_t readUInt64 (uint8_t const* start) throw() {
|
||||
// read an unsigned little endian integer value of the
|
||||
// specified length, starting at the specified byte offset
|
||||
template<typename T>
|
||||
static inline T readInteger (uint8_t const* start, ValueLength length) throw() {
|
||||
uint64_t value = 0;
|
||||
uint64_t x = 0;
|
||||
uint8_t const* end = start + 8;
|
||||
uint8_t const* end = start + length;
|
||||
do {
|
||||
value += static_cast<uint64_t>(*start++) << x;
|
||||
value += static_cast<T>(*start++) << x;
|
||||
x += 8;
|
||||
}
|
||||
while (start < end);
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline uint64_t readUInt64 (uint8_t const* start) throw() {
|
||||
return readInteger<uint64_t>(start, 8);
|
||||
}
|
||||
|
||||
static inline void storeUInt64 (uint8_t* start, uint64_t value) throw() {
|
||||
uint8_t const* end = start + 8;
|
||||
do {
|
||||
|
|
|
@ -40,6 +40,7 @@ void AttributeTranslator::add (std::string const& key, uint64_t id) {
|
|||
}
|
||||
|
||||
_builder->add(key, Value(id));
|
||||
_count++;
|
||||
}
|
||||
|
||||
void AttributeTranslator::seal () {
|
||||
|
@ -52,6 +53,7 @@ void AttributeTranslator::seal () {
|
|||
Slice s(_builder->slice());
|
||||
|
||||
ObjectIterator it(s);
|
||||
|
||||
while (it.valid()) {
|
||||
_keyToId.emplace(it.key().copyString(), it.value().begin());
|
||||
_idToKey.emplace(it.value().getUInt(), it.key().begin());
|
||||
|
@ -70,6 +72,17 @@ uint8_t const* AttributeTranslator::translate (std::string const& key) const {
|
|||
return (*it).second;
|
||||
}
|
||||
|
||||
// translate from string to id
|
||||
uint8_t const* AttributeTranslator::translate (char const* key, ValueLength length) const {
|
||||
auto it = _keyToId.find(std::string(key, length));
|
||||
|
||||
if (it == _keyToId.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
// translate from id to string
|
||||
uint8_t const* AttributeTranslator::translate (uint64_t id) const {
|
||||
auto it = _idToKey.find(id);
|
||||
|
|
|
@ -745,25 +745,25 @@ uint8_t* Builder::add (std::string const& attrName, Value const& sub) {
|
|||
return addInternal<Value>(attrName, sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (std::string const& attrName, Slice const& sub) {
|
||||
return addInternal<Slice>(attrName, sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (std::string const& attrName, ValuePair const& sub) {
|
||||
return addInternal<ValuePair>(attrName, sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (std::string const& attrName, Slice const& sub) {
|
||||
return addInternal<Slice>(attrName, sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (Value const& sub) {
|
||||
return addInternal<Value>(sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (Slice const& sub) {
|
||||
return addInternal<Slice>(sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (ValuePair const& sub) {
|
||||
return addInternal<ValuePair>(sub);
|
||||
}
|
||||
|
||||
uint8_t* Builder::add (Slice const& sub) {
|
||||
return addInternal<Slice>(sub);
|
||||
}
|
||||
|
||||
static_assert(sizeof(double) == 8, "double is not 8 bytes");
|
||||
|
||||
|
|
|
@ -325,3 +325,88 @@ Builder Collection::merge (Slice const& left, Slice const& right, bool mergeValu
|
|||
return b;
|
||||
}
|
||||
|
||||
template<Collection::VisitationOrder order>
|
||||
static bool doVisit (Slice const& slice, std::function<bool(Slice const& key, Slice const& value)> const& func);
|
||||
|
||||
template<Collection::VisitationOrder order>
|
||||
static bool visitObject (Slice const& value, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
ObjectIterator it(value);
|
||||
|
||||
while (it.valid()) {
|
||||
// sub-object?
|
||||
Slice v = it.value();
|
||||
bool const isCompound = (v.isObject() || v.isArray());
|
||||
|
||||
if (isCompound && order == Collection::PreOrder) {
|
||||
if (! doVisit<order>(v, func)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! func(it.key(), v)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isCompound && order == Collection::PostOrder) {
|
||||
if (! doVisit<order>(v, func)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
it.next();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<Collection::VisitationOrder order>
|
||||
static bool visitArray (Slice const& value, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
ArrayIterator it(value);
|
||||
|
||||
while (it.valid()) {
|
||||
// sub-object?
|
||||
Slice v = it.value();
|
||||
bool const isCompound = (v.isObject() || v.isArray());
|
||||
|
||||
if (isCompound && order == Collection::PreOrder) {
|
||||
if (! doVisit<order>(v, func)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (! func(Slice(), v)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isCompound && order == Collection::PostOrder) {
|
||||
if (! doVisit<order>(v, func)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
it.next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<Collection::VisitationOrder order>
|
||||
static bool doVisit (Slice const& slice, std::function<bool(Slice const& key, Slice const& value)> const& func) {
|
||||
if (slice.isObject()) {
|
||||
return visitObject<order>(slice, func);
|
||||
}
|
||||
if (slice.isArray()) {
|
||||
return visitArray<order>(slice, func);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (order == Collection::PreOrder) {
|
||||
doVisit<Collection::PreOrder>(slice, func);
|
||||
}
|
||||
else {
|
||||
doVisit<Collection::PostOrder>(slice, func);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -144,6 +144,7 @@ void Parser::parseNumber () {
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
double fractionalPart;
|
||||
if (i == '.') {
|
||||
// fraction. skip over '.'
|
||||
|
@ -479,16 +480,35 @@ void Parser::parseObject () {
|
|||
|
||||
_b.reportAdd(base);
|
||||
bool excludeAttribute = false;
|
||||
auto const lastPos = _b._pos;
|
||||
if (options->attributeExcludeHandler == nullptr) {
|
||||
parseString();
|
||||
}
|
||||
else {
|
||||
auto lastPos = _b._pos;
|
||||
parseString();
|
||||
if (options->attributeExcludeHandler->shouldExclude(Slice(_b._start + lastPos, options), _nesting)) {
|
||||
excludeAttribute = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (! excludeAttribute && options->attributeTranslator != nullptr) {
|
||||
// check if a translation for the attribute name exists
|
||||
Slice key(_b._start + lastPos, options);
|
||||
|
||||
if (key.isString()) {
|
||||
ValueLength keyLength;
|
||||
char const* p = key.getString(keyLength);
|
||||
uint8_t const* translated = options->attributeTranslator->translate(p, keyLength);
|
||||
|
||||
if (translated != nullptr) {
|
||||
// found translation... now reset position to old key position
|
||||
// and simply overwrite the existing key with the numeric translation id
|
||||
_b._pos = lastPos;
|
||||
_b.addUInt(Slice(translated, options).getUInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = skipWhiteSpace("Expecting ':'");
|
||||
// always expecting the ':' here
|
||||
if (i != ':') {
|
||||
|
|
Loading…
Reference in New Issue