Browse Source

Add generic class 'POD', a generic POD-wrapper

heck-rework
heck 3 years ago
parent
commit
e49c88052d
  1. 271
      test/test_nr1.cc

271
test/test_nr1.cc

@ -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);
}
}

Loading…
Cancel
Save