Changeset 745 for trunk/server/source3/lib/adt_tree.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/lib/adt_tree.c
r414 r745 21 21 #include "adt_tree.h" 22 22 23 struct tree_node { 24 struct tree_node *parent; 25 struct tree_node **children; 26 int num_children; 27 char *key; 28 void *data_p; 29 }; 30 31 struct sorted_tree { 32 struct tree_node *root; 33 }; 23 34 24 35 /************************************************************************** … … 28 39 { 29 40 char *p; 30 41 31 42 *new_path = *base = NULL; 32 43 33 44 if ( !path ) 34 45 return False; 35 46 36 47 *base = path; 37 38 p = strchr( path, ' /' );39 48 49 p = strchr( path, '\\' ); 50 40 51 if ( p ) { 41 52 *p = '\0'; 42 53 *new_path = p+1; 43 54 } 44 55 45 56 return True; 46 57 } 47 58 48 49 /************************************************************************** 50 Initialize the tree's root. The cmp_fn is a callback function used 51 for comparision of two children 52 *************************************************************************/ 53 54 SORTED_TREE* pathtree_init( void *data_p, int (cmp_fn)(void*, void*) ) 55 { 56 SORTED_TREE *tree = NULL; 57 58 if ( !(tree = TALLOC_ZERO_P(NULL, SORTED_TREE)) ) 59 return NULL; 60 61 tree->compare = cmp_fn; 62 63 if ( !(tree->root = TALLOC_ZERO_P(tree, TREE_NODE)) ) { 59 /************************************************************************** 60 Initialize the tree's root. 61 *************************************************************************/ 62 63 struct sorted_tree *pathtree_init(void *data_p) 64 { 65 struct sorted_tree *tree = NULL; 66 67 tree = talloc_zero(NULL, struct sorted_tree); 68 if (tree == NULL) { 69 return NULL; 70 } 71 72 tree->root = talloc_zero(tree, struct tree_node); 73 if (tree->root == NULL) { 64 74 TALLOC_FREE( tree ); 65 75 return NULL; 66 76 } 67 77 68 78 tree->root->data_p = data_p; 69 79 70 80 return tree; 71 81 } … … 76 86 *************************************************************************/ 77 87 78 static TREE_NODE* pathtree_birth_child( TREE_NODE *node, char* key ) 79 { 80 TREE_NODE *infant = NULL; 81 TREE_NODE **siblings; 88 static struct tree_node *pathtree_birth_child(struct tree_node *node, 89 char* key ) 90 { 91 struct tree_node *infant = NULL; 92 struct tree_node **siblings; 82 93 int i; 83 84 if ( !(infant = TALLOC_ZERO_P( node, TREE_NODE)) ) 85 return NULL; 86 94 95 infant = talloc_zero(node, struct tree_node); 96 if (infant == NULL) { 97 return NULL; 98 } 99 87 100 infant->key = talloc_strdup( infant, key ); 88 101 infant->parent = node; 89 90 siblings = TALLOC_REALLOC_ARRAY( node, node->children, TREE_NODE *, node->num_children+1 ); 91 102 103 siblings = talloc_realloc(node, node->children, struct tree_node *, 104 node->num_children+1); 105 92 106 if ( siblings ) 93 107 node->children = siblings; 94 108 95 109 node->num_children++; 96 110 97 111 /* first child */ 98 112 99 113 if ( node->num_children == 1 ) { 100 114 DEBUG(11,("pathtree_birth_child: First child of node [%s]! [%s]\n", … … 112 126 * from left to right 113 127 */ 114 128 115 129 for ( i = node->num_children-1; i>=1; i-- ) 116 130 { 117 131 DEBUG(11,("pathtree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n", 118 132 infant->key, node->children[i-1]->key)); 119 133 120 134 /* the strings should never match assuming that we 121 135 have called pathtree_find_child() first */ 122 136 123 137 if ( StrCaseCmp( infant->key, node->children[i-1]->key ) > 0 ) { 124 138 DEBUG(11,("pathtree_birth_child: storing infant in i == [%d]\n", … … 127 141 break; 128 142 } 129 143 130 144 /* bump everything towards the end on slot */ 131 145 132 146 node->children[i] = node->children[i-1]; 133 147 } 134 148 135 149 DEBUG(11,("pathtree_birth_child: Exiting loop (i == [%d])\n", i )); 136 150 137 151 /* if we haven't found the correct slot yet, the child 138 152 will be first in the list */ 139 153 140 154 if ( i == 0 ) 141 155 node->children[0] = infant; … … 149 163 *************************************************************************/ 150 164 151 static TREE_NODE* pathtree_find_child( TREE_NODE *node, char* key ) 152 { 153 TREE_NODE *next = NULL; 165 static struct tree_node *pathtree_find_child(struct tree_node *node, 166 char *key ) 167 { 168 struct tree_node *next = NULL; 154 169 int i, result; 155 170 156 171 if ( !node ) { 157 172 DEBUG(0,("pathtree_find_child: NULL node passed into function!\n")); 158 173 return NULL; 159 174 } 160 175 161 176 if ( !key ) { 162 177 DEBUG(0,("pathtree_find_child: NULL key string passed into function!\n")); 163 178 return NULL; 164 179 } 165 180 166 181 for ( i=0; i<node->num_children; i++ ) 167 182 { 168 183 DEBUG(11,("pathtree_find_child: child key => [%s]\n", 169 184 node->children[i]->key)); 170 185 171 186 result = StrCaseCmp( node->children[i]->key, key ); 172 187 173 188 if ( result == 0 ) 174 189 next = node->children[i]; 175 190 176 191 /* if result > 0 then we've gone to far because 177 192 the list of children is sorted by key name 178 193 If result == 0, then we have a match */ 179 194 180 195 if ( result > 0 ) 181 196 break; … … 184 199 DEBUG(11,("pathtree_find_child: %s [%s]\n", 185 200 next ? "Found" : "Did not find", key )); 186 201 187 202 return next; 188 203 } … … 192 207 *************************************************************************/ 193 208 194 WERROR pathtree_add( SORTED_TREE *tree, const char *path, void *data_p)209 WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p) 195 210 { 196 211 char *str, *base, *path2; 197 TREE_NODE*current, *next;212 struct tree_node *current, *next; 198 213 WERROR ret = WERR_OK; 199 214 200 215 DEBUG(8,("pathtree_add: Enter\n")); 201 202 if ( !path || *path != ' /' ) {216 217 if ( !path || *path != '\\' ) { 203 218 DEBUG(0,("pathtree_add: Attempt to add a node with a bad path [%s]\n", 204 219 path ? path : "NULL" )); 205 220 return WERR_INVALID_PARAM; 206 221 } 207 222 208 223 if ( !tree ) { 209 224 DEBUG(0,("pathtree_add: Attempt to add a node to an uninitialized tree!\n")); 210 225 return WERR_INVALID_PARAM; 211 226 } 212 213 /* move past the first ' /' */214 227 228 /* move past the first '\\' */ 229 215 230 path++; 216 231 path2 = SMB_STRDUP( path ); … … 219 234 return WERR_NOMEM; 220 235 } 221 236 222 237 223 238 /* … … 226 241 * The path should be of the form /<key1>/<key2>/... 227 242 */ 228 243 229 244 base = path2; 230 245 str = path2; 231 246 current = tree->root; 232 247 233 248 do { 234 249 /* break off the remaining part of the path */ 235 236 str = strchr( str, ' /' );250 251 str = strchr( str, '\\' ); 237 252 if ( str ) 238 253 *str = '\0'; 239 254 240 255 /* iterate to the next child--birth it if necessary */ 241 256 242 257 next = pathtree_find_child( current, base ); 243 258 if ( !next ) { … … 250 265 } 251 266 current = next; 252 267 253 268 /* setup the next part of the path */ 254 269 255 270 base = str; 256 271 if ( base ) { 257 *base = ' /';272 *base = '\\'; 258 273 base++; 259 274 str = base; 260 275 } 261 276 262 277 } while ( base != NULL ); 263 278 264 279 current->data_p = data_p; 265 280 266 281 DEBUG(10,("pathtree_add: Successfully added node [%s] to tree\n", 267 282 path )); … … 276 291 277 292 /************************************************************************** 278 Recursive routine to print out all children of a TREE_NODE293 Recursive routine to print out all children of a struct tree_node 279 294 *************************************************************************/ 280 295 281 296 static void pathtree_print_children(TALLOC_CTX *ctx, 282 TREE_NODE*node,297 struct tree_node *node, 283 298 int debug, 284 299 const char *path ) … … 320 335 *************************************************************************/ 321 336 322 void pathtree_print_keys( SORTED_TREE*tree, int debug )337 void pathtree_print_keys(struct sorted_tree *tree, int debug ) 323 338 { 324 339 int i; … … 344 359 *************************************************************************/ 345 360 346 void* pathtree_find( SORTED_TREE*tree, char *key )361 void* pathtree_find(struct sorted_tree *tree, char *key ) 347 362 { 348 363 char *keystr, *base = NULL, *str = NULL, *p; 349 TREE_NODE*current;364 struct tree_node *current; 350 365 void *result = NULL; 351 366 352 367 DEBUG(10,("pathtree_find: Enter [%s]\n", key ? key : "NULL" )); 353 368 354 369 /* sanity checks first */ 355 370 356 371 if ( !key ) { 357 372 DEBUG(0,("pathtree_find: Attempt to search tree using NULL search string!\n")); 358 373 return NULL; 359 374 } 360 375 361 376 if ( !tree ) { 362 377 DEBUG(0,("pathtree_find: Attempt to search an uninitialized tree using string [%s]!\n", … … 364 379 return NULL; 365 380 } 366 381 367 382 if ( !tree->root ) 368 383 return NULL; 369 384 370 385 /* make a copy to play with */ 371 372 if ( *key == ' /' )386 387 if ( *key == '\\' ) 373 388 keystr = SMB_STRDUP( key+1 ); 374 389 else 375 390 keystr = SMB_STRDUP( key ); 376 391 377 392 if ( !keystr ) { 378 393 DEBUG(0,("pathtree_find: strdup() failed on string [%s]!?!?!\n", key)); … … 381 396 382 397 /* start breaking the path apart */ 383 398 384 399 p = keystr; 385 400 current = tree->root; 386 401 387 402 if ( tree->root->data_p ) 388 403 result = tree->root->data_p; 389 404 390 405 do 391 406 { … … 393 408 394 409 trim_tree_keypath( p, &base, &str ); 395 410 396 411 DEBUG(11,("pathtree_find: [loop] base => [%s], new_path => [%s]\n", 397 412 base ? base : "", … … 399 414 400 415 /* iterate to the next child */ 401 416 402 417 current = pathtree_find_child( current, base ); 403 418 404 419 /* 405 420 * the idea is that the data_p for a parent should … … 407 422 * overridden farther down 408 423 */ 409 424 410 425 if ( current && current->data_p ) 411 426 result = current->data_p; … … 414 429 415 430 p = str; 416 431 417 432 } while ( str && current ); 418 433 419 434 /* result should be the data_p from the lowest match node in the tree */ 420 435 if ( result ) 421 436 DEBUG(11,("pathtree_find: Found data_p!\n")); 422 437 423 438 SAFE_FREE( keystr ); 424 439 425 440 DEBUG(10,("pathtree_find: Exit\n")); 426 441 427 442 return result; 428 443 }
Note:
See TracChangeset
for help on using the changeset viewer.