add ubjson parser

This commit is contained in:
lixianjing 2019-09-15 17:57:19 +08:00
parent 90301d46bf
commit 85c308c7aa
9 changed files with 269 additions and 4 deletions

View File

@ -1,5 +1,12 @@
# 最新动态
* 2019/09/15
* ubjson reader
* ubjson parser
* 2019/09/14
* ubjson writer
* 2019/09/13
* 窗口切换到后台时自动失去焦点。

160
src/ubjson/ubjson_parser.c Normal file
View File

@ -0,0 +1,160 @@
/**
* File: ubjson_parser.c
* Author: AWTK Develop Team
* Brief: ubjson parser
*
* Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-09-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#include "tkc/buffer.h"
#include "ubjson/ubjson_parser.h"
typedef enum _parse_state_t {
STATE_NONE,
STATE_KEY,
STATE_VALUE,
STATE_ARRAY,
} parse_state_t;
typedef struct _ubjson_parser_t {
void* ctx;
str_t temp;
rbuffer_t rb;
object_t* obj;
object_t* root;
parse_state_t state;
ubjson_reader_t reader;
} ubjson_parser_t;
#define PROP_PARENT "__parent__"
static ubjson_parser_t* ubjson_parser_init(ubjson_parser_t* parser, void* data, uint32_t size) {
str_t* temp = &(parser->temp);
rbuffer_t* rb = &(parser->rb);
ubjson_reader_t* reader = &(parser->reader);
str_init(temp, 64);
rbuffer_init(rb, data, size);
parser->state = STATE_NONE;
ubjson_reader_init(reader, (ubjson_read_callback_t)rbuffer_read_binary, rb);
return parser;
}
static ret_t ubjson_parser_deinit(ubjson_parser_t* parser) {
str_t* temp = &(parser->temp);
ubjson_reader_t* reader = &(parser->reader);
str_reset(temp);
ubjson_reader_reset(reader);
return RET_OK;
}
static ret_t ubjson_parser_read(ubjson_parser_t* parser, value_t* v) {
ubjson_reader_t* reader = &(parser->reader);
return ubjson_reader_read(reader, v);
}
static ret_t ubjson_parser_on_value(ubjson_parser_t* parser, value_t* v) {
str_t* str = &(parser->temp);
switch (parser->state) {
case STATE_NONE: {
if (v->type == VALUE_TYPE_TOKEN && value_token(v) == UBJSON_MARKER_OBJECT_BEGIN) {
parser->obj = object_default_create();
return_value_if_fail(parser->obj != NULL, RET_OOM);
parser->state = STATE_KEY;
parser->root = parser->obj;
} else {
assert(!"invalid format");
return RET_BAD_PARAMS;
}
break;
}
case STATE_KEY: {
if (v->type == VALUE_TYPE_TOKEN) {
if (value_token(v) == UBJSON_MARKER_OBJECT_END) {
object_t* parent = (object_t*)object_get_prop_pointer(parser->obj, PROP_PARENT);
parser->obj = parent;
} else {
assert(!"invalid format");
return RET_BAD_PARAMS;
}
} else if (v->type == VALUE_TYPE_STRING) {
return_value_if_fail(str_set(str, value_str(v)) == RET_OK, RET_OOM);
parser->state = STATE_VALUE;
} else {
assert(!"invalid format");
return RET_BAD_PARAMS;
}
break;
}
case STATE_VALUE: {
if (v->type == VALUE_TYPE_TOKEN) {
if (value_token(v) == UBJSON_MARKER_OBJECT_BEGIN) {
object_t* obj = object_default_create();
return_value_if_fail(obj != NULL, RET_OOM);
parser->state = STATE_KEY;
object_set_prop_object(parser->obj, str->str, obj);
object_set_prop_pointer(obj, PROP_PARENT, parser->obj);
parser->obj = obj;
object_unref(obj);
} else {
assert(!"invalid format");
return RET_BAD_PARAMS;
}
} else {
parser->state = STATE_KEY;
object_set_prop(parser->obj, str->str, v);
}
break;
}
default:
break;
}
return RET_OK;
}
ret_t ubjson_do_parse(ubjson_parser_t* parser) {
value_t v;
while (TRUE) {
if (ubjson_parser_read(parser, &v) != RET_OK) {
break;
}
ubjson_parser_on_value(parser, &v);
}
return RET_OK;
}
object_t* ubjson_parse(void* data, uint32_t size) {
ubjson_parser_t parser;
return_value_if_fail(data != NULL && size > 0, NULL);
ubjson_parser_init(&parser, data, size);
ubjson_do_parse(&parser);
ubjson_parser_deinit(&parser);
return parser.root;
}

View File

@ -0,0 +1,34 @@
/**
* File: ubjson_parser.h
* Author: AWTK Develop Team
* Brief: ubjson parser
*
* Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2019-09-15 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef TK_UBJSON_PARSER_H
#define TK_UBJSON_PARSER_H
#include "tkc/object_default.h"
#include "ubjson/ubjson_reader.h"
BEGIN_C_DECLS
object_t* ubjson_parse(void* data, uint32_t size);
END_C_DECLS
#endif /*TK_UBJSON_PARSER_H*/

View File

@ -137,6 +137,7 @@ ret_t ubjson_reader_read(ubjson_reader_t* reader, value_t* v) {
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->str[len] = '\0';
value_set_str(v, str->str);
break;
}

View File

@ -139,7 +139,7 @@ ret_t ubjson_writer_write_char(ubjson_writer_t* writer, char value) {
return RET_OK;
}
ret_t ubjson_writer_write_string(ubjson_writer_t* writer, const char* value) {
ret_t ubjson_writer_write_str(ubjson_writer_t* writer, const char* value) {
uint32_t len = 0;
return_value_if_fail(writer != NULL && value != NULL, RET_BAD_PARAMS);
return_value_if_fail(ubjson_writer_write_marker(writer, UBJSON_MARKER_STRING) == RET_OK, RET_OOM);

View File

@ -52,7 +52,7 @@ ret_t ubjson_writer_write_int64(ubjson_writer_t* writer, int64_t value);
ret_t ubjson_writer_write_float32(ubjson_writer_t* writer, float value);
ret_t ubjson_writer_write_float64(ubjson_writer_t* writer, double value);
ret_t ubjson_writer_write_char(ubjson_writer_t* writer, char value);
ret_t ubjson_writer_write_string(ubjson_writer_t* writer, const char* value);
ret_t ubjson_writer_write_str(ubjson_writer_t* writer, const char* value);
ret_t ubjson_writer_write_array_begin(ubjson_writer_t* writer);
ret_t ubjson_writer_write_array_end(ubjson_writer_t* writer);
ret_t ubjson_writer_write_object_begin(ubjson_writer_t* writer);

View File

@ -0,0 +1,63 @@
#include "gtest/gtest.h"
#include "tkc/buffer.h"
#include "ubjson/ubjson_writer.h"
#include "ubjson/ubjson_parser.h"
TEST(UBJsonWriter, basic) {
uint8_t buff[256];
wbuffer_t wb;
ubjson_writer_t ub;
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_str(&ub, "name"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "aaa"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "age"), RET_OK);
ASSERT_EQ(ubjson_writer_write_int32(&ub, 100), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
obj = ubjson_parse(wb.data, wb.cursor);
ASSERT_STREQ(object_get_prop_str(obj, "name"), "aaa");
ASSERT_EQ(object_get_prop_int(obj, "age", 0), 100);
object_unref(obj);
}
TEST(UBJsonWriter, embedded) {
uint8_t buff[256];
wbuffer_t wb;
ubjson_writer_t ub;
object_t* obj = NULL;
object_t* addr = 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_str(&ub, "name"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "aaa"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "age"), RET_OK);
ASSERT_EQ(ubjson_writer_write_int32(&ub, 100), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "addr"), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_begin(&ub), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "city"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "shenzhen"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "post"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "518000"), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
ASSERT_EQ(ubjson_writer_write_object_end(&ub), RET_OK);
obj = ubjson_parse(wb.data, wb.cursor);
ASSERT_STREQ(object_get_prop_str(obj, "name"), "aaa");
ASSERT_EQ(object_get_prop_int(obj, "age", 0), 100);
addr = object_get_prop_object(obj, "addr");
ASSERT_EQ(addr != NULL, true);
ASSERT_STREQ(object_get_prop_str(addr, "city"), "shenzhen");
ASSERT_STREQ(object_get_prop_str(addr, "post"), "518000");
object_unref(obj);
}

View File

@ -180,7 +180,7 @@ TEST(UBJsonReader, double) {
TEST(UBJsonReader, string) {
PREPARE_TEST();
ASSERT_EQ(ubjson_writer_write_string(&ub, "a"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "a"), RET_OK);
rb.capacity = wb.cursor;
ASSERT_EQ(ubjson_reader_read(&ur, &v), RET_OK);

View File

@ -184,7 +184,7 @@ TEST(UBJsonWriter, string) {
wbuffer_init(&wb, buff, sizeof(buff));
ubjson_writer_init(&ub, (ubjson_write_callback_t)wbuffer_write_binary, &wb);
ASSERT_EQ(ubjson_writer_write_string(&ub, "a"), RET_OK);
ASSERT_EQ(ubjson_writer_write_str(&ub, "a"), RET_OK);
ASSERT_EQ(buff[0], UBJSON_MARKER_STRING);
ASSERT_EQ(buff[1], UBJSON_MARKER_INT8);