Annotation of embedaddon/php/ext/xmlrpc/libxmlrpc/queue.c, revision 1.1.1.1

1.1       misho       1: static const char rcsid[] = "#(@) $Id: queue.c 87765 2002-07-05 04:43:55Z danda $";
                      2: 
                      3: /* 
                      4:  * Date last modified: Jan 2001
                      5:  * Modifications by Dan Libby (dan@libby.com), including:
                      6:  *  - various fixes, null checks, etc
                      7:  *  - addition of Q_Iter funcs, macros
                      8:  */
                      9: 
                     10: 
                     11: /*-**************************************************************
                     12:  *
                     13:  *  File : q.c
                     14:  *
                     15:  *  Author: Peter Yard [1993.01.02] -- 02 Jan 1993
                     16:  *
                     17:  *  Disclaimer: This code is released to the public domain.
                     18:  *
                     19:  *  Description:
                     20:  *      Generic double ended queue (Deque pronounced DEK) for handling
                     21:  *      any data types, with sorting.
                     22:  *
                     23:  *      By use of various functions in this module the caller
                     24:  *      can create stacks, queues, lists, doubly linked lists,
                     25:  *      sorted lists, indexed lists.  All lists are dynamic.
                     26:  *
                     27:  *      It is the responsibility of the caller to malloc and free
                     28:  *      memory for insertion into the queue. A pointer to the object
                     29:  *      is used so that not only can any data be used but various kinds
                     30:  *      of data can be pushed on the same queue if one so wished e.g.
                     31:  *      various length string literals mixed with pointers to structures
                     32:  *      or integers etc.
                     33:  *
                     34:  *  Enhancements:
                     35:  *      A future improvement would be the option of multiple "cursors"
                     36:  *      so that multiple locations could occur in the one queue to allow
                     37:  *      placemarkers and additional flexibility.  Perhaps even use queue
                     38:  *      itself to have a list of cursors.
                     39:  *
                     40:  * Usage:
                     41:  *
                     42:  *          /x init queue x/
                     43:  *          queue  q;
                     44:  *          Q_Init(&q);
                     45:  *
                     46:  *      To create a stack :
                     47:  *
                     48:  *          Q_PushHead(&q, &mydata1); /x push x/
                     49:  *          Q_PushHead(&q, &mydata2);
                     50:  *          .....
                     51:  *          data_ptr = Q_PopHead(&q); /x pop x/
                     52:  *          .....
                     53:  *          data_ptr = Q_Head(&q);   /x top of stack x/
                     54:  *
                     55:  *      To create a FIFO:
                     56:  *
                     57:  *          Q_PushHead(&q, &mydata1);
                     58:  *          .....
                     59:  *          data_ptr = Q_PopTail(&q);
                     60:  *
                     61:  *      To create a double list:
                     62:  *
                     63:  *          data_ptr = Q_Head(&q);
                     64:  *          ....
                     65:  *          data_ptr = Q_Next(&q);
                     66:  *          data_ptr = Q_Tail(&q);
                     67:  *          if (Q_IsEmpty(&q)) ....
                     68:  *          .....
                     69:  *          data_ptr = Q_Previous(&q);
                     70:  *
                     71:  *      To create a sorted list:
                     72:  *
                     73:  *          Q_PushHead(&q, &mydata1); /x push x/
                     74:  *          Q_PushHead(&q, &mydata2);
                     75:  *          .....
                     76:  *          if (!Q_Sort(&q, MyFunction))
                     77:  *              .. error ..
                     78:  *
                     79:  *          /x fill in key field of mydata1.
                     80:  *           * NB: Q_Find does linear search
                     81:  *           x/
                     82:  *
                     83:  *          if (Q_Find(&q, &mydata1, MyFunction))
                     84:  *          {
                     85:  *              /x found it, queue cursor now at correct record x/
                     86:  *              /x can retrieve with x/
                     87:  *              data_ptr = Q_Get(&q);
                     88:  *
                     89:  *              /x alter data , write back with x/
                     90:  *              Q_Put(&q, data_ptr);
                     91:  *          }
                     92:  *
                     93:  *          /x Search with binary search x/
                     94:  *          if (Q_Seek(&q, &mydata, MyFunction))
                     95:  *              /x etc x/
                     96:  *
                     97:  *
                     98:  ****************************************************************/
                     99: 
                    100: #ifdef _WIN32
                    101: #include "xmlrpc_win32.h"
                    102: #endif
                    103: #include <stdlib.h>
                    104: #include "queue.h"
                    105: 
                    106: 
                    107: static void QuickSort(void *list[], int low, int high,
                    108:                       int (*Comp)(const void *, const void *));
                    109: static int  Q_BSearch(queue *q, void *key,
                    110:                       int (*Comp)(const void *, const void *));
                    111: 
                    112: /* The index: a pointer to pointers */
                    113: 
                    114: static  void        **index;
                    115: static  datanode    **posn_index;
                    116: 
                    117: 
                    118: /***
                    119:  *
                    120:  ** function    : Q_Init
                    121:  *
                    122:  ** purpose     : Initialise queue object and pointers.
                    123:  *
                    124:  ** parameters  : 'queue' pointer.
                    125:  *
                    126:  ** returns     : True_ if init successful else False_
                    127:  *
                    128:  ** comments    :
                    129:  ***/
                    130: 
                    131: int Q_Init(queue  *q)
                    132: {
                    133:    if(q) {
                    134:       q->head = q->tail = NULL;
                    135:       q->cursor = q->head;
                    136:       q->size = 0;
                    137:       q->sorted = False_;
                    138:    }
                    139: 
                    140:    return True_;
                    141: }
                    142: 
                    143: /***
                    144:  *
                    145:  ** function    : Q_AtHead
                    146:  *
                    147:  ** purpose     : tests if cursor is at head of queue
                    148:  *
                    149:  ** parameters  : 'queue' pointer.
                    150:  *
                    151:  ** returns     : boolean - True_ is at head else False_
                    152:  *
                    153:  ** comments    :
                    154:  *
                    155:  ***/
                    156: 
                    157: int Q_AtHead(queue *q)
                    158: {
                    159:    return(q && q->cursor == q->head);
                    160: }
                    161: 
                    162: 
                    163: /***
                    164:  *
                    165:  ** function    : Q_AtTail
                    166:  *
                    167:  ** purpose     : boolean test if cursor at tail of queue
                    168:  *
                    169:  ** parameters  : 'queue' pointer to test.
                    170:  *
                    171:  ** returns     : True_ or False_
                    172:  *
                    173:  ** comments    :
                    174:  *
                    175:  ***/
                    176: 
                    177: int Q_AtTail(queue *q)
                    178: {
                    179:    return(q && q->cursor == q->tail);
                    180: }
                    181: 
                    182: 
                    183: /***
                    184:  *
                    185:  ** function    : Q_IsEmpty
                    186:  *
                    187:  ** purpose     : test if queue has nothing in it.
                    188:  *
                    189:  ** parameters  : 'queue' pointer
                    190:  *
                    191:  ** returns     : True_ if IsEmpty queue, else False_
                    192:  *
                    193:  ** comments    :
                    194:  *
                    195:  ***/
                    196: 
                    197: inline int Q_IsEmpty(queue *q)
                    198: {
                    199:    return(!q || q->size == 0);
                    200: }
                    201: 
                    202: /***
                    203:  *
                    204:  ** function    : Q_Size
                    205:  *
                    206:  ** purpose     : return the number of elements in the queue
                    207:  *
                    208:  ** parameters  : queue pointer
                    209:  *
                    210:  ** returns     : number of elements
                    211:  *
                    212:  ** comments    :
                    213:  *
                    214:  ***/
                    215: 
                    216: int Q_Size(queue *q)
                    217: {
                    218:    return q ? q->size : 0;
                    219: }
                    220: 
                    221: 
                    222: /***
                    223:  *
                    224:  ** function    : Q_Head
                    225:  *
                    226:  ** purpose     : position queue cursor to first element (head) of queue.
                    227:  *
                    228:  ** parameters  : 'queue' pointer
                    229:  *
                    230:  ** returns     : pointer to data at head. If queue is IsEmpty returns NULL
                    231:  *
                    232:  ** comments    :
                    233:  *
                    234:  ***/
                    235: 
                    236: void *Q_Head(queue *q)
                    237: {
                    238:    if(Q_IsEmpty(q))
                    239:       return NULL;
                    240: 
                    241:    q->cursor = q->head;
                    242: 
                    243:    return  q->cursor->data;
                    244: }
                    245: 
                    246: 
                    247: /***
                    248:  *
                    249:  ** function    : Q_Tail
                    250:  *
                    251:  ** purpose     : locate cursor at tail of queue.
                    252:  *
                    253:  ** parameters  : 'queue' pointer
                    254:  *
                    255:  ** returns     : pointer to data at tail , if queue IsEmpty returns NULL
                    256:  *
                    257:  ** comments    :
                    258:  *
                    259:  ***/
                    260: 
                    261: void *Q_Tail(queue *q)
                    262: {
                    263:    if(Q_IsEmpty(q))
                    264:       return NULL;
                    265: 
                    266:    q->cursor = q->tail;
                    267: 
                    268:    return  q->cursor->data;
                    269: }
                    270: 
                    271: 
                    272: /***
                    273:  *
                    274:  ** function    : Q_PushHead
                    275:  *
                    276:  ** purpose     : put a data pointer at the head of the queue
                    277:  *
                    278:  ** parameters  : 'queue' pointer, void pointer to the data.
                    279:  *
                    280:  ** returns     : True_ if success else False_ if unable to push data.
                    281:  *
                    282:  ** comments    :
                    283:  *
                    284:  ***/
                    285: 
                    286: int Q_PushHead(queue *q, void *d)
                    287: {
                    288:    if(q && d) {
                    289:       node    *n;
                    290:       datanode *p;
                    291: 
                    292:       p = malloc(sizeof(datanode));
                    293:       if(p == NULL)
                    294:          return False_;
                    295: 
                    296:       n = q->head;
                    297: 
                    298:       q->head = (node*)p;
                    299:       q->head->prev = NULL;
                    300: 
                    301:       if(q->size == 0) {
                    302:          q->head->next = NULL;
                    303:          q->tail = q->head;
                    304:       }
                    305:       else {
                    306:          q->head->next = (datanode*)n;
                    307:          n->prev = q->head;
                    308:       }
                    309: 
                    310:       q->head->data = d;
                    311:       q->size++;
                    312: 
                    313:       q->cursor = q->head;
                    314: 
                    315:       q->sorted = False_;
                    316: 
                    317:       return True_;
                    318:    }
                    319:    return False_;
                    320: }
                    321: 
                    322: 
                    323: 
                    324: /***
                    325:  *
                    326:  ** function    : Q_PushTail
                    327:  *
                    328:  ** purpose     : put a data element pointer at the tail of the queue
                    329:  *
                    330:  ** parameters  : queue pointer, pointer to the data
                    331:  *
                    332:  ** returns     : True_ if data pushed, False_ if data not inserted.
                    333:  *
                    334:  ** comments    :
                    335:  *
                    336:  ***/
                    337: 
                    338: int Q_PushTail(queue *q, void *d)
                    339: {
                    340:    if(q && d) {
                    341:       node        *p;
                    342:       datanode    *n;
                    343: 
                    344:       n = malloc(sizeof(datanode));
                    345:       if(n == NULL)
                    346:          return False_;
                    347: 
                    348:       p = q->tail;
                    349:       q->tail = (node *)n;
                    350: 
                    351:       if(q->size == 0) {
                    352:          q->tail->prev = NULL;
                    353:          q->head = q->tail;
                    354:       }
                    355:       else {
                    356:          q->tail->prev = (datanode *)p;
                    357:          p->next = q->tail;
                    358:       }
                    359: 
                    360:       q->tail->next = NULL;
                    361: 
                    362:       q->tail->data =  d;
                    363:       q->cursor = q->tail;
                    364:       q->size++;
                    365: 
                    366:       q->sorted = False_;
                    367: 
                    368:       return True_;
                    369:    }
                    370:    return False_;
                    371: }
                    372: 
                    373: 
                    374: 
                    375: /***
                    376:  *
                    377:  ** function    : Q_PopHead
                    378:  *
                    379:  ** purpose     : remove and return the top element at the head of the
                    380:  *                queue.
                    381:  *
                    382:  ** parameters  : queue pointer
                    383:  *
                    384:  ** returns     : pointer to data element or NULL if queue is IsEmpty.
                    385:  *
                    386:  ** comments    :
                    387:  *
                    388:  ***/
                    389: 
                    390: void *Q_PopHead(queue *q)
                    391: {
                    392:    datanode    *n;
                    393:    void        *d;
                    394: 
                    395:    if(Q_IsEmpty(q))
                    396:       return NULL;
                    397: 
                    398:    d = q->head->data;
                    399:    n = q->head->next;
                    400:    free(q->head);
                    401: 
                    402:    q->size--;
                    403: 
                    404:    if(q->size == 0)
                    405:       q->head = q->tail = q->cursor = NULL;
                    406:    else {
                    407:       q->head = (node *)n;
                    408:       q->head->prev = NULL;
                    409:       q->cursor = q->head;
                    410:    }
                    411: 
                    412:    q->sorted = False_;
                    413: 
                    414:    return d;
                    415: }
                    416: 
                    417: 
                    418: /***
                    419:  *
                    420:  ** function    : Q_PopTail
                    421:  *
                    422:  ** purpose     : remove element from tail of queue and return data.
                    423:  *
                    424:  ** parameters  : queue pointer
                    425:  *
                    426:  ** returns     : pointer to data element that was at tail. NULL if queue
                    427:  *                IsEmpty.
                    428:  *
                    429:  ** comments    :
                    430:  *
                    431:  ***/
                    432: 
                    433: void *Q_PopTail(queue *q)
                    434: {
                    435:    datanode    *p;
                    436:    void        *d;
                    437: 
                    438:    if(Q_IsEmpty(q))
                    439:       return NULL;
                    440: 
                    441:    d = q->tail->data;
                    442:    p = q->tail->prev;
                    443:    free(q->tail);
                    444:    q->size--;
                    445: 
                    446:    if(q->size == 0)
                    447:       q->head = q->tail = q->cursor = NULL;
                    448:    else {
                    449:       q->tail = (node *)p;
                    450:       q->tail->next = NULL;
                    451:       q->cursor = q->tail;
                    452:    }
                    453: 
                    454:    q->sorted = False_;
                    455: 
                    456:    return d;
                    457: }
                    458: 
                    459: 
                    460: 
                    461: /***
                    462:  *
                    463:  ** function    : Q_Next
                    464:  *
                    465:  ** purpose     : Move to the next element in the queue without popping
                    466:  *
                    467:  ** parameters  : queue pointer.
                    468:  *
                    469:  ** returns     : pointer to data element of new element or NULL if end
                    470:  *                of the queue.
                    471:  *
                    472:  ** comments    : This uses the cursor for the current position. Q_Next
                    473:  *                only moves in the direction from the head of the queue
                    474:  *                to the tail.
                    475:  ***/
                    476: 
                    477: void *Q_Next(queue *q)
                    478: {
                    479:    if(!q)
                    480:       return NULL;
                    481: 
                    482:    if(!q->cursor || q->cursor->next == NULL)
                    483:       return NULL;
                    484: 
                    485:    q->cursor = (node *)q->cursor->next;
                    486: 
                    487:    return  q->cursor->data ;
                    488: }
                    489: 
                    490: 
                    491: 
                    492: /***
                    493:  *
                    494:  ** function    : Q_Previous
                    495:  *
                    496:  ** purpose     : Opposite of Q_Next. Move to next element closer to the
                    497:  *                head of the queue.
                    498:  *
                    499:  ** parameters  : pointer to queue
                    500:  *
                    501:  ** returns     : pointer to data of new element else NULL if queue IsEmpty
                    502:  *
                    503:  ** comments    : Makes cursor move towards the head of the queue.
                    504:  *
                    505:  ***/
                    506: 
                    507: void *Q_Previous(queue *q)
                    508: {
                    509:    if(!q)
                    510:       return NULL;
                    511:    
                    512:    if(q->cursor->prev == NULL)
                    513:       return NULL;
                    514: 
                    515:    q->cursor = (node *)q->cursor->prev;
                    516: 
                    517:    return q->cursor->data;
                    518: }
                    519: 
                    520: 
                    521: void *Q_Iter_Del(queue *q, q_iter iter)
                    522: {
                    523:    void        *d;
                    524:    datanode    *n, *p;
                    525: 
                    526:    if(!q)
                    527:       return NULL;
                    528: 
                    529:    if(iter == NULL)
                    530:       return NULL;
                    531: 
                    532:    if(iter == (q_iter)q->head)
                    533:       return Q_PopHead(q);
                    534: 
                    535:    if(iter == (q_iter)q->tail)
                    536:       return Q_PopTail(q);
                    537: 
                    538:    n = ((node*)iter)->next;
                    539:    p = ((node*)iter)->prev;
                    540:    d = ((node*)iter)->data;
                    541: 
                    542:    free(iter);
                    543: 
                    544:    if(p) {
                    545:       p->next = n;
                    546:    }
                    547:    if (q->cursor == (node*)iter) {
                    548:       if (p) {
                    549:          q->cursor = p;
                    550:       } else {
                    551:          q->cursor = n;
                    552:       }
                    553:    }
                    554: 
                    555: 
                    556:    if (n != NULL) {
                    557:        n->prev = p;
                    558:    }
                    559: 
                    560:    q->size--;
                    561: 
                    562:    q->sorted = False_;
                    563: 
                    564:    return d;
                    565: }
                    566: 
                    567: 
                    568: 
                    569: /***
                    570:  *
                    571:  ** function    : Q_DelCur
                    572:  *
                    573:  ** purpose     : Delete the current queue element as pointed to by
                    574:  *                the cursor.
                    575:  *
                    576:  ** parameters  : queue pointer
                    577:  *
                    578:  ** returns     : pointer to data element.
                    579:  *
                    580:  ** comments    : WARNING! It is the responsibility of the caller to
                    581:  *                free any memory. Queue cannot distinguish between
                    582:  *                pointers to literals and malloced memory.
                    583:  *
                    584:  ***/
                    585: 
                    586: void *Q_DelCur(queue* q) {
                    587:    if(q) {
                    588:       return Q_Iter_Del(q, (q_iter)q->cursor);
                    589:    }
                    590:    return 0;
                    591: }
                    592: 
                    593: 
                    594: /***
                    595:  *
                    596:  ** function    : Q_Destroy
                    597:  *
                    598:  ** purpose     : Free all queue resources
                    599:  *
                    600:  ** parameters  : queue pointer
                    601:  *
                    602:  ** returns     : null.
                    603:  *
                    604:  ** comments    : WARNING! It is the responsibility of the caller to
                    605:  *                free any memory. Queue cannot distinguish between
                    606:  *                pointers to literals and malloced memory.
                    607:  *
                    608:  ***/
                    609: 
                    610: void Q_Destroy(queue *q)
                    611: {
                    612:    while(!Q_IsEmpty(q)) {
                    613:       Q_PopHead(q);
                    614:    }
                    615: }
                    616: 
                    617: 
                    618: /***
                    619:  *
                    620:  ** function    : Q_Get
                    621:  *
                    622:  ** purpose     : get the pointer to the data at the cursor location
                    623:  *
                    624:  ** parameters  : queue pointer
                    625:  *
                    626:  ** returns     : data element pointer
                    627:  *
                    628:  ** comments    :
                    629:  *
                    630:  ***/
                    631: 
                    632: void *Q_Get(queue *q)
                    633: {
                    634:    if(!q)
                    635:       return NULL;
                    636: 
                    637:    if(q->cursor == NULL)
                    638:       return NULL;
                    639:    return q->cursor->data;
                    640: }
                    641: 
                    642: 
                    643: 
                    644: /***
                    645:  *
                    646:  ** function    : Q_Put
                    647:  *
                    648:  ** purpose     : replace pointer to data with new pointer to data.
                    649:  *
                    650:  ** parameters  : queue pointer, data pointer
                    651:  *
                    652:  ** returns     : boolean- True_ if successful, False_ if cursor at NULL
                    653:  *
                    654:  ** comments    :
                    655:  *
                    656:  ***/
                    657: 
                    658: int Q_Put(queue *q, void *data)
                    659: {
                    660:    if(q && data) {
                    661:       if(q->cursor == NULL)
                    662:          return False_;
                    663: 
                    664:       q->cursor->data = data;
                    665:       return True_;
                    666:    }
                    667:    return False_;
                    668: }
                    669: 
                    670: 
                    671: /***
                    672:  *
                    673:  ** function    : Q_Find
                    674:  *
                    675:  ** purpose     : Linear search of queue for match with key in *data
                    676:  *
                    677:  ** parameters  : queue pointer q, data pointer with data containing key
                    678:  *                comparison function here called Comp.
                    679:  *
                    680:  ** returns     : True_ if found , False_ if not in queue.
                    681:  *
                    682:  ** comments    : Useful for small queues that are constantly changing
                    683:  *                and would otherwise need constant sorting with the
                    684:  *                Q_Seek function.
                    685:  *                For description of Comp see Q_Sort.
                    686:  *                Queue cursor left on position found item else at end.
                    687:  *
                    688:  ***/
                    689: 
                    690: int Q_Find(queue *q, void *data,
                    691:            int (*Comp)(const void *, const void *))
                    692: {
                    693:    void *d;
                    694: 
                    695:    if (q == NULL) {
                    696:        return False_;
                    697:    }
                    698: 
                    699:    d = Q_Head(q);
                    700:    do {
                    701:       if(Comp(d, data) == 0)
                    702:          return True_;
                    703:       d = Q_Next(q);
                    704:    } while(!Q_AtTail(q));
                    705: 
                    706:    if(Comp(d, data) == 0)
                    707:       return True_;
                    708: 
                    709:    return False_;
                    710: }
                    711: 
                    712: /*========  Sorted Queue and Index functions   ========= */
                    713: 
                    714: 
                    715: static void QuickSort(void *list[], int low, int high,
                    716:                       int (*Comp)(const void *, const void *))
                    717: {
                    718:    int     flag = 1, i, j;
                    719:    void    *key, *temp;
                    720: 
                    721:    if(low < high) {
                    722:       i = low;
                    723:       j = high + 1;
                    724: 
                    725:       key = list[ low ];
                    726: 
                    727:       while(flag) {
                    728:          i++;
                    729:          while(Comp(list[i], key) < 0)
                    730:             i++;
                    731: 
                    732:          j--;
                    733:          while(Comp(list[j], key) > 0)
                    734:             j--;
                    735: 
                    736:          if(i < j) {
                    737:             temp = list[i];
                    738:             list[i] = list[j];
                    739:             list[j] = temp;
                    740:          }
                    741:          else  flag = 0;
                    742:       }
                    743: 
                    744:       temp = list[low];
                    745:       list[low] = list[j];
                    746:       list[j] = temp;
                    747: 
                    748:       QuickSort(list, low, j-1, Comp);
                    749:       QuickSort(list, j+1, high, Comp);
                    750:    }
                    751: }
                    752: 
                    753: 
                    754: /***
                    755:  *
                    756:  ** function    : Q_Sort
                    757:  *
                    758:  ** purpose     : sort the queue and allow index style access.
                    759:  *
                    760:  ** parameters  : queue pointer, comparison function compatible with
                    761:  *                with 'qsort'.
                    762:  *
                    763:  ** returns     : True_ if sort succeeded. False_ if error occurred.
                    764:  *
                    765:  ** comments    : Comp function supplied by caller must return
                    766:  *                  -1 if data1  < data2
                    767:  *                   0 if data1 == data2
                    768:  *                  +1 if data1  > data2
                    769:  *
                    770:  *                    for Comp(data1, data2)
                    771:  *
                    772:  *                If queue is already sorted it frees the memory of the
                    773:  *                old index and starts again.
                    774:  *
                    775:  ***/
                    776: 
                    777: int Q_Sort(queue *q, int (*Comp)(const void *, const void *))
                    778: {
                    779:    int         i;
                    780:    void        *d;
                    781:    datanode    *dn;
                    782: 
                    783:    /* if already sorted free memory for tag array */
                    784: 
                    785:    if(q->sorted) {
                    786:       free(index);
                    787:       free(posn_index);
                    788:       q->sorted = False_;
                    789:    }
                    790: 
                    791:    /* Now allocate memory of array, array of pointers */
                    792: 
                    793:    index = malloc(q->size * sizeof(q->cursor->data));
                    794:    if(index == NULL)
                    795:       return False_;
                    796: 
                    797:    posn_index = malloc(q->size * sizeof(q->cursor));
                    798:    if(posn_index == NULL) {
                    799:       free(index);
                    800:       return False_;
                    801:    }
                    802: 
                    803:    /* Walk queue putting pointers into array */
                    804: 
                    805:    d = Q_Head(q);
                    806:    for(i=0; i < q->size; i++) {
                    807:       index[i] = d;
                    808:       posn_index[i] = q->cursor;
                    809:       d = Q_Next(q);
                    810:    }
                    811: 
                    812:    /* Now sort the index */
                    813: 
                    814:    QuickSort(index, 0, q->size - 1, Comp);
                    815: 
                    816:    /* Rearrange the actual queue into correct order */
                    817: 
                    818:    dn = q->head;
                    819:    i = 0;
                    820:    while(dn != NULL) {
                    821:       dn->data = index[i++];
                    822:       dn = dn->next;
                    823:    }
                    824: 
                    825:    /* Re-position to original element */
                    826: 
                    827:    if(d != NULL)
                    828:       Q_Find(q, d, Comp);
                    829:    else  Q_Head(q);
                    830: 
                    831:    q->sorted = True_;
                    832: 
                    833:    return True_;
                    834: }
                    835: 
                    836: 
                    837: /***
                    838:  *
                    839:  ** function    : Q_BSearch
                    840:  *
                    841:  ** purpose     : binary search of queue index for node containing key
                    842:  *
                    843:  ** parameters  : queue pointer 'q', data pointer of key 'key',
                    844:  *                  Comp comparison function.
                    845:  *
                    846:  ** returns     : integer index into array of node pointers,
                    847:  *                or -1 if not found.
                    848:  *
                    849:  ** comments    : see Q_Sort for description of 'Comp' function.
                    850:  *
                    851:  ***/
                    852: 
                    853: static int Q_BSearch( queue *q, void *key,
                    854:                       int (*Comp)(const void *, const void*))
                    855: {
                    856:    int low, mid, hi, val;
                    857: 
                    858:    low = 0;
                    859:    hi = q->size - 1;
                    860: 
                    861:    while(low <= hi) {
                    862:       mid = (low + hi) / 2;
                    863:       val = Comp(key, index[ mid ]);
                    864: 
                    865:       if(val < 0)
                    866:          hi = mid - 1;
                    867: 
                    868:       else if(val > 0)
                    869:          low = mid + 1;
                    870: 
                    871:       else /* Success */
                    872:          return mid;
                    873:    }
                    874: 
                    875:    /* Not Found */
                    876: 
                    877:    return -1;
                    878: }
                    879: 
                    880: 
                    881: /***
                    882:  *
                    883:  ** function    : Q_Seek
                    884:  *
                    885:  ** purpose     : use index to locate data according to key in 'data'
                    886:  *
                    887:  ** parameters  : queue pointer 'q', data pointer 'data', Comp comparison
                    888:  *                function.
                    889:  *
                    890:  ** returns     : pointer to data or NULL if could not find it or could
                    891:  *                not sort queue.
                    892:  *
                    893:  ** comments    : see Q_Sort for description of 'Comp' function.
                    894:  *
                    895:  ***/
                    896: 
                    897: void *Q_Seek(queue *q, void *data, int (*Comp)(const void *, const void *))
                    898: {
                    899:    int idx;
                    900: 
                    901:    if (q == NULL) {
                    902:        return NULL;
                    903:    }
                    904: 
                    905:    if(!q->sorted) {
                    906:       if(!Q_Sort(q, Comp))
                    907:          return NULL;
                    908:    }
                    909: 
                    910:    idx = Q_BSearch(q, data, Comp);
                    911: 
                    912:    if(idx < 0)
                    913:       return NULL;
                    914: 
                    915:    q->cursor = posn_index[idx];
                    916: 
                    917:    return index[idx];
                    918: }
                    919: 
                    920: 
                    921: 
                    922: /***
                    923:  *
                    924:  ** function    : Q_Insert
                    925:  *
                    926:  ** purpose     : Insert an element into an indexed queue
                    927:  *
                    928:  ** parameters  : queue pointer 'q', data pointer 'data', Comp comparison
                    929:  *                function.
                    930:  *
                    931:  ** returns     : pointer to data or NULL if could not find it or could
                    932:  *                not sort queue.
                    933:  *
                    934:  ** comments    : see Q_Sort for description of 'Comp' function.
                    935:  *                WARNING! This code can be very slow since each new
                    936:  *                element means a new Q_Sort.  Should only be used for
                    937:  *                the insertion of the odd element ,not the piecemeal
                    938:  *                building of an entire queue.
                    939:  ***/
                    940: 
                    941: int Q_Insert(queue *q, void *data, int (*Comp)(const void *, const void *))
                    942: {
                    943:    if (q == NULL) {
                    944:        return False_;
                    945:    }
                    946: 
                    947:    Q_PushHead(q, data);
                    948: 
                    949:    if(!Q_Sort(q, Comp))
                    950:       return False_;
                    951: 
                    952:    return True_;
                    953: }
                    954: 
                    955: /* read only funcs for iterating through queue. above funcs modify queue */
                    956: q_iter Q_Iter_Head(queue *q) {
                    957:    return q ? (q_iter)q->head : NULL;
                    958: }
                    959: 
                    960: q_iter Q_Iter_Tail(queue *q) {
                    961:    return q ? (q_iter)q->tail : NULL;
                    962: }
                    963: 
                    964: q_iter Q_Iter_Next(q_iter qi) {
                    965:    return qi ? (q_iter)((node*)qi)->next : NULL;
                    966: }
                    967: 
                    968: q_iter Q_Iter_Prev(q_iter qi) {
                    969:    return qi ? (q_iter)((node*)qi)->prev : NULL;
                    970: }
                    971: 
                    972: void * Q_Iter_Get(q_iter qi) {
                    973:    return qi ? ((node*)qi)->data : NULL;
                    974: }
                    975: 
                    976: int Q_Iter_Put(q_iter qi, void* data) {
                    977:    if(qi) {
                    978:       ((node*)qi)->data = data;
                    979:       return True_;
                    980:    }
                    981:    return False_;
                    982: }

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