|
|
@ -13,32 +13,114 @@ |
|
|
|
|
|
|
|
namespace pEp { |
|
|
|
|
|
|
|
// type ----------------------------------------
|
|
|
|
// same for pointer and value typee
|
|
|
|
template<class T> |
|
|
|
std::string type_addr_val(const T c, size_t val_len = 30) |
|
|
|
std::string type_str(const T) |
|
|
|
{ |
|
|
|
static_assert(std::is_pointer<T>::value, "only pointer types are valid"); |
|
|
|
std::stringstream ss_type; |
|
|
|
//type
|
|
|
|
ss_type << typeid(T).name(); |
|
|
|
return ss_type.str(); |
|
|
|
} |
|
|
|
|
|
|
|
//addr
|
|
|
|
std::stringstream ss_addr{}; |
|
|
|
ss_addr << static_cast<const void*>(c); |
|
|
|
|
|
|
|
//value
|
|
|
|
std::stringstream ss_val{}; |
|
|
|
if (c != nullptr) { |
|
|
|
ss_val << "\"" << c << "\""; |
|
|
|
} else { |
|
|
|
ss_val << "<NULL>"; |
|
|
|
// addr ----------------------------------------
|
|
|
|
template<class T> |
|
|
|
struct addr_str_helper { |
|
|
|
static std::string str(const T c) |
|
|
|
{ |
|
|
|
std::stringstream ss_addr{}; |
|
|
|
ss_addr << static_cast<const void*>(&c); |
|
|
|
return ss_addr.str(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
struct addr_str_helper<T*> { |
|
|
|
static std::string str(const T* c) |
|
|
|
{ |
|
|
|
std::stringstream ss_addr{}; |
|
|
|
ss_addr << static_cast<const void*>(c); |
|
|
|
return ss_addr.str(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
std::stringstream ret{}; |
|
|
|
ret << "{ " << ss_type.str() << " | " + ss_addr.str() << " | " |
|
|
|
<< pEp::Utils::clip(ss_val.str(), val_len) << " }"; |
|
|
|
return ret.str(); |
|
|
|
// rertuns the address of c
|
|
|
|
template<class T> |
|
|
|
std::string addr_str(T c) |
|
|
|
{ |
|
|
|
return addr_str_helper<T>::str(c); |
|
|
|
} |
|
|
|
|
|
|
|
// val ----------------------------------------
|
|
|
|
template<class T> |
|
|
|
struct val_str_helper { |
|
|
|
static std::string str(T c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
//value
|
|
|
|
std::stringstream ss_val{}; |
|
|
|
ss_val << c; |
|
|
|
|
|
|
|
return pEp::Utils::clip(ss_val.str(), val_len); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
struct val_str_helper<T*> { |
|
|
|
static std::string str(T* c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
//value
|
|
|
|
std::stringstream ss_val{}; |
|
|
|
if (c != nullptr) { |
|
|
|
ss_val << &c; |
|
|
|
} else { |
|
|
|
ss_val << "<NULL>"; |
|
|
|
} |
|
|
|
|
|
|
|
return pEp::Utils::clip(ss_val.str(), val_len); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// returns the value of c (if T is pointer type, the address p is pointing to)
|
|
|
|
template<class T> |
|
|
|
std::string val_str(T c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
return val_str_helper<T>::str(c, val_len); |
|
|
|
} |
|
|
|
|
|
|
|
// type_addr_val ----------------------------------------
|
|
|
|
template<class T> |
|
|
|
struct type_addr_val_helper { |
|
|
|
static std::string str(T c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
std::stringstream ret{}; |
|
|
|
ret << "{ " << type_str(c) << " | " << addr_str(c) << " | " << val_str(c, val_len) |
|
|
|
<< " }"; |
|
|
|
return ret.str(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
struct type_addr_val_helper<T*> { |
|
|
|
static std::string str(T* c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
std::stringstream ret{}; |
|
|
|
ret << "{ " << type_str(c) << " | " << addr_str(c) << " | " << val_str(c, val_len) |
|
|
|
<< " }"; |
|
|
|
return ret.str(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
std::string type_addr_val(T c, size_t val_len = 30) |
|
|
|
{ |
|
|
|
return type_addr_val_helper<T>::str(c, val_len); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace pEp
|
|
|
|
|
|
|
|
namespace pEp { |
|
|
|
|
|
|
|
char* alloc(const std::string& str) |
|
|
|
{ |
|
|
|
char* ret = strdup(str.c_str()); |
|
|
@ -71,7 +153,88 @@ namespace pEp { |
|
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
#define EXSTR(msg) std::string(__FUNCTION__) + " - " + msg |
|
|
|
|
|
|
|
class PODBase { |
|
|
|
public: |
|
|
|
static bool log_enabled; |
|
|
|
|
|
|
|
protected: |
|
|
|
bool _is_initialized{ false }; |
|
|
|
|
|
|
|
Adapter::pEpLog::pEpLogger logger{ "pEp::Enum", log_enabled }; |
|
|
|
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger; |
|
|
|
}; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
class POD : public PODBase { |
|
|
|
static_assert(std::is_pod<T>::value, "only POD types are allowed"); |
|
|
|
|
|
|
|
public: |
|
|
|
POD() = delete; |
|
|
|
|
|
|
|
explicit POD(T* pod_p) |
|
|
|
{ |
|
|
|
if (pod_p == nullptr) { |
|
|
|
throw Exception{ EXSTR("cant initialize on a nullptr") }; |
|
|
|
} |
|
|
|
|
|
|
|
// init
|
|
|
|
_pod_p = pod_p; |
|
|
|
pEpLogClass(to_string() + " - taking ownership"); |
|
|
|
} |
|
|
|
|
|
|
|
// make a copy
|
|
|
|
POD& operator=(T value) |
|
|
|
{ |
|
|
|
pEpLogClass("Before: " + to_string() + " - new val: '" + val_str(value) + "'"); |
|
|
|
|
|
|
|
*_pod_p = value; |
|
|
|
pEpLogClass("After: " + to_string()); |
|
|
|
return *this; |
|
|
|
} |
|
|
|
|
|
|
|
// return a copy
|
|
|
|
operator T() const |
|
|
|
{ |
|
|
|
return *_pod_p; |
|
|
|
} |
|
|
|
|
|
|
|
// return address of the wrappee
|
|
|
|
T* data() |
|
|
|
{ |
|
|
|
return _pod_p; |
|
|
|
} |
|
|
|
|
|
|
|
// return address of the wrappee (const)
|
|
|
|
const T* c_data() const |
|
|
|
{ |
|
|
|
return _pod_p; |
|
|
|
} |
|
|
|
|
|
|
|
std::string to_string() const |
|
|
|
{ |
|
|
|
std::string ret{ "[" + type_addr_val(_pod_p) + "]" }; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
bool _is_initialized{ false }; |
|
|
|
T* _pod_p{ nullptr }; |
|
|
|
|
|
|
|
class Exception : public std::runtime_error { |
|
|
|
public: |
|
|
|
explicit Exception(const std::string& msg) : std::runtime_error(msg) {} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
bool pEp::PODBase::log_enabled{ true }; |
|
|
|
|
|
|
|
template<class T> |
|
|
|
std::ostream& operator<<(std::ostream& o, pEp::POD<T> pEpEnum) |
|
|
|
{ |
|
|
|
return o << (int)pEpEnum; |
|
|
|
} |
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------------------
|
|
|
|
// Manages a char* to appear like a std::string
|
|
|
|
// char* c_str
|
|
|
|
// c_str MUST point to either:
|
|
|
@ -86,8 +249,6 @@ namespace pEp { |
|
|
|
// set() can only be called once, will throw otherwise.
|
|
|
|
class String { |
|
|
|
public: |
|
|
|
// Usually you _have_ to use this ctor, because its impossible to create a static
|
|
|
|
// object if you have to know the address of a dynamically created one.
|
|
|
|
String() = default; |
|
|
|
|
|
|
|
// Best to use this constructor, as the object is in a valid state when the wrapped
|
|
|
@ -139,7 +300,7 @@ namespace pEp { |
|
|
|
*_c_str_pp = pEp::alloc(str); |
|
|
|
_c_str_p = *_c_str_pp; |
|
|
|
} |
|
|
|
pEpLogClass("After: " + to_string()); |
|
|
|
pEpLogClass("After: " + to_string()); |
|
|
|
return *this; |
|
|
|
} |
|
|
|
|
|
|
@ -175,7 +336,8 @@ namespace pEp { |
|
|
|
throw Exception{ EXSTR("invalid state") }; |
|
|
|
} |
|
|
|
|
|
|
|
std::string ret{ "[" + type_addr_val(_c_str_pp) + " / " + type_addr_val(*_c_str_pp) + "]" }; |
|
|
|
std::string ret{ "[" + type_addr_val(_c_str_pp) + " / " + type_addr_val(*_c_str_pp) + |
|
|
|
"]" }; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
@ -321,13 +483,50 @@ void test_assign_and_getters(char** c_str_p, pEp::String& pstr) |
|
|
|
test_getters(c_str_p, pstr); |
|
|
|
} |
|
|
|
|
|
|
|
extern "C" { |
|
|
|
typedef enum |
|
|
|
{ |
|
|
|
SOBER, |
|
|
|
WHIPPY, |
|
|
|
YIPPIE, |
|
|
|
HOORAY |
|
|
|
} Drunk_level; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
char* name; |
|
|
|
Drunk_level drk; |
|
|
|
int btc_fanlevel; |
|
|
|
} SchlossInsasse; |
|
|
|
} |
|
|
|
|
|
|
|
int main() |
|
|
|
{ |
|
|
|
// pEp::Utils::readKey();
|
|
|
|
pEp::Adapter::pEpLog::set_enabled(true); |
|
|
|
|
|
|
|
|
|
|
|
SchlossInsasse tschappy; |
|
|
|
tschappy.name = strdup("tschappy"); |
|
|
|
tschappy.drk = YIPPIE; |
|
|
|
tschappy.btc_fanlevel = 100; |
|
|
|
|
|
|
|
pEp::POD<::Drunk_level> penum(&tschappy.drk); |
|
|
|
pEpLog(tschappy.drk); |
|
|
|
pEpLog(penum); |
|
|
|
penum = HOORAY; |
|
|
|
pEpLog(tschappy.drk); |
|
|
|
pEpLog(penum); |
|
|
|
|
|
|
|
pEp::POD<int> pint(&tschappy.btc_fanlevel); |
|
|
|
pEpLog(tschappy.btc_fanlevel); |
|
|
|
pEpLog(pint); |
|
|
|
pint = 33; |
|
|
|
pEpLog(tschappy.btc_fanlevel); |
|
|
|
pEpLog(pint); |
|
|
|
|
|
|
|
|
|
|
|
// pEp::String::log_enabled = false;
|
|
|
|
if (1) { |
|
|
|
if (0) { |
|
|
|
// INVALID USAGE
|
|
|
|
// char* c_str_u; // uninitialized == INVALID
|
|
|
|
// undefined behaviour, most likely "pointer being freed was not allocated"
|
|
|
@ -374,21 +573,23 @@ int main() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
setenv("HOME", ".", 1); |
|
|
|
::init(&session, nullptr, nullptr, nullptr); |
|
|
|
if (0) { |
|
|
|
setenv("HOME", ".", 1); |
|
|
|
::init(&session, nullptr, nullptr, nullptr); |
|
|
|
|
|
|
|
// create identity
|
|
|
|
pEp::Identity id1{ "wrong@entry.lol", "wrong", "23", "INVA_FPR" }; |
|
|
|
// create identity
|
|
|
|
pEp::Identity id1{ "wrong@entry.lol", "wrong", "23", "INVA_FPR" }; |
|
|
|
|
|
|
|
pEpLog(*id1); |
|
|
|
id1.username = "alice"; |
|
|
|
id1.address = "alice@peptest.org"; |
|
|
|
pEpLog(id1.address); |
|
|
|
pEpLog(id1.username); |
|
|
|
::myself(session, id1); |
|
|
|
pEpLog(*id1); |
|
|
|
pEpLog(*id1); |
|
|
|
id1.username = "alice"; |
|
|
|
id1.address = "alice@peptest.org"; |
|
|
|
pEpLog(id1.address); |
|
|
|
pEpLog(id1.username); |
|
|
|
::myself(session, id1); |
|
|
|
pEpLog(*id1); |
|
|
|
|
|
|
|
pEp::Identity id2{ "bob" }; |
|
|
|
::update_identity(session, id2); |
|
|
|
pEpLog(*id2); |
|
|
|
pEp::Identity id2{ "bob" }; |
|
|
|
::update_identity(session, id2); |
|
|
|
pEpLog(*id2); |
|
|
|
} |
|
|
|
} |
|
|
|