Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2015 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
#include <ipaaca/ipaaca.h>
namespace ipaaca {
using namespace rsb;
using namespace rsb::filter;
using namespace rsb::converter;
using namespace rsb::patterns;
// temporary helper to show rapidjson internal type
std::string value_diagnosis(rapidjson::Value* val)
{
if (!val) return "nullptr";
if (val->IsNull()) return "null";
if (val->IsString()) return "string";
if (val->IsNumber()) return "number";
if (val->IsBool()) return "bool";
if (val->IsArray()) return "array";
if (val->IsObject()) return "object";
return "other";
}
IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const rapidjson::Value& val)//{{{
{
os << json_value_cast<std::string>(val);
return os;
}
//}}}
IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy)//{{{
{
if (proxy.json_value) os << *(proxy.json_value);
else os << "null";
return os;
}
//}}}
IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, PayloadDocumentEntry::ptr entry)//{{{
{
os << json_value_cast<std::string>(entry->document);
return os;
}
//}}}
IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{{
{
os << "{";
bool first = true;
for (auto& kv: obj._document_store) {
if (first) { first=false; } else { os << ", "; }

Ramin Yaghoubzadeh Torky
committed
os << "\"" << kv.first << "\":" << kv.second->to_json_string_representation() << "";
}
os << "}";
return os;
}
//}}}
double strict_numerical_interpretation(const std::string& str)
{
char* endptr;
auto s = str_trim(str);
const char* startptr = s.c_str();
long l = strtod(startptr, &endptr);
if ((*endptr)=='\0') {
// everything could be parsed
return l;
} else {
throw PayloadTypeConversionError();
}
}
IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v)
{
if (v.IsString()) return v.GetString();
if (v.IsNull()) return "";
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
v.Accept(writer);
return buffer.GetString();
}
IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v)
if (v.IsString()) return (long) strict_numerical_interpretation(v.GetString());
if (v.IsInt()) return v.GetInt();
if (v.IsUint()) return v.GetUint();
if (v.IsInt64()) return v.GetInt64();
if (v.IsUint64()) return v.GetUint64();
if (v.IsDouble()) return (long) v.GetDouble();
if (v.IsBool()) return v.GetBool() ? 1l : 0l;
if (v.IsNull()) return 0l;
// default: return parse of string version (should always be 0 though?)
throw PayloadTypeConversionError();
/*
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
v.Accept(writer);
return atol(std::string(buffer.GetString()).c_str());
*/
}
IPAACA_EXPORT template<> int json_value_cast(const rapidjson::Value& v)
{
if (v.IsString()) return (int) strict_numerical_interpretation(v.GetString());
if (v.IsInt()) return v.GetInt();
if (v.IsUint()) return v.GetUint();
if (v.IsInt64()) return v.GetInt64();
if (v.IsUint64()) return v.GetUint64();
if (v.IsDouble()) return (long) v.GetDouble();
if (v.IsBool()) return v.GetBool() ? 1l : 0l;
if (v.IsNull()) return 0l;
throw PayloadTypeConversionError();
IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v)
if (v.IsString()) return strict_numerical_interpretation(v.GetString());
if (v.IsDouble()) return v.GetDouble();
if (v.IsInt()) return (double) v.GetInt();
if (v.IsUint()) return (double) v.GetUint();
if (v.IsInt64()) return (double) v.GetInt64();
if (v.IsUint64()) return (double) v.GetUint64();
if (v.IsBool()) return v.GetBool() ? 1.0 : 0.0;
if (v.IsNull()) return 0.0;
throw PayloadTypeConversionError();
IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
{
if (v.IsString()) {
std::string s = v.GetString();
return !((s=="")||(s=="false")||(s=="False")||(s=="0"));
//return ((s=="1")||(s=="true")||(s=="True"));
}
if (v.IsBool()) return v.GetBool();
if (v.IsNull()) return false;
if (v.IsInt()) return v.GetInt() != 0;
if (v.IsUint()) return v.GetUint() != 0;
if (v.IsInt64()) return v.GetInt64() != 0;
if (v.IsUint64()) return v.GetUint64() != 0;
if (v.IsDouble()) return v.GetDouble() != 0.0;
// default: assume "pointer-like" semantics (i.e. objects are TRUE)
return true;
}
/*
* 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();
});
*/
//}}}
IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, int newvalue)
{
valueobject.SetInt(newvalue);
}
IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, long newvalue)
IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, double newvalue)
{
valueobject.SetDouble(newvalue);
}
IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, bool newvalue)
{
valueobject.SetBool(newvalue);
}
IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::string& newvalue)
{
valueobject.SetString(newvalue.c_str(), allocator);
}
IPAACA_EXPORT 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)
{
valueobject.SetArray();
for (auto& str: newvalue) {
rapidjson::Value sv;
sv.SetString(str, allocator);
valueobject.PushBack(sv, allocator);
}
}
IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::list<std::string>& newvalue)
{
IPAACA_IMPLEMENT_ME
}
IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::map<std::string, std::string>& newvalue)
{
IPAACA_IMPLEMENT_ME
}
*/
// PayloadDocumentEntry//{{{
IPAACA_EXPORT std::string PayloadDocumentEntry::to_json_string_representation()
{
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
document.Accept(writer);
return buffer.GetString();
}
IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_representation(const std::string& json_str)
{
PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
if (entry->document.Parse(json_str.c_str()).HasParseError()) {
throw JsonParsingError();
}

Ramin Yaghoubzadeh Torky
committed
//entry->json_source = json_str;
IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_unquoted_string_value(const std::string& str)
{
PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
entry->document.SetString(str.c_str(), entry->document.GetAllocator());

Ramin Yaghoubzadeh Torky
committed
//entry->update_json_source();
return entry;
}
/// update json_source after a write operation (on newly cloned entries)

Ramin Yaghoubzadeh Torky
committed
/*
IPAACA_EXPORT void PayloadDocumentEntry::update_json_source()
{
json_source = to_json_string_representation();
}

Ramin Yaghoubzadeh Torky
committed
*/
IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null()
{
PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();

Ramin Yaghoubzadeh Torky
committed
//entry->json_source = "null"; // rapidjson::Document value is also null implicitly
IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::clone()

Ramin Yaghoubzadeh Torky
committed
//auto entry = PayloadDocumentEntry::from_json_string_representation(this->json_source);
auto entry = PayloadDocumentEntry::create_null();
entry->document.CopyFrom(this->document, entry->document.GetAllocator());
IPAACA_DEBUG("Cloned for copy-on-write, contents: " << entry)
return entry;
IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep)
{
if (!(pep->parent)) {
return document;
}
rapidjson::Value& parent_value = get_or_create_nested_value_from_proxy_path(pep->parent);
if (pep->addressed_as_array) {
IPAACA_DEBUG("Addressed as array with index " << pep->addressed_index)
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
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_DEBUG("Addressed as dict with key " << pep->addressed_key)
// addressed as object (dict)
//rapidjson::Value& parent_value = *(pep->parent->json_value);
if (! parent_value.IsObject()) {
IPAACA_DEBUG("parent is not of type Object")
throw PayloadAddressingError();
} else {
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
//Value key;
//key.SetString(pep->addressed_key, allocator);
//parent_value.AddMember(key, *json_value, allocator);
rapidjson::Value key;
key.SetString(pep->addressed_key, allocator);
auto it = parent_value.FindMember(key);
if (it != parent_value.MemberEnd()) {
return parent_value[key];
} else {
rapidjson::Value val;
parent_value.AddMember(key, val, allocator);
rapidjson::Value rkey;
rkey.SetString(pep->addressed_key, allocator);
return parent_value[rkey];
// PayloadEntryProxy//{{{
IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents()
{
rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator();
PayloadEntryProxy* pep = this;
while (!(pep->existent) && pep->parent) { // only if not top-level
if (pep->addressed_as_array) {
rapidjson::Value& parent_value = *(pep->parent->json_value);
if (! parent_value.IsArray()) {
throw PayloadAddressingError();
} else {
long idx = pep->addressed_index;
long s = parent_value.Size();
if (idx<s) {
parent_value[idx] = *json_value;
} else {
throw PayloadAddressingError();
}
}
/*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 {
// addressed as object (dict)
rapidjson::Value& parent_value = *(pep->parent->json_value);
if (! parent_value.IsObject()) {
throw PayloadAddressingError();
} else {
Value key;
key.SetString(pep->addressed_key, allocator);
parent_value.AddMember(key, *json_value, allocator);
}
}
// repeat for next parent in the tree
pep = pep->parent;
}
}
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key)
: _payload(payload), _key(key), parent(nullptr)
{
document_entry = _payload->get_entry(key);
json_value = &(document_entry->document);
}
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, const std::string& addr_key_)
: parent(parent_), addressed_key(addr_key_), addressed_as_array(false)
{
_payload = parent->_payload;
_key = parent->_key;
document_entry = parent->document_entry;
auto it = parent->json_value->FindMember(addr_key_.c_str());
json_value = &(parent->json_value->operator[](addr_key_.c_str()));
existent = true;
} else {
json_value = nullptr; // avoid heap construction here
existent = false;
}
}
IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(PayloadEntryProxy* parent_, size_t addr_idx_)
: parent(parent_), addressed_index(addr_idx_), addressed_as_array(true)
{
_payload = parent->_payload;
_key = parent->_key;
document_entry = parent->document_entry;
json_value = &(parent->json_value->operator[](addr_idx_));
existent = true;
}
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_)
{
IPAACA_DEBUG("Invalid json_value!")
throw PayloadAddressingError();
}
if (! json_value->IsObject()) {
IPAACA_DEBUG("Expected Object for operator[](string)!")
return PayloadEntryProxy(this, addr_key_);
}
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](size_t addr_idx_)
{
IPAACA_DEBUG("Invalid json_value!")
throw PayloadAddressingError();
}
if (! json_value->IsArray()) {
IPAACA_DEBUG("Expected Array for operator[](size_t)!")
IPAACA_DEBUG("Array out of bounds!")
return PayloadEntryProxy(this, addr_idx_);

Ramin Yaghoubzadeh Torky
committed
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](int addr_idx_)
{
if (addr_idx_ < 0) {
IPAACA_DEBUG("Negative index!")

Ramin Yaghoubzadeh Torky
committed
throw PayloadAddressingError();
}
return operator[]((size_t) addr_idx_);
}
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const PayloadEntryProxy& otherproxy)
{
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);
auto valueptr = otherproxy.json_value;
if (valueptr) { // only set if value is valid, keep default null value otherwise
newval.CopyFrom(*valueptr, new_entry->document.GetAllocator());
}

Ramin Yaghoubzadeh Torky
committed
//new_entry->update_json_source();
_payload->set(_key, new_entry);
return *this;
}
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value)
{
//std::cout << "operator=(string)" << std::endl;
IPAACA_IMPLEMENT_ME
//_payload->set(_key, value);
return *this;
}
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const char* value)
{
//std::cout << "operator=(const char*)" << std::endl;
IPAACA_IMPLEMENT_ME
//_payload->set(_key, value);
return *this;
}
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(double value)
{
//std::cout << "operator=(double)" << std::endl;
IPAACA_IMPLEMENT_ME
//_payload->set(_key, boost::lexical_cast<std::string>(value));
return *this;
}
IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(bool value)
{
//std::cout << "operator=(bool)" << std::endl;
IPAACA_IMPLEMENT_ME
//_payload->set(_key, boost::lexical_cast<std::string>(value));
return *this;
}

Ramin Yaghoubzadeh Torky
committed
IPAACA_EXPORT PayloadEntryProxy::operator std::string()
return json_value_cast<std::string>(json_value);
//PayloadEntryProxy::get<std::string>();

Ramin Yaghoubzadeh Torky
committed
}
IPAACA_EXPORT PayloadEntryProxy::operator long()
return json_value_cast<long>(json_value);
//return PayloadEntryProxy::get<long>();
IPAACA_EXPORT PayloadEntryProxy::operator double()
return json_value_cast<double>(json_value);
//return PayloadEntryProxy::get<double>();
IPAACA_EXPORT PayloadEntryProxy::operator bool()
return json_value_cast<bool>(json_value);
//return PayloadEntryProxy::get<bool>();
IPAACA_EXPORT std::string PayloadEntryProxy::to_str()
return json_value_cast<std::string>(json_value);
//return PayloadEntryProxy::get<std::string>();
IPAACA_EXPORT long PayloadEntryProxy::to_long()
return json_value_cast<long>(json_value);
//return PayloadEntryProxy::get<long>();
IPAACA_EXPORT double PayloadEntryProxy::to_float()
return json_value_cast<double>(json_value);
//return PayloadEntryProxy::get<double>();
IPAACA_EXPORT bool PayloadEntryProxy::to_bool()
return json_value_cast<bool>(json_value);
//return PayloadEntryProxy::get<bool>();
IPAACA_EXPORT PayloadEntryProxyMapDecorator PayloadEntryProxy::as_map()
{
if (json_value && json_value->IsObject()) return PayloadEntryProxyMapDecorator(this);
throw PayloadTypeConversionError();
}
IPAACA_EXPORT PayloadEntryProxyListDecorator PayloadEntryProxy::as_list()
{
if (json_value && json_value->IsArray()) return PayloadEntryProxyListDecorator(this);
throw PayloadTypeConversionError();
}
IPAACA_EXPORT size_t PayloadEntryProxy::size()
{
if (!json_value) return 0;
if (json_value->IsArray()) return json_value->Size();
if (json_value->IsObject()) return json_value->MemberCount();
return 0;
}
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
IPAACA_EXPORT bool PayloadEntryProxy::is_null()
{
return (!json_value) || json_value->IsNull();
}
IPAACA_EXPORT bool PayloadEntryProxy::is_string()
{
return json_value && json_value->IsString();
}
/// is_number => whether it is *interpretable* as
/// a numerical value (i.e. including conversions)
IPAACA_EXPORT bool PayloadEntryProxy::is_number()
{
if (!json_value) return false;
try {
double dummy = json_value_cast<double>(*json_value);
return true;
} catch (PayloadTypeConversionError& ex) {
return false;
}
}
IPAACA_EXPORT bool PayloadEntryProxy::is_list()
{
return json_value && json_value->IsArray();
}
IPAACA_EXPORT bool PayloadEntryProxy::is_map()
{
return json_value && json_value->IsObject();
}
//
// new stuff for protocol v2
//
IPAACA_EXPORT template<> std::string PayloadEntryProxy::get<std::string>()
if (!json_value) return "";
//IPAACA_INFO( value_diagnosis(json_value) )
if (json_value->IsString()) return json_value->GetString();
if (json_value->IsNull()) return "";
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
json_value->Accept(writer);
return buffer.GetString();
//return _payload->get(_key);
IPAACA_EXPORT template<> long PayloadEntryProxy::get<long>()
{
return atof(operator std::string().c_str());
}
IPAACA_EXPORT template<> double PayloadEntryProxy::get<double>()
{
return atol(operator std::string().c_str());
}
IPAACA_EXPORT template<> bool PayloadEntryProxy::get<bool>()
{
std::string s = operator std::string();
return ((s=="1")||(s=="true")||(s=="True"));
}
// complex types
IPAACA_EXPORT template<> std::list<std::string> PayloadEntryProxy::get<std::list<std::string> >()
{
std::list<std::string> l;
l.push_back(PayloadEntryProxy::get<std::string>());
return l;
}
IPAACA_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get<std::vector<std::string> >()
{
std::vector<std::string> v;
v.push_back(PayloadEntryProxy::get<std::string>());
return v;
}
IPAACA_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get<std::map<std::string, std::string> >()
{
std::map<std::string, std::string> m;
m["__automatic__"] = PayloadEntryProxy::get<std::string>();
return m;
}
//}}}
// Payload//{{{
IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu)
{
_iu = boost::weak_ptr<IUInterface>(iu);
}
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] = json_value_cast<std::string>(pair.second->document);
IPAACA_EXPORT void Payload::_internal_set(const std::string& k, PayloadDocumentEntry::ptr v, const std::string& writer_name) {
std::map<std::string, PayloadDocumentEntry::ptr> _new;
std::vector<std::string> _remove;
_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
IPAACA_DEBUG(" Setting local payload item \"" << k << "\" to " << v)
mark_revision_change();
}
IPAACA_EXPORT void Payload::_internal_remove(const std::string& k, const std::string& writer_name) {
std::map<std::string, PayloadDocumentEntry::ptr> _new;
std::vector<std::string> _remove;
_remove.push_back(k);
_iu.lock()->_modify_payload(true, _new, _remove, writer_name );
mark_revision_change();
IPAACA_EXPORT void Payload::_internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name)
{
std::vector<std::string> _remove;
_iu.lock()->_modify_payload(false, new_contents, _remove, writer_name );
mark_revision_change();
IPAACA_EXPORT void Payload::_internal_merge(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::string& writer_name)
{
std::vector<std::string> _remove;
_iu.lock()->_modify_payload(true, contents_to_merge, _remove, writer_name );
for (auto& kv: contents_to_merge) {
_document_store[kv.first] = kv.second;
}
mark_revision_change();
//_document_store.insert(contents_to_merge.begin(), contents_to_merge.end());
//for (std::map<std::string, std::string>::iterator it = contents_to_merge.begin(); it!=contents_to_merge.end(); i++) {
// _store[it->first] = it->second;
//}
}
IPAACA_EXPORT PayloadDocumentEntry::ptr Payload::get_entry(const std::string& k) {
if (_document_store.count(k)>0) return _document_store[k];
else return PayloadDocumentEntry::create_null(); // contains Document with 'null' value
}
IPAACA_EXPORT std::string Payload::get(const std::string& k) { // DEPRECATED
if (_document_store.count(k)>0) return _document_store[k]->document.GetString();
return "";
IPAACA_EXPORT void Payload::set(const std::map<std::string, std::string>& all_elems)
{
std::map<std::string, PayloadDocumentEntry::ptr> newmap;
for (auto& kv: all_elems) {
/*PayloadDocumentEntry::ptr newit = PayloadDocumentEntry::create_null();
newit->document.SetString(kv.second, newit->document.GetAllocator());
newit->update_json_source();
newmap[kv.first] = newit;*/
newmap[kv.first] = PayloadDocumentEntry::from_unquoted_string_value(kv.second);
}
_internal_replace_all(newmap);
}
IPAACA_EXPORT void Payload::_remotely_enforced_wipe()
{
mark_revision_change();
}
IPAACA_EXPORT void Payload::_remotely_enforced_delitem(const std::string& k)
{
mark_revision_change();
IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry)
mark_revision_change();
}
IPAACA_EXPORT PayloadIterator Payload::begin()
{
return PayloadIterator(this, _document_store.begin());
}
IPAACA_EXPORT PayloadIterator Payload::end()
{
return PayloadIterator(this, _document_store.end());
}
//}}}
// PayloadIterator//{{{
IPAACA_EXPORT PayloadIterator::PayloadIterator(Payload* payload, PayloadDocumentStore::iterator&& ref_it)
: _payload(payload), reference_payload_revision(payload->internal_revision), raw_iterator(std::move(ref_it))
{
}
IPAACA_EXPORT PayloadIterator::PayloadIterator(const PayloadIterator& iter)
: _payload(iter._payload), reference_payload_revision(iter.reference_payload_revision), raw_iterator(iter.raw_iterator)
{
}
IPAACA_EXPORT PayloadIterator& PayloadIterator::operator++()
{
if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
++raw_iterator;
return *this;
}
IPAACA_EXPORT std::pair<std::string, PayloadEntryProxy> PayloadIterator::operator*()
{
if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
if (raw_iterator == _payload->_document_store.end()) throw PayloadIteratorInvalidError();
return std::pair<std::string, PayloadEntryProxy>(raw_iterator->first, PayloadEntryProxy(_payload, raw_iterator->first));
}
IPAACA_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > PayloadIterator::operator->()
{
if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
if (raw_iterator == _payload->_document_store.end()) throw PayloadIteratorInvalidError();
return std::make_shared<std::pair<std::string, PayloadEntryProxy> >(raw_iterator->first, PayloadEntryProxy(_payload, raw_iterator->first));
}
IPAACA_EXPORT bool PayloadIterator::operator==(const PayloadIterator& ref)
{
if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
return (raw_iterator==ref.raw_iterator);
}
IPAACA_EXPORT bool PayloadIterator::operator!=(const PayloadIterator& ref)
{
if (_payload->revision_changed(reference_payload_revision)) throw PayloadIteratorInvalidError();
return (raw_iterator!=ref.raw_iterator);
}
//}}}
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
// PayloadEntryProxyMapIterator//{{{
IPAACA_EXPORT PayloadEntryProxyMapIterator::PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy_, RawIterator&& raw_iter)
: proxy(proxy_), raw_iterator(std::move(raw_iter))
{
}
IPAACA_EXPORT PayloadEntryProxyMapIterator& PayloadEntryProxyMapIterator::operator++()
{
// prevent increase beyond end() ?
raw_iterator++;
return *this;
}
IPAACA_EXPORT std::pair<std::string, PayloadEntryProxy> PayloadEntryProxyMapIterator::operator*()
{
std::string key = raw_iterator->name.GetString();
return std::pair<std::string, PayloadEntryProxy>(key, (*proxy)[key] ); // generates child Proxy
}
IPAACA_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > PayloadEntryProxyMapIterator::operator->()
{
std::string key = raw_iterator->name.GetString();
return std::make_shared<std::pair<std::string, PayloadEntryProxy> >(key, (*proxy)[key] ); // generates child Proxy
}
IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator==(const PayloadEntryProxyMapIterator& other_iter)
{
return raw_iterator==other_iter.raw_iterator;
}
IPAACA_EXPORT bool PayloadEntryProxyMapIterator::operator!=(const PayloadEntryProxyMapIterator& other_iter)
{
return raw_iterator!=other_iter.raw_iterator;
}
//}}}
// PayloadEntryProxyMapDecorator//{{{
PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::begin()
{
return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberBegin());
}
PayloadEntryProxyMapIterator PayloadEntryProxyMapDecorator::end()
{
return PayloadEntryProxyMapIterator(proxy, proxy->json_value->MemberEnd());
}
//}}}
// PayloadEntryProxyListIterator//{{{
IPAACA_EXPORT PayloadEntryProxyListIterator::PayloadEntryProxyListIterator(PayloadEntryProxy* proxy_, size_t idx, size_t size_)
: proxy(proxy_), current_idx(idx), size(size_)
{
}
IPAACA_EXPORT PayloadEntryProxyListIterator& PayloadEntryProxyListIterator::operator++()
{
if (current_idx!=size) current_idx++;
return *this;
}
IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxyListIterator::operator*()
{
return (*proxy)[current_idx];
}
IPAACA_EXPORT std::shared_ptr<PayloadEntryProxy> PayloadEntryProxyListIterator::operator->()
{
return std::make_shared<PayloadEntryProxy>((*proxy)[current_idx]);
}
IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator==(const PayloadEntryProxyListIterator& other_iter)
{
return (proxy==other_iter.proxy) && (current_idx==other_iter.current_idx);
}
IPAACA_EXPORT bool PayloadEntryProxyListIterator::operator!=(const PayloadEntryProxyListIterator& other_iter)
{
return (current_idx!=other_iter.current_idx) || (proxy!=other_iter.proxy);
}
//}}}
// PayloadEntryProxyListDecorator//{{{
PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::begin()
{
return PayloadEntryProxyListIterator(proxy, 0, proxy->json_value->Size());
}
PayloadEntryProxyListIterator PayloadEntryProxyListDecorator::end()
{
size_t size = proxy->json_value->Size();
return PayloadEntryProxyListIterator(proxy, size, size);
}
//}}}
} // of namespace ipaaca