1
0
Fork 0

Merge branch 'aql2' of https://github.com/triAGENS/ArangoDB into aql2

This commit is contained in:
Jan Steemann 2014-07-25 16:57:01 +02:00
commit ddf18650e7
3 changed files with 443 additions and 62 deletions

View File

@ -27,8 +27,6 @@
#include "Aql/ExecutionPlan.h"
#include <Basics/JsonHelper.h>
using namespace triagens::basics;
using namespace triagens::aql;
@ -40,29 +38,28 @@ using namespace triagens::aql;
/// @brief toJson, export an ExecutionPlan to JSON
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* ExecutionPlan::toJson (TRI_memory_zone_t* zone) {
Json ExecutionPlan::toJson (TRI_memory_zone_t* zone) {
Json json;
try {
json = Json(Json::Array,2)
("type", Json(getTypeString()));
}
catch (std::exception& e) {
return nullptr;
return json;
}
if (_dependencies.size() != 0) {
Json deps;
try {
deps = Json(Json::List, _dependencies.size());
Json deps(Json::List, _dependencies.size());
for (size_t i = 0; i < _dependencies.size(); i++) {
deps(_dependencies[i]->toJson(zone));
}
json("dependencies", deps);
}
catch (std::exception& e) {
return nullptr;
return Json(); // returns an empty one
}
}
return json.steal();
return json;
}
////////////////////////////////////////////////////////////////////////////////
@ -94,27 +91,61 @@ void ExecutionPlan::appendAsString (std::string& st, int indent) {
st.push_back('>');
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of EnumerateCollectionPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson, for EnumerateCollectionPlan
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* EnumerateCollectionPlan::toJson (TRI_memory_zone_t* zone) {
auto ep = static_cast<ExecutionPlan*>(this);
Json json(zone, ep->toJson(zone));
Json EnumerateCollectionPlan::toJson (TRI_memory_zone_t* zone) {
Json json(ExecutionPlan::toJson(zone)); // call base class method
if (json.isEmpty()) {
return nullptr;
return json;
}
// Now put info about vocbase and cid in there
try {
json("vocbase", Json(_vocbase->_name))
("cid", JsonHelper::uint64String(zone, _cid));
if (_vocbase == nullptr) {
json("vocbase", Json("<nullptr>"));
}
else {
json("vocbase", Json(_vocbase->_name));
}
json("collection", Json(_collname));
}
catch (std::exception& e) {
return nullptr;
return Json();
}
// And return it:
return json.steal();
return json;
}
// -----------------------------------------------------------------------------
// --SECTION-- methods of LimitPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief toJson, for LimitPlan
////////////////////////////////////////////////////////////////////////////////
Json LimitPlan::toJson (TRI_memory_zone_t* zone) {
Json json(ExecutionPlan::toJson(zone)); // call base class method
if (json.isEmpty()) {
return json;
}
// Now put info about offset and limit in
try {
json("offset", Json(static_cast<double>(_offset)))
("limit", Json(static_cast<double>(_limit)));
}
catch (std::exception& e) {
return Json();
}
// And return it:
return json;
}
////////////////////////////////////////////////////////////////////////////////
@ -123,51 +154,66 @@ TRI_json_t* EnumerateCollectionPlan::toJson (TRI_memory_zone_t* zone) {
using namespace triagens::basics;
using namespace std;
void testExecutionPlans () {
Json a(12);
Json b(Json::Array);
b("a",a);
std::cout << b.toString() << std::endl;
std::cout << a.toString() << std::endl;
std::cout << "Got here" << std::endl;
ExecutionPlan* e = new ExecutionPlan();
ExecutionPlan* f = new ExecutionPlan(e);
std::string st;
string st;
e->appendAsString(st, 0);
std::cout << "e as string:\n" << st << std::endl;
cout << "e as string:\n" << st << endl;
st.clear();
f->appendAsString(st, 0);
std::cout << "f as string:\n" << st << std::endl;
cout << "f as string:\n" << st << endl;
TRI_json_t* json = e->toJson(TRI_UNKNOWN_MEM_ZONE);
if (json != nullptr) {
std::cout << "e as JSON:\n" <<
JsonHelper::toString(json) << std::endl;
cout << "e as JSON:\n" <<
JsonHelper::toString(json) << endl;
}
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = f->toJson(TRI_UNKNOWN_MEM_ZONE);
if (json != nullptr) {
std::cout << "f as JSON:\n" <<
JsonHelper::toString(json) << std::endl;
cout << "f as JSON:\n" <<
JsonHelper::toString(json) << endl;
}
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
delete f; // should not leave a leak
auto ec = new EnumerateCollectionPlan(nullptr, "guck");
Json jjj(ec->toJson());
cout << jjj.toString() << endl;
auto li = new LimitPlan(ec, 12, 17);
jjj = li->toJson();
cout << jjj.toString() << endl;
json = Json(12);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(true);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(Json::Null);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(Json::String);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(Json::List);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(Json::Array);
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
json = Json(Json::Array, 10)
@ -182,7 +228,7 @@ void testExecutionPlans () {
("myarray", Json(Json::Array, 2)
("a",Json("hallo"))
("b",Json(13)));
std::cout << JsonHelper::toString(json) << std::endl;
cout << JsonHelper::toString(json) << endl;
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
Json j(Json::Array);
@ -193,14 +239,22 @@ void testExecutionPlans () {
("d", Json(Json::Array)
("x", Json(12))
("y", Json(true)));
std::cout << j.toString() << std::endl;
cout << j.toString() << endl;
std::cout << j.get("a").toString() << std::endl;
// We expect to see exactly two copies here:
Json jjjj = j.copy(); // create an explicit copy
Json jj(12);
cout << "Before assignment" << jj.toString() << endl;
jj = j; // this steals the pointer from j
Json k = j.get("c");
cout << jjjj.toString();
cout << jj.toString();
Json k = jj.get("c");
Json l = k.at(2);
std::cout << l.toString() << std::endl;
cout << l.toString() << endl;
}
// Local Variables:

View File

@ -31,6 +31,7 @@
#include <Basics/Common.h>
#include <BasicsC/json.h>
#include <Basics/JsonHelper.h>
#include <VocBase/voc-types.h>
#include <VocBase/vocbase.h>
@ -160,10 +161,11 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON
/// @brief export to JSON, returns an AUTOFREE Json object
////////////////////////////////////////////////////////////////////////////////
virtual TRI_json_t* toJson (TRI_memory_zone_t* zone);
virtual triagens::basics::Json toJson (
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert to a string, basically for debugging purposes
@ -185,18 +187,24 @@ namespace triagens {
};
// -----------------------------------------------------------------------------
// --SECTION-- class EnumerateCollectionPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief class EnumerateCollectionPlan, derived from ExecutionPlan
////////////////////////////////////////////////////////////////////////////////
class EnumerateCollectionPlan : ExecutionPlan {
class EnumerateCollectionPlan : public ExecutionPlan {
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor with just a collection ID
/// @brief constructor with a vocbase and a collection name
////////////////////////////////////////////////////////////////////////////////
EnumerateCollectionPlan (TRI_vocbase_t* vocbase, TRI_voc_cid_t cid)
: ExecutionPlan(), _vocbase(vocbase), _cid(cid) {
public:
EnumerateCollectionPlan (TRI_vocbase_t* vocbase, std::string collname)
: ExecutionPlan(), _vocbase(vocbase), _collname(collname) {
}
////////////////////////////////////////////////////////////////////////////////
@ -219,20 +227,91 @@ namespace triagens {
/// @brief export to JSON
////////////////////////////////////////////////////////////////////////////////
virtual TRI_json_t* toJson (TRI_memory_zone_t* zone);
virtual triagens::basics::Json toJson (
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief our dependent nodes
/// @brief we need to know the database and the collection
////////////////////////////////////////////////////////////////////////////////
private:
TRI_vocbase_t* _vocbase;
TRI_voc_cid_t _cid;
std::string _collname;
};
// -----------------------------------------------------------------------------
// --SECTION-- class EnumerateCollectionPlan
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief class LimitPlan, derived from ExecutionPlan
////////////////////////////////////////////////////////////////////////////////
class LimitPlan : public ExecutionPlan {
////////////////////////////////////////////////////////////////////////////////
/// @brief constructors for various arguments, always with offset and limit
////////////////////////////////////////////////////////////////////////////////
public:
LimitPlan (size_t o, size_t l)
: ExecutionPlan(), _offset(o), _limit(l) {
}
LimitPlan (ExecutionPlan* ep, size_t o, size_t l)
: ExecutionPlan(ep), _offset(o), _limit(l) {
}
LimitPlan (size_t l)
: ExecutionPlan(), _offset(0), _limit(l) {
}
LimitPlan (ExecutionPlan* ep, size_t l)
: ExecutionPlan(ep), _offset(0), _limit(l) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the type of the node
////////////////////////////////////////////////////////////////////////////////
virtual NodeType getType () {
return LIMIT;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the type of the node as a string
////////////////////////////////////////////////////////////////////////////////
virtual std::string getTypeString () {
return std::string("LimitPlan");
}
////////////////////////////////////////////////////////////////////////////////
/// @brief export to JSON
////////////////////////////////////////////////////////////////////////////////
virtual triagens::basics::Json toJson (
TRI_memory_zone_t* zone = TRI_UNKNOWN_MEM_ZONE);
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief we need to know the offset and limit
////////////////////////////////////////////////////////////////////////////////
private:
size_t _offset;
size_t _limit;
};
} // namespace triagens::aql

View File

@ -217,7 +217,7 @@ namespace triagens {
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Json, a class to fabricate TRI_json_t* conveniently
/// @brief JsonException, an exception class for the Json class
////////////////////////////////////////////////////////////////////////////////
class JsonException : std::exception {
@ -232,10 +232,18 @@ namespace triagens {
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Json, a class to fabricate TRI_json_t* conveniently
////////////////////////////////////////////////////////////////////////////////
class Json {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief enum for the type of a Json structure
////////////////////////////////////////////////////////////////////////////////
enum type_e {
Null,
Bool,
@ -245,11 +253,19 @@ namespace triagens {
Array
};
////////////////////////////////////////////////////////////////////////////////
/// @brief enum to say whether we are automatically freeing the TRI_json_t*
////////////////////////////////////////////////////////////////////////////////
enum autofree_e {
AUTOFREE,
NOFREE
};
////////////////////////////////////////////////////////////////////////////////
/// @brief internal helper for the generic constructor
////////////////////////////////////////////////////////////////////////////////
private:
void make (type_e t, size_t size_hint) {
@ -278,33 +294,61 @@ namespace triagens {
}
}
// -----------------------------------------------------------------------------
// --SECTION-- public constructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief default constructor making an empty Json
////////////////////////////////////////////////////////////////////////////////
public:
Json ()
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(AUTOFREE) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generic constructor for a type_e
////////////////////////////////////////////////////////////////////////////////
Json (type_e t, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
make(t, 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generic constructor for a memzone and a type_e
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, type_e t, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
make(t, 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generic constructor for a type_e with a size hint
////////////////////////////////////////////////////////////////////////////////
Json (type_e t, size_t size_hint, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
make(t, size_hint);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief generic constructor for a memzone, a type_e and a size hint
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, type_e t, size_t size_hint,
autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
make(t, size_hint);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a bool
////////////////////////////////////////////////////////////////////////////////
Json (bool x, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateBooleanJson(_zone, x);
@ -313,6 +357,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and a bool
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, bool x, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateBooleanJson(_zone, x);
@ -321,6 +369,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for an int32_t
////////////////////////////////////////////////////////////////////////////////
Json (int32_t x, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateNumberJson(_zone, static_cast<double>(x));
@ -329,6 +381,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and an int32_t
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, int32_t x, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateNumberJson(_zone, static_cast<double>(x));
@ -337,6 +393,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a double
////////////////////////////////////////////////////////////////////////////////
Json (double x, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateNumberJson(_zone, x);
@ -345,6 +405,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and a double
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, double x, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateNumberJson(_zone, x);
@ -353,6 +417,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a char const*
////////////////////////////////////////////////////////////////////////////////
Json (char const* x, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateStringCopyJson(_zone, x);
@ -361,6 +429,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and a char const*
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, char const* x, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateStringCopyJson(_zone, x);
@ -369,6 +441,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a string
////////////////////////////////////////////////////////////////////////////////
Json (std::string const x, autofree_e autofree = AUTOFREE)
: _zone(TRI_UNKNOWN_MEM_ZONE), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateString2CopyJson(_zone, x.c_str(), x.size());
@ -377,6 +453,10 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and a string
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, std::string const x, autofree_e autofree = AUTOFREE)
: _zone(z), _json(nullptr), _autofree(autofree) {
_json = TRI_CreateString2CopyJson(_zone, x.c_str(), x.size());
@ -385,31 +465,63 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor for a memzone and a TRI_json_t*
////////////////////////////////////////////////////////////////////////////////
Json (TRI_memory_zone_t* z, TRI_json_t* j, autofree_e autofree = AUTOFREE)
: _zone(z), _json(j), _autofree(autofree) {
}
Json (Json const& j)
: _zone(j._zone), _json(nullptr), _autofree(j._autofree) {
std::cout << "Copy constructor called!" << std::endl;
if (_autofree == AUTOFREE) {
_json = TRI_CopyJson(_zone, j._json);
}
else {
_json = j._json;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief "copy" constructor, note that in the AUTOFREE case this steals
/// the structure from j to allow returning Json objects by value without
/// copying the whole structure.
////////////////////////////////////////////////////////////////////////////////
Json (Json& j)
: _zone(j._zone), _json(j.steal()), _autofree(j._autofree) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief move constructor, note that in the AUTOFREE case this steals
/// the structure from j to allow returning Json objects by value without
/// copying the whole structure.
////////////////////////////////////////////////////////////////////////////////
Json (Json&& j)
: _zone(j._zone), _json(j.steal()), _autofree(j._autofree) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
~Json () throw() {
if (_json != nullptr && _autofree == AUTOFREE) {
TRI_FreeJson(_zone, _json);
}
}
TRI_json_t* json () throw() {
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief return internal TRI_json_t*, this does not change the ownership
/// of the pointer
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* json () const throw() {
return _json;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief steal the TRI_json_t*, that is, in the AUTOFREE case the pointer
/// _json is changed to a nullptr. This is used in the copy and the move
/// constructor and in the cast operator to TRI_json_t*.
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* steal () throw() {
TRI_json_t* res = _json;
if (_autofree == AUTOFREE) {
@ -418,23 +530,70 @@ namespace triagens {
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief type cast operator to TRI_json_t*, this steals the pointer
////////////////////////////////////////////////////////////////////////////////
operator TRI_json_t* () throw() {
return steal();
}
Json& operator= (Json const& j) {
////////////////////////////////////////////////////////////////////////////////
/// @brief assignment operator, note that, as the copy constructor, this
/// has steal semantics, which avoids deep copies in situations that
/// people will use. If you need an actual copy, use the copy method.
////////////////////////////////////////////////////////////////////////////////
Json& operator= (Json& j) {
if (_json != nullptr && _autofree == AUTOFREE) {
TRI_FreeJson(_zone, _json);
}
_zone = j._zone;
_autofree = j._autofree;
_json = j._json;
if (j._autofree == AUTOFREE) {
j._autofree = NOFREE;
}
_json = j.steal();
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief move assignment operator, this has steal semantics.
////////////////////////////////////////////////////////////////////////////////
Json& operator= (Json&& j) {
if (_json != nullptr && _autofree == AUTOFREE) {
TRI_FreeJson(_zone, _json);
}
_zone = j._zone;
_autofree = j._autofree;
_json = j.steal();
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief copy recursively, even if NOFREE is set!
////////////////////////////////////////////////////////////////////////////////
Json copy () {
Json c;
c._zone = _zone;
if (_json != nullptr) {
c._json = TRI_CopyJson(_zone, _json);
}
else {
c._json = nullptr;
}
c._autofree = _autofree;
return c;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set an attribute value in an array, an exception is thrown
/// if *this is not a Json array. Note that you can call this with
/// a Json as second argument because of the automatic type conversion
/// to TRI_json_t* with steal semantics. Therefore
/// Json(Json::Array).set("a",Json(12)).set("b",Json(true))
/// is both legal and efficient.
////////////////////////////////////////////////////////////////////////////////
Json& set (char const* name, TRI_json_t* sub) {
if (! TRI_IsArrayJson(_json)) {
throw JsonException("Json is no array");
@ -443,6 +602,10 @@ namespace triagens {
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief this is a syntactic shortcut for the set method using operator()
////////////////////////////////////////////////////////////////////////////////
Json& operator() (char const* name, TRI_json_t* sub) {
if (! TRI_IsArrayJson(_json)) {
throw JsonException("Json is no array");
@ -451,6 +614,16 @@ namespace triagens {
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief append an Json value to the end of a Json list, an exception
/// is thrown if *this is not a Json list. Note that you can call this with
/// a Json as argument because of the automatic type conversion
/// to TRI_json_t* with steal semantics. Therefore
/// Json(Json::List).add(Json(12)).add(Json(13))
/// is both legal and efficient.
////////////////////////////////////////////////////////////////////////////////
Json& add (TRI_json_t* sub) {
if (! TRI_IsListJson(_json)) {
throw JsonException("Json is no list");
@ -459,6 +632,10 @@ namespace triagens {
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief this is a syntactic shortcut for the add method using operator()
////////////////////////////////////////////////////////////////////////////////
Json& operator() (TRI_json_t* sub) {
if (! TRI_IsListJson(_json)) {
throw JsonException("Json is no list");
@ -467,6 +644,15 @@ namespace triagens {
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief this gets an attribute value of a Json array. An exception is
/// thrown if *this is not a Json array. The resulting TRI_json_t* is
/// wrapped in a NOFREE Json to allow things like
/// j.get("a").get("b")
/// to access j.a.b. The ownership of the whole structure remains with
/// *this.
////////////////////////////////////////////////////////////////////////////////
Json get (char const* name) {
if (! TRI_IsArrayJson(_json)) {
throw JsonException("Json is no array");
@ -474,6 +660,16 @@ namespace triagens {
return Json(_zone, TRI_LookupArrayJson(_json, name), NOFREE);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief this gets a list entry of a Json list. An exception is
/// thrown if *this is not a Json list. The resulting TRI_json_t* is
/// wrapped in a NOFREE Json to allow things like
/// j.at(0).at(1)
/// to access j[0][1]. The ownership of the whole structure remains with
/// *this. If the position given is not bound, then an empty Json is
/// returned.
////////////////////////////////////////////////////////////////////////////////
Json at (int pos) {
if (! TRI_IsListJson(_json)) {
throw JsonException("Json is no list");
@ -504,42 +700,94 @@ namespace triagens {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is a Json that is equal to null.
////////////////////////////////////////////////////////////////////////////////
bool isNull () throw() {
return _json != nullptr && _json->_type == TRI_JSON_NULL;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is a boolean Json.
////////////////////////////////////////////////////////////////////////////////
bool isBoolean () throw() {
return TRI_IsBooleanJson(_json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is a number Json.
////////////////////////////////////////////////////////////////////////////////
bool isNumber () throw() {
return TRI_IsNumberJson(_json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is a string Json.
////////////////////////////////////////////////////////////////////////////////
bool isString () throw() {
return TRI_IsStringJson(_json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is an array Json.
////////////////////////////////////////////////////////////////////////////////
bool isArray () throw() {
return TRI_IsArrayJson(_json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is a list Json.
////////////////////////////////////////////////////////////////////////////////
bool isList () throw() {
return TRI_IsListJson(_json);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief checks whether *this is an empty Json (not even null).
////////////////////////////////////////////////////////////////////////////////
bool isEmpty () throw() {
return _json == nullptr;
}
string toString () {
return JsonHelper::toString(_json);
////////////////////////////////////////////////////////////////////////////////
/// @brief converts the Json recursively into a string.
////////////////////////////////////////////////////////////////////////////////
std::string toString () {
if (_json != nullptr) {
return JsonHelper::toString(_json);
}
else {
return std::string("");
}
}
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief store the memory zone used
////////////////////////////////////////////////////////////////////////////////
TRI_memory_zone_t* _zone;
////////////////////////////////////////////////////////////////////////////////
/// @brief the actual TRI_json_t*
////////////////////////////////////////////////////////////////////////////////
TRI_json_t* _json;
mutable autofree_e _autofree;
////////////////////////////////////////////////////////////////////////////////
/// @brief flag, whether we automatically free the TRI_json_t*.
////////////////////////////////////////////////////////////////////////////////
autofree_e _autofree;
};
}