diff --git a/3rdParty/velocypack/include/velocypack/Dump.h b/3rdParty/velocypack/include/velocypack/Dump.h deleted file mode 100644 index 7a96ca0d6f..0000000000 --- a/3rdParty/velocypack/include/velocypack/Dump.h +++ /dev/null @@ -1,47 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief Library to build up VPack documents. -/// -/// DISCLAIMER -/// -/// Copyright 2015 ArangoDB GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is ArangoDB GmbH, Cologne, Germany -/// -/// @author Max Neunhoeffer -/// @author Jan Steemann -/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#ifndef VELOCYPACK_DUMP_H -#define VELOCYPACK_DUMP_H 1 - -#include - -#include "velocypack/velocypack-common.h" -#include "velocypack/Buffer.h" -#include "velocypack/Dumper.h" - -namespace arangodb { - namespace velocypack { - - // some alias types for easier usage - typedef Dumper BufferDumper; - typedef Dumper StringDumper; - typedef Dumper StringPrettyDumper; - - } // namespace arangodb::velocypack -} // namespace arangodb - -#endif diff --git a/3rdParty/velocypack/include/velocypack/Dumper.h b/3rdParty/velocypack/include/velocypack/Dumper.h index c39e182b0f..6bcfd46746 100644 --- a/3rdParty/velocypack/include/velocypack/Dumper.h +++ b/3rdParty/velocypack/include/velocypack/Dumper.h @@ -114,6 +114,8 @@ namespace arangodb { dumpString(str.c_str(), str.size()); _sink->push_back('"'); } + + void appendUInt (uint64_t); private: diff --git a/3rdParty/velocypack/src/Dumper.cpp b/3rdParty/velocypack/src/Dumper.cpp index e8b9c5854c..7ae3a8e782 100644 --- a/3rdParty/velocypack/src/Dumper.cpp +++ b/3rdParty/velocypack/src/Dumper.cpp @@ -39,32 +39,36 @@ namespace arangodb { int fpconv_dtoa (double fp, char dest[24]); } }; - + +void Dumper::appendUInt (uint64_t v) { + if (10000000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000000ULL) % 10); } + if ( 1000000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000000ULL) % 10); } + if ( 100000000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000000ULL) % 10); } + if ( 10000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000ULL) % 10); } + if ( 1000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000ULL) % 10); } + if ( 100000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000ULL) % 10); } + if ( 10000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000ULL) % 10); } + if ( 1000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000ULL) % 10); } + if ( 100000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000ULL) % 10); } + if ( 10000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000ULL) % 10); } + if ( 1000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000ULL) % 10); } + if ( 100000000ULL <= v) { _sink->push_back('0' + (v / 100000000ULL) % 10); } + if ( 10000000ULL <= v) { _sink->push_back('0' + (v / 10000000ULL) % 10); } + if ( 1000000ULL <= v) { _sink->push_back('0' + (v / 1000000ULL) % 10); } + if ( 100000ULL <= v) { _sink->push_back('0' + (v / 100000ULL) % 10); } + if ( 10000ULL <= v) { _sink->push_back('0' + (v / 10000ULL) % 10); } + if ( 1000ULL <= v) { _sink->push_back('0' + (v / 1000ULL) % 10); } + if ( 100ULL <= v) { _sink->push_back('0' + (v / 100ULL) % 10); } + if ( 10ULL <= v) { _sink->push_back('0' + (v / 10ULL) % 10); } + + _sink->push_back('0' + (v % 10)); +} + void Dumper::dumpInteger (Slice const* slice) { if (slice->isType(ValueType::UInt)) { uint64_t v = slice->getUInt(); - if (10000000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000000ULL) % 10); } - if ( 1000000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000000ULL) % 10); } - if ( 100000000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000000ULL) % 10); } - if ( 10000000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000000ULL) % 10); } - if ( 1000000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000000ULL) % 10); } - if ( 100000000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000000ULL) % 10); } - if ( 10000000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000000ULL) % 10); } - if ( 1000000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000000ULL) % 10); } - if ( 100000000000ULL <= v) { _sink->push_back('0' + (v / 100000000000ULL) % 10); } - if ( 10000000000ULL <= v) { _sink->push_back('0' + (v / 10000000000ULL) % 10); } - if ( 1000000000ULL <= v) { _sink->push_back('0' + (v / 1000000000ULL) % 10); } - if ( 100000000ULL <= v) { _sink->push_back('0' + (v / 100000000ULL) % 10); } - if ( 10000000ULL <= v) { _sink->push_back('0' + (v / 10000000ULL) % 10); } - if ( 1000000ULL <= v) { _sink->push_back('0' + (v / 1000000ULL) % 10); } - if ( 100000ULL <= v) { _sink->push_back('0' + (v / 100000ULL) % 10); } - if ( 10000ULL <= v) { _sink->push_back('0' + (v / 10000ULL) % 10); } - if ( 1000ULL <= v) { _sink->push_back('0' + (v / 1000ULL) % 10); } - if ( 100ULL <= v) { _sink->push_back('0' + (v / 100ULL) % 10); } - if ( 10ULL <= v) { _sink->push_back('0' + (v / 10ULL) % 10); } - - _sink->push_back('0' + (v % 10)); + appendUInt(v); } else if (slice->isType(ValueType::Int)) { int64_t v = slice->getInt(); diff --git a/arangod/Storage/Options.cpp b/arangod/Storage/Options.cpp index f60528a3b3..9c52706828 100644 --- a/arangod/Storage/Options.cpp +++ b/arangod/Storage/Options.cpp @@ -28,15 +28,18 @@ //////////////////////////////////////////////////////////////////////////////// #include "Storage/Options.h" +#include "Basics/Exceptions.h" +#include "Utils/CollectionNameResolver.h" +#include "VocBase/voc-types.h" using namespace arangodb; // global options used when converting JSON into a document -VPackOptions JsonToDocumentOptions; +VPackOptions StorageOptions::JsonToDocumentTemplate; // global options used when converting documents into JSON -VPackOptions DocumentToJsonOptions; +VPackOptions StorageOptions::DocumentToJsonTemplate; // global options used for other conversions -VPackOptions NonDocumentOptions; +VPackOptions StorageOptions::NonDocumentTemplate; struct ExcludeHandlerImpl : public VPackAttributeExcludeHandler { bool shouldExclude (VPackSlice const& key, int nesting) override final { @@ -62,16 +65,45 @@ struct ExcludeHandlerImpl : public VPackAttributeExcludeHandler { }; struct CustomTypeHandlerImpl : public VPackCustomTypeHandler { + CustomTypeHandlerImpl (triagens::arango::CollectionNameResolver const* resolver, + TRI_voc_cid_t cid) + : resolver(resolver), + cid(cid) { + } + void toJson (VPackSlice const& value, VPackDumper* dumper, VPackSlice const& base) { if (value.head() == 0xf0) { // _id - // TODO - return; + if (! base.isObject()) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid value type"); + } + char buffer[512]; // TODO: check if size is appropriate + size_t len = resolver->getCollectionName(&buffer[0], cid); + buffer[len] = '/'; + VPackSlice key = base.get("_key"); + + VPackValueLength keyLength; + char const* p = key.getString(keyLength); + if (p == nullptr) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid _key value"); + } + memcpy(&buffer[len + 1], p, keyLength); + dumper->appendString(&buffer[0], len + 1 + keyLength); } if (value.head() == 0xf1) { // _rev - // TODO + uint64_t rev = 0; + uint8_t const* start = value.start() + 1; + uint8_t const* end = start + value.byteSize(); + do { + rev <<= 8; + rev += static_cast(*start++); + } + while (start < end); + dumper->sink()->push_back('"'); + dumper->appendUInt(rev); + dumper->sink()->push_back('"'); return; } @@ -101,12 +133,13 @@ struct CustomTypeHandlerImpl : public VPackCustomTypeHandler { } throw "unknown type!"; } + + triagens::arango::CollectionNameResolver const* resolver; + TRI_voc_cid_t cid; }; - StorageOptions::StorageOptions () : _translator(new VPackAttributeTranslator), - _customTypeHandler(new CustomTypeHandlerImpl), _excludeHandler(new ExcludeHandlerImpl) { // these attribute names will be translated into short integer values @@ -118,38 +151,49 @@ StorageOptions::StorageOptions () _translator->seal(); // set options for JSON to document conversion - JsonToDocumentOptions.buildUnindexedArrays = false; - JsonToDocumentOptions.buildUnindexedObjects = false; - JsonToDocumentOptions.checkAttributeUniqueness = true; - JsonToDocumentOptions.sortAttributeNames = true; - JsonToDocumentOptions.attributeTranslator = _translator.get(); - JsonToDocumentOptions.customTypeHandler = _customTypeHandler.get(); - JsonToDocumentOptions.attributeExcludeHandler = _excludeHandler.get(); + JsonToDocumentTemplate.buildUnindexedArrays = false; + JsonToDocumentTemplate.buildUnindexedObjects = false; + JsonToDocumentTemplate.checkAttributeUniqueness = true; + JsonToDocumentTemplate.sortAttributeNames = true; + JsonToDocumentTemplate.attributeTranslator = _translator.get(); + JsonToDocumentTemplate.customTypeHandler = nullptr; + JsonToDocumentTemplate.attributeExcludeHandler = _excludeHandler.get(); // set options for document to JSON conversion - DocumentToJsonOptions.prettyPrint = false; - DocumentToJsonOptions.escapeForwardSlashes = true; - DocumentToJsonOptions.unsupportedTypeBehavior = VPackOptions::FailOnUnsupportedType; - DocumentToJsonOptions.attributeTranslator = _translator.get(); - DocumentToJsonOptions.customTypeHandler = _customTypeHandler.get(); - DocumentToJsonOptions.attributeExcludeHandler = nullptr; + DocumentToJsonTemplate.attributeTranslator = _translator.get(); + DocumentToJsonTemplate.customTypeHandler = nullptr; + DocumentToJsonTemplate.attributeExcludeHandler = nullptr; + DocumentToJsonTemplate.prettyPrint = false; + DocumentToJsonTemplate.escapeForwardSlashes = true; + DocumentToJsonTemplate.unsupportedTypeBehavior = VPackOptions::FailOnUnsupportedType; - - NonDocumentOptions.prettyPrint = false; - NonDocumentOptions.escapeForwardSlashes = true; - NonDocumentOptions.sortAttributeNames = false; - NonDocumentOptions.buildUnindexedArrays = true; - NonDocumentOptions.buildUnindexedObjects = true; - NonDocumentOptions.checkAttributeUniqueness = false; - NonDocumentOptions.unsupportedTypeBehavior = VPackOptions::FailOnUnsupportedType; - NonDocumentOptions.attributeTranslator = nullptr; - NonDocumentOptions.customTypeHandler = nullptr; - NonDocumentOptions.attributeExcludeHandler = nullptr; -// bool keepTopLevelOpen = false; + // non-document options + NonDocumentTemplate.buildUnindexedArrays = true; + NonDocumentTemplate.buildUnindexedObjects = true; + NonDocumentTemplate.checkAttributeUniqueness = false; + NonDocumentTemplate.sortAttributeNames = false; + NonDocumentTemplate.attributeTranslator = nullptr; + NonDocumentTemplate.customTypeHandler = nullptr; + NonDocumentTemplate.attributeExcludeHandler = nullptr; + NonDocumentTemplate.prettyPrint = false; + NonDocumentTemplate.escapeForwardSlashes = true; + NonDocumentTemplate.unsupportedTypeBehavior = VPackOptions::FailOnUnsupportedType; } StorageOptions::~StorageOptions () { } + +VPackOptions StorageOptions::getDocumentToJsonTemplate () { + return DocumentToJsonTemplate; +} + +VPackOptions StorageOptions::getJsonToDocumentTemplate () { + return JsonToDocumentTemplate; +} + +VPackOptions StorageOptions::getNonDocumentTemplate () { + return NonDocumentTemplate; +} // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE diff --git a/arangod/Storage/Options.h b/arangod/Storage/Options.h index 786a54bf30..73c9d933ff 100644 --- a/arangod/Storage/Options.h +++ b/arangod/Storage/Options.h @@ -42,15 +42,18 @@ namespace arangodb { StorageOptions (StorageOptions const&) = delete; StorageOptions& operator= (StorageOptions const&) = delete; + static VPackOptions getDocumentToJsonTemplate (); + static VPackOptions getJsonToDocumentTemplate (); + static VPackOptions getNonDocumentTemplate (); + private: std::unique_ptr _translator; - std::unique_ptr _customTypeHandler; std::unique_ptr _excludeHandler; - static VPackOptions JsonToDocumentOptions; - static VPackOptions DocumentToJsonOptions; - static VPackOptions NonDocumentOptions; + static VPackOptions JsonToDocumentTemplate; + static VPackOptions DocumentToJsonTemplate; + static VPackOptions NonDocumentTemplate; }; } diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 72aa8fa48b..5f16398fc9 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -34,6 +34,7 @@ #include "Basics/json-utilities.h" #include "Cluster/ClusterMethods.h" #include "Indexes/PrimaryIndex.h" +#include "Storage/Options.h" #include "Utils/transactions.h" #include "Utils/V8ResolverGuard.h" #include "Utils/V8TransactionContext.h" @@ -1005,11 +1006,23 @@ static void InsertVocbaseCol (TRI_vocbase_col_t* col, TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID); } - VPackBuilder builder = TRI_V8ToVPack(isolate, args[0]->ToObject()); + VPackOptions vOptions = arangodb::StorageOptions::getDocumentToJsonTemplate(); + VPackBuilder builder(&vOptions); + int res2 = TRI_V8ToVPack(isolate, builder, args[0]->ToObject(), true); + + if (res2 || builder.hasKey("_key")) { + } + else { + } + + builder.close(); VPackSlice slice(builder.slice()); + for (auto const& it : VPackObjectIterator(slice)) { + std::cout << "KEY: " << it.key.copyString() << "\n"; + } - //std::cout << "GOT: " << VPackHexDump(slice) << "\n\n"; + // std::cout << "GOT: " << VPackHexDump(slice) << "\n\n"; // set document key diff --git a/lib/V8/v8-vpack.cpp b/lib/V8/v8-vpack.cpp index 48d2e59b3b..462245e469 100644 --- a/lib/V8/v8-vpack.cpp +++ b/lib/V8/v8-vpack.cpp @@ -128,19 +128,31 @@ v8::Handle TRI_VPackToV8 (v8::Isolate* isolate, } } +struct BuilderContext { + BuilderContext (v8::Isolate* isolate, VPackBuilder& builder, bool keepTopLevelOpen) + : isolate(isolate), builder(builder), keepTopLevelOpen(keepTopLevelOpen) { + } + + v8::Isolate* isolate; + VPackBuilder& builder; + std::set seenHashes; + std::vector> seenObjects; + bool keepTopLevelOpen; +}; + //////////////////////////////////////////////////////////////////////////////// /// @brief adds a VPackValue to either an array or an object //////////////////////////////////////////////////////////////////////////////// -static void AddValue (VPackBuilder& builder, +static void AddValue (BuilderContext& context, std::string const& attributeName, bool inObject, VPackValue const& value) { if (inObject) { - builder.add(attributeName, value); + context.builder.add(attributeName, value); } else { - builder.add(value); + context.builder.add(value); } } @@ -148,29 +160,27 @@ static void AddValue (VPackBuilder& builder, /// @brief convert a V8 value to a VPack value //////////////////////////////////////////////////////////////////////////////// -static int V8ToVPack (v8::Isolate* isolate, - VPackBuilder& builder, +static int V8ToVPack (BuilderContext& context, v8::Handle const parameter, - std::set& seenHashes, - std::vector>& seenObjects, std::string const& attributeName, bool inObject) { + v8::Isolate* isolate = context.isolate; v8::HandleScope scope(isolate); if (parameter->IsNull()) { - AddValue(builder, attributeName, inObject, VPackValue(VPackValueType::Null)); + AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Null)); return TRI_ERROR_NO_ERROR; } if (parameter->IsBoolean()) { v8::Handle booleanParameter = parameter->ToBoolean(); - AddValue(builder, attributeName, inObject, VPackValue(booleanParameter->Value())); + AddValue(context, attributeName, inObject, VPackValue(booleanParameter->Value())); return TRI_ERROR_NO_ERROR; } if (parameter->IsNumber()) { v8::Handle numberParameter = parameter->ToNumber(); - AddValue(builder, attributeName, inObject, VPackValue(numberParameter->Value())); + AddValue(context, attributeName, inObject, VPackValue(numberParameter->Value())); return TRI_ERROR_NO_ERROR; } @@ -182,37 +192,37 @@ static int V8ToVPack (v8::Isolate* isolate, return TRI_ERROR_OUT_OF_MEMORY; } - AddValue(builder, attributeName, inObject, VPackValue(*str)); + AddValue(context, attributeName, inObject, VPackValue(*str)); return TRI_ERROR_NO_ERROR; } if (parameter->IsArray()) { v8::Handle array = v8::Handle::Cast(parameter); - AddValue(builder, attributeName, inObject, VPackValue(VPackValueType::Array)); + AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Array)); uint32_t const n = array->Length(); for (uint32_t i = 0; i < n; ++i) { // get address of next element - int res = V8ToVPack(isolate, builder, array->Get(i), seenHashes, seenObjects, "", false); + int res = V8ToVPack(context, array->Get(i), "", false); if (res != TRI_ERROR_NO_ERROR) { return res; } } - builder.close(); + context.builder.close(); return TRI_ERROR_NO_ERROR; } if (parameter->IsObject()) { if (parameter->IsBooleanObject()) { - AddValue(builder, attributeName, inObject, VPackValue(v8::Handle::Cast(parameter)->BooleanValue())); + AddValue(context, attributeName, inObject, VPackValue(v8::Handle::Cast(parameter)->BooleanValue())); return TRI_ERROR_NO_ERROR; } if (parameter->IsNumberObject()) { - AddValue(builder, attributeName, inObject, VPackValue(v8::Handle::Cast(parameter)->NumberValue())); + AddValue(context, attributeName, inObject, VPackValue(v8::Handle::Cast(parameter)->NumberValue())); return TRI_ERROR_NO_ERROR; } @@ -224,7 +234,7 @@ static int V8ToVPack (v8::Isolate* isolate, return TRI_ERROR_OUT_OF_MEMORY; } - AddValue(builder, attributeName, inObject, VPackValue(*str)); + AddValue(context, attributeName, inObject, VPackValue(*str)); return TRI_ERROR_NO_ERROR; } @@ -256,7 +266,7 @@ static int V8ToVPack (v8::Isolate* isolate, } // this passes ownership for the utf8 string to the JSON object - AddValue(builder, attributeName, inObject, VPackValue(*str)); + AddValue(context, attributeName, inObject, VPackValue(*str)); return TRI_ERROR_NO_ERROR; } } @@ -266,10 +276,10 @@ static int V8ToVPack (v8::Isolate* isolate, int hash = o->GetIdentityHash(); - if (seenHashes.find(hash) != seenHashes.end()) { + if (context.seenHashes.find(hash) != context.seenHashes.end()) { // LOG_TRACE("found hash %d", hash); - for (auto& it : seenObjects) { + for (auto& it : context.seenObjects) { if (parameter->StrictEquals(it)) { // object is recursive return TRI_ERROR_BAD_PARAMETER; @@ -277,15 +287,15 @@ static int V8ToVPack (v8::Isolate* isolate, } } else { - seenHashes.emplace(hash); + context.seenHashes.emplace(hash); } - seenObjects.emplace_back(o); + context.seenObjects.emplace_back(o); v8::Handle names = o->GetOwnPropertyNames(); uint32_t const n = names->Length(); - AddValue(builder, attributeName, inObject, VPackValue(VPackValueType::Object)); + AddValue(context, attributeName, inObject, VPackValue(VPackValueType::Object)); for (uint32_t i = 0; i < n; ++i) { // process attribute name @@ -296,7 +306,7 @@ static int V8ToVPack (v8::Isolate* isolate, return TRI_ERROR_OUT_OF_MEMORY; } - int res = V8ToVPack(isolate, builder, o->Get(key), seenHashes, seenObjects, *str, true); + int res = V8ToVPack(context, o->Get(key), *str, true); if (res != TRI_ERROR_NO_ERROR) { // to mimic behavior of previous ArangoDB versions, we need to silently ignore this error @@ -305,8 +315,10 @@ static int V8ToVPack (v8::Isolate* isolate, } } - seenObjects.pop_back(); - builder.close(); + context.seenObjects.pop_back(); + if (! context.keepTopLevelOpen || ! context.seenObjects.empty()) { + context.builder.close(); + } return TRI_ERROR_NO_ERROR; } @@ -317,20 +329,15 @@ static int V8ToVPack (v8::Isolate* isolate, /// @brief convert a V8 value to VPack value //////////////////////////////////////////////////////////////////////////////// -VPackBuilder TRI_V8ToVPack (v8::Isolate* isolate, - v8::Handle const parameter) { +int TRI_V8ToVPack (v8::Isolate* isolate, + VPackBuilder& builder, + v8::Handle const value, + bool keepTopLevelOpen) { - VPackBuilder builder; + BuilderContext context(isolate, builder, keepTopLevelOpen); + int res = V8ToVPack(context, value, "", false); - std::set seenHashes; - std::vector> seenObjects; - int res = V8ToVPack(isolate, builder, parameter, seenHashes, seenObjects, "", false); - - if (res != TRI_ERROR_NO_ERROR) { - THROW_ARANGO_EXCEPTION(res); - } - - return builder; + return res; } // ----------------------------------------------------------------------------- diff --git a/lib/V8/v8-vpack.h b/lib/V8/v8-vpack.h index 8ee7eef3e8..4b6122322c 100644 --- a/lib/V8/v8-vpack.h +++ b/lib/V8/v8-vpack.h @@ -54,8 +54,10 @@ v8::Handle TRI_VPackToV8 (v8::Isolate* isolate, /// @brief convert a V8 value to VPack value //////////////////////////////////////////////////////////////////////////////// -VPackBuilder TRI_V8ToVPack (v8::Isolate* isolate, - v8::Handle const); +int TRI_V8ToVPack (v8::Isolate* isolate, + VPackBuilder& builder, + v8::Handle const value, + bool keepTopLevelOpen); #endif