Browse Source

prtotype: make struct wrapper generic

heck-rework
heck 3 years ago
parent
commit
79a3dfecf8
  1. 135
      test/test_nr1.cc

135
test/test_nr1.cc

@ -4,6 +4,7 @@
#include <pEp/message_api.h>
#include <pEp/keymanagement.h>
#include <pEp/identity_list.h>
#include <utility>
#include <pEp/utils.hh>
#include <pEp/pEpLog.hh>
#include <pEp/inspect.hh>
@ -42,7 +43,7 @@ namespace pEp {
//---------------------------------------------------------------------------------------------
#define EXSTR(msg) std::string(__FUNCTION__) + " - " + msg
#define EXSTR(msg) std::string(__FUNCTION__) + "() - " + msg
template<class T>
class POD {
@ -431,35 +432,36 @@ void test_assign(char** c_str_p, pEp::String& pstr)
namespace pEp {
// TOOD:
// ctor not exception safe
class TestStruct1 {
// You can create an instance of a c-struct or you can wrap an already existing c-struct
// In both cases, you can define if the wrapper owns the instance, or not.
// If if owns it, it will free() it when the wrapper dies, otherwise it doesnt.
template<typename T>
class PODStruct {
public:
// Create a new instance
TestStruct1(int i, ::Test_enum e, const std::string& str)
{
pEpLogClass("called");
_c_struct_p = ::new_test_struct(0, ONE, nullptr); //dont use raw-setters
bind(true, &_c_struct_p);
// need to use these setter because of value conversions
this->c_int = i;
this->c_enum = e;
this->c_str = str;
}
PODStruct() = delete;
// Wrap an existing instance
TestStruct1()
// Creates a new instance or binds an existing one
PODStruct(
bool is_owner,
std::function<T*()> alloc,
std::function<void(T*)> free,
T** c_struct_pp = nullptr) :
_alloc(std::move(alloc)),
_free(std::move(free))
{
pEpLogClass("called");
}
// Best to use this constructor, as the object is in a valid state when the wrapped
// c_struct_pp is known
TestStruct1(bool is_owner, ::Test_struct1** c_struct_pp)
{
pEpLogClass("called");
bind(is_owner, c_struct_pp);
// if no pp is given, alloc new,
// otherwise bind to it
if (!c_struct_pp) {
_c_struct_p = _alloc();
bind(is_owner, &_c_struct_p);
} else {
bind(is_owner, c_struct_pp);
}
}
void bind(bool is_owner, ::Test_struct1** c_struct_pp)
void bind(bool is_owner, T** c_struct_pp)
{
if (c_struct_pp == nullptr) {
throw Exception{ EXSTR("cant bind on a nullptr") };
@ -474,18 +476,17 @@ namespace pEp {
_c_struct_p = *_c_struct_pp;
_is_bound = true;
pEpLogClass(to_string());
_bind_members();
set_owner(is_owner);
}
~TestStruct1()
~PODStruct()
{
if (_is_owner) {
_free();
_free(_c_struct_p);
}
}
operator ::Test_struct1*()
operator T*()
{
return _c_struct_p;
}
@ -507,31 +508,18 @@ namespace pEp {
return _is_owner;
}
pEp::POD<int> c_int{};
pEp::POD<::Test_enum> c_enum{};
pEp::String c_str{};
static bool log_enabled;
private:
void _bind_members()
{
this->c_int.bind(&_c_struct_p->c_int);
this->c_enum.bind(&_c_struct_p->c_enum);
this->c_str.bind(false, &_c_struct_p->c_str);
}
protected:
const std::function<T*()> _alloc;
const std::function<void(T*)> _free;
void _free()
{
pEpLogClass("called");
::free_test_struct(_c_struct_p);
}
bool _is_bound{ false };
bool _is_owner{ false };
::Test_struct1** _c_struct_pp{ nullptr };
::Test_struct1* _c_struct_p{ nullptr };
T** _c_struct_pp{ nullptr };
T* _c_struct_p{ nullptr };
Adapter::pEpLog::pEpLogger logger{ "TestStruct", log_enabled };
Adapter::pEpLog::pEpLogger logger{ "typeid(T).name()", log_enabled };
Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
class Exception : public std::runtime_error {
@ -540,8 +528,43 @@ namespace pEp {
};
};
// TOOD:
// ctor not exception safe
// You can create an instance of a c-struct or you can wrap an already existing c-struct
// In both cases, you can define if the wrapper owns the instance, or not.
// If if owns it, it will free() it when the wrapper dies, otherwise it doesnt.
//
// alloc/free:
// the alloc() and free() functions HAVE to use calloc/malloc NOT 'new', because we are interfacing
// c99 code, that could possible get ownership of the struct and can only free memory that has
// been allocated using malloc/calloc. (malloc/free - new/delete are NOT compatible)
class TestStruct1 : public PODStruct<::Test_struct1> {
public:
TestStruct1(bool is_owner, ::Test_struct1** test_struct1_p = nullptr) :
PODStruct<::Test_struct1>(is_owner, _alloc, _free, test_struct1_p)
{
}
// fields of the struct as 'properties' ;)
pEp::POD<int> c_int{ &_c_struct_p->c_int };
pEp::POD<::Test_enum> c_enum{ &_c_struct_p->c_enum };
pEp::String c_str{ false, &_c_struct_p->c_str,"fd" };
private:
static Test_struct1* _alloc()
{
return (Test_struct1*)calloc(1, sizeof(Test_struct1));
}
static void _free(Test_struct1* ptr)
{
pEpLog("called");
::free_test_struct(ptr);
}
};
bool TestStruct1::log_enabled{ true };
template<>
bool PODStruct<::Test_struct1>::log_enabled{ true };
} // namespace pEp
@ -559,7 +582,7 @@ int main()
std::is_pod<::Test_struct1>::value && !std::is_pointer<::Test_struct1>::value,
"not an integral");
// pEp::Utils::readKey();
pEp::Utils::readKey();
pEp::Adapter::pEpLog::set_enabled(true);
// POD
@ -590,7 +613,7 @@ int main()
// String
// pEp::String::log_enabled = false;
if (1) {
if (0) {
//TODO: Test non-owning mode
// INVALID USAGE
@ -657,10 +680,11 @@ int main()
}
// Struct
if (0) {
// create
{
pEp::TestStruct1 pstruct1(23, TWO, "pEp");
if (1) {
// create an instance
if (0) {
pEp::TestStruct1 pstruct1{ true };
// pEp::TestStruct1 pstruct1(true, 23, TWO, "pEp");
pEpLog(pstruct1.c_int);
pEpLog(pstruct1.c_enum);
pEpLog(pstruct1.c_str);
@ -672,9 +696,9 @@ int main()
pEpLog("DONE");
}
// wrap
// wrap already existing instance
{
::Test_struct1* c_struct1 = new_test_struct(0, ONE, "pEp");
::Test_struct1* c_struct1 = ::new_test_struct(0, ONE, "pEp");
pEpLog(c_struct1->c_int);
pEpLog(c_struct1->c_enum);
pEpLog(c_struct1->c_str);
@ -684,6 +708,7 @@ int main()
pEpLog(pstruct1.c_int);
pEpLog(pstruct1.c_enum);
pEpLog(pstruct1.c_str);
pEpLog("DONE");
}
}

Loading…
Cancel
Save