+added hash, cmp, format functor for referenced usertype.

This commit is contained in:
Wang Renxin 2015-10-15 13:01:28 +08:00
parent 12ed696e31
commit e94e43622c

View File

@ -298,8 +298,11 @@ typedef struct _gc_t {
typedef struct _usertype_ref_t { typedef struct _usertype_ref_t {
_ref_t ref; _ref_t ref;
void* usertype; void* usertype;
mb_unref_func_t unref; mb_dtor_func_t unref;
mb_clone_func_t clone; mb_clone_func_t clone;
mb_hash_func_t hash;
mb_cmp_func_t cmp;
mb_fmt_func_t fmt;
} _usertype_ref_t; } _usertype_ref_t;
typedef struct _array_t { typedef struct _array_t {
@ -990,7 +993,7 @@ static void _gc_try_trigger(mb_interpreter_t* s);
static void _gc_collect_garbage(mb_interpreter_t* s); static void _gc_collect_garbage(mb_interpreter_t* s);
#endif /* MB_ENABLE_GC */ #endif /* MB_ENABLE_GC */
static _usertype_ref_t* _create_usertype_ref(mb_interpreter_t* s, void* val, mb_unref_func_t un, mb_clone_func_t cl); static _usertype_ref_t* _create_usertype_ref(mb_interpreter_t* s, void* val, 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);
static void _destroy_usertype_ref(_usertype_ref_t* c); static void _destroy_usertype_ref(_usertype_ref_t* c);
static void _unref_usertype_ref(_ref_t* ref, void* data); static void _unref_usertype_ref(_ref_t* ref, void* data);
@ -1707,6 +1710,13 @@ unsigned int _ht_hash_object(void* ht, void* d) {
result = 5 * h + _ht_hash_string(ht, o->data.string); result = 5 * h + _ht_hash_string(ht, o->data.string);
break; break;
case _DT_USERTYPE_REF:
if(o->data.usertype_ref->hash) {
h = 5 * h + o->data.usertype_ref->hash(o->data.usertype_ref->ref.s, o->data.usertype_ref->usertype);
break;
}
/* Fall through */
default: default:
for(i = 0; i < sizeof(_raw_t); ++i) for(i = 0; i < sizeof(_raw_t); ++i)
h = 5 * h + o->data.raw[i]; h = 5 * h + o->data.raw[i];
@ -1774,6 +1784,17 @@ int _ht_cmp_object(void* d1, void* d2) {
switch(o1->type) { switch(o1->type) {
case _DT_STRING: case _DT_STRING:
return _ht_cmp_string(o1->data.string, o2->data.string); return _ht_cmp_string(o1->data.string, o2->data.string);
case _DT_USERTYPE_REF:
if(o1->data.usertype_ref->cmp) {
o1->data.usertype_ref->cmp(o1->data.usertype_ref->ref.s, o1->data.usertype_ref->usertype, o2->data.usertype_ref->usertype);
break;
} else if(o2->data.usertype_ref->cmp) {
o2->data.usertype_ref->cmp(o1->data.usertype_ref->ref.s, o1->data.usertype_ref->usertype, o2->data.usertype_ref->usertype);
break;
}
/* Fall through */
default: default:
for(i = 0; i < sizeof(_raw_t); ++i) { for(i = 0; i < sizeof(_raw_t); ++i) {
if(o1->data.raw[i] < o2->data.raw[i]) if(o1->data.raw[i] < o2->data.raw[i])
@ -3885,13 +3906,16 @@ void _gc_collect_garbage(mb_interpreter_t* s) {
} }
#endif /* MB_ENABLE_GC */ #endif /* MB_ENABLE_GC */
_usertype_ref_t* _create_usertype_ref(mb_interpreter_t* s, void* val, mb_unref_func_t un, mb_clone_func_t cl) { _usertype_ref_t* _create_usertype_ref(mb_interpreter_t* s, void* val, 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 */ /* Create a referenced usertype */
_usertype_ref_t* result = (_usertype_ref_t*)mb_malloc(sizeof(_usertype_ref_t)); _usertype_ref_t* result = (_usertype_ref_t*)mb_malloc(sizeof(_usertype_ref_t));
memset(result, 0, sizeof(_usertype_ref_t)); memset(result, 0, sizeof(_usertype_ref_t));
result->usertype = val; result->usertype = val;
result->unref = un; result->unref = un;
result->clone = cl; result->clone = cl;
result->hash = hs;
result->cmp = cp;
result->fmt = ft;
_create_ref(&result->ref, _unref_usertype_ref, _DT_USERTYPE_REF, s); _create_ref(&result->ref, _unref_usertype_ref, _DT_USERTYPE_REF, s);
return result; return result;
@ -5240,7 +5264,8 @@ int _clone_object(_object_t* obj, _object_t* tgt) {
tgt->data.usertype_ref = _create_usertype_ref( tgt->data.usertype_ref = _create_usertype_ref(
obj->data.usertype_ref->ref.s, obj->data.usertype_ref->ref.s,
obj->data.usertype_ref->clone(obj->data.usertype_ref->ref.s, obj->data.usertype_ref->usertype), obj->data.usertype_ref->clone(obj->data.usertype_ref->ref.s, obj->data.usertype_ref->usertype),
obj->data.usertype_ref->unref, obj->data.usertype_ref->clone obj->data.usertype_ref->unref, obj->data.usertype_ref->clone,
obj->data.usertype_ref->hash, obj->data.usertype_ref->cmp, obj->data.usertype_ref->fmt
); );
break; break;
@ -7183,7 +7208,7 @@ _exit:
return result; return result;
} }
int mb_ref_value(struct mb_interpreter_t* s, void* val, mb_unref_func_t un, mb_clone_func_t cl, mb_value_t* out) { int mb_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 */ /* Create a referenced usertype value */
int result = MB_FUNC_OK; int result = MB_FUNC_OK;
_usertype_ref_t* ref = 0; _usertype_ref_t* ref = 0;
@ -7191,7 +7216,7 @@ int mb_ref_value(struct mb_interpreter_t* s, void* val, mb_unref_func_t un, mb_c
mb_assert(s && out); mb_assert(s && out);
if(out) { if(out) {
ref = _create_usertype_ref(s, val, un, cl); ref = _create_usertype_ref(s, val, un, cl, hs, cp, ft);
out->type = MB_DT_USERTYPE_REF; out->type = MB_DT_USERTYPE_REF;
out->value.usertype_ref = ref; out->value.usertype_ref = ref;
} }
@ -9800,20 +9825,15 @@ int _std_print(mb_interpreter_t* s, void** l) {
if(!val_ptr->ref && val_ptr->data.string) { if(!val_ptr->ref && val_ptr->data.string) {
safe_free(val_ptr->data.string); safe_free(val_ptr->data.string);
} }
} else if(val_ptr->type == _DT_USERTYPE_REF) {
if(val_ptr->data.usertype_ref->fmt)
val_ptr->data.usertype_ref->fmt(s, val_ptr->data.usertype_ref->usertype, _get_printer(s));
else
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
} else if(val_ptr->type == _DT_TYPE) { } else if(val_ptr->type == _DT_TYPE) {
_get_printer(s)(mb_get_type_string(val_ptr->data.type)); _get_printer(s)(mb_get_type_string(val_ptr->data.type));
} else if(val_ptr->type == _DT_ARRAY) { } else {
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type))); _get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
#ifdef MB_ENABLE_COLLECTION_LIB
} else if(val_ptr->type == _DT_LIST) {
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
} else if(val_ptr->type == _DT_LIST_IT) {
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
} else if(val_ptr->type == _DT_DICT) {
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
} else if(val_ptr->type == _DT_DICT_IT) {
_get_printer(s)(mb_get_type_string(_internal_type_to_public_type(val_ptr->type)));
#endif /* MB_ENABLE_COLLECTION_LIB */
} }
if(result != MB_FUNC_OK) if(result != MB_FUNC_OK)
goto _exit; goto _exit;