Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsa/string.c

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
28static int _mach_strlen(const char *str);
29static 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
45int
46strcmp(
47 const char *s1,
48 const char *s2)
49{
50unsigned int a, b;
51
52do {
53a = *s1++;
54b = *s2++;
55if (a != b)
56return a-b; /* includes case when
57 'a' is zero and 'b' is not zero
58 or vice versa */
59} while (a != '\0');
60
61return 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
71int
72strncmp(
73 const char *s1,
74 const char *s2,
75 size_t n)
76{
77unsigned int a, b;
78
79while (n != 0) {
80a = *s1++;
81b = *s2++;
82if (a != b)
83return a-b; /* includes case when
84 'a' is zero and 'b' is not zero
85 or vice versa */
86if (a == '\0')
87return 0; /* both are zero */
88n--;
89}
90
91return 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 */
102char *
103strcpy(
104 char *to,
105 const char *from)
106{
107char *ret = to;
108
109while ((*to++ = *from++) != '\0')
110continue;
111
112return 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
124char *
125strncpy(
126char *s1,
127const char *s2,
128size_t n)
129{
130char *os1 = s1;
131unsigned long i;
132
133for (i = 0; i < n;)
134if ((*s1++ = *s2++) == '\0')
135for (i++; i < n; i++)
136*s1++ = '\0';
137else
138i++;
139return (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 */
147size_t
148strlcpy(char *dst, const char *src, size_t siz)
149{
150char *d = dst;
151const char *s = src;
152size_t n = siz;
153
154/* Copy as many bytes as will fit */
155if (n != 0 && --n != 0) {
156do {
157if ((*d++ = *s++) == 0)
158break;
159} while (--n != 0);
160}
161
162/* Not enough room in dst, add NUL and traverse rest of src */
163if (n == 0) {
164if (siz != 0)
165*d = '\0';/* NUL-terminate dst */
166while (*s++)
167;
168}
169
170return(s - src - 1);/* count does not include NUL */
171}
172
173/*
174 * History:
175 * 2002-01-24 gvdlInitial implementation of strstr
176 */
177
178const char *
179strstr(const char *in, const char *str)
180{
181 char c;
182 size_t len;
183
184 c = *str++;
185 if (!c)
186 return (const char *) in;// Trivial empty string case
187
188 len = strlen(str);
189 do {
190 char sc;
191
192 do {
193 sc = *in++;
194 if (!sc)
195 return (char *) 0;
196 } while (sc != c);
197 } while (strncmp(in, str, len) != 0);
198
199 return (const char *) (in - 1);
200}
201
202void *
203memmove(void *dst, const void *src, size_t ulen)
204{
205 bcopy(src, dst, ulen);
206 return dst;
207}
208
209int
210ptol(const char *str)
211{
212register int c = *str;
213
214if (c <= '7' && c >= '0')
215c -= '0';
216else if (c <= 'h' && c >= 'a')
217c -= 'a';
218else c = 0;
219return c;
220}
221
222/*
223 * atoi:
224 *
225 * This function converts an ascii string into an integer.
226 *
227 * input : string
228 * output : a number
229 */
230
231int
232atoi(const char *cp)
233{
234int number;
235
236for (number = 0; ('0' <= *cp) && (*cp <= '9'); cp++)
237number = (number * 10) + (*cp - '0');
238
239return( number );
240}
241
242/*
243 * convert an integer to an ASCII string.
244 * inputs:
245 *numinteger to be converted
246 *strstring pointer.
247 *
248 * outputs:
249 *pointer to string start.
250 */
251
252char *
253itoa(
254 intnum,
255 char*str)
256{
257char digits[11];
258char *dp;
259char *cp = str;
260
261if (num == 0) {
262*cp++ = '0';
263}
264else {
265dp = digits;
266while (num) {
267*dp++ = '0' + num % 10;
268num /= 10;
269}
270while (dp != digits) {
271*cp++ = *--dp;
272}
273}
274*cp++ = '\0';
275
276return str;
277}
278/*
279 * Appends src to string dst of size siz (unlike strncat, siz is the
280 * full size of dst, not space left). At most siz-1 characters
281 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
282 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
283 * If retval >= siz, truncation occurred.
284 */
285size_t
286strlcat(char *dst, const char *src, size_t siz)
287{
288char *d = dst;
289const char *s = src;
290size_t n = siz;
291size_t dlen;
292
293/* Find the end of dst and adjust bytes left but don't go past end */
294while (n-- != 0 && *d != '\0')
295d++;
296dlen = d - dst;
297n = siz - dlen;
298
299if (n == 0)
300return(dlen + strlen(s));
301while (*s != '\0') {
302if (n != 1) {
303*d++ = *s;
304n--;
305}
306s++;
307}
308*d = '\0';
309
310return(dlen + (s - src)); /* count does not include NUL */
311}
312
313/*
314 *
315 */
316
317char *
318strncat(char *s1, const char *s2, unsigned long n)
319{
320char *os1;
321int i = n;
322
323os1 = s1;
324while (*s1++)
325;
326--s1;
327while ((*s1++ = *s2++))
328if (--i < 0) {
329*--s1 = '\0';
330break;
331}
332return(os1);
333}
334
335static int
336_mach_strlen(const char *str)
337{
338const char *p;
339for (p = str; p; p++) {
340if (*p == '\0') {
341return (p - str);
342}
343}
344/* NOTREACHED */
345return 0;
346}
347
348size_t strlen(const char * str)
349{
350return (size_t)_mach_strlen(str);
351}
352
353/*
354 * Does the same thing as strlen, except only looks up
355 * to max chars inside the buffer.
356 * Taken from archive/kern-stuff/sbf_machine.c in
357 * seatbelt.
358 * inputs:
359 * sstring whose length is to be measured
360 *maxmaximum length of string to search for null
361 * outputs:
362 *length of s or max; whichever is smaller
363 */
364size_t
365strnlen(const char *s, size_t max) {
366const char *es = s + max, *p = s;
367while(*p && p != es)
368p++;
369
370return p - s;
371}
372
373/*
374 * Deprecation Warning:
375 *strcat() is being deprecated. Please use strlcat() instead.
376 */
377char *
378strcat(
379 char *dest,
380 const char *src)
381{
382char *old = dest;
383
384while (*dest)
385++dest;
386while ((*dest++ = *src++))
387;
388return (old);
389}
390
391/*
392 * STRDUP
393 *
394 * Description: The STRDUP function allocates sufficient memory for a copy
395 * of the string "string", does the copy, and returns a pointer
396 * it. The pointer may subsequently be used as an argument to
397 * the macro FREE().
398 *
399 * Parameters: stringString to be duplicated
400 *
401 * Returns: char * A pointer to the newly allocated string with
402 * duplicated contents in it.
403 *
404 * NULLIf MALLOC() fails.
405 *
406 */
407
408static char *
409STRDUP(const char *string)
410{
411size_t len;
412char *copy;
413
414len = strlen(string) + 1;
415#if (defined(MEMORY_TEST))
416copy = _malloc(len);
417#else
418 copy = malloc(len);
419#endif
420if (copy == NULL)
421return (NULL);
422bcopy(string, copy, len);
423return (copy);
424}
425
426char *strdup(const char *string)
427{
428if (string) {
429return STRDUP(string);
430}
431return (NULL);
432}
433
434#if STRNCASECMP
435
436//
437// Lame implementation just for use by strcasecmp/strncasecmp
438//
439static int
440tolower(unsigned char ch)
441{
442 if (ch >= 'A' && ch <= 'Z')
443ch = 'a' + (ch - 'A');
444
445 return ch;
446}
447
448int
449strcasecmp(const char *s1, const char *s2)
450{
451 const unsigned char *us1 = (const u_char *)s1,
452*us2 = (const u_char *)s2;
453
454 while (tolower(*us1) == tolower(*us2++))
455if (*us1++ == '\0')
456return (0);
457 return (tolower(*us1) - tolower(*--us2));
458}
459
460int
461strncasecmp(const char *s1, const char *s2, size_t n)
462{
463 if (n != 0) {
464const unsigned char *us1 = (const u_char *)s1,
465*us2 = (const u_char *)s2;
466
467do {
468if (tolower(*us1) != tolower(*us2++))
469return (tolower(*us1) - tolower(*--us2));
470if (*us1++ == '\0')
471break;
472} while (--n != 0);
473 }
474 return (0);
475}
476#endif
477/*
478 *
479 */
480
481char *strchr(const char *str, int ch)
482{
483 do {
484if (*str == ch)
485return(__CAST_AWAY_QUALIFIER(str, const, char *));
486 } while (*str++);
487 return ((char *) 0);
488}
489
490char* strbreak(const char *str, char **next, long *len)
491{
492 char *start = (char*)str, *end;
493 bool quoted = false;
494
495 if ( !start || !len )
496 return 0;
497
498 *len = 0;
499
500 while ( isspace(*start) )
501 start++;
502
503 if (*start == '"')
504 {
505 start++;
506
507 end = strchr(start, '"');
508 if(end)
509 quoted = true;
510 else
511 end = strchr(start, '\0');
512 }
513 else
514 {
515 for ( end = start; *end && !isspace(*end); end++ )
516 {}
517 }
518
519 *len = end - start;
520
521 if(next)
522 *next = quoted ? end+1 : end;
523
524 return start;
525}
526
527unsigned long
528local_adler32( unsigned char * buffer, long length )
529{
530 long cnt;
531 unsigned long result, lowHalf, highHalf;
532
533 lowHalf = 1;
534 highHalf = 0;
535
536for ( cnt = 0; cnt < length; cnt++ )
537 {
538 if ((cnt % 5000) == 0)
539 {
540 lowHalf %= 65521L;
541 highHalf %= 65521L;
542 }
543
544 lowHalf += buffer[cnt];
545 highHalf += lowHalf;
546 }
547
548lowHalf %= 65521L;
549highHalf %= 65521L;
550
551result = (highHalf << 16) | lowHalf;
552
553return result;
554}
555
556/*-
557 * For memcmp, bsearch, memchr , memcpy, memmove, bcopy.
558 * Copyright (c) 1990, 1993
559 *The Regents of the University of California. All rights reserved.
560 *
561 * This code is derived from software contributed to Berkeley by
562 * Chris Torek.
563 *
564 * Redistribution and use in source and binary forms, with or without
565 * modification, are permitted provided that the following conditions
566 * are met:
567 * 1. Redistributions of source code must retain the above copyright
568 * notice, this list of conditions and the following disclaimer.
569 * 2. Redistributions in binary form must reproduce the above copyright
570 * notice, this list of conditions and the following disclaimer in the
571 * documentation and/or other materials provided with the distribution.
572 * 4. Neither the name of the University nor the names of its contributors
573 * may be used to endorse or promote products derived from this software
574 * without specific prior written permission.
575 *
576 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
577 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
578 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
579 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
580 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
581 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
582 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
583 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
584 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
585 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
586 * SUCH DAMAGE.
587 */
588
589/*
590 * Compare memory regions.
591 */
592int
593memcmp(const void *s1, const void *s2, size_t n)
594{
595if (n != 0) {
596const unsigned char *p1 = s1, *p2 = s2;
597
598do {
599if (*p1++ != *p2++)
600return (*--p1 - *--p2);
601} while (--n != 0);
602}
603return (0);
604}
605
606/*
607 * Perform a binary search.
608 *
609 * The code below is a bit sneaky. After a comparison fails, we
610 * divide the work in half by moving either left or right. If lim
611 * is odd, moving left simply involves halving lim: e.g., when lim
612 * is 5 we look at item 2, so we change lim to 2 so that we will
613 * look at items 0 & 1. If lim is even, the same applies. If lim
614 * is odd, moving right again involes halving lim, this time moving
615 * the base up one item past p: e.g., when lim is 5 we change base
616 * to item 3 and make lim 2 so that we will look at items 3 and 4.
617 * If lim is even, however, we have to shrink it by one before
618 * halving: e.g., when lim is 4, we still looked at item 2, so we
619 * have to make lim 3, then halve, obtaining 1, so that we will only
620 * look at item 3.
621 */
622void *
623bsearch(key, base0, nmemb, size, compar)
624register const void *key;
625const void *base0;
626size_t nmemb;
627register size_t size;
628register int (*compar)(const void *, const void *);
629{
630register const char *base = base0;
631register size_t lim;
632register int cmp;
633register const void *p;
634
635for (lim = nmemb; lim != 0; lim >>= 1) {
636p = base + (lim >> 1) * size;
637cmp = (*compar)(key, p);
638if (cmp == 0)
639return ((void *)(uintptr_t)p);
640if (cmp > 0) {/* key > p: move right */
641base = (const char *)p + size;
642lim--;
643}/* else move left */
644}
645return (NULL);
646}
647
648void *
649memchr(const void *s, int c, size_t n)
650{
651if (n != 0) {
652const unsigned char *p = s;
653
654do {
655if (*p++ == (unsigned char)c)
656return ((void *)(p - 1));
657} while (--n != 0);
658}
659return (NULL);
660}
661
662#if 1
663/*
664 * sizeof(word) MUST BE A POWER OF TWO
665 * SO THAT wmask BELOW IS ALL ONES
666 */
667typedef int word; /* "word" used for optimal copy speed */
668
669#define wsize sizeof(word)
670#define wmask (wsize - 1)
671
672/*
673 * Copy a block of memory, handling overlap.
674 * This is the routine that actually implements
675 * (the portable versions of) bcopy, memcpy, and memmove.
676 */
677
678void
679bcopy(const void *src0, void *dst0, size_t length)
680{
681memcpy(dst0,src0,length);
682}
683
684void *memcpy(void *dst0, const void *src0, size_t length)
685{
686char *dst = dst0;
687const char *src = src0;
688size_t t;
689
690if (length == 0 || dst == src) /* nothing to do */
691goto done;
692
693/*
694 * Macros: loop-t-times; and loop-t-times, t>0
695 */
696#define TLOOP(s) if (t) TLOOP1(s)
697#define TLOOP1(s) do { s; } while (--t)
698
699if ((unsigned long)dst < (unsigned long)src) {
700/*
701 * Copy forward.
702 */
703t = (uintptr_t)src; /* only need low bits */
704if ((t | (uintptr_t)dst) & wmask) {
705/*
706 * Try to align operands. This cannot be done
707 * unless the low bits match.
708 */
709if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
710t = length;
711else
712t = wsize - (t & wmask);
713length -= t;
714TLOOP1(*dst++ = *src++);
715}
716/*
717 * Copy whole words, then mop up any trailing bytes.
718 */
719t = length / wsize;
720TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
721t = length & wmask;
722TLOOP(*dst++ = *src++);
723} else {
724/*
725 * Copy backwards. Otherwise essentially the same.
726 * Alignment works as before, except that it takes
727 * (t&wmask) bytes to align, not wsize-(t&wmask).
728 */
729src += length;
730dst += length;
731t = (uintptr_t)src;
732if ((t | (uintptr_t)dst) & wmask) {
733if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
734t = length;
735else
736t &= wmask;
737length -= t;
738TLOOP1(*--dst = *--src);
739}
740t = length / wsize;
741TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
742t = length & wmask;
743TLOOP(*--dst = *--src);
744}
745done:
746return (dst0);
747}
748
749
750#ifdef wsize
751#undef wsize
752#endif
753#ifdef wmask
754#undef wmask
755#endif
756#define wsize sizeof(u_int)
757#define wmask (wsize - 1)
758
759
760void bzero(void *dst0, size_t length)
761{
762#ifdef RETURN
763#undef RETURN
764#endif
765#ifdef VAL
766#undef VAL
767#endif
768#ifdef WIDEVAL
769#undef WIDEVAL
770#endif
771#define RETURN return
772#define VAL 0
773#define WIDEVAL 0
774
775size_t t;
776u_char *dst;
777
778dst = dst0;
779/*
780 * If not enough words, just fill bytes. A length >= 2 words
781 * guarantees that at least one of them is `complete' after
782 * any necessary alignment. For instance:
783 *
784 * |-----------|-----------|-----------|
785 * |00|01|02|03|04|05|06|07|08|09|0A|00|
786 * ^---------------------^
787 * dst dst+length-1
788 *
789 * but we use a minimum of 3 here since the overhead of the code
790 * to do word writes is substantial.
791 */
792if (length < 3 * wsize) {
793while (length != 0) {
794*dst++ = VAL;
795--length;
796}
797RETURN;
798}
799
800/* Align destination by filling in bytes. */
801if ((t = (long)dst & wmask) != 0) {
802t = wsize - t;
803length -= t;
804do {
805*dst++ = VAL;
806} while (--t != 0);
807}
808
809/* Fill words. Length was >= 2*words so we know t >= 1 here. */
810t = length / wsize;
811do {
812*(u_int *)dst = WIDEVAL;
813dst += wsize;
814} while (--t != 0);
815
816/* Mop up trailing bytes, if any. */
817t = length & wmask;
818if (t != 0)
819do {
820*dst++ = VAL;
821} while (--t != 0);
822RETURN;
823}
824
825
826void *
827memset(void *dst0, int c0, size_t length)
828{
829#ifdef RETURN
830#undef RETURN
831#endif
832#ifdef VAL
833#undef VAL
834#endif
835#ifdef WIDEVAL
836#undef WIDEVAL
837#endif
838
839#define VAL c0
840#define WIDEVAL c
841#define RETURN return (dst0)
842
843size_t t;
844u_int c;
845u_char *dst;
846
847dst = dst0;
848/*
849 * If not enough words, just fill bytes. A length >= 2 words
850 * guarantees that at least one of them is `complete' after
851 * any necessary alignment. For instance:
852 *
853 * |-----------|-----------|-----------|
854 * |00|01|02|03|04|05|06|07|08|09|0A|00|
855 * ^---------------------^
856 * dst dst+length-1
857 *
858 * but we use a minimum of 3 here since the overhead of the code
859 * to do word writes is substantial.
860 */
861if (length < 3 * wsize) {
862while (length != 0) {
863*dst++ = VAL;
864--length;
865}
866RETURN;
867}
868
869if ((c = (u_char)c0) != 0) { /* Fill the word. */
870c = (c << 8) | c; /* u_int is 16 bits. */
871#if UINT_MAX > 0xffff
872c = (c << 16) | c; /* u_int is 32 bits. */
873#endif
874#if UINT_MAX > 0xffffffff
875c = (c << 32) | c; /* u_int is 64 bits. */
876#endif
877}
878
879/* Align destination by filling in bytes. */
880if ((t = (long)dst & wmask) != 0) {
881t = wsize - t;
882length -= t;
883do {
884*dst++ = VAL;
885} while (--t != 0);
886}
887
888/* Fill words. Length was >= 2*words so we know t >= 1 here. */
889t = length / wsize;
890do {
891*(u_int *)dst = WIDEVAL;
892dst += wsize;
893} while (--t != 0);
894
895/* Mop up trailing bytes, if any. */
896t = length & wmask;
897if (t != 0)
898do {
899*dst++ = VAL;
900} while (--t != 0);
901RETURN;
902}
903
904#endif

Archive Download this file

Revision: 2154