| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- #ifndef TREE_LIST_H
- #define TREE_LIST_H
- #include <stdbool.h> // bool
- #include <string.h> // NULL
- // Tree List of nodes
- // Sychov A., 13/08/2019
- // Allows to organize your data into the tree-like list and
- // ... attach some data to each node.
- // @TREE_LIST_DEEP_ENABLE
- // Enable deep search in tree-list using "default" nodes.
- // If user marks the node as default, the search continues inside it
- // even if no specfied node found during flat search. Each default node
- // can contain either normal and default nodes, that can be used in
- // recursive search. The depth of recursive search can be limited by
- // user using @TREE_LIST_RECURSIVE_LIMIT_ENABLE macro
- #define TREE_LIST_DEEP_ENABLE 1
- // @TREE_LIST_RECURSIVE_LIMIT_ENABLE
- // Only used if @TREE_LIST_DEEP_ENABLE is enabled
- // Limits the maximum recursive depth during deep search.
- // User defines it's own procedure to allow/disallow enter each
- // next recurisve level of search. See @fTreeListSearchDeepRecursiveLimiter_t
- #define TREE_LIST_RECURSIVE_LIMIT_ENABLE 1
- // @TREE_LIST_DEEP_PARENT_SEARCH_ENABLE
- // Only used if @TREE_LIST_DEEP_ENABLE is enabled
- // Enable feature of searching for the parent of found node during
- // deep search. See @fTreeListSearchDeepResultNotify_t
- #define TREE_LIST_DEEP_PARENT_SEARCH_ENABLE 1
- union sTreeList_t;
- typedef union sTreeList_t
- {
- struct {
- void * key;
- union sTreeList_t * list;
- void * ctx;
- };
- struct {
- const void * c_key;
- const union sTreeList_t * c_list;
- const void * c_ctx;
- };
- }
- sTreeList_t;
-
- // @DECLARE_TREE_LIST_NODE
- // Declares simple node: it contains only child nodes.
- #define DECLARE_TREE_LIST_NODE( nodekey_, nodechilds_ )\
- { .key = nodekey_, .list = nodechilds_, .ctx = NULL }
- // @DECLARE_TREE_LIST_CNODE
- // Declares simple constant node: it contains only child nodes.
- #define DECLARE_TREE_LIST_CNODE( nodekey_, nodechilds_ )\
- { .c_key = nodekey_, .c_list = nodechilds_, .c_ctx = NULL }
- // @DECLARE_TREE_LIST_NODE_EX
- // Declares extended node: it contains either context and child nodes.
- #define DECLARE_TREE_LIST_NODE_EX( nodekey_, nodechilds_, nodectx_ )\
- { .key = nodekey_, .list = nodechilds_, .ctx = nodectx_ }
- // @DECLARE_TREE_LIST_CNODE_EX
- // Declares extended constant node: it contains either context and child nodes.
- #define DECLARE_TREE_LIST_CNODE_EX( nodekey_, nodechilds_, nodectx_ )\
- { .c_key = nodekey_, .c_list = nodechilds_, .c_ctx = nodectx_ }
- // @DECLARE_TREE_LIST_LEAF
- // Declares a tree leaf: leaf does not contain any nodes.
- #define DECLARE_TREE_LIST_LEAF( nodekey_, nodectx_ )\
- { .key = nodekey_, .list = NULL, .ctx = nodectx_ }
- // @DECLARE_TREE_LIST_CLEAF
- // Declares a tree constant leaf: leaf does not contain any nodes.
- #define DECLARE_TREE_LIST_CLEAF( nodekey_, nodectx_ )\
- { .c_key = nodekey_, .c_list = NULL, .c_ctx = nodectx_ }
- // @DECLARE_TREE_LIST_LAST
- // Declares the end of sibling list
- // Each list of tree-list nodes shall contain this element in the end.
- #define DECLARE_TREE_LIST_LAST()\
- { .c_key = NULL, .c_list = NULL, .c_ctx = NULL }
- // @fTreeListComparer_t
- // Tree-list compare function prototype.
- // The function shall be able to compare a couple of keys for equality.
- // This interface is used in @tree_list_search to compare two nodes,
- // ... where @key_a is a node's key, and @key_b is a @search_key argument.
- // Returns: true if equal, false otherwise
- typedef bool ( * fTreeListComparer_t )( const void * key_a, const void * key_b );
- #if TREE_LIST_DEEP_ENABLE
- // @fTreeListNextKey_t
- // Tree-list abstract function to get next key to search.
- // @ctx - abstract context pointer, is passed to used-defined function in used-dependent format;
- // Returns:
- // NON NULL: a search key to be used as @search_key parameter in @tree_list_search;
- // NULL: terminate the search (end of command is reached)
- typedef const void * ( * fTreeListNextKey )( void * ctx );
- #endif
- #if TREE_LIST_DEEP_ENABLE
- // @fTreeListForEach_t
- // Tree-list abstract function prototype.
- // Used in @tree_list_foreach function as an user function callback
- // @node - current node;
- // @ctx - user dependent context;
- // Returns: true - continue walking; false - terminate walking;
- typedef bool ( * fTreeListForEach_t )( const sTreeList_t * node, void * ctx );
- #endif
- #if TREE_LIST_DEEP_ENABLE
- // @fTreeListForEach_t
- // Tree-list abstraction function prototype.
- // Checks if the specified node can be considered as default node.
- // @node - node to check;
- // @ctx - optional user dependent context, can be NULL;
- // Returns:
- // - true: the specified @node is the default node;
- // - false: the specified @node is not the default node;
- typedef bool ( * fTreeListIsDefault_t )( const sTreeList_t * node, void * ctx );
- #endif
- #if TREE_LIST_DEEP_ENABLE
- // @tree_list_foreach
- // Tree-List iteration function
- // Walks the specified node seaching for derived nodes. Each node found is passed to the specified
- // by user function @fcall with the specified user dependent context @ctx
- // Function walks the current node while @fcall returns 'true', and returns current node immediately as
- // far as @fcall returns 'false'. The function returns NULL if @fcall never returns 'false'.
- // @ref_node - the tree node to walk in;
- // @fcall - user defined function callback;
- // @ctx - user defined function context;
- // Returns: tree-list node in case @fcall have returned 'false', or NULL otherwise.
- const sTreeList_t * tree_list_foreach( const sTreeList_t * ref_node, fTreeListForEach_t fcall, void * ctx );
- #endif
- // @tree_list_search
- // Search in the tree list @in for the node specified by @key using
- // ... the compare function @fcmp.
- // @in - the tree list to search in, shall not be NULL;
- // @search_key - the node key to search for, shall not be NULL;
- // @fcmp - nodes comparator, shall not be NULL;
- // @def_node - the default node to be returned if no node found by @search_key, can be NULL;
- // Returns: the node pointer if found, @def_node otherwise.
- // Note: The list @in shall be terminated by DECLARE_TREE_LIST_LAST() element.
- const sTreeList_t * tree_list_search( const sTreeList_t * in,
- const void * search_key,
- fTreeListComparer_t fcmp,
- const sTreeList_t * def_node );
- #if TREE_LIST_DEEP_ENABLE
- #if TREE_LIST_RECURSIVE_LIMIT_ENABLE
- // @fTreeListSearchDeepRecursiveLimiter_t
- // Tree-list abstraction function prototype.
- // Limits the depth of recursive searching in @tree_list_search_deep.
- // Is called by each call @tree_list_search_deep to count calls;
- // User must implement user-dependent way to count recursive calls
- // using @dir and @ctx parameters;
- // @dir - direction: true - enter recursive call, false - leave call;
- // @ctx - mandatory user dependent context.
- // Returns, if @dir is 'true':
- // - true: recursive call is possible;
- // - false: recursive call is impossible;
- // Returns, if @dir is 'false': does not matter;
- // Note: direct calls of @tree_list_search_deep never use this function,
- // only recursive calls can be limited by this function; so, this function can return 'false'
- // forever to limit all recursive calls (call depth > 1) and allow direct calls.
- typedef bool ( * fTreeListSearchDeepRecursiveLimiter_t )( bool dir, void * ctx );
- #endif
- #endif
- #if TREE_LIST_DEEP_ENABLE
- #if TREE_LIST_DEEP_PARENT_SEARCH_ENABLE
- // @fTreeListSearchDeepResultNotify_t
- // Tree-list abstraction function prototype.
- // Defines user-dependent funtion callback protype used to notify the user
- // after successful search and pass the search results. User can agree and accept the result,
- // or disagree and continue searching for the next result.
- // Parameters:
- // @found - the search result (found node), not NULL;
- // @parent - the found node parent node, not NULL;
- // @user_ctx - user dependent context passed to @tree_list_search_deep in @user_ctx argument
- // Returns: the result acception: 'true' to agree and terminate searching and 'false' to disagree
- // and continue searching.
- // Note: the function is not being invoked if no result found.
- typedef bool ( * fTreeListSearchDeepResultNotify_t )( const sTreeList_t * found,
- const sTreeList_t * parent,
- void * user_ctx );
- #endif
- #endif
- #if TREE_LIST_DEEP_ENABLE
- // @sTreeListSearchDeep_FSet_t
- // Functional set for @tree_list_search
- typedef struct
- {
- fTreeListNextKey fnext; // next key getter, mandatory, can not be NULL
- fTreeListComparer_t fcmp; // node comparer, mandatory, can not be NULL
- fTreeListIsDefault_t fisdef; // default node detector, optional, can be NULL
- #if TREE_LIST_RECURSIVE_LIMIT_ENABLE
- fTreeListSearchDeepRecursiveLimiter_t freclim; // recursive call limiter, optional, can be NULL
- #endif
- #if TREE_LIST_DEEP_PARENT_SEARCH_ENABLE
- fTreeListSearchDeepResultNotify_t fagree; // result notification/agreeing, optional, can be NULL
- #endif
- }
- sTreeListSearchDeep_FSet_t;
- #endif
- #if TREE_LIST_DEEP_ENABLE
- // @tree_list_search_deep_int
- // Extended search for a key chain in the tree-list.
- // @ref_node - base node, root, the node to start search from;
- // @fs - functional set, see @sTreeListSearchDeep_FSet_t:
- // - fnext: user-defined abstract routine to retrieve next key in the chain;
- // - fcmp: user-defined abstract predicate to compare nodes;
- // - fisdef: user-defined predicate to determine if the node is the "default" node;
- // - freclim: user-defined abstract routine to limit recursive calls, see @fTreeListSearchDeepRecursiveLimiter_t;
- // @user_ctx - user-dependent context, will be passed to routines in functional set @fs;
- // Returns:
- // NON NULL: found node;
- // NULL: node not found;
- const sTreeList_t * tree_list_search_deep( const sTreeList_t * ref_node,
- const sTreeListSearchDeep_FSet_t * fs,
- void * user_ctx );
- #endif
- #endif
|