improve ubjson

This commit is contained in:
lixianjing 2025-02-14 17:44:55 +08:00
parent ca4a3278c9
commit f8dfd03f9e
10 changed files with 641 additions and 14 deletions

View File

@ -2,6 +2,7 @@
2025/02/14
* endian类增加了小端的支持和修改了注释增加测试用例(感谢智明提供补丁)
* 实现了 ubjson 规范中的使用类型和计数进行数组优化(感谢林福提供补丁)
2025/02/13
* 更新1m资源感谢泽武提供补丁

View File

@ -48,7 +48,11 @@ typedef enum _ubjson_marker_t {
UBJSON_MARKER_ARRAY_BEGIN = '[',
UBJSON_MARKER_ARRAY_END = ']',
UBJSON_MARKER_OBJECT_BEGIN = '{',
UBJSON_MARKER_OBJECT_END = '}'
UBJSON_MARKER_OBJECT_END = '}',
/* container optimized format */
UBJSON_MARKER_CONTAINER_TYPE = '&',
UBJSON_MARKER_CONTAINER_COUNT = '#',
} ubjson_marker_t;
END_C_DECLS

View File

@ -39,6 +39,8 @@ typedef struct _ubjson_parser_t {
bool_t error;
uint32_t level;
tk_object_t* stack[MAX_LEVEL + 1];
uint32_t optimized_type;
} ubjson_parser_t;
static ret_t ubjson_do_parse_object(ubjson_parser_t* parser);
@ -123,6 +125,65 @@ static ret_t ubjson_parser_read(ubjson_parser_t* parser, value_t* v) {
return ubjson_reader_read(reader, v);
}
static ret_t ubjson_on_optimized_array_object(ubjson_parser_t* parser, const char* key,
value_t* v) {
ret_t ret = RET_OK;
uint32_t type = parser->optimized_type;
parser->optimized_type = 0;
if (type == UBJSON_MARKER_UINT8) {
uint8_t* p = v->value.binary_data.data;
for (uint32_t i = 0; i < v->value.binary_data.size; i++) {
ret = tk_object_set_prop_uint8(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_INT8) {
int8_t* p = v->value.binary_data.data;
for (uint32_t i = 0; i < v->value.binary_data.size; i++) {
ret = tk_object_set_prop_int8(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_INT16) {
int16_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int16_t);
for (uint32_t i = 0; i < count; i++) {
ret = tk_object_set_prop_int16(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_INT32) {
int32_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int32_t);
for (uint32_t i = 0; i < count; i++) {
ret = tk_object_set_prop_int32(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_INT64) {
int64_t* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(int64_t);
for (uint32_t i = 0; i < count; i++) {
ret = tk_object_set_prop_int64(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_FLOAT32) {
float* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(float);
for (uint32_t i = 0; i < count; i++) {
ret = tk_object_set_prop_float(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else if (type == UBJSON_MARKER_FLOAT64) {
double* p = v->value.binary_data.data;
uint32_t count = v->value.binary_data.size / sizeof(double);
for (uint32_t i = 0; i < count; i++) {
ret = tk_object_set_prop_double(parser->obj, key, p[i]);
return_value_if_fail(ret == RET_OK, ret);
}
} else {
return_value_if_fail(!"not support!", RET_FAIL);
}
return ret;
}
static ret_t ubjson_on_key_value_object(void* ctx, const char* key, value_t* v) {
ret_t ret = RET_OK;
ubjson_parser_t* parser = (ubjson_parser_t*)ctx;
@ -134,6 +195,7 @@ static ret_t ubjson_on_key_value_object(void* ctx, const char* key, value_t* v)
if (v->type == VALUE_TYPE_TOKEN) {
uint32_t token = value_token(v);
if (token == UBJSON_MARKER_OBJECT_BEGIN || token == UBJSON_MARKER_ARRAY_BEGIN) {
tk_object_t* obj =
token == UBJSON_MARKER_OBJECT_BEGIN ? object_default_create() : object_array_create();
@ -152,12 +214,26 @@ static ret_t ubjson_on_key_value_object(void* ctx, const char* key, value_t* v)
tk_object_unref(obj);
} else if (token == UBJSON_MARKER_OBJECT_END || token == UBJSON_MARKER_ARRAY_END) {
ret = ubjson_parser_pop(parser);
} else if (token == UBJSON_MARKER_UINT8 || token == UBJSON_MARKER_INT8 ||
token == UBJSON_MARKER_INT16 || token == UBJSON_MARKER_INT32 ||
token == UBJSON_MARKER_INT64 || token == UBJSON_MARKER_FLOAT32 ||
token == UBJSON_MARKER_FLOAT64) {
parser->optimized_type = token;
} else {
assert(!"not supported");
ret = RET_NOT_IMPL;
}
} else {
ret = tk_object_set_prop(parser->obj, key, v);
if (parser->optimized_type != 0) {
return_value_if_fail(v->type == VALUE_TYPE_BINARY, RET_FAIL);
ubjson_on_optimized_array_object(parser, key, v);
ret = ubjson_parser_pop(parser);
} else {
ret = tk_object_set_prop(parser->obj, key, v);
}
}
return ret;
@ -248,8 +324,11 @@ static ret_t ubjson_do_parse_array(ubjson_parser_t* parser) {
ubjson_do_parse_array(parser);
continue;
} else {
assert(!"invalid format");
return RET_BAD_PARAMS;
ubjson_parser_on_key_value(parser, NULL, v); /* 上报优化数组的类型 */
return_value_if_fail(ubjson_parser_read(parser, &value) == RET_OK, RET_FAIL);
ubjson_parser_on_key_value(parser, NULL, v);
return RET_OK;
}
}

View File

@ -57,11 +57,78 @@ static bool_t is_binary(const char* str, uint32_t len) {
return FALSE;
}
static ret_t ubjson_reader_read_optimized_array(ubjson_reader_t* reader, uint8_t type, int count,
value_t* v) {
return_value_if_fail(reader != NULL && reader->read != NULL && v != NULL, RET_BAD_PARAMS);
ret_t ret = RET_OK;
value_t vlen;
int len = 0;
str_t* str = &(reader->str);
if (type == UBJSON_MARKER_UINT8 || type == UBJSON_MARKER_INT8) {
len = count;
} else if (type == UBJSON_MARKER_INT16) {
len = count * sizeof(int16_t);
} else if (type == UBJSON_MARKER_INT32) {
len = count * sizeof(int32_t);
} else if (type == UBJSON_MARKER_INT64) {
len = count * sizeof(int64_t);
} else if (type == UBJSON_MARKER_FLOAT32) {
len = count * sizeof(float);
} else if (type == UBJSON_MARKER_FLOAT64) {
len = count * sizeof(double);
}
return_value_if_fail(str_extend(str, len + 1) == RET_OK, RET_OOM);
return_value_if_fail(ubjson_reader_read_data(reader, str->str, len) == RET_OK, RET_FAIL);
str->size = len;
str->str[len] = '\0';
if (type == UBJSON_MARKER_INT16) {
int16_t* p = (int16_t*)str->str;
for (int i = 0; i < count; i++) {
int16_t vp = uint16_from_big_endian(p[i]);
p[i] = vp;
}
} else if (type == UBJSON_MARKER_INT32) {
int32_t* p = (int32_t*)str->str;
for (int i = 0; i < count; i++) {
int32_t vp = int32_from_big_endian(p[i]);
p[i] = vp;
}
} else if (type == UBJSON_MARKER_INT64) {
int64_t* p = (int64_t*)str->str;
for (int i = 0; i < count; i++) {
int64_t vp = int64_from_big_endian(p[i]);
p[i] = vp;
}
} else if (type == UBJSON_MARKER_FLOAT32) {
float* p = (float*)str->str;
for (int i = 0; i < count; i++) {
float vp = float_from_big_endian(p[i]);
p[i] = vp;
}
} else if (type == UBJSON_MARKER_FLOAT64) {
double* p = (double*)str->str;
for (int i = 0; i < count; i++) {
double vp = double_from_big_endian(p[i]);
p[i] = vp;
}
}
value_set_binary_data(v, str->str, len);
return RET_OK;
}
ret_t ubjson_reader_read(ubjson_reader_t* reader, value_t* v) {
ret_t ret = RET_OK;
uint8_t marker = 0;
return_value_if_fail(reader != NULL && reader->read != NULL && v != NULL, RET_BAD_PARAMS);
ret = ubjson_reader_read_data(reader, &marker, 1);
if (ret != RET_OK) {
@ -219,6 +286,24 @@ ret_t ubjson_reader_read(ubjson_reader_t* reader, value_t* v) {
value_set_token(v, UBJSON_MARKER_OBJECT_END);
break;
}
case UBJSON_MARKER_CONTAINER_TYPE: {
ret = ubjson_reader_read_data(reader, &marker, 1);
return_value_if_fail(ret == RET_OK, RET_FAIL);
value_set_token(v, marker);
reader->optimized_type = marker;
break;
}
case UBJSON_MARKER_CONTAINER_COUNT: {
value_t vlen;
ret = ubjson_reader_read(reader, &vlen);
return_value_if_fail(ret == RET_OK, RET_FAIL);
ret = ubjson_reader_read_optimized_array(reader, reader->optimized_type, value_int(&vlen), v);
reader->optimized_type = 0;
break;
}
default: {
ret = RET_FAIL;
break;

View File

@ -38,6 +38,7 @@ struct _ubjson_reader_t {
str_t str;
wstr_t wstr;
ubjson_read_callback_t read;
uint8_t optimized_type;
};
ubjson_reader_t* ubjson_reader_init(ubjson_reader_t* reader, ubjson_read_callback_t read,

View File

@ -45,18 +45,23 @@ static ret_t ubjson_writer_write_marker(ubjson_writer_t* writer, uint8_t marker)
return ubjson_writer_write_data(writer, &marker, 1);
}
static ret_t ubjson_writer_write_length(ubjson_writer_t* writer, uint32_t len) {
ret_t ret = RET_BAD_PARAMS;
if (len <= INT8_MAX) {
ret = ubjson_writer_write_int8(writer, (int8_t)len);
} else if (len <= INT16_MAX) {
ret = ubjson_writer_write_int16(writer, (int16_t)len);
} else if (len <= INT_MAX) {
ret = ubjson_writer_write_int32(writer, (int32_t)len);
}
return ret;
}
static ret_t ubjson_writer_write_key_len(ubjson_writer_t* writer, const char* value, uint32_t len) {
return_value_if_fail(writer != NULL && value != NULL, RET_BAD_PARAMS);
if (len <= INT8_MAX) {
ubjson_writer_write_int8(writer, (int8_t)len);
} else if (len <= INT16_MAX) {
ubjson_writer_write_int16(writer, (int16_t)len);
} else if (len <= INT_MAX) {
ubjson_writer_write_int32(writer, (int32_t)len);
} else {
return RET_BAD_PARAMS;
}
return_value_if_fail(ubjson_writer_write_length(writer, len) == RET_OK, RET_OOM);
return_value_if_fail(ubjson_writer_write_data(writer, value, len) == RET_OK, RET_OOM);
@ -496,3 +501,104 @@ ret_t ubjson_writer_write_object_end(ubjson_writer_t* writer) {
return RET_OK;
}
static ret_t ubjson_writer_write_optimized_array(ubjson_writer_t* writer, char type, uint32_t count,
void* array) {
ret_t ret;
return_value_if_fail(writer != NULL && array != NULL && count > 0, RET_BAD_PARAMS);
return_value_if_fail(ubjson_writer_write_marker(writer, UBJSON_MARKER_ARRAY_BEGIN) == RET_OK,
RET_OOM);
return_value_if_fail(ubjson_writer_write_marker(writer, UBJSON_MARKER_CONTAINER_TYPE) == RET_OK,
RET_OOM);
return_value_if_fail(ubjson_writer_write_marker(writer, type) == RET_OK, RET_OOM);
return_value_if_fail(ubjson_writer_write_marker(writer, UBJSON_MARKER_CONTAINER_COUNT) == RET_OK,
RET_OOM);
return_value_if_fail(ubjson_writer_write_length(writer, count) == RET_OK, RET_OOM);
if (type == UBJSON_MARKER_INT8 || type == UBJSON_MARKER_UINT8) {
ret = ubjson_writer_write_data(writer, array, count);
return_value_if_fail(ret == RET_OK, RET_OOM);
} else if (type == UBJSON_MARKER_INT16) {
int16_t* p = (int16_t*)array;
for (uint32_t i = 0; i < count; i++) {
int16_t val = p[i];
val = int16_to_big_endian(val);
ret = ubjson_writer_write_data(writer, &val, sizeof(val));
return_value_if_fail(ret == RET_OK, RET_OOM);
}
} else if (type == UBJSON_MARKER_INT32) {
int32_t* p = (int32_t*)array;
for (uint32_t i = 0; i < count; i++) {
int32_t val = p[i];
val = int32_to_big_endian(val);
ret = ubjson_writer_write_data(writer, &val, sizeof(val));
return_value_if_fail(ret == RET_OK, RET_OOM);
}
} else if (type == UBJSON_MARKER_INT64) {
int64_t* p = (int64_t*)array;
for (uint32_t i = 0; i < count; i++) {
int64_t val = p[i];
val = int64_to_big_endian(val);
ret = ubjson_writer_write_data(writer, &val, sizeof(val));
return_value_if_fail(ret == RET_OK, RET_OOM);
}
} else if (type == UBJSON_MARKER_FLOAT32) {
float* p = (float*)array;
for (uint32_t i = 0; i < count; i++) {
float val = p[i];
val = float_to_big_endian(val);
ret = ubjson_writer_write_data(writer, &val, sizeof(val));
return_value_if_fail(ret == RET_OK, RET_OOM);
}
} else if (type == UBJSON_MARKER_FLOAT64) {
double* p = (double*)array;
for (uint32_t i = 0; i < count; i++) {
double val = p[i];
val = double_to_big_endian(val);
ret = ubjson_writer_write_data(writer, &val, sizeof(val));
return_value_if_fail(ret == RET_OK, RET_OOM);
}
}
/* 优化数组,没有结束标记 */
return RET_OK;
}
ret_t ubjson_writer_write_array_uint8(ubjson_writer_t* writer, uint8_t* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_UINT8, count, data);
}
ret_t ubjson_writer_write_array_int8(ubjson_writer_t* writer, int8_t* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_INT8, count, data);
}
ret_t ubjson_writer_write_array_int16(ubjson_writer_t* writer, int16_t* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_INT16, count, data);
}
ret_t ubjson_writer_write_array_int32(ubjson_writer_t* writer, int32_t* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_INT32, count, data);
}
ret_t ubjson_writer_write_array_int64(ubjson_writer_t* writer, int64_t* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_INT64, count, data);
}
ret_t ubjson_writer_write_array_float32(ubjson_writer_t* writer, float* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_FLOAT32, count, data);
}
ret_t ubjson_writer_write_array_float64(ubjson_writer_t* writer, double* data, uint32_t count) {
return ubjson_writer_write_optimized_array(writer, UBJSON_MARKER_FLOAT64, count, data);
}

View File

@ -705,6 +705,91 @@ ret_t ubjson_writer_write_kv_wstr_len(ubjson_writer_t* writer, const char* key,
*/
ret_t ubjson_writer_write_kv_value(ubjson_writer_t* writer, const char* key, const value_t* value);
/**
* @method ubjson_writer_write_array_uint8
* uint8
*
* @param {ubjson_writer_t*} writer writer对象
* @param {uint8_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_uint8(ubjson_writer_t* writer, uint8_t* data, uint32_t count);
/**
* @method ubjson_writer_write_array_int8
* int8
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int8_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_int8(ubjson_writer_t* writer, int8_t* data, uint32_t count);
/**
* @method ubjson_writer_write_array_int16
* int16
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int16_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_int16(ubjson_writer_t* writer, int16_t* data, uint32_t count);
/**
* @method ubjson_writer_write_array_int32
* int32
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int32_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_int32(ubjson_writer_t* writer, int32_t* data, uint32_t count);
/**
* @method ubjson_writer_write_array_int64
* int64
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int32_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_int64(ubjson_writer_t* writer, int64_t* data, uint32_t count);
/**
* @method ubjson_writer_write_array_float32
* float32
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int32_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_float32(ubjson_writer_t* writer, float* data, uint32_t count);
/**
* @method ubjson_writer_write_array_float64
* float64
*
* @param {ubjson_writer_t*} writer writer对象
* @param {int32_t*} data
* @param {uint32_t} count
*
* @return {ret_t} ret_t
*/
ret_t ubjson_writer_write_array_float64(ubjson_writer_t* writer, double* data, uint32_t count);
END_C_DECLS
#endif /*TK_UBJSON_WRITER_H*/

View File

@ -271,3 +271,99 @@ TEST(UBJsonParser, ubjson_writer_write_kv_value) {
tk_object_unref(obj);
}
TEST(UBJsonParser, optimized_array_uint8) {
uint8_t buff[256];
uint8_t data[] = {100, 200, 255};
value_t v;
wbuffer_t wb;
ubjson_writer_t ub;
tk_object_t* obj = NULL;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
ASSERT_EQ(ubjson_writer_write_object_begin(&ub), RET_OK);
ASSERT_EQ(ubjson_writer_write_key(&ub, "values"), RET_OK);
ASSERT_EQ(ubjson_writer_write_array_uint8(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
obj = object_from_ubjson(wb.data, wb.cursor);
ASSERT_EQ(tk_object_get_prop_by_path(obj, "values.0", &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_UINT8, true);
ASSERT_EQ(value_int(&v), 100);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.1", 0), 200);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.2", 0), 255);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.size", 0), 3);
tk_object_unref(obj);
}
TEST(UBJsonParser, optimized_array_int32) {
uint8_t buff[256];
int32_t data[] = {100, 200, 300};
value_t v;
wbuffer_t wb;
ubjson_writer_t ub;
tk_object_t* obj = NULL;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
ASSERT_EQ(ubjson_writer_write_object_begin(&ub), RET_OK);
ASSERT_EQ(ubjson_writer_write_key(&ub, "values"), RET_OK);
ASSERT_EQ(ubjson_writer_write_array_int32(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
obj = object_from_ubjson(wb.data, wb.cursor);
ASSERT_EQ(tk_object_get_prop_by_path(obj, "values.0", &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_INT32, true);
ASSERT_EQ(value_int(&v), 100);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.1", 0), 200);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.2", 0), 300);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.size", 0), 3);
tk_object_unref(obj);
}
TEST(UBJsonParser, optimized_array_float64) {
uint8_t buff[256];
double data[] = {100.11, 200.11, 300.11};
value_t v;
wbuffer_t wb;
ubjson_writer_t ub;
tk_object_t* obj = NULL;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
ASSERT_EQ(ubjson_writer_write_object_begin(&ub), RET_OK);
ASSERT_EQ(ubjson_writer_write_key(&ub, "values"), RET_OK);
ASSERT_EQ(ubjson_writer_write_array_float64(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(ubjson_writer_write_kv_str(&ub, "name", "optimized_array"), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
obj = object_from_ubjson(wb.data, wb.cursor);
ASSERT_EQ(tk_object_get_prop_by_path(obj, "values.0", &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_DOUBLE, true);
ASSERT_EQ(value_double(&v), 100.11);
ASSERT_EQ(tk_object_get_prop_by_path(obj, "values.1", &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_DOUBLE, true);
ASSERT_EQ(value_double(&v), 200.11);
ASSERT_EQ(tk_object_get_prop_by_path(obj, "values.2", &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_DOUBLE, true);
ASSERT_EQ(value_double(&v), 300.11);
ASSERT_EQ(tk_object_get_prop_int_by_path(obj, "values.size", 0), 3);
ASSERT_STREQ(tk_object_get_prop_str_by_path(obj, "name"), "optimized_array");
tk_object_unref(obj);
}

View File

@ -4,7 +4,7 @@
#include "ubjson/ubjson_reader.h"
#define PREPARE_TEST() \
uint8_t buff[256]; \
uint8_t buff[4096]; \
value_t v; \
wbuffer_t wb; \
rbuffer_t rb; \
@ -267,3 +267,90 @@ TEST(UBJsonReader, wstring) {
ubjson_reader_reset(&ur);
}
TEST(UBJsonReader, optimized_array_uint8) {
PREPARE_TEST();
uint8_t data[120];
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i;
}
ASSERT_EQ(ubjson_writer_write_array_uint8(&ub, data, ARRAY_SIZE(data)), RET_OK);
rb.capacity = wb.cursor;
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_ARRAY_BEGIN);
// 优化数组的类型
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_UINT8);
// 数据
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type, VALUE_TYPE_BINARY);
ASSERT_TRUE(memcmp(v.value.binary_data.data, data, ARRAY_SIZE(data)) == 0);
ASSERT_EQ(v.value.binary_data.size, ARRAY_SIZE(data));
ubjson_reader_reset(&ur);
}
TEST(UBJsonReader, optimized_array_int32) {
PREPARE_TEST();
int32_t data[120];
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i;
}
ASSERT_EQ(ubjson_writer_write_array_int32(&ub, data, ARRAY_SIZE(data)), RET_OK);
rb.capacity = wb.cursor;
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_ARRAY_BEGIN);
// 优化数组的类型
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_INT32);
// 数据
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type, VALUE_TYPE_BINARY);
ASSERT_TRUE(memcmp(v.value.binary_data.data, data, sizeof(data)) == 0);
ASSERT_EQ(v.value.binary_data.size, sizeof(data));
ubjson_reader_reset(&ur);
}
TEST(UBJsonReader, optimized_array_double) {
PREPARE_TEST();
double data[120];
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i * 1.11;
}
ASSERT_EQ(ubjson_writer_write_array_float64(&ub, data, ARRAY_SIZE(data)), RET_OK);
rb.capacity = wb.cursor;
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_ARRAY_BEGIN);
// 优化数组的类型
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type == VALUE_TYPE_TOKEN, true);
ASSERT_EQ(value_token(&v), UBJSON_MARKER_FLOAT64);
// 数据
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);
ASSERT_EQ(v.type, VALUE_TYPE_BINARY);
ASSERT_TRUE(memcmp(v.value.binary_data.data, data, sizeof(data)) == 0);
ASSERT_EQ(v.value.binary_data.size, sizeof(data));
ubjson_reader_reset(&ur);
}

View File

@ -1,5 +1,6 @@
#include "gtest/gtest.h"
#include "tkc/buffer.h"
#include "tkc/endian.h"
#include "ubjson/ubjson_writer.h"
TEST(UBJsonWriter, null) {
@ -355,3 +356,85 @@ TEST(UBJsonWriter, kv_wstring_len) {
ASSERT_EQ(buff[6], 'b');
ASSERT_EQ(wb.cursor, 7u);
}
TEST(UBJsonWriter, optimized_array_uint8) {
uint8_t buff[256];
uint8_t data[120];
wbuffer_t wb;
ubjson_writer_t ub;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i;
}
ASSERT_EQ(ubjson_writer_write_array_uint8(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(wb.cursor, 6 + sizeof(data));
ASSERT_EQ(buff[0], UBJSON_MARKER_ARRAY_BEGIN);
ASSERT_EQ(buff[1], UBJSON_MARKER_CONTAINER_TYPE);
ASSERT_EQ(buff[2], UBJSON_MARKER_UINT8);
ASSERT_EQ(buff[3], UBJSON_MARKER_CONTAINER_COUNT);
ASSERT_EQ(buff[4], UBJSON_MARKER_INT8);
ASSERT_EQ(buff[5], ARRAY_SIZE(data));
ASSERT_EQ(memcmp(buff + 6, data, sizeof(data)), 0);
}
TEST(UBJsonWriter, optimized_array_int32) {
uint8_t buff[256 + 120 * sizeof(int32_t)];
int32_t data[120];
wbuffer_t wb;
ubjson_writer_t ub;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i;
}
ASSERT_EQ(ubjson_writer_write_array_int32(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(wb.cursor, 6 + sizeof(data));
ASSERT_EQ(buff[0], UBJSON_MARKER_ARRAY_BEGIN);
ASSERT_EQ(buff[1], UBJSON_MARKER_CONTAINER_TYPE);
ASSERT_EQ(buff[2], UBJSON_MARKER_INT32);
ASSERT_EQ(buff[3], UBJSON_MARKER_CONTAINER_COUNT);
ASSERT_EQ(buff[4], UBJSON_MARKER_INT8);
ASSERT_EQ(buff[5], ARRAY_SIZE(data));
int32_t* p = (int32_t*)(buff + 6);
for (int i = 0; i < ARRAY_SIZE(data); i++) {
int32_t v = int32_from_big_endian(p[i]);
ASSERT_EQ(v, data[i]);
}
}
TEST(UBJsonWriter, optimized_array_float64) {
uint8_t buff[256 + 120 * sizeof(double)];
double data[120];
wbuffer_t wb;
ubjson_writer_t ub;
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
for (int i = 0; i < ARRAY_SIZE(data); i++) {
data[i] = i * 1.11;
}
ASSERT_EQ(ubjson_writer_write_array_float64(&ub, data, ARRAY_SIZE(data)), RET_OK);
ASSERT_EQ(wb.cursor, 6 + sizeof(data));
ASSERT_EQ(buff[0], UBJSON_MARKER_ARRAY_BEGIN);
ASSERT_EQ(buff[1], UBJSON_MARKER_CONTAINER_TYPE);
ASSERT_EQ(buff[2], UBJSON_MARKER_FLOAT64);
ASSERT_EQ(buff[3], UBJSON_MARKER_CONTAINER_COUNT);
ASSERT_EQ(buff[4], UBJSON_MARKER_INT8);
ASSERT_EQ(buff[5], ARRAY_SIZE(data));
double* p = (double*)(buff + 6);
for (int i = 0; i < ARRAY_SIZE(data); i++) {
double v = double_from_big_endian(p[i]);
ASSERT_EQ(v, data[i]);
}
}