string.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Martin Decky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <string.h>
00036 #include <unistd.h>
00037 #include <ctype.h>
00038 #include <limits.h>
00039 #include <align.h>
00040 
00041 
00042 /* Dummy implementation of mem/ functions */
00043 
00044 void *memset(void *s, int c, size_t n)
00045 {
00046         char *os = s;
00047         
00048         while (n--)
00049                 *(os++) = c;
00050         
00051         return s;
00052 }
00053 
00054 struct along {
00055         unsigned long n;
00056 } __attribute__ ((packed));
00057 
00058 static void *unaligned_memcpy(void *dst, const void *src, size_t n)
00059 {
00060         int i, j;
00061         struct along *adst = dst;
00062         const struct along *asrc = src;
00063 
00064         for (i = 0; i < n / sizeof(unsigned long); i++)
00065                 adst[i].n = asrc[i].n;
00066                 
00067         for (j = 0; j < n % sizeof(unsigned long); j++)
00068                 ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
00069                 
00070         return (char *) src;
00071 }
00072 
00073 void *memcpy(void *dst, const void *src, size_t n)
00074 {
00075         int i, j;
00076 
00077         if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1)))
00078                 return unaligned_memcpy(dst, src, n);
00079 
00080         for (i = 0; i < n / sizeof(unsigned long); i++)
00081                 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
00082                 
00083         for (j = 0; j < n % sizeof(unsigned long); j++)
00084                 ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
00085                 
00086         return (char *) src;
00087 }
00088 
00089 void *memmove(void *dst, const void *src, size_t n)
00090 {
00091         int i, j;
00092         
00093         if (src > dst)
00094                 return memcpy(dst, src, n);
00095 
00096         for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
00097                 ((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j];
00098 
00099         for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
00100                 ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
00101                 
00102         return (char *) src;
00103 }
00104 
00105 
00110 size_t strlen(const char *str) 
00111 {
00112         size_t counter = 0;
00113 
00114         while (str[counter] != 0)
00115                 counter++;
00116 
00117         return counter;
00118 }
00119 
00120 int strcmp(const char *a, const char *b)
00121 {
00122         int c = 0;
00123         
00124         while (a[c] && b[c] && (!(a[c] - b[c])))
00125                 c++;
00126         
00127         return (a[c] - b[c]);
00128         
00129 }
00130 
00131 
00137 char *strchr(const char *str, int c)
00138 {
00139         while (*str != '\0') {
00140                 if (*str == (char) c)
00141                         return (char *) str;
00142                 str++;
00143         }
00144 
00145         return NULL;
00146 }
00147 
00153 char *strrchr(const char *str, int c)
00154 {
00155         char *retval = NULL;
00156 
00157         while (*str != '\0') {
00158                 if (*str == (char) c)
00159                         retval = (char *) str;
00160                 str++;
00161         }
00162 
00163         return (char *) retval;
00164 }
00165 
00174 static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
00175 {
00176         unsigned char c;
00177         unsigned long result = 0;
00178         unsigned long a, b;
00179         const char *str = nptr;
00180         const char *tmpptr;
00181         
00182         while (isspace(*str))
00183                 str++;
00184         
00185         if (*str == '-') {
00186                 *sgn = 1;
00187                 ++str;
00188         } else if (*str == '+')
00189                 ++str;
00190         
00191         if (base) {
00192                 if ((base == 1) || (base > 36)) {
00193                         /* FIXME: set errno to EINVAL */
00194                         return 0;
00195                 }
00196                 if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
00197                         str += 2;
00198                 }
00199         } else {
00200                 base = 10;
00201                 
00202                 if (*str == '0') {
00203                         base = 8;
00204                         if ((str[1] == 'X') || (str[1] == 'x'))  {
00205                                 base = 16;
00206                                 str += 2;
00207                         }
00208                 } 
00209         }
00210         
00211         tmpptr = str;
00212 
00213         while (*str) {
00214                 c = *str;
00215                 c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff)));
00216                 if (c > base) {
00217                         break;
00218                 }
00219                 
00220                 a = (result & 0xff) * base + c;
00221                 b = (result >> 8) * base + (a >> 8);
00222                 
00223                 if (b > (ULONG_MAX >> 8)) {
00224                         /* overflow */
00225                         /* FIXME: errno = ERANGE*/
00226                         return ULONG_MAX;
00227                 }
00228         
00229                 result = (b << 8) + (a & 0xff);
00230                 ++str;
00231         }
00232         
00233         if (str == tmpptr) {
00234                 /* no number was found => first invalid character is the first character of the string */
00235                 /* FIXME: set errno to EINVAL */
00236                 str = nptr;
00237                 result = 0;
00238         }
00239         
00240         if (endptr)
00241                 *endptr = (char *) str;
00242 
00243         if (nptr == str) { 
00244                 /*FIXME: errno = EINVAL*/
00245                 return 0;
00246         }
00247 
00248         return result;
00249 }
00250 
00261 long int strtol(const char *nptr, char **endptr, int base)
00262 {
00263         char sgn = 0;
00264         unsigned long number = 0;
00265         
00266         number = _strtoul(nptr, endptr, base, &sgn);
00267 
00268         if (number > LONG_MAX) {
00269                 if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
00270                         /* FIXME: set 0 to errno */
00271                         return number;          
00272                 }
00273                 /* FIXME: set ERANGE to errno */
00274                 return (sgn ? LONG_MIN : LONG_MAX);     
00275         }
00276         
00277         return (sgn ? -number : number);
00278 }
00279 
00280 
00291 unsigned long strtoul(const char *nptr, char **endptr, int base)
00292 {
00293         char sgn = 0;
00294         unsigned long number = 0;
00295         
00296         number = _strtoul(nptr, endptr, base, &sgn);
00297 
00298         return (sgn ? -number : number);
00299 }
00300 
00301 char *strcpy(char *dest, const char *src)
00302 {
00303         char *orig = dest;
00304         
00305         while ((*(dest++) = *(src++)));
00306         return orig;
00307 }
00308 
00309 char *strncpy(char *dest, const char *src, size_t n)
00310 {
00311         char *orig = dest;
00312         
00313         while ((*(dest++) = *(src++)) && --n);
00314         return orig;
00315 }
00316 
00317 

Generated on Sun Jun 18 18:00:18 2006 for HelenOS Userspace (ia64) by  doxygen 1.4.6