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 | ␊ |
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 | ␊ |
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 | ␊ |
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 | ␊ |
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 | ␊ |
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 | ␊ |
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 | static char *␊ |
410 | STRDUP(const char *string)␊ |
411 | {␊ |
412 | ␉size_t len;␊ |
413 | ␉char *copy; ␊ |
414 | ␉␊ |
415 | ␉len = strlen(string) + 1;␊ |
416 | ␉copy = malloc(len);␊ |
417 | ␉if (copy == NULL)␊ |
418 | ␉␉return (NULL);␊ |
419 | ␉bcopy(string, copy, len);␊ |
420 | ␉return (copy); ␊ |
421 | }␊ |
422 | ␊ |
423 | char *strdup(const char *string)␊ |
424 | {␊ |
425 | ␉if (string) {␊ |
426 | ␉␉return STRDUP(string);␊ |
427 | ␉}␊ |
428 | ␉return (NULL);␊ |
429 | }␊ |
430 | ␊ |
431 | #if STRNCASECMP␊ |
432 | ␊ |
433 | //␊ |
434 | // Lame implementation just for use by strcasecmp/strncasecmp␊ |
435 | //␊ |
436 | static int␊ |
437 | tolower(unsigned char ch)␊ |
438 | {␊ |
439 | if (ch >= 'A' && ch <= 'Z')␊ |
440 | ␉␉ch = 'a' + (ch - 'A');␊ |
441 | ␉␊ |
442 | return ch;␊ |
443 | }␊ |
444 | ␊ |
445 | int␊ |
446 | strcasecmp(const char *s1, const char *s2)␊ |
447 | {␊ |
448 | const unsigned char *us1 = (const u_char *)s1,␊ |
449 | ␉*us2 = (const u_char *)s2;␊ |
450 | ␉␊ |
451 | while (tolower(*us1) == tolower(*us2++))␊ |
452 | ␉␉if (*us1++ == '\0')␊ |
453 | ␉␉␉return (0);␊ |
454 | return (tolower(*us1) - tolower(*--us2));␊ |
455 | }␊ |
456 | ␊ |
457 | int␊ |
458 | strncasecmp(const char *s1, const char *s2, size_t n)␊ |
459 | {␊ |
460 | if (n != 0) {␊ |
461 | ␉␉const unsigned char *us1 = (const u_char *)s1,␊ |
462 | ␉␉*us2 = (const u_char *)s2;␊ |
463 | ␉␉␊ |
464 | ␉␉do {␊ |
465 | ␉␉␉if (tolower(*us1) != tolower(*us2++))␊ |
466 | ␉␉␉␉return (tolower(*us1) - tolower(*--us2));␊ |
467 | ␉␉␉if (*us1++ == '\0')␊ |
468 | ␉␉␉␉break;␊ |
469 | ␉␉} while (--n != 0);␊ |
470 | }␊ |
471 | return (0);␊ |
472 | }␊ |
473 | #endif␊ |
474 | ␊ |
475 | /*␊ |
476 | *␊ |
477 | */␊ |
478 | ␊ |
479 | char *strchr(const char *str, int ch)␊ |
480 | {␊ |
481 | do {␊ |
482 | ␉␉if (*str == ch)␊ |
483 | ␉␉␉return(__CAST_AWAY_QUALIFIER(str, const, char *));␊ |
484 | } while (*str++);␊ |
485 | return ((char *) 0);␊ |
486 | } ␊ |
487 | ␊ |
488 | char* strbreak(const char *str, char **next, long *len)␊ |
489 | {␊ |
490 | char *start = (char*)str, *end;␊ |
491 | bool quoted = false;␊ |
492 | ␊ |
493 | if ( !start || !len )␊ |
494 | return 0;␊ |
495 | ␊ |
496 | *len = 0;␊ |
497 | ␊ |
498 | while ( isspace(*start) )␊ |
499 | start++;␊ |
500 | ␊ |
501 | if (*start == '"')␊ |
502 | {␊ |
503 | start++;␊ |
504 | ␊ |
505 | end = strchr(start, '"');␊ |
506 | if(end)␊ |
507 | quoted = true;␊ |
508 | else␊ |
509 | end = strchr(start, '\0');␊ |
510 | }␊ |
511 | else␊ |
512 | {␊ |
513 | for ( end = start; *end && !isspace(*end); end++ )␊ |
514 | {}␊ |
515 | }␊ |
516 | ␊ |
517 | *len = end - start;␊ |
518 | ␊ |
519 | if(next)␊ |
520 | *next = quoted ? end+1 : end;␊ |
521 | ␊ |
522 | return start;␊ |
523 | }␊ |
524 | ␊ |
525 | /* COPYRIGHT NOTICE: checksum8 from AppleSMBIOS */␊ |
526 | uint8_t checksum8( void * start, unsigned int length )␊ |
527 | {␊ |
528 | uint8_t csum = 0;␊ |
529 | uint8_t * cp = (uint8_t *) start;␊ |
530 | unsigned int i;␊ |
531 | ␉␊ |
532 | for ( i = 0; i < length; i++)␊ |
533 | csum += *cp++;␊ |
534 | ␉␊ |
535 | return csum;␊ |
536 | }␊ |
537 | ␊ |
538 | unsigned long␊ |
539 | adler32( unsigned char * buffer, long length )␊ |
540 | {␊ |
541 | long cnt;␊ |
542 | unsigned long result, lowHalf, highHalf;␊ |
543 | ␊ |
544 | lowHalf = 1;␊ |
545 | highHalf = 0;␊ |
546 | ␉␊ |
547 | ␉for ( cnt = 0; cnt < length; cnt++ )␊ |
548 | {␊ |
549 | if ((cnt % 5000) == 0)␊ |
550 | {␊ |
551 | lowHalf %= 65521L;␊ |
552 | highHalf %= 65521L;␊ |
553 | }␊ |
554 | ␉␉␊ |
555 | lowHalf += buffer[cnt];␊ |
556 | highHalf += lowHalf;␊ |
557 | }␊ |
558 | ␉␊ |
559 | ␉lowHalf %= 65521L;␊ |
560 | ␉highHalf %= 65521L;␊ |
561 | ␉␊ |
562 | ␉result = (highHalf << 16) | lowHalf;␊ |
563 | ␉␊ |
564 | ␉return result;␊ |
565 | }␊ |
566 | ␊ |
567 | static long holdrand = 1L;␊ |
568 | #define␉RAND_MAX␉0x7fffffff␊ |
569 | ␊ |
570 | void srand (unsigned int seed)␊ |
571 | {␊ |
572 | ␉holdrand = (long)seed;␊ |
573 | }␊ |
574 | ␊ |
575 | int rand (void)␊ |
576 | {␉␊ |
577 | ␉holdrand = holdrand * 214013L + 2531011L;␊ |
578 | ␉return ((holdrand >> 16) & RAND_MAX);␊ |
579 | }␊ |
580 | ␊ |
581 | /*-␊ |
582 | * For memcmp, bsearch.␊ |
583 | * Copyright (c) 1990, 1993␊ |
584 | *␉The Regents of the University of California. All rights reserved.␊ |
585 | *␊ |
586 | * This code is derived from software contributed to Berkeley by␊ |
587 | * Chris Torek.␊ |
588 | *␊ |
589 | * Redistribution and use in source and binary forms, with or without␊ |
590 | * modification, are permitted provided that the following conditions␊ |
591 | * are met:␊ |
592 | * 1. Redistributions of source code must retain the above copyright␊ |
593 | * notice, this list of conditions and the following disclaimer.␊ |
594 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
595 | * notice, this list of conditions and the following disclaimer in the␊ |
596 | * documentation and/or other materials provided with the distribution.␊ |
597 | * 4. Neither the name of the University nor the names of its contributors␊ |
598 | * may be used to endorse or promote products derived from this software␊ |
599 | * without specific prior written permission.␊ |
600 | *␊ |
601 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND␊ |
602 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE␊ |
603 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
604 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE␊ |
605 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
606 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS␊ |
607 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)␊ |
608 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT␊ |
609 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY␊ |
610 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF␊ |
611 | * SUCH DAMAGE.␊ |
612 | */␊ |
613 | ␊ |
614 | /*␊ |
615 | * Compare memory regions.␊ |
616 | */␊ |
617 | int␊ |
618 | memcmp(const void *s1, const void *s2, size_t n)␊ |
619 | {␊ |
620 | ␉if (n != 0) {␊ |
621 | ␉␉const unsigned char *p1 = s1, *p2 = s2;␊ |
622 | ␉␉␊ |
623 | ␉␉do {␊ |
624 | ␉␉␉if (*p1++ != *p2++)␊ |
625 | ␉␉␉␉return (*--p1 - *--p2);␊ |
626 | ␉␉} while (--n != 0);␊ |
627 | ␉}␊ |
628 | ␉return (0);␊ |
629 | }␊ |
630 | ␊ |
631 | /*␊ |
632 | * Perform a binary search.␊ |
633 | *␊ |
634 | * The code below is a bit sneaky. After a comparison fails, we␊ |
635 | * divide the work in half by moving either left or right. If lim␊ |
636 | * is odd, moving left simply involves halving lim: e.g., when lim␊ |
637 | * is 5 we look at item 2, so we change lim to 2 so that we will␊ |
638 | * look at items 0 & 1. If lim is even, the same applies. If lim␊ |
639 | * is odd, moving right again involes halving lim, this time moving␊ |
640 | * the base up one item past p: e.g., when lim is 5 we change base␊ |
641 | * to item 3 and make lim 2 so that we will look at items 3 and 4.␊ |
642 | * If lim is even, however, we have to shrink it by one before␊ |
643 | * halving: e.g., when lim is 4, we still looked at item 2, so we␊ |
644 | * have to make lim 3, then halve, obtaining 1, so that we will only␊ |
645 | * look at item 3.␊ |
646 | */␊ |
647 | void *␊ |
648 | bsearch(key, base0, nmemb, size, compar)␊ |
649 | register const void *key;␊ |
650 | const void *base0;␊ |
651 | size_t nmemb;␊ |
652 | register size_t size;␊ |
653 | register int (*compar)(const void *, const void *);␊ |
654 | {␊ |
655 | ␉register const char *base = base0;␊ |
656 | ␉register size_t lim;␊ |
657 | ␉register int cmp;␊ |
658 | ␉register const void *p;␊ |
659 | ␊ |
660 | ␉for (lim = nmemb; lim != 0; lim >>= 1) {␊ |
661 | ␉␉p = base + (lim >> 1) * size;␊ |
662 | ␉␉cmp = (*compar)(key, p);␊ |
663 | ␉␉if (cmp == 0)␊ |
664 | ␉␉␉return ((void *)(uintptr_t)p);␊ |
665 | ␉␉if (cmp > 0) {␉/* key > p: move right */␊ |
666 | ␉␉␉base = (const char *)p + size;␊ |
667 | ␉␉␉lim--;␊ |
668 | ␉␉}␉␉/* else move left */␊ |
669 | ␉}␊ |
670 | ␉return (NULL);␊ |
671 | } |