Răsfoiți Sursa

feat[mpp_trie]: Add functions for import / export

1. Change MppTrieInfo internal structure.
2. Allow to export / import root, node_count and info_count.
3. Add trie check in import functon.

Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
Change-Id: Id10edbc92db14d045b5bbd15d13ef2472e695037
Herman Chen 5 luni în urmă
părinte
comite
dfc7564693

+ 21 - 8
mpp/base/inc/mpp_trie.h

@@ -39,36 +39,49 @@ typedef void* MppTrie;
  * +---------------+
  * |  MppTrieInfo  |
  * +---------------+
- * |  User context |
- * +---------------+
  * |  name string  |
  * +---------------+
+ * |  User context |
+ * +---------------+
  */
 typedef struct MppTrieInfo_t {
-    const char  *name;
-    void        *ctx;
-    RK_S16      index;
-    RK_S16      str_len;
+    RK_U32      index       : 12;
+    RK_U32      ctx_len     : 12;
+    RK_U32      str_len     : 8;
 } MppTrieInfo;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-MPP_RET mpp_trie_init(MppTrie *trie, RK_S32 info_size);
+MPP_RET mpp_trie_init(MppTrie *trie, const char *name);
 MPP_RET mpp_trie_deinit(MppTrie trie);
 
 /* Add NULL info to mark the last trie entry */
-MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx);
+MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx, RK_U32 ctx_len);
+MPP_RET mpp_trie_import(MppTrie trie, void *root);
 
 RK_S32 mpp_trie_get_node_count(MppTrie trie);
 RK_S32 mpp_trie_get_info_count(MppTrie trie);
 RK_S32 mpp_trie_get_buf_size(MppTrie trie);
+void *mpp_trie_get_node_root(MppTrie trie);
+
+static inline const char *mpp_trie_info_name(MppTrieInfo *info)
+{
+    return (info) ? (const char *)(info + 1) : NULL;
+}
+
+static inline void *mpp_trie_info_ctx(MppTrieInfo *info)
+{
+    return (info) ? (void *)((char *)(info + 1) + info->str_len) : NULL;
+}
 
 /* trie lookup function */
 MppTrieInfo *mpp_trie_get_info(MppTrie trie, const char *name);
 MppTrieInfo *mpp_trie_get_info_first(MppTrie trie);
 MppTrieInfo *mpp_trie_get_info_next(MppTrie trie, MppTrieInfo *info);
+/* root base lookup function */
+MppTrieInfo *mpp_trie_get_info_from_root(void *root, const char *name);
 
 void mpp_trie_dump(MppTrie trie, const char *func);
 #define mpp_trie_dump_f(trie)   mpp_trie_dump(trie, __FUNCTION__)

+ 9 - 9
mpp/base/mpp_dec_cfg.cpp

@@ -84,7 +84,7 @@ public:
             (RK_U32)((long)&(((MppDecCfgSet *)0)->field_change.field_data)), \
             sizeof((((MppDecCfgSet *)0)->field_change.field_data)), \
         }; \
-        mpp_trie_add_info(mTrie, #base":"#name, &tmp); \
+        mpp_trie_add_info(mTrie, #base":"#name, &tmp, sizeof(tmp)); \
     } while (0);
 
 #define ENTRY_TABLE(ENTRY)  \
@@ -118,7 +118,7 @@ public:
 MppDecCfgService::MppDecCfgService() :
     mTrie(NULL)
 {
-    MPP_RET ret = mpp_trie_init(&mTrie, sizeof(MppCfgInfo));
+    MPP_RET ret = mpp_trie_init(&mTrie, "MppDecCfg");
     if (ret) {
         mpp_err_f("failed to init dec cfg set trie\n");
         return ;
@@ -126,7 +126,7 @@ MppDecCfgService::MppDecCfgService() :
 
     ENTRY_TABLE(EXPAND_AS_TRIE)
 
-    mpp_trie_add_info(mTrie, NULL, NULL);
+    mpp_trie_add_info(mTrie, NULL, NULL, 0);
 
     mHead.node_count = mpp_trie_get_node_count(mTrie);
     mHead.info_count = mpp_trie_get_info_count(mTrie);
@@ -224,11 +224,11 @@ MPP_RET mpp_dec_cfg_deinit(MppDecCfg cfg)
         } \
         MppDecCfgImpl *p = (MppDecCfgImpl *)cfg; \
         MppTrieInfo *node = MppDecCfgService::get()->get_info(name); \
-        MppCfgInfo *info = (MppCfgInfo *)(node ? node->ctx : NULL); \
+        MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node); \
         if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
             return MPP_NOK; \
         } \
-        mpp_dec_cfg_dbg_set("name %s type %s\n", node->name, strof_cfg_type(info->data_type)); \
+        mpp_dec_cfg_dbg_set("name %s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type)); \
         MPP_RET ret = MPP_CFG_SET_##cfg_type(info, &p->cfg, val); \
         return ret; \
     }
@@ -249,11 +249,11 @@ DEC_CFG_SET_ACCESS(mpp_dec_cfg_set_st,  void *, St);
         } \
         MppDecCfgImpl *p = (MppDecCfgImpl *)cfg; \
         MppTrieInfo *node = MppDecCfgService::get()->get_info(name); \
-        MppCfgInfo *info = (MppCfgInfo *)(node ? node->ctx : NULL); \
+        MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node); \
         if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
             return MPP_NOK; \
         } \
-        mpp_dec_cfg_dbg_set("name %s type %s\n", node->name, strof_cfg_type(info->data_type)); \
+        mpp_dec_cfg_dbg_set("name %s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type)); \
         MPP_RET ret = MPP_CFG_GET_##cfg_type(info, &p->cfg, val); \
         return ret; \
     }
@@ -276,9 +276,9 @@ void mpp_dec_cfg_show(void)
         MppTrieInfo *node = root;
 
         do {
-            MppCfgInfo *info = (MppCfgInfo *)node->ctx;
+            MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node);
 
-            mpp_log("%-25s type %s\n", node->name, strof_cfg_type(info->data_type));
+            mpp_log("%-25s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type));
 
             node = srv->get_info_next(node);
             if (!node)

+ 9 - 9
mpp/base/mpp_enc_cfg.cpp

@@ -85,7 +85,7 @@ public:
             (RK_U32)((long)&(((MppEncCfgSet *)0)->field_change.field_data)), \
             sizeof((((MppEncCfgSet *)0)->field_change.field_data)), \
         }; \
-        mpp_trie_add_info(mTrie, #base":"#name, &tmp); \
+        mpp_trie_add_info(mTrie, #base":"#name, &tmp, sizeof(tmp)); \
     } while (0);
 
 #define ENTRY_TABLE(ENTRY)  \
@@ -276,7 +276,7 @@ MppEncCfgService::MppEncCfgService() :
 
     mpp_env_get_u32("mpp_enc_cfg_debug", &mpp_enc_cfg_debug, 0);
 
-    ret = mpp_trie_init(&mTrie, sizeof(MppCfgInfo));
+    ret = mpp_trie_init(&mTrie, "MppEncCfg");
     if (ret) {
         mpp_err_f("failed to init enc cfg set trie ret %d\n", ret);
         return ;
@@ -284,7 +284,7 @@ MppEncCfgService::MppEncCfgService() :
 
     ENTRY_TABLE(EXPAND_AS_TRIE)
 
-    mpp_trie_add_info(mTrie, NULL, NULL);
+    mpp_trie_add_info(mTrie, NULL, NULL, 0);
 
     mHead.node_count = mpp_trie_get_node_count(mTrie);
     mHead.info_count = mpp_trie_get_info_count(mTrie);
@@ -390,11 +390,11 @@ MPP_RET mpp_enc_cfg_deinit(MppEncCfg cfg)
         } \
         MppEncCfgImpl *p = (MppEncCfgImpl *)cfg; \
         MppTrieInfo *node = MppEncCfgService::get()->get_info(name); \
-        MppCfgInfo *info = (MppCfgInfo *)(node ? node->ctx : NULL); \
+        MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node); \
         if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
             return MPP_NOK; \
         } \
-        mpp_enc_cfg_dbg_set("name %s type %s\n", node->name, strof_cfg_type(info->data_type)); \
+        mpp_enc_cfg_dbg_set("name %s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type)); \
         MPP_RET ret = MPP_CFG_SET_##cfg_type(info, &p->cfg, val); \
         return ret; \
     }
@@ -415,11 +415,11 @@ ENC_CFG_SET_ACCESS(mpp_enc_cfg_set_st,  void *, St);
         } \
         MppEncCfgImpl *p = (MppEncCfgImpl *)cfg; \
         MppTrieInfo *node = MppEncCfgService::get()->get_info(name); \
-        MppCfgInfo *info = (MppCfgInfo *)(node ? node->ctx : NULL); \
+        MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node); \
         if (CHECK_CFG_INFO(info, name, CFG_FUNC_TYPE_##cfg_type)) { \
             return MPP_NOK; \
         } \
-        mpp_enc_cfg_dbg_set("name %s type %s\n", node->name, strof_cfg_type(info->data_type)); \
+        mpp_enc_cfg_dbg_set("name %s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type)); \
         MPP_RET ret = MPP_CFG_GET_##cfg_type(info, &p->cfg, val); \
         return ret; \
     }
@@ -442,9 +442,9 @@ void mpp_enc_cfg_show(void)
         MppTrieInfo *node = root;
 
         do {
-            MppCfgInfo *info = (MppCfgInfo *)node->ctx;
+            MppCfgInfo *info = (MppCfgInfo *)mpp_trie_info_ctx(node);
 
-            mpp_log("%-25s type %s\n", node->name, strof_cfg_type(info->data_type));
+            mpp_log("%-25s type %s\n", mpp_trie_info_name(node), strof_cfg_type(info->data_type));
 
             node = srv->get_info_next(node);
             if (!node)

+ 222 - 77
mpp/base/mpp_trie.cpp

@@ -34,6 +34,7 @@
 #define MPP_TRIE_DBG_LAST               (0x00000020)
 #define MPP_TRIE_DBG_LAST_STEP          (0x00000040)
 #define MPP_TRIE_DBG_LAST_CHECK         (0x00000080)
+#define MPP_TRIE_DBG_IMPORT             (0x00000100)
 
 #define trie_dbg(flag, fmt, ...)        _mpp_dbg_f(mpp_trie_debug, flag, fmt, ## __VA_ARGS__)
 #define trie_dbg_func(fmt, ...)         trie_dbg(MPP_TRIE_DBG_FUNC, fmt, ## __VA_ARGS__)
@@ -43,6 +44,11 @@
 #define trie_dbg_walk(fmt, ...)         trie_dbg(MPP_TRIE_DBG_WALK, fmt, ## __VA_ARGS__)
 #define trie_dbg_last(fmt, ...)         trie_dbg(MPP_TRIE_DBG_LAST, fmt, ## __VA_ARGS__)
 
+#define MPP_TRIE_KEY_LEN                (4)
+#define MPP_TRIE_KEY_MAX                (1 << (MPP_TRIE_KEY_LEN))
+#define MPP_TRIE_INFO_MAX               (1 << 12)
+#define MPP_TRIE_NAME_MAX               (1 << 12)
+
 #define DEFAULT_NODE_COUNT              900
 #define DEFAULT_INFO_COUNT              80
 #define INVALID_NODE_ID                 (-1)
@@ -75,17 +81,18 @@ typedef struct MppTrieNode_t {
 } MppTrieNode;
 
 typedef struct MppTrieInfoInt_t {
-    RK_S32          ctx_offset;
-    RK_S32          name_offset;
     RK_S32          index;
+    RK_S32          ctx_len;
     RK_S32          str_len;
+    RK_S32          ctx_offset;
+    RK_S32          name_offset;
 } MppTrieInfoInt;
 
 typedef struct MppTrieImpl_t {
-    RK_S32          ctx_size;
+    char            *name;
+    RK_S32          name_len;
     RK_S32          buf_size;
 
-    RK_S32          nodes_size;
     RK_S32          infos_size;
 
     RK_S32          info_count;
@@ -99,6 +106,7 @@ typedef struct MppTrieImpl_t {
     void            *info_buf;
     void            *name_buf;
     RK_S32          info_buf_size;
+    RK_S32          info_buf_pos;
     RK_S32          name_buf_size;
     RK_S32          name_buf_pos;
 } MppTrieImpl;
@@ -143,7 +151,7 @@ static RK_S32 trie_get_node(MppTrieImpl *trie, RK_S32 prev, RK_U64 key)
     return idx;
 }
 
-MPP_RET mpp_trie_init(MppTrie *trie, RK_S32 info_size)
+MPP_RET mpp_trie_init(MppTrie *trie, const char *name)
 {
     if (!trie) {
         mpp_err_f("invalid NULL input trie automation\n");
@@ -152,13 +160,18 @@ MPP_RET mpp_trie_init(MppTrie *trie, RK_S32 info_size)
 
     mpp_env_get_u32("mpp_trie_debug", &mpp_trie_debug, 0);
 
+    RK_S32 name_len = strnlen(name, MPP_TRIE_NAME_MAX) + 1;
     MPP_RET ret = MPP_ERR_NOMEM;
-    MppTrieImpl *p = mpp_calloc(MppTrieImpl, 1);
+    MppTrieImpl *p = mpp_calloc_size(MppTrieImpl, sizeof(MppTrieImpl) + name_len);
     if (!p) {
         mpp_err_f("create trie impl failed\n");
         goto DONE;
     }
 
+    p->name = (char *)(p + 1);
+    p->name_len = name_len;
+    strncpy(p->name, name, name_len);
+
     p->node_count = DEFAULT_NODE_COUNT;
     p->nodes = mpp_calloc(MppTrieNode, p->node_count);
     if (!p->nodes) {
@@ -173,8 +186,7 @@ MPP_RET mpp_trie_init(MppTrie *trie, RK_S32 info_size)
         goto DONE;
     }
 
-    p->ctx_size = info_size;
-    p->info_buf_size = p->ctx_size * p->info_count;
+    p->info_buf_size = SZ_4K;
     p->info_buf = mpp_calloc_size(void, p->info_buf_size);
     if (!p->info_buf) {
         mpp_err_f("failed to alloc %d info buffer\n", p->info_buf_size);
@@ -214,7 +226,9 @@ MPP_RET mpp_trie_deinit(MppTrie trie)
 
     MppTrieImpl *p = (MppTrieImpl *)trie;
 
-    MPP_FREE(p->nodes);
+    if (p->node_count)
+        MPP_FREE(p->nodes);
+
     MPP_FREE(p->info);
     MPP_FREE(p->info_buf);
     MPP_FREE(p->name_buf);
@@ -298,7 +312,7 @@ static MppTrieNode *mpp_trie_get_node(MppTrieNode *root, const char *name)
     return ret;
 }
 
-static RK_S32 mpp_trie_check(MppTrie trie, const char *log)
+static MPP_RET mpp_trie_check(MppTrie trie, const char *log)
 {
     MppTrieImpl *p = (MppTrieImpl *)trie;
     char *buf = (char *)p->name_buf;
@@ -338,6 +352,13 @@ MPP_RET mpp_trie_last_info(MppTrie trie)
         return MPP_ERR_NULL_PTR;
     }
 
+    /* write trie self entry info */
+    pos = p->info_used + 3;
+    mpp_trie_add_info(trie, "__name__", p->name, p->name_len);
+    mpp_trie_add_info(trie, "__info__", &pos, sizeof(pos));
+    /* NOTE: node count need to be update after shrinking */
+    mpp_trie_add_info(trie, "__node__", &p->node_used, sizeof(p->node_used));
+
     root = p->nodes;
     node_count = p->node_used;
     node_valid = node_count;
@@ -463,50 +484,40 @@ MPP_RET mpp_trie_last_info(MppTrie trie)
     trie_dbg_last("create user buffer start\n");
 
     nodes_size = sizeof(MppTrieNode) * p->node_used;
-    p->nodes_size = nodes_size;
-    p->infos_size = (sizeof(MppTrieInfo) + p->ctx_size) * p->info_used;
-
-    pos += nodes_size;
-    /* update info size and string name size */
-    for (i = 0; i < p->info_used; i++) {
-        len = p->info[i].str_len;
-        pos += sizeof(MppTrieInfo) + p->ctx_size + len;
-    }
+    p->buf_size = nodes_size + sizeof(MppTrieInfo) * p->info_used + p->info_buf_pos + p->name_buf_pos;
 
-    len = pos;
-    buf = mpp_calloc_size(char, len);
+    buf = mpp_calloc_size(char, p->buf_size);
     if (!buf) {
         mpp_loge("failed to alloc trie buffer size %d\n", len);
         return MPP_NOK;
     }
 
     p->nodes = (MppTrieNode *)buf;
-    p->buf_size = len;
     memcpy(p->nodes, root, nodes_size);
     pos = nodes_size;
 
     for (i = 0; i < p->info_used; i++) {
-        MppTrieInfo *info;
-        const char *name = (char *)p->name_buf + p->info[i].name_offset;
+        MppTrieInfoInt *src = &p->info[i];
+        MppTrieInfo *dst;
+        const char *name = (char *)p->name_buf + src->name_offset;
 
         node = mpp_trie_get_node(p->nodes, name);
         node->id = pos;
 
         /* reserve node info */
-        info = (MppTrieInfo *)(buf + pos);
-        info->index = p->info[i].index;
-        info->str_len = p->info[i].str_len;
+        dst = (MppTrieInfo *)(buf + pos);
+        dst->index = src->index;
+        dst->ctx_len = src->ctx_len;
+        dst->str_len = src->str_len;
         pos += sizeof(MppTrieInfo);
 
-        /* reserve user context space */
-        info->ctx = (void *)(buf + pos);
-        memcpy(buf + pos, (char *)p->info_buf + p->info[i].ctx_offset, p->ctx_size);
-        pos += p->ctx_size;
-
         /* copy info name */
-        info->name = (char *)(buf + pos);
-        strncpy(buf + pos, name, info->str_len);
-        pos += info->str_len;
+        strncpy(buf + pos, name, dst->str_len);
+        pos += dst->str_len;
+
+        /* reserve user context space */
+        memcpy(buf + pos, (char *)p->info_buf + src->ctx_offset, src->ctx_len);
+        pos += dst->ctx_len;
     }
 
     MPP_FREE(root);
@@ -514,16 +525,26 @@ MPP_RET mpp_trie_last_info(MppTrie trie)
     MPP_FREE(p->info_buf);
     MPP_FREE(p->name_buf);
 
+    /* NOTE: udpate final shrinked node count */
+    {
+        MppTrieInfo *info = mpp_trie_get_info_from_root(p->nodes, "__node__");
+
+        if (info)
+            *(RK_U32 *)mpp_trie_info_ctx(info) = p->node_used;
+    }
+
     return MPP_OK;
 }
 
-MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx)
+MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx, RK_U32 ctx_len)
 {
     MppTrieImpl *p;
     MppTrieInfoInt *info;
     MppTrieNode *node;
     const char *s;
-    RK_S32 act_id;
+    RK_S32 info_buf_pos;
+    RK_S32 name_buf_pos;
+    RK_S32 info_used;
     RK_S32 next;
     RK_S32 len;
     RK_S32 idx;
@@ -539,34 +560,77 @@ MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx)
 
     p = (MppTrieImpl *)trie;
 
-    /* create */
-    if (p->info_used >= p->info_count) {
-        RK_S32 new_count = p->info_count * 2;
+    info_buf_pos = p->info_buf_pos;
+    name_buf_pos = p->name_buf_pos;
+    info_used = p->info_used;
+    len = strnlen(name, MPP_TRIE_NAME_MAX);
+
+    if (len >= MPP_TRIE_NAME_MAX) {
+        mpp_err_f("invalid trie name %s len %d larger than max %d\n",
+                  name, len, MPP_TRIE_NAME_MAX);
+        return MPP_NOK;
+    }
+    if (info_used >= MPP_TRIE_INFO_MAX) {
+        mpp_err_f("invalid trie info count %d larger than max %d\n",
+                  len, MPP_TRIE_INFO_MAX);
+        return MPP_NOK;
+    }
+
+    /* check and enlarge info record buffer */
+    if (info_used >= p->info_count) {
+        rk_s32 old_count = p->info_count;
+        rk_s32 new_count = old_count * 2;
         void *ptr = mpp_realloc_size(p->info, void, sizeof(MppTrieInfoInt) * new_count);
 
         if (!ptr) {
             mpp_err_f("failed to realloc new info %d\n", new_count);
             return MPP_ERR_MALLOC;
         }
-        p->info = (MppTrieInfoInt *)ptr;
+
         trie_dbg_cnt("trie %p enlarge info %p:%d -> %p:%d\n",
-                     trie, p->info, p->info_count, ptr, new_count);
+                     trie, p->info, old_count, ptr, new_count);
 
-        ptr = mpp_realloc_size(p->info_buf, void, p->ctx_size * new_count);
+        p->info = (MppTrieInfoInt *)ptr;
+        p->info_count = new_count;
+    }
+
+    /* check and enlarge contex buffer */
+    if (info_buf_pos + (RK_S32)ctx_len > p->info_buf_size) {
+        rk_s32 old_size = p->info_buf_size;
+        rk_s32 new_size = old_size * 2;
+        void *ptr = mpp_realloc_size(p->info_buf, void, new_size);
         if (!ptr) {
-            mpp_err_f("failed to realloc new info buffer %d\n", new_count);
+            mpp_err_f("failed to realloc new info buffer %d\n", new_size);
             return MPP_ERR_MALLOC;
         }
-        p->info_buf = ptr;
+
         trie_dbg_cnt("trie %p enlarge info_buf %p:%d -> %p:%d\n",
-                     trie, p->info_buf, p->info_count, ptr, new_count);
+                     trie, p->info_buf, old_size, ptr, new_size);
 
-        p->info_count = new_count;
+        p->info_buf = ptr;
+        p->info_buf_size = new_size;
+    }
+
+    /* check and enlarge name string buffer */
+    if (name_buf_pos + len + 1 >= p->name_buf_size) {
+        rk_s32 old_size = p->name_buf_size;
+        rk_s32 new_size = old_size * 2;
+        void *ptr = mpp_realloc_size(p->name_buf, void, new_size);
+
+        if (!ptr) {
+            mpp_err_f("failed to realloc new info buffer %d\n", new_size);
+            return MPP_ERR_MALLOC;
+        }
+
+        trie_dbg_cnt("trie %p enlarge name %p:%d -> %p:%d\n",
+                     trie, p->name_buf, old_size, ptr, new_size);
+
+        p->name_buf = ptr;
+        p->name_buf_size = new_size;
     }
 
     node = NULL;
     s = name;
-    len = strnlen(s, SZ_1K);
     next = 0;
     idx = 0;
 
@@ -616,38 +680,93 @@ MPP_RET mpp_trie_add_info(MppTrie trie, const char *name, void *ctx)
                      trie, s, i, key, key, key0, key1, idx, next);
     }
 
-    act_id = p->info_used++;
-    p->nodes[idx].id = act_id;
+    if (p->nodes[idx].id != -1) {
+        mpp_err_f("trie %p add info %s already exist\n", trie, name);
+        return MPP_NOK;
+    }
 
-    info = &p->info[act_id];
-    info->index = act_id;
-    info->str_len = MPP_ALIGN(len + 1, sizeof(RK_U64));
-    info->ctx_offset = act_id * p->ctx_size;
-    info->name_offset = p->name_buf_pos;
+    p->nodes[idx].id = info_used;
+    p->info_used++;
 
-    memcpy((RK_U8 *)p->info_buf + info->ctx_offset, ctx, p->ctx_size);
+    info = &p->info[info_used];
+    info->index = info_used;
+    info->ctx_len = ctx_len;
+    info->str_len = MPP_ALIGN(len + 1, sizeof(rk_u32));
+    info->ctx_offset = info_buf_pos;
+    info->name_offset = name_buf_pos;
 
-    if (p->name_buf_pos + len + 1 >= p->name_buf_size) {
-        RK_S32 new_size = p->name_buf_size * 2;
-        void *ptr = mpp_realloc(p->name_buf, RK_U8, new_size);
+    memcpy((char *)p->info_buf + info_buf_pos, ctx, ctx_len);
+    p->info_buf_pos += info->ctx_len;
 
-        if (!ptr) {
-            mpp_err_f("failed to realloc new name buffer %d\n", new_size);
-            return MPP_ERR_MALLOC;
-        }
+    snprintf((char *)p->name_buf + p->name_buf_pos,
+             p->name_buf_size - p->name_buf_pos - 1, "%s", name);
+    p->name_buf_pos += info->str_len;
 
-        trie_dbg_cnt("trie %p enlarge name %p:%d -> %p:%d\n",
-                     trie, p->name_buf, p->name_buf_size, ptr, new_size);
+    trie_dbg_set("trie %p add %d info %s at node %d pos %d ctx %p size %d done\n",
+                 trie, i, s, idx, info_used, ctx, ctx_len);
 
-        p->name_buf = ptr;
-        p->name_buf_size = new_size;
+    return MPP_OK;
+}
+
+MPP_RET mpp_trie_import(MppTrie trie, void *root)
+{
+    MppTrieImpl *p = (MppTrieImpl *)trie;
+    MppTrieInfo *info;
+    RK_S32 i;
+
+    if (!p || !root) {
+        mpp_err_f("invalid trie %p root %p\n", trie, root);
+        return MPP_NOK;
     }
 
-    snprintf((char *)p->name_buf + p->name_buf_pos, p->name_buf_size - p->name_buf_pos - 1, "%s", name);
-    p->name_buf_pos += info->str_len;
+    /* free all old buffer */
+    MPP_FREE(p->nodes);
+    MPP_FREE(p->info);
+    MPP_FREE(p->info_buf);
+    MPP_FREE(p->name_buf);
+
+    info = mpp_trie_get_info_from_root(root, "__name__");
+    if (info)
+        p->name = (char *)mpp_trie_info_ctx(info);
+
+    info = mpp_trie_get_info_from_root(root, "__node__");
+    if (info)
+        p->node_used = *(rk_u32 *)mpp_trie_info_ctx(info);
+
+    info = mpp_trie_get_info_from_root(root, "__info__");
+    if (info)
+        p->info_used = *(rk_u32 *)mpp_trie_info_ctx(info);
+
+    /* import and update new buffer */
+    p->nodes = (MppTrieNode *)root;
+
+    /* set count to zero to avoid free on deinit */
+    p->node_count = 0;
+    p->info_count = 0;
+    p->info_buf_size = 0;
+    p->info_buf_pos = 0;
+    p->name_buf_size = 0;
+    p->name_buf_pos = 0;
+
+    if (mpp_trie_debug & MPP_TRIE_DBG_LAST_STEP)
+        mpp_trie_dump(trie, "root import");
 
-    trie_dbg_set("trie %p add %d info %s at node %d pos %d action %p done\n",
-                 trie, i, s, idx, act_id, ctx);
+    info = mpp_trie_get_info_first(trie);
+
+    for (i = 0; i < p->info_used; i++) {
+        const char *name = mpp_trie_info_name(info);
+        MppTrieInfo *info_set = info;
+        MppTrieInfo *info_ret = mpp_trie_get_info(p, name);
+
+        info = mpp_trie_get_info_next(trie, info);
+
+        if (info_ret && info_set == info_ret && info_ret->index == i)
+            continue;
+
+        mpp_loge("trie check on import found mismatch info %s [%d:%p] - [%d:%p]\n",
+                 name, i, info_set, info_ret ? info_ret->index : -1, info_ret);
+        return MPP_NOK;
+    }
 
     return MPP_OK;
 }
@@ -673,6 +792,13 @@ RK_S32 mpp_trie_get_buf_size(MppTrie trie)
     return (p) ? p->buf_size : 0;
 }
 
+void *mpp_trie_get_node_root(MppTrie trie)
+{
+    MppTrieImpl *p = (MppTrieImpl *)trie;
+
+    return (p) ? p->nodes : NULL;
+}
+
 MppTrieInfo *mpp_trie_get_info(MppTrie trie, const char *name)
 {
     MppTrieImpl *p = (MppTrieImpl *)trie;
@@ -687,14 +813,14 @@ MppTrieInfo *mpp_trie_get_info(MppTrie trie, const char *name)
     if (!node || node->id < 0)
         return NULL;
 
-    return (MppTrieInfo *)(((RK_U8 *)p->nodes) + node->id);
+    return (MppTrieInfo *)(((char *)p->nodes) + node->id);
 }
 
 MppTrieInfo *mpp_trie_get_info_first(MppTrie trie)
 {
     MppTrieImpl *p = (MppTrieImpl *)trie;
 
-    return (p) ? (MppTrieInfo *)(((RK_U8 *)p->nodes) + p->node_used * sizeof(MppTrieNode)) : NULL;
+    return (p) ? (MppTrieInfo *)(((char *)p->nodes) + p->node_used * sizeof(MppTrieNode)) : NULL;
 }
 
 MppTrieInfo *mpp_trie_get_info_next(MppTrie trie, MppTrieInfo *info)
@@ -704,7 +830,23 @@ MppTrieInfo *mpp_trie_get_info_next(MppTrie trie, MppTrieInfo *info)
     if (!p || !info || info->index >= p->info_used - 1)
         return NULL;
 
-    return (MppTrieInfo *)(info->name + info->str_len);
+    return (MppTrieInfo *)((char *)(info + 1) + info->str_len + info->ctx_len);
+}
+
+MppTrieInfo *mpp_trie_get_info_from_root(void *root, const char *name)
+{
+    MppTrieNode *node;
+
+    if (!root || !name) {
+        mpp_loge_f("invalid root %p name %p\n", root, name);
+        return NULL;
+    }
+
+    node = mpp_trie_get_node((MppTrieNode *)root, name);
+    if (!node || node->id < 0)
+        return NULL;
+
+    return (MppTrieInfo *)(((char *)root) + node->id);
 }
 
 void mpp_trie_dump(MppTrie trie, const char *func)
@@ -717,7 +859,9 @@ void mpp_trie_dump(MppTrie trie, const char *func)
     memset(next_cnt, 0, sizeof(next_cnt));
     memset(tag_len, 0, sizeof(tag_len));
 
-    mpp_logi("%s dumping node count %d used %d\n", func, p->node_count, p->node_used);
+    mpp_logi("%s dumping trie %p\n", func, trie);
+    mpp_logi("name %s size %d node %d info %d\n",
+             p->name, p->buf_size, p->node_used, p->info_used);
 
     for (i = 0; i < p->node_used; i++) {
         MppTrieNode *node = &p->nodes[i];
@@ -731,10 +875,11 @@ void mpp_trie_dump(MppTrie trie, const char *func)
             /* check before and after last info */
             if (node->id < (RK_S32)(p->node_used * sizeof(MppTrieNode)))
                 mpp_logi("node %d key %x info %d - %s\n", node->idx, node->key, node->id,
-                         (char *)p->name_buf + p->info[node->id].name_offset);
+                         p->name_buf ? ((char *)p->name_buf + p->info[node->id].name_offset) :
+                         mpp_trie_info_name(((MppTrieInfo *)((char *)p->nodes + node->id))));
             else
                 mpp_logi("node %d key %x info %d - %s\n", node->idx, node->key, node->id,
-                         ((MppTrieInfo *)((char *)p->nodes + node->id))->name);
+                         mpp_trie_info_name(((MppTrieInfo *)((char *)p->nodes + node->id))));
         } else
             mpp_logi("node %d key %x\n", node->idx, node->key);
 

+ 5 - 5
mpp/base/test/mpp_trie_test.c

@@ -77,15 +77,15 @@ int main()
 
     mpp_log("mpp_trie_test start\n");
 
-    mpp_trie_init(&trie, sizeof(TestAction));
+    mpp_trie_init(&trie, "test_trie");
 
     start = mpp_time();
     for (i = 0; i < info_cnt; i++)
-        mpp_trie_add_info(trie, test_info[i].name, &test_info[i]);
+        mpp_trie_add_info(trie, test_info[i].name, &test_info[i], sizeof(test_info[i]));
     end = mpp_time();
     mpp_log("add act time %lld us\n", end - start);
 
-    ret = mpp_trie_add_info(trie, NULL, NULL);
+    ret = mpp_trie_add_info(trie, NULL, NULL, 0);
     if (ret) {
         mpp_loge("mpp_trie_add_info last failed\n");
         goto DONE;
@@ -100,8 +100,8 @@ int main()
         info = mpp_trie_get_info(trie, name);
         end = mpp_time();
 
-        if (info && info->ctx)
-            act = (TestAction *)info->ctx;
+        if (info)
+            act = (TestAction *)mpp_trie_info_ctx(info);
 
         if (act && act->proc)
             act->proc(act->ctx, end - start);

+ 4 - 4
utils/mpp_opt.c

@@ -62,7 +62,7 @@ MPP_RET mpp_opt_setup(MppOpt opt, void *ctx)
     if (NULL == impl)
         return MPP_NOK;
 
-    mpp_trie_init(&impl->trie, sizeof(MppOptInfo));
+    mpp_trie_init(&impl->trie, "mpp_opt");
     if (impl->trie) {
         impl->ctx = ctx;
         return MPP_OK;
@@ -79,9 +79,9 @@ MPP_RET mpp_opt_add(MppOpt opt, MppOptInfo *info)
         return MPP_NOK;
 
     if (NULL == info)
-        return mpp_trie_add_info(impl->trie, NULL, NULL);
+        return mpp_trie_add_info(impl->trie, NULL, NULL, 0);
 
-    return mpp_trie_add_info(impl->trie, info->name, info);
+    return mpp_trie_add_info(impl->trie, info->name, info, sizeof(*info));
 }
 
 MPP_RET mpp_opt_parse(MppOpt opt, int argc, char **argv)
@@ -113,7 +113,7 @@ MPP_RET mpp_opt_parse(MppOpt opt, int argc, char **argv)
                 continue;
             }
 
-            info = node->ctx;
+            info = mpp_trie_info_ctx(node);
             if (info->proc)
                 step = info->proc(impl->ctx, next);