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

C++: iteration over deep proxies

Address mode must be selected explicitly using as_map/as_list, like so:
  for (auto value: iu->payload()["listItem"].as_list()) { .... }
  for (auto kv_pair: iu->payload()["mapItem"].as_map()) { .... }
Generic size() function (reports 0 for non-structured types)
parent ae91a7cf
No related branches found
No related tags found
No related merge requests found
...@@ -254,10 +254,64 @@ IPAACA_HEADER_EXPORT class PayloadIterator//{{{ ...@@ -254,10 +254,64 @@ IPAACA_HEADER_EXPORT class PayloadIterator//{{{
}; };
//}}} //}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxyMapIterator//{{{
{
public:
typedef rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::MemberIterator RawIterator;
protected:
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
IPAACA_MEMBER_VAR_EXPORT RawIterator raw_iterator;
public:
IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator(PayloadEntryProxy* proxy, RawIterator&& raw_iter);
IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator& operator++();
IPAACA_HEADER_EXPORT std::pair<std::string, PayloadEntryProxy> operator*();
IPAACA_HEADER_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > operator->();
IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyMapIterator& other_iter);
IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyMapIterator& other_iter);
};
//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxyListIterator//{{{
{
protected:
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
IPAACA_MEMBER_VAR_EXPORT size_t current_idx;
IPAACA_MEMBER_VAR_EXPORT size_t size;
public:
IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator(PayloadEntryProxy* proxy, size_t idx, size_t size);
IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator& operator++();
IPAACA_HEADER_EXPORT PayloadEntryProxy operator*();
IPAACA_HEADER_EXPORT std::shared_ptr<PayloadEntryProxy> operator->();
IPAACA_HEADER_EXPORT bool operator==(const PayloadEntryProxyListIterator& other_iter);
IPAACA_HEADER_EXPORT bool operator!=(const PayloadEntryProxyListIterator& other_iter);
};
//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxyMapDecorator//{{{
{
public:
IPAACA_HEADER_EXPORT inline PayloadEntryProxyMapDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator begin();
IPAACA_HEADER_EXPORT PayloadEntryProxyMapIterator end();
protected:
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
};
//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxyListDecorator//{{{
{
public:
IPAACA_HEADER_EXPORT inline PayloadEntryProxyListDecorator(PayloadEntryProxy* proxy_): proxy(proxy_) { }
IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator begin();
IPAACA_HEADER_EXPORT PayloadEntryProxyListIterator end();
protected:
IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* proxy;
};
//}}}
IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
{ {
friend std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy); friend std::ostream& operator<<(std::ostream& os, const PayloadEntryProxy& proxy);
protected: protected:
public:
IPAACA_HEADER_EXPORT PayloadEntryProxyMapDecorator as_map();
IPAACA_HEADER_EXPORT PayloadEntryProxyListDecorator as_list();
public: public:
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node; //IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node; //IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node;
...@@ -283,6 +337,8 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ ...@@ -283,6 +337,8 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
// constructors for navigation through objects // constructors for navigation through objects
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key); IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, const std::string& addressed_key);
IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index); IPAACA_HEADER_EXPORT PayloadEntryProxy(PayloadEntryProxy* parent, size_t addressed_index);
public:
IPAACA_HEADER_EXPORT size_t size();
public: public:
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](size_t index); // array-style navigation
IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](int index); // int is UNFORTUNATELY required to catch IPAACA_HEADER_EXPORT PayloadEntryProxy operator[](int index); // int is UNFORTUNATELY required to catch
......
...@@ -41,7 +41,20 @@ using namespace std; ...@@ -41,7 +41,20 @@ using namespace std;
int iterators_main(int argc, char** argv)//{{{ int iterators_main(int argc, char** argv)//{{{
{ {
std::string json_source("[\"old\",2,3,{\"key1\":\"value1\", \"key2\":\"value2\"}]"); std::string json_source("[\n\
\"old\",\n\
[\n\
\"str\",\n\
null\n\
],\n\
3,\n\
{\n\
\"key1\": \"value1\",\n\
\"key2\": \"value2\"\n\
}\n\
]");
std::cout << "Using this JSON document as initial payload entry 'a':" << std::endl << json_source << std::endl;
ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source); ipaaca::PayloadDocumentEntry::ptr entry = ipaaca::PayloadDocumentEntry::from_json_string_representation(json_source);
ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create(); ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
...@@ -50,14 +63,18 @@ int iterators_main(int argc, char** argv)//{{{ ...@@ -50,14 +63,18 @@ int iterators_main(int argc, char** argv)//{{{
iu->payload()["bPrime"] = "simpleString"; iu->payload()["bPrime"] = "simpleString";
iu->payload()["c"] = "anotherSimpleString"; iu->payload()["c"] = "anotherSimpleString";
iu->payload()["d"] = 100; iu->payload()["d"] = 100;
iu->payload()["e"] = 10000l; iu->payload()["e"] = 3l;
std::cout << "Iterate over payload" << std::endl; std::cout << std::endl << "Iterate over payload" << std::endl;
for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) { for (auto it = iu->payload().begin(); it != iu->payload().end(); ++it) {
std::cout << " " << it->first << " -> " << it->second << std::endl; std::cout << " " << it->first << " -> " << it->second << std::endl;
} }
std::cout << std::endl << "Iterate over payload, range-based" << std::endl;
for (auto it: iu->payload()) {
std::cout << " " << it.first << " -> " << it.second << std::endl;
}
std::cout << "Comparisons" << std::endl; std::cout << std::endl << "Comparisons" << std::endl;
bool eq; bool eq;
eq = iu->payload()["a"] == iu->payload()["b"]; eq = iu->payload()["a"] == iu->payload()["b"];
std::cout << " a==b ? : " << (eq?"true":"false") << std::endl; std::cout << " a==b ? : " << (eq?"true":"false") << std::endl;
...@@ -69,7 +86,57 @@ int iterators_main(int argc, char** argv)//{{{ ...@@ -69,7 +86,57 @@ int iterators_main(int argc, char** argv)//{{{
std::cout << " b==100 ? : " << (eq?"true":"false") << std::endl; std::cout << " b==100 ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["d"] == 100; eq = iu->payload()["d"] == 100;
std::cout << " d==100 ? : " << (eq?"true":"false") << std::endl; std::cout << " d==100 ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["a"][2] == iu->payload()["e"];
std::cout << " a[2]==e ? : " << (eq?"true":"false") << std::endl;
std::cout << std::endl << "Inner iterators, map (printing values as strings)" << std::endl;
try {
auto inner = iu->payload()["a"][3];
std::cout << "Map iteration over payload['a'][3], which equals " << inner << std::endl;
std::cout << "Reported size is " << inner.size() << std::endl;
for (auto kv: inner.as_map()) {
std::cout << " \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
}
} catch (ipaaca::Exception& ex) {
std::cout << " Unexpected exception: " << ex.what() << std::endl;
}
try {
auto inner = iu->payload()["a"][2];
std::cout << "Map iteration over payload['a'][2], which equals " << inner << std::endl;
std::cout << "Reported size is " << inner.size() << std::endl;
for (auto kv: inner.as_map()) {
std::cout << " \"" << kv.first << "\" -> \"" << kv.second << "\"" << std::endl;
}
} catch (ipaaca::PayloadTypeConversionError& ex) {
std::cout << " Failed as expected with " << ex.what() << std::endl;
} catch (ipaaca::Exception& ex) {
std::cout << " Unexpected exception: " << ex.what() << std::endl;
}
std::cout << std::endl << "Inner iterators, list (printing values as strings)" << std::endl;
try {
auto inner = iu->payload()["a"][1];
std::cout << "List iteration over payload['a'][1], which equals " << inner << std::endl;
std::cout << "Reported size is " << inner.size() << std::endl;
for (auto proxy: inner.as_list()) {
std::cout << " \"" << proxy << "\"" << std::endl;
}
} catch (ipaaca::Exception& ex) {
std::cout << " Unexpected exception: " << ex.what() << std::endl;
}
try {
auto inner = iu->payload()["a"][1][1];
std::cout << "List iteration over payload['a'][1][1], which equals " << inner << std::endl;
std::cout << "Reported size is " << inner.size() << std::endl;
for (auto proxy: inner.as_list()) {
std::cout << " \"" << proxy << "\"" << std::endl;
}
} catch (ipaaca::PayloadTypeConversionError& ex) {
std::cout << " Failed as expected with " << ex.what() << std::endl;
} catch (ipaaca::Exception& ex) {
std::cout << " Unexpected exception: " << ex.what() << std::endl;
}
return 0; return 0;
} }
//}}} //}}}
......
...@@ -567,6 +567,25 @@ IPAACA_EXPORT bool PayloadEntryProxy::to_bool() ...@@ -567,6 +567,25 @@ IPAACA_EXPORT bool PayloadEntryProxy::to_bool()
//return PayloadEntryProxy::get<bool>(); //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;
}
// //
// new stuff for protocol v2 // new stuff for protocol v2
...@@ -772,4 +791,90 @@ IPAACA_EXPORT bool PayloadIterator::operator!=(const PayloadIterator& ref) ...@@ -772,4 +791,90 @@ IPAACA_EXPORT bool PayloadIterator::operator!=(const PayloadIterator& ref)
} }
//}}} //}}}
// 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 } // of namespace ipaaca
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment