1
0
Fork 0

updated library

This commit is contained in:
Jan Steemann 2015-11-20 10:48:21 +01:00
parent f604f1d434
commit 560206557b
12 changed files with 189 additions and 47 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -28,6 +28,7 @@
#define VELOCYPACK_ITERATOR_H 1
#include <iosfwd>
#include <functional>
#include "velocypack/velocypack-common.h"
#include "velocypack/Exception.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 != ':') {