From b6d855c10896bfe06516e5456f1c28528db5a9fe Mon Sep 17 00:00:00 2001
From: Ramin Yaghoubzadeh <ryaghoubzadeh@uni-bielefeld.de>
Date: Sat, 28 Mar 2015 23:05:19 +0100
Subject: [PATCH] C++: added push_back() and extend() for proxy arguments

---
 ipaacalib/cpp/include/ipaaca/ipaaca-payload.h | 31 +++++++++++++++++--
 ipaacalib/cpp/src/ipaaca-json.cc              |  9 ++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
index aad0f3f..58386e7 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
@@ -505,8 +505,20 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 			list.PushBack(newval, new_entry->document.GetAllocator());
 			_payload->set(_key, new_entry);
 		}
-		/// Alias for push_back() (somewhat pythonic - since we also provide extend())
-		IPAACA_HEADER_EXPORT template<typename T> void append(T t) { push_back<T>(t); }
+		/// Append the value of another proxy (or a null value) to a list-type value
+		IPAACA_HEADER_EXPORT void push_back(const PayloadEntryProxy& otherproxy)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			rapidjson::Value newval;
+			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());
+			}
+			list.PushBack(newval, new_entry->document.GetAllocator());
+			_payload->set(_key, new_entry);
+		}
 		/// Extend a list-type payload value with a vector containing items of a supported type
 		IPAACA_HEADER_EXPORT template<typename T> void extend(const std::vector<T>& ts)
 		{
@@ -533,6 +545,21 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 			}
 			_payload->set(_key, new_entry);
 		}
+		/// Extend a list-type payload value with items (copies) from another list-type value
+		IPAACA_HEADER_EXPORT void extend(const PayloadEntryProxy& otherproxy)
+		{
+			if ((!json_value) || (!json_value->IsArray())) throw PayloadAddressingError();
+			if ((!otherproxy.json_value) || (!(otherproxy.json_value->IsArray()))) throw PayloadAddressingError();
+			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
+			rapidjson::Value& list = new_entry->get_or_create_nested_value_from_proxy_path(this);
+			for (size_t i=0; i<otherproxy.json_value->Size(); ++i) {
+				rapidjson::Value newval;
+				rapidjson::Value& value = (*(otherproxy.json_value))[i];
+				newval.CopyFrom(value, new_entry->document.GetAllocator());
+				list.PushBack(newval, new_entry->document.GetAllocator());
+			}
+			_payload->set(_key, new_entry);
+		}
 };
 // Available interpretations of payload entries (or children thereof) below.
 //  Usage of standard complex data structures (vector etc.) currently entails
diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc
index e0a0888..fb0aa13 100644
--- a/ipaacalib/cpp/src/ipaaca-json.cc
+++ b/ipaacalib/cpp/src/ipaaca-json.cc
@@ -66,6 +66,7 @@ int iterators_main(int argc, char** argv)//{{{
 	iu->payload()["d"] = 100;
 	iu->payload()["e"] = 3l;
 	iu->payload()["f"] = "12.5000";
+	iu->payload()["g"] = std::vector<std::string>{"g1", "g2"};
 	
 	std::cout << std::endl << "Iterate over payload" << std::endl;
 	for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) {
@@ -166,6 +167,14 @@ int iterators_main(int argc, char** argv)//{{{
 		std::cout << "  " << v << std::endl;
 	}
 	
+	std::cout << std::endl << "Extending payload['a'] by payload['g'] and appending payload['f']" << std::endl;
+	iu->payload()["a"].extend(iu->payload()["g"]);
+	iu->payload()["a"].push_back(iu->payload()["f"]);
+	std::cout << "Resulting entries in payload['a']:" << std::endl;
+	for (auto v: iu->payload()["a"].as_list()) {
+		std::cout << "  " << v << std::endl;
+	}
+	
 	return 0;
 }
 //}}}
-- 
GitLab