]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/array.c
Merge changes from CUPS 1.4svn-r7394.
[thirdparty/cups.git] / cups / array.c
CommitLineData
ef416fc2 1/*
bc44d920 2 * "$Id: array.c 6649 2007-07-11 21:46:42Z mike $"
ef416fc2 3 *
4 * Sorted array routines for the Common UNIX Printing System (CUPS).
5 *
5a738aea 6 * Copyright 2007-2008 by Apple Inc.
b94498cf 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
f7deaa1a 19 * cupsArrayAdd() - Add an element to the array.
20 * cupsArrayClear() - Clear the array.
21 * cupsArrayCount() - Get the number of elements in the array.
22 * cupsArrayCurrent() - Return the current element in the array.
23 * cupsArrayDelete() - Free all memory used by the array.
24 * cupsArrayDup() - Duplicate the array.
25 * cupsArrayFind() - Find an element in the array.
26 * cupsArrayFirst() - Get the first element in the array.
27 * cupsArrayGetIndex() - Get the index of the current element.
28 * cupsArrayGetInsert() - Get the index of the last inserted element.
29 * cupsArrayIndex() - Get the N-th element in the array.
30 * cupsArrayInsert() - Insert an element in the array.
31 * cupsArrayLast() - Get the last element in the array.
32 * cupsArrayNew() - Create a new array.
33 * cupsArrayNext() - Get the next element in the array.
34 * cupsArrayPrev() - Get the previous element in the array.
35 * cupsArrayRemove() - Remove an element from the array.
36 * cupsArrayRestore() - Reset the current element to the last cupsArraySave.
37 * cupsArraySave() - Mark the current element for a later
38 * cupsArrayRestore.
39 * cupsArrayUserData() - Return the user data for an array.
40 * cups_array_add() - Insert or append an element to the array...
41 * cups_array_find() - Find an element in the array...
ef416fc2 42 */
43
44/*
45 * Include necessary headers...
46 */
47
48#include "array.h"
49#include "string.h"
50#include "debug.h"
51
52
53/*
54 * Limits...
55 */
56
57#define _CUPS_MAXSAVE 32 /**** Maximum number of saves ****/
58
59
60/*
61 * Types and structures...
62 */
63
64struct _cups_array_s /**** CUPS array structure ****/
65{
66 /*
67 * The current implementation uses an insertion sort into an array of
68 * sorted pointers. We leave the array type private/opaque so that we
69 * can change the underlying implementation without affecting the users
70 * of this API.
71 */
72
73 int num_elements, /* Number of array elements */
74 alloc_elements, /* Allocated array elements */
75 current, /* Current element */
76 insert, /* Last inserted element */
bd7854cb 77 unique, /* Are all elements unique? */
ef416fc2 78 num_saved, /* Number of saved elements */
79 saved[_CUPS_MAXSAVE];
80 /* Saved elements */
81 void **elements; /* Array elements */
82 cups_array_func_t compare; /* Element comparison function */
83 void *data; /* User data passed to compare */
b94498cf 84 cups_ahash_func_t hashfunc; /* Hash function */
85 int hashsize, /* Size of hash */
86 *hash; /* Hash array */
ef416fc2 87};
88
89
90/*
91 * Local functions...
92 */
93
bd7854cb 94static int cups_array_add(cups_array_t *a, void *e, int insert);
95static int cups_array_find(cups_array_t *a, void *e, int prev, int *rdiff);
ef416fc2 96
97
98/*
99 * 'cupsArrayAdd()' - Add an element to the array.
bd7854cb 100 *
101 * When adding an element to a sorted array, non-unique elements are
102 * appended at the end of the run. For unsorted arrays, the element
103 * is inserted at the end of the array.
5a738aea
MS
104 *
105 * @since CUPS 1.2@
ef416fc2 106 */
107
108int /* O - 1 on success, 0 on failure */
109cupsArrayAdd(cups_array_t *a, /* I - Array */
110 void *e) /* I - Element */
111{
ef416fc2 112 DEBUG_printf(("cupsArrayAdd(a=%p, e=%p)\n", a, e));
113
114 /*
115 * Range check input...
116 */
117
118 if (!a || !e)
119 {
120 DEBUG_puts("cupsArrayAdd: returning 0");
121 return (0);
122 }
123
124 /*
bd7854cb 125 * Append the element...
ef416fc2 126 */
127
bd7854cb 128 return (cups_array_add(a, e, 0));
ef416fc2 129}
130
131
132/*
133 * 'cupsArrayClear()' - Clear the array.
5a738aea
MS
134 *
135 * @since CUPS 1.2@
ef416fc2 136 */
137
138void
139cupsArrayClear(cups_array_t *a) /* I - Array */
140{
141 /*
142 * Range check input...
143 */
144
145 if (!a)
146 return;
147
148 /*
149 * Set the number of elements to 0; we don't actually free the memory
150 * here - that is done in cupsArrayDelete()...
151 */
152
153 a->num_elements = 0;
154 a->current = -1;
155 a->insert = -1;
bd7854cb 156 a->unique = 1;
ef416fc2 157 a->num_saved = 0;
158}
159
160
161/*
162 * 'cupsArrayCount()' - Get the number of elements in the array.
5a738aea
MS
163 *
164 * @since CUPS 1.2@
ef416fc2 165 */
166
167int /* O - Number of elements */
168cupsArrayCount(cups_array_t *a) /* I - Array */
169{
170 /*
171 * Range check input...
172 */
173
174 if (!a)
175 return (0);
176
177 /*
178 * Return the number of elements...
179 */
180
181 return (a->num_elements);
182}
183
184
185/*
186 * 'cupsArrayCurrent()' - Return the current element in the array.
5a738aea
MS
187 *
188 * @since CUPS 1.2@
ef416fc2 189 */
190
191void * /* O - Element */
192cupsArrayCurrent(cups_array_t *a) /* I - Array */
193{
194 /*
195 * Range check input...
196 */
197
198 if (!a)
199 return (NULL);
200
201 /*
202 * Return the current element...
203 */
204
205 if (a->current >= 0 && a->current < a->num_elements)
206 return (a->elements[a->current]);
207 else
208 return (NULL);
209}
210
211
212/*
213 * 'cupsArrayDelete()' - Free all memory used by the array.
5a738aea
MS
214 *
215 * @since CUPS 1.2@
ef416fc2 216 */
217
218void
219cupsArrayDelete(cups_array_t *a) /* I - Array */
220{
221 /*
222 * Range check input...
223 */
224
225 if (!a)
226 return;
227
228 /*
229 * Free the array of element pointers - the caller is responsible
230 * for freeing the elements themselves...
231 */
232
233 if (a->alloc_elements)
234 free(a->elements);
235
b94498cf 236 if (a->hashsize)
237 free(a->hash);
238
ef416fc2 239 free(a);
240}
241
242
243/*
244 * 'cupsArrayDup()' - Duplicate the array.
5a738aea
MS
245 *
246 * @since CUPS 1.2@
ef416fc2 247 */
248
249cups_array_t * /* O - Duplicate array */
250cupsArrayDup(cups_array_t *a) /* I - Array */
251{
252 cups_array_t *da; /* Duplicate array */
253
254
255 /*
256 * Range check input...
257 */
258
259 if (!a)
260 return (NULL);
261
262 /*
263 * Allocate memory for the array...
264 */
265
266 da = calloc(1, sizeof(cups_array_t));
267 if (!da)
268 return (NULL);
269
270 da->compare = a->compare;
271 da->data = a->data;
272 da->current = a->current;
273 da->insert = a->insert;
bd7854cb 274 da->unique = a->unique;
ef416fc2 275 da->num_saved = a->num_saved;
276
277 memcpy(da->saved, a->saved, sizeof(a->saved));
278
279 if (a->num_elements)
280 {
281 /*
282 * Allocate memory for the elements...
283 */
284
285 da->elements = malloc(a->num_elements * sizeof(void *));
286 if (!da->elements)
287 {
288 free(da);
289 return (NULL);
290 }
291
292 /*
293 * Copy the element pointers...
294 */
295
296 memcpy(da->elements, a->elements, a->num_elements * sizeof(void *));
297 da->num_elements = a->num_elements;
298 da->alloc_elements = a->num_elements;
299 }
300
301 /*
302 * Return the new array...
303 */
304
305 return (da);
306}
307
308
309/*
310 * 'cupsArrayFind()' - Find an element in the array.
5a738aea
MS
311 *
312 * @since CUPS 1.2@
ef416fc2 313 */
314
5a738aea 315void * /* O - Element found or @code NULL@ */
ef416fc2 316cupsArrayFind(cups_array_t *a, /* I - Array */
317 void *e) /* I - Element */
318{
319 int current, /* Current element */
b94498cf 320 diff, /* Difference */
321 hash; /* Hash index */
ef416fc2 322
323
324 /*
325 * Range check input...
326 */
327
328 if (!a || !e)
329 return (NULL);
330
331 /*
332 * See if we have any elements...
333 */
334
335 if (!a->num_elements)
336 return (NULL);
337
338 /*
339 * Yes, look for a match...
340 */
341
b94498cf 342 if (a->hash)
343 {
344 hash = (*(a->hashfunc))(e, a->data);
345
346 if (hash < 0 || hash >= a->hashsize)
347 {
348 current = a->current;
349 hash = -1;
350 }
351 else
352 {
353 current = a->hash[hash];
354
355 if (current < 0 || current >= a->num_elements)
356 current = a->current;
357 }
358 }
359 else
360 {
361 current = a->current;
362 hash = -1;
363 }
364
365 current = cups_array_find(a, e, current, &diff);
ef416fc2 366 if (!diff)
367 {
368 /*
bd7854cb 369 * Found a match! If the array does not contain unique values, find
370 * the first element that is the same...
ef416fc2 371 */
372
bd7854cb 373 if (!a->unique && a->compare)
374 {
375 /*
376 * The array is not unique, find the first match...
377 */
378
379 while (current > 0 && !(*(a->compare))(e, a->elements[current - 1],
380 a->data))
381 current --;
382 }
383
ef416fc2 384 a->current = current;
385
b94498cf 386 if (hash >= 0)
387 a->hash[hash] = current;
388
ef416fc2 389 return (a->elements[current]);
390 }
391 else
392 {
393 /*
394 * No match...
395 */
396
397 a->current = -1;
398
399 return (NULL);
400 }
401}
402
403
404/*
405 * 'cupsArrayFirst()' - Get the first element in the array.
5a738aea
MS
406 *
407 * @since CUPS 1.2@
ef416fc2 408 */
409
5a738aea 410void * /* O - First element or @code NULL@ */
ef416fc2 411cupsArrayFirst(cups_array_t *a) /* I - Array */
412{
413 /*
414 * Range check input...
415 */
416
417 if (!a)
418 return (NULL);
419
420 /*
421 * Return the first element...
422 */
423
424 a->current = 0;
425
426 return (cupsArrayCurrent(a));
427}
428
429
f7deaa1a 430/*
431 * 'cupsArrayGetIndex()' - Get the index of the current element.
432 *
433 * @since CUPS 1.3@
434 */
435
436int /* O - Index of the current element */
437cupsArrayGetIndex(cups_array_t *a) /* I - Array */
438{
439 if (!a)
440 return (-1);
441 else
442 return (a->current);
443}
444
445
446/*
447 * 'cupsArrayGetInsert()' - Get the index of the last inserted element.
448 *
449 * @since CUPS 1.3@
450 */
451
452int /* O - Index of the last inserted element */
453cupsArrayGetInsert(cups_array_t *a) /* I - Array */
454{
455 if (!a)
456 return (-1);
457 else
458 return (a->insert);
459}
460
461
ef416fc2 462/*
463 * 'cupsArrayIndex()' - Get the N-th element in the array.
5a738aea
MS
464 *
465 * @since CUPS 1.2@
ef416fc2 466 */
467
5a738aea 468void * /* O - N-th element or @code NULL@ */
ef416fc2 469cupsArrayIndex(cups_array_t *a, /* I - Array */
470 int n) /* I - Index into array, starting at 0 */
471{
472 if (!a)
473 return (NULL);
474
475 a->current = n;
476
477 return (cupsArrayCurrent(a));
478}
479
480
fa73b229 481/*
482 * 'cupsArrayInsert()' - Insert an element in the array.
483 *
bd7854cb 484 * When inserting an element in a sorted array, non-unique elements are
485 * inserted at the beginning of the run. For unsorted arrays, the element
486 * is inserted at the beginning of the array.
5a738aea
MS
487 *
488 * @since CUPS 1.2@
fa73b229 489 */
490
491int /* O - 0 on failure, 1 on success */
492cupsArrayInsert(cups_array_t *a, /* I - Array */
493 void *e) /* I - Element */
494{
fa73b229 495 DEBUG_printf(("cupsArrayInsert(a=%p, e=%p)\n", a, e));
496
497 /*
498 * Range check input...
499 */
500
501 if (!a || !e)
502 {
503 DEBUG_puts("cupsArrayInsert: returning 0");
504 return (0);
505 }
506
fa73b229 507 /*
508 * Insert the element...
509 */
510
bd7854cb 511 return (cups_array_add(a, e, 1));
fa73b229 512}
513
514
ef416fc2 515/*
516 * 'cupsArrayLast()' - Get the last element in the array.
5a738aea
MS
517 *
518 * @since CUPS 1.2@
ef416fc2 519 */
520
5a738aea 521void * /* O - Last element or @code NULL@ */
ef416fc2 522cupsArrayLast(cups_array_t *a) /* I - Array */
523{
524 /*
525 * Range check input...
526 */
527
528 if (!a)
529 return (NULL);
530
531 /*
532 * Return the last element...
533 */
534
535 a->current = a->num_elements - 1;
536
537 return (cupsArrayCurrent(a));
538}
539
540
541/*
542 * 'cupsArrayNew()' - Create a new array.
5a738aea
MS
543 *
544 * @since CUPS 1.2@
ef416fc2 545 */
546
547cups_array_t * /* O - Array */
548cupsArrayNew(cups_array_func_t f, /* I - Comparison function */
549 void *d) /* I - User data */
b94498cf 550{
551 return (cupsArrayNew2(f, d, 0, 0));
552}
553
554
555/*
556 * 'cupsArrayNew2()' - Create a new array with hash.
557 *
558 * @since CUPS 1.3@
559 */
560
561cups_array_t * /* O - Array */
562cupsArrayNew2(cups_array_func_t f, /* I - Comparison function */
563 void *d, /* I - User data */
564 cups_ahash_func_t h, /* I - Hash function*/
565 int hsize) /* I - Hash size */
ef416fc2 566{
567 cups_array_t *a; /* Array */
568
569
570 /*
571 * Allocate memory for the array...
572 */
573
574 a = calloc(1, sizeof(cups_array_t));
575 if (!a)
576 return (NULL);
577
578 a->compare = f;
579 a->data = d;
580 a->current = -1;
581 a->insert = -1;
582 a->num_saved = 0;
bd7854cb 583 a->unique = 1;
ef416fc2 584
b94498cf 585 if (hsize > 0 && h)
586 {
587 a->hashfunc = h;
588 a->hashsize = hsize;
589 a->hash = malloc(hsize * sizeof(int));
590
591 if (!a->hash)
592 {
593 free(a);
594 return (NULL);
595 }
596
597 memset(a->hash, -1, hsize * sizeof(int));
598 }
599
ef416fc2 600 return (a);
601}
602
603
604/*
605 * 'cupsArrayNext()' - Get the next element in the array.
5a738aea
MS
606 *
607 * @since CUPS 1.2@
ef416fc2 608 */
609
5a738aea 610void * /* O - Next element or @code NULL@ */
ef416fc2 611cupsArrayNext(cups_array_t *a) /* I - Array */
612{
613 /*
614 * Range check input...
615 */
616
617 if (!a)
618 return (NULL);
619
620 /*
621 * Return the next element...
622 */
623
624 if (a->current < a->num_elements)
625 a->current ++;
626
627 return (cupsArrayCurrent(a));
628}
629
630
631/*
632 * 'cupsArrayPrev()' - Get the previous element in the array.
5a738aea
MS
633 *
634 * @since CUPS 1.2@
ef416fc2 635 */
636
5a738aea 637void * /* O - Previous element or @code NULL@ */
ef416fc2 638cupsArrayPrev(cups_array_t *a) /* I - Array */
639{
640 /*
641 * Range check input...
642 */
643
644 if (!a)
645 return (NULL);
646
647 /*
648 * Return the previous element...
649 */
650
651 if (a->current >= 0)
652 a->current --;
653
654 return (cupsArrayCurrent(a));
655}
656
657
658/*
659 * 'cupsArrayRemove()' - Remove an element from the array.
5a738aea
MS
660 *
661 * @since CUPS 1.2@
ef416fc2 662 */
663
664int /* O - 1 on success, 0 on failure */
665cupsArrayRemove(cups_array_t *a, /* I - Array */
666 void *e) /* I - Element */
667{
668 int i, /* Looping var */
669 current, /* Current element */
670 diff; /* Difference */
671
672
673 /*
674 * Range check input...
675 */
676
677 if (!a || !e)
678 return (0);
679
680 /*
681 * See if the element is in the array...
682 */
683
684 if (!a->num_elements)
685 return (0);
686
bd7854cb 687 current = cups_array_find(a, e, a->current, &diff);
ef416fc2 688 if (diff)
689 return (0);
690
691 /*
692 * Yes, now remove it...
693 */
694
695 a->num_elements --;
696
697 if (current < a->num_elements)
698 memmove(a->elements + current, a->elements + current + 1,
699 (a->num_elements - current) * sizeof(void *));
700
701 if (current <= a->current)
702 a->current --;
703
f7deaa1a 704 if (current < a->insert)
ef416fc2 705 a->insert --;
f7deaa1a 706 else if (current == a->insert)
707 a->insert = -1;
ef416fc2 708
709 for (i = 0; i < a->num_saved; i ++)
710 if (current <= a->saved[i])
711 a->saved[i] --;
712
bd7854cb 713 if (a->num_elements <= 1)
714 a->unique = 1;
715
ef416fc2 716 return (1);
717}
718
719
720/*
721 * 'cupsArrayRestore()' - Reset the current element to the last cupsArraySave.
5a738aea
MS
722 *
723 * @since CUPS 1.2@
ef416fc2 724 */
725
726void * /* O - New current element */
727cupsArrayRestore(cups_array_t *a) /* I - Array */
728{
729 if (!a)
730 return (NULL);
731
732 if (a->num_saved <= 0)
733 return (NULL);
734
735 a->num_saved --;
736 a->current = a->saved[a->num_saved];
737
738 if (a->current >= 0 && a->current < a->num_elements)
739 return (a->elements[a->current]);
740 else
741 return (NULL);
742}
743
744
745/*
746 * 'cupsArraySave()' - Mark the current element for a later cupsArrayRestore.
747 *
748 * The save/restore stack is guaranteed to be at least 32 elements deep.
5a738aea
MS
749 *
750 * @since CUPS 1.2@
ef416fc2 751 */
752
753int /* O - 1 on success, 0 on failure */
754cupsArraySave(cups_array_t *a) /* I - Array */
755{
756 if (!a)
757 return (0);
758
759 if (a->num_saved >= _CUPS_MAXSAVE)
760 return (0);
761
762 a->saved[a->num_saved] = a->current;
763 a->num_saved ++;
764
765 return (1);
766}
767
768
e1d6a774 769/*
770 * 'cupsArrayUserData()' - Return the user data for an array.
5a738aea
MS
771 *
772 * @since CUPS 1.2@
e1d6a774 773 */
774
775void * /* O - User data */
776cupsArrayUserData(cups_array_t *a) /* I - Array */
777{
778 if (a)
779 return (a->data);
780 else
781 return (NULL);
782}
783
784
ef416fc2 785/*
bd7854cb 786 * 'cups_array_add()' - Insert or append an element to the array...
5a738aea
MS
787 *
788 * @since CUPS 1.2@
bd7854cb 789 */
790
791static int /* O - 1 on success, 0 on failure */
792cups_array_add(cups_array_t *a, /* I - Array */
793 void *e, /* I - Element to add */
794 int insert) /* I - 1 = insert, 0 = append */
795{
796 int i, /* Looping var */
797 current, /* Current element */
798 diff; /* Comparison with current element */
799
800
801 DEBUG_printf(("cups_array_add(a=%p, e=%p, insert=%d)\n", a, e, insert));
802
803 /*
804 * Verify we have room for the new element...
805 */
806
807 if (a->num_elements >= a->alloc_elements)
808 {
809 /*
810 * Allocate additional elements; start with 16 elements, then
811 * double the size until 1024 elements, then add 1024 elements
812 * thereafter...
813 */
814
815 void **temp; /* New array elements */
816 int count; /* New allocation count */
817
818
819 if (a->alloc_elements == 0)
820 {
821 count = 16;
822 temp = malloc(count * sizeof(void *));
823 }
824 else
825 {
826 if (a->alloc_elements < 1024)
827 count = a->alloc_elements * 2;
828 else
829 count = a->alloc_elements + 1024;
830
831 temp = realloc(a->elements, count * sizeof(void *));
832 }
833
834 DEBUG_printf(("cups_array_add: count=%d\n", count));
835
836 if (!temp)
837 {
838 DEBUG_puts("cupsAddAdd: allocation failed, returning 0");
839 return (0);
840 }
841
842 a->alloc_elements = count;
843 a->elements = temp;
844 }
845
846 /*
847 * Find the insertion point for the new element; if there is no
848 * compare function or elements, just add it to the beginning or end...
849 */
850
851 if (!a->num_elements || !a->compare)
852 {
853 /*
854 * No elements or comparison function, insert/append as needed...
855 */
856
857 if (insert)
858 current = 0; /* Insert at beginning */
859 else
860 current = a->num_elements; /* Append to the end */
861 }
862 else
863 {
864 /*
865 * Do a binary search for the insertion point...
866 */
867
868 current = cups_array_find(a, e, a->insert, &diff);
869
870 if (diff > 0)
871 {
872 /*
873 * Insert after the current element...
874 */
875
876 current ++;
877 }
878 else if (!diff)
879 {
880 /*
881 * Compared equal, make sure we add to the begining or end of
882 * the current run of equal elements...
883 */
884
885 a->unique = 0;
886
887 if (insert)
888 {
889 /*
890 * Insert at beginning of run...
891 */
892
893 while (current > 0 && !(*(a->compare))(e, a->elements[current - 1],
894 a->data))
895 current --;
896 }
897 else
898 {
899 /*
900 * Append at end of run...
901 */
902
903 do
904 {
905 current ++;
906 }
907 while (current < a->num_elements &&
908 !(*(a->compare))(e, a->elements[current], a->data));
909 }
910 }
911 }
912
913 /*
914 * Insert or append the element...
915 */
916
917 if (current < a->num_elements)
918 {
919 /*
920 * Shift other elements to the right...
921 */
922
923 memmove(a->elements + current + 1, a->elements + current,
924 (a->num_elements - current) * sizeof(void *));
925
926 if (a->current >= current)
927 a->current ++;
928
929 for (i = 0; i < a->num_saved; i ++)
930 if (a->saved[i] >= current)
931 a->saved[i] ++;
932
933 DEBUG_printf(("cups_array_add: insert element at index %d...\n", current));
934 }
935#ifdef DEBUG
936 else
937 printf("cups_array_add: append element at %d...\n", current);
938#endif /* DEBUG */
939
940 a->elements[current] = e;
941 a->num_elements ++;
942 a->insert = current;
943
944#ifdef DEBUG
945 for (current = 0; current < a->num_elements; current ++)
946 printf("cups_array_add: a->elements[%d]=%p\n", current, a->elements[current]);
947#endif /* DEBUG */
948
949 DEBUG_puts("cups_array_add: returning 1");
950
951 return (1);
952}
953
954
955/*
956 * 'cups_array_find()' - Find an element in the array...
5a738aea
MS
957 *
958 * @since CUPS 1.2@
ef416fc2 959 */
960
961static int /* O - Index of match */
bd7854cb 962cups_array_find(cups_array_t *a, /* I - Array */
963 void *e, /* I - Element */
964 int prev, /* I - Previous index */
965 int *rdiff) /* O - Difference of match */
ef416fc2 966{
967 int left, /* Left side of search */
968 right, /* Right side of search */
969 current, /* Current element */
970 diff; /* Comparison with current element */
971
972
bd7854cb 973 DEBUG_printf(("cups_array_find(a=%p, e=%p, prev=%d, rdiff=%p)\n", a, e, prev,
ef416fc2 974 rdiff));
975
976 if (a->compare)
977 {
978 /*
979 * Do a binary search for the element...
980 */
981
bd7854cb 982 DEBUG_puts("cups_array_find: binary search");
ef416fc2 983
984 if (prev >= 0 && prev < a->num_elements)
985 {
986 /*
987 * Start search on either side of previous...
988 */
989
990 if ((diff = (*(a->compare))(e, a->elements[prev], a->data)) == 0 ||
991 (diff < 0 && prev == 0) ||
992 (diff > 0 && prev == (a->num_elements - 1)))
993 {
994 /*
995 * Exact or edge match, return it!
996 */
997
bd7854cb 998 DEBUG_printf(("cups_array_find: Returning %d, diff=%d\n", prev, diff));
ef416fc2 999
1000 *rdiff = diff;
1001
1002 return (prev);
1003 }
1004 else if (diff < 0)
1005 {
1006 /*
1007 * Start with previous on right side...
1008 */
1009
1010 left = 0;
1011 right = prev;
1012 }
1013 else
1014 {
1015 /*
1016 * Start wih previous on left side...
1017 */
1018
1019 left = prev;
1020 right = a->num_elements - 1;
1021 }
1022 }
1023 else
1024 {
1025 /*
1026 * Start search in the middle...
1027 */
1028
1029 left = 0;
1030 right = a->num_elements - 1;
1031 }
1032
1033 do
1034 {
1035 current = (left + right) / 2;
1036 diff = (*(a->compare))(e, a->elements[current], a->data);
1037
bd7854cb 1038 DEBUG_printf(("cups_array_find: left=%d, right=%d, current=%d, diff=%d\n",
ef416fc2 1039 left, right, current, diff));
1040
1041 if (diff == 0)
1042 break;
1043 else if (diff < 0)
1044 right = current;
1045 else
1046 left = current;
1047 }
1048 while ((right - left) > 1);
1049
1050 if (diff != 0)
1051 {
1052 /*
1053 * Check the last 1 or 2 elements...
1054 */
1055
1056 if ((diff = (*(a->compare))(e, a->elements[left], a->data)) <= 0)
1057 current = left;
1058 else
1059 {
1060 diff = (*(a->compare))(e, a->elements[right], a->data);
1061 current = right;
1062 }
1063 }
1064 }
1065 else
1066 {
1067 /*
1068 * Do a linear pointer search...
1069 */
1070
bd7854cb 1071 DEBUG_puts("cups_array_find: linear search");
ef416fc2 1072
a74454a7 1073 diff = 1;
ef416fc2 1074
1075 for (current = 0; current < a->num_elements; current ++)
1076 if (a->elements[current] == e)
a74454a7 1077 {
1078 diff = 0;
ef416fc2 1079 break;
a74454a7 1080 }
ef416fc2 1081 }
1082
1083 /*
1084 * Return the closest element and the difference...
1085 */
1086
bd7854cb 1087 DEBUG_printf(("cups_array_find: Returning %d, diff=%d\n", current, diff));
ef416fc2 1088
1089 *rdiff = diff;
1090
1091 return (current);
1092}
1093
1094
1095/*
bc44d920 1096 * End of "$Id: array.c 6649 2007-07-11 21:46:42Z mike $".
ef416fc2 1097 */