mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-30 11:08:34 +08:00
improve object_array
This commit is contained in:
parent
4c4470376f
commit
e760b78332
@ -28,11 +28,11 @@
|
||||
static ret_t object_array_clean_invalid_props(object_t* obj) {
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
if (o->props_size > 0) {
|
||||
if (o->size > 0) {
|
||||
uint32_t i = 0;
|
||||
value_t* dst = o->props;
|
||||
|
||||
for (i = 0; i < o->props_size; i++) {
|
||||
for (i = 0; i < o->size; i++) {
|
||||
value_t* iter = o->props + i;
|
||||
|
||||
if (iter->type != VALUE_TYPE_INVALID) {
|
||||
@ -43,7 +43,7 @@ static ret_t object_array_clean_invalid_props(object_t* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
o->props_size = dst - o->props;
|
||||
o->size = dst - o->props;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
@ -54,12 +54,12 @@ ret_t object_array_clear_props(object_t* obj) {
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
for (i = 0; i < o->props_size; i++) {
|
||||
for (i = 0; i < o->size; i++) {
|
||||
value_t* iter = o->props + i;
|
||||
value_reset(iter);
|
||||
}
|
||||
|
||||
o->props_size = 0;
|
||||
o->size = 0;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
@ -69,7 +69,7 @@ static ret_t object_array_on_destroy(object_t* obj) {
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
object_array_clear_props(obj);
|
||||
o->props_capacity = 0;
|
||||
o->capacity = 0;
|
||||
TKMEM_FREE(o->props);
|
||||
|
||||
return RET_OK;
|
||||
@ -84,16 +84,16 @@ static ret_t object_array_extend(object_t* obj) {
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
if (o->props_size < o->props_capacity) {
|
||||
if (o->size < o->capacity) {
|
||||
ret = RET_OK;
|
||||
} else {
|
||||
value_t* props = NULL;
|
||||
uint32_t capacity = o->props_capacity + (o->props_capacity >> 1) + 1;
|
||||
uint32_t capacity = o->capacity + (o->capacity >> 1) + 1;
|
||||
props = TKMEM_REALLOCT(value_t, o->props, capacity);
|
||||
|
||||
if (props != NULL) {
|
||||
o->props = props;
|
||||
o->props_capacity = capacity;
|
||||
o->capacity = capacity;
|
||||
ret = RET_OK;
|
||||
}
|
||||
}
|
||||
@ -101,17 +101,37 @@ static ret_t object_array_extend(object_t* obj) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ret_t object_array_append(object_t* obj, const value_t* v) {
|
||||
ret_t object_array_insert(object_t* obj, uint32_t index, const value_t* v) {
|
||||
value_t* s = NULL;
|
||||
value_t* d = NULL;
|
||||
value_t* p = NULL;
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return_value_if_fail(o != NULL && v != NULL, RET_BAD_PARAMS);
|
||||
index = tk_min(index, o->size);
|
||||
return_value_if_fail(object_array_extend(obj) == RET_OK, RET_OOM);
|
||||
|
||||
value_deep_copy(o->props + o->props_size, v);
|
||||
o->props_size++;
|
||||
p = o->props + index;
|
||||
d = o->props + o->size;
|
||||
s = d - 1;
|
||||
|
||||
while (s >= p) {
|
||||
*d-- = *s--;
|
||||
}
|
||||
value_deep_copy(p, v);
|
||||
o->size++;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t object_array_push(object_t* obj, const value_t* v) {
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
return object_array_insert(obj, o->size, v);
|
||||
}
|
||||
|
||||
static int32_t object_array_parse_index(const char* name) {
|
||||
if (isdigit(*name)) {
|
||||
return tk_atoi(name);
|
||||
@ -122,12 +142,11 @@ static int32_t object_array_parse_index(const char* name) {
|
||||
}
|
||||
}
|
||||
|
||||
static ret_t object_array_remove_prop(object_t* obj, const char* name) {
|
||||
ret_t object_array_remove(object_t* obj, uint32_t index) {
|
||||
ret_t ret = RET_NOT_FOUND;
|
||||
int32_t index = object_array_parse_index(name);
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
if (index >= 0 && index < o->props_size) {
|
||||
if (index >= 0 && index < o->size) {
|
||||
value_t* iter = o->props + index;
|
||||
value_reset(iter);
|
||||
ret = object_array_clean_invalid_props(obj);
|
||||
@ -136,18 +155,37 @@ static ret_t object_array_remove_prop(object_t* obj, const char* name) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ret_t object_array_remove_prop(object_t* obj, const char* name) {
|
||||
int32_t index = object_array_parse_index(name);
|
||||
|
||||
return object_array_remove(obj, index);
|
||||
}
|
||||
|
||||
ret_t object_array_pop(object_t* obj, value_t* v) {
|
||||
value_t* last = NULL;
|
||||
ret_t ret = RET_NOT_FOUND;
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL && o->size > 0, RET_BAD_PARAMS);
|
||||
last = o->props + o->size - 1;
|
||||
*v = *last;
|
||||
memset(last, 0x00, sizeof(value_t));
|
||||
o->size--;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static ret_t object_array_set_prop(object_t* obj, const char* name, const value_t* v) {
|
||||
ret_t ret = RET_NOT_FOUND;
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
int32_t index = object_array_parse_index(name);
|
||||
return_value_if_fail(object_array_extend(obj) == RET_OK, RET_OOM);
|
||||
|
||||
if (isdigit(*name) && index >= 0 && index < o->props_size) {
|
||||
if (isdigit(*name) && index >= 0 && index < o->size) {
|
||||
value_t* iter = o->props + index;
|
||||
value_reset(iter);
|
||||
ret = value_deep_copy(iter, v);
|
||||
} else if (index == -1) {
|
||||
ret = object_array_append(obj, v);
|
||||
ret = object_array_push(obj, v);
|
||||
} else {
|
||||
ret = RET_BAD_PARAMS;
|
||||
}
|
||||
@ -161,11 +199,11 @@ static ret_t object_array_get_prop(object_t* obj, const char* name, value_t* v)
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
if (tk_str_eq(name, "length") || tk_str_eq(name, "size") || tk_str_eq(name, "#size")) {
|
||||
value_set_int(v, o->props_size);
|
||||
value_set_int(v, o->size);
|
||||
ret = RET_OK;
|
||||
} else {
|
||||
int32_t index = object_array_parse_index(name);
|
||||
if (index >= 0 && index < o->props_size) {
|
||||
if (index >= 0 && index < o->size) {
|
||||
value_t* iter = o->props + index;
|
||||
ret = value_copy(v, iter);
|
||||
}
|
||||
@ -179,13 +217,13 @@ static ret_t object_array_foreach_prop(object_t* obj, tk_visit_t on_prop, void*
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
return_value_if_fail(o != NULL, RET_BAD_PARAMS);
|
||||
|
||||
if (o->props_size > 0) {
|
||||
if (o->size > 0) {
|
||||
uint32_t i = 0;
|
||||
named_value_t nv;
|
||||
char name[TK_NAME_LEN + 1];
|
||||
|
||||
nv.name = name;
|
||||
for (i = 0; i < o->props_size; i++) {
|
||||
for (i = 0; i < o->size; i++) {
|
||||
value_t* iter = o->props + i;
|
||||
tk_snprintf(name, TK_NAME_LEN, "%u", i);
|
||||
|
||||
@ -225,7 +263,7 @@ static object_t* object_array_create_with_capacity(uint32_t init_capacity) {
|
||||
|
||||
o->props = TKMEM_ZALLOCN(value_t, init_capacity);
|
||||
if (o->props != NULL) {
|
||||
o->props_capacity = init_capacity;
|
||||
o->capacity = init_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,20 +278,20 @@ object_t* object_array_clone(object_array_t* o) {
|
||||
object_t* dup = NULL;
|
||||
return_value_if_fail(o != NULL, NULL);
|
||||
|
||||
dup = object_array_create_with_capacity(o->props_capacity);
|
||||
dup = object_array_create_with_capacity(o->capacity);
|
||||
return_value_if_fail(dup != NULL, NULL);
|
||||
|
||||
if (o->props_size > 0) {
|
||||
if (o->size > 0) {
|
||||
uint32_t i = 0;
|
||||
object_array_t* dup_o = OBJECT_ARRAY(dup);
|
||||
|
||||
for (i = 0; i < o->props_size; i++) {
|
||||
for (i = 0; i < o->size; i++) {
|
||||
value_t* src = o->props + i;
|
||||
value_t* dst = dup_o->props + i;
|
||||
|
||||
value_deep_copy(dst, src);
|
||||
}
|
||||
dup_o->props_size = o->props_size;
|
||||
dup_o->size = o->size;
|
||||
}
|
||||
|
||||
return dup;
|
||||
|
@ -44,20 +44,20 @@ typedef struct _object_array_t {
|
||||
object_t object;
|
||||
|
||||
/**
|
||||
* @property {uint32_t} props_size
|
||||
* @property {uint32_t} size
|
||||
* @annotation ["readable", "scriptable"]
|
||||
* 属性个数。
|
||||
*
|
||||
*/
|
||||
uint32_t props_size;
|
||||
uint32_t size;
|
||||
|
||||
/**
|
||||
* @property {uint32_t} props_capacity
|
||||
* @property {uint32_t} capacity
|
||||
* @annotation ["readable"]
|
||||
* 属性数组的容量。
|
||||
*
|
||||
*/
|
||||
uint32_t props_capacity;
|
||||
uint32_t capacity;
|
||||
|
||||
/**
|
||||
* @property {value_t} props
|
||||
@ -120,6 +120,60 @@ ret_t object_array_unref(object_t* obj);
|
||||
*/
|
||||
ret_t object_array_clear_props(object_t* obj);
|
||||
|
||||
/**
|
||||
* @method object_array_insert
|
||||
*
|
||||
* 在指定位置插入一个元素。
|
||||
*
|
||||
* @annotation ["scriptable"]
|
||||
* @param {object_t*} obj 对象。
|
||||
* @param {uint32_t} index 位置。
|
||||
* @param {const value_t*} v 值。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*
|
||||
*/
|
||||
ret_t object_array_insert(object_t* obj, uint32_t index, const value_t* v);
|
||||
|
||||
/**
|
||||
* @method object_array_push
|
||||
*
|
||||
* 追加一个元素。
|
||||
*
|
||||
* @annotation ["scriptable"]
|
||||
* @param {object_t*} obj 对象。
|
||||
* @param {const value_t*} v 值。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*
|
||||
*/
|
||||
ret_t object_array_push(object_t* obj, const value_t* v);
|
||||
|
||||
/**
|
||||
* @method object_array_remove
|
||||
*
|
||||
* 在指定位置删除一个元素。
|
||||
*
|
||||
* @annotation ["scriptable"]
|
||||
* @param {object_t*} obj 对象。
|
||||
* @param {uint32_t} index 位置。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*
|
||||
*/
|
||||
ret_t object_array_remove(object_t* obj, uint32_t index);
|
||||
/**
|
||||
* @method object_array_pop
|
||||
*
|
||||
* 弹出一个元素。
|
||||
* @param {object_t*} obj 对象。
|
||||
* @param {value_t*} v 返回值。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*
|
||||
*/
|
||||
ret_t object_array_pop(object_t* obj, value_t* v);
|
||||
|
||||
object_array_t* object_array_cast(object_t* obj);
|
||||
#define OBJECT_ARRAY(obj) object_array_cast(obj)
|
||||
|
||||
|
@ -61,49 +61,49 @@ TEST(ObjectArray, basic) {
|
||||
object_t* obj = object_array_create();
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
|
||||
ASSERT_EQ(o->props_size, 0);
|
||||
ASSERT_EQ(o->size, 0);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "-1", value_set_int(&v, 0)), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 1);
|
||||
ASSERT_EQ(o->size, 1);
|
||||
ASSERT_EQ(object_get_prop(obj, "0", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 0);
|
||||
ASSERT_EQ(object_get_prop(obj, "[0]", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 0);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "-1", value_set_int(&v, 1)), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 2);
|
||||
ASSERT_EQ(o->size, 2);
|
||||
ASSERT_EQ(object_get_prop(obj, "1", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 1);
|
||||
ASSERT_EQ(object_get_prop(obj, "[1]", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 1);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "-1", value_set_int(&v, 2)), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 3);
|
||||
ASSERT_EQ(o->size, 3);
|
||||
ASSERT_EQ(object_get_prop(obj, "2", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 2);
|
||||
ASSERT_EQ(object_get_prop(obj, "[2]", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 2);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "-1", value_set_int(&v, 3)), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 4);
|
||||
ASSERT_EQ(o->size, 4);
|
||||
ASSERT_EQ(object_get_prop(obj, "3", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 3);
|
||||
ASSERT_EQ(object_get_prop(obj, "[3]", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 3);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "3", value_set_int(&v, 4)), RET_OK);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "size", -1), o->props_size);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "#size", -1), o->props_size);
|
||||
ASSERT_EQ(o->props_size, 4);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "size", -1), o->size);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "#size", -1), o->size);
|
||||
ASSERT_EQ(o->size, 4);
|
||||
ASSERT_EQ(object_get_prop(obj, "3", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 4);
|
||||
ASSERT_EQ(object_get_prop(obj, "[3]", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 4);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "2", value_set_int(&v, 5)), RET_OK);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "size", -1), o->props_size);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "#size", -1), o->props_size);
|
||||
ASSERT_EQ(o->props_size, 4);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "size", -1), o->size);
|
||||
ASSERT_EQ(object_get_prop_int(obj, "#size", -1), o->size);
|
||||
ASSERT_EQ(o->size, 4);
|
||||
ASSERT_EQ(object_get_prop(obj, "2", &v), RET_OK);
|
||||
ASSERT_EQ(value_int(&v), 5);
|
||||
ASSERT_EQ(object_get_prop(obj, "[2]", &v), RET_OK);
|
||||
@ -115,14 +115,14 @@ TEST(ObjectArray, basic) {
|
||||
ASSERT_EQ(log, "0154");
|
||||
|
||||
ASSERT_EQ(object_remove_prop(obj, "3"), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 3);
|
||||
ASSERT_EQ(o->size, 3);
|
||||
ASSERT_EQ(object_get_prop(obj, "3", &v), RET_NOT_FOUND);
|
||||
ASSERT_EQ(object_remove_prop(obj, "3"), RET_NOT_FOUND);
|
||||
|
||||
ASSERT_EQ(object_set_prop(obj, "-1", value_set_int(&v, 3)), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 4);
|
||||
ASSERT_EQ(o->size, 4);
|
||||
ASSERT_EQ(object_remove_prop(obj, "[3]"), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 3);
|
||||
ASSERT_EQ(o->size, 3);
|
||||
ASSERT_EQ(object_get_prop(obj, "[3]", &v), RET_NOT_FOUND);
|
||||
ASSERT_EQ(object_remove_prop(obj, "[3]"), RET_NOT_FOUND);
|
||||
|
||||
@ -131,7 +131,7 @@ TEST(ObjectArray, basic) {
|
||||
ASSERT_EQ(log, "015");
|
||||
|
||||
ASSERT_EQ(object_remove_prop(obj, "0"), RET_OK);
|
||||
ASSERT_EQ(o->props_size, 2);
|
||||
ASSERT_EQ(o->size, 2);
|
||||
|
||||
log = "";
|
||||
object_foreach_prop(obj, visit_dump, &log);
|
||||
@ -204,3 +204,44 @@ TEST(ObjectArray, path) {
|
||||
object_unref(objb1);
|
||||
object_unref(objb2);
|
||||
}
|
||||
|
||||
TEST(ObjectArray, insert) {
|
||||
value_t v;
|
||||
object_t* obj = object_array_create();
|
||||
object_array_t* o = OBJECT_ARRAY(obj);
|
||||
|
||||
ASSERT_EQ(object_array_insert(obj, 0, value_set_str(&v, "c")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "0"), "c");
|
||||
ASSERT_EQ(o->size, 1);
|
||||
|
||||
ASSERT_EQ(object_array_insert(obj, 1, value_set_str(&v, "d")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "1"), "d");
|
||||
ASSERT_EQ(o->size, 2);
|
||||
|
||||
ASSERT_EQ(object_array_insert(obj, 2, value_set_str(&v, "e")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "2"), "e");
|
||||
ASSERT_EQ(o->size, 3);
|
||||
|
||||
ASSERT_EQ(object_array_insert(obj, 0, value_set_str(&v, "b")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "0"), "b");
|
||||
ASSERT_EQ(o->size, 4);
|
||||
|
||||
ASSERT_EQ(object_array_insert(obj, 0, value_set_str(&v, "a")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "0"), "a");
|
||||
ASSERT_EQ(o->size, 5);
|
||||
|
||||
ASSERT_EQ(object_array_push(obj, value_set_str(&v, "hello")), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "5"), "hello");
|
||||
ASSERT_EQ(o->size, 6);
|
||||
|
||||
ASSERT_EQ(object_array_pop(obj, &v), RET_OK);
|
||||
ASSERT_STREQ(value_str(&v), "hello");
|
||||
|
||||
ASSERT_EQ(object_array_pop(obj, &v), RET_OK);
|
||||
ASSERT_STREQ(value_str(&v), "e");
|
||||
|
||||
ASSERT_EQ(object_array_remove(obj, 0), RET_OK);
|
||||
ASSERT_STREQ(object_get_prop_str(obj, "0"), "b");
|
||||
|
||||
object_unref(obj);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user