Annotation of embedaddon/quagga/isisd/dict.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * Dictionary Abstract Data Type
                      3:  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
                      4:  *
                      5:  * Free Software License:
                      6:  *
                      7:  * All rights are reserved by the author, with the following exceptions:
                      8:  * Permission is granted to freely reproduce and distribute this software,
                      9:  * possibly in exchange for a fee, provided that this copyright notice appears
                     10:  * intact. Permission is also granted to adapt this software to produce
                     11:  * derivative works, as long as the modified versions carry this copyright
                     12:  * notice and additional notices stating that the work has been modified.
                     13:  * This source code may be translated into executable form and incorporated
                     14:  * into proprietary software; there is no requirement for such software to
                     15:  * contain a copyright notice related to this source.
                     16:  */
                     17: 
                     18: #include "zebra.h"
                     19: #include "zassert.h"
1.1.1.2 ! misho      20: #include "memory.h"
1.1       misho      21: #include "dict.h"
                     22: 
                     23: /*
                     24:  * These macros provide short convenient names for structure members,
                     25:  * which are embellished with dict_ prefixes so that they are
                     26:  * properly confined to the documented namespace. It's legal for a 
                     27:  * program which uses dict to define, for instance, a macro called ``parent''.
                     28:  * Such a macro would interfere with the dnode_t struct definition.
                     29:  * In general, highly portable and reusable C modules which expose their
                     30:  * structures need to confine structure member names to well-defined spaces.
                     31:  * The resulting identifiers aren't necessarily convenient to use, nor
                     32:  * readable, in the implementation, however!
                     33:  */
                     34: 
                     35: #define left dict_left
                     36: #define right dict_right
                     37: #define parent dict_parent
                     38: #define color dict_color
                     39: #define key dict_key
                     40: #define data dict_data
                     41: 
                     42: #define nilnode dict_nilnode
                     43: #define nodecount dict_nodecount
                     44: #define maxcount dict_maxcount
                     45: #define compare dict_compare
                     46: #define allocnode dict_allocnode
                     47: #define freenode dict_freenode
                     48: #define context dict_context
                     49: #define dupes dict_dupes
                     50: 
                     51: #define dictptr dict_dictptr
                     52: 
                     53: #define dict_root(D) ((D)->nilnode.left)
                     54: #define dict_nil(D) (&(D)->nilnode)
                     55: #define DICT_DEPTH_MAX 64
                     56: 
                     57: static dnode_t *dnode_alloc(void *context);
                     58: static void dnode_free(dnode_t *node, void *context);
                     59: 
                     60: /*
                     61:  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
                     62:  * its right child C are rearranged so that the P instead becomes the left
                     63:  * child of C.   The left subtree of C is inherited as the new right subtree
                     64:  * for P.  The ordering of the keys within the tree is thus preserved.
                     65:  */
                     66: 
                     67: static void rotate_left(dnode_t *upper)
                     68: {
                     69:     dnode_t *lower, *lowleft, *upparent;
                     70: 
                     71:     lower = upper->right;
                     72:     upper->right = lowleft = lower->left;
                     73:     lowleft->parent = upper;
                     74: 
                     75:     lower->parent = upparent = upper->parent;
                     76: 
                     77:     /* don't need to check for root node here because root->parent is
                     78:        the sentinel nil node, and root->parent->left points back to root */
                     79: 
                     80:     if (upper == upparent->left) {
                     81:        upparent->left = lower;
                     82:     } else {
                     83:        assert (upper == upparent->right);
                     84:        upparent->right = lower;
                     85:     }
                     86: 
                     87:     lower->left = upper;
                     88:     upper->parent = lower;
                     89: }
                     90: 
                     91: /*
                     92:  * This operation is the ``mirror'' image of rotate_left. It is
                     93:  * the same procedure, but with left and right interchanged.
                     94:  */
                     95: 
                     96: static void rotate_right(dnode_t *upper)
                     97: {
                     98:     dnode_t *lower, *lowright, *upparent;
                     99: 
                    100:     lower = upper->left;
                    101:     upper->left = lowright = lower->right;
                    102:     lowright->parent = upper;
                    103: 
                    104:     lower->parent = upparent = upper->parent;
                    105: 
                    106:     if (upper == upparent->right) {
                    107:        upparent->right = lower;
                    108:     } else {
                    109:        assert (upper == upparent->left);
                    110:        upparent->left = lower;
                    111:     }
                    112: 
                    113:     lower->right = upper;
                    114:     upper->parent = lower;
                    115: }
                    116: 
                    117: /*
                    118:  * Do a postorder traversal of the tree rooted at the specified
                    119:  * node and free everything under it.  Used by dict_free().
                    120:  */
                    121: 
                    122: static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
                    123: {
                    124:     if (node == nil)
                    125:        return;
                    126:     free_nodes(dict, node->left, nil);
                    127:     free_nodes(dict, node->right, nil);
                    128:     dict->freenode(node, dict->context);
                    129: }
                    130: 
                    131: /*
                    132:  * This procedure performs a verification that the given subtree is a binary
                    133:  * search tree. It performs an inorder traversal of the tree using the
                    134:  * dict_next() successor function, verifying that the key of each node is
                    135:  * strictly lower than that of its successor, if duplicates are not allowed,
                    136:  * or lower or equal if duplicates are allowed.  This function is used for
                    137:  * debugging purposes. 
                    138:  */
                    139: 
                    140: static int verify_bintree(dict_t *dict)
                    141: {
                    142:     dnode_t *first, *next;
                    143: 
                    144:     first = dict_first(dict);
                    145: 
                    146:     if (dict->dupes) {
                    147:        while (first && (next = dict_next(dict, first))) {
                    148:            if (dict->compare(first->key, next->key) > 0)
                    149:                return 0;
                    150:            first = next;
                    151:        }
                    152:     } else {
                    153:        while (first && (next = dict_next(dict, first))) {
                    154:            if (dict->compare(first->key, next->key) >= 0)
                    155:                return 0;
                    156:            first = next;
                    157:        }
                    158:     }
                    159:     return 1;
                    160: }
                    161: 
                    162: 
                    163: /*
                    164:  * This function recursively verifies that the given binary subtree satisfies
                    165:  * three of the red black properties. It checks that every red node has only
                    166:  * black children. It makes sure that each node is either red or black. And it
                    167:  * checks that every path has the same count of black nodes from root to leaf.
                    168:  * It returns the blackheight of the given subtree; this allows blackheights to
                    169:  * be computed recursively and compared for left and right siblings for
                    170:  * mismatches. It does not check for every nil node being black, because there
                    171:  * is only one sentinel nil node. The return value of this function is the
                    172:  * black height of the subtree rooted at the node ``root'', or zero if the
                    173:  * subtree is not red-black.
                    174:  */
                    175: 
                    176: static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
                    177: {
                    178:     unsigned height_left, height_right;
                    179: 
                    180:     if (root != nil) {
                    181:        height_left = verify_redblack(nil, root->left);
                    182:        height_right = verify_redblack(nil, root->right);
                    183:        if (height_left == 0 || height_right == 0)
                    184:            return 0;
                    185:        if (height_left != height_right)
                    186:            return 0;
                    187:        if (root->color == dnode_red) {
                    188:            if (root->left->color != dnode_black)
                    189:                return 0;
                    190:            if (root->right->color != dnode_black)
                    191:                return 0;
                    192:            return height_left;
                    193:        }
                    194:        if (root->color != dnode_black)
                    195:            return 0;
                    196:        return height_left + 1;
                    197:     } 
                    198:     return 1;
                    199: }
                    200: 
                    201: /*
                    202:  * Compute the actual count of nodes by traversing the tree and
                    203:  * return it. This could be compared against the stored count to
                    204:  * detect a mismatch.
                    205:  */
                    206: 
                    207: static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
                    208: {
                    209:     if (root == nil)
                    210:        return 0;
                    211:     else
                    212:        return 1 + verify_node_count(nil, root->left)
                    213:            + verify_node_count(nil, root->right);
                    214: }
                    215: 
                    216: /*
                    217:  * Verify that the tree contains the given node. This is done by
                    218:  * traversing all of the nodes and comparing their pointers to the
                    219:  * given pointer. Returns 1 if the node is found, otherwise
                    220:  * returns zero. It is intended for debugging purposes.
                    221:  */
                    222: 
                    223: static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
                    224: {
                    225:     if (root != nil) {
                    226:        return root == node
                    227:                || verify_dict_has_node(nil, root->left, node)
                    228:                || verify_dict_has_node(nil, root->right, node);
                    229:     }
                    230:     return 0;
                    231: }
                    232: 
                    233: 
                    234: /*
                    235:  * Dynamically allocate and initialize a dictionary object.
                    236:  */
                    237: 
                    238: dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
                    239: {
1.1.1.2 ! misho     240:     dict_t *new = XCALLOC(MTYPE_ISIS_DICT, sizeof(dict_t));
1.1       misho     241: 
                    242:     if (new) {
                    243:        new->compare = comp;
                    244:        new->allocnode = dnode_alloc;
                    245:        new->freenode = dnode_free;
                    246:        new->context = NULL;
                    247:        new->nodecount = 0;
                    248:        new->maxcount = maxcount;
                    249:        new->nilnode.left = &new->nilnode;
                    250:        new->nilnode.right = &new->nilnode;
                    251:        new->nilnode.parent = &new->nilnode;
                    252:        new->nilnode.color = dnode_black;
                    253:        new->dupes = 0;
                    254:     }
                    255:     return new;
                    256: }
                    257: 
                    258: /*
                    259:  * Select a different set of node allocator routines.
                    260:  */
                    261: 
                    262: void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
                    263:        dnode_free_t fr, void *context)
                    264: {
                    265:     assert (dict_count(dict) == 0);
                    266:     assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
                    267: 
                    268:     dict->allocnode = al ? al : dnode_alloc;
                    269:     dict->freenode = fr ? fr : dnode_free;
                    270:     dict->context = context;
                    271: }
                    272: 
                    273: /*
                    274:  * Free a dynamically allocated dictionary object. Removing the nodes
                    275:  * from the tree before deleting it is required.
                    276:  */
                    277: 
                    278: void dict_destroy(dict_t *dict)
                    279: {
                    280:     assert (dict_isempty(dict));
1.1.1.2 ! misho     281:     XFREE(MTYPE_ISIS_DICT, dict);
1.1       misho     282: }
                    283: 
                    284: /*
                    285:  * Free all the nodes in the dictionary by using the dictionary's
                    286:  * installed free routine. The dictionary is emptied.
                    287:  */
                    288: 
                    289: void dict_free_nodes(dict_t *dict)
                    290: {
                    291:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
                    292:     free_nodes(dict, root, nil);
                    293:     dict->nodecount = 0;
                    294:     dict->nilnode.left = &dict->nilnode;
                    295:     dict->nilnode.right = &dict->nilnode;
                    296: }
                    297: 
                    298: /*
                    299:  * Obsolescent function, equivalent to dict_free_nodes
                    300:  */
                    301: 
                    302: void dict_free(dict_t *dict)
                    303: {
                    304:     dict_free_nodes(dict);
                    305: }
                    306: 
                    307: /*
                    308:  * Initialize a user-supplied dictionary object.
                    309:  */
                    310: 
                    311: dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
                    312: {
                    313:     dict->compare = comp;
                    314:     dict->allocnode = dnode_alloc;
                    315:     dict->freenode = dnode_free;
                    316:     dict->context = NULL;
                    317:     dict->nodecount = 0;
                    318:     dict->maxcount = maxcount;
                    319:     dict->nilnode.left = &dict->nilnode;
                    320:     dict->nilnode.right = &dict->nilnode;
                    321:     dict->nilnode.parent = &dict->nilnode;
                    322:     dict->nilnode.color = dnode_black;
                    323:     dict->dupes = 0;
                    324:     return dict;
                    325: }
                    326: 
                    327: /* 
                    328:  * Initialize a dictionary in the likeness of another dictionary
                    329:  */
                    330: 
                    331: void dict_init_like(dict_t *dict, const dict_t *template)
                    332: {
                    333:     dict->compare = template->compare;
                    334:     dict->allocnode = template->allocnode;
                    335:     dict->freenode = template->freenode;
                    336:     dict->context = template->context;
                    337:     dict->nodecount = 0;
                    338:     dict->maxcount = template->maxcount;
                    339:     dict->nilnode.left = &dict->nilnode;
                    340:     dict->nilnode.right = &dict->nilnode;
                    341:     dict->nilnode.parent = &dict->nilnode;
                    342:     dict->nilnode.color = dnode_black;
                    343:     dict->dupes = template->dupes;
                    344: 
                    345:     assert (dict_similar(dict, template));
                    346: }
                    347: 
                    348: /*
                    349:  * Remove all nodes from the dictionary (without freeing them in any way).
                    350:  */
                    351: 
                    352: static void dict_clear(dict_t *dict)
                    353: {
                    354:     dict->nodecount = 0;
                    355:     dict->nilnode.left = &dict->nilnode;
                    356:     dict->nilnode.right = &dict->nilnode;
                    357:     dict->nilnode.parent = &dict->nilnode;
                    358:     assert (dict->nilnode.color == dnode_black);
                    359: }
                    360: 
                    361: 
                    362: /*
                    363:  * Verify the integrity of the dictionary structure.  This is provided for
                    364:  * debugging purposes, and should be placed in assert statements.   Just because
                    365:  * this function succeeds doesn't mean that the tree is not corrupt. Certain
                    366:  * corruptions in the tree may simply cause undefined behavior.
                    367:  */ 
                    368: 
                    369: int dict_verify(dict_t *dict)
                    370: {
                    371:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
                    372: 
                    373:     /* check that the sentinel node and root node are black */
                    374:     if (root->color != dnode_black)
                    375:        return 0;
                    376:     if (nil->color != dnode_black)
                    377:        return 0;
                    378:     if (nil->right != nil)
                    379:        return 0;
                    380:     /* nil->left is the root node; check that its parent pointer is nil */
                    381:     if (nil->left->parent != nil)
                    382:        return 0;
                    383:     /* perform a weak test that the tree is a binary search tree */
                    384:     if (!verify_bintree(dict))
                    385:        return 0;
                    386:     /* verify that the tree is a red-black tree */
                    387:     if (!verify_redblack(nil, root))
                    388:        return 0;
                    389:     if (verify_node_count(nil, root) != dict_count(dict))
                    390:        return 0;
                    391:     return 1;
                    392: }
                    393: 
                    394: /*
                    395:  * Determine whether two dictionaries are similar: have the same comparison and
                    396:  * allocator functions, and same status as to whether duplicates are allowed.
                    397:  */
                    398: 
                    399: int dict_similar(const dict_t *left, const dict_t *right)
                    400: {
                    401:     if (left->compare != right->compare)
                    402:        return 0;
                    403: 
                    404:     if (left->allocnode != right->allocnode)
                    405:        return 0;
                    406: 
                    407:     if (left->freenode != right->freenode)
                    408:        return 0;
                    409: 
                    410:     if (left->context != right->context)
                    411:        return 0;
                    412: 
                    413:     if (left->dupes != right->dupes)
                    414:        return 0;
                    415: 
                    416:     return 1;
                    417: }
                    418: 
                    419: /*
                    420:  * Locate a node in the dictionary having the given key.
                    421:  * If the node is not found, a null a pointer is returned (rather than 
                    422:  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
                    423:  * located node is returned.
                    424:  */
                    425: 
                    426: dnode_t *dict_lookup(dict_t *dict, const void *key)
                    427: {
                    428:     dnode_t *root = dict_root(dict);
                    429:     dnode_t *nil = dict_nil(dict);
                    430:     dnode_t *saved;
                    431:     int result;
                    432: 
                    433:     /* simple binary search adapted for trees that contain duplicate keys */
                    434: 
                    435:     while (root != nil) {
                    436:        result = dict->compare(key, root->key);
                    437:        if (result < 0)
                    438:            root = root->left;
                    439:        else if (result > 0)
                    440:            root = root->right;
                    441:        else {
                    442:            if (!dict->dupes) { /* no duplicates, return match          */
                    443:                return root;
                    444:            } else {            /* could be dupes, find leftmost one    */
                    445:                do {
                    446:                    saved = root;
                    447:                    root = root->left;
                    448:                    while (root != nil && dict->compare(key, root->key))
                    449:                        root = root->right;
                    450:                } while (root != nil);
                    451:                return saved;
                    452:            }
                    453:        }
                    454:     }
                    455: 
                    456:     return NULL;
                    457: }
                    458: 
                    459: /*
                    460:  * Look for the node corresponding to the lowest key that is equal to or
                    461:  * greater than the given key.  If there is no such node, return null.
                    462:  */
                    463: 
                    464: dnode_t *dict_lower_bound(dict_t *dict, const void *key)
                    465: {
                    466:     dnode_t *root = dict_root(dict);
                    467:     dnode_t *nil = dict_nil(dict);
                    468:     dnode_t *tentative = 0;
                    469: 
                    470:     while (root != nil) {
                    471:        int result = dict->compare(key, root->key);
                    472: 
                    473:        if (result > 0) {
                    474:            root = root->right;
                    475:        } else if (result < 0) {
                    476:            tentative = root;
                    477:            root = root->left;
                    478:        } else {
                    479:            if (!dict->dupes) {
                    480:                return root;
                    481:            } else {
                    482:                tentative = root;
                    483:                root = root->left;
                    484:            }
                    485:        } 
                    486:     }
                    487:     
                    488:     return tentative;
                    489: }
                    490: 
                    491: /*
                    492:  * Look for the node corresponding to the greatest key that is equal to or
                    493:  * lower than the given key.  If there is no such node, return null.
                    494:  */
                    495: 
                    496: dnode_t *dict_upper_bound(dict_t *dict, const void *key)
                    497: {
                    498:     dnode_t *root = dict_root(dict);
                    499:     dnode_t *nil = dict_nil(dict);
                    500:     dnode_t *tentative = 0;
                    501: 
                    502:     while (root != nil) {
                    503:        int result = dict->compare(key, root->key);
                    504: 
                    505:        if (result < 0) {
                    506:            root = root->left;
                    507:        } else if (result > 0) {
                    508:            tentative = root;
                    509:            root = root->right;
                    510:        } else {
                    511:            if (!dict->dupes) {
                    512:                return root;
                    513:            } else {
                    514:                tentative = root;
                    515:                root = root->right;
                    516:            }
                    517:        } 
                    518:     }
                    519:     
                    520:     return tentative;
                    521: }
                    522: 
                    523: /*
                    524:  * Insert a node into the dictionary. The node should have been
                    525:  * initialized with a data field. All other fields are ignored.
                    526:  * The behavior is undefined if the user attempts to insert into
                    527:  * a dictionary that is already full (for which the dict_isfull()
                    528:  * function returns true).
                    529:  */
                    530: 
                    531: void dict_insert(dict_t *dict, dnode_t *node, const void *key)
                    532: {
                    533:     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
                    534:     dnode_t *parent = nil, *uncle, *grandpa;
                    535:     int result = -1;
                    536: 
                    537:     node->key = key;
                    538: 
                    539:     assert (!dict_isfull(dict));
                    540:     assert (!dict_contains(dict, node));
                    541:     assert (!dnode_is_in_a_dict(node));
                    542: 
                    543:     /* basic binary tree insert */
                    544: 
                    545:     while (where != nil) {
                    546:        parent = where;
                    547:        result = dict->compare(key, where->key);
                    548:        /* trap attempts at duplicate key insertion unless it's explicitly allowed */
                    549:        assert (dict->dupes || result != 0);
                    550:        if (result < 0)
                    551:            where = where->left;
                    552:        else
                    553:            where = where->right;
                    554:     }
                    555: 
                    556:     assert (where == nil);
                    557: 
                    558:     if (result < 0)
                    559:        parent->left = node;
                    560:     else
                    561:        parent->right = node;
                    562: 
                    563:     node->parent = parent;
                    564:     node->left = nil;
                    565:     node->right = nil;
                    566: 
                    567:     dict->nodecount++;
                    568: 
                    569:     /* red black adjustments */
                    570: 
                    571:     node->color = dnode_red;
                    572: 
                    573:     while (parent->color == dnode_red) {
                    574:        grandpa = parent->parent;
                    575:        if (parent == grandpa->left) {
                    576:            uncle = grandpa->right;
                    577:            if (uncle->color == dnode_red) {    /* red parent, red uncle */
                    578:                parent->color = dnode_black;
                    579:                uncle->color = dnode_black;
                    580:                grandpa->color = dnode_red;
                    581:                node = grandpa;
                    582:                parent = grandpa->parent;
                    583:            } else {                            /* red parent, black uncle */
                    584:                if (node == parent->right) {
                    585:                    rotate_left(parent);
                    586:                    parent = node;
                    587:                    assert (grandpa == parent->parent);
                    588:                    /* rotation between parent and child preserves grandpa */
                    589:                }
                    590:                parent->color = dnode_black;
                    591:                grandpa->color = dnode_red;
                    592:                rotate_right(grandpa);
                    593:                break;
                    594:            }
                    595:        } else {        /* symmetric cases: parent == parent->parent->right */
                    596:            uncle = grandpa->left;
                    597:            if (uncle->color == dnode_red) {
                    598:                parent->color = dnode_black;
                    599:                uncle->color = dnode_black;
                    600:                grandpa->color = dnode_red;
                    601:                node = grandpa;
                    602:                parent = grandpa->parent;
                    603:            } else {
                    604:                if (node == parent->left) {
                    605:                    rotate_right(parent);
                    606:                    parent = node;
                    607:                    assert (grandpa == parent->parent);
                    608:                }
                    609:                parent->color = dnode_black;
                    610:                grandpa->color = dnode_red;
                    611:                rotate_left(grandpa);
                    612:                break;
                    613:            }
                    614:        }
                    615:     }
                    616: 
                    617:     dict_root(dict)->color = dnode_black;
                    618: 
                    619:     assert (dict_verify(dict));
                    620: }
                    621: 
                    622: /*
                    623:  * Delete the given node from the dictionary. If the given node does not belong
                    624:  * to the given dictionary, undefined behavior results.  A pointer to the
                    625:  * deleted node is returned.
                    626:  */
                    627: 
                    628: dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
                    629: {
                    630:     dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
                    631: 
                    632:     /* basic deletion */
                    633: 
                    634:     assert (!dict_isempty(dict));
                    635:     assert (dict_contains(dict, delete));
                    636: 
                    637:     /*
                    638:      * If the node being deleted has two children, then we replace it with its
                    639:      * successor (i.e. the leftmost node in the right subtree.) By doing this,
                    640:      * we avoid the traditional algorithm under which the successor's key and
                    641:      * value *only* move to the deleted node and the successor is spliced out
                    642:      * from the tree. We cannot use this approach because the user may hold
                    643:      * pointers to the successor, or nodes may be inextricably tied to some
                    644:      * other structures by way of embedding, etc. So we must splice out the
                    645:      * node we are given, not some other node, and must not move contents from
                    646:      * one node to another behind the user's back.
                    647:      */
                    648: 
                    649:     if (delete->left != nil && delete->right != nil) {
                    650:        dnode_t *next = dict_next(dict, delete);
                    651:        dnode_t *nextparent = next->parent;
                    652:        dnode_color_t nextcolor = next->color;
                    653: 
                    654:        assert (next != nil);
                    655:        assert (next->parent != nil);
                    656:        assert (next->left == nil);
                    657: 
                    658:        /*
                    659:         * First, splice out the successor from the tree completely, by
                    660:         * moving up its right child into its place.
                    661:         */
                    662: 
                    663:        child = next->right;
                    664:        child->parent = nextparent;
                    665: 
                    666:        if (nextparent->left == next) {
                    667:            nextparent->left = child;
                    668:        } else {
                    669:            assert (nextparent->right == next);
                    670:            nextparent->right = child;
                    671:        }
                    672: 
                    673:        /*
                    674:         * Now that the successor has been extricated from the tree, install it
                    675:         * in place of the node that we want deleted.
                    676:         */
                    677: 
                    678:        next->parent = delparent;
                    679:        next->left = delete->left;
                    680:        next->right = delete->right;
                    681:        next->left->parent = next;
                    682:        next->right->parent = next;
                    683:        next->color = delete->color;
                    684:        delete->color = nextcolor;
                    685: 
                    686:        if (delparent->left == delete) {
                    687:            delparent->left = next;
                    688:        } else {
                    689:            assert (delparent->right == delete);
                    690:            delparent->right = next;
                    691:        }
                    692: 
                    693:     } else {
                    694:        assert (delete != nil);
                    695:        assert (delete->left == nil || delete->right == nil);
                    696: 
                    697:        child = (delete->left != nil) ? delete->left : delete->right;
                    698: 
                    699:        child->parent = delparent = delete->parent;         
                    700: 
                    701:        if (delete == delparent->left) {
                    702:            delparent->left = child;    
                    703:        } else {
                    704:            assert (delete == delparent->right);
                    705:            delparent->right = child;
                    706:        }
                    707:     }
                    708: 
                    709:     delete->parent = NULL;
                    710:     delete->right = NULL;
                    711:     delete->left = NULL;
                    712: 
                    713:     dict->nodecount--;
                    714: 
                    715:     assert (verify_bintree(dict));
                    716: 
                    717:     /* red-black adjustments */
                    718: 
                    719:     if (delete->color == dnode_black) {
                    720:        dnode_t *parent, *sister;
                    721: 
                    722:        dict_root(dict)->color = dnode_red;
                    723: 
                    724:        while (child->color == dnode_black) {
                    725:            parent = child->parent;
                    726:            if (child == parent->left) {
                    727:                sister = parent->right;
                    728:                assert (sister != nil);
                    729:                if (sister->color == dnode_red) {
                    730:                    sister->color = dnode_black;
                    731:                    parent->color = dnode_red;
                    732:                    rotate_left(parent);
                    733:                    sister = parent->right;
                    734:                    assert (sister != nil);
                    735:                }
                    736:                if (sister->left->color == dnode_black
                    737:                        && sister->right->color == dnode_black) {
                    738:                    sister->color = dnode_red;
                    739:                    child = parent;
                    740:                } else {
                    741:                    if (sister->right->color == dnode_black) {
                    742:                        assert (sister->left->color == dnode_red);
                    743:                        sister->left->color = dnode_black;
                    744:                        sister->color = dnode_red;
                    745:                        rotate_right(sister);
                    746:                        sister = parent->right;
                    747:                        assert (sister != nil);
                    748:                    }
                    749:                    sister->color = parent->color;
                    750:                    sister->right->color = dnode_black;
                    751:                    parent->color = dnode_black;
                    752:                    rotate_left(parent);
                    753:                    break;
                    754:                }
                    755:            } else {    /* symmetric case: child == child->parent->right */
                    756:                assert (child == parent->right);
                    757:                sister = parent->left;
                    758:                assert (sister != nil);
                    759:                if (sister->color == dnode_red) {
                    760:                    sister->color = dnode_black;
                    761:                    parent->color = dnode_red;
                    762:                    rotate_right(parent);
                    763:                    sister = parent->left;
                    764:                    assert (sister != nil);
                    765:                }
                    766:                if (sister->right->color == dnode_black
                    767:                        && sister->left->color == dnode_black) {
                    768:                    sister->color = dnode_red;
                    769:                    child = parent;
                    770:                } else {
                    771:                    if (sister->left->color == dnode_black) {
                    772:                        assert (sister->right->color == dnode_red);
                    773:                        sister->right->color = dnode_black;
                    774:                        sister->color = dnode_red;
                    775:                        rotate_left(sister);
                    776:                        sister = parent->left;
                    777:                        assert (sister != nil);
                    778:                    }
                    779:                    sister->color = parent->color;
                    780:                    sister->left->color = dnode_black;
                    781:                    parent->color = dnode_black;
                    782:                    rotate_right(parent);
                    783:                    break;
                    784:                }
                    785:            }
                    786:        }
                    787: 
                    788:        child->color = dnode_black;
                    789:        dict_root(dict)->color = dnode_black;
                    790:     }
                    791: 
                    792:     assert (dict_verify(dict));
                    793: 
                    794:     return delete;
                    795: }
                    796: 
                    797: /*
                    798:  * Allocate a node using the dictionary's allocator routine, give it
                    799:  * the data item.
                    800:  */
                    801: 
                    802: int dict_alloc_insert(dict_t *dict, const void *key, void *data)
                    803: {
1.1.1.2 ! misho     804:     dnode_t *node = dict->allocnode (dict->context);
1.1       misho     805: 
                    806:     if (node) {
                    807:        dnode_init(node, data);
                    808:        dict_insert(dict, node, key);
                    809:        return 1;
                    810:     }
                    811:     return 0;
                    812: }
                    813: 
                    814: void dict_delete_free(dict_t *dict, dnode_t *node)
                    815: {
                    816:     dict_delete(dict, node);
                    817:     dict->freenode(node, dict->context);
                    818: }
                    819: 
                    820: /*
                    821:  * Return the node with the lowest (leftmost) key. If the dictionary is empty
                    822:  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
                    823:  */
                    824: 
                    825: dnode_t *dict_first(dict_t *dict)
                    826: {
                    827:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
                    828: 
                    829:     if (root != nil)
                    830:        while ((left = root->left) != nil)
                    831:            root = left;
                    832: 
                    833:     return (root == nil) ? NULL : root;
                    834: }
                    835: 
                    836: /*
                    837:  * Return the node with the highest (rightmost) key. If the dictionary is empty
                    838:  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
                    839:  */
                    840: 
                    841: dnode_t *dict_last(dict_t *dict)
                    842: {
                    843:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
                    844: 
                    845:     if (root != nil)
                    846:        while ((right = root->right) != nil)
                    847:            root = right;
                    848: 
                    849:     return (root == nil) ? NULL : root;
                    850: }
                    851: 
                    852: /*
                    853:  * Return the given node's successor node---the node which has the
                    854:  * next key in the the left to right ordering. If the node has
                    855:  * no successor, a null pointer is returned rather than a pointer to
                    856:  * the nil node.
                    857:  */
                    858: 
                    859: dnode_t *dict_next(dict_t *dict, dnode_t *curr)
                    860: {
                    861:     dnode_t *nil = dict_nil(dict), *parent, *left;
                    862: 
                    863:     if (curr->right != nil) {
                    864:        curr = curr->right;
                    865:        while ((left = curr->left) != nil)
                    866:            curr = left;
                    867:        return curr;
                    868:     }
                    869: 
                    870:     parent = curr->parent;
                    871: 
                    872:     while (parent != nil && curr == parent->right) {
                    873:        curr = parent;
                    874:        parent = curr->parent;
                    875:     }
                    876: 
                    877:     return (parent == nil) ? NULL : parent;
                    878: }
                    879: 
                    880: /*
                    881:  * Return the given node's predecessor, in the key order.
                    882:  * The nil sentinel node is returned if there is no predecessor.
                    883:  */
                    884: 
                    885: dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
                    886: {
                    887:     dnode_t *nil = dict_nil(dict), *parent, *right;
                    888: 
                    889:     if (curr->left != nil) {
                    890:        curr = curr->left;
                    891:        while ((right = curr->right) != nil)
                    892:            curr = right;
                    893:        return curr;
                    894:     }
                    895: 
                    896:     parent = curr->parent;
                    897: 
                    898:     while (parent != nil && curr == parent->left) {
                    899:        curr = parent;
                    900:        parent = curr->parent;
                    901:     }
                    902: 
                    903:     return (parent == nil) ? NULL : parent;
                    904: }
                    905: 
                    906: void dict_allow_dupes(dict_t *dict)
                    907: {
                    908:     dict->dupes = 1;
                    909: }
                    910: 
                    911: #undef dict_count
                    912: #undef dict_isempty
                    913: #undef dict_isfull
                    914: #undef dnode_get
                    915: #undef dnode_put
                    916: #undef dnode_getkey
                    917: 
                    918: dictcount_t dict_count(dict_t *dict)
                    919: {
                    920:     return dict->nodecount;
                    921: }
                    922: 
                    923: int dict_isempty(dict_t *dict)
                    924: {
                    925:     return dict->nodecount == 0;
                    926: }
                    927: 
                    928: int dict_isfull(dict_t *dict)
                    929: {
                    930:     return dict->nodecount == dict->maxcount;
                    931: }
                    932: 
                    933: int dict_contains(dict_t *dict, dnode_t *node)
                    934: {
                    935:     return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
                    936: }
                    937: 
                    938: static dnode_t *dnode_alloc(void *context)
                    939: {
1.1.1.2 ! misho     940:     return XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
1.1       misho     941: }
                    942: 
                    943: static void dnode_free(dnode_t *node, void *context)
                    944: {
1.1.1.2 ! misho     945:     XFREE(MTYPE_ISIS_DICT_NODE, node);
1.1       misho     946: }
                    947: 
                    948: dnode_t *dnode_create(void *data)
                    949: {
1.1.1.2 ! misho     950:     dnode_t *new = XCALLOC(MTYPE_ISIS_DICT_NODE, sizeof(dnode_t));
1.1       misho     951:     if (new) {
                    952:        new->data = data;
                    953:        new->parent = NULL;
                    954:        new->left = NULL;
                    955:        new->right = NULL;
                    956:     }
                    957:     return new;
                    958: }
                    959: 
                    960: dnode_t *dnode_init(dnode_t *dnode, void *data)
                    961: {
                    962:     dnode->data = data;
                    963:     dnode->parent = NULL;
                    964:     dnode->left = NULL;
                    965:     dnode->right = NULL;
                    966:     return dnode;
                    967: }
                    968: 
                    969: void dnode_destroy(dnode_t *dnode)
                    970: {
                    971:     assert (!dnode_is_in_a_dict(dnode));
1.1.1.2 ! misho     972:     XFREE(MTYPE_ISIS_DICT_NODE, dnode);
1.1       misho     973: }
                    974: 
                    975: void *dnode_get(dnode_t *dnode)
                    976: {
                    977:     return dnode->data;
                    978: }
                    979: 
                    980: const void *dnode_getkey(dnode_t *dnode)
                    981: {
                    982:     return dnode->key;
                    983: }
                    984: 
                    985: void dnode_put(dnode_t *dnode, void *data)
                    986: {
                    987:     dnode->data = data;
                    988: }
                    989: 
                    990: int dnode_is_in_a_dict(dnode_t *dnode)
                    991: {
                    992:     return (dnode->parent && dnode->left && dnode->right);
                    993: }
                    994: 
                    995: void dict_process(dict_t *dict, void *context, dnode_process_t function)
                    996: {
                    997:     dnode_t *node = dict_first(dict), *next;
                    998: 
                    999:     while (node != NULL) {
                   1000:        /* check for callback function deleting */
                   1001:        /* the next node from under us          */
                   1002:        assert (dict_contains(dict, node));
                   1003:        next = dict_next(dict, node);
                   1004:        function(dict, node, context);
                   1005:        node = next;
                   1006:     }
                   1007: }
                   1008: 
                   1009: static void load_begin_internal(dict_load_t *load, dict_t *dict)
                   1010: {
                   1011:     load->dictptr = dict;
                   1012:     load->nilnode.left = &load->nilnode;
                   1013:     load->nilnode.right = &load->nilnode;
                   1014: }
                   1015: 
                   1016: void dict_load_begin(dict_load_t *load, dict_t *dict)
                   1017: {
                   1018:     assert (dict_isempty(dict));
                   1019:     load_begin_internal(load, dict);
                   1020: }
                   1021: 
                   1022: void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
                   1023: {
                   1024:     dict_t *dict = load->dictptr;
                   1025:     dnode_t *nil = &load->nilnode;
                   1026:    
                   1027:     assert (!dnode_is_in_a_dict(newnode));
                   1028:     assert (dict->nodecount < dict->maxcount);
                   1029: 
                   1030:     #ifndef NDEBUG
                   1031:     if (dict->nodecount > 0) {
                   1032:        if (dict->dupes)
                   1033:            assert (dict->compare(nil->left->key, key) <= 0);
                   1034:        else
                   1035:            assert (dict->compare(nil->left->key, key) < 0);
                   1036:     }
                   1037:     #endif
                   1038: 
                   1039:     newnode->key = key;
                   1040:     nil->right->left = newnode;
                   1041:     nil->right = newnode;
                   1042:     newnode->left = nil;
                   1043:     dict->nodecount++;
                   1044: }
                   1045: 
                   1046: void dict_load_end(dict_load_t *load)
                   1047: {
                   1048:     dict_t *dict = load->dictptr;
                   1049:     dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
                   1050:     dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
                   1051:     dnode_t *complete = 0;
                   1052:     dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
                   1053:     dictcount_t botrowcount;
                   1054:     unsigned baselevel = 0, level = 0, i;
                   1055: 
                   1056:     assert (dnode_red == 0 && dnode_black == 1);
                   1057: 
                   1058:     while (fullcount >= nodecount && fullcount)
                   1059:        fullcount >>= 1;
                   1060: 
                   1061:     botrowcount = nodecount - fullcount;
                   1062: 
                   1063:     for (curr = loadnil->left; curr != loadnil; curr = next) {
                   1064:        next = curr->left;
                   1065: 
                   1066:        if (complete == NULL && botrowcount-- == 0) {
                   1067:            assert (baselevel == 0);
                   1068:            assert (level == 0);
                   1069:            baselevel = level = 1;
                   1070:            complete = tree[0];
                   1071: 
                   1072:            if (complete != 0) {
                   1073:                tree[0] = 0;
                   1074:                complete->right = dictnil;
                   1075:                while (tree[level] != 0) {
                   1076:                    tree[level]->right = complete;
                   1077:                    complete->parent = tree[level];
                   1078:                    complete = tree[level];
                   1079:                    tree[level++] = 0;
                   1080:                }
                   1081:            }
                   1082:        }
                   1083: 
                   1084:        if (complete == NULL) {
                   1085:            curr->left = dictnil;
                   1086:            curr->right = dictnil;
                   1087:            curr->color = level % 2;
                   1088:            complete = curr;
                   1089: 
                   1090:            assert (level == baselevel);
                   1091:            while (tree[level] != 0) {
                   1092:                tree[level]->right = complete;
                   1093:                complete->parent = tree[level];
                   1094:                complete = tree[level];
                   1095:                tree[level++] = 0;
                   1096:            }
                   1097:        } else {
                   1098:            curr->left = complete;
                   1099:            curr->color = (level + 1) % 2;
                   1100:            complete->parent = curr;
                   1101:            tree[level] = curr;
                   1102:            complete = 0;
                   1103:            level = baselevel;
                   1104:        }
                   1105:     }
                   1106: 
                   1107:     if (complete == NULL)
                   1108:        complete = dictnil;
                   1109: 
                   1110:     for (i = 0; i < DICT_DEPTH_MAX; i++) {
                   1111:        if (tree[i] != 0) {
                   1112:            tree[i]->right = complete;
                   1113:            complete->parent = tree[i];
                   1114:            complete = tree[i];
                   1115:        }
                   1116:     }
                   1117: 
                   1118:     dictnil->color = dnode_black;
                   1119:     dictnil->right = dictnil;
                   1120:     complete->parent = dictnil;
                   1121:     complete->color = dnode_black;
                   1122:     dict_root(dict) = complete;
                   1123: 
                   1124:     assert (dict_verify(dict));
                   1125: }
                   1126: 
                   1127: void dict_merge(dict_t *dest, dict_t *source)
                   1128: {
                   1129:     dict_load_t load;
                   1130:     dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
                   1131: 
                   1132:     assert (dict_similar(dest, source));       
                   1133: 
                   1134:     if (source == dest)
                   1135:        return;
                   1136: 
                   1137:     dest->nodecount = 0;
                   1138:     load_begin_internal(&load, dest);
                   1139: 
                   1140:     for (;;) {
                   1141:        if (leftnode != NULL && rightnode != NULL) {
                   1142:            if (dest->compare(leftnode->key, rightnode->key) < 0)
                   1143:                goto copyleft;
                   1144:            else
                   1145:                goto copyright;
                   1146:        } else if (leftnode != NULL) {
                   1147:            goto copyleft;
                   1148:        } else if (rightnode != NULL) {
                   1149:            goto copyright;
                   1150:        } else {
                   1151:            assert (leftnode == NULL && rightnode == NULL);
                   1152:            break;
                   1153:        }
                   1154: 
                   1155:     copyleft:
                   1156:        {
                   1157:            dnode_t *next = dict_next(dest, leftnode);
                   1158:            #ifndef NDEBUG
                   1159:            leftnode->left = NULL;      /* suppress assertion in dict_load_next */
                   1160:            #endif
                   1161:            dict_load_next(&load, leftnode, leftnode->key);
                   1162:            leftnode = next;
                   1163:            continue;
                   1164:        }
                   1165:        
                   1166:     copyright:
                   1167:        {
                   1168:            dnode_t *next = dict_next(source, rightnode);
                   1169:            #ifndef NDEBUG
                   1170:            rightnode->left = NULL;
                   1171:            #endif
                   1172:            dict_load_next(&load, rightnode, rightnode->key);
                   1173:            rightnode = next;
                   1174:            continue;
                   1175:        }
                   1176:     }
                   1177: 
                   1178:     dict_clear(source);
                   1179:     dict_load_end(&load);
                   1180: }
                   1181: 
                   1182: #ifdef KAZLIB_TEST_MAIN
                   1183: 
                   1184: #include <stdio.h>
                   1185: #include <string.h>
                   1186: #include <ctype.h>
                   1187: #include <stdarg.h>
                   1188: 
                   1189: typedef char input_t[256];
                   1190: 
                   1191: static int tokenize(char *string, ...)
                   1192: {
                   1193:     char **tokptr; 
                   1194:     va_list arglist;
                   1195:     int tokcount = 0;
                   1196: 
                   1197:     va_start(arglist, string);
                   1198:     tokptr = va_arg(arglist, char **);
                   1199:     while (tokptr) {
                   1200:        while (*string && isspace((unsigned char) *string))
                   1201:            string++;
                   1202:        if (!*string)
                   1203:            break;
                   1204:        *tokptr = string;
                   1205:        while (*string && !isspace((unsigned char) *string))
                   1206:            string++;
                   1207:        tokptr = va_arg(arglist, char **);
                   1208:        tokcount++;
                   1209:        if (!*string)
                   1210:            break;
                   1211:        *string++ = 0;
                   1212:     }
                   1213:     va_end(arglist);
                   1214: 
                   1215:     return tokcount;
                   1216: }
                   1217: 
                   1218: static int comparef(const void *key1, const void *key2)
                   1219: {
                   1220:     return strcmp(key1, key2);
                   1221: }
                   1222: 
                   1223: static char *dupstring(char *str)
                   1224: {
                   1225:     int sz = strlen(str) + 1;
1.1.1.2 ! misho    1226:     char *new = XCALLOC(MTYPE_ISIS_TMP, sz);
1.1       misho    1227:     if (new)
                   1228:        memcpy(new, str, sz);
                   1229:     return new;
                   1230: }
                   1231: 
                   1232: static dnode_t *new_node(void *c)
                   1233: {
                   1234:     static dnode_t few[5];
                   1235:     static int count;
                   1236: 
                   1237:     if (count < 5)
                   1238:        return few + count++;
                   1239: 
                   1240:     return NULL;
                   1241: }
                   1242: 
                   1243: static void del_node(dnode_t *n, void *c)
                   1244: {
                   1245: }
                   1246: 
                   1247: static int prompt = 0;
                   1248: 
                   1249: static void construct(dict_t *d)
                   1250: {
                   1251:     input_t in;
                   1252:     int done = 0;
                   1253:     dict_load_t dl;
                   1254:     dnode_t *dn;
                   1255:     char *tok1, *tok2, *val;
                   1256:     const char *key;
                   1257:     char *help = 
                   1258:        "p                      turn prompt on\n"
                   1259:        "q                      finish construction\n"
                   1260:        "a <key> <val>          add new entry\n";
                   1261: 
                   1262:     if (!dict_isempty(d))
                   1263:        puts("warning: dictionary not empty!");
                   1264: 
                   1265:     dict_load_begin(&dl, d);
                   1266: 
                   1267:     while (!done) {
                   1268:        if (prompt)
                   1269:            putchar('>');
                   1270:        fflush(stdout);
                   1271: 
                   1272:        if (!fgets(in, sizeof(input_t), stdin))
                   1273:            break;
                   1274: 
                   1275:        switch (in[0]) {
                   1276:            case '?':
                   1277:                puts(help);
                   1278:                break;
                   1279:            case 'p':
                   1280:                prompt = 1;
                   1281:                break;
                   1282:            case 'q':
                   1283:                done = 1;
                   1284:                break;
                   1285:            case 'a':
                   1286:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1287:                    puts("what?");
                   1288:                    break;
                   1289:                }
                   1290:                key = dupstring(tok1);
                   1291:                val = dupstring(tok2);
                   1292:                dn = dnode_create(val);
                   1293: 
                   1294:                if (!key || !val || !dn) {
                   1295:                    puts("out of memory");
                   1296:                    free((void *) key);
                   1297:                    free(val);
                   1298:                    if (dn)
                   1299:                        dnode_destroy(dn);
                   1300:                }
                   1301: 
                   1302:                dict_load_next(&dl, dn, key);
                   1303:                break;
                   1304:            default:
                   1305:                putchar('?');
                   1306:                putchar('\n');
                   1307:                break;
                   1308:        }
                   1309:     }
                   1310: 
                   1311:     dict_load_end(&dl);
                   1312: }
                   1313: 
                   1314: int main(void)
                   1315: {
                   1316:     input_t in;
                   1317:     dict_t darray[10];
                   1318:     dict_t *d = &darray[0];
                   1319:     dnode_t *dn;
                   1320:     int i;
                   1321:     char *tok1, *tok2, *val;
                   1322:     const char *key;
                   1323: 
                   1324:     char *help =
                   1325:        "a <key> <val>          add value to dictionary\n"
                   1326:        "d <key>                delete value from dictionary\n"
                   1327:        "l <key>                lookup value in dictionary\n"
                   1328:        "( <key>                lookup lower bound\n"
                   1329:        ") <key>                lookup upper bound\n"
                   1330:        "# <num>                switch to alternate dictionary (0-9)\n"
                   1331:        "j <num> <num>          merge two dictionaries\n"
                   1332:        "f                      free the whole dictionary\n"
                   1333:        "k                      allow duplicate keys\n"
                   1334:        "c                      show number of entries\n"
                   1335:        "t                      dump whole dictionary in sort order\n"
                   1336:        "m                      make dictionary out of sorted items\n"
                   1337:        "p                      turn prompt on\n"
                   1338:        "s                      switch to non-functioning allocator\n"
                   1339:        "q                      quit";
                   1340: 
1.1.1.2 ! misho    1341:     for (i = 0; i < 10; i++)
1.1       misho    1342:        dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
                   1343: 
                   1344:     for (;;) {
                   1345:        if (prompt)
                   1346:            putchar('>');
                   1347:        fflush(stdout);
                   1348: 
                   1349:        if (!fgets(in, sizeof(input_t), stdin))
                   1350:            break;
                   1351: 
                   1352:        switch(in[0]) {
                   1353:            case '?':
                   1354:                puts(help);
                   1355:                break;
                   1356:            case 'a':
                   1357:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1358:                    puts("what?");
                   1359:                    break;
                   1360:                }
                   1361:                key = dupstring(tok1);
                   1362:                val = dupstring(tok2);
                   1363: 
                   1364:                if (!key || !val) {
                   1365:                    puts("out of memory");
                   1366:                    free((void *) key);
                   1367:                    free(val);
                   1368:                }
                   1369: 
                   1370:                if (!dict_alloc_insert(d, key, val)) {
                   1371:                    puts("dict_alloc_insert failed");
                   1372:                    free((void *) key);
                   1373:                    free(val);
                   1374:                    break;
                   1375:                }
                   1376:                break;
                   1377:            case 'd':
                   1378:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1379:                    puts("what?");
                   1380:                    break;
                   1381:                }
                   1382:                dn = dict_lookup(d, tok1);
                   1383:                if (!dn) {
                   1384:                    puts("dict_lookup failed");
                   1385:                    break;
                   1386:                }
                   1387:                val = dnode_get(dn);
                   1388:                key = dnode_getkey(dn);
                   1389:                dict_delete_free(d, dn);
                   1390: 
                   1391:                free(val);
                   1392:                free((void *) key);
                   1393:                break;
                   1394:            case 'f':
                   1395:                dict_free(d);
                   1396:                break;
                   1397:            case 'l':
                   1398:            case '(':
                   1399:            case ')':
                   1400:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1401:                    puts("what?");
                   1402:                    break;
                   1403:                }
                   1404:                dn = 0;
                   1405:                switch (in[0]) {
                   1406:                case 'l':
                   1407:                    dn = dict_lookup(d, tok1);
                   1408:                    break;
                   1409:                case '(':
                   1410:                    dn = dict_lower_bound(d, tok1);
                   1411:                    break;
                   1412:                case ')':
                   1413:                    dn = dict_upper_bound(d, tok1);
                   1414:                    break;
                   1415:                }
                   1416:                if (!dn) {
                   1417:                    puts("lookup failed");
                   1418:                    break;
                   1419:                }
                   1420:                val = dnode_get(dn);
                   1421:                puts(val);
                   1422:                break;
                   1423:            case 'm':
                   1424:                construct(d);
                   1425:                break;
                   1426:            case 'k':
                   1427:                dict_allow_dupes(d);
                   1428:                break;
                   1429:            case 'c':
                   1430:                printf("%lu\n", (unsigned long) dict_count(d));
                   1431:                break;
                   1432:            case 't':
                   1433:                for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
                   1434:                    printf("%s\t%s\n", (char *) dnode_getkey(dn),
                   1435:                            (char *) dnode_get(dn));
                   1436:                }
                   1437:                break;
                   1438:            case 'q':
                   1439:                exit(0);
                   1440:                break;
                   1441:            case '\0':
                   1442:                break;
                   1443:            case 'p':
                   1444:                prompt = 1;
                   1445:                break;
                   1446:            case 's':
                   1447:                dict_set_allocator(d, new_node, del_node, NULL);
                   1448:                break;
                   1449:            case '#':
                   1450:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1451:                    puts("what?");
                   1452:                    break;
                   1453:                } else {
                   1454:                    int dictnum = atoi(tok1);
                   1455:                    if (dictnum < 0 || dictnum > 9) {
                   1456:                        puts("invalid number");
                   1457:                        break;
                   1458:                    }
                   1459:                    d = &darray[dictnum];
                   1460:                }
                   1461:                break;
                   1462:            case 'j':
                   1463:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1464:                    puts("what?");
                   1465:                    break;
                   1466:                } else {
                   1467:                    int dict1 = atoi(tok1), dict2 = atoi(tok2);
                   1468:                    if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
                   1469:                        puts("invalid number");
                   1470:                        break;
                   1471:                    }
                   1472:                    dict_merge(&darray[dict1], &darray[dict2]);
                   1473:                }
                   1474:                break;
                   1475:            default:
                   1476:                putchar('?');
                   1477:                putchar('\n');
                   1478:                break;
                   1479:        }
                   1480:     }
                   1481: 
                   1482:     return 0;
                   1483: }
                   1484: 
                   1485: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>