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
416 copy = calloc(len, sizeof(char));
417
418if (copy == NULL)
419return (NULL);
420bcopy(string, copy, len);
421return (copy);
422}
423
424char *strdup(const char *string)
425{
426if (string) {
427return STRDUP(string);
428}
429return (NULL);
430}
431
432#if STRNCASECMP
433
434//
435// Lame implementation just for use by strcasecmp/strncasecmp
436//
437static int
438tolower(unsigned char ch)
439{
440 if (ch >= 'A' && ch <= 'Z')
441ch = 'a' + (ch - 'A');
442
443 return ch;
444}
445
446int
447strcasecmp(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++))
453if (*us1++ == '\0')
454return (0);
455 return (tolower(*us1) - tolower(*--us2));
456}
457
458int
459strncasecmp(const char *s1, const char *s2, size_t n)
460{
461 if (n != 0) {
462const unsigned char *us1 = (const u_char *)s1,
463*us2 = (const u_char *)s2;
464
465do {
466if (tolower(*us1) != tolower(*us2++))
467return (tolower(*us1) - tolower(*--us2));
468if (*us1++ == '\0')
469break;
470} while (--n != 0);
471 }
472 return (0);
473}
474#endif
475/*
476 *
477 */
478
479char *strchr(const char *str, int ch)
480{
481 do {
482if (*str == ch)
483return(__CAST_AWAY_QUALIFIER(str, const, char *));
484 } while (*str++);
485 return ((char *) 0);
486}
487
488char* 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
525unsigned long
526local_adler32( unsigned char * buffer, long length )
527{
528 long cnt;
529 unsigned long result, lowHalf, highHalf;
530
531 lowHalf = 1;
532 highHalf = 0;
533
534for ( cnt = 0; cnt < length; cnt++ )
535 {
536 if ((cnt % 5000) == 0)
537 {
538 lowHalf %= 65521L;
539 highHalf %= 65521L;
540 }
541
542 lowHalf += buffer[cnt];
543 highHalf += lowHalf;
544 }
545
546lowHalf %= 65521L;
547highHalf %= 65521L;
548
549result = (highHalf << 16) | lowHalf;
550
551return result;
552}
553
554/*-
555 * For memcmp, bsearch, memchr , memcpy, memmove, bcopy.
556 * Copyright (c) 1990, 1993
557 *The Regents of the University of California. All rights reserved.
558 *
559 * This code is derived from software contributed to Berkeley by
560 * Chris Torek.
561 *
562 * Redistribution and use in source and binary forms, with or without
563 * modification, are permitted provided that the following conditions
564 * are met:
565 * 1. Redistributions of source code must retain the above copyright
566 * notice, this list of conditions and the following disclaimer.
567 * 2. Redistributions in binary form must reproduce the above copyright
568 * notice, this list of conditions and the following disclaimer in the
569 * documentation and/or other materials provided with the distribution.
570 * 4. Neither the name of the University nor the names of its contributors
571 * may be used to endorse or promote products derived from this software
572 * without specific prior written permission.
573 *
574 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
575 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
576 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
577 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
578 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
579 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
580 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
581 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
582 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
583 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
584 * SUCH DAMAGE.
585 */
586
587/*
588 * Compare memory regions.
589 */
590int
591memcmp(const void *s1, const void *s2, size_t n)
592{
593if (n != 0) {
594const unsigned char *p1 = s1, *p2 = s2;
595
596do {
597if (*p1++ != *p2++)
598return (*--p1 - *--p2);
599} while (--n != 0);
600}
601return (0);
602}
603
604/*
605 * Perform a binary search.
606 *
607 * The code below is a bit sneaky. After a comparison fails, we
608 * divide the work in half by moving either left or right. If lim
609 * is odd, moving left simply involves halving lim: e.g., when lim
610 * is 5 we look at item 2, so we change lim to 2 so that we will
611 * look at items 0 & 1. If lim is even, the same applies. If lim
612 * is odd, moving right again involes halving lim, this time moving
613 * the base up one item past p: e.g., when lim is 5 we change base
614 * to item 3 and make lim 2 so that we will look at items 3 and 4.
615 * If lim is even, however, we have to shrink it by one before
616 * halving: e.g., when lim is 4, we still looked at item 2, so we
617 * have to make lim 3, then halve, obtaining 1, so that we will only
618 * look at item 3.
619 */
620void *
621bsearch(key, base0, nmemb, size, compar)
622register const void *key;
623const void *base0;
624size_t nmemb;
625register size_t size;
626register int (*compar)(const void *, const void *);
627{
628register const char *base = base0;
629register size_t lim;
630register int cmp;
631register const void *p;
632
633for (lim = nmemb; lim != 0; lim >>= 1) {
634p = base + (lim >> 1) * size;
635cmp = (*compar)(key, p);
636if (cmp == 0)
637return ((void *)(uintptr_t)p);
638if (cmp > 0) {/* key > p: move right */
639base = (const char *)p + size;
640lim--;
641}/* else move left */
642}
643return (NULL);
644}
645
646void *
647memchr(const void *s, int c, size_t n)
648{
649if (n != 0) {
650const unsigned char *p = s;
651
652do {
653if (*p++ == (unsigned char)c)
654return ((void *)(p - 1));
655} while (--n != 0);
656}
657return (NULL);
658}
659
660#if 1
661/*
662 * sizeof(word) MUST BE A POWER OF TWO
663 * SO THAT wmask BELOW IS ALL ONES
664 */
665typedef int word; /* "word" used for optimal copy speed */
666
667#define wsize sizeof(word)
668#define wmask (wsize - 1)
669
670/*
671 * Copy a block of memory, handling overlap.
672 * This is the routine that actually implements
673 * (the portable versions of) bcopy, memcpy, and memmove.
674 */
675
676void
677bcopy(const void *src0, void *dst0, size_t length)
678{
679memcpy(dst0,src0,length);
680}
681
682void *memcpy(void *dst0, const void *src0, size_t length)
683{
684char *dst = dst0;
685const char *src = src0;
686size_t t;
687
688if (length == 0 || dst == src) /* nothing to do */
689goto done;
690
691/*
692 * Macros: loop-t-times; and loop-t-times, t>0
693 */
694#define TLOOP(s) if (t) TLOOP1(s)
695#define TLOOP1(s) do { s; } while (--t)
696
697if ((unsigned long)dst < (unsigned long)src) {
698/*
699 * Copy forward.
700 */
701t = (uintptr_t)src; /* only need low bits */
702if ((t | (uintptr_t)dst) & wmask) {
703/*
704 * Try to align operands. This cannot be done
705 * unless the low bits match.
706 */
707if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
708t = length;
709else
710t = wsize - (t & wmask);
711length -= t;
712TLOOP1(*dst++ = *src++);
713}
714/*
715 * Copy whole words, then mop up any trailing bytes.
716 */
717t = length / wsize;
718TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
719t = length & wmask;
720TLOOP(*dst++ = *src++);
721} else {
722/*
723 * Copy backwards. Otherwise essentially the same.
724 * Alignment works as before, except that it takes
725 * (t&wmask) bytes to align, not wsize-(t&wmask).
726 */
727src += length;
728dst += length;
729t = (uintptr_t)src;
730if ((t | (uintptr_t)dst) & wmask) {
731if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
732t = length;
733else
734t &= wmask;
735length -= t;
736TLOOP1(*--dst = *--src);
737}
738t = length / wsize;
739TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
740t = length & wmask;
741TLOOP(*--dst = *--src);
742}
743done:
744return (dst0);
745}
746
747
748#ifdef wsize
749#undef wsize
750#endif
751#ifdef wmask
752#undef wmask
753#endif
754#define wsize sizeof(u_int)
755#define wmask (wsize - 1)
756
757
758void bzero(void *dst0, size_t length)
759{
760#ifdef RETURN
761#undef RETURN
762#endif
763#ifdef VAL
764#undef VAL
765#endif
766#ifdef WIDEVAL
767#undef WIDEVAL
768#endif
769#define RETURN return
770#define VAL 0
771#define WIDEVAL 0
772
773size_t t;
774u_char *dst;
775
776dst = dst0;
777/*
778 * If not enough words, just fill bytes. A length >= 2 words
779 * guarantees that at least one of them is `complete' after
780 * any necessary alignment. For instance:
781 *
782 * |-----------|-----------|-----------|
783 * |00|01|02|03|04|05|06|07|08|09|0A|00|
784 * ^---------------------^
785 * dst dst+length-1
786 *
787 * but we use a minimum of 3 here since the overhead of the code
788 * to do word writes is substantial.
789 */
790if (length < 3 * wsize) {
791while (length != 0) {
792*dst++ = VAL;
793--length;
794}
795RETURN;
796}
797
798/* Align destination by filling in bytes. */
799if ((t = (long)dst & wmask) != 0) {
800t = wsize - t;
801length -= t;
802do {
803*dst++ = VAL;
804} while (--t != 0);
805}
806
807/* Fill words. Length was >= 2*words so we know t >= 1 here. */
808t = length / wsize;
809do {
810*(u_int *)dst = WIDEVAL;
811dst += wsize;
812} while (--t != 0);
813
814/* Mop up trailing bytes, if any. */
815t = length & wmask;
816if (t != 0)
817do {
818*dst++ = VAL;
819} while (--t != 0);
820RETURN;
821}
822
823
824void *
825memset(void *dst0, int c0, size_t length)
826{
827#ifdef RETURN
828#undef RETURN
829#endif
830#ifdef VAL
831#undef VAL
832#endif
833#ifdef WIDEVAL
834#undef WIDEVAL
835#endif
836
837#define VAL c0
838#define WIDEVAL c
839#define RETURN return (dst0)
840
841size_t t;
842u_int c;
843u_char *dst;
844
845dst = dst0;
846/*
847 * If not enough words, just fill bytes. A length >= 2 words
848 * guarantees that at least one of them is `complete' after
849 * any necessary alignment. For instance:
850 *
851 * |-----------|-----------|-----------|
852 * |00|01|02|03|04|05|06|07|08|09|0A|00|
853 * ^---------------------^
854 * dst dst+length-1
855 *
856 * but we use a minimum of 3 here since the overhead of the code
857 * to do word writes is substantial.
858 */
859if (length < 3 * wsize) {
860while (length != 0) {
861*dst++ = VAL;
862--length;
863}
864RETURN;
865}
866
867if ((c = (u_char)c0) != 0) { /* Fill the word. */
868c = (c << 8) | c; /* u_int is 16 bits. */
869#if UINT_MAX > 0xffff
870c = (c << 16) | c; /* u_int is 32 bits. */
871#endif
872#if UINT_MAX > 0xffffffff
873c = (c << 32) | c; /* u_int is 64 bits. */
874#endif
875}
876
877/* Align destination by filling in bytes. */
878if ((t = (long)dst & wmask) != 0) {
879t = wsize - t;
880length -= t;
881do {
882*dst++ = VAL;
883} while (--t != 0);
884}
885
886/* Fill words. Length was >= 2*words so we know t >= 1 here. */
887t = length / wsize;
888do {
889*(u_int *)dst = WIDEVAL;
890dst += wsize;
891} while (--t != 0);
892
893/* Mop up trailing bytes, if any. */
894t = length & wmask;
895if (t != 0)
896do {
897*dst++ = VAL;
898} while (--t != 0);
899RETURN;
900}
901
902#endif

Archive Download this file

Revision: HEAD