libubox—kvlist工具
Libubox 是 OpenWrt 的一个必备的基础库,包含大小端转换、链表、MD5 、定时器等实用工具基础库。
Libubox的kvlist
组件基于平衡二叉树实现,另外kvlist
是纯数据结构组件,不依赖uloop
.
下面介绍其kvlist
工具的使用方法:
kvlist主要数据结构和函数
struct kvlist {
struct avl_tree avl;
int (*get_len)(struct kvlist *kv, const void *data);
};
struct kvlist
用于描述一个kvlist
,其数据储存在平衡二叉树avl
.
get_len()
需要我们自行实现,其作用是获取插入KV
值的长度,也就是data
的实际长度。
//静态初始化一个kvlist
#define KVLIST(_name, _get_len) \
struct kvlist _name = KVLIST_INIT(_name, _get_len)
//动态初始化一个kvlist
void kvlist_init(struct kvlist *kv, int (*get_len)(struct kvlist *kv, const void *data));
//删除一个kvlist
void kvlist_free(struct kvlist *kv);
//根据key值在kvlist中查找value
void *kvlist_get(struct kvlist *kv, const char *name);
//向kvlist中添加kv键值对
bool kvlist_set(struct kvlist *kv, const char *name, const void *data);
//根据key值删除kvlist中指定的键值对
bool kvlist_delete(struct kvlist *kv, const char *name);
//kvlist_strlen是一个参考的(*get_len)函数,不一定适用于所有的情况,例如当data是结构体时就无法通过strlen计算其长度
int kvlist_strlen(struct kvlist *kv, const void *data)
{
return strlen(data) + 1;
}
//遍历kvlist中所有的成员
#define kvlist_for_each(kv, name, value)
如果key的值一样,那么后添加的kv会覆盖前面的。因此,key的值必须不不同,否则会造成数据覆盖。
kvlist_for_each
宏定义可以遍历一个kvlist中所有的成员,调试时使用十分方便。使用方法见下文。
kvlist使用实例
#include "stdio.h"
#include "string.h"
#include "kvlist.h"
typedef struct user_data
{
int id;
char name[10];
};
struct user_data data1={1,"data1"};
struct user_data data2={2,"data2"};
struct user_data data3={3,"data3"};
static struct kvlist kv_list;
int get_len(struct kvlist *kv, const void *data)
{
return sizeof(struct user_data);
}
static void dump_kvnode(struct user_data *p)
{
if(!p)
{
printf("data null\n");
return;
}
printf("id=%d\n",p->id);
printf("name=%s\n",p->name);
}
int main()
{
struct user_data *p = NULL;
kvlist_init(&kv_list,get_len);
//set KVs
kvlist_set(&kv_list,data1.name,&data1);
kvlist_set(&kv_list,data2.name,&data2);
kvlist_set(&kv_list,data3.name,&data3);
//get KV by name
p=(struct user_data *)kvlist_get(&kv_list,data1.name);
if(!p)
{
printf("kvlist_get failed!\n");
return -1;
}
dump_kvnode(p);
//iterate over all KVs
char *p_name;
struct user_data *p_value;
kvlist_for_each(&kv_list,p_name,p_value)
{
printf("===================\n");
printf("name=%s\n",p_name);
printf("id=%d\n",p_value->id);
printf("===================\n");
}
//delete kv_list
kvlist_delete(&kv_list,data1.name);
return 0;
}
调试结果
# ./kvlist
===================
name=data1
id=1
===================
===================
name=data2
id=2
===================
===================
name=data3
id=3
===================