diff --git a/include/token/cclass.h b/include/token/cclass.h index cf1cf3d..f1c0d25 100644 --- a/include/token/cclass.h +++ b/include/token/cclass.h @@ -32,33 +32,33 @@ extern const _CCLASS const __##_class; \ struct _##_class -#define ENDC(_class) } * _class; \ - extern const _CCLASS const __##_class; - typedef void (* ctor)(void *, va_list *); +typedef void (* clr)(void *); typedef void (* dtor)(void *); typedef void (* jCtor)(void *, struct json_object *); typedef void (* jTo)(void *, struct json_object **); - typedef struct CCLASS { const int magic; size_t size; void (* __construct)(void * _this, va_list * params); + void (* __clear)(void * _this); void (* __destruct)(void * _this); void (* __jsonConst)(void * _this, struct json_object * json); void (* __toJson)(void * _this, struct json_object ** json); } * _CCLASS; -#define CCLASS_PTR_SIZE sizeof(struct CCLASS *) -#define CCLASS_SIZE sizeof(struct CCLASS) +#define _CCLASS_SIZE sizeof(_CCLASS) +#define CCLASS_SIZE sizeof(struct CCLASS) #define __construct(class) static void __construct(class _this, va_list * params) +#define __clear(class) static void __clear(class _this) #define __destruct(class) static void __destruct(class _this) #define __jsonConst(class) static void __jsonConst(class _this, struct json_object * json) #define __toJson(class) static void __toJson(class _this, struct json_object ** json) #define INIT_CCLASS(class) \ __construct(class); \ + __clear(class); \ __destruct(class); \ __jsonConst(class); \ __toJson(class); \ @@ -66,6 +66,7 @@ typedef struct CCLASS { CCLASS_MAGIC, \ sizeof(struct _##class), \ (ctor)__construct, \ + (clr)__clear, \ (dtor)__destruct, \ (jCtor)__jsonConst, \ (jTo)__toJson \ @@ -73,6 +74,7 @@ typedef struct CCLASS { void * _new(const _CCLASS _class, ...); void * _newFromJson(const _CCLASS _class, struct json_object * json); +void clear(void * _object); void delete(void * _object); void toJson(void * _object, struct json_object ** json); int isObject(void * _object); diff --git a/include/token/dyntype.h b/include/token/dyntype.h index c6e60f1..caa4f98 100644 --- a/include/token/dyntype.h +++ b/include/token/dyntype.h @@ -40,11 +40,10 @@ enum DYNTYPE_TYPES { CLASS(DYNTYPE) { const _CCLASS const class; enum DYNTYPE_TYPES type; - size_t size; union _data { unsigned char _boolean; int _int; - double _float; + double _double; char * _string; struct _DYNTYPE ** _array; DYNTYPE_HASH _hash; @@ -53,6 +52,22 @@ CLASS(DYNTYPE) { #include "token/dyntype/hash.h" +#define dyntype_newBoolean(value) new(DYNTYPE, DYNTYPE_TYPE_BOOLEAN, value) +#define dyntype_newInt(value) new(DYNTYPE, DYNTYPE_TYPE_INT, value) +#define dyntype_newDouble(value) new(DYNTYPE, DYNTYPE_TYPE_DOUBLE, value) +#define dyntype_newString(value) new(DYNTYPE, DYNTYPE_TYPE_STRING, value) +#define dyntype_newArray(value) new(DYNTYPE, DYNTYPE_TYPE_ARRAY, value) +#define dyntype_newHash(value) new(DYNTYPE, DYNTYPE_TYPE_HASH, value) + +enum DYNTYPE_TYPES dyntype_getType(DYNTYPE _this); +size_t dyntype_getSize(DYNTYPE _this); +unsigned char dyntype_getBoolean(DYNTYPE _this); +int dyntype_getInt(DYNTYPE _this); +double dyntype_getDouble(DYNTYPE _this); +char * dyntype_getString(DYNTYPE _this); +DYNTYPE * dyntype_getArray(DYNTYPE _this); +DYNTYPE_HASH dyntype_getHash(DYNTYPE _this); + #endif//__DYNTYPE_H__ // vim: set et ts=4 sw=4: diff --git a/src/cclass.c b/src/cclass.c index 6d1713b..71c165c 100644 --- a/src/cclass.c +++ b/src/cclass.c @@ -23,6 +23,7 @@ #include "token/cclass.h" #undef __construct +#undef __clear #undef __destruct #undef __jsonConst #undef __toJson @@ -61,6 +62,16 @@ _newFromJson(const _CCLASS _class, struct json_object * json) return object; } +void +clear(void * _object) +{ + const struct CCLASS ** class = _object; + + if (_object && *class && (*class)->__clear) { + (*class)->__clear(_object); + } +} + void delete(void * _object) { @@ -97,7 +108,7 @@ _instanceOf(const _CCLASS _class, void * _object) { const struct CCLASS ** class = _object; - return (_class == *class); + return (class && _class == *class); } // vim: set et ts=4 sw=4: diff --git a/src/crypt.c b/src/crypt.c index 3bde1ee..8483c38 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -56,6 +56,7 @@ __destruct(CRYPT) __jsonConst(CRYPT) {} __toJson(CRYPT) {} +__clear(CRYPT) {} void * crypt_createIv(CRYPT _this) diff --git a/src/dyntype.c b/src/dyntype.c index 516fbe6..650722e 100644 --- a/src/dyntype.c +++ b/src/dyntype.c @@ -23,13 +23,22 @@ #include "token/dyntype.h" #include "token/dyntype/hash.h" +static +size_t _dyntype_sizes[] = { + 0, + sizeof(unsigned char), + sizeof(int), + sizeof(double), + sizeof(char *), + sizeof(DYNTYPE *), + sizeof(DYNTYPE_HASH) +}; INIT_CCLASS(DYNTYPE); __construct(DYNTYPE) { _this->type = va_arg(* params, enum DYNTYPE_TYPES); - _this->size = va_arg(* params, size_t); switch(_this->type) { case DYNTYPE_TYPE_INT: @@ -37,8 +46,13 @@ __construct(DYNTYPE) break; case DYNTYPE_TYPE_STRING: - (_this->data)._string = calloc(_this->size + 1, sizeof(char)); - memcpy((_this->data)._string, va_arg(* params, const char *), _this->size); + { + const char * string = va_arg(* params, const char *); + const size_t length = strlen(string); + + (_this->data)._string = calloc(length + 1, sizeof(char)); + memcpy((_this->data)._string, string, length); + } break; case DYNTYPE_TYPE_HASH: @@ -55,35 +69,34 @@ __jsonConst(DYNTYPE) switch (json_object_get_type(json)) { case json_type_int: _this->type = DYNTYPE_TYPE_INT; - _this->size = sizeof(int); (_this->data)._int = (int)json_object_get_int(json); break; case json_type_string: { const char * string = json_object_get_string(json); + const size_t length = strlen(string); _this->type = DYNTYPE_TYPE_STRING; - _this->size = strlen(string); - (_this->data)._string = calloc(_this->size + 1, sizeof(char)); - memcpy((_this->data)._string, string, _this->size); + (_this->data)._string = calloc(length + 1, sizeof(char)); + memcpy((_this->data)._string, string, length); // the json object handles the memory for string.... } break; case json_type_object: _this->type = DYNTYPE_TYPE_HASH; - _this->size = sizeof(DYNTYPE_HASH); (_this->data)._hash = newFromJson(DYNTYPE_HASH, json); break; default: _this->type = DYNTYPE_TYPE_NULL; - _this->size = 0; (_this->data)._hash = NULL; } } +__clear(DYNTYPE) {} + __destruct(DYNTYPE) { if (_this) { @@ -122,4 +135,53 @@ __toJson(DYNTYPE) } } +enum DYNTYPE_TYPES +dyntype_getType(DYNTYPE _this) +{ + return _this->type; +} + +size_t +dyntype_getSize(DYNTYPE _this) +{ + return _dyntype_sizes[_this->type]; +} + +unsigned char +dyntype_getBoolean(DYNTYPE _this) +{ + return (_this->data)._boolean; +} + +int +dyntype_getInt(DYNTYPE _this) +{ + return (_this->data)._int; +} + +double +dyntype_getDouble(DYNTYPE _this) +{ + return (_this->data)._double; +} + +char * +dyntype_getString(DYNTYPE _this) +{ + return (_this->data)._string; +} + +DYNTYPE * +dyntype_getArray(DYNTYPE _this) +{ + return (_this->data)._array; +} + +DYNTYPE_HASH +dyntype_getHash(DYNTYPE _this) +{ + return (_this->data)._hash; +} + + // vim: set et ts=4 sw=4: diff --git a/src/dyntype/hash.c b/src/dyntype/hash.c index 306098d..4a900e9 100644 --- a/src/dyntype/hash.c +++ b/src/dyntype/hash.c @@ -37,6 +37,7 @@ __construct(DYNTYPE_HASH) _this->used = 0; _updateHashSize(_this); } + #undef __construct __jsonConst(DYNTYPE_HASH) @@ -52,16 +53,22 @@ __jsonConst(DYNTYPE_HASH) } } +__clear(DYNTYPE_HASH) {} + __destruct(DYNTYPE_HASH) { size_t index; for (index = 0; index < _this->used; index ++) { free(_this->keys[index]); + delete(_this->values[index]); } free(_this->keys); free(_this->values); + + _this->size = _this->used = 0; + _updateHashSize(_this); } __toJson(DYNTYPE_HASH) diff --git a/src/packet.c b/src/packet.c index 9a37ef9..ef7d1ab 100644 --- a/src/packet.c +++ b/src/packet.c @@ -24,7 +24,23 @@ INIT_CCLASS(PACKET); __construct(PACKET) { - packet_set_default_content(_this); + DYNTYPE header = va_arg(* params, DYNTYPE); + DYNTYPE data = NULL; + + if (instanceOf(DYNTYPE, header)) { + data = va_arg(* params, DYNTYPE); + } + + if (instanceOf(DYNTYPE, data)) { + + packet_setHeader(_this, header); + packet_setData(_this, data); + + } else { + + packet_set_default_content(_this); + + } } __jsonConst(PACKET) @@ -49,7 +65,21 @@ __jsonConst(PACKET) packet_setData(_this, newFromJson(DYNTYPE, data)); } -__destruct(PACKET) {} +__clear(PACKET) {} + +__destruct(PACKET) +{ + DYNTYPE header = packet_getHeader(_this); + DYNTYPE data = packet_getData(_this); + + if (NULL != header) { + delete(&header); + } + + if (NULL != data) { + delete(&data); + } +} __toJson(PACKET) { diff --git a/tests/cclassTest.c b/tests/cclassTest.c index ba27b2b..c31e1ca 100644 --- a/tests/cclassTest.c +++ b/tests/cclassTest.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/tests/cryptTest.c b/tests/cryptTest.c index 5bc0622..6baf98e 100644 --- a/tests/cryptTest.c +++ b/tests/cryptTest.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/tests/mock/class.c b/tests/mock/class.c index da28fd3..41c06e7 100644 --- a/tests/mock/class.c +++ b/tests/mock/class.c @@ -22,6 +22,8 @@ __jsonConst(MOCK_CLASS) _this->value = json_object_get_int(json); } +__clear(MOCK_CLASS) {} + __destruct(MOCK_CLASS) { _called = 1; diff --git a/tests/packetTest.c b/tests/packetTest.c index 4f6afe5..62a89de 100644 --- a/tests/packetTest.c +++ b/tests/packetTest.c @@ -1,3 +1,5 @@ +#include + #include "runtest.h" #include "token/cclass.h" #include "token/packet.h" @@ -36,14 +38,59 @@ static int testDefaultInit() { + ASSERT_INSTANCE_OF(PACKET, packet); ASSERT_NULL(packet_getHeader(packet)); ASSERT_NULL(packet_getData(packet)); return TEST_OK; } +static +int +testParamInit1() +{ + __tearDown(); + + DYNTYPE header = dyntype_newInt(123); + packet = new(PACKET, header, NULL); + + ASSERT_INSTANCE_OF(PACKET, packet); + ASSERT_NULL(packet_getHeader(packet)); + ASSERT_NULL(packet_getData(packet)); + + delete(&header); + + return TEST_OK; +} + +static +int +testParamInit2() +{ + DYNTYPE header, data; + + __tearDown(); + + packet = new(PACKET, dyntype_newInt(123), dyntype_newInt(321)); + + ASSERT_INSTANCE_OF(PACKET, packet); + + header = packet_getHeader(packet); + data = packet_getData(packet); + + ASSERT_INSTANCE_OF(DYNTYPE, header); + ASSERT_INSTANCE_OF(DYNTYPE, data); + + ASSERT_EQUAL(123, dyntype_getInt(header)); + ASSERT_EQUAL(321, dyntype_getInt(data)); + + return TEST_OK; +} + const testfunc tests[] = { - testDefaultInit + testDefaultInit, + testParamInit1, + testParamInit2 }; const size_t count = FUNCS_COUNT(tests); diff --git a/tests/runtest.c b/tests/runtest.c index 8d5dea4..69c10b0 100644 --- a/tests/runtest.c +++ b/tests/runtest.c @@ -24,7 +24,7 @@ isObjectNull(void * _object) const struct CCLASS ** class = _object; ASSERT_OBJECT(_object); - ASSERT_MEM_NULL(_object + CCLASS_PTR_SIZE, (*class)->size - CCLASS_PTR_SIZE); + ASSERT_MEM_NULL(_object + _CCLASS_SIZE, (*class)->size - _CCLASS_SIZE); return TEST_OK; } diff --git a/tests/runtest.h b/tests/runtest.h index 401f4b9..ce6689c 100644 --- a/tests/runtest.h +++ b/tests/runtest.h @@ -11,26 +11,68 @@ enum RESULT_TYPES { TEST_ERROR }; -#define ASSERT_NULL(value) if (NULL != (value)) return TEST_FAILED -#define ASSERT_NOT_NULL(value) if (NULL == (value)) return TEST_FAILED -#define ASSERT_EQUAL(val1,val2) if ((val1) != (val2)) return TEST_FAILED -#define ASSERT_NOT_EQUAL(val1,val2) if ((val1) == (val2)) return TEST_FAILED +#define ASSERT_NULL(value) \ + if (NULL != (value)) { \ + printf("%s[%d]: Assertion failed that %s is NULL\n", \ + __FILE__, __LINE__, #value); \ + return TEST_FAILED; } + +#define ASSERT_NOT_NULL(value) \ + if (NULL == (value)) { \ + printf("%s[%d]: Assertion failed that %s is NOT NULL\n", \ + __FILE__, __LINE__, #value); \ + return TEST_FAILED; } + +#define ASSERT_EQUAL(val1,val2) \ + if ((val1) != (val2)) { \ + printf("%s[%d]: Assertion failed that %s equals %s\n", \ + __FILE__, __LINE__, #val1, #val2); \ + return TEST_FAILED; } + +#define ASSERT_NOT_EQUAL(val1,val2) \ + if ((val1) == (val2)) { \ + printf("%s[%d]: Assertion failed that %s not equals %2\n", \ + __FILE__, __LINE__, #val1, #val2); \ + return TEST_FAILED; } + #define ASSERT_MEM_EQUAL(val1,val2,size) \ - if(0 != memcmp((val1), (val2), (size))) return TEST_FAILED + if(0 != memcmp((val1), (val2), (size))) { \ + printf("%s[%d]: Assertion failed that memory at %s equals %s for %lu bytes\n", \ + __FILE__, __LINE__, #val1, #val2, size); \ + return TEST_FAILED; } + #define ASSERT_MEM_NOT_EQUAL(val1,val2,size) \ - if(0 == memcmp((val1), (val2), (size))) return TEST_FAILED -#define ASSERT_MEM_NULL(val, size) if (! isMemNull((val), (size))) return TEST_FAILED + if(0 == memcmp((val1), (val2), (size))) { \ + printf("%s[%d]: Assertion failed that memory at %s not equals %s for %lu bytes\n", \ + __FILE__, __LINE__, #val1, #val2, size); \ + return TEST_FAILED; } + +#define ASSERT_MEM_NULL(val, size) \ + if (! isMemNull((val), (size))) { \ + printf("%s[%d]: Assertion failed that memory at %s is NULL for %lu bytes\n", \ + __FILE__, __LINE__, #val, size); \ + return TEST_FAILED; } + #define ASSERT_MEM_NOT_NULL(val, size) \ - if (isMemNull((val), (size))) return TEST_FAILED + if (isMemNull((val), (size))) { \ + printf("%s[%d]: Assertion failed that memory at %s is NOT NULL for %lu bytes\n", \ + __FILE__, __LINE__, #val, size); \ + return TEST_FAILED; } + #define ASSERT_STRING_EQUAL(val1,val2) \ if(0 != strcmp((val1), (val2))) return TEST_FAILED #define ASSERT_STRING_NOT_EQUAL(val1,val2) \ if(0 == strcmp((val1), (val2))) return TEST_FAILED + #define ASSERT_OBJECT(val) if (! isObject((val))) return TEST_FAILED #define ASSERT_OBJECT_NULL(val) if (! isObjectNull((val))) return TEST_FAILED #define ASSERT_OBJECT_NOT_NULL(val) if (isObjectNull((val))) return TEST_FAILED + #define ASSERT_INSTANCE_OF(class, val) \ - if (! instanceOf(class, val)) return TEST_FAILED + if (! instanceOf(class, val)) { \ + printf("%s[%d]: Assertion failed that %s is instance of %s\n", \ + __FILE__, __LINE__, #val, #class); \ + return TEST_FAILED; } typedef int (* const testfunc)(void);