Skip to content
Snippets Groups Projects
Commit e6581ff2 authored by Ramin Yaghoubzadeh Torky's avatar Ramin Yaghoubzadeh Torky
Browse files

More work

parent 87282af6
No related branches found
No related tags found
No related merge requests found
......@@ -55,6 +55,7 @@ IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rap
IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, double);
IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, bool);
IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::string&);
IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const char*);
IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<T>& ts)
{
......@@ -102,104 +103,12 @@ IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{
IPAACA_HEADER_EXPORT inline ~PayloadDocumentEntry() { IPAACA_INFO("") }
//IPAACA_HEADER_EXPORT PayloadDocumentEntry(const std::string& source): modified(false), json_source(source), {};
IPAACA_HEADER_EXPORT std::string to_json_string_representation();
static std::shared_ptr<PayloadDocumentEntry> from_json_string_representation(const std::string& input);
static std::shared_ptr<PayloadDocumentEntry> create_null();
std::shared_ptr<PayloadDocumentEntry> clone();
IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> from_json_string_representation(const std::string& input);
IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> create_null();
IPAACA_HEADER_EXPORT std::shared_ptr<PayloadDocumentEntry> clone();
IPAACA_HEADER_EXPORT rapidjson::Value& get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep);
typedef std::shared_ptr<PayloadDocumentEntry> ptr;
};
//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
{
protected:
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node;
IPAACA_MEMBER_VAR_EXPORT Payload* _payload;
IPAACA_MEMBER_VAR_EXPORT std::string _key;
//
// new json stuff / hierarchical navigation
//
PayloadEntryProxy* parent; // parent (up to document root -> then null)
PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc
bool existent; // whether Value exists already (or blindly navigated)
bool addressed_as_array; // whether long or string navigation used
long addressed_index;
std::string addressed_key;
/// currently navigated value in json tree (or a new Null value)
rapidjson::Value* json_value;
protected:
IPAACA_HEADER_EXPORT void connect_to_existing_parents();
public:
// constructor to create a new top-most parent proxy (from a payload key)
IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key);
// constructors for navigation through objects
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key);
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index);
public:
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const std::string& key);
//
IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value);
IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const char* value);
IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(double value);
IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(bool value);
IPAACA_HEADER_EXPORT operator std::string();
IPAACA_HEADER_EXPORT operator long();
IPAACA_HEADER_EXPORT operator double();
IPAACA_HEADER_EXPORT operator bool();
IPAACA_HEADER_EXPORT template<typename Inner> operator std::vector<Inner>() {
if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
std::vector<Inner> result;
for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
result.push_back( json_value_cast<Inner>(*it) );
}
return result;
}
IPAACA_HEADER_EXPORT template<typename Inner> operator std::list<Inner>() {
if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
std::list<Inner> result;
for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
result.push_back( json_value_cast<Inner>(*it) );
}
return result;
}
IPAACA_HEADER_EXPORT template<typename Inner> operator std::map<std::string, Inner>() {
if ((!json_value) || (!json_value->IsObject())) throw PayloadAddressingError();
std::map<std::string, Inner> result;
for (auto it = json_value->MemberBegin(); it != json_value->MemberEnd(); ++it) {
result[std::string(it->name.GetString())] = json_value_cast<Inner>(it->value);
}
return result;
}
// FIXME why are these needed again?
IPAACA_HEADER_EXPORT std::string to_str();
//long to_int() { return operator long(); ;
IPAACA_HEADER_EXPORT long to_long();
IPAACA_HEADER_EXPORT double to_float();
IPAACA_HEADER_EXPORT bool to_bool();
// getters
IPAACA_HEADER_EXPORT template<typename T> T get() { return json_value_cast<T>(json_value); } // specializations below
// setters
IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& set(T t);
/*{
pack_into_json_value<T>(t);
connect_to_existing_parents();
_payload->set(key, document_entry->document);
}*/
};
// Available interpretations of payload entries (or children thereof) below.
// Usage of standard complex data structures (vector etc.) currently entails
// casting all entries to a uniform type (a-priori choice: std::string).
/*
IPAACA_HEADER_EXPORT template<> long PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> double PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> bool PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get();
*/
//}}}
/*
......@@ -300,4 +209,110 @@ IPAACA_HEADER_EXPORT class Payload//{{{
typedef boost::shared_ptr<Payload> ptr;
};//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
{
protected:
public:
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node;
IPAACA_MEMBER_VAR_EXPORT Payload* _payload;
IPAACA_MEMBER_VAR_EXPORT std::string _key;
//
// new json stuff / hierarchical navigation
//
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* parent; // parent (up to document root -> then null)
IPAACA_MEMBER_VAR_EXPORT PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc
IPAACA_MEMBER_VAR_EXPORT bool existent; // whether Value exists already (or blindly navigated)
IPAACA_MEMBER_VAR_EXPORT bool addressed_as_array; // whether long or string navigation used
IPAACA_MEMBER_VAR_EXPORT long addressed_index;
IPAACA_MEMBER_VAR_EXPORT std::string addressed_key;
/// currently navigated value in json tree (or a new Null value)
IPAACA_MEMBER_VAR_EXPORT rapidjson::Value* json_value;
/* protected:
IPAACA_HEADER_EXPORT void connect_to_existing_parents();
*/
public:
// constructor to create a new top-most parent proxy (from a payload key)
IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key);
// constructors for navigation through objects
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key);
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index);
public:
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const std::string& key);
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](const char* key);
//
IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& operator=(T t)
{
PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
rapidjson::Value& newval = new_entry->get_or_create_nested_value_from_proxy_path(this);
pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
_payload->set(_key, new_entry);
return *this;
}
//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value);
//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const char* value);
//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(double value);
//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(bool value);
IPAACA_HEADER_EXPORT operator std::string();
IPAACA_HEADER_EXPORT operator long();
IPAACA_HEADER_EXPORT operator double();
IPAACA_HEADER_EXPORT operator bool();
IPAACA_HEADER_EXPORT template<typename Inner> operator std::vector<Inner>() {
if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
std::vector<Inner> result;
for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
result.push_back( json_value_cast<Inner>(*it) );
}
return result;
}
IPAACA_HEADER_EXPORT template<typename Inner> operator std::list<Inner>() {
if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
std::list<Inner> result;
for (auto it = json_value->Begin(); it != json_value->End(); ++it) {
result.push_back( json_value_cast<Inner>(*it) );
}
return result;
}
IPAACA_HEADER_EXPORT template<typename Inner> operator std::map<std::string, Inner>() {
if ((!json_value) || (!json_value->IsObject())) throw PayloadAddressingError();
std::map<std::string, Inner> result;
for (auto it = json_value->MemberBegin(); it != json_value->MemberEnd(); ++it) {
result[std::string(it->name.GetString())] = json_value_cast<Inner>(it->value);
}
return result;
}
// FIXME why are these needed again?
IPAACA_HEADER_EXPORT std::string to_str();
//long to_int() { return operator long(); ;
IPAACA_HEADER_EXPORT long to_long();
IPAACA_HEADER_EXPORT double to_float();
IPAACA_HEADER_EXPORT bool to_bool();
// getters
IPAACA_HEADER_EXPORT template<typename T> T get() { return json_value_cast<T>(json_value); } // specializations below
// setters
IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& set(T t);
/*{
pack_into_json_value<T>(t);
connect_to_existing_parents();
_payload->set(key, document_entry->document);
}*/
};
// Available interpretations of payload entries (or children thereof) below.
// Usage of standard complex data structures (vector etc.) currently entails
// casting all entries to a uniform type (a-priori choice: std::string).
/*
IPAACA_HEADER_EXPORT template<> long PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> double PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> bool PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get();
IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get();
*/
//}}}
#endif
......@@ -35,11 +35,15 @@
namespace ipaaca {
IPAACA_EXPORT inline FakeIU::FakeIU() { IPAACA_INFO("") }
IPAACA_EXPORT inline FakeIU::FakeIU() {
IPAACA_INFO("")
}
IPAACA_EXPORT boost::shared_ptr<FakeIU> FakeIU::create()
{
IPAACA_INFO("");
return boost::shared_ptr<FakeIU>(new FakeIU());
auto iu = boost::shared_ptr<FakeIU>(new FakeIU());
iu->_payload.initialize(iu);
return iu;
}
IPAACA_EXPORT void FakeIU::add_fake_payload_item(const std::string& key, PayloadDocumentEntry::ptr entry)
{
......
......@@ -34,6 +34,8 @@
#include <ipaaca/ipaaca.h>
#include <ipaaca/ipaaca-json.h>
#include <iomanip>
using namespace rapidjson;
using namespace std;
......@@ -131,179 +133,25 @@ int main(int argc, char** argv) {
//iu->payload()["b"] = "newEntry";
//std::vector<long> vs = { 10, 20, 30, 40 };
std::map<std::string, double> vs = { {"A", 10}, {"B", 20}, {"C", 30}, {"D", 40} };
ipaaca::pack_into_json_value(entry->document, entry->document.GetAllocator(), vs);
{
//std::map<std::string, double> vs = { {"A", 10}, {"B", 20}, {"C", 30}, {"D", 40} };
//ipaaca::pack_into_json_value(entry->document, entry->document.GetAllocator(), vs);
std::cout << "Setting a value deep in the object:" << std::endl;
//iu->payload()["a"][(int)0] = "set by pep::op=";
iu->payload()["a"]["A"] = "set by pep::op=";
std::cout << "Final payload (printed as strings):" << std::endl;
std::map<std::string, std::string> pl_flat = iu->payload();
for (auto& kv: pl_flat) {
std::cout << " " << std::left << std::setw(15) << (kv.first+": ") << kv.second << std::endl;
}
/*{
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
entry->document.Accept(writer);
std::string docstring = buffer.GetString();
std::cout << "Final document: " << docstring << std::endl;
}
}*/
// Done
return 0;
////////////////////////////////////////////////////////////////////////////
// 1. Parse a JSON text string to a document.
const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4], \"dict\":{\"s\":\"stringvalue\", \"arr\":[6, 7, \"test\"]} } ";
printf("Original JSON:\n %s\n", json);
ipaaca::PayloadDocumentStore ds;
ds["document_test"] = std::make_shared<ipaaca::PayloadDocumentEntry>();
Document& document = ds["document_test"]->document;
//std::map<std::string, Document> documents;
//Document _document; // Default template parameter uses UTF8 and MemoryPoolAllocator.
//documents["document_test"] = std::move(_document);
//Document& document = documents["document_test"];
printf("Check whether document contains 'none' initially ...");
assert(document.IsNull()); // initial state of object
#if 1
// "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream().
if (document.Parse(json).HasParseError())
return 1;
#else
// In-situ parsing, decode strings directly in the source string. Source must be string.
{
char buffer[sizeof(json)];
memcpy(buffer, json, sizeof(json));
if (document.ParseInsitu(buffer).HasParseError())
return 1;
}
#endif
printf("\nParsing succeeded.\n");
////////////////////////////////////////////////////////////////////////////
assert(document.IsObject()); // testing dict here
assert(document.HasMember("dict"));
assert(document["dict"].IsObject());
assert(document["dict"].HasMember("s"));
assert(document["dict"]["s"].IsString());
assert(document["dict"].HasMember("arr"));
assert(document["dict"]["arr"].IsArray());
Value& arr = document["dict"]["arr"];
printf("dict.arr size: %d\n", arr.Size());
for (SizeType i = 0; i < arr.Size(); i++) {
if (arr[i].IsInt()) {
printf("a[%d] = %d\n", i, arr[i].GetInt());
} else {
printf("a[%d] = \"%s\"\n", i, arr[i].GetString());
}
}
puts("Putting new dict in array.\n");
Document::AllocatorType& allocator = document.GetAllocator();
Value dict;
Value insertstr;
insertstr.SetString("testvalue", allocator);
dict.SetObject();
dict.AddMember("testkey", insertstr, allocator);
arr.PushBack(dict, allocator);
Value newint;
newint.SetInt(12345);
document["i"] = newint;
puts("Done.\n");
// ->Assertion failed in []:
// Value& nonexisting = document["dict"]["NONEXISTING"];
#if 0
// 2. Access values in document.
printf("\nAccess values in document:\n");
assert(document.IsObject()); // Document is a JSON value represents the root of DOM. Root can be either an object or array.
assert(document.HasMember("hello"));
assert(document["hello"].IsString());
printf("hello = %s\n", document["hello"].GetString());
// Since version 0.2, you can use single lookup to check the existing of member and its value:
Value::MemberIterator hello = document.FindMember("hello");
assert(hello != document.MemberEnd());
assert(hello->value.IsString());
assert(strcmp("world", hello->value.GetString()) == 0);
(void)hello;
assert(document["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue().
printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
assert(document["f"].IsBool());
printf("f = %s\n", document["f"].GetBool() ? "true" : "false");
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type.
assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true.
printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
printf("pi = %g\n", document["pi"].GetDouble());
{
const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster.
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t.
printf("a[%d] = %d\n", i, a[i].GetInt());
int y = a[0].GetInt();
(void)y;
// Iterating array with iterators
printf("a = ");
for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
printf("%d ", itr->GetInt());
printf("\n");
}
// Iterating object members
static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr)
printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]);
////////////////////////////////////////////////////////////////////////////
// 3. Modify values in document.
// Change i to a bigger number
{
uint64_t f20 = 1; // compute factorial of 20
for (uint64_t j = 1; j <= 20; j++)
f20 *= j;
document["i"] = f20; // Alternate form: document["i"].SetUint64(f20)
assert(!document["i"].IsInt()); // No longer can be cast as int or uint.
}
// Adding values to array.
{
Value& a = document["a"]; // This time we uses non-const reference.
Document::AllocatorType& allocator = document.GetAllocator();
for (int i = 5; i <= 10; i++)
a.PushBack(i, allocator); // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.
// Fluent API
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
}
// Making string values.
// This version of SetString() just store the pointer to the string.
// So it is for literal and string that exists within value's life-cycle.
{
document["hello"] = "rapidjson"; // This will invoke strlen()
// Faster version:
// document["hello"].SetString("rapidjson", 9);
}
// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
Value author;
{
char buffer[10];
int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string.
author.SetString(buffer, static_cast<size_t>(len), document.GetAllocator());
// Shorter but slower version:
// document["hello"].SetString(buffer, document.GetAllocator());
// Constructor version:
// Value author(buffer, len, document.GetAllocator());
// Value author(buffer, document.GetAllocator());
memset(buffer, 0, sizeof(buffer)); // For demonstration purpose.
}
// Variable 'buffer' is unusable now but 'author' has already made a copy.
document.AddMember("author", author, document.GetAllocator());
assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.
////////////////////////////////////////////////////////////////////////////
#endif
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
document.Accept(writer);
std::string docstring = buffer.GetString();
std::cout << "FIRST DUMP: " << docstring << std::endl;
//// 4. Stringify JSON
//printf("\nModified JSON with reformatting:\n");
//FileStream f(stdout);
//PrettyWriter<FileStream> writer(f);
//document.Accept(writer); // Accept() traverses the DOM and generates Handler events.
return 0;
}
......@@ -142,6 +142,10 @@ IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject
{
valueobject.SetString(newvalue.c_str(), allocator);
}
IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const char* newvalue)
{
valueobject.SetString(newvalue, allocator);
}
/*
IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<std::string>& newvalue)
{
......@@ -185,16 +189,89 @@ IPAACA_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null
entry->json_source = "null"; // rapidjson::Document value is also null implicitly
return entry;
}
IPAACA_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::clone()
IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::clone()
{
IPAACA_INFO("")
return PayloadDocumentEntry::from_json_string_representation(this->json_source);
}
IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep)
{
if (!(pep->parent)) {
IPAACA_INFO("Reached top-most parent")
return document;
}
IPAACA_INFO("(Check parent)")
rapidjson::Value& parent_value = get_or_create_nested_value_from_proxy_path(pep->parent);
IPAACA_INFO("Resolving address path")
if (pep->addressed_as_array) {
IPAACA_INFO("Addressed as array with index " << pep->addressed_index)
if (! parent_value.IsArray()) {
throw PayloadAddressingError();
} else {
long idx = pep->addressed_index;
long s = parent_value.Size();
if (idx<s) {
return parent_value[idx];
} else {
throw PayloadAddressingError();
}
}
// for append / push_back? :
/*if (parent_value.IsNull()) {
wasnull = true;
parent_value.SetArray();
}
if (wasnull || parent_value.IsArray()) {
long idx = pep->addressed_index;
long s = parent_value.Size();
if (idx<s) {
// existing element modified
parent_value[idx] = *json_value;
} else {
// implicitly initialize missing elements to null values
if (idx>s) {
long missing_elements = pep->addressed_index - p;
for (int i=0; i<missing_elements; ++i) {
parent_value.PushBack(, allocator)
}
}
}
if (s ==
} else {
throw PayloadAddressingError();
}*/
} else {
IPAACA_INFO("Addressed as dict with key " << pep->addressed_key)
// addressed as object (dict)
//rapidjson::Value& parent_value = *(pep->parent->json_value);
if (! parent_value.IsObject()) {
throw PayloadAddressingError();
} else {
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
//Value key;
//key.SetString(pep->addressed_key, allocator);
//parent_value.AddMember(key, *json_value, allocator);
Value key;
key.SetString(pep->addressed_key, allocator);
// FIXME LAST this complains
auto it = parent_value.FindMember(key);
if (it != parent_value.MemberEnd()) {
return parent_value[pep->addressed_key.c_str()];
} else {
rapidjson::Value val;
parent_value.AddMember(key, val, allocator);
return parent_value[key];
}
}
}
}
//}}}
// PayloadEntryProxy//{{{
// only if not top-level
#if 0
IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents()
{
rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator();
......@@ -251,55 +328,81 @@ IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents()
pep = pep->parent;
}
}
#endif
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key)
: _payload(payload), _key(key), parent(nullptr)
{
IPAACA_INFO("PEP construction on parent document ...")
document_entry = _payload->get_entry(key);
json_value = &(document_entry->document);
IPAACA_INFO("... parent done.")
}
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, const std::string& addr_key_)
: parent(parent_), addressed_key(addr_key_), addressed_as_array(false)
{
IPAACA_INFO("PEP construction as dict child, addressed by " << addr_key_ << " ...")
_payload = parent->_payload;
_key = parent->_key;
document_entry = parent->document_entry;
auto it = parent->json_value->FindMember(addr_key_.c_str());
if (it != json_value->MemberEnd()) {
if (it != parent->json_value->MemberEnd()) {
json_value = &(parent->json_value->operator[](addr_key_.c_str()));
existent = true;
} else {
json_value = nullptr; // avoid heap construction here
existent = false;
}
IPAACA_INFO("... dict child done.")
}
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, size_t addr_idx_)
: parent(parent_), addressed_index(addr_idx_), addressed_as_array(true)
{
IPAACA_INFO("PEP construction as array child, addressed by " << addr_idx_ << " ...")
_payload = parent->_payload;
_key = parent->_key;
document_entry = parent->document_entry;
json_value = &(parent->json_value->operator[](addr_idx_));
existent = true;
IPAACA_INFO("... array child done.")
}
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const char* addr_key_)
{
return operator[](std::string(addr_key_));
}
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const std::string& addr_key_)
{
if (!json_value) throw PayloadAddressingError();
if (! json_value->IsObject()) throw PayloadAddressingError();
if (!json_value) {
IPAACA_INFO("Invalid json_value!")
throw PayloadAddressingError();
}
if (! json_value->IsObject()) {
IPAACA_INFO("Expected Object for operator[](string)!")
throw PayloadAddressingError();
}
return PayloadEntryProxy(this, addr_key_);
}
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](size_t addr_idx_)
{
if (!json_value) throw PayloadAddressingError();
if (! json_value->IsArray()) throw PayloadAddressingError();
if (!json_value) {
IPAACA_INFO("Invalid json_value!")
throw PayloadAddressingError();
}
if (! json_value->IsArray()) {
IPAACA_INFO("Expected Array for operator[](size_t)!")
throw PayloadAddressingError();
}
long s = json_value->Size();
if (addr_idx_>=s) throw PayloadAddressingError();
if (addr_idx_>=s) {
IPAACA_INFO("Array out of bounds!")
throw PayloadAddressingError();
}
return PayloadEntryProxy(this, addr_idx_);
}
/*
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value)
{
//std::cout << "operator=(string)" << std::endl;
......@@ -328,6 +431,7 @@ IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(bool value)
//_payload->set(_key, boost::lexical_cast<std::string>(value));
return *this;
}
*/
IPAACA_EXPORT PayloadEntryProxy::operator std::string()
{
......@@ -443,11 +547,12 @@ IPAACA_EXPORT PayloadEntryProxy Payload::operator[](const std::string& key)
//boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key));
return PayloadEntryProxy(this, key);
}
IPAACA_EXPORT Payload::operator std::map<std::string, std::string>()
{
std::map<std::string, std::string> result;
std::for_each(_document_store.begin(), _document_store.end(), [&result](std::pair<std::string, PayloadDocumentEntry::ptr> pair) {
result[pair.first] = pair.second->document.GetString();
result[pair.first] = json_value_cast<std::string>(pair.second->document);
});
return result;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment