- improve the interface of rtti to pass meta_obj_t* as parameter of type function to easy to access private/data
- rename some macro with RTTI - add RTTI_MAGIC in object header - add new rtti api
This commit is contained in:
parent
c8c1749347
commit
f78ed03591
15 changed files with 252 additions and 114 deletions
|
|
@ -3,6 +3,5 @@
|
||||||
#define _LIBRTTI_RTTI_H_ 1
|
#define _LIBRTTI_RTTI_H_ 1
|
||||||
|
|
||||||
#include "rtti/typeinfo.h"
|
#include "rtti/typeinfo.h"
|
||||||
#include "rtti/utils.h"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,14 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#define RTTI_MAGIC (0x5254544949545452)
|
||||||
|
|
||||||
#define var void*
|
#define var void*
|
||||||
|
|
||||||
#define SIZE_ROUNDUP(sz) \
|
#define RTTI_SIZE_ROUNDUP(sz) \
|
||||||
((((sz + sizeof(void*) - 1)) / (sizeof(void*))) * sizeof(void*))
|
((((sz + sizeof(void*) - 1)) / (sizeof(void*))) * sizeof(void*))
|
||||||
|
|
||||||
#define OBJ_HEADER_SIZE SIZE_ROUNDUP(sizeof(meta_obj_t))
|
#define RTTI_OBJ_HEADER_SIZE RTTI_SIZE_ROUNDUP(sizeof(meta_obj_t))
|
||||||
|
|
||||||
/** Object format
|
/** Object format
|
||||||
**
|
**
|
||||||
|
|
@ -23,10 +25,34 @@
|
||||||
** +=====================+===================+===================+
|
** +=====================+===================+===================+
|
||||||
**
|
**
|
||||||
**/
|
**/
|
||||||
#define OBJ_TO_DATA(T, obj) ((T*)(((char*)obj) + OBJ_HEADER_SIZE))
|
#define RTTI_OBJ_TO_DATA(T, obj) ((T*)((obj)->data))
|
||||||
#define DATA_TO_OBJ(v) ((meta_obj_t*)(((char*)v) - OBJ_HEADER_SIZE))
|
#define RTTI_DATA_TO_OBJ(v) \
|
||||||
#define OBJ_TO_PRIV(obj) \
|
(((v) == NULL) ? NULL : ((meta_obj_t*)(((char*)v) - RTTI_OBJ_HEADER_SIZE)))
|
||||||
((void*)(((char*)obj) - SIZE_ROUNDUP((obj)->type->privateSize)))
|
#define RTTI_OBJ_TO_PRIV(obj) ((obj)->privdata)
|
||||||
|
|
||||||
|
#define RTTI_GET_METHOD(result, obj, intf, method) \
|
||||||
|
do { \
|
||||||
|
typeinfo_t* type_ = NULL; \
|
||||||
|
\
|
||||||
|
(result) = NULL; \
|
||||||
|
\
|
||||||
|
if ((obj) == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
type_ = obj->type; \
|
||||||
|
if (type_ == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (type_->interfaces.intf == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
(result) = type_->interfaces.intf->method; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define RTTI_OBJ_INVALID(obj) (((obj) == NULL) || ((obj)->magic != RTTI_MAGIC))
|
||||||
|
|
||||||
struct meta_obj_;
|
struct meta_obj_;
|
||||||
struct typeinfo_;
|
struct typeinfo_;
|
||||||
|
|
@ -38,12 +64,12 @@ typedef struct typeinfo_ typeinfo_t;
|
||||||
typedef size_t (*datasize_fn_t)(va_list);
|
typedef size_t (*datasize_fn_t)(va_list);
|
||||||
|
|
||||||
/* object life cycle */
|
/* object life cycle */
|
||||||
typedef int (*obj_init_fn_t)(typeinfo_t*, va_list);
|
typedef int (*obj_init_fn_t)(meta_obj_t*, va_list);
|
||||||
typedef void (*obj_destroy_fn_t)(var);
|
typedef void (*obj_destroy_fn_t)(meta_obj_t*);
|
||||||
|
|
||||||
/* lock/unlock */
|
/* lock/unlock */
|
||||||
typedef int (*lock_fn_t)(var, uint64_t);
|
typedef int (*lock_fn_t)(meta_obj_t*, uint64_t);
|
||||||
typedef void (*unlock_fn_t)(var);
|
typedef void (*unlock_fn_t)(meta_obj_t*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
lock_fn_t lock;
|
lock_fn_t lock;
|
||||||
|
|
@ -51,7 +77,7 @@ typedef struct {
|
||||||
} intf_lock_t;
|
} intf_lock_t;
|
||||||
|
|
||||||
/* convert to string */
|
/* convert to string */
|
||||||
typedef char* (*to_string_fn_t)(var, va_list);
|
typedef char* (*to_string_fn_t)(meta_obj_t*, va_list);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
to_string_fn_t toString;
|
to_string_fn_t toString;
|
||||||
|
|
@ -59,15 +85,15 @@ typedef struct {
|
||||||
|
|
||||||
/* iterator function */
|
/* iterator function */
|
||||||
|
|
||||||
#define ITER_NO_DATA (0)
|
#define RTTI_ITER_NO_DATA (0)
|
||||||
#define ITER_OK (1)
|
#define RTTI_ITER_OK (1)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
var v;
|
meta_obj_t* obj;
|
||||||
var data;
|
var data;
|
||||||
} iterator_t;
|
} iterator_t;
|
||||||
|
|
||||||
typedef int (*iter_make_fn_t)(iterator_t*, var);
|
typedef int (*iter_make_fn_t)(iterator_t*);
|
||||||
typedef int (*iter_next_fn_t)(iterator_t*, void**);
|
typedef int (*iter_next_fn_t)(iterator_t*, void**);
|
||||||
typedef int (*iter_reset_fn_t)(iterator_t*);
|
typedef int (*iter_reset_fn_t)(iterator_t*);
|
||||||
typedef void (*iter_destroy_fn_t)(iterator_t*);
|
typedef void (*iter_destroy_fn_t)(iterator_t*);
|
||||||
|
|
@ -80,8 +106,8 @@ typedef struct {
|
||||||
} intf_iterator_t;
|
} intf_iterator_t;
|
||||||
|
|
||||||
/* reference and deref */
|
/* reference and deref */
|
||||||
typedef int32_t (*reference_fn_t)(var);
|
typedef int32_t (*reference_fn_t)(meta_obj_t*);
|
||||||
typedef void (*dereference_fn_t)(var);
|
typedef void (*dereference_fn_t)(meta_obj_t*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
reference_fn_t reference;
|
reference_fn_t reference;
|
||||||
|
|
@ -90,14 +116,14 @@ typedef struct {
|
||||||
|
|
||||||
/* hash */
|
/* hash */
|
||||||
|
|
||||||
typedef int32_t (*hash_fn_t)(var);
|
typedef int32_t (*hash_fn_t)(meta_obj_t*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
hash_fn_t hash;
|
hash_fn_t hash;
|
||||||
} intf_hash_t;
|
} intf_hash_t;
|
||||||
|
|
||||||
/* length */
|
/* length */
|
||||||
typedef int64_t (*length_fn_t)(var);
|
typedef int64_t (*length_fn_t)(meta_obj_t*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
length_fn_t length;
|
length_fn_t length;
|
||||||
|
|
@ -122,11 +148,15 @@ struct typeinfo_ {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct meta_obj_ {
|
struct meta_obj_ {
|
||||||
|
uint64_t magic;
|
||||||
typeinfo_t* type;
|
typeinfo_t* type;
|
||||||
|
void* privdata;
|
||||||
|
void* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern var makeInstance(typeinfo_t*, ...);
|
extern var makeInstance(typeinfo_t*, ...);
|
||||||
extern void destroy(var);
|
extern void destroy(var);
|
||||||
|
extern int is_rtti_obj(var);
|
||||||
extern int lock(var, uint64_t);
|
extern int lock(var, uint64_t);
|
||||||
extern void unlock(var);
|
extern void unlock(var);
|
||||||
extern char* toString(var, ...);
|
extern char* toString(var, ...);
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
#if !defined(_RTTI_UTILS_H_)
|
|
||||||
|
|
||||||
#define _RTTI_UTILS_H_ 1
|
|
||||||
|
|
||||||
#define RTTI_GET_METHOD(result, obj, intf, method) \
|
|
||||||
do { \
|
|
||||||
typeinfo_t* type_ = NULL; \
|
|
||||||
meta_obj_t* obj_ = NULL; \
|
|
||||||
\
|
|
||||||
(result) = NULL; \
|
|
||||||
\
|
|
||||||
if ((obj) == NULL) { \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
obj_ = DATA_TO_OBJ(obj); \
|
|
||||||
\
|
|
||||||
type_ = obj_->type; \
|
|
||||||
if (type_ == NULL) { \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (type_->interfaces.intf == NULL) { \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
(result) = type_->interfaces.intf->method; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
58
src/create.c
58
src/create.c
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
#include "rtti.h"
|
#include "rtti.h"
|
||||||
|
|
||||||
static void* objAlloc(typeinfo_t* type, size_t sz)
|
static meta_obj_t* objAlloc(typeinfo_t* type, size_t sz)
|
||||||
{
|
{
|
||||||
size_t privateSize = SIZE_ROUNDUP(type->privateSize);
|
size_t privateSize = RTTI_SIZE_ROUNDUP(type->privateSize);
|
||||||
size_t headerSize = OBJ_HEADER_SIZE;
|
size_t headerSize = RTTI_OBJ_HEADER_SIZE;
|
||||||
char* p = NULL;
|
char* p = NULL;
|
||||||
meta_obj_t* obj = NULL;
|
meta_obj_t* obj = NULL;
|
||||||
size_t total = privateSize + headerSize + sz;
|
size_t total = privateSize + headerSize + sz;
|
||||||
|
|
@ -16,18 +16,21 @@ static void* objAlloc(typeinfo_t* type, size_t sz)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = (meta_obj_t*)(p + privateSize);
|
obj = (meta_obj_t*)(p + privateSize);
|
||||||
obj->type = type;
|
obj->type = type;
|
||||||
|
obj->magic = RTTI_MAGIC;
|
||||||
|
obj->privdata = p;
|
||||||
|
obj->data = (void*)(p + privateSize + headerSize);
|
||||||
|
|
||||||
return (void*)(p + privateSize + headerSize);
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
var makeInstance(typeinfo_t* type, ...)
|
var makeInstance(typeinfo_t* type, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_list ap1;
|
va_list ap1;
|
||||||
var v = NULL;
|
meta_obj_t* obj;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if ((type == NULL) || (type->init == NULL) || (type->dataSize == NULL)) {
|
if ((type == NULL) || (type->init == NULL) || (type->dataSize == NULL)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
|
@ -36,46 +39,57 @@ var makeInstance(typeinfo_t* type, ...)
|
||||||
|
|
||||||
va_start(ap, type);
|
va_start(ap, type);
|
||||||
va_copy(ap1, ap);
|
va_copy(ap1, ap);
|
||||||
v = objAlloc(type, type->dataSize(ap1));
|
obj = objAlloc(type, type->dataSize(ap1));
|
||||||
va_end(ap1);
|
va_end(ap1);
|
||||||
|
|
||||||
if (v != NULL) {
|
if (obj != NULL) {
|
||||||
rc = type->init(v, ap);
|
rc = type->init(obj, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
destroy(v);
|
destroy(obj);
|
||||||
v = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return obj->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy(var v)
|
void destroy(var v)
|
||||||
{
|
{
|
||||||
typeinfo_t* type = NULL;
|
typeinfo_t* type = NULL;
|
||||||
meta_obj_t* obj = NULL;
|
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
|
||||||
if (v == NULL) {
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = DATA_TO_OBJ(v);
|
|
||||||
|
|
||||||
type = obj->type;
|
type = obj->type;
|
||||||
if (type == NULL) {
|
if (type == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type->destroy != NULL) {
|
if (type->destroy != NULL) {
|
||||||
type->destroy(v);
|
type->destroy(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = OBJ_TO_PRIV(obj);
|
p = RTTI_OBJ_TO_PRIV(obj);
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_rtti_obj(var v)
|
||||||
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
|
||||||
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
||||||
22
src/hash.c
Normal file
22
src/hash.c
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
int32_t hash(var v) {
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
hash_fn_t method = NULL;
|
||||||
|
|
||||||
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, hash, hash);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(obj);
|
||||||
|
}
|
||||||
36
src/iter.c
36
src/iter.c
|
|
@ -6,32 +6,42 @@
|
||||||
|
|
||||||
int iter_make(iterator_t* it, var v)
|
int iter_make(iterator_t* it, var v)
|
||||||
{
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
iter_make_fn_t method = NULL;
|
iter_make_fn_t method = NULL;
|
||||||
|
|
||||||
if (it == NULL) {
|
if (it == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, v, iter, make);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, iter, make);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(it, 0x0, sizeof(*it));
|
memset(it, 0x0, sizeof(*it));
|
||||||
it->v = v;
|
it->obj = obj;
|
||||||
|
|
||||||
return method(it, v);
|
return method(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iter_next(iterator_t* it, void** data)
|
int iter_next(iterator_t* it, void** data)
|
||||||
{
|
{
|
||||||
iter_next_fn_t method = NULL;
|
iter_next_fn_t method = NULL;
|
||||||
|
|
||||||
if ((it == NULL) || (data == NULL) || (it->v == NULL)) {
|
if ((it == NULL) || (data == NULL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, it->v, iter, next);
|
if (RTTI_OBJ_INVALID(it->obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->obj, iter, next);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -43,11 +53,15 @@ int iter_reset(iterator_t* it)
|
||||||
{
|
{
|
||||||
iter_reset_fn_t method = NULL;
|
iter_reset_fn_t method = NULL;
|
||||||
|
|
||||||
if ((it == NULL) || (it->v == NULL)) {
|
if (it == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, it->v, iter, reset);
|
if (RTTI_OBJ_INVALID(it->obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->obj, iter, reset);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -59,11 +73,15 @@ void iter_destroy(iterator_t* it)
|
||||||
{
|
{
|
||||||
iter_destroy_fn_t method = NULL;
|
iter_destroy_fn_t method = NULL;
|
||||||
|
|
||||||
if ((it == NULL) || (it->v == NULL)) {
|
if (it == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, it->v, iter, destroy);
|
if (RTTI_OBJ_INVALID(it->obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, it->obj, iter, destroy);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
src/length.c
Normal file
23
src/length.c
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
int64_t length(var v)
|
||||||
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
|
length_fn_t method = NULL;
|
||||||
|
|
||||||
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, length, length);
|
||||||
|
if (method == NULL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method(obj);
|
||||||
|
}
|
||||||
20
src/lock.c
20
src/lock.c
|
|
@ -5,21 +5,33 @@
|
||||||
|
|
||||||
int lock(var v, uint64_t option)
|
int lock(var v, uint64_t option)
|
||||||
{
|
{
|
||||||
lock_fn_t method = NULL;
|
meta_obj_t* obj = NULL;
|
||||||
|
lock_fn_t method = NULL;
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, v, lock, lock);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, lock, lock);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return method(v, option);
|
return method(obj, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock(var v)
|
void unlock(var v)
|
||||||
{
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
unlock_fn_t method = NULL;
|
unlock_fn_t method = NULL;
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, v, lock, unlock);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, lock, unlock);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ librtti_c_srcs=[
|
||||||
'iter.c',
|
'iter.c',
|
||||||
'ref.c',
|
'ref.c',
|
||||||
'str.c',
|
'str.c',
|
||||||
|
'hash.c',
|
||||||
|
'length.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,7 +21,6 @@ rtti_top_headers = [
|
||||||
|
|
||||||
rtti_headers = [
|
rtti_headers = [
|
||||||
'../include/rtti/typeinfo.h',
|
'../include/rtti/typeinfo.h',
|
||||||
'../include/rtti/utils.h',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
librtti_deps = [
|
librtti_deps = [
|
||||||
|
|
|
||||||
20
src/ref.c
20
src/ref.c
|
|
@ -6,23 +6,35 @@
|
||||||
|
|
||||||
int32_t reference(var v)
|
int32_t reference(var v)
|
||||||
{
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
reference_fn_t method = NULL;
|
reference_fn_t method = NULL;
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, v, reference, reference);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, reference, reference);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return method(v);
|
return method(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dereference(var v)
|
void dereference(var v)
|
||||||
{
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
dereference_fn_t method = NULL;
|
dereference_fn_t method = NULL;
|
||||||
|
|
||||||
RTTI_GET_METHOD(method,v, reference, dereference);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, reference, dereference);
|
||||||
if (method != NULL) {
|
if (method != NULL) {
|
||||||
method(v);
|
method(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
11
src/str.c
11
src/str.c
|
|
@ -5,13 +5,20 @@
|
||||||
|
|
||||||
char* toString(var v, ...)
|
char* toString(var v, ...)
|
||||||
{
|
{
|
||||||
|
meta_obj_t* obj = NULL;
|
||||||
to_string_fn_t method = NULL;
|
to_string_fn_t method = NULL;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char* s = NULL;
|
char* s = NULL;
|
||||||
|
|
||||||
RTTI_GET_METHOD(method, v, toString, toString);
|
obj = RTTI_DATA_TO_OBJ(v);
|
||||||
|
if (RTTI_OBJ_INVALID(obj)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RTTI_GET_METHOD(method, obj, toString, toString);
|
||||||
if (method == NULL) {
|
if (method == NULL) {
|
||||||
errno = -EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
librtti_test_srcs = [
|
librtti_test_srcs = [
|
||||||
'test.c',
|
'test.c',
|
||||||
'test_iter.c',
|
'test_iter.c',
|
||||||
|
'test_invalid_obj.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
unity_dep = dependency('unity')
|
unity_dep = dependency('unity')
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,17 @@
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
{
|
{
|
||||||
printf("\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tearDown(void)
|
void tearDown(void)
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf(">>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void test_iter(void);
|
extern void test_iter(void);
|
||||||
|
extern void test_invalid(void);
|
||||||
|
|
||||||
#define TEST(x) x()
|
#define TEST(x) x()
|
||||||
|
|
||||||
|
|
@ -24,6 +24,7 @@ int main(int argc, char* argv[])
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
|
|
||||||
TEST(test_iter);
|
TEST(test_iter);
|
||||||
|
TEST(test_invalid);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
26
testsuite/test_invalid_obj.c
Normal file
26
testsuite/test_invalid_obj.c
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unity/unity.h>
|
||||||
|
|
||||||
|
#include "rtti.h"
|
||||||
|
|
||||||
|
static void test_c_str_invalid(void)
|
||||||
|
{
|
||||||
|
char* hello = "Hello, world";
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(is_rtti_obj(hello) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intptr_invalid(void) {
|
||||||
|
int x = 20;
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(is_rtti_obj(&x) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_invalid(void)
|
||||||
|
{
|
||||||
|
printf("\n invalid object\n\n");
|
||||||
|
|
||||||
|
RUN_TEST(test_c_str_invalid);
|
||||||
|
RUN_TEST(test_intptr_invalid);
|
||||||
|
}
|
||||||
|
|
@ -11,10 +11,11 @@ typedef struct {
|
||||||
|
|
||||||
static size_t my_array_datasize(va_list ap) { return sizeof(myArray_t); }
|
static size_t my_array_datasize(va_list ap) { return sizeof(myArray_t); }
|
||||||
|
|
||||||
static int my_array_init(myArray_t* a, va_list ap)
|
static int my_array_init(meta_obj_t* obj, va_list ap)
|
||||||
{
|
{
|
||||||
int count;
|
myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, obj);
|
||||||
int i;
|
int count;
|
||||||
|
int i;
|
||||||
|
|
||||||
count = va_arg(ap, int);
|
count = va_arg(ap, int);
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
|
|
@ -34,42 +35,43 @@ static int my_array_init(myArray_t* a, va_list ap)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_array_destroy(myArray_t* a)
|
static void my_array_destroy(meta_obj_t* obj)
|
||||||
{
|
{
|
||||||
|
myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, obj);
|
||||||
if (a->data != NULL) {
|
if (a->data != NULL) {
|
||||||
free(a->data);
|
free(a->data);
|
||||||
a->data = NULL;
|
a->data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_array_make_iter(iterator_t* iter, var obj)
|
static int my_array_make_iter(iterator_t* iter)
|
||||||
{
|
{
|
||||||
iter->data = (void*)(long)0;
|
iter->data = (void*)(long)0;
|
||||||
|
|
||||||
return ITER_OK;
|
return RTTI_ITER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_array_iter_next(iterator_t* iter, void** data)
|
static int my_array_iter_next(iterator_t* iter, void** data)
|
||||||
{
|
{
|
||||||
myArray_t* a = iter->v;
|
myArray_t* a = RTTI_OBJ_TO_DATA(myArray_t, iter->obj);
|
||||||
int idx = (int)(long)iter->data;
|
int idx = (int)(long)iter->data;
|
||||||
|
|
||||||
if (idx >= a->count) {
|
if (idx >= a->count) {
|
||||||
/* no data */
|
/* no data */
|
||||||
return ITER_NO_DATA;
|
return RTTI_ITER_NO_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = (void*)(long)a->data[idx];
|
*data = (void*)(long)a->data[idx];
|
||||||
iter->data = (void*)(long)(idx + 1);
|
iter->data = (void*)(long)(idx + 1);
|
||||||
|
|
||||||
return ITER_OK;
|
return RTTI_ITER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int my_array_iter_reset(iterator_t* iter)
|
static int my_array_iter_reset(iterator_t* iter)
|
||||||
{
|
{
|
||||||
iter->data = (void*)(long)0;
|
iter->data = (void*)(long)0;
|
||||||
|
|
||||||
return ITER_OK;
|
return RTTI_ITER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void my_array_iter_destroy(iterator_t* iter) { return; }
|
static void my_array_iter_destroy(iterator_t* iter) { return; }
|
||||||
|
|
@ -95,7 +97,7 @@ static void test_array_iter(void)
|
||||||
void* data;
|
void* data;
|
||||||
|
|
||||||
TEST_ASSERT_TRUE(array != NULL);
|
TEST_ASSERT_TRUE(array != NULL);
|
||||||
|
TEST_ASSERT_TRUE(is_rtti_obj(array) == 1);
|
||||||
rc = iter_make(&it, array);
|
rc = iter_make(&it, array);
|
||||||
TEST_ASSERT_TRUE(rc == 1);
|
TEST_ASSERT_TRUE(rc == 1);
|
||||||
|
|
||||||
|
|
@ -120,7 +122,7 @@ static void test_array_iter(void)
|
||||||
TEST_ASSERT_TRUE((int)(long)data == 4);
|
TEST_ASSERT_TRUE((int)(long)data == 4);
|
||||||
|
|
||||||
rc = iter_next(&it, (void**)&data);
|
rc = iter_next(&it, (void**)&data);
|
||||||
TEST_ASSERT_TRUE(rc == ITER_NO_DATA);
|
TEST_ASSERT_TRUE(rc == RTTI_ITER_NO_DATA);
|
||||||
|
|
||||||
sum = 0;
|
sum = 0;
|
||||||
rc = iter_reset(&it);
|
rc = iter_reset(&it);
|
||||||
|
|
@ -129,7 +131,7 @@ static void test_array_iter(void)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rc = iter_next(&it, &data);
|
rc = iter_next(&it, &data);
|
||||||
TEST_ASSERT_TRUE(rc >= 0);
|
TEST_ASSERT_TRUE(rc >= 0);
|
||||||
if (rc == ITER_NO_DATA) {
|
if (rc == RTTI_ITER_NO_DATA) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue