Annotation of embedaddon/php/ext/xmlrpc/libxmlrpc/queue.c, revision 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>