From b6b881e76e2f94eb395669cbbc36a4df9d46b72c Mon Sep 17 00:00:00 2001 From: Wang Renxin Date: Fri, 23 Oct 2015 13:57:21 +0800 Subject: [PATCH] +added public collection manipulation interfaces: mb_get_coll, mb_set_coll, mb_remove_coll, mb_count_coll; *improved referenced usertype; *improved usertype by adding size customizable mb_val_bytes_t to the value union; *fixed a dictionary iterator validation bug. --- core/my_basic.c | 208 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 199 insertions(+), 9 deletions(-) diff --git a/core/my_basic.c b/core/my_basic.c index 71e5d29..10df605 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -79,7 +79,7 @@ extern "C" { /** Macros */ #define _VER_MAJOR 1 #define _VER_MINOR 1 -#define _VER_REVISION 92 +#define _VER_REVISION 93 #define _VER_SUFFIX #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) #define _STRINGIZE(A) _MAKE_STRINGIZE(A) @@ -370,7 +370,7 @@ typedef struct _routine_t { typedef int (* _has_routine_arg)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, _routine_t*); typedef int (* _pop_routine_arg)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, _routine_t*, mb_value_t*); -typedef union _raw_u { char c; int_t i; real_t r; void* p; } _raw_u; +typedef union _raw_u { char c; int_t i; real_t r; void* p; mb_val_bytes_t b; } _raw_u; typedef unsigned char _raw_t[sizeof(_raw_u)]; @@ -396,6 +396,7 @@ typedef struct _object_t { _routine_t* routine; _class_t* instance; char separator; + mb_val_bytes_t bytes; _raw_t raw; } data; bool_t ref; @@ -4806,7 +4807,7 @@ bool_t _invalid_list_it(_list_it_t* it) { bool_t _invalid_dict_it(_dict_it_t* it) { /* Determin whether a dictionary iterator is invalid */ - if(!it) return true; + if(!it) return false; return it && it->dict && it->dict->lock <= 0; } @@ -5767,7 +5768,7 @@ int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) { break; case MB_DT_USERTYPE: itn->type = _DT_USERTYPE; - itn->data.usertype = pbl->value.usertype; + memcpy(itn->data.raw, pbl->value.bytes, sizeof(mb_val_bytes_t)); break; case MB_DT_USERTYPE_REF: @@ -5850,7 +5851,7 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) { break; case _DT_USERTYPE: pbl->type = MB_DT_USERTYPE; - pbl->value.usertype = itn->data.usertype; + memcpy(pbl->value.bytes, itn->data.raw, sizeof(mb_val_bytes_t)); break; case _DT_USERTYPE_REF: @@ -7244,6 +7245,187 @@ _exit: return result; } +int mb_get_coll(struct mb_interpreter_t* s, void** l, mb_value_t coll, mb_value_t idx, mb_value_t* val) { + /* Get an element of a collection */ + int result = MB_FUNC_OK; + _object_t ocoll; + int_t i = 0; + mb_value_t ret; + + mb_assert(s); + + mb_make_nil(ret); + + _MAKE_NIL(&ocoll); +#ifdef MB_ENABLE_COLLECTION_LIB + switch(coll.type) { + case MB_DT_LIST: + mb_int_val(idx, i); + _public_value_to_internal_object(&coll, &ocoll); + if(!_at_list(ocoll.data.list, i, &ret)) { + _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, 0, TON(l), MB_FUNC_ERR, _exit, result); + } + + break; + case MB_DT_DICT: + _public_value_to_internal_object(&coll, &ocoll); + if(!_find_dict(ocoll.data.dict, &idx, &ret)) { + _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, 0, TON(l), MB_FUNC_ERR, _exit, result); + } + + break; + default: + _handle_error_on_obj(s, SE_RN_COLLECTION_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); + + break; + } +#else /* MB_ENABLE_COLLECTION_LIB */ + mb_unrefvar(idx); + mb_unrefvar(coll); + mb_unrefvar(i); + _handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, TON(l), MB_FUNC_ERR, _exit, result); +#endif /* MB_ENABLE_COLLECTION_LIB */ + +_exit: + if(val) *val = ret; + + return result; +} + +int mb_set_coll(struct mb_interpreter_t* s, void** l, mb_value_t coll, mb_value_t idx, mb_value_t val) { + /* Set an element of a collection */ + int result = MB_FUNC_OK; + _object_t ocoll; + int_t i = 0; + _object_t* oval = 0; + mb_value_t ret; + + mb_assert(s); + + mb_make_nil(ret); + + _MAKE_NIL(&ocoll); +#ifdef MB_ENABLE_COLLECTION_LIB + switch(coll.type) { + case MB_DT_LIST: + mb_int_val(idx, i); + _public_value_to_internal_object(&coll, &ocoll); + if(!_set_list(ocoll.data.list, i, &val, &oval)) { + _destroy_object(oval, 0); + + _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, 0, TON(l), MB_FUNC_ERR, _exit, result); + } + + break; + case MB_DT_DICT: + _public_value_to_internal_object(&coll, &ocoll); + _set_dict(ocoll.data.dict, &idx, &val, 0, 0); + + break; + default: + _handle_error_on_obj(s, SE_RN_COLLECTION_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); + + break; + } +#else /* MB_ENABLE_COLLECTION_LIB */ + mb_unrefvar(val); + mb_unrefvar(idx); + mb_unrefvar(coll); + mb_unrefvar(oval); + mb_unrefvar(i); + _handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, TON(l), MB_FUNC_ERR, _exit, result); +#endif /* MB_ENABLE_COLLECTION_LIB */ + +_exit: + return result; +} + +int mb_remove_coll(struct mb_interpreter_t* s, void** l, mb_value_t coll, mb_value_t idx) { + /* Remove an element from a collection */ + int result = MB_FUNC_OK; + _object_t ocoll; + int_t i = 0; + mb_value_t ret; + + mb_assert(s); + + mb_make_nil(ret); + + _MAKE_NIL(&ocoll); +#ifdef MB_ENABLE_COLLECTION_LIB + switch(coll.type) { + case MB_DT_LIST: + mb_int_val(idx, i); + _public_value_to_internal_object(&coll, &ocoll); + if(!_remove_at_list(ocoll.data.list, i)) { + _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, 0, TON(l), MB_FUNC_ERR, _exit, result); + } + + break; + case MB_DT_DICT: + _public_value_to_internal_object(&coll, &ocoll); + if(!_remove_dict(ocoll.data.dict, &idx)) { + _handle_error_on_obj(s, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, 0, TON(l), MB_FUNC_ERR, _exit, result); + } + + break; + default: + _handle_error_on_obj(s, SE_RN_COLLECTION_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); + + break; + } +#else /* MB_ENABLE_COLLECTION_LIB */ + mb_unrefvar(coll); + mb_unrefvar(idx); + mb_unrefvar(i); + _handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, TON(l), MB_FUNC_ERR, _exit, result); +#endif /* MB_ENABLE_COLLECTION_LIB */ + +_exit: + return result; +} + +int mb_count_coll(struct mb_interpreter_t* s, void** l, mb_value_t coll, int* c) { + /* Tell the element count of a collection */ + int result = MB_FUNC_OK; + _object_t ocoll; +#ifdef MB_ENABLE_COLLECTION_LIB + _list_t* lst = 0; + _dict_t* dct = 0; +#endif /* MB_ENABLE_COLLECTION_LIB */ + int ret = 0; + + mb_assert(s); + + _MAKE_NIL(&ocoll); +#ifdef MB_ENABLE_COLLECTION_LIB + switch(coll.type) { + case MB_DT_LIST: + lst = (_list_t*)coll.value.list; + ret = (int)lst->count; + + break; + case MB_DT_DICT: + dct = (_dict_t*)coll.value.dict; + ret = (int)_ht_count(dct->dict); + + break; + default: + _handle_error_on_obj(s, SE_RN_COLLECTION_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); + + break; + } +#else /* MB_ENABLE_COLLECTION_LIB */ + mb_unrefvar(coll); + _handle_error_on_obj(s, SE_RN_NOT_SUPPORTED, 0, TON(l), MB_FUNC_ERR, _exit, result); +#endif /* MB_ENABLE_COLLECTION_LIB */ + +_exit: + if(c) *c = ret; + + return result; +} + int mb_make_ref_value(struct mb_interpreter_t* s, void* val, mb_value_t* out, mb_dtor_func_t un, mb_clone_func_t cl, mb_hash_func_t hs, mb_cmp_func_t cp, mb_fmt_func_t ft) { /* Create a referenced usertype value */ int result = MB_FUNC_OK; @@ -7269,10 +7451,14 @@ int mb_ref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) { _MAKE_NIL(&obj); _public_value_to_internal_object(&val, &obj); - if(obj.type != _DT_USERTYPE_REF) { +#ifdef MB_ENABLE_COLLECTION_LIB + if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY && obj.type != _DT_LIST && obj.type != _DT_DICT) { +#else /* MB_ENABLE_COLLECTION_LIB */ + if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY) { +#endif /* MB_ENABLE_COLLECTION_LIB */ _handle_error_on_obj(s, SE_RN_REFERENCED_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); } - _ref(&obj.data.usertype_ref->ref, &obj.data.usertype_ref); + _REF(&obj); _exit: return result; @@ -7287,10 +7473,14 @@ int mb_unref_value(struct mb_interpreter_t* s, void** l, mb_value_t val) { _MAKE_NIL(&obj); _public_value_to_internal_object(&val, &obj); - if(obj.type != _DT_USERTYPE_REF) { +#ifdef MB_ENABLE_COLLECTION_LIB + if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY && obj.type != _DT_LIST && obj.type != _DT_DICT) { +#else /* MB_ENABLE_COLLECTION_LIB */ + if(obj.type != _DT_USERTYPE_REF && obj.type != _DT_ARRAY) { +#endif /* MB_ENABLE_COLLECTION_LIB */ _handle_error_on_obj(s, SE_RN_REFERENCED_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result); } - _unref(&obj.data.usertype_ref->ref, &obj.data.usertype_ref); + _UNREF(&obj); _exit: return result;