improve object_array

This commit is contained in:
lixianjing 2021-01-08 12:08:32 +08:00
parent 4c4470376f
commit e760b78332
3 changed files with 178 additions and 45 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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);
}