1 | /*␊ |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
7 | * Reserved. This file contains Original Code and/or Modifications of␊ |
8 | * Original Code as defined in and that are subject to the Apple Public␊ |
9 | * Source License Version 2.0 (the "License"). You may not use this file␊ |
10 | * except in compliance with the License. Please obtain a copy of the␊ |
11 | * License at http://www.apple.com/publicsource and read it before using␊ |
12 | * this file.␊ |
13 | * ␊ |
14 | * The Original Code and all software distributed under the License are␊ |
15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the␊ |
19 | * License for the specific language governing rights and limitations␊ |
20 | * under the License.␊ |
21 | * ␊ |
22 | * @APPLE_LICENSE_HEADER_END@␊ |
23 | */␊ |
24 | /* string operations */␊ |
25 | ␊ |
26 | #include "libsa.h"␊ |
27 | ␊ |
28 | static char *STRDUP(const char *string);␊ |
29 | ␊ |
30 | #if 0␊ |
31 | /*␊ |
32 | * Abstract:␊ |
33 | * strcmp (s1, s2) compares the strings "s1" and "s2".␊ |
34 | * It returns 0 if the strings are identical. It returns␊ |
35 | * > 0 if the first character that differs in the two strings␊ |
36 | * is larger in s1 than in s2 or if s1 is longer than s2 and␊ |
37 | * the contents are identical up to the length of s2.␊ |
38 | * It returns < 0 if the first differing character is smaller␊ |
39 | * in s1 than in s2 or if s1 is shorter than s2 and the␊ |
40 | * contents are identical upto the length of s1.␊ |
41 | * Deprecation Warning:␊ |
42 | *␉strcmp() is being deprecated. Please use strncmp() instead.␊ |
43 | */␊ |
44 | ␊ |
45 | int␊ |
46 | strcmp(␊ |
47 | ␉ const char *s1,␊ |
48 | ␉ const char *s2)␊ |
49 | {␊ |
50 | ␉unsigned int a, b;␊ |
51 | ␉␊ |
52 | ␉do {␊ |
53 | ␉␉a = *s1++;␊ |
54 | ␉␉b = *s2++;␊ |
55 | ␉␉if (a != b)␊ |
56 | ␉␉␉return a-b; /* includes case when␊ |
57 | ␉␉␉␉␉␉␉ 'a' is zero and 'b' is not zero␊ |
58 | ␉␉␉␉␉␉␉ or vice versa */␊ |
59 | ␉} while (a != '\0');␊ |
60 | ␉␊ |
61 | ␉return 0; /* both are zero */␊ |
62 | }␊ |
63 | ␊ |
64 | /*␊ |
65 | * Abstract:␊ |
66 | * strncmp (s1, s2, n) compares the strings "s1" and "s2"␊ |
67 | * in exactly the same way as strcmp does. Except the␊ |
68 | * comparison runs for at most "n" characters.␊ |
69 | */␊ |
70 | ␊ |
71 | int␊ |
72 | strncmp(␊ |
73 | const char *s1,␊ |
74 | const char *s2,␊ |
75 | size_t n)␊ |
76 | {␊ |
77 | ␉unsigned int a, b;␊ |
78 | ␉␊ |
79 | ␉while (n != 0) {␊ |
80 | ␉␉a = *s1++;␊ |
81 | ␉␉b = *s2++;␊ |
82 | ␉␉if (a != b)␊ |
83 | ␉␉␉return a-b; /* includes case when␊ |
84 | ␉␉␉␉␉␉␉ 'a' is zero and 'b' is not zero␊ |
85 | ␉␉␉␉␉␉␉ or vice versa */␊ |
86 | ␉␉if (a == '\0')␊ |
87 | ␉␉␉return 0; /* both are zero */␊ |
88 | ␉␉n--;␊ |
89 | ␉}␊ |
90 | ␉␊ |
91 | ␉return 0;␊ |
92 | }␊ |
93 | ␊ |
94 | /*␊ |
95 | * Abstract:␊ |
96 | * strcpy copies the contents of the string "from" including␊ |
97 | * the null terminator to the string "to". A pointer to "to"␊ |
98 | * is returned.␊ |
99 | * Deprecation Warning: ␊ |
100 | *␉strcpy() is being deprecated. Please use strlcpy() instead.␊ |
101 | */␊ |
102 | char *␊ |
103 | strcpy(␊ |
104 | ␉ char *to,␊ |
105 | ␉ const char *from)␊ |
106 | {␊ |
107 | ␉char *ret = to;␊ |
108 | ␉␊ |
109 | ␉while ((*to++ = *from++) != '\0')␊ |
110 | ␉␉continue;␊ |
111 | ␉␊ |
112 | ␉return ret;␊ |
113 | }␊ |
114 | ␊ |
115 | /*␊ |
116 | * Abstract:␊ |
117 | * strncpy copies "count" characters from the "from" string to␊ |
118 | * the "to" string. If "from" contains less than "count" characters␊ |
119 | * "to" will be padded with null characters until exactly "count"␊ |
120 | * characters have been written. The return value is a pointer␊ |
121 | * to the "to" string.␊ |
122 | */␊ |
123 | ␊ |
124 | char *␊ |
125 | strncpy(␊ |
126 | ␉␉char *s1, ␊ |
127 | ␉␉const char *s2,␊ |
128 | ␉␉size_t n)␊ |
129 | {␊ |
130 | ␉char *os1 = s1;␊ |
131 | ␉unsigned long i;␊ |
132 | ␉␊ |
133 | ␉for (i = 0; i < n;)␊ |
134 | ␉␉if ((*s1++ = *s2++) == '\0')␊ |
135 | ␉␉␉for (i++; i < n; i++)␊ |
136 | ␉␉␉␉*s1++ = '\0';␊ |
137 | ␉␉else␊ |
138 | ␉␉␉i++;␊ |
139 | ␉return (os1);␊ |
140 | }␊ |
141 | ␊ |
142 | /*␊ |
143 | * Copy src to string dst of size siz. At most siz-1 characters␊ |
144 | * will be copied. Always NUL terminates (unless siz == 0).␊ |
145 | * Returns strlen(src); if retval >= siz, truncation occurred.␊ |
146 | */␊ |
147 | size_t␊ |
148 | strlcpy(char *dst, const char *src, size_t siz)␊ |
149 | {␊ |
150 | ␉char *d = dst;␊ |
151 | ␉const char *s = src;␊ |
152 | ␉size_t n = siz;␊ |
153 | ␉␊ |
154 | ␉/* Copy as many bytes as will fit */␊ |
155 | ␉if (n != 0 && --n != 0) {␊ |
156 | ␉␉do {␊ |
157 | ␉␉␉if ((*d++ = *s++) == 0)␊ |
158 | ␉␉␉␉break;␊ |
159 | ␉␉} while (--n != 0);␊ |
160 | ␉}␊ |
161 | ␉␊ |
162 | ␉/* Not enough room in dst, add NUL and traverse rest of src */␊ |
163 | ␉if (n == 0) {␊ |
164 | ␉␉if (siz != 0)␊ |
165 | ␉␉␉*d = '\0';␉␉/* NUL-terminate dst */␊ |
166 | ␉␉while (*s++)␊ |
167 | ␉␉␉;␊ |
168 | ␉}␊ |
169 | ␉␊ |
170 | ␉return(s - src - 1);␉/* count does not include NUL */␊ |
171 | }␊ |
172 | #endif␊ |
173 | ␊ |
174 | /*␊ |
175 | * History:␊ |
176 | * 2002-01-24 ␉gvdl␉Initial implementation of strstr␊ |
177 | */␊ |
178 | ␊ |
179 | const char *␊ |
180 | strstr(const char *in, const char *str)␊ |
181 | {␊ |
182 | char c;␊ |
183 | size_t len;␊ |
184 | ␉␊ |
185 | c = *str++;␊ |
186 | if (!c)␊ |
187 | return (const char *) in;␉// Trivial empty string case␊ |
188 | ␉␊ |
189 | len = strlen(str);␊ |
190 | do {␊ |
191 | char sc;␊ |
192 | ␉␉␊ |
193 | do {␊ |
194 | sc = *in++;␊ |
195 | if (!sc)␊ |
196 | return (char *) 0;␊ |
197 | } while (sc != c);␊ |
198 | } while (strncmp(in, str, len) != 0);␊ |
199 | ␉␊ |
200 | return (const char *) (in - 1);␊ |
201 | }␊ |
202 | ␊ |
203 | #if 0␊ |
204 | void *␊ |
205 | memmove(void *dst, const void *src, size_t ulen)␊ |
206 | {␊ |
207 | bcopy(src, dst, ulen); ␊ |
208 | return dst;␊ |
209 | }␊ |
210 | #endif␊ |
211 | ␊ |
212 | #if UNUSED␊ |
213 | int␊ |
214 | ptol(const char *str)␊ |
215 | {␊ |
216 | ␉register int c = *str;␊ |
217 | ␉␊ |
218 | ␉if (c <= '7' && c >= '0')␊ |
219 | ␉␉c -= '0';␊ |
220 | ␉else if (c <= 'h' && c >= 'a')␊ |
221 | ␉␉c -= 'a';␊ |
222 | ␉else c = 0;␊ |
223 | ␉return c;␊ |
224 | }␊ |
225 | #endif␊ |
226 | /*␊ |
227 | * atoi:␊ |
228 | *␊ |
229 | * This function converts an ascii string into an integer.␊ |
230 | *␊ |
231 | * input : string␊ |
232 | * output : a number␊ |
233 | */␊ |
234 | ␊ |
235 | int␊ |
236 | atoi(const char *cp)␊ |
237 | {␊ |
238 | ␉int number;␊ |
239 | ␉␊ |
240 | ␉for (number = 0; ('0' <= *cp) && (*cp <= '9'); cp++)␊ |
241 | ␉␉number = (number * 10) + (*cp - '0');␊ |
242 | ␉␊ |
243 | ␉return( number );␊ |
244 | }␊ |
245 | #if UNUSED␊ |
246 | /*␊ |
247 | * convert an integer to an ASCII string.␊ |
248 | * inputs:␊ |
249 | *␉num␉integer to be converted␊ |
250 | *␉str␉string pointer.␊ |
251 | *␊ |
252 | * outputs:␊ |
253 | *␉pointer to string start.␊ |
254 | */␊ |
255 | ␊ |
256 | char *␊ |
257 | itoa(␊ |
258 | ␉ int␉num,␊ |
259 | ␉ char␉*str)␊ |
260 | {␊ |
261 | ␉char digits[11];␊ |
262 | ␉char *dp;␊ |
263 | ␉char *cp = str;␊ |
264 | ␉␊ |
265 | ␉if (num == 0) {␊ |
266 | ␉␉*cp++ = '0';␊ |
267 | ␉}␊ |
268 | ␉else {␊ |
269 | ␉␉dp = digits;␊ |
270 | ␉␉while (num) {␊ |
271 | ␉␉␉*dp++ = '0' + num % 10;␊ |
272 | ␉␉␉num /= 10;␊ |
273 | ␉␉}␊ |
274 | ␉␉while (dp != digits) {␊ |
275 | ␉␉␉*cp++ = *--dp;␊ |
276 | ␉␉}␊ |
277 | ␉}␊ |
278 | ␉*cp++ = '\0';␊ |
279 | ␉␊ |
280 | ␉return str;␊ |
281 | }␊ |
282 | #endif␊ |
283 | ␊ |
284 | #if 0␊ |
285 | /*␊ |
286 | * Appends src to string dst of size siz (unlike strncat, siz is the␊ |
287 | * full size of dst, not space left). At most siz-1 characters␊ |
288 | * will be copied. Always NUL terminates (unless siz <= strlen(dst)).␊ |
289 | * Returns strlen(src) + MIN(siz, strlen(initial dst)).␊ |
290 | * If retval >= siz, truncation occurred.␊ |
291 | */␊ |
292 | size_t␊ |
293 | strlcat(char *dst, const char *src, size_t siz)␊ |
294 | {␊ |
295 | ␉char *d = dst;␊ |
296 | ␉const char *s = src;␊ |
297 | ␉size_t n = siz;␊ |
298 | ␉size_t dlen;␊ |
299 | ␉␊ |
300 | ␉/* Find the end of dst and adjust bytes left but don't go past end */␊ |
301 | ␉while (n-- != 0 && *d != '\0')␊ |
302 | ␉␉d++;␊ |
303 | ␉dlen = d - dst;␊ |
304 | ␉n = siz - dlen;␊ |
305 | ␉␊ |
306 | ␉if (n == 0)␊ |
307 | ␉␉return(dlen + strlen(s));␊ |
308 | ␉while (*s != '\0') {␊ |
309 | ␉␉if (n != 1) {␊ |
310 | ␉␉␉*d++ = *s;␊ |
311 | ␉␉␉n--;␊ |
312 | ␉␉}␊ |
313 | ␉␉s++;␊ |
314 | ␉}␊ |
315 | ␉*d = '\0';␊ |
316 | ␉␊ |
317 | ␉return(dlen + (s - src)); /* count does not include NUL */␊ |
318 | }␊ |
319 | #endif␊ |
320 | ␊ |
321 | /*␊ |
322 | *␊ |
323 | */␊ |
324 | ␊ |
325 | char *␊ |
326 | strncat(char *s1, const char *s2, unsigned long n)␊ |
327 | {␊ |
328 | ␉char *os1;␊ |
329 | ␉int i = n;␊ |
330 | ␉␊ |
331 | ␉os1 = s1;␊ |
332 | ␉while (*s1++)␊ |
333 | ␉␉;␊ |
334 | ␉--s1;␊ |
335 | ␉while ((*s1++ = *s2++))␊ |
336 | ␉␉if (--i < 0) {␊ |
337 | ␉␉␉*--s1 = '\0';␊ |
338 | ␉␉␉break;␊ |
339 | ␉␉}␊ |
340 | ␉return(os1);␊ |
341 | }␊ |
342 | ␊ |
343 | #if 0␊ |
344 | static int _mach_strlen(const char *str);␊ |
345 | static int␊ |
346 | _mach_strlen(const char *str)␊ |
347 | {␊ |
348 | ␉const char *p;␊ |
349 | ␉for (p = str; p; p++) {␊ |
350 | ␉␉if (*p == '\0') {␊ |
351 | ␉␉␉return (p - str);␊ |
352 | ␉␉}␊ |
353 | ␉}␊ |
354 | ␉/* NOTREACHED */␊ |
355 | ␉return 0;␊ |
356 | }␊ |
357 | ␊ |
358 | size_t strlen(const char * str)␊ |
359 | {␉␊ |
360 | ␉return (size_t)_mach_strlen(str);␊ |
361 | }␊ |
362 | #endif␊ |
363 | ␊ |
364 | #if UNUSED␊ |
365 | /*␊ |
366 | * Does the same thing as strlen, except only looks up␊ |
367 | * to max chars inside the buffer. ␊ |
368 | * Taken from archive/kern-stuff/sbf_machine.c in ␊ |
369 | * seatbelt. ␊ |
370 | * inputs:␊ |
371 | * ␉s␉string whose length is to be measured␊ |
372 | *␉max␉maximum length of string to search for null␊ |
373 | * outputs:␊ |
374 | *␉length of s or max; whichever is smaller␊ |
375 | */␊ |
376 | size_t ␊ |
377 | strnlen(const char *s, size_t max) {␊ |
378 | ␉const char *es = s + max, *p = s;␊ |
379 | ␉while(*p && p != es) ␊ |
380 | ␉␉p++;␊ |
381 | ␉␊ |
382 | ␉return p - s;␊ |
383 | }␊ |
384 | #endif␊ |
385 | /* ␊ |
386 | * Deprecation Warning:␊ |
387 | *␉strcat() is being deprecated. Please use strlcat() instead.␊ |
388 | */␊ |
389 | char *␊ |
390 | strcat(␊ |
391 | ␉ char *dest,␊ |
392 | ␉ const char *src)␊ |
393 | {␊ |
394 | ␉char *old = dest;␊ |
395 | ␉␊ |
396 | ␉while (*dest)␊ |
397 | ␉␉++dest;␊ |
398 | ␉while ((*dest++ = *src++))␊ |
399 | ␉␉;␊ |
400 | ␉return (old);␊ |
401 | }␊ |
402 | ␊ |
403 | /*␊ |
404 | * STRDUP␊ |
405 | *␊ |
406 | * Description: The STRDUP function allocates sufficient memory for a copy␊ |
407 | * of the string "string", does the copy, and returns a pointer␊ |
408 | * it. The pointer may subsequently be used as an argument to␊ |
409 | * the macro FREE().␊ |
410 | *␊ |
411 | * Parameters: string␉␉String to be duplicated␊ |
412 | *␊ |
413 | * Returns: char * A pointer to the newly allocated string with␊ |
414 | * duplicated contents in it.␊ |
415 | *␊ |
416 | * NULL␉␉If MALLOC() fails.␊ |
417 | * ␊ |
418 | */␊ |
419 | ␊ |
420 | static char *␊ |
421 | STRDUP(const char *string)␊ |
422 | {␊ |
423 | ␉size_t len;␊ |
424 | ␉char *copy; ␊ |
425 | ␉␊ |
426 | ␉len = strlen(string) + 1;␊ |
427 | ␉copy = malloc(len);␊ |
428 | ␉if (copy == NULL)␊ |
429 | ␉␉return (NULL);␊ |
430 | ␉bcopy(string, copy, len);␊ |
431 | ␉return (copy); ␊ |
432 | }␊ |
433 | ␊ |
434 | char *strdup(const char *string)␊ |
435 | {␊ |
436 | ␉if (string) {␊ |
437 | ␉␉return STRDUP(string);␊ |
438 | ␉}␊ |
439 | ␉return (NULL);␊ |
440 | }␊ |
441 | ␊ |
442 | #if STRNCASECMP␊ |
443 | ␊ |
444 | //␊ |
445 | // Lame implementation just for use by strcasecmp/strncasecmp␊ |
446 | //␊ |
447 | static int␊ |
448 | tolower(unsigned char ch)␊ |
449 | {␊ |
450 | if (ch >= 'A' && ch <= 'Z')␊ |
451 | ␉␉ch = 'a' + (ch - 'A');␊ |
452 | ␉␊ |
453 | return ch;␊ |
454 | }␊ |
455 | ␊ |
456 | int␊ |
457 | strcasecmp(const char *s1, const char *s2)␊ |
458 | {␊ |
459 | const unsigned char *us1 = (const u_char *)s1,␊ |
460 | ␉*us2 = (const u_char *)s2;␊ |
461 | ␉␊ |
462 | while (tolower(*us1) == tolower(*us2++))␊ |
463 | ␉␉if (*us1++ == '\0')␊ |
464 | ␉␉␉return (0);␊ |
465 | return (tolower(*us1) - tolower(*--us2));␊ |
466 | }␊ |
467 | ␊ |
468 | int␊ |
469 | strncasecmp(const char *s1, const char *s2, size_t n)␊ |
470 | {␊ |
471 | if (n != 0) {␊ |
472 | ␉␉const unsigned char *us1 = (const u_char *)s1,␊ |
473 | ␉␉*us2 = (const u_char *)s2;␊ |
474 | ␉␉␊ |
475 | ␉␉do {␊ |
476 | ␉␉␉if (tolower(*us1) != tolower(*us2++))␊ |
477 | ␉␉␉␉return (tolower(*us1) - tolower(*--us2));␊ |
478 | ␉␉␉if (*us1++ == '\0')␊ |
479 | ␉␉␉␉break;␊ |
480 | ␉␉} while (--n != 0);␊ |
481 | }␊ |
482 | return (0);␊ |
483 | }␊ |
484 | #endif␊ |
485 | ␊ |
486 | /*␊ |
487 | *␊ |
488 | */␊ |
489 | ␊ |
490 | char *strchr(const char *str, int ch)␊ |
491 | {␊ |
492 | do {␊ |
493 | ␉␉if (*str == ch)␊ |
494 | ␉␉␉return(__CAST_AWAY_QUALIFIER(str, const, char *));␊ |
495 | } while (*str++);␊ |
496 | return ((char *) 0);␊ |
497 | } ␊ |
498 | ␊ |
499 | char* strbreak(const char *str, char **next, long *len)␊ |
500 | {␊ |
501 | char *start = (char*)str, *end;␊ |
502 | bool quoted = false;␊ |
503 | ␊ |
504 | if ( !start || !len )␊ |
505 | return 0;␊ |
506 | ␊ |
507 | *len = 0;␊ |
508 | ␊ |
509 | while ( isspace(*start) )␊ |
510 | start++;␊ |
511 | ␊ |
512 | if (*start == '"')␊ |
513 | {␊ |
514 | start++;␊ |
515 | ␊ |
516 | end = strchr(start, '"');␊ |
517 | if(end)␊ |
518 | quoted = true;␊ |
519 | else␊ |
520 | end = strchr(start, '\0');␊ |
521 | }␊ |
522 | else␊ |
523 | {␊ |
524 | for ( end = start; *end && !isspace(*end); end++ )␊ |
525 | {}␊ |
526 | }␊ |
527 | ␊ |
528 | *len = end - start;␊ |
529 | ␊ |
530 | if(next)␊ |
531 | *next = quoted ? end+1 : end;␊ |
532 | ␊ |
533 | return start;␊ |
534 | }␊ |
535 | ␊ |
536 | unsigned long␊ |
537 | adler32( unsigned char * buffer, long length )␊ |
538 | {␊ |
539 | long cnt;␊ |
540 | unsigned long result, lowHalf, highHalf;␊ |
541 | ␊ |
542 | lowHalf = 1;␊ |
543 | highHalf = 0;␊ |
544 | ␉␊ |
545 | ␉for ( cnt = 0; cnt < length; cnt++ )␊ |
546 | {␊ |
547 | if ((cnt % 5000) == 0)␊ |
548 | {␊ |
549 | lowHalf %= 65521L;␊ |
550 | highHalf %= 65521L;␊ |
551 | }␊ |
552 | ␉␉␊ |
553 | lowHalf += buffer[cnt];␊ |
554 | highHalf += lowHalf;␊ |
555 | }␊ |
556 | ␉␊ |
557 | ␉lowHalf %= 65521L;␊ |
558 | ␉highHalf %= 65521L;␊ |
559 | ␉␊ |
560 | ␉result = (highHalf << 16) | lowHalf;␊ |
561 | ␉␊ |
562 | ␉return result;␊ |
563 | }␊ |
564 | ␊ |
565 | /*-␊ |
566 | * For memcmp, bsearch.␊ |
567 | * Copyright (c) 1990, 1993␊ |
568 | *␉The Regents of the University of California. All rights reserved.␊ |
569 | *␊ |
570 | * This code is derived from software contributed to Berkeley by␊ |
571 | * Chris Torek.␊ |
572 | *␊ |
573 | * Redistribution and use in source and binary forms, with or without␊ |
574 | * modification, are permitted provided that the following conditions␊ |
575 | * are met:␊ |
576 | * 1. Redistributions of source code must retain the above copyright␊ |
577 | * notice, this list of conditions and the following disclaimer.␊ |
578 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
579 | * notice, this list of conditions and the following disclaimer in the␊ |
580 | * documentation and/or other materials provided with the distribution.␊ |
581 | * 4. Neither the name of the University nor the names of its contributors␊ |
582 | * may be used to endorse or promote products derived from this software␊ |
583 | * without specific prior written permission.␊ |
584 | *␊ |
585 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND␊ |
586 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE␊ |
587 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
588 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE␊ |
589 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
590 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS␊ |
591 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)␊ |
592 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT␊ |
593 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY␊ |
594 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF␊ |
595 | * SUCH DAMAGE.␊ |
596 | */␊ |
597 | ␊ |
598 | #if 0␊ |
599 | /*␊ |
600 | * Compare memory regions.␊ |
601 | */␊ |
602 | int␊ |
603 | memcmp(const void *s1, const void *s2, size_t n)␊ |
604 | {␊ |
605 | ␉if (n != 0) {␊ |
606 | ␉␉const unsigned char *p1 = s1, *p2 = s2;␊ |
607 | ␉␉␊ |
608 | ␉␉do {␊ |
609 | ␉␉␉if (*p1++ != *p2++)␊ |
610 | ␉␉␉␉return (*--p1 - *--p2);␊ |
611 | ␉␉} while (--n != 0);␊ |
612 | ␉}␊ |
613 | ␉return (0);␊ |
614 | }␊ |
615 | #endif␊ |
616 | /*␊ |
617 | * Perform a binary search.␊ |
618 | *␊ |
619 | * The code below is a bit sneaky. After a comparison fails, we␊ |
620 | * divide the work in half by moving either left or right. If lim␊ |
621 | * is odd, moving left simply involves halving lim: e.g., when lim␊ |
622 | * is 5 we look at item 2, so we change lim to 2 so that we will␊ |
623 | * look at items 0 & 1. If lim is even, the same applies. If lim␊ |
624 | * is odd, moving right again involes halving lim, this time moving␊ |
625 | * the base up one item past p: e.g., when lim is 5 we change base␊ |
626 | * to item 3 and make lim 2 so that we will look at items 3 and 4.␊ |
627 | * If lim is even, however, we have to shrink it by one before␊ |
628 | * halving: e.g., when lim is 4, we still looked at item 2, so we␊ |
629 | * have to make lim 3, then halve, obtaining 1, so that we will only␊ |
630 | * look at item 3.␊ |
631 | */␊ |
632 | void *␊ |
633 | bsearch(key, base0, nmemb, size, compar)␊ |
634 | register const void *key;␊ |
635 | const void *base0;␊ |
636 | size_t nmemb;␊ |
637 | register size_t size;␊ |
638 | register int (*compar)(const void *, const void *);␊ |
639 | {␊ |
640 | ␉register const char *base = base0;␊ |
641 | ␉register size_t lim;␊ |
642 | ␉register int cmp;␊ |
643 | ␉register const void *p;␊ |
644 | ␊ |
645 | ␉for (lim = nmemb; lim != 0; lim >>= 1) {␊ |
646 | ␉␉p = base + (lim >> 1) * size;␊ |
647 | ␉␉cmp = (*compar)(key, p);␊ |
648 | ␉␉if (cmp == 0)␊ |
649 | ␉␉␉return ((void *)(uintptr_t)p);␊ |
650 | ␉␉if (cmp > 0) {␉/* key > p: move right */␊ |
651 | ␉␉␉base = (const char *)p + size;␊ |
652 | ␉␉␉lim--;␊ |
653 | ␉␉}␉␉/* else move left */␊ |
654 | ␉}␊ |
655 | ␉return (NULL);␊ |
656 | }␊ |
657 | |