lept_json的学习之API
这一节就整理一下所有的api
先从整个JSON开始
Parse
用户只能用到parse,像parse_value、parse_whitespace之类就属于内部函数了
int lept_parse(lept_value& v, const char* json){
lept_context c;
int ret;
assert(&v != NULL);
c.json = json;
c.stack = NULL;//初始化堆栈
c.size =c.top = 0;//初识化栈容量和栈顶
lept_init(v);
lept_parse_whitespace(c);
if ((ret = lept_parse_value(c, v)) == LEPT_PARSE_OK) {
lept_parse_whitespace(c);
if (*(c.json) != '\0') {
v.type = LEPT_NULL;
ret = LEPT_PARSE_ROOT_NOT_SINGULAR;
}
}
assert(c.top == 0);//判断栈顶元素是否为0(即栈中所有数据成功弹出
free(c.stack);//释放栈
return ret;
}
Stringify
char* lept_stringify(const lept_value& v, size_t length) {
lept_context c;
assert(&v != NULL);
c.stack = (char*)malloc(c.size = LEPT_PARSE_STRINGIFY_INIT_SIZE);
c.top = 0;
lept_stringify_value(c, v);
if (length)
length = c.top;
PUTC(c, '\0');
return c.stack;
}
Free(JSON)
内存释放也是api,可以给用户使用,让用户在内存管理这一块可以更加确定一块内存的使用与否。
void lept_free (lept_value & v) {
size_t i;
assert(&v != NULL);
switch (v.type) {
case LEPT_STRING:
free(v.u.m_str.s);
break;
case LEPT_ARRAY:
for (i = 0; i < v.u.m_arr.size; i++)
lept_free(v.u.m_arr.e[i]);
free(v.u.m_arr.e);
break;
case LEPT_OBJECT:
for (i = 0; i < v.u.m_obj.size; i++) {
free(v.u.m_obj.m[i].k);
lept_free(v.u.m_obj.m[i].v);
}
free(v.u.m_obj.m);
break;
default: break;
}
v.type = LEPT_NULL;
}
Tool
两值是否相等?相等则返回1,不相等则返回0
size_t lept_find_object_index(const lept_value& v, const char* key, size_t klen);//前向声明
int lept_is_equal(const lept_value& lhs, const lept_value& rhs) {
size_t i;
assert(&lhs != NULL && &rhs != NULL);
if (lhs.type != rhs.type)
return 0;
switch (lhs.type) {
case LEPT_STRING:
return lhs.u.m_str.len == rhs.u.m_str.len &&
memcmp(lhs.u.m_str.s, rhs.u.m_str.s, lhs.u.m_str.len) == 0;
case LEPT_NUMBER:
return lhs.u.m_num == rhs.u.m_num;
case LEPT_ARRAY:
if (lhs.u.m_arr.size != rhs.u.m_arr.size)
return 0;
for (i = 0; i < lhs.u.m_arr.size; i++)
if (!lept_is_equal(lhs.u.m_arr.e[i], rhs.u.m_arr.e[i]))
return 0;
return 1;
case LEPT_OBJECT://对象的键值是无序的,所以不能像array那样逐个比对
if (lhs.u.m_obj.size != rhs.u.m_obj.size)
return 0;
for (i = 0; i < lhs.u.m_obj.size; i++) {
if (lept_find_object_index(rhs, lhs.u.m_obj.m[i].k, lhs.u.m_obj.m[i].klen) == LEPT_KEY_NOT_EXIST)
return 0;
if (!lept_is_equal(lhs.u.m_obj.m[i].v, rhs.u.m_obj.m[i].v))
return 0;
}
return 1;
default:
return 1;
}
}
将一个值赋值给另一个值
void lept_copy(lept_value& dst, const lept_value& src)
{
size_t i;
assert(&src != NULL && &dst != NULL && &src != &dst);
switch (src.type) {
case LEPT_STRING:
lept_set_string(dst, src.u.m_str.s, src.u.m_str.len);
break;
case LEPT_ARRAY:
lept_set_array(dst, src.u.m_arr.size);
for (i = 0; i < src.u.m_arr.size; i++) {
lept_copy(dst.u.m_arr.e[i], src.u.m_arr.e[i]);
}
dst.u.m_arr.size = src.u.m_arr.size;
break;
case LEPT_OBJECT:
lept_set_object(dst, src.u.m_obj.size);
for (i = 0; i < src.u.m_obj.size; i++) {
//k
lept_value& val = lept_set_object_value(dst, src.u.m_obj.m[i].k, src.u.m_obj.m[i].klen);
//v
lept_copy(val, src.u.m_obj.m[i].v);
}
dst.u.m_obj.size = src.u.m_obj.size;
break;
default:
lept_free(dst);
memcpy(&dst, &src, sizeof(lept_value));
break;
}
}
将一个值移动到目标容器
void lept_move(lept_value& dst, lept_value& src)
{
assert(&dst != NULL && &src != NULL && &src != &dst);
lept_free(dst);
memcpy(&dst, &src, sizeof(lept_value));
lept_init(src);
}
交换两个值
void lept_swap(lept_value& lhs, lept_value& rhs)
{
assert(&lhs != NULL && &rhs != NULL);
if (&lhs != &rhs) {
lept_value temp;
memcpy(&temp, &lhs, sizeof(lept_value));
memcpy(&lhs, &rhs, sizeof(lept_value));
memcpy(&rhs, &temp, sizeof(lept_value));
}
}
NULL类型
#define lept_set_null(v) lept_free(v)
对的,null的api其实就是free
BOOL类型
int lept_get_boolean(const lept_value& v)
{
assert(&v != NULL && (v.type == LEPT_TRUE || v.type == LEPT_FALSE));
return v.type == LEPT_TRUE;
}
void lept_set_boolean(lept_value& v, int b)
{
lept_free(v);
v.type = b ? LEPT_TRUE : LEPT_FALSE;
}
NUMBER类型
double lept_get_number(const lept_value& v)
{
assert(&v != NULL);
assert(v.type == LEPT_NUMBER);
return v.u.m_num;
}
void lept_set_number(lept_value& v, double n)//唐铭德独自完成(但做错了
{
lept_free(v);
v.u.m_num = n;
v.type = LEPT_NUMBER;
}
STRING类型
const char* lept_get_string(const lept_value& v) {
assert(&v != NULL && v.type == LEPT_STRING);
return v.u.m_str.s;
}
size_t lept_get_string_length(const lept_value& v) {
assert(&v != NULL && v.type == LEPT_STRING);
return v.u.m_str.len;
}
//设置字符串,将v的s置为输入字符串值和输入字符串长度
void lept_set_string(lept_value& v, const char* s, size_t len) {
assert(&v != NULL && (s != NULL || len == 0));//数据类型不为空,且字符串不为空或长度为0
lept_free(v); //先释放v的string 内存
v.u.m_str.s = (char*)malloc(len + 1); //重新分配内存
memcpy(v.u.m_str.s, s, len); //内存值copy过去
v.u.m_str.s[len] = '\0'; //字符串尾置为空字符
v.u.m_str.len = len; //字符串长赋值
v.type = LEPT_STRING; //类型改为string类
}
ARRAY类型
size_t lept_get_array_size(const lept_value& v)
{
assert(&v != NULL);
assert(v.type == LEPT_ARRAY);
return v.u.m_arr.size;
}
size_t lept_get_array_capacity(const lept_value& v)
{
assert(&v != NULL && v.type == LEPT_ARRAY);
return v.u.m_arr.capacity;
}
void lept_reserve_array(lept_value& v, size_t capacity)
{
assert(&v != NULL && v.type == LEPT_ARRAY);
if (v.u.m_arr.capacity < capacity) {
v.u.m_arr.capacity = capacity;
v.u.m_arr.e = (lept_value*)realloc(v.u.m_arr.e, capacity * sizeof(lept_value));
}
}
void lept_shrink_array(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_ARRAY);
if (v.u.m_arr.capacity > v.u.m_arr.size) {
v.u.m_arr.capacity = v.u.m_arr.size;
v.u.m_arr.e = (lept_value*)realloc(v.u.m_arr.e, v.u.m_arr.capacity * sizeof(lept_value));
}
}
lept_value& lept_pushback_array_element(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_ARRAY);
if (v.u.m_arr.size == v.u.m_arr.capacity)
lept_reserve_array(v, v.u.m_arr.capacity == 0 ? 1 : v.u.m_arr.capacity * 2);
lept_init(v.u.m_arr.e[v.u.m_arr.size]);
return v.u.m_arr.e[v.u.m_arr.size++];
}
void lept_popback_array_element(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_ARRAY && v.u.m_arr.size > 0);
lept_free(v.u.m_arr.e[--v.u.m_arr.size]);
}
lept_value& lept_insert_array_element(lept_value& v, size_t index)
{
assert(&v != NULL && v.type == LEPT_ARRAY && index <= v.u.m_arr.size);
if (v.u.m_arr.size == v.u.m_arr.capacity)
lept_reserve_array(v, v.u.m_arr.capacity == 0 ? 1 : (v.u.m_arr.capacity << 1)); //扩容为原来一倍
memcpy(&v.u.m_arr.e[index + 1], &v.u.m_arr.e[index], (v.u.m_arr.size - index) * sizeof(lept_value));
lept_init(v.u.m_arr.e[index]);
v.u.m_arr.size++;
return v.u.m_arr.e[index];
}
void lept_erase_array_element(lept_value& v, size_t index, size_t count)
{
assert(&v != NULL && v.type == LEPT_ARRAY && index + count <= v.u.m_arr.size);
size_t i;
for (i = index; i < index + count; i++) {
lept_free(v.u.m_arr.e[i]);
}
memcpy( v.u.m_arr.e + index,
v.u.m_arr.e + index + count,
(v.u.m_arr.size - index - count) * sizeof(lept_value));
for (i = v.u.m_arr.size - count; i < v.u.m_arr.size; i++)
lept_init(v.u.m_arr.e[i]);
v.u.m_arr.size -= count;
}
void lept_clear_array(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_ARRAY);
size_t i;
for (i = 0; i < v.u.m_arr.size; i++) {
lept_free(v.u.m_arr.e[i]);
}
v.u.m_arr.size = 0;
}
lept_value& lept_get_array_element(const lept_value& v, size_t index) //返回数组中第index个元素
{
assert(&v != NULL);
assert(v.type == LEPT_ARRAY);
assert(index < v.u.m_arr.size);
return v.u.m_arr.e[index];
}
void lept_set_array(lept_value& v, size_t capacity)
{
assert(&v != NULL);
lept_free(v);
v.type = LEPT_ARRAY;
v.u.m_arr.size = 0;
v.u.m_arr.capacity = capacity;
v.u.m_arr.e = capacity > 0 ? (lept_value*)malloc(capacity * sizeof(lept_value)) : NULL;
}
array中的reserve和shrink也都是为了方便用户内存管理
OBJECT类型
void lept_set_object(lept_value& v, size_t capacity)
{
assert(&v != NULL);
lept_free(v);
v.type = LEPT_OBJECT;
v.u.m_obj.size = 0;
v.u.m_obj.capacity = capacity;
v.u.m_obj.m = capacity > 0 ? (lept_member*)malloc(capacity * sizeof(lept_member)) : NULL;
}
size_t lept_get_object_size(const lept_value& v)
{
assert(&v != NULL );
assert(v.type == LEPT_OBJECT);
return v.u.m_obj.size;
}
size_t lept_get_object_capacity(const lept_value& v)
{
assert(&v != NULL );
assert(v.type == LEPT_OBJECT);
return v.u.m_obj.capacity;
}
const char* lept_get_object_key(const lept_value& v, size_t index)
{
assert(&v != NULL );
assert( v.type == LEPT_OBJECT);
assert(index < v.u.m_obj.size);
return v.u.m_obj.m[index].k;
}
size_t lept_get_object_key_length(const lept_value& v, size_t index)
{
assert(&v != NULL);
assert(v.type == LEPT_OBJECT);
assert(index < v.u.m_obj.size);
return v.u.m_obj.m[index].klen;
}
lept_value& lept_get_object_value(const lept_value& v, size_t index)
{
assert(&v != NULL);
assert(v.type == LEPT_OBJECT);
assert(index < v.u.m_obj.size);
return v.u.m_obj.m[index].v;
}
size_t lept_find_object_index(const lept_value& v, const char* key, size_t klen)//知道key值和长度查index
{
size_t i;
assert(&v != NULL && v.type == LEPT_OBJECT && key != NULL);
for (i = 0; i < v.u.m_obj.size; i++)
if (v.u.m_obj.m[i].klen == klen && memcmp(v.u.m_obj.m[i].k, key, klen) == 0)
return i;
return LEPT_KEY_NOT_EXIST;
}
lept_value& lept_find_object_value(lept_value& v, const char* key, size_t klen) {
assert(&v != NULL);
assert(key != NULL);
assert(klen != 0);
size_t index = lept_find_object_index(v, key, klen);
assert(index != LEPT_KEY_NOT_EXIST);
return v.u.m_obj.m[index].v;
}
lept_value& lept_set_object_value(lept_value& v, const char* key, size_t klen)
{
assert(&v != NULL && v.type == LEPT_OBJECT && key != NULL);
size_t i,index;
index = lept_find_object_index(v, key, klen);
if (index != LEPT_KEY_NOT_EXIST)
return v.u.m_obj.m[index].v;
//key not exist, then we make room and init
if (v.u.m_obj.size == v.u.m_obj.capacity) {
lept_reserve_object(v, v.u.m_obj.capacity == 0 ? 1 : (v.u.m_obj.capacity << 1));
}
i = v.u.m_obj.size;
v.u.m_obj.m[i].k = (char*)malloc((klen + 1));
memcpy(v.u.m_obj.m[i].k, key, klen);
v.u.m_obj.m[i].k[klen] = '\0';
v.u.m_obj.m[i].klen = klen;
lept_init(v.u.m_obj.m[i].v);
v.u.m_obj.size++;
return v.u.m_obj.m[i].v;
}
void lept_remove_object_value(lept_value& v, size_t index)
{
assert(&v != NULL && v.type == LEPT_OBJECT && index < v.u.m_obj.size);
free(v.u.m_obj.m[index].k);
lept_free(v.u.m_obj.m[index].v);
memcpy(v.u.m_obj.m + index, v.u.m_obj.m + index + 1, (v.u.m_obj.size - index - 1) * sizeof(lept_member));
v.u.m_obj.m[--v.u.m_obj.size].k = NULL;
v.u.m_obj.m[v.u.m_obj.size].klen = 0;
lept_init(v.u.m_obj.m[v.u.m_obj.size].v);
}
void lept_reserve_object(lept_value& v, size_t capacity)
{
assert(&v != NULL && v.type == LEPT_OBJECT);
if (v.u.m_obj.capacity < capacity) {
v.u.m_obj.capacity = capacity;
v.u.m_obj.m = (lept_member*)realloc(v.u.m_obj.m, capacity * sizeof(lept_member));
}
}
void lept_shrink_object(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_OBJECT);
if (v.u.m_obj.capacity > v.u.m_obj.size) {
v.u.m_obj.capacity = v.u.m_obj.size;
v.u.m_obj.m = (lept_member*)realloc(v.u.m_obj.m, v.u.m_obj.capacity * sizeof(lept_value));
}
}
void lept_clear_object(lept_value& v)
{
assert(&v != NULL && v.type == LEPT_OBJECT);
size_t i;
for (i = 0; i < v.u.m_obj.size; i++) {
free(v.u.m_obj.m[i].k);
v.u.m_obj.m[i].k = NULL;
v.u.m_obj.m[i].klen = 0;
lept_free(v.u.m_obj.m[i].v);
}
v.u.m_obj.size = 0;
}
英语好的话,这些接口应该是不需要注释也能看懂的。
当然还有这些api的单元测试,叶老师一再强调:
为贯彻 TDD,先写测试:
那么整个json的复习就到这里,虽然从讲解上来讲我可能什么都每讲,不过大致的过程我就这样再过一遍。
总结
那么整个JSON项目到这里就差不多结束了,吧。
(Github上叶老师的第9章还没有完成,但整体上已经全部讲完了)
我的下一个项目是红黑树。
在学习红黑树的实现的过程中,也会将数据结构整个复习一遍。以上。
lept_json Github:https://github.com/miloyip/json-tutorial
本人流星画魂第八次在csdn上做笔记,有什么错误或者是需要改进的地方请即时提出
我只是一个对编程感兴趣的人,但懒得要死,学得又不认真,希望读者能骂就骂两句,真的太懒了