1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
10 /* Common API for dealing with directory trees */
14 static OSDirTree *_OSTreeNode_Add(OSDirTree *tree, const char *str,
15 void *data, char sep) __attribute__((nonnull(2)));
19 * Returns NULL on error
21 OSDirTree *OSDirTree_Create()
25 my_tree = (OSDirTree *) calloc(1, sizeof(OSDirTree));
30 my_tree->first_node = NULL;
31 my_tree->last_node = NULL;
36 /* Get first node from tree (starting from parent)
37 * Returns null on invalid tree (not initialized)
39 OSTreeNode *OSDirTree_GetFirstNode(OSDirTree *tree)
41 return (tree->first_node);
44 /* Look for an entry in the middle of the tree
45 * Should not be called directly
47 static OSDirTree *_OSTreeNode_Add(OSDirTree *tree, const char *str,
54 /* Look for a next entry */
55 tmp_str = strchr(str, sep);
62 tree = (OSDirTree *) calloc(1, sizeof(OSDirTree));
67 tree->first_node = NULL;
68 tree->last_node = NULL;
71 curnode = tree->first_node;
73 /* Loop over all nodes */
75 if (strcmp(curnode->value, str) == 0) {
76 /* If we have other elements, keep going */
78 curnode->child = _OSTreeNode_Add(curnode->child,
79 tmp_str + 1, data, sep);
83 curnode = curnode->next;
86 /* Add a new entry, if not found */
88 os_calloc(1, sizeof(OSTreeNode), newnode);
90 if (!tree->first_node && !tree->last_node) {
91 tree->last_node = newnode;
92 tree->first_node = newnode;
94 tree->last_node->next = newnode;
98 tree->last_node = newnode;
99 os_strdup(str, newnode->value);
101 /* If we have other elements, keep going */
103 newnode->child = _OSTreeNode_Add(newnode->child,
104 tmp_str + 1, data, sep);
105 newnode->data = NULL;
107 /* Otherwise, set the data in here */
109 newnode->data = data;
110 newnode->child = NULL;
114 /* Fix the string back */
122 /* Add a new string to the tree, setting the data at the final leaf.
123 * The tree will be divided by the "separator", where each token
124 * will delimit the child.
125 * For example, /etc/my/name.conf will become:
129 * Str must not be NULL.
131 void OSDirTree_AddToTree(OSDirTree *tree, const char *str, void *data, char sep)
137 /* First character doesn't count as a separator */
138 tmp_str = strchr(str + 1, sep);
143 curnode = tree->first_node;
145 if (strcmp(str, curnode->value) == 0) {
146 /* If we have other elements, keep going */
148 curnode->child = _OSTreeNode_Add(curnode->child,
149 tmp_str + 1, data, sep);
154 curnode = curnode->next;
157 /* If we didn't find an entry, create one */
159 os_calloc(1, sizeof(OSTreeNode), newnode);
160 printf("XX Adding MAIN node: %s\n", str);
162 if (!tree->first_node && !tree->last_node) {
163 tree->last_node = newnode;
164 tree->first_node = newnode;
166 printf("XXX last new node: %s\n", tree->last_node->value);
167 tree->last_node->next = newnode;
168 tree->last_node = newnode;
171 newnode->next = NULL;
172 os_strdup(str, newnode->value);
174 /* If we have other elements, keep going */
176 newnode->child = _OSTreeNode_Add(newnode->child,
177 tmp_str + 1, data, sep);
178 newnode->data = NULL;
180 /* Otherwise, set the data in here */
182 newnode->data = data;
183 newnode->child = NULL;
187 /* Fix the string back */
195 void *OSDirTree_SearchTree(const OSDirTree *tree, const char *str, char sep)
199 const OSTreeNode *curnode;
201 /* First character doesn't count as a separator */
202 tmp_str = strchr(str + 1, sep);
207 printf("looking for: %s\n", str);
209 /* If our tree is not empty, look for the main entry */
210 curnode = tree->first_node;
212 printf("comparing: '%s' and '%s'\n", str, curnode->value);
213 if (strcmp(str, curnode->value) == 0) {
214 printf("found node: %s\n", str);
216 /* If we have other elements, keep going */
218 ret = OSDirTree_SearchTree(curnode->child, tmp_str + 1, sep);
225 curnode = curnode->next;
228 /* Fix the string back */