Bug Summary

File:d/index.c
Warning:line 322, column 13
Memory copy function accesses out-of-bound array element

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name index.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/isvv/naviserver/nsd -resource-dir /usr/local/lib/clang/15.0.0 -D _FORTIFY_SOURCE=2 -D NDEBUG -D SYSTEM_MALLOC -I ../include -I /usr/include/tcl8.6 -D HAVE_CONFIG_H -internal-isystem /usr/local/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c99 -fdebug-compilation-dir=/home/isvv/naviserver/nsd -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker alpha -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-07-23-130959-11103-1 -x c index.c
1/*
2 * The contents of this file are subject to the Mozilla Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://mozilla.org/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30
31/*
32 * index.c --
33 *
34 * Implement the index data type.
35 */
36
37#include "nsd.h"
38
39/*
40 * Local functions defined in this file
41 */
42
43static ssize_t BinSearch(void *const*elPtrPtr, void *const* listPtrPtr, ssize_t n, Ns_IndexCmpProc *cmpProc)
44 NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1))) NS_GNUC_NONNULL(2)__attribute__((__nonnull__(2))) NS_GNUC_NONNULL(4)__attribute__((__nonnull__(4)));
45static ssize_t BinSearchKey(const void *key, void *const*listPtrPtr, ssize_t n, Ns_IndexCmpProc *cmpProc)
46 NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1))) NS_GNUC_NONNULL(2)__attribute__((__nonnull__(2))) NS_GNUC_NONNULL(4)__attribute__((__nonnull__(4)));
47
48static Ns_IndexCmpProc CmpStr;
49static Ns_IndexKeyCmpProc CmpKeyWithStr;
50
51static Ns_IndexCmpProc CmpInts;
52static Ns_IndexKeyCmpProc CmpKeyWithInt;
53
54#ifdef _MSC_VER_VERY_OLD
55static void *
56NsBsearch (register const void *key, register const void *base,
57 register size_t nmemb, register size_t size,
58 int (*compar)(const void *left, const void *right));
59#endif
60
61
62/*
63 *----------------------------------------------------------------------
64 *
65 * Ns_IndexInit --
66 *
67 * Initialize a new index.
68 *
69 * Results:
70 * None.
71 *
72 * Side effects:
73 * Will allocate space for the index elements from the heap.
74 *
75 *----------------------------------------------------------------------
76 */
77
78void
79Ns_IndexInit(Ns_Index *indexPtr, size_t inc,
80 int (*CmpEls) (const void *left, const void *right),
81 int (*CmpKeyWithEl) (const void *left, const void *right))
82{
83
84 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
85 NS_NONNULL_ASSERT(CmpEls != NULL)((void) (0));
86 NS_NONNULL_ASSERT(CmpKeyWithEl != NULL)((void) (0));
87
88 indexPtr->n = 0u;
89 indexPtr->max = inc;
90 indexPtr->inc = inc;
91
92 indexPtr->CmpEls = CmpEls;
93 indexPtr->CmpKeyWithEl = CmpKeyWithEl;
94
95 indexPtr->el = (void **) ns_malloc((size_t)inc * sizeof(void *));
96}
97
98
99/*
100 *----------------------------------------------------------------------
101 *
102 * Ns_IndexTrunc --
103 *
104 * Remove all elements from an index.
105 *
106 * Results:
107 * None.
108 *
109 * Side effects:
110 * Frees and mallocs element memory.
111 *
112 *----------------------------------------------------------------------
113 */
114
115void
116Ns_IndexTrunc(Ns_Index* indexPtr)
117{
118 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
119
120 indexPtr->n = 0u;
121 ns_free(indexPtr->el);
122 indexPtr->max = indexPtr->inc;
123 indexPtr->el = (void **) ns_malloc((size_t)indexPtr->inc * sizeof(void *));
124}
125
126
127/*
128 *----------------------------------------------------------------------
129 *
130 * Ns_IndexDestroy --
131 *
132 * Release all of an index's memory.
133 *
134 * Results:
135 * None.
136 *
137 * Side effects:
138 * Frees elements.
139 *
140 *----------------------------------------------------------------------
141 */
142
143void
144Ns_IndexDestroy(Ns_Index *indexPtr)
145{
146 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
147
148 indexPtr->CmpEls = NULL((void*)0);
149 indexPtr->CmpKeyWithEl = NULL((void*)0);
150 ns_free(indexPtr->el);
151}
152
153
154/*
155 *----------------------------------------------------------------------
156 *
157 * Ns_IndexDup --
158 *
159 * Make a copy of an index.
160 *
161 * Results:
162 * A pointer to a copy of the index.
163 *
164 * Side effects:
165 * Mallocs memory for index and elements.
166 *
167 *----------------------------------------------------------------------
168 */
169
170Ns_Index *
171Ns_IndexDup(const Ns_Index *indexPtr)
172{
173 Ns_Index *newPtr;
174
175 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
176
177 newPtr = (Ns_Index *) ns_malloc(sizeof(Ns_Index));
178 memcpy(newPtr, indexPtr, sizeof(Ns_Index));
179 newPtr->el = (void **) ns_malloc(indexPtr->max * sizeof(void *));
180 memcpy(newPtr->el, indexPtr->el, indexPtr->n * sizeof(void *));
181
182 return newPtr;
183}
184
185
186/*
187 *----------------------------------------------------------------------
188 *
189 * Ns_IndexFind --
190 *
191 * Find a key in an index.
192 *
193 * Results:
194 * A pointer to the element, or NULL if none found.
195 *
196 * Side effects:
197 * None.
198 *
199 *----------------------------------------------------------------------
200 */
201
202void *
203Ns_IndexFind(const Ns_Index *indexPtr, const void *key)
204{
205 void *const *pPtrPtr;
206
207 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
208 NS_NONNULL_ASSERT(key != NULL)((void) (0));
209
210 pPtrPtr = (void **) bsearch(key, indexPtr->el, indexPtr->n,
211 sizeof(void *), indexPtr->CmpKeyWithEl);
212
213 return (pPtrPtr != NULL((void*)0)) ? *pPtrPtr : NULL((void*)0);
214}
215
216
217/*
218 *----------------------------------------------------------------------
219 *
220 * Ns_IndexFindInf --
221 *
222 * Find the element with the key, or if none exists, the element
223 * before which the key would appear.
224 *
225 * Results:
226 * An element, or NULL if the key is not there AND would be the
227 * last element in the list.
228 *
229 * Side effects:
230 * None.
231 *
232 *----------------------------------------------------------------------
233 */
234
235void *
236Ns_IndexFindInf(const Ns_Index *indexPtr, const void *key)
237{
238 void *result = NULL((void*)0);
239
240 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
241 NS_NONNULL_ASSERT(key != NULL)((void) (0));
242
243 if (indexPtr->n > 0u) {
244 ssize_t i = BinSearchKey(key, indexPtr->el, (ssize_t)indexPtr->n,
245 indexPtr->CmpKeyWithEl);
246
247 if (i < (ssize_t)indexPtr->n) {
248 if ((i > 0) &&
249 ((indexPtr->CmpKeyWithEl)(key, &(indexPtr->el[i])) != 0)) {
250 result = indexPtr->el[i - 1];
251 } else {
252 result = indexPtr->el[i];
253 }
254 }
255 }
256
257 return result;
258}
259
260
261/*
262 *----------------------------------------------------------------------
263 *
264 * Ns_IndexFindMultiple --
265 *
266 * Find all elements that match key.
267 *
268 * Results:
269 * An array of pointers to matching elements, terminated with a
270 * null pointer.
271 *
272 * Side effects:
273 * Will allocate memory for the return result.
274 *
275 *----------------------------------------------------------------------
276 */
277
278void **
279Ns_IndexFindMultiple(const Ns_Index *indexPtr, const void *key)
280{
281 void *const *firstPtrPtr;
282 void **retPtrPtr = NULL((void*)0);
283
284 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
285 NS_NONNULL_ASSERT(key != NULL)((void) (0));
286
287 /*
288 * Find a place in the array that matches the key
289 */
290 firstPtrPtr = (void **) bsearch(key, indexPtr->el, indexPtr->n,
291 sizeof(void *), indexPtr->CmpKeyWithEl);
292
293 if (firstPtrPtr != NULL((void*)0)) {
1
Assuming 'firstPtrPtr' is not equal to NULL
2
Taking true branch
294 size_t i, n;
295
296 /*
297 * Search linearly back to make sure we've got the first one
298 */
299
300 while (firstPtrPtr != indexPtr->el
3
Assuming 'firstPtrPtr' is not equal to field 'el'
5
Loop condition is true. Entering loop body
6
Assuming 'firstPtrPtr' is equal to field 'el'
301 && indexPtr->CmpKeyWithEl(key, firstPtrPtr - 1) == 0) {
4
Assuming the condition is true
302 firstPtrPtr--;
303 }
304
305 /*
306 * Search linearly forward to find out how many there are
307 */
308 n = indexPtr->n - (size_t)(firstPtrPtr - indexPtr->el);
309 for (i = 1u;
310 i < n && indexPtr->CmpKeyWithEl(key, firstPtrPtr + i) == 0;
7
Assuming 'i' is >= 'n'
311 i++) {
312 ;
313 }
314
315 /*
316 * Build array of values to return
317 */
318 retPtrPtr = ns_malloc((i + 1u) * sizeof(void *));
319 if (unlikely(retPtrPtr == NULL)(__builtin_expect((retPtrPtr == ((void*)0)), 0))) {
8
Assuming 'retPtrPtr' is not equal to null
9
Taking false branch
320 Ns_Fatal("IndexFindMultiple: out of memory while allocating result");
321 } else {
322 memcpy(retPtrPtr, firstPtrPtr, i * sizeof(void *));
10
Memory copy function accesses out-of-bound array element
323 retPtrPtr[i] = NULL((void*)0);
324 }
325 }
326
327 return retPtrPtr;
328}
329
330
331/*
332 *----------------------------------------------------------------------
333 *
334 * BinSearch --
335 *
336 * Modified from BinSearch in K&R.
337 *
338 * Results:
339 * The position where an element should be inserted even if it
340 * does not already exist. "bsearch" will just return NULL.
341 *
342 * Side effects:
343 * None.
344 *
345 *----------------------------------------------------------------------
346 */
347
348static ssize_t
349BinSearch(void *const* elPtrPtr, void *const* listPtrPtr, ssize_t n, Ns_IndexCmpProc *cmpProc)
350{
351 ssize_t low = 0, high = n-1, mid = 0;
352
353 NS_NONNULL_ASSERT(elPtrPtr != NULL)((void) (0));
354 NS_NONNULL_ASSERT(listPtrPtr != NULL)((void) (0));
355 NS_NONNULL_ASSERT(cmpProc != NULL)((void) (0));
356
357 while (low <= high) {
358 int cond;
359
360 mid = (low + high) / 2;
361 cond = (*cmpProc) (elPtrPtr, ((const unsigned char *const*)listPtrPtr) + mid);
362 if (cond < 0) {
363 high = mid - 1;
364 } else if (cond > 0) {
365 low = mid + 1;
366 } else {
367 return mid;
368 }
369 }
370 return (high < mid) ? mid : low;
371}
372
373
374/*
375 *----------------------------------------------------------------------
376 *
377 * BinSearchKey --
378 *
379 * Like BinSearch, but takes a key instead of an element
380 * pointer.
381 *
382 * Results:
383 * See BinSearch.
384 *
385 * Side effects:
386 * None.
387 *
388 *----------------------------------------------------------------------
389 */
390
391static ssize_t
392BinSearchKey(const void *key, void *const* listPtrPtr, ssize_t n, Ns_IndexCmpProc *cmpProc)
393{
394 ssize_t low = 0, high = n-1, mid = 0;
395
396 NS_NONNULL_ASSERT(key != NULL)((void) (0));
397 NS_NONNULL_ASSERT(listPtrPtr != NULL)((void) (0));
398 NS_NONNULL_ASSERT(cmpProc != NULL)((void) (0));
399
400 while (low <= high) {
401 int cond;
402
403 mid = (low + high) / 2;
404 cond = (*cmpProc)(key, ((const unsigned char *const*)listPtrPtr) + mid);
405 if (cond < 0) {
406 high = mid - 1;
407 } else if (cond > 0) {
408 low = mid + 1;
409 } else {
410 return mid;
411 }
412 }
413 return (high < mid) ? mid : low;
414}
415
416
417/*
418 *----------------------------------------------------------------------
419 *
420 * Ns_IndexAdd --
421 *
422 * Add an element to an index.
423 *
424 * Results:
425 * None.
426 *
427 * Side effects:
428 * May allocate extra element memory.
429 *
430 *----------------------------------------------------------------------
431 */
432
433void
434Ns_IndexAdd(Ns_Index *indexPtr, void *el)
435{
436 ssize_t i;
437
438 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
439 NS_NONNULL_ASSERT(el != NULL)((void) (0));
440
441 if (indexPtr->n == indexPtr->max) {
442 indexPtr->max += indexPtr->inc;
443 indexPtr->el = (void **) ns_realloc(indexPtr->el,
444 indexPtr->max * sizeof(void *));
445 } else if (indexPtr->max == 0u) {
446 indexPtr->max = indexPtr->inc;
447 indexPtr->el = (void **) ns_malloc(indexPtr->max * sizeof(void *));
448 }
449 if (indexPtr->n > 0u) {
450 i = BinSearch(&el, indexPtr->el, (ssize_t)indexPtr->n, indexPtr->CmpEls);
451 } else {
452 i = 0;
453 }
454
455 if (i < (int)indexPtr->n) {
456 size_t j;
457
458 for (j = indexPtr->n; (int)j > i; j--) {
459 indexPtr->el[j] = indexPtr->el[j - 1u];
460 }
461 }
462 indexPtr->el[i] = el;
463 indexPtr->n++;
464}
465
466
467/*
468 *----------------------------------------------------------------------
469 *
470 * Ns_IndexDel --
471 *
472 * Remove an element from an index.
473 *
474 * Results:
475 * None.
476 *
477 * Side effects:
478 * None.
479 *
480 *----------------------------------------------------------------------
481 */
482
483void
484Ns_IndexDel(Ns_Index *indexPtr, const void *el)
485{
486 size_t i, j;
487
488 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
489 NS_NONNULL_ASSERT(el != NULL)((void) (0));
490
491 for (i = 0u; i < indexPtr->n; i++) {
492 if (indexPtr->el[i] == el) {
493 indexPtr->n--;
494 if (i < indexPtr->n) {
495 for (j = i; j < indexPtr->n; j++) {
496 indexPtr->el[j] = indexPtr->el[j + 1u];
497 }
498 }
499 break;
500 }
501 }
502}
503
504
505/*
506 *----------------------------------------------------------------------
507 *
508 * Ns_IndexEl --
509 *
510 * Find the i'th element of an index.
511 *
512 * Results:
513 * Element.
514 *
515 * Side effects:
516 * None.
517 *
518 *----------------------------------------------------------------------
519 */
520
521void *
522Ns_IndexEl(const Ns_Index *indexPtr, size_t i)
523{
524 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
525
526 return indexPtr->el[i];
527}
528
529
530/*
531 *----------------------------------------------------------------------
532 *
533 * CmpStr --
534 *
535 * Default comparison function.
536 *
537 * Results:
538 * See strcmp.
539 *
540 * Side effects:
541 * None.
542 *
543 *----------------------------------------------------------------------
544 */
545
546static int
547CmpStr(const void *leftPtr, const void *rightPtr)
548{
549 NS_NONNULL_ASSERT(leftPtr != NULL)((void) (0));
550 NS_NONNULL_ASSERT(rightPtr != NULL)((void) (0));
551
552 return strcmp(*(const char**)leftPtr, *((const char**)rightPtr));
553}
554
555
556/*
557 *----------------------------------------------------------------------
558 *
559 * CmpKeyWithStr --
560 *
561 * Default comparison function, with key.
562 *
563 * Results:
564 * See strcmp.
565 *
566 * Side effects:
567 * None.
568 *
569 *----------------------------------------------------------------------
570 */
571
572static int
573CmpKeyWithStr(const void *key, const void *elPtr)
574{
575 NS_NONNULL_ASSERT(key != NULL)((void) (0));
576 NS_NONNULL_ASSERT(elPtr != NULL)((void) (0));
577
578 return strcmp((const char *)key, *(const char *const*)elPtr);
579}
580
581
582/*
583 *----------------------------------------------------------------------
584 *
585 * Ns_IndexStringInit --
586 *
587 * Initialize an index where the elements themselves are
588 * strings.
589 *
590 * Results:
591 * None.
592 *
593 * Side effects:
594 * See Ns_IndexInit.
595 *
596 *----------------------------------------------------------------------
597 */
598
599void
600Ns_IndexStringInit(Ns_Index *indexPtr, size_t inc)
601{
602 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
603
604 Ns_IndexInit(indexPtr, inc, CmpStr, CmpKeyWithStr);
605}
606
607
608/*
609 *----------------------------------------------------------------------
610 *
611 * Ns_IndexStringDup --
612 *
613 * Make a copy of an index, using ns_strdup to duplicate the
614 * keys.
615 *
616 * Results:
617 * A new index.
618 *
619 * Side effects:
620 * Will make memory copies of the elements.
621 *
622 *----------------------------------------------------------------------
623 */
624
625Ns_Index *
626Ns_IndexStringDup(const Ns_Index *indexPtr)
627{
628 Ns_Index *newPtr;
629 size_t i;
630
631 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
632
633 newPtr = (Ns_Index *) ns_malloc(sizeof(Ns_Index));
634 memcpy(newPtr, indexPtr, sizeof(Ns_Index));
635 newPtr->el = (void **) ns_malloc(indexPtr->max * sizeof(void *));
636
637 for (i = 0u; i < newPtr->n; i++) {
638 newPtr->el[i] = ns_strdup(indexPtr->el[i]);
639 }
640
641 return newPtr;
642}
643
644
645/*
646 *----------------------------------------------------------------------
647 *
648 * Ns_IndexStringAppend --
649 *
650 * Append one index of strings to another.
651 *
652 * Results:
653 * None.
654 *
655 * Side effects:
656 * Will append to the first index.
657 *
658 *----------------------------------------------------------------------
659 */
660
661void
662Ns_IndexStringAppend(Ns_Index *addtoPtr, const Ns_Index *addfromPtr)
663{
664 size_t i;
665
666 NS_NONNULL_ASSERT(addtoPtr != NULL)((void) (0));
667 NS_NONNULL_ASSERT(addfromPtr != NULL)((void) (0));
668
669 for (i = 0u; i < addfromPtr->n; i++) {
670 Ns_IndexAdd(addtoPtr, ns_strdup(addfromPtr->el[i]));
671 }
672}
673
674
675/*
676 *----------------------------------------------------------------------
677 *
678 * Ns_IndexStringDestroy --
679 *
680 * Free an index of strings.
681 *
682 * Results:
683 * None.
684 *
685 * Side effects:
686 * See Ns_IndexDestroy.
687 *
688 *----------------------------------------------------------------------
689 */
690
691void
692Ns_IndexStringDestroy(Ns_Index *indexPtr)
693{
694 size_t i;
695
696 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
697
698 for (i = 0u; i < indexPtr->n; i++) {
699 ns_free(indexPtr->el[i]);
700 }
701
702 Ns_IndexDestroy(indexPtr);
703}
704
705
706/*
707 *----------------------------------------------------------------------
708 *
709 * Ns_IndexStringTrunc --
710 *
711 * Remove all elements from an index of strings.
712 *
713 * Results:
714 * None.
715 *
716 * Side effects:
717 * See Ns_IndexTrunc.
718 *
719 *----------------------------------------------------------------------
720 */
721
722void
723Ns_IndexStringTrunc(Ns_Index *indexPtr)
724{
725 size_t i;
726
727 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
728
729 for (i = 0u; i < indexPtr->n; i++) {
730 ns_free(indexPtr->el[i]);
731 }
732
733 Ns_IndexTrunc(indexPtr);
734}
735
736
737/*
738 *----------------------------------------------------------------------
739 *
740 * CmpInts --
741 *
742 * Default comparison function for an index of ints.
743 *
744 * Results:
745 * -1: left < right; 1: left > right; 0: left == right
746 *
747 * Side effects:
748 * None.
749 *
750 *----------------------------------------------------------------------
751 */
752
753static int
754CmpInts(const void *leftPtr, const void *rightPtr)
755{
756 int result, left, right;
757
758 NS_NONNULL_ASSERT(leftPtr != NULL)((void) (0));
759 NS_NONNULL_ASSERT(rightPtr != NULL)((void) (0));
760
761 left = *(const int *)leftPtr;
762 right = *(const int *)rightPtr;
763
764 if (left == right) {
765 result = 0;
766 } else {
767 result = (left < right) ? -1 : 1;
768 }
769 return result;
770}
771
772
773/*
774 *----------------------------------------------------------------------
775 *
776 * CmpKeyWithInt --
777 *
778 * Default comparison function for an index of ints, with key.
779 *
780 * Results:
781 * -1: key < el; 1: key > el; 0: key == el
782 *
783 * Side effects:
784 * None.
785 *
786 *----------------------------------------------------------------------
787 */
788
789static int
790CmpKeyWithInt(const void *keyPtr, const void *elPtr)
791{
792 int result, key, element;
793
794 NS_NONNULL_ASSERT(keyPtr != NULL)((void) (0));
795 NS_NONNULL_ASSERT(elPtr != NULL)((void) (0));
796
797 key = *(const int *)keyPtr;
798 element = *(const int *)elPtr;
799
800 if (key == element) {
801 result = 0;
802 } else {
803 result = key < element ? -1 : 1;
804 }
805 return result;
806}
807
808
809/*
810 *----------------------------------------------------------------------
811 *
812 * Ns_IndexIntInit --
813 *
814 * Initialize an index whose elements will be integers.
815 *
816 * Results:
817 * None.
818 *
819 * Side effects:
820 * See Ns_IndexInit.
821 *
822 *----------------------------------------------------------------------
823 */
824
825void
826Ns_IndexIntInit(Ns_Index *indexPtr, size_t inc)
827{
828 NS_NONNULL_ASSERT(indexPtr != NULL)((void) (0));
829
830 Ns_IndexInit(indexPtr, inc, CmpInts, CmpKeyWithInt);
831}
832
833#ifdef _MSC_VER_VERY_OLD
834#define bsearch(a, b, c, d, e) NsBsearch((a), (b), (c), (d), (e))
835
836/*
837 *----------------------------------------------------------------------
838 *
839 * NsBsearch --
840 *
841 * Binary search.
842 *
843 * Due to Windows hanging in its own bsearch() routine, this was added
844 * to alleviate the problem.
845 *
846 * Results:
847 * A pointer to the element, or NULL if none found.
848 *
849 * Side effects:
850 * None.
851 *
852 *----------------------------------------------------------------------
853 */
854
855static void *
856NsBsearch (register const void *key, register const void *base,
857 register size_t nmemb, register size_t size,
858 int (*compar)(const void *key, const void *value))
859{
860 while (nmemb > 0) {
861 register const void *mid_point;
862 register int cmp;
863
864 mid_point = (char *)base + size * (nmemb >> 1);
865 if ((cmp = (*compar)(key, mid_point)) == 0)
866 return (void *)mid_point;
867 if (cmp >= 0) {
868 base = (char *)mid_point + size;
869 nmemb = (nmemb - 1) >> 1;
870 } else
871 nmemb >>= 1;
872 }
873 return NULL((void*)0);
874}
875#endif
876
877/*
878 * Local Variables:
879 * mode: c
880 * c-basic-offset: 4
881 * fill-column: 78
882 * indent-tabs-mode: nil
883 * End:
884 */