From 3daf95b398546f0e087e94467038f97077560406 Mon Sep 17 00:00:00 2001 From: Ramin Yaghoubzadeh <ryaghoubzadeh@uni-bielefeld.de> Date: Sat, 14 Feb 2015 00:55:58 +0100 Subject: [PATCH] Proxy read access halfway OK --- ipaacalib/cpp/CMakeLists.txt | 27 +- .../cpp/include/ipaaca/ipaaca-definitions.h | 8 + .../cpp/include/ipaaca/ipaaca-forwards.h | 2 +- ipaacalib/cpp/include/ipaaca/ipaaca-ius.h | 28 ++ ipaacalib/cpp/include/ipaaca/ipaaca-payload.h | 57 ++-- ipaacalib/cpp/include/ipaaca/ipaaca.h | 21 +- ipaacalib/cpp/src/ipaaca-buffers.cc | 61 ----- ipaacalib/cpp/src/ipaaca-fake.cc | 61 +++++ ipaacalib/cpp/src/ipaaca-internal.cc | 10 +- ipaacalib/cpp/src/ipaaca-iuinterface.cc | 156 +++++++++++ ipaacalib/cpp/src/ipaaca-ius.cc | 113 -------- ipaacalib/cpp/src/ipaaca-json.cc | 25 +- ipaacalib/cpp/src/ipaaca-links.cc | 106 ++++++++ ipaacalib/cpp/src/ipaaca-payload.cc | 249 ++++++++++++++---- 14 files changed, 662 insertions(+), 262 deletions(-) create mode 100644 ipaacalib/cpp/src/ipaaca-fake.cc create mode 100644 ipaacalib/cpp/src/ipaaca-iuinterface.cc create mode 100644 ipaacalib/cpp/src/ipaaca-links.cc diff --git a/ipaacalib/cpp/CMakeLists.txt b/ipaacalib/cpp/CMakeLists.txt index 285676a..326c3f9 100644 --- a/ipaacalib/cpp/CMakeLists.txt +++ b/ipaacalib/cpp/CMakeLists.txt @@ -94,7 +94,7 @@ else() # Setup section for Linux or OS X (using 'rsb' soa project) # # - find_package(Boost COMPONENTS system filesystem thread regex REQUIRED) + find_package(Boost COMPONENTS system filesystem thread regex signals REQUIRED) link_directories(${Boost_LIBRARY_DIRS}) include_directories(${Boost_INCLUDE_DIRS}) #set(BOOSTLIBS boost_regex-mt boost_date_time-mt boost_program_options-mt boost_thread-mt boost_filesystem-mt boost_signals-mt boost_system-mt) @@ -105,9 +105,9 @@ else() # change for each new rsb version if (DEFINED APPLE) - set(RSBLIBS rsc0.10 rsb.0.10) + set(RSBLIBS rsc0.11 rsb0.11) else(DEFINED APPLE) - set(RSBLIBS ${PROJECT_SOURCE_DIR}/../../deps/lib/librsc0.10.so ${PROJECT_SOURCE_DIR}/../../deps/lib/librsb.so.0.10 ) + set(RSBLIBS ${PROJECT_SOURCE_DIR}/../../deps/lib/librsc0.11.so ${PROJECT_SOURCE_DIR}/../../deps/lib/librsb0.11.so ) set(LIBS ${LIBS} uuid) endif(DEFINED APPLE) # enhance the default search paths (headers, libs ...) @@ -124,15 +124,18 @@ endif(WIN32) set(LIBS ${LIBS} ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${RSBLIBS}) +# Hide the rsb-induced boost-signals warning (FOR NOW) +set(IPAACA_CXX_DEFINES "${IPAACA_CXX_DEFINES} -DBOOST_SIGNALS_NO_DEPRECATION_WARNING") + # Compiler defines copied from the old build system -set(CXX_DEFINES "-D_BSD_SOURCE -DUSE_AV -DMGC_USE_DOUBLE -DLEDA_PREFIX -D__NO_CAST_TO_LOCAL_TYPE__ -DDBGLVL=0") +set(IPAACA_CXX_DEFINES "${IPAACA_CXX_DEFINES} -D_BSD_SOURCE -DUSE_AV -DMGC_USE_DOUBLE -DLEDA_PREFIX -D__NO_CAST_TO_LOCAL_TYPE__ -DDBGLVL=0") # Combine the extra compiler flags -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_OLD_CODE_CONVENIENCE_FLAGS} ${CXX_DEFINES}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_OLD_CODE_CONVENIENCE_FLAGS} ${IPAACA_CXX_DEFINES}") # add for for each new rsb version -include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsc0.10 ) -include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsb0.10 ) +include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsc0.11 ) +include_directories( ${PROJECT_SOURCE_DIR}/../../deps/include/rsb0.11 ) # add include dir for auto-generated headers placed in build/ include_directories( ${PROJECT_SOURCE_DIR}/build ) @@ -149,7 +152,9 @@ set (SOURCE src/ipaaca.cc src/ipaaca-buffers.cc src/ipaaca-internal.cc + src/ipaaca-iuinterface.cc src/ipaaca-ius.cc + src/ipaaca-links.cc src/ipaaca-locking.cc src/ipaaca-payload.cc src/ipaaca-cmdline-parser.cc @@ -159,7 +164,13 @@ set (SOURCE ) set (JSON_TEST_SOURCE - src/ipaaca-json.cc + src/ipaaca-fake.cc + src/ipaaca-iuinterface.cc + src/ipaaca-json.cc # main + src/ipaaca-locking.cc + src/ipaaca-links.cc + src/ipaaca-payload.cc + src/ipaaca-string-utils.cc ) diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h index 856464a..cf0ebe2 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h @@ -218,6 +218,14 @@ IPAACA_HEADER_EXPORT class JsonParsingError: public Exception//{{{ _description = "JsonParsingError"; } };//}}} +IPAACA_HEADER_EXPORT class PayloadEntryProxyInvalidatedError: public Exception//{{{ +{ + public: + IPAACA_HEADER_EXPORT inline ~PayloadEntryProxyInvalidatedError() throw() { } + IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() { //boost::shared_ptr<IU> iu) { + _description = "PayloadEntryProxyInvalidatedError"; + } +};//}}} /// Static library initialization IPAACA_HEADER_EXPORT class Initializer diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h index 5d64840..3eab622 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h @@ -42,7 +42,7 @@ * forward declarations */ class PayloadDocumentEntry; -class PayloadDocumentStore; +//class PayloadDocumentStore; class PayloadEntryProxy; class Payload; diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h index 75e22d7..0fc9e80 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h @@ -223,4 +223,32 @@ IPAACA_HEADER_EXPORT class RemoteMessage: public IUInterface {//{{{ typedef boost::shared_ptr<RemoteMessage> ptr; };//}}} +IPAACA_HEADER_EXPORT class FakeIU: public IUInterface {//{{{ + friend class Buffer; + friend class InputBuffer; + friend class OutputBuffer; + friend class IUConverter; + friend class MessageConverter; + protected: + IPAACA_MEMBER_VAR_EXPORT Payload _payload; + IPAACA_HEADER_EXPORT FakeIU(); + public: + IPAACA_HEADER_EXPORT static boost::shared_ptr<FakeIU> create(); + IPAACA_HEADER_EXPORT ~FakeIU(); + IPAACA_HEADER_EXPORT Payload& payload(); + IPAACA_HEADER_EXPORT const Payload& const_payload() const; + IPAACA_HEADER_EXPORT void commit(); + IPAACA_HEADER_EXPORT void add_fake_payload_item(const std::string& key, PayloadDocumentEntry::ptr entry); + protected: + IPAACA_HEADER_EXPORT void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = ""); + IPAACA_HEADER_EXPORT void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = ""); + protected: + IPAACA_HEADER_EXPORT void _apply_update(IUPayloadUpdate::ptr update); + IPAACA_HEADER_EXPORT void _apply_link_update(IULinkUpdate::ptr update); + IPAACA_HEADER_EXPORT void _apply_commission(); + IPAACA_HEADER_EXPORT void _apply_retraction(); + public: + typedef boost::shared_ptr<FakeIU> ptr; +};//}}} + #endif diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h index f41d4cf..6cbd1bb 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h @@ -38,15 +38,30 @@ #error "Please do not include this file directly, use ipaaca.h instead" #endif +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&); +IPAACA_HEADER_EXPORT template<> double json_value_cast(const rapidjson::Value&); +IPAACA_HEADER_EXPORT template<> bool json_value_cast(const rapidjson::Value&); +IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Value&); +IPAACA_HEADER_EXPORT template<> std::vector<std::string> json_value_cast(const rapidjson::Value&); +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&); + +// FIXME TODO locking / invalidating proxy on first write of a payload entry IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{ { public: IPAACA_MEMBER_VAR_EXPORT ipaaca::Lock lock; + IPAACA_MEMBER_VAR_EXPORT bool modified; + IPAACA_MEMBER_VAR_EXPORT std::string json_source; IPAACA_MEMBER_VAR_EXPORT rapidjson::Document document; - IPAACA_HEADER_EXPORT PayloadDocumentEntry(rapidjson::Document&& doc): document(std::move(doc)) {}; - IPAACA_HEADER_EXPORT PayloadDocumentEntry() {}; + IPAACA_HEADER_EXPORT inline PayloadDocumentEntry(): modified(false) { IPAACA_INFO("") } + 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(); typedef std::shared_ptr<PayloadDocumentEntry> ptr; }; //}}} @@ -62,24 +77,26 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ // PayloadEntryProxy* parent; // parent (up to document root -> then null) PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc - bool existant; // whether Value exist already (or blindly navigated) + 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; - public: - IPAACA_HEADER_EXPORT PayloadEntryProxy& operator[](long index); // array-style navigation - IPAACA_HEADER_EXPORT PayloadEntryProxy& operator[](const std::string& key); + 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: - IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key, PayloadDocumentEntry::ptr entry); + // 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, long addressed_index); - // + 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); @@ -94,7 +111,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ IPAACA_HEADER_EXPORT double to_float(); IPAACA_HEADER_EXPORT bool to_bool(); // getters - IPAACA_HEADER_EXPORT template<typename T> T get(); // specializations below + 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); /*{ @@ -106,6 +123,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ // 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(); @@ -113,6 +131,8 @@ 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(); +*/ + // value converters IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(long); IPAACA_HEADER_EXPORT template<> void PayloadEntryProxy::pack_into_json_value(double); @@ -162,8 +182,9 @@ IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryP //}}} */ -// shared_ptrs stored for shared read access, ref must be held -// even if the key for the entry is overwritten remotely +typedef std::map<std::string, PayloadDocumentEntry::ptr> PayloadDocumentStore; + +/* IPAACA_HEADER_EXPORT class PayloadDocumentStore//{{{ : public std::map<std::string, PayloadDocumentEntry::ptr> { @@ -171,7 +192,7 @@ IPAACA_HEADER_EXPORT class PayloadDocumentStore//{{{ typedef std::shared_ptr<PayloadDocumentStore> ptr; }; //}}} - +*/ IPAACA_HEADER_EXPORT class Payload//{{{ { friend std::ostream& operator<<(std::ostream& os, const Payload& obj); @@ -183,6 +204,8 @@ IPAACA_HEADER_EXPORT class Payload//{{{ friend class IUConverter; friend class MessageConverter; friend class CallbackIUPayloadUpdate; + friend class PayloadEntryProxy; + friend class FakeIU; protected: IPAACA_MEMBER_VAR_EXPORT std::string _owner_name; //IPAACA_MEMBER_VAR_EXPORT rapidjson::Document _json_document; @@ -195,6 +218,7 @@ IPAACA_HEADER_EXPORT class Payload//{{{ IPAACA_HEADER_EXPORT void _remotely_enforced_wipe(); IPAACA_HEADER_EXPORT void _remotely_enforced_delitem(const std::string& k); IPAACA_HEADER_EXPORT void _remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry); + //IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name=""); IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name=""); IPAACA_HEADER_EXPORT void _internal_merge(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::string& writer_name=""); IPAACA_HEADER_EXPORT void _internal_set(const std::string& k, PayloadDocumentEntry::ptr v, const std::string& writer_name=""); @@ -210,7 +234,10 @@ IPAACA_HEADER_EXPORT class Payload//{{{ // to be more precise: types of map<string, T> with T several interesting things (string, list<string>, etc.) //IPAACA_HEADER_EXPORT inline void set(const std::map<std::string, const rapidjson::Document&>& all_elems) { _internal_replace_all(all_elems); } //IPAACA_HEADER_EXPORT inline void merge(const std::map<std::string, const rapidjson::Document&>& elems_to_merge) { _internal_merge(elems_to_merge); } - IPAACA_HEADER_EXPORT PayloadEntryProxy get(const std::string& k); // json, changed str to proxy here, too + protected: + IPAACA_HEADER_EXPORT PayloadDocumentEntry::ptr get_entry(const std::string& k); // json, changed str to proxy here, too + public: + IPAACA_HEADER_EXPORT std::string get(const std::string& k); // DEPRECATED typedef boost::shared_ptr<Payload> ptr; };//}}} diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca.h b/ipaacalib/cpp/include/ipaaca/ipaaca.h index 95cc0f0..f79e092 100644 --- a/ipaacalib/cpp/include/ipaaca/ipaaca.h +++ b/ipaacalib/cpp/include/ipaaca/ipaaca.h @@ -99,6 +99,7 @@ #endif // new json-based payload API, used in several classes +#define RAPIDJSON_HAS_STDSTRING 1 #include "rapidjson/document.h" #include "rapidjson/prettywriter.h" #include "rapidjson/filestream.h" @@ -161,15 +162,6 @@ namespace ipaaca { #include <ipaaca/ipaaca-forwards.h> #include <ipaaca/ipaaca-locking.h> -#include <ipaaca/ipaaca-buffers.h> -#include <ipaaca/ipaaca-payload.h> -#include <ipaaca/ipaaca-ius.h> - -/// Full API (including RSB transport) is only exposed during -/// ipaaca compilation, user programs should use abstract API. -#ifdef IPAACA_EXPOSE_FULL_RSB_API -#include <ipaaca/ipaaca-internal.h> -#endif IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock(); @@ -181,6 +173,17 @@ IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock(); #define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; } #endif +#include <ipaaca/ipaaca-payload.h> +#include <ipaaca/ipaaca-buffers.h> +#include <ipaaca/ipaaca-ius.h> + +/// Full API (including RSB transport) is only exposed during +/// ipaaca compilation, user programs should use abstract API. +#ifdef IPAACA_EXPOSE_FULL_RSB_API +#include <ipaaca/ipaaca-internal.h> +#endif + + } // of namespace ipaaca diff --git a/ipaacalib/cpp/src/ipaaca-buffers.cc b/ipaacalib/cpp/src/ipaaca-buffers.cc index 9d7208c..3600772 100644 --- a/ipaacalib/cpp/src/ipaaca-buffers.cc +++ b/ipaacalib/cpp/src/ipaaca-buffers.cc @@ -42,24 +42,6 @@ using namespace rsb::filter; using namespace rsb::converter; using namespace rsb::patterns; -IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj)//{{{ -{ - os << "{"; - bool first = true; - for (LinkMap::const_iterator it=obj._links.begin(); it!=obj._links.end(); ++it) { - if (first) { first=false; } else { os << ", "; } - os << "'" << it->first << "': ["; - bool firstinner = true; - for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { - if (firstinner) { firstinner=false; } else { os << ", "; } - os << "'" << *it2 << "'"; - } - os << "]"; - } - os << "}"; - return os; -} -//}}} IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IUPayloadUpdate& obj)//{{{ { os << "PayloadUpdate(uid=" << obj.uid << ", revision=" << obj.revision; @@ -114,49 +96,6 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IULinkUpdate& obj } //}}} -// SmartLinkMap//{{{ - -IPAACA_EXPORT LinkSet SmartLinkMap::empty_link_set; -IPAACA_EXPORT void SmartLinkMap::_add_and_remove_links(const LinkMap& add, const LinkMap& remove) -{ - // remove specified links - for (LinkMap::const_iterator it = remove.begin(); it != remove.end(); ++it ) { - // if link type exists - if (_links.count(it->first) > 0) { - // remove one by one - for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { - _links[it->first].erase(*it2); - } - // wipe the type key if no more links are left - if (_links[it->first].size() == 0) { - _links.erase(it->first); - } - } - } - // add specified links - for (LinkMap::const_iterator it = add.begin(); it != add.end(); ++it ) { - for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { - _links[it->first].insert(*it2); - } - } -} -IPAACA_EXPORT void SmartLinkMap::_replace_links(const LinkMap& links) -{ - //_links.clear(); - _links=links; -} -IPAACA_EXPORT const LinkSet& SmartLinkMap::get_links(const std::string& key) -{ - LinkMap::const_iterator it = _links.find(key); - if (it==_links.end()) return empty_link_set; - return it->second; -} -IPAACA_EXPORT const LinkMap& SmartLinkMap::get_all_links() -{ - return _links; -} -//}}} - // IUEventHandler//{{{ IPAACA_EXPORT IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category) : _function(function), _event_mask(event_mask), _for_all_categories(false) diff --git a/ipaacalib/cpp/src/ipaaca-fake.cc b/ipaacalib/cpp/src/ipaaca-fake.cc new file mode 100644 index 0000000..0cb444b --- /dev/null +++ b/ipaacalib/cpp/src/ipaaca-fake.cc @@ -0,0 +1,61 @@ +/* + * 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 { + +IPAACA_EXPORT inline FakeIU::FakeIU() { IPAACA_INFO("") } +IPAACA_EXPORT boost::shared_ptr<FakeIU> FakeIU::create() +{ + IPAACA_INFO(""); + return boost::shared_ptr<FakeIU>(new FakeIU()); +} +IPAACA_EXPORT void FakeIU::add_fake_payload_item(const std::string& key, PayloadDocumentEntry::ptr entry) +{ + _payload._remotely_enforced_setitem(key, entry); +} +IPAACA_EXPORT inline FakeIU::~FakeIU() { IPAACA_INFO("") } +IPAACA_EXPORT inline Payload& FakeIU::payload() { return _payload; } +IPAACA_EXPORT inline const Payload& FakeIU::const_payload() const { return _payload; } +IPAACA_EXPORT inline void FakeIU::commit() { IPAACA_INFO("") } +IPAACA_EXPORT inline void FakeIU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name) { IPAACA_INFO("") } +IPAACA_EXPORT inline void FakeIU::_modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name) { IPAACA_INFO("")} +IPAACA_EXPORT inline void FakeIU::_apply_update(IUPayloadUpdate::ptr update) { IPAACA_INFO("") } +IPAACA_EXPORT inline void FakeIU::_apply_link_update(IULinkUpdate::ptr update) { IPAACA_INFO("") } +IPAACA_EXPORT inline void FakeIU::_apply_commission() { IPAACA_INFO("") } +IPAACA_EXPORT inline void FakeIU::_apply_retraction() { IPAACA_INFO("") } + +} // of namespace ipaaca + + diff --git a/ipaacalib/cpp/src/ipaaca-internal.cc b/ipaacalib/cpp/src/ipaaca-internal.cc index e8defae..6b3e4c8 100644 --- a/ipaacalib/cpp/src/ipaaca-internal.cc +++ b/ipaacalib/cpp/src/ipaaca-internal.cc @@ -223,7 +223,7 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche // fully parse json text entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) } else { - // implying legacy "str" -> just copy value to raw string in document + // assuming legacy "str" -> just copy value to raw string in document entry = std::make_shared<PayloadDocumentEntry>(); entry->document.SetString(it.value(), entry->document.GetAllocator()); } @@ -261,7 +261,7 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche // fully parse json text entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) } else { - // implying legacy "str" -> just copy value to raw string in document + // assuming legacy "str" -> just copy value to raw string in document entry = std::make_shared<PayloadDocumentEntry>(); entry->document.SetString(it.value(), entry->document.GetAllocator()); } @@ -372,7 +372,7 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir // fully parse json text entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) } else { - // implying legacy "str" -> just copy value to raw string in document + // assuming legacy "str" -> just copy value to raw string in document entry = std::make_shared<PayloadDocumentEntry>(); entry->document.SetString(it.value(), entry->document.GetAllocator()); } @@ -409,7 +409,7 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir // fully parse json text entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) } else { - // implying legacy "str" -> just copy value to raw string in document + // assuming legacy "str" -> just copy value to raw string in document entry = std::make_shared<PayloadDocumentEntry>(); entry->document.SetString(it.value(), entry->document.GetAllocator()); } @@ -481,7 +481,7 @@ AnnotatedData IUPayloadUpdateConverter::deserialize(const std::string& wireSchem // fully parse json text entry = PayloadDocumentEntry::from_json_string_representation( it.value() ) } else { - // implying legacy "str" -> just copy value to raw string in document + // assuming legacy "str" -> just copy value to raw string in document entry = std::make_shared<PayloadDocumentEntry>(); entry->document.SetString(it.value(), entry->document.GetAllocator()); } diff --git a/ipaacalib/cpp/src/ipaaca-iuinterface.cc b/ipaacalib/cpp/src/ipaaca-iuinterface.cc new file mode 100644 index 0000000..2c36848 --- /dev/null +++ b/ipaacalib/cpp/src/ipaaca-iuinterface.cc @@ -0,0 +1,156 @@ +/* + * 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; + +IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IUInterface& obj)//{{{ +{ + os << "IUInterface(uid='" << obj.uid() << "'"; + os << ", category='" << obj.category() << "'"; + os << ", revision=" << obj.revision(); + os << ", committed=" << (obj.committed()?"True":"False"); + os << ", owner_name='" << obj.owner_name() << "'"; + os << ", payload="; + os << obj.const_payload(); + os << ", links="; + os << obj._links; + os << ")"; + return os; +} +//}}} + +// IUInterface//{{{ + +IPAACA_EXPORT IUInterface::IUInterface() +: _buffer(NULL), _committed(false), _retracted(false) +{ +} + +IPAACA_EXPORT void IUInterface::_set_uid(const std::string& uid) { + if (_uid != "") { + throw IUAlreadyHasAnUIDError(); + } + _uid = uid; +} + +IPAACA_EXPORT void IUInterface::_set_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) { + if (_buffer) { + throw IUAlreadyInABufferError(); + } + _buffer = buffer; + +} + +IPAACA_EXPORT void IUInterface::_set_owner_name(const std::string& owner_name) { + if (_owner_name != "") { + throw IUAlreadyHasAnOwnerNameError(); + } + _owner_name = owner_name; +} + +/// set the buffer pointer and the owner names of IU and Payload +IPAACA_EXPORT void IUInterface::_associate_with_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) { + _set_buffer(buffer); // will throw if already set + _set_owner_name(buffer->unique_name()); + payload()._set_owner_name(buffer->unique_name()); +} + +/// C++-specific convenience function to add one single link +IPAACA_EXPORT void IUInterface::add_link(const std::string& type, const std::string& target, const std::string& writer_name) +{ + LinkMap none; + LinkMap add; + add[type].insert(target); + _modify_links(true, add, none, writer_name); + _add_and_remove_links(add, none); +} +/// C++-specific convenience function to remove one single link +IPAACA_EXPORT void IUInterface::remove_link(const std::string& type, const std::string& target, const std::string& writer_name) +{ + LinkMap none; + LinkMap remove; + remove[type].insert(target); + _modify_links(true, none, remove, writer_name); + _add_and_remove_links(none, remove); +} + +IPAACA_EXPORT void IUInterface::add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name) +{ + LinkMap none; + LinkMap add; + add[type] = targets; + _modify_links(true, add, none, writer_name); + _add_and_remove_links(add, none); +} + +IPAACA_EXPORT void IUInterface::remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name) +{ + LinkMap none; + LinkMap remove; + remove[type] = targets; + _modify_links(true, none, remove, writer_name); + _add_and_remove_links(none, remove); +} + +IPAACA_EXPORT void IUInterface::modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name) +{ + _modify_links(true, add, remove, writer_name); + _add_and_remove_links(add, remove); +} + +IPAACA_EXPORT void IUInterface::set_links(const LinkMap& links, const std::string& writer_name) +{ + LinkMap none; + _modify_links(false, links, none, writer_name); + _replace_links(links); +} + +IPAACA_HEADER_EXPORT const std::string& IUInterface::channel() +{ + if (_buffer == NULL) + throw IUUnpublishedError(); + else + return _buffer->channel(); + +} + +//}}} + +} // of namespace ipaaca diff --git a/ipaacalib/cpp/src/ipaaca-ius.cc b/ipaacalib/cpp/src/ipaaca-ius.cc index 27a2f4c..0d5c920 100644 --- a/ipaacalib/cpp/src/ipaaca-ius.cc +++ b/ipaacalib/cpp/src/ipaaca-ius.cc @@ -40,119 +40,6 @@ using namespace rsb::filter; using namespace rsb::converter; using namespace rsb::patterns; -IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const IUInterface& obj)//{{{ -{ - os << "IUInterface(uid='" << obj.uid() << "'"; - os << ", category='" << obj.category() << "'"; - os << ", revision=" << obj.revision(); - os << ", committed=" << (obj.committed()?"True":"False"); - os << ", owner_name='" << obj.owner_name() << "'"; - os << ", payload="; - os << obj.const_payload(); - os << ", links="; - os << obj._links; - os << ")"; - return os; -} -//}}} - -// IUInterface//{{{ - -IPAACA_EXPORT IUInterface::IUInterface() -: _buffer(NULL), _committed(false), _retracted(false) -{ -} - -IPAACA_EXPORT void IUInterface::_set_uid(const std::string& uid) { - if (_uid != "") { - throw IUAlreadyHasAnUIDError(); - } - _uid = uid; -} - -IPAACA_EXPORT void IUInterface::_set_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) { - if (_buffer) { - throw IUAlreadyInABufferError(); - } - _buffer = buffer; - -} - -IPAACA_EXPORT void IUInterface::_set_owner_name(const std::string& owner_name) { - if (_owner_name != "") { - throw IUAlreadyHasAnOwnerNameError(); - } - _owner_name = owner_name; -} - -/// set the buffer pointer and the owner names of IU and Payload -IPAACA_EXPORT void IUInterface::_associate_with_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) { - _set_buffer(buffer); // will throw if already set - _set_owner_name(buffer->unique_name()); - payload()._set_owner_name(buffer->unique_name()); -} - -/// C++-specific convenience function to add one single link -IPAACA_EXPORT void IUInterface::add_link(const std::string& type, const std::string& target, const std::string& writer_name) -{ - LinkMap none; - LinkMap add; - add[type].insert(target); - _modify_links(true, add, none, writer_name); - _add_and_remove_links(add, none); -} -/// C++-specific convenience function to remove one single link -IPAACA_EXPORT void IUInterface::remove_link(const std::string& type, const std::string& target, const std::string& writer_name) -{ - LinkMap none; - LinkMap remove; - remove[type].insert(target); - _modify_links(true, none, remove, writer_name); - _add_and_remove_links(none, remove); -} - -IPAACA_EXPORT void IUInterface::add_links(const std::string& type, const LinkSet& targets, const std::string& writer_name) -{ - LinkMap none; - LinkMap add; - add[type] = targets; - _modify_links(true, add, none, writer_name); - _add_and_remove_links(add, none); -} - -IPAACA_EXPORT void IUInterface::remove_links(const std::string& type, const LinkSet& targets, const std::string& writer_name) -{ - LinkMap none; - LinkMap remove; - remove[type] = targets; - _modify_links(true, none, remove, writer_name); - _add_and_remove_links(none, remove); -} - -IPAACA_EXPORT void IUInterface::modify_links(const LinkMap& add, const LinkMap& remove, const std::string& writer_name) -{ - _modify_links(true, add, remove, writer_name); - _add_and_remove_links(add, remove); -} - -IPAACA_EXPORT void IUInterface::set_links(const LinkMap& links, const std::string& writer_name) -{ - LinkMap none; - _modify_links(false, links, none, writer_name); - _replace_links(links); -} - -IPAACA_HEADER_EXPORT const std::string& IUInterface::channel() -{ - if (_buffer == NULL) - throw IUUnpublishedError(); - else - return _buffer->channel(); - -} - -//}}} - // IU//{{{ IPAACA_EXPORT IU::ptr IU::create(const std::string& category, IUAccessMode access_mode, bool read_only, const std::string& payload_type) { diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc index 5908926..bb7acfe 100644 --- a/ipaacalib/cpp/src/ipaaca-json.cc +++ b/ipaacalib/cpp/src/ipaaca-json.cc @@ -37,7 +37,30 @@ using namespace rapidjson; using namespace std; -int main(int, char*[]) { +int main(int argc, char** argv) { + + if (argc<2) { + std::cout << "Please provide json content as the first argument." << std::endl; + return 0; + } + std::string json_source(argv[1]); + ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source); + + ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create(); + iu->add_fake_payload_item("a", entry); + + auto a = iu->payload()["a"]; + //auto a0 = a[0]; + std::cout << "entry as string: " << (std::string) a << std::endl; + std::cout << "entry as long: " << (long) a << std::endl; + std::cout << "entry as double: " << (double) a << std::endl; + std::cout << "entry as bool: " << ((bool) a?"true":"false") << std::endl; + std::cout << "entry as list<string>: "; + try { + } catch { + std::cout << "(Error)" << std::endl; + } + return 0; //////////////////////////////////////////////////////////////////////////// // 1. Parse a JSON text string to a document. diff --git a/ipaacalib/cpp/src/ipaaca-links.cc b/ipaacalib/cpp/src/ipaaca-links.cc new file mode 100644 index 0000000..e0a6229 --- /dev/null +++ b/ipaacalib/cpp/src/ipaaca-links.cc @@ -0,0 +1,106 @@ +/* + * 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; + +IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const SmartLinkMap& obj)//{{{ +{ + os << "{"; + bool first = true; + for (LinkMap::const_iterator it=obj._links.begin(); it!=obj._links.end(); ++it) { + if (first) { first=false; } else { os << ", "; } + os << "'" << it->first << "': ["; + bool firstinner = true; + for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { + if (firstinner) { firstinner=false; } else { os << ", "; } + os << "'" << *it2 << "'"; + } + os << "]"; + } + os << "}"; + return os; +} +//}}} + +// SmartLinkMap//{{{ + +IPAACA_EXPORT LinkSet SmartLinkMap::empty_link_set; +IPAACA_EXPORT void SmartLinkMap::_add_and_remove_links(const LinkMap& add, const LinkMap& remove) +{ + // remove specified links + for (LinkMap::const_iterator it = remove.begin(); it != remove.end(); ++it ) { + // if link type exists + if (_links.count(it->first) > 0) { + // remove one by one + for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { + _links[it->first].erase(*it2); + } + // wipe the type key if no more links are left + if (_links[it->first].size() == 0) { + _links.erase(it->first); + } + } + } + // add specified links + for (LinkMap::const_iterator it = add.begin(); it != add.end(); ++it ) { + for (LinkSet::const_iterator it2=it->second.begin(); it2!=it->second.end(); ++it2) { + _links[it->first].insert(*it2); + } + } +} +IPAACA_EXPORT void SmartLinkMap::_replace_links(const LinkMap& links) +{ + //_links.clear(); + _links=links; +} +IPAACA_EXPORT const LinkSet& SmartLinkMap::get_links(const std::string& key) +{ + LinkMap::const_iterator it = _links.find(key); + if (it==_links.end()) return empty_link_set; + return it->second; +} +IPAACA_EXPORT const LinkMap& SmartLinkMap::get_all_links() +{ + return _links; +} +//}}} + +} // of namespace ipaaca + diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc index 00674e1..a502226 100644 --- a/ipaacalib/cpp/src/ipaaca-payload.cc +++ b/ipaacalib/cpp/src/ipaaca-payload.cc @@ -35,6 +35,8 @@ namespace ipaaca { +using namespace rapidjson; + using namespace rsb; using namespace rsb::filter; using namespace rsb::converter; @@ -44,15 +46,86 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{ { os << "{"; bool first = true; - for (std::map<std::string, std::string>::const_iterator it=obj._document_store.begin(); it!=obj._document_store.end(); ++it) { + for (auto& kv: obj._document_store) { if (first) { first=false; } else { os << ", "; } - os << "'" << it->first << "':'" << it->second << "'"; + os << "'" << kv.first << "':'" << kv.second->json_source << "'"; } os << "}"; return os; } //}}} +// json_value_cast//{{{ +IPAACA_HEADER_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_HEADER_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(); + 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?) + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + v.Accept(writer); + return atol(std::string(buffer.GetString()).c_str()); +} +IPAACA_HEADER_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(); + 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; + // default: return parse of string version (should always be 0.0 though?) + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + v.Accept(writer); + return atof(std::string(buffer.GetString()).c_str()); +} +IPAACA_HEADER_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: return parse of string version (should always be 0.0 though?) + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + v.Accept(writer); + std::string s = buffer.GetString(); + return !((s=="")||(s=="false")||(s=="False")||(s=="0")); +} +/* + * 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(); + }); + */ +//}}} + // PayloadDocumentEntry//{{{ IPAACA_HEADER_EXPORT inline std::string PayloadDocumentEntry::to_json_string_representation() { @@ -61,12 +134,19 @@ IPAACA_HEADER_EXPORT inline std::string PayloadDocumentEntry::to_json_string_rep document.Accept(writer); return buffer.GetString(); } -IPAACA_HEADER_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_representation(const std::string& json) +IPAACA_HEADER_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).HasParseError()) { + if (entry->document.Parse(json_str.c_str()).HasParseError()) { throw JsonParsingError(); } + entry->json_source = json_str; + return entry; +} +IPAACA_HEADER_EXPORT inline PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null() +{ + PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>(); + entry->json_source = "null"; return entry; } //}}} @@ -78,16 +158,16 @@ IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents() { rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator(); PayloadEntryProxy* pep = this; - while (!(pep->existant) && pep->parent) { // only if not top-level + while (!(pep->existent) && pep->parent) { // only if not top-level if (pep->addressed_as_array) { - Value& parent_value = pep->parent->json_value; + 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; + parent_value[idx] = *json_value; } else { throw PayloadAddressingError(); } @@ -101,7 +181,7 @@ IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents() long s = parent_value.Size(); if (idx<s) { // existing element modified - parent_value[idx] = json_value; + parent_value[idx] = *json_value; } else { // implicitly initialize missing elements to null values if (idx>s) { @@ -117,11 +197,13 @@ IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents() }*/ } else { // addressed as object (dict) - Value& parent_value = pep->parent->json_value; + rapidjson::Value& parent_value = *(pep->parent->json_value); if (! parent_value.IsObject()) { throw PayloadAddressingError(); } else { - parent_value.AddMember(pep->addressed_key, json_value, allocator); + Value key; + key.SetString(pep->addressed_key, allocator); + parent_value.AddMember(key, *json_value, allocator); } } // repeat for next parent in the tree @@ -129,42 +211,80 @@ IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents() } } -IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key, PayloadDocumentEntry::ptr entry) -: _payload(payload), _key(key), parent(nullptr), document_entry(entry) -{ - PayloadEntryProxy* parent; // parent (up to document root -> then null) - PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc - bool existant; // whether Value exist 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; - + + +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()); + if (it != 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_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 std::string& addr_key_) +{ + if (!json_value) throw PayloadAddressingError(); + if (! json_value->IsObject()) 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(); + long s = json_value->Size(); + if (addr_idx_>=s) throw PayloadAddressingError(); + return PayloadEntryProxy(this, addr_idx_); } IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value) { //std::cout << "operator=(string)" << std::endl; - _payload->set(_key, value); + IPAACA_IMPLEMENT_ME + //_payload->set(_key, value); return *this; } IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const char* value) { //std::cout << "operator=(const char*)" << std::endl; - _payload->set(_key, value); + IPAACA_IMPLEMENT_ME + //_payload->set(_key, value); return *this; } IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(double value) { //std::cout << "operator=(double)" << std::endl; - _payload->set(_key, boost::lexical_cast<std::string>(value)); + 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; - _payload->set(_key, boost::lexical_cast<std::string>(value)); + IPAACA_IMPLEMENT_ME + //_payload->set(_key, boost::lexical_cast<std::string>(value)); return *this; } @@ -172,42 +292,66 @@ IPAACA_EXPORT PayloadEntryProxy::operator std::string() { return PayloadEntryProxy::get<std::string>(); } -IPAACA_EXPORT inline PayloadEntryProxy::operator long() +IPAACA_EXPORT PayloadEntryProxy::operator long() { return PayloadEntryProxy::get<long>(); } -IPAACA_EXPORT inline PayloadEntryProxy::operator double() +IPAACA_EXPORT PayloadEntryProxy::operator double() { return PayloadEntryProxy::get<double>(); } -IPAACA_EXPORT inline PayloadEntryProxy::operator bool() +IPAACA_EXPORT PayloadEntryProxy::operator bool() { return PayloadEntryProxy::get<bool>(); } -IPAACA_EXPORT inline std::string PayloadEntryProxy::to_str() +IPAACA_EXPORT std::string PayloadEntryProxy::to_str() { return PayloadEntryProxy::get<std::string>(); } -IPAACA_EXPORT inline long PayloadEntryProxy::to_long() +IPAACA_EXPORT long PayloadEntryProxy::to_long() { return PayloadEntryProxy::get<long>(); } -IPAACA_EXPORT inline double PayloadEntryProxy::to_float() +IPAACA_EXPORT double PayloadEntryProxy::to_float() { return PayloadEntryProxy::get<double>(); } -IPAACA_EXPORT inline bool PayloadEntryProxy::to_bool() +IPAACA_EXPORT bool PayloadEntryProxy::to_bool() { return PayloadEntryProxy::get<bool>(); } +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"; + +} + // // new stuff for protocol v2 // + +/* IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get<std::string>() { - return _payload->get(_key); + 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_HEADER_EXPORT template<> long PayloadEntryProxy::get<long>() { @@ -241,6 +385,8 @@ IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryP m["__automatic__"] = PayloadEntryProxy::get<std::string>(); return m; } +*/ + //}}} // Payload//{{{ @@ -252,39 +398,40 @@ IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu) IPAACA_EXPORT PayloadEntryProxy Payload::operator[](const std::string& key) { + // TODO atomicize //boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key)); - return PayloadEntryProxy(this, key, get(key)); + return PayloadEntryProxy(this, key); } IPAACA_EXPORT Payload::operator std::map<std::string, std::string>() { std::map<std::string, std::string> result; - std::foreach(_document_store.begin(), _document_store.end(), [&result](auto pair) { - result[pair.first] = pair.second.GetString(); + std::for_each(_document_store.begin(), _document_store.end(), [&result](std::pair<std::string, PayloadDocumentEntry::ptr> pair) { + result[pair.first] = pair.second->document.GetString(); }); return result; } -IPAACA_EXPORT void Payload::_internal_set(const std::string& k, const rapidjson::Document& v, const std::string& writer_name) { - std::map<std::string, const rapidjson::Document&> _new; +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; - _new[k]=v; + _new[k] = v; _iu.lock()->_modify_payload(true, _new, _remove, writer_name ); _document_store[k] = v; } IPAACA_EXPORT void Payload::_internal_remove(const std::string& k, const std::string& writer_name) { - std::map<std::string, const rapidjson::Document&> _new; + 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 ); - _store.erase(k); + _document_store.erase(k); } -IPAACA_EXPORT void Payload::_internal_replace_all(const std::map<std::string, const rapidjson::Document&>& new_contents, const std::string& writer_name) +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 ); - _store = new_contents; + _document_store = new_contents; } -IPAACA_EXPORT void Payload::_internal_merge(const std::map<std::string, const rapidjson::Document&>& contents_to_merge, const std::string& writer_name) +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 ); @@ -293,9 +440,13 @@ IPAACA_EXPORT void Payload::_internal_merge(const std::map<std::string, const ra // _store[it->first] = it->second; //} } -IPAACA_EXPORT inline PayloadDocumentEntry::ptr Payload::get(const std::string& k) { +IPAACA_EXPORT inline PayloadDocumentEntry::ptr Payload::get_entry(const std::string& k) { if (_document_store.count(k)>0) return _document_store[k]; - else return make_shared<PayloadDocumentEntry>(); // contains Document with 'null' value + else return PayloadDocumentEntry::create_null(); // contains Document with 'null' value +} +IPAACA_EXPORT inline 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::_remotely_enforced_wipe() { @@ -305,9 +456,9 @@ IPAACA_EXPORT void Payload::_remotely_enforced_delitem(const std::string& k) { _document_store.erase(k); } -IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, rapidjson::Document&& received_json_doc) +IPAACA_EXPORT void Payload::_remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry) { - _document_store[k] = make_shared<PayloadDocumentEntry>(std::move(received_json_doc)); + _document_store[k] = entry; } //}}} -- GitLab