diff --git a/test/test_nr1.cc b/test/test_nr1.cc index 564b1a1..f9a75cd 100644 --- a/test/test_nr1.cc +++ b/test/test_nr1.cc @@ -13,32 +13,114 @@ namespace pEp { + // type ---------------------------------------- + // same for pointer and value typee template - std::string type_addr_val(const T c, size_t val_len = 30) + std::string type_str(const T) { - static_assert(std::is_pointer::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(c); - //value - std::stringstream ss_val{}; - if (c != nullptr) { - ss_val << "\"" << c << "\""; - } else { - ss_val << ""; + // addr ---------------------------------------- + template + struct addr_str_helper { + static std::string str(const T c) + { + std::stringstream ss_addr{}; + ss_addr << static_cast(&c); + return ss_addr.str(); + } + }; + + template + struct addr_str_helper { + static std::string str(const T* c) + { + std::stringstream ss_addr{}; + ss_addr << static_cast(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 + std::string addr_str(T c) + { + return addr_str_helper::str(c); } + // val ---------------------------------------- + template + 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 + struct val_str_helper { + 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 << ""; + } + + 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 + std::string val_str(T c, size_t val_len = 30) + { + return val_str_helper::str(c, val_len); + } + + // type_addr_val ---------------------------------------- + template + 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 + 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 + std::string type_addr_val(T c, size_t val_len = 30) + { + return type_addr_val_helper::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 POD : public PODBase { + static_assert(std::is_pod::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 + std::ostream& operator<<(std::ostream& o, pEp::POD 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 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); + } }