diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h index 66c61f8e6213662a638ac22bb407e4caf1b94c7a..353bce4b01d06c353d7e20da9728844e700aa210 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h @@ -38,6 +38,7 @@ #error "Please do not include this file directly, use ipaaca.h instead" #endif +// casting operators from Value& IPAACA_HEADER_EXPORT template<typename T> T json_value_cast(const rapidjson::Value&); IPAACA_HEADER_EXPORT template<typename T> T json_value_cast(const rapidjson::Value* value) { if (!value) return T(); return json_value_cast<T>(*value); } IPAACA_HEADER_EXPORT template<> long json_value_cast(const rapidjson::Value&); @@ -48,6 +49,47 @@ IPAACA_HEADER_EXPORT template<> std::vector<std::string> json_value_cast(const r IPAACA_HEADER_EXPORT template<> std::list<std::string> json_value_cast(const rapidjson::Value&); IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> json_value_cast(const rapidjson::Value&); +// helpers to set Value& from various standard types +IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, T t); +IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, long); +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<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<T>& ts) +{ + valueobject.SetArray(); + for (auto& val: ts) { + rapidjson::Value newv; + pack_into_json_value<T>(newv, allocator, val); + valueobject.PushBack(newv, allocator); + } +} +IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::list<T>& ts) +{ + valueobject.SetArray(); + for (auto& val: ts) { + rapidjson::Value newv; + pack_into_json_value<T>(newv, allocator, val); + valueobject.PushBack(newv, allocator); + } +} +IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::map<std::string, T>& ts) +{ + valueobject.SetObject(); + for (auto& val: ts) { + rapidjson::Value key; + key.SetString(val.first, allocator); + rapidjson::Value newv; + pack_into_json_value<T>(newv, allocator, val.second); + valueobject.AddMember(key, newv, allocator); + } +} +/*IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::vector<std::string>&); +IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::list<std::string>&); +IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::map<std::string, std::string>&); +*/ + // FIXME TODO locking / invalidating proxy on first write of a payload entry IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{ { @@ -62,6 +104,7 @@ IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{ 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(); typedef std::shared_ptr<PayloadDocumentEntry> ptr; }; //}}} @@ -85,8 +128,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ rapidjson::Value* json_value; protected: IPAACA_HEADER_EXPORT void connect_to_existing_parents(); - protected: - IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(T t); //specializations below public: // constructor to create a new top-most parent proxy (from a payload key) IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key); @@ -101,6 +142,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ 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(); @@ -158,14 +200,6 @@ IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get(); IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get(); */ -// value converters -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(long); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(double); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(bool); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::string&); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::vector<std::string>&); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::list<std::string>&); -IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(const std::map<std::string, std::string>&); //}}} /* diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc index f7c74deb71b696f8326e5536faef4aa1d9bfc022..d5dd285cc9b9aa6839da7bff1b25907998107adf 100644 --- a/ipaacalib/cpp/src/ipaaca-json.cc +++ b/ipaacalib/cpp/src/ipaaca-json.cc @@ -128,6 +128,19 @@ int main(int argc, char** argv) { std::cout << "(n/a)" << std::endl; } + //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); + { + 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; diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc index a50222677955212950048235a98934bf71918cc7..aeb95163905f0525325cc99c5d21cc5bf6d31ade 100644 --- a/ipaacalib/cpp/src/ipaaca-payload.cc +++ b/ipaacalib/cpp/src/ipaaca-payload.cc @@ -56,7 +56,7 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{ //}}} // json_value_cast//{{{ -IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v) +IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v) { if (v.IsString()) return v.GetString(); if (v.IsNull()) return ""; @@ -65,7 +65,7 @@ IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Val v.Accept(writer); return buffer.GetString(); } -IPAACA_HEADER_EXPORT template<> long json_value_cast(const rapidjson::Value& v) +IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v) { if (v.IsString()) return atol(std::string(v.GetString()).c_str()); if (v.IsInt()) return v.GetInt(); @@ -81,7 +81,7 @@ IPAACA_HEADER_EXPORT template<> long json_value_cast(const rapidjson::Value& v) v.Accept(writer); return atol(std::string(buffer.GetString()).c_str()); } -IPAACA_HEADER_EXPORT template<> double json_value_cast(const rapidjson::Value& v) +IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v) { if (v.IsString()) return atof(std::string(v.GetString()).c_str()); if (v.IsDouble()) return v.GetDouble(); @@ -97,7 +97,7 @@ IPAACA_HEADER_EXPORT template<> double json_value_cast(const rapidjson::Value& v v.Accept(writer); return atof(std::string(buffer.GetString()).c_str()); } -IPAACA_HEADER_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) +IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) { if (v.IsString()) { std::string s = v.GetString(); @@ -126,15 +126,51 @@ IPAACA_HEADER_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) */ //}}} +IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, long newvalue) +{ + valueobject.SetInt(newvalue); +} +IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, double newvalue) +{ + valueobject.SetDouble(newvalue); +} +IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, bool newvalue) +{ + valueobject.SetBool(newvalue); +} +IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::string& newvalue) +{ + valueobject.SetString(newvalue.c_str(), 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_HEADER_EXPORT inline std::string PayloadDocumentEntry::to_json_string_representation() +IPAACA_EXPORT inline std::string PayloadDocumentEntry::to_json_string_representation() { rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); document.Accept(writer); return buffer.GetString(); } -IPAACA_HEADER_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_representation(const std::string& json_str) +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()) { @@ -143,12 +179,17 @@ IPAACA_HEADER_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_s entry->json_source = json_str; return entry; } -IPAACA_HEADER_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null() +IPAACA_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null() { PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>(); - entry->json_source = "null"; + entry->json_source = "null"; // rapidjson::Document value is also null implicitly return entry; } +IPAACA_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::clone() +{ + return PayloadDocumentEntry::from_json_string_representation(this->json_source); +} + //}}} // PayloadEntryProxy//{{{ @@ -340,7 +381,7 @@ std::string value_diagnosis(rapidjson::Value* val) // /* -IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get<std::string>() +IPAACA_EXPORT template<> std::string PayloadEntryProxy::get<std::string>() { if (!json_value) return ""; //IPAACA_INFO( value_diagnosis(json_value) ) @@ -353,33 +394,33 @@ IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get<std::string>( //return _payload->get(_key); } -IPAACA_HEADER_EXPORT template<> long PayloadEntryProxy::get<long>() +IPAACA_EXPORT template<> long PayloadEntryProxy::get<long>() { return atof(operator std::string().c_str()); } -IPAACA_HEADER_EXPORT template<> double PayloadEntryProxy::get<double>() +IPAACA_EXPORT template<> double PayloadEntryProxy::get<double>() { return atol(operator std::string().c_str()); } -IPAACA_HEADER_EXPORT template<> bool PayloadEntryProxy::get<bool>() +IPAACA_EXPORT template<> bool PayloadEntryProxy::get<bool>() { std::string s = operator std::string(); return ((s=="1")||(s=="true")||(s=="True")); } // complex types -IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get<std::list<std::string> >() +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_HEADER_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get<std::vector<std::string> >() +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_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get<std::map<std::string, std::string> >() +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>();