this is `Funnel\_Three.h` :
```
#pragma once

#include 
#include 
#include "cJSON.h"
#include "Funnel.h"

#define FUNNEL\_TREE\_HASH\_ZERO 0x00000000
#define FUNNEL\_TREE\_HASH\_ERROR 0x00000FFF

typedef struct funnel\_tree\_s {
 funnel\_tree\_t \*parent; /\*\*< always points to logical parent \*/
 funnel\_tree\_t \*child; /\*\*< points to first child of this node \*/
 funnel\_tree\_t \*prev; /\*\*< points to previous sibling \*/
 funnel\_tree\_t \*next; /\*\*< points to next sibling \*/
 char \*name; /\*\*< last token of topic, if null, hex `key` is used \*/
 uint64\_t key; /\*\*< BeauDB key \*/
 uint32\_t subtree\_hash; /\*\*< hash for this node (includes children) ("\_") \*/
 uint32\_t local\_hash; /\*\*< hash of data local to this node ("\_\_") \*/
 request\_handler\_t handler;
 void \*data;
 uint16\_t data\_type;
 bool hidden; /\*\*< dont enumerate this node when querying parent \*/
 bool allow\_unauthenticated;
} funnel\_tree\_t;

/\*\*
 \* initialize the funnel tree before use
 \*/
void Funnel\_Tree\_Init();

/\*\*
 \* free the whole funnel tree
 \* @warning funnel tree functions unusable after this point!
 \*/
void Funnel\_Tree\_Deinit();

/\*\*
 \* recompute hashes for specified node,
 \* and apply recursively to parent nodes
 \* @param ft node to rehash
 \*/
bool Funnel\_Tree\_Rehash(funnel\_tree\_t \* ft);

/\*\*
 \* recompute hashes for specified node,
 \* but do not update parents
 \* @param ft node to rehash
 \*/
bool Funnel\_Tree\_Rehash\_NoParents(funnel\_tree\_t \* ft);

/\*\*
 \* allow unauthenticated access to this endpoint, and all parent endpoints
 \* @note Used for HTTP / BLE
 \* @return true if the node exists and parents are sucessfully tagged
 \*/
bool Funnel\_Tree\_Allow\_Unauthenticated(funnel\_tree\_t \* ft);

/\*\*
 \* return root node of topic tree
 \* @return always valid
 \*/
funnel\_tree\_t \*Funnel\_Tree\_Get\_Root();

/\*\*
 \* find child of specified node by name or key
 \* @param ft node
 \* @param name name or hex key of desired child (NULL to only use key search)
 \* @param key key of desired child (only used if name is NULL)
 \* @return child, or NULL if not found
 \*/
funnel\_tree\_t \*Funnel\_Tree\_Get\_Child(funnel\_tree\_t \* ft,
 const char \*name, uint64\_t key);

/\*\*
 \* get node given a topic string
 \* @param topic cstring
 \* @return node, or NULL if none found
 \*/
funnel\_tree\_t \*Funnel\_Tree\_Get\_By\_Topic(const char \*topic);

/\*\*
 \* remove a child by name or key from speciied parent
 \* @param child child node to detach and free
 \* @note Cannot be used on root node.
 \* @return [description]
 \*/
bool Funnel\_Tree\_Delete\_Child(funnel\_tree\_t \* child);

/\*\*
 \* add a child node to existing parent
 \* @param parent node to which to attach child
 \* @param name (optional) static name of topic
 \* @param handler function for handling requests on this topic
 \* @return the new child node, or NULL on error
 \*/
funnel\_tree\_t \*Funnel\_Tree\_Add\_Child(funnel\_tree\_t \* parent,
 const char \*name,
 request\_handler\_t handler);
/\*\*
 \* build a path to a node, creating new nodes with NULL handlers
 \* for each nonexistent part of the path, and assign the given handler
 \* to the leaf node of the path.
 \* @param path the topic path (from root), in typical slash-separated form
 \* e.g. "sys/debug/leds"
 \* @param handler function for handling requests on the leaf topic
 \* @return the (new) leaf node, or NULL on error
 \* @note This function will fail if it attempts to overwrite a handler
 \* (overwriting a NULL handler is permitted)
 \*/
funnel\_tree\_t \* Funnel\_Tree\_Add\_By\_Topic(
 const char \* path,
 request\_handler\_t handler
);

/\*\*
 \* associate data with this node
 \* @param ft
 \* @param data argument for use by handler
 \* @param data\_type BEAU\_TYPE\_x of data, or 0 if not applicable
 \*/
void Funnel\_Tree\_Add\_Data(funnel\_tree\_t \* ft,
 void \*data, uint16\_t data\_type);
/\*\*
 \* return pointer to name of node
 \* @detail If ft->name is present, then that name is used.
 \* Otherwise, we generate a hex string of ft->key
 \* and return that.
 \* @param ft node
 \* @param buf output buffer (not always used)
 \* @param buf\_size maximum size of buffer (must be at least 12)
 \* @return valid name (never returns NULL)
 \*/
const char \*Funnel\_Tree\_Get\_Name(funnel\_tree\_t \* ft, char \*buf,
 uint32\_t buf\_size);

/\*\*
 \* add node hash to existing object
 \* @param ft node to hash
 \* @param obj object to add hash entry to
 \* @param include\_local\_hash true will also add "\_\_" local\_hash
 \* @return true on success
 \*/
bool Funnel\_Tree\_Add\_Hash\_To\_Object(funnel\_tree\_t \* ft, cJSON \* obj, bool include\_local\_hash);

/\*\*
 \* returns a new JSON object containing the node's hash
 \* @param ft node
 \* @return cJSON object (newly-allocated)
 \*/
cJSON \*Funnel\_Tree\_Create\_Hash\_Object(funnel\_tree\_t \* ft);

/\*\*
 \* print debug information about a node
 \* @param ft
 \*/
void Funnel\_Tree\_Print(funnel\_tree\_t \* ft);

/\*\*
 \* print debug information about a whole tree
 \* @param ft
 \*/
void Funnel\_Tree\_Print\_Walk(funnel\_tree\_t \* ft);

/\*\*
 \* Generates a random key for a node
 \* @return a random 32-bit key with the high bit not set
 \* @note high bit never set for random keys to avoid conflict
 \* with fixed Beau keys
 \*\*/
uint64\_t Funnel\_Tree\_Random\_Key ();

/\*\*
 \* get a cJSON array of strings listing names of children of ft
 \* return value owned by caller
 \* @param ft
 \* @return NULL on error
 \*/
cJSON \* Funnel\_Tree\_Get\_Children\_List(funnel\_tree\_t \* ft);
```
이것은 `Funnel\_Three.h` 입니다:```#프래그마 한 번#include #포함 #include "cJSON.h"#include "Funnel.h"#define FUNNEL\_TREE\_HASH\_ZERO 0x00000000#define FUNNEL\_TREE\_HASH\_ERROR 0x00000FFFtypedef struct funnel\_tree\_s { FUNNEL\_TREE\_T \*부모; /\*\*< 항상 논리적 부모 \*/를 가리킴 funnel\_tree\_t \*child; /\*\*< 이 노드의 첫 번째 자식을 가리킴 \*/ funnel\_tree\_t \*prev; /\*\*< 이전 형제자매를 가리킴 \*/ funnel\_tree\_t \*next; /\*\*< 다음 형제자매를 가리킴 \*/ char \*name; /\*\*< 토픽의 마지막 토큰, null이면 헥스 `key`가 사용됨 \*/ uint64\_t key; /\*\*< BeauDB 키 \*/ uint32\_t subtree\_hash; /\*\*< 이 노드(자식 포함)의 해시 ("\_") \*/ uint32\_t local\_hash; /\*\*< 이 노드에 로컬한 데이터의 해시 ("\_\_") \*/ 요청\_핸들러\_t 핸들러; void \*data; UINT16\_t 데이터\_type; bool hidden; /\*\*< 부모를 쿼리할 때 이 노드를 열거하지 않음 \*/ bool allow\_unauthenticated;} funnel\_tree\_t;/\*\* \* 사용하기 전에 퍼널 트리 초기화 \*/void Funnel\_Tree\_Init();/\*\* \* 전체 퍼널 트리를 해제합니다 \* @경고 이 시점 이후에는 퍼널 트리 기능을 사용할 수 없습니다! \*/void Funnel\_Tree\_Deinit();/\*\* \* 지정된 노드에 대한 해시를 다시 계산합니다, \* 그리고 부모 노드에 재귀적으로 적용합니다. \* @param ft 재해시할 노드 \*/bool Funnel\_Tree\_Rehash(funnel\_tree\_t \* ft);/\*\* \* 지정된 노드에 대한 해시를 다시 계산합니다, \* 하지만 부모 노드는 업데이트하지 않습니다. \* @param ft 리해시할 노드 \*/bool Funnel\_Tree\_Rehash\_NoParents(funnel\_tree\_t \* ft);/\*\* \* 이 엔드포인트와 모든 부모 엔드포인트에 대한 인증되지 않은 액세스를 허용합니다. \* @주 HTTP/BLE에 사용됨 노드가 존재하고 부모가 성공적으로 태그된 경우 \* @리턴 참을 반환합니다. \*/bool 퍼널\_트리\_허용\_미인증(퍼널\_트리\_t \* ft);/\*\* \* 토픽 트리의 루트 노드 반환 \* @리턴 항상 유효 \*/funnel\_tree\_t \*Funnel\_Tree\_Get\_Root();/\*\* \* 이름 또는 키로 지정된 노드의 자식 찾기 \* @param ft 노드 \* @param name 원하는 자식의 이름 또는 16진수 키 (키 검색만 사용하려면 NULL) \* @param 키 원하는 자식의 키 (이름이 NULL인 경우에만 사용) \* @리턴 자식, 또는 찾을 수 없는 경우 NULL \*/funnel\_tree\_t \*Funnel\_Tree\_Get\_Child(funnel\_tree\_t \* ft, const char \*이름, uint64\_t 키);/\*\* \* 토픽 문자열이 주어진 노드를 가져옵니다. \* @param topic cstring \* @리턴 노드, 또는 찾을 수 없는 경우 NULL \*/funnel\_tree\_t \*Funnel\_Tree\_Get\_By\_Topic(const char \*topic);/\*\* \* 지정된 부모에서 이름 또는 키로 자식을 제거합니다. \* @param 분리하고 해제할 자식 자식 노드 \* @note 루트 노드에서는 사용할 수 없습니다. \* @return [설명] \*/bool Funnel\_Tree\_Delete\_Child(funnel\_tree\_t \* child);/\*\* \* 기존 부모에 자식 노드 추가 \* @param 자식을 연결할 부모 노드 \* @param name (선택 사항) 토픽의 정적 이름 \* 이 토픽에 대한 요청을 처리하기 위한 @param 핸들러 함수 \* @새 자식 노드를 반환하거나 오류시 NULL을 반환합니다. \*/funnel\_tree\_t \*Funnel\_Tree\_Add\_Child(funnel\_tree\_t \* parent, const char \*name, 요청\_핸들러\_t 핸들러);/\*\* \* 노드에 대한 경로를 구축하여 NULL 핸들러로 새 노드를 생성합니다. \* 경로의 존재하지 않는 각 부분에 대해 주어진 핸들러를 할당합니다. \* 경로의 리프 노드에 할당합니다. \* param 경로 일반적인 슬래시로 구분된 형식의 토픽 경로(루트에서) \* 예: "sys/debug/leds" \* 리프 토픽에 대한 요청을 처리하기 위한 @param 핸들러 함수 \* (새) 리프 노드를 반환하거나 오류 시 NULL을 반환합니다. \* @주 이 함수는 핸들러를 덮어쓰려고 시도하면 실패합니다. \* (NULL 핸들러 덮어쓰기는 허용됩니다) \*/funnel\_tree\_t \* Funnel\_Tree\_Add\_By\_Topic( const char \* path, 요청\_핸들러\_t 핸들러);/\*\* \* 데이터를 이 노드와 연결 \* @param ft \* 핸들러에서 사용할 @param 데이터 인수 데이터의 \* @param data\_type BEAU\_TYPE\_x, 해당되지 않는 경우 0 \*/void Funnel\_Tree\_Add\_Data(funnel\_tree\_t \* ft, void \*데이터, uint16\_t 데이터\_type);/\*\* \* 노드 이름에 대한 포인터 반환 \* @detail ft->name이 존재하면 그 이름이 사용됩니다. \* 그렇지 않으면, ft->key의 16진수 문자열을 생성하여 \* 의 문자열을 생성하여 반환합니다. \* @param ft 노드 \* @param buf 출력 버퍼(항상 사용되지는 않음) \* @param buf\_size 버퍼의 최대 크기(12 이상이어야 함) \* @return 유효한 이름(절대 NULL을 반환하지 않음) \*/const char \*Funnel\_Tree\_Get\_Name(funnel\_tree\_t \* ft, char \*buf, UINT32\_t BUF\_SIZE);/\*\* \* 기존 오브젝트에 노드 해시 추가 \* @param ft 노드 해시에 해시 항목을 추가할 오브젝트 \* @param 오브젝트 \* @param include\_local\_hash true는 "\_\_" local\_hash도 추가합니다. \* @성공 시 참을 반환 \*/bool Funnel\_Tree\_Add\_Hash\_To\_Object(funnel\_tree\_t \* ft, cJSON \* obj, bool include\_local\_hash);/\*\* \* 노드의 해시가 포함된 새 JSON 객체를 반환합니다. \* @param ft 노드 \* @return cJSON 객체(새로 할당된) \*/cJSON \*Funnel\_Tree\_Create\_Hash\_Object(funnel\_tree\_t \* ft);/\*\* \* 노드에 대한 디버그 정보 인쇄 \* @param ft \*/void Funnel\_Tree\_Print(funnel