/* Checks that |tree| is well-formed and verifies that the values in |array[]| are actually in |tree|. There must be |n| elements in |array[]| and |tree|. Returns nonzero only if no errors detected. */ static int verify_tree (struct tavl_table *tree, int array[], size_t n) { int okay = 1; /* Check |tree|'s bst_count against that supplied. */ if (tavl_count (tree) != n) { printf (" Tree count is %lu, but should be %lu.\n", (unsigned long) tavl_count (tree), (unsigned long) n); okay = 0; } if (okay) { /* Recursively verify tree structure. */ size_t count; int height; recurse_verify_tree (tree->tavl_root, &okay, &count, 0, INT_MAX, &height); if (count != n) { printf (" Tree has %lu nodes, but should have %lu.\n", (unsigned long) count, (unsigned long) n); okay = 0; } } if (okay) { /* Check that all the values in |array[]| are in |tree|. */ size_t i; for (i = 0; i < n; i++) if (tavl_find (tree, &array[i]) == NULL) { printf (" Tree does not contain expected value %d.\n", array[i]); okay = 0; } } if (okay) { /* Check that |tavl_t_first()| and |tavl_t_next()| work properly. */ struct tavl_traverser trav; size_t i; int prev = -1; int *item; for (i = 0, item = tavl_t_first (&trav, tree); i < 2 * n && item != NULL; i++, item = tavl_t_next (&trav)) { if (*item <= prev) { printf (" Tree out of order: %d follows %d in traversal\n", *item, prev); okay = 0; } prev = *item; } if (i != n) { printf (" Tree should have %lu items, but has %lu in traversal\n", (unsigned long) n, (unsigned long) i); okay = 0; } } if (okay) { /* Check that |tavl_t_last()| and |tavl_t_prev()| work properly. */ struct tavl_traverser trav; size_t i; int next = INT_MAX; int *item; for (i = 0, item = tavl_t_last (&trav, tree); i < 2 * n && item != NULL; i++, item = tavl_t_prev (&trav)) { if (*item >= next) { printf (" Tree out of order: %d precedes %d in traversal\n", *item, next); okay = 0; } next = *item; } if (i != n) { printf (" Tree should have %lu items, but has %lu in reverse\n", (unsigned long) n, (unsigned long) i); okay = 0; } } if (okay) { /* Check that |tavl_t_init()| works properly. */ struct tavl_traverser init, first, last; int *cur, *prev, *next; tavl_t_init (&init, tree); tavl_t_first (&first, tree); tavl_t_last (&last, tree); cur = tavl_t_cur (&init); if (cur != NULL) { printf (" Inited traverser should be null, but is actually %d.\n", *cur); okay = 0; } next = tavl_t_next (&init); if (next != tavl_t_cur (&first)) { printf (" Next after null should be %d, but is actually %d.\n", *(int *) tavl_t_cur (&first), *next); okay = 0; } tavl_t_prev (&init); prev = tavl_t_prev (&init); if (prev != tavl_t_cur (&last)) { printf (" Previous before null should be %d, but is actually %d.\n", *(int *) tavl_t_cur (&last), *prev); okay = 0; } tavl_t_next (&init); } return okay; }
int main( int argc, char **argv ) { Avlnode *tree = NULL, *n; char command[ 10 ]; char name[ 80 ]; char *p; printf( "> " ); while ( fgets( command, sizeof( command ), stdin ) != NULL ) { switch( *command ) { case 'n': /* new tree */ ( void ) tavl_free( tree, free ); tree = NULL; break; case 'p': /* print */ ( void ) myprint( tree ); break; case 't': /* traverse with first, next */ printf( "***\n" ); for ( n = tavl_end( tree, TAVL_DIR_LEFT ); n != NULL; n = tavl_next( n, TAVL_DIR_RIGHT )) printf( "%s\n", n->avl_data ); printf( "***\n" ); break; case 'f': /* find */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( (p = (char *) tavl_find( tree, name, avl_strcmp )) == NULL ) printf( "Not found.\n\n" ); else printf( "%s\n\n", p ); break; case 'i': /* insert */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( tavl_insert( &tree, strdup( name ), avl_strcmp, avl_dup_error ) != 0 ) printf( "\nNot inserted!\n" ); break; case 'd': /* delete */ printf( "data? " ); if ( fgets( name, sizeof( name ), stdin ) == NULL ) exit( EXIT_SUCCESS ); name[ strlen( name ) - 1 ] = '\0'; if ( tavl_delete( &tree, name, avl_strcmp ) == NULL ) printf( "\nNot found!\n" ); break; case 'q': /* quit */ exit( EXIT_SUCCESS ); break; case '\n': break; default: printf("Commands: insert, delete, print, new, quit\n"); } printf( "> " ); } return( 0 ); }
int mdb_tool_idl_add( MDB_cursor *mc, struct berval *keys, ID id ) { MDB_dbi dbi; mdb_tool_idl_cache *ic, itmp; mdb_tool_idl_cache_entry *ice; int i, rc, lcount; AttrInfo *ai = (AttrInfo *)mc; mc = ai->ai_cursor; dbi = ai->ai_dbi; for (i=0; keys[i].bv_val; i++) { itmp.kstr = keys[i]; ic = tavl_find( (Avlnode *)ai->ai_root, &itmp, mdb_tool_idl_cmp ); /* No entry yet, create one */ if ( !ic ) { MDB_val key, data; ID nid; int rc; if ( ai->ai_clist ) { ic = ai->ai_clist; ai->ai_clist = ic->head; } else { ic = ch_malloc( sizeof( mdb_tool_idl_cache ) + itmp.kstr.bv_len + 4 ); } ic->kstr.bv_len = itmp.kstr.bv_len; ic->kstr.bv_val = (char *)(ic+1); memcpy( ic->kstr.bv_val, itmp.kstr.bv_val, ic->kstr.bv_len ); ic->head = ic->tail = NULL; ic->last = 0; ic->count = 0; ic->offset = 0; ic->flags = 0; tavl_insert( (Avlnode **)&ai->ai_root, ic, mdb_tool_idl_cmp, avl_dup_error ); /* load existing key count here */ key.mv_size = keys[i].bv_len; key.mv_data = keys[i].bv_val; rc = mdb_cursor_get( mc, &key, &data, MDB_SET ); if ( rc == 0 ) { ic->flags |= WAS_FOUND; nid = *(ID *)data.mv_data; if ( nid == 0 ) { ic->count = MDB_IDL_DB_SIZE+1; ic->flags |= WAS_RANGE; } else { size_t count; mdb_cursor_count( mc, &count ); ic->count = count; ic->first = nid; ic->offset = count & (IDBLOCK-1); } } } /* are we a range already? */ if ( ic->count > MDB_IDL_DB_SIZE ) { ic->last = id; continue; /* Are we at the limit, and converting to a range? */ } else if ( ic->count == MDB_IDL_DB_SIZE ) { if ( ic->head ) { ic->tail->next = ai->ai_flist; ai->ai_flist = ic->head; } ic->head = ic->tail = NULL; ic->last = id; ic->count++; continue; } /* No free block, create that too */ lcount = ic->count & (IDBLOCK-1); if ( !ic->tail || lcount == 0) { if ( ai->ai_flist ) { ice = ai->ai_flist; ai->ai_flist = ice->next; } else { ice = ch_malloc( sizeof( mdb_tool_idl_cache_entry )); } ice->next = NULL; if ( !ic->head ) { ic->head = ice; } else { ic->tail->next = ice; } ic->tail = ice; if ( lcount ) ice->ids[lcount-1] = 0; if ( !ic->count ) ic->first = id; } ice = ic->tail; if (!lcount || ice->ids[lcount-1] != id) ice->ids[lcount] = id; ic->count++; } return 0; }