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