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

C++: stricter type conversions (to be discussed)

PayloadTypeConversionError thrown if (trimmed) string parse is
incomplete; comparison operators == and != catch this error though.
parent 54c953c9
No related branches found
No related tags found
No related merge requests found
...@@ -210,6 +210,14 @@ IPAACA_HEADER_EXPORT class NotImplementedError: public Exception//{{{ ...@@ -210,6 +210,14 @@ IPAACA_HEADER_EXPORT class NotImplementedError: public Exception//{{{
_description = "NotImplementedError"; _description = "NotImplementedError";
} }
};//}}} };//}}}
IPAACA_HEADER_EXPORT class PayloadTypeConversionError: public Exception//{{{
{
public:
IPAACA_HEADER_EXPORT inline ~PayloadTypeConversionError() throw() { }
IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() { //boost::shared_ptr<IU> iu) {
_description = "PayloadTypeConversionError";
}
};//}}}
IPAACA_HEADER_EXPORT class PayloadAddressingError: public Exception//{{{ IPAACA_HEADER_EXPORT class PayloadAddressingError: public Exception//{{{
{ {
public: public:
...@@ -308,6 +316,7 @@ class CommandLineParser { ...@@ -308,6 +316,7 @@ class CommandLineParser {
//}}} //}}}
// in ipaaca-string-utils.cc // in ipaaca-string-utils.cc
// additional misc functions ( String splitting / joining )//{{{ // additional misc functions ( String splitting / joining )//{{{
IPAACA_HEADER_EXPORT std::string str_trim(const std::string &s);
IPAACA_HEADER_EXPORT std::string str_join(const std::set<std::string>& set,const std::string& sep); IPAACA_HEADER_EXPORT std::string str_join(const std::set<std::string>& set,const std::string& sep);
IPAACA_HEADER_EXPORT std::string str_join(const std::vector<std::string>& vec,const std::string& sep); IPAACA_HEADER_EXPORT std::string str_join(const std::vector<std::string>& vec,const std::string& sep);
IPAACA_HEADER_EXPORT void str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters ); IPAACA_HEADER_EXPORT void str_split_wipe(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
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&);
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<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<> long json_value_cast(const rapidjson::Value&);
IPAACA_HEADER_EXPORT template<> int json_value_cast(const rapidjson::Value&);
IPAACA_HEADER_EXPORT template<> double 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<> bool json_value_cast(const rapidjson::Value&);
IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Value&); IPAACA_HEADER_EXPORT template<> std::string json_value_cast(const rapidjson::Value&);
...@@ -53,6 +54,7 @@ IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> json_value_ca ...@@ -53,6 +54,7 @@ IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> json_value_ca
// helpers to set Value& from various standard types // 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<typename T> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, T t);
IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, int);
IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, long); IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, long);
IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, double); IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, double);
IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, bool); IPAACA_HEADER_EXPORT void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, bool);
...@@ -301,6 +303,26 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{ ...@@ -301,6 +303,26 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
_payload->set(_key, new_entry); _payload->set(_key, new_entry);
return *this; return *this;
} }
IPAACA_HEADER_EXPORT inline bool operator==(const PayloadEntryProxy& otherproxy) { return (json_value && otherproxy.json_value && ((*json_value)==*(otherproxy.json_value))); }
IPAACA_HEADER_EXPORT inline bool operator!=(const PayloadEntryProxy& otherproxy) { return !operator==(otherproxy); }
IPAACA_HEADER_EXPORT template<typename T> bool operator==(T othervalue)
{
if (!json_value) return false;
try {
return json_value_cast<T>(*json_value) == othervalue;
} catch(PayloadTypeConversionError& ex) {
// assume conversion error = type mismatch = unequal
return false;
}
}
IPAACA_HEADER_EXPORT template<typename T> bool operator!=(T othervalue) { return !operator==(othervalue); }
IPAACA_HEADER_EXPORT inline bool operator==(const char* othervalue)
{
if (!json_value) return false;
return json_value_cast<std::string>(*json_value) == othervalue;
}
IPAACA_HEADER_EXPORT inline bool operator!=(const char* othervalue) { return !operator==(othervalue); }
IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const PayloadEntryProxy& otherproxy); IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const PayloadEntryProxy& otherproxy);
//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value); //IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value);
......
...@@ -47,13 +47,29 @@ int iterators_main(int argc, char** argv)//{{{ ...@@ -47,13 +47,29 @@ int iterators_main(int argc, char** argv)//{{{
ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create(); ipaaca::FakeIU::ptr iu = ipaaca::FakeIU::create();
iu->add_fake_payload_item("a", entry); iu->add_fake_payload_item("a", entry);
iu->payload()["b"] = "simpleString"; iu->payload()["b"] = "simpleString";
iu->payload()["bPrime"] = "simpleString";
iu->payload()["c"] = "anotherSimpleString"; iu->payload()["c"] = "anotherSimpleString";
iu->payload()["d"] = 100;
iu->payload()["e"] = 10000l;
std::cout << "Iterate over payload" << std::endl; std::cout << "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 << "Comparisons" << std::endl;
bool eq;
eq = iu->payload()["a"] == iu->payload()["b"];
std::cout << " a==b ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["b"] == iu->payload()["bPrime"];
std::cout << " b==bPrime ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["b"] == "simpleString";
std::cout << " b==\"simpleString\" ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["b"] == 100;
std::cout << " b==100 ? : " << (eq?"true":"false") << std::endl;
eq = iu->payload()["d"] == 100;
std::cout << " d==100 ? : " << (eq?"true":"false") << std::endl;
return 0; return 0;
} }
//}}} //}}}
......
...@@ -90,6 +90,20 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{ ...@@ -90,6 +90,20 @@ IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const Payload& obj)//{{
} }
//}}} //}}}
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();
}
}
// json_value_cast//{{{ // json_value_cast//{{{
IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v) IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v)
{ {
...@@ -102,7 +116,7 @@ IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v) ...@@ -102,7 +116,7 @@ IPAACA_EXPORT template<> std::string json_value_cast(const rapidjson::Value& v)
} }
IPAACA_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.IsString()) return (long) strict_numerical_interpretation(v.GetString());
if (v.IsInt()) return v.GetInt(); if (v.IsInt()) return v.GetInt();
if (v.IsUint()) return v.GetUint(); if (v.IsUint()) return v.GetUint();
if (v.IsInt64()) return v.GetInt64(); if (v.IsInt64()) return v.GetInt64();
...@@ -111,14 +125,29 @@ IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v) ...@@ -111,14 +125,29 @@ IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v)
if (v.IsBool()) return v.GetBool() ? 1l : 0l; if (v.IsBool()) return v.GetBool() ? 1l : 0l;
if (v.IsNull()) return 0l; if (v.IsNull()) return 0l;
// default: return parse of string version (should always be 0 though?) // default: return parse of string version (should always be 0 though?)
throw PayloadTypeConversionError();
/*
rapidjson::StringBuffer buffer; rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
v.Accept(writer); v.Accept(writer);
return atol(std::string(buffer.GetString()).c_str()); 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) IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v)
{ {
if (v.IsString()) return atof(std::string(v.GetString()).c_str()); if (v.IsString()) return strict_numerical_interpretation(v.GetString());
if (v.IsDouble()) return v.GetDouble(); if (v.IsDouble()) return v.GetDouble();
if (v.IsInt()) return (double) v.GetInt(); if (v.IsInt()) return (double) v.GetInt();
if (v.IsUint()) return (double) v.GetUint(); if (v.IsUint()) return (double) v.GetUint();
...@@ -126,11 +155,7 @@ IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v) ...@@ -126,11 +155,7 @@ IPAACA_EXPORT template<> double json_value_cast(const rapidjson::Value& v)
if (v.IsUint64()) return (double) v.GetUint64(); if (v.IsUint64()) return (double) v.GetUint64();
if (v.IsBool()) return v.GetBool() ? 1.0 : 0.0; if (v.IsBool()) return v.GetBool() ? 1.0 : 0.0;
if (v.IsNull()) return 0.0; if (v.IsNull()) return 0.0;
// default: return parse of string version (should always be 0.0 though?) throw PayloadTypeConversionError();
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
v.Accept(writer);
return atof(std::string(buffer.GetString()).c_str());
} }
IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
{ {
...@@ -146,12 +171,8 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) ...@@ -146,12 +171,8 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
if (v.IsInt64()) return v.GetInt64() != 0; if (v.IsInt64()) return v.GetInt64() != 0;
if (v.IsUint64()) return v.GetUint64() != 0; if (v.IsUint64()) return v.GetUint64() != 0;
if (v.IsDouble()) return v.GetDouble() != 0.0; if (v.IsDouble()) return v.GetDouble() != 0.0;
// default: return parse of string version (should always be 0.0 though?) // default: assume "pointer-like" semantics (i.e. objects are TRUE)
rapidjson::StringBuffer buffer; return true;
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::map<std::string, std::string> result;
...@@ -161,6 +182,10 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v) ...@@ -161,6 +182,10 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
*/ */
//}}} //}}}
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, long newvalue)
{ {
valueobject.SetInt(newvalue); valueobject.SetInt(newvalue);
......
...@@ -32,8 +32,20 @@ ...@@ -32,8 +32,20 @@
#include <ipaaca/ipaaca.h> #include <ipaaca/ipaaca.h>
#include <cctype>
#include <string>
#include <algorithm>
namespace ipaaca { namespace ipaaca {
std::string str_trim(const std::string &s)
{
auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c){ return std::isspace(c); } );
auto wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c){ return std::isspace(c); } ).base();
return (wsback<=wsfront ? std::string() : std::string(wsfront, wsback));
}
std::string str_join(const std::set<std::string>& set,const std::string& sep) std::string str_join(const std::set<std::string>& set,const std::string& sep)
{ {
if(set.size()==0) if(set.size()==0)
......
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