singe/thirdparty/rockchip-mpp/mpp/base/inc/mpp_trie.h
2026-09-10 20:17:28 -05:00

185 lines
6 KiB
C

/* SPDX-License-Identifier: Apache-2.0 OR MIT */
/*
* Copyright (c) 2024 Rockchip Electronics Co., Ltd.
*/
#ifndef MPP_TRIE_H
#define MPP_TRIE_H
#include <string.h>
#include "mpp_internal.h"
#define MPP_TRIE_KEY_LEN (4)
#define MPP_TRIE_KEY_MAX (1 << (MPP_TRIE_KEY_LEN))
/*
* MppTrie node buffer layout
* +---------------+
* | MppTrieImpl |
* +---------------+
* | MppTrieNodes |
* +---------------+
* | MppTrieInfos |
* +---------------+
*
* MppTrieInfo element layout
* +---------------+
* | MppTrieInfo |
* +---------------+
* | name string |
* +---------------+
* | User context |
* +---------------+
*/
typedef struct MppTrieInfo_t {
rk_u32 index : 12;
rk_u32 ctx_len : 12;
rk_u32 str_len : 8;
} MppTrieInfo;
/*
* MppTrieResult - result type from layered walk / resolve
*
* Provides clear semantics: negative - error, 0 - leaf, 1 - subroot.
*/
#define MPP_TRIE_LEAF 0 /* normal leaf node found */
#define MPP_TRIE_SUBROOT 1 /* subtree root (array), need continue */
/*
* MppTrieStatus - segment-based pave / walk status for add / get_entry
*
* Segment registration, segment retrieval:
* get_entry returns at the first subroot boundary, caller accumulates
* the entry chain and continues from name + name_pos for next segment.
*/
typedef struct MppTrieStatus_t {
/*
* [in] starting node index
* 0 - trie root
* non-zero - subtree root index
*/
rk_s32 root_idx;
/*
* [out] current node index (valid when return >= 0)
*/
rk_s32 node_idx;
/*
* [out] parsed digit value on array pattern
* negative - not parsed
* >= zero - parsed digit value
*/
rk_s32 array_idx;
/*
* [out] consumed position in name string
* SUBROOT - offset of next segment start for continued retrieval
* LEAF - strlen(name), entire path consumed
*/
rk_s32 name_pos;
} MppTrieStatus;
#ifdef __cplusplus
extern "C" {
#endif
rk_s32 mpp_trie_init(MppTrie *trie, const char *name);
rk_s32 mpp_trie_init_by_root(MppTrie *trie, void *root);
rk_s32 mpp_trie_deinit(MppTrie trie);
/* Add NULL info to mark the last trie entry */
rk_s32 mpp_trie_add_info(MppTrie trie, const char *name, void *ctx, rk_u32 ctx_len);
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);
rk_s32 mpp_trie_get_name_max(MppTrie trie);
const char *mpp_trie_get_name(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;
}
static inline rk_s32 mpp_trie_info_is_self(MppTrieInfo *info)
{
return (info) ? (strstr((const char *)(info + 1), "__") != NULL ? 1 : 0) : 0;
}
static inline rk_s32 mpp_trie_info_name_is_self(const char *name)
{
return (name) ? (strstr(name, "__") != NULL ? 1 : 0) : 0;
}
/* 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);
/*
* Segment-based registration, segment retrieval
*
* mpp_trie_add_entry - register one text segment from st->root_idx.
* ENTRY_TYPE_VLA_INFO -> subroot node (count from entry->vla.elem_count)
* other entry types -> leaf node
* Children are paved directly under the subroot node (no ':' separator).
*
* mpp_trie_get_entry - segment retrieval with full path "mid:0:inner:1:value".
* trie_split_path splits by ':digits' boundaries into segments.
* Returns at first subroot boundary, st.name_pos indicates next segment start.
* Caller sets st.root_idx = st.node_idx, calls again with name + name_pos.
*
* Example:
* add_entry(trie, &st, "mid", &vla_entry); st.root_idx = st.node_idx;
* add_entry(trie, &st, "inner", &vla_entry); st.root_idx = st.node_idx;
* add_entry(trie, &st, "value", &leaf_entry);
*
* // segment retrieval loop
* const char *p = "mid:0:inner:1:value";
* get_entry(trie, &st, p, &e); // SUBROOT, st.name_pos = 5
* st.root_idx = st.node_idx; p += st.name_pos; // p -> "inner:1:value"
* get_entry(trie, &st, p, &e); // SUBROOT, st.name_pos = 8
* st.root_idx = st.node_idx; p += st.name_pos; // p -> "value"
* get_entry(trie, &st, p, &e); // LEAF
*/
rk_s32 mpp_trie_add_entry(MppTrie trie, MppTrieStatus *st, const char *name, KmppEntry *entry);
rk_s32 mpp_trie_get_entry(MppTrie trie, MppTrieStatus *st, const char *name, KmppEntry *entry);
/*
* mpp_trie_for_each_entry - iterate every node carrying an info payload.
*
* The callback receives:
* name - info name string (single segment for subroot children,
* full colon-path for top-level / struct fields)
* info - pointer to the info's context data (mpp_trie_info_ctx).
* Typed as void* since the payload type is caller-defined
* (KmppEntry for objdef fields, but other types for self-info).
* subroot - node index of the nearest sub_root ancestor, or 0 if none.
* A non-zero value means this entry lives under a VLA/array
* subroot; zero means it is a top-level or struct field
* addressable by its full path from the trie root.
* ctx - opaque caller context.
*
* Returning non-zero from the callback aborts the iteration.
* Self-describing info nodes (names starting with "__") are skipped.
*/
typedef rk_s32 (*MppTrieInfoCb)(const char *name, void *info, rk_s32 subroot, void *ctx);
rk_s32 mpp_trie_for_each_entry(MppTrie trie, MppTrieInfoCb cb, void *ctx);
void mpp_trie_dump(MppTrie trie, const char *func);
#define mpp_trie_dump_f(trie) mpp_trie_dump(trie, __FUNCTION__)
void mpp_trie_timing_test(MppTrie trie);
#ifdef __cplusplus
}
#endif
#endif /* MPP_TRIE_H */