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/message_api.h>
#include <pEp/keymanagement.h> #include <pEp/keymanagement.h>
#include <pEp/identity_list.h> #include <pEp/identity_list.h>
#include <utility>
#include <pEp/utils.hh> #include <pEp/utils.hh>
#include <pEp/pEpLog.hh> #include <pEp/pEpLog.hh>
#include <pEp/inspect.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> template<class T>
class POD { class POD {
@ -431,35 +432,36 @@ void test_assign(char** c_str_p, pEp::String& pstr)
namespace pEp { namespace pEp {
// TOOD: // TOOD:
// ctor not exception safe // 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: public:
// Create a new instance PODStruct() = delete;
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;
}
// Wrap an existing instance // Creates a new instance or binds an existing one
TestStruct1() 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"); pEpLogClass("called");
}
// Best to use this constructor, as the object is in a valid state when the wrapped // if no pp is given, alloc new,
// c_struct_pp is known // otherwise bind to it
TestStruct1(bool is_owner, ::Test_struct1** c_struct_pp) if (!c_struct_pp) {
{ _c_struct_p = _alloc();
pEpLogClass("called"); bind(is_owner, &_c_struct_p);
bind(is_owner, c_struct_pp); } 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) { if (c_struct_pp == nullptr) {
throw Exception{ EXSTR("cant bind on a nullptr") }; throw Exception{ EXSTR("cant bind on a nullptr") };
@ -474,18 +476,17 @@ namespace pEp {
_c_struct_p = *_c_struct_pp; _c_struct_p = *_c_struct_pp;
_is_bound = true; _is_bound = true;
pEpLogClass(to_string()); pEpLogClass(to_string());
_bind_members();
set_owner(is_owner); set_owner(is_owner);
} }
~TestStruct1() ~PODStruct()
{ {
if (_is_owner) { if (_is_owner) {
_free(); _free(_c_struct_p);
} }
} }
operator ::Test_struct1*() operator T*()
{ {
return _c_struct_p; return _c_struct_p;
} }
@ -507,31 +508,18 @@ namespace pEp {
return _is_owner; return _is_owner;
} }
pEp::POD<int> c_int{};
pEp::POD<::Test_enum> c_enum{};
pEp::String c_str{};
static bool log_enabled; static bool log_enabled;
private: protected:
void _bind_members() const std::function<T*()> _alloc;
{ const std::function<void(T*)> _free;
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);
}
void _free()
{
pEpLogClass("called");
::free_test_struct(_c_struct_p);
}
bool _is_bound{ false }; bool _is_bound{ false };
bool _is_owner{ false }; bool _is_owner{ false };
::Test_struct1** _c_struct_pp{ nullptr }; T** _c_struct_pp{ nullptr };
::Test_struct1* _c_struct_p{ 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; Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
class Exception : public std::runtime_error { 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 } // namespace pEp
@ -559,7 +582,7 @@ int main()
std::is_pod<::Test_struct1>::value && !std::is_pointer<::Test_struct1>::value, std::is_pod<::Test_struct1>::value && !std::is_pointer<::Test_struct1>::value,
"not an integral"); "not an integral");
// pEp::Utils::readKey(); pEp::Utils::readKey();
pEp::Adapter::pEpLog::set_enabled(true); pEp::Adapter::pEpLog::set_enabled(true);
// POD // POD
@ -590,7 +613,7 @@ int main()
// String // String
// pEp::String::log_enabled = false; // pEp::String::log_enabled = false;
if (1) { if (0) {
//TODO: Test non-owning mode //TODO: Test non-owning mode
// INVALID USAGE // INVALID USAGE
@ -657,10 +680,11 @@ int main()
} }
// Struct // Struct
if (0) { if (1) {
// create // create an instance
{ if (0) {
pEp::TestStruct1 pstruct1(23, TWO, "pEp"); pEp::TestStruct1 pstruct1{ true };
// pEp::TestStruct1 pstruct1(true, 23, TWO, "pEp");
pEpLog(pstruct1.c_int); pEpLog(pstruct1.c_int);
pEpLog(pstruct1.c_enum); pEpLog(pstruct1.c_enum);
pEpLog(pstruct1.c_str); pEpLog(pstruct1.c_str);
@ -672,9 +696,9 @@ int main()
pEpLog("DONE"); 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_int);
pEpLog(c_struct1->c_enum); pEpLog(c_struct1->c_enum);
pEpLog(c_struct1->c_str); pEpLog(c_struct1->c_str);
@ -684,6 +708,7 @@ int main()
pEpLog(pstruct1.c_int); pEpLog(pstruct1.c_int);
pEpLog(pstruct1.c_enum); pEpLog(pstruct1.c_enum);
pEpLog(pstruct1.c_str); pEpLog(pstruct1.c_str);
pEpLog("DONE");
} }
} }

Loading…
Cancel
Save