You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
12 KiB
414 lines
12 KiB
#include <iostream>
|
|
#include <cctype>
|
|
#include <pEp/pEpEngine.h>
|
|
#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>
|
|
#include <type_traits>
|
|
//#include "../examples/libc99/libc99.h"
|
|
#include "../src/prototype.hh"
|
|
|
|
void test_getters(int* c_int_p, pEp::POD<int>& pint, int expected)
|
|
{
|
|
// pEpLog("to_string(): " + pint.to_string());
|
|
// compare addresses
|
|
pEpLog("addresses == c_int_p");
|
|
assert(pint.c_data() == c_int_p);
|
|
assert(pint.data() == c_int_p);
|
|
|
|
// compare values
|
|
if (c_int_p != nullptr) {
|
|
pEpLog("operator int(): " + std::to_string(pint));
|
|
assert(pint == *c_int_p);
|
|
assert(pint == expected);
|
|
|
|
// will segfault with nullptr, and this is correct
|
|
pEpLog("data(): " + std::to_string(*pint.data()));
|
|
assert(*pint.data() == *c_int_p);
|
|
assert(*pint.data() == expected);
|
|
|
|
pEpLog("c_data(): " + std::to_string(*pint.c_data()));
|
|
assert(*pint.c_data() == *c_int_p);
|
|
assert(*pint.c_data() == expected);
|
|
}
|
|
}
|
|
|
|
void test_assign(int* c_int_p, pEp::POD<int>& pint)
|
|
{
|
|
{
|
|
pEpLogH2("assign operator");
|
|
int new_val = 23;
|
|
pint = new_val;
|
|
test_getters(c_int_p, pint, new_val);
|
|
}
|
|
{
|
|
pEpLogH2("raw c_str assign");
|
|
int new_val = 23;
|
|
*c_int_p = new_val;
|
|
test_getters(c_int_p, pint, new_val);
|
|
}
|
|
}
|
|
|
|
|
|
void test_getters(char** c_str_p, pEp::String& pstr, const std::string& expected)
|
|
{
|
|
pEpLog("to_string(): " + pstr.to_string());
|
|
// compare addresses
|
|
pEpLog("addresses == c_str_p");
|
|
assert(pstr.c_data() == *c_str_p);
|
|
assert(pstr.obj() == c_str_p);
|
|
|
|
// compare values
|
|
if (*c_str_p != nullptr) {
|
|
pEpLog("operator std::string(): " + std::string(pstr));
|
|
assert(std::string(pstr) == std::string(*c_str_p));
|
|
assert(std::string(pstr) == expected);
|
|
|
|
// will segfault with nullptr, and this is correct
|
|
pEpLog("data(): " + std::string(*pstr.obj()));
|
|
assert(std::string(*pstr.obj()) == std::string(*c_str_p));
|
|
assert(std::string(*pstr.obj()) == expected);
|
|
|
|
pEpLog("c_data(): " + std::string(pstr.c_data()));
|
|
assert(std::string(pstr.c_data()) == std::string(*c_str_p));
|
|
assert(std::string(pstr.c_data()) == expected);
|
|
} else {
|
|
std::string tmp{ pstr };
|
|
pEpLog("operator std::string(): " + tmp);
|
|
assert(tmp.empty());
|
|
}
|
|
}
|
|
|
|
void test_assign(char** c_str_p, pEp::String& pstr)
|
|
{
|
|
{
|
|
pEpLogH2("assign operator");
|
|
std::string new_val{ "assign operator" };
|
|
pstr = new_val;
|
|
test_getters(c_str_p, pstr, new_val);
|
|
}
|
|
{
|
|
pEpLogH2("raw c_str assign");
|
|
std::string new_val{ "raw c_str assign" };
|
|
free(*c_str_p);
|
|
*c_str_p = strdup(new_val.c_str());
|
|
test_getters(c_str_p, pstr, new_val);
|
|
}
|
|
}
|
|
|
|
|
|
//void test_func1(char** out) {
|
|
// *out = strdup("fds");
|
|
//}
|
|
|
|
|
|
int main()
|
|
{
|
|
// c-types are always POD
|
|
// we need to handle pointer types and value types differently
|
|
// pointer types need to be memory-managed (heap)
|
|
// value types are being copied around (stack)
|
|
static_assert(std::is_pod<int>::value && !std::is_pointer<int>::value, "not an integral");
|
|
static_assert(
|
|
std::is_pod<::C99_Enum>::value && !std::is_pointer<::C99_Enum>::value,
|
|
"not an integral");
|
|
static_assert(std::is_pod<::C99_B>::value && !std::is_pointer<::C99_B>::value, "not an integral");
|
|
|
|
// pEp::Utils::readKey();
|
|
pEp::Adapter::pEpLog::set_enabled(true);
|
|
|
|
// char* tmp = strdup("fd");
|
|
// std::cout << pEp::CXX::Inspect::all(tmp) << std::endl;
|
|
// change_ptr(tmp);
|
|
// std::cout << pEp::CXX::Inspect::all(tmp) << std::endl;
|
|
|
|
// char *ht;
|
|
// pEp::String tmp1{true,&ht};
|
|
//
|
|
// test_func1(tmp1);
|
|
// std::cout << tmp1;
|
|
|
|
// POD
|
|
if (0) {
|
|
// VALID USAGE
|
|
int init_val = 0;
|
|
// new pEp::POD on int
|
|
{
|
|
pEpLogH1("new pEp::POD on int");
|
|
int c_int = init_val;
|
|
pEp::POD<int> pint(&c_int);
|
|
test_getters(&c_int, pint, init_val);
|
|
test_assign(&c_int, pint);
|
|
}
|
|
// equality operator
|
|
{
|
|
pEpLogH1("equality operator");
|
|
int c_int1 = init_val;
|
|
int c_int2 = init_val;
|
|
pEp::POD<int> pint1(&c_int1);
|
|
pEp::POD<int> pint2(&c_int2);
|
|
assert(pint1 == pint2);
|
|
|
|
c_int2 = 23;
|
|
assert(pint1 != pint2);
|
|
}
|
|
}
|
|
|
|
// String
|
|
// pEp::String::log_enabled = false;
|
|
if (0) {
|
|
//TODO: Test non-owning mode
|
|
//
|
|
// INVALID USAGE
|
|
// char* c_str_u; // uninitialized == INVALID
|
|
// undefined behaviour, most likely "pointer being freed was not allocated"
|
|
// {
|
|
// char* c_str;
|
|
// pEp::String pstr(c_str);
|
|
// }
|
|
// char* c_str_s = "fdsfs"; // statically initialized == INVALID
|
|
// {
|
|
// char ca[4] = { 'p', 'E', 'p'};
|
|
// char* c_str = ca;
|
|
// pEp::String pstr(c_str);
|
|
// }
|
|
|
|
// VALID USAGE
|
|
{
|
|
pEpLogH1("new pEp::String on char* pointing to NULL");
|
|
char* c_str = NULL; // nullptr
|
|
|
|
pEp::String pstr(&c_str);
|
|
test_getters(&c_str, pstr, "");
|
|
test_assign(&c_str, pstr);
|
|
}
|
|
|
|
std::string init_val{ "initialized c string" };
|
|
{
|
|
pEpLogH1("new pEp::String on already initalized char*");
|
|
char* c_str = strdup(init_val.c_str());
|
|
|
|
pEp::String pstr(&c_str);
|
|
test_getters(&c_str, pstr, init_val);
|
|
test_assign(&c_str, pstr);
|
|
}
|
|
|
|
// equality operator
|
|
{
|
|
pEpLogH1("equality operator");
|
|
|
|
char* c_str1 = strdup(init_val.c_str());
|
|
char* c_str2 = strdup(init_val.c_str());
|
|
pEp::String pstr1{ &c_str1 };
|
|
pEp::String pstr2{ &c_str2 };
|
|
assert(pstr1 == pstr2);
|
|
pstr2 = "huhu";
|
|
assert(pstr1 != pstr2);
|
|
}
|
|
}
|
|
|
|
|
|
if (1) {
|
|
pEpLogH2("Create a sleeve and an instance");
|
|
int i = 23;
|
|
pEp::Sleeve<int> ot_i{ i };
|
|
|
|
|
|
pEpLog(pEp::CXX::Inspect::all(i));
|
|
pEpLog(ot_i.to_string());
|
|
assert(ot_i == i);
|
|
assert(!ot_i.is(i));
|
|
|
|
pEpLogH3("change from C++ / POTS");
|
|
pEp::Sleeve<int> i_pots{42};
|
|
ot_i = i_pots;
|
|
assert(ot_i == i_pots);
|
|
assert(!ot_i.is(i_pots));
|
|
|
|
pEpLogH3("change from C++ / native");
|
|
int i_native = 23;
|
|
ot_i = i_native;
|
|
assert(ot_i == i_native);
|
|
assert(!ot_i.is(i_native));
|
|
|
|
pEpLogH3("change from C99");
|
|
i = 42;
|
|
int* pi = ot_i.obj_ptr();
|
|
*pi = i;
|
|
assert(ot_i == i);
|
|
assert(!ot_i.is(i));
|
|
}
|
|
|
|
if (1) {
|
|
pEpLogH2("create a sleeve on an instance, static");
|
|
int i{ 23 };
|
|
pEp::Sleeve<int> ot_i{ &i };
|
|
pEpLog(pEp::CXX::Inspect::all(i));
|
|
pEpLog(ot_i.to_string());
|
|
assert(ot_i == i);
|
|
assert(ot_i.is(i));
|
|
|
|
pEpLogH3("change from C++ / POTS");
|
|
pEp::Sleeve<int> i_pots{42};
|
|
ot_i = i_pots;
|
|
assert(ot_i == i_pots);
|
|
assert(!ot_i.is(i_pots));
|
|
|
|
pEpLogH3("change from C++ / native");
|
|
int i_native = 23;
|
|
ot_i = i_native;
|
|
assert(ot_i == i_native);
|
|
assert(!ot_i.is(i_native));
|
|
|
|
pEpLogH3("change from C99");
|
|
i = 42;
|
|
int* pi = ot_i.obj_ptr();
|
|
*pi = i;
|
|
assert(ot_i == i);
|
|
assert(ot_i.is(i));
|
|
}
|
|
|
|
if (1) {
|
|
pEpLogH2("create a sleeve on an instance, dynamic");
|
|
int i{ 23 };
|
|
pEp::Sleeve<int> ot_i{ [&i](){ return &i;} };
|
|
pEpLog(pEp::CXX::Inspect::all(i));
|
|
pEpLog(ot_i.to_string());
|
|
assert(ot_i == i);
|
|
assert(ot_i.is(i));
|
|
|
|
pEpLogH3("change from C++ / POTS");
|
|
pEp::Sleeve<int> i_pots{42};
|
|
ot_i = i_pots;
|
|
assert(ot_i == i_pots);
|
|
assert(!ot_i.is(i_pots));
|
|
|
|
pEpLogH3("change from C++ / native");
|
|
int i_native = 23;
|
|
ot_i = i_native;
|
|
assert(ot_i == i_native);
|
|
assert(!ot_i.is(i_native));
|
|
|
|
pEpLogH3("change from C99");
|
|
i = 42;
|
|
int* pi = ot_i.obj_ptr();
|
|
*pi = i;
|
|
assert(ot_i == i);
|
|
assert(ot_i.is(i));
|
|
}
|
|
|
|
// Struct
|
|
/* if (0) {
|
|
// sleeve empty
|
|
{
|
|
pEp::Sleeve<::B> pstruct1{ nullptr };
|
|
const B* cc_struct = pstruct1;
|
|
B* c_struct = pstruct1;
|
|
assert(pstruct1.data() == nullptr);
|
|
assert(pstruct1.c_data() == nullptr);
|
|
assert(c_struct == nullptr);
|
|
assert(cc_struct == nullptr);
|
|
pEpLog("DONE");
|
|
|
|
// return_struct(pstruct1);
|
|
}
|
|
|
|
// Creates a sleeve managing and holding a newly created object
|
|
{
|
|
pEp::Sleeve<::B> pstruct1{};
|
|
B* c_struct = pstruct1;
|
|
c_struct->c_int = 3;
|
|
c_struct->c_str = std::string("huhu").data();
|
|
c_struct->c_enum = TWO;
|
|
pEpLog("DONE");
|
|
}
|
|
|
|
// Create a sleeve managing and holding an already existing object
|
|
{
|
|
// create an object
|
|
::B* c_struct1 = ::new_B(0, ONE, "pEp");
|
|
pEpLog(c_struct1->c_int);
|
|
pEpLog(c_struct1->c_enum);
|
|
pEpLog(c_struct1->c_str);
|
|
pEpLog("DONE");
|
|
|
|
// reference the object
|
|
pEp::Sleeve<::B> pstruct1{ c_struct1 };
|
|
pEpLog("DONE");
|
|
}
|
|
|
|
// Create a sleeve managing a C-sleeve
|
|
{
|
|
|
|
B* c_struct = nullptr;
|
|
pEp::Sleeve<::B> pstruct1{ &c_struct };
|
|
// c_struct->c_str = strdup("pEp");
|
|
// c_struct->c_int = 5;
|
|
// c_struct->c_enum = TWO;
|
|
}
|
|
}
|
|
*/
|
|
// Calling conventions
|
|
// pEp::Utils::readKey();
|
|
// {
|
|
// pEpLogH1("use_struct()");
|
|
// {
|
|
// pEp::A a{};
|
|
// use_struct(a);
|
|
// }
|
|
// pEpLogH1("c99_supply_struct()");
|
|
// {
|
|
// int val = 23;
|
|
// // C99
|
|
// {
|
|
// // prepare data structure
|
|
// ::C99_A* c_a = ::c99_A_new();
|
|
// c_a->b = c99_B_new();
|
|
// c_a->b->c = c99_C_new();
|
|
// c_a->b->c->pi = (int*)calloc(1, sizeof(int));
|
|
// *c_a->b->c->pi = val;
|
|
//
|
|
// // call supply
|
|
// ::C99_Status status = c99_supply_struct(c_a);
|
|
//
|
|
// // test
|
|
// assert(!status);
|
|
// assert(*c_a->b->c->pi == val * 2);
|
|
// }
|
|
|
|
// C++
|
|
{
|
|
|
|
// a = b;
|
|
// b = 5
|
|
// a.b = pEp::B{};
|
|
// a.b.c = pEp::C{};
|
|
// a.b.c.pi = (int*)calloc(1, sizeof(int));
|
|
// a.b.c.pi = 23;
|
|
// ::Status status = supply_struct(a);
|
|
// test
|
|
// assert(!status);
|
|
// assert(*a.b.c.pi == val * 2);
|
|
}
|
|
// pstruct1.c_int
|
|
// }
|
|
// pEpLogH1("provide_struct()");
|
|
// {
|
|
// pEp::A a{};
|
|
// //release ownership
|
|
// provide_struct(a);
|
|
// }
|
|
// pEpLogH1("return_struct()");
|
|
// {
|
|
// A* a = NULL;
|
|
// return_struct(&a);
|
|
// pEp::A pa{ a };
|
|
// pEpLog(*(pa.b.c.pi.data()));
|
|
// }
|
|
// }
|
|
return 0;
|
|
}
|
|
|