Subversion Repositories HelenOS

Rev

Rev 2541 | Rev 3238 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Martin Decky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include <ctype.h>
  38. #include <limits.h>
  39. #include <align.h>
  40. #include <sys/types.h>
  41.  
  42.  
  43. /* Dummy implementation of mem/ functions */
  44.  
  45. void *memset(void *s, int c, size_t n)
  46. {
  47.     char *os = s;
  48.    
  49.     while (n--)
  50.         *(os++) = c;
  51.    
  52.     return s;
  53. }
  54.  
  55. struct along {
  56.     unsigned long n;
  57. } __attribute__ ((packed));
  58.  
  59. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  60. {
  61.     int i, j;
  62.     struct along *adst = dst;
  63.     const struct along *asrc = src;
  64.  
  65.     for (i = 0; i < n / sizeof(unsigned long); i++)
  66.         adst[i].n = asrc[i].n;
  67.        
  68.     for (j = 0; j < n % sizeof(unsigned long); j++)
  69.         ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
  70.        
  71.     return (char *) src;
  72. }
  73.  
  74. void *memcpy(void *dst, const void *src, size_t n)
  75. {
  76.     int i, j;
  77.  
  78.     if (((long) dst & (sizeof(long) - 1)) || ((long) src & (sizeof(long) - 1)))
  79.         return unaligned_memcpy(dst, src, n);
  80.  
  81.     for (i = 0; i < n / sizeof(unsigned long); i++)
  82.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  83.        
  84.     for (j = 0; j < n % sizeof(unsigned long); j++)
  85.         ((unsigned char *) (((unsigned long *) dst) + i))[j] = ((unsigned char *) (((unsigned long *) src) + i))[j];
  86.        
  87.     return (char *) src;
  88. }
  89.  
  90. void *memmove(void *dst, const void *src, size_t n)
  91. {
  92.     int i, j;
  93.    
  94.     if (src > dst)
  95.         return memcpy(dst, src, n);
  96.  
  97.     for (j = (n % sizeof(unsigned long)) - 1; j >= 0; j--)
  98.         ((unsigned char *) ((unsigned long *) dst))[j] = ((unsigned char *) ((unsigned long *) src))[j];
  99.  
  100.     for (i = n / sizeof(unsigned long) - 1; i >=0 ; i--)
  101.         ((unsigned long *) dst)[i] = ((unsigned long *) src)[i];
  102.        
  103.     return (char *) src;
  104. }
  105.  
  106. /** Compare two memory areas.
  107.  *
  108.  * @param s1    Pointer to the first area to compare.
  109.  * @param s2    Pointer to the second area to compare.
  110.  * @param len   Size of the first area in bytes. Both areas must have the same
  111.  *      length.
  112.  * @return  If len is 0, return zero. If the areas match, return zero.
  113.  *      Otherwise return non-zero.
  114.  */
  115. int bcmp(const char *s1, const char *s2, size_t len)
  116. {
  117.     for (; len && *s1++ == *s2++; len--)
  118.         ;
  119.     return len;
  120. }
  121.  
  122. /** Count the number of characters in the string, not including terminating 0.
  123.  * @param str string
  124.  * @return number of characters in string.
  125.  */
  126. size_t strlen(const char *str)
  127. {
  128.     size_t counter = 0;
  129.  
  130.     while (str[counter] != 0)
  131.         counter++;
  132.  
  133.     return counter;
  134. }
  135.  
  136. int strcmp(const char *a, const char *b)
  137. {
  138.     int c = 0;
  139.    
  140.     while (a[c] && b[c] && (!(a[c] - b[c])))
  141.         c++;
  142.    
  143.     return (a[c] - b[c]);
  144.    
  145. }
  146.  
  147. int strncmp(const char *a, const char *b, size_t n)
  148. {
  149.     size_t c = 0;
  150.  
  151.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  152.         c++;
  153.    
  154.     return ( c < n ? a[c] - b[c] : 0);
  155.    
  156. }
  157.  
  158. /** Return pointer to the first occurence of character c in string
  159.  * @param str scanned string
  160.  * @param c searched character (taken as one byte)
  161.  * @return pointer to the matched character or NULL if it is not found in given string.
  162.  */
  163. char *strchr(const char *str, int c)
  164. {
  165.     while (*str != '\0') {
  166.         if (*str == (char) c)
  167.             return (char *) str;
  168.         str++;
  169.     }
  170.  
  171.     return NULL;
  172. }
  173.  
  174. /** Return pointer to the last occurence of character c in string
  175.  * @param str scanned string
  176.  * @param c searched character (taken as one byte)
  177.  * @return pointer to the matched character or NULL if it is not found in given string.
  178.  */
  179. char *strrchr(const char *str, int c)
  180. {
  181.     char *retval = NULL;
  182.  
  183.     while (*str != '\0') {
  184.         if (*str == (char) c)
  185.             retval = (char *) str;
  186.         str++;
  187.     }
  188.  
  189.     return (char *) retval;
  190. }
  191.  
  192. /** Convert string to a number.
  193.  * Core of strtol and strtoul functions.
  194.  * @param nptr pointer to string
  195.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  196.  * @param base zero or number between 2 and 36 inclusive
  197.  * @param sgn its set to 1 if minus found
  198.  * @return result of conversion.
  199.  */
  200. static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  201. {
  202.     unsigned char c;
  203.     unsigned long result = 0;
  204.     unsigned long a, b;
  205.     const char *str = nptr;
  206.     const char *tmpptr;
  207.    
  208.     while (isspace(*str))
  209.         str++;
  210.    
  211.     if (*str == '-') {
  212.         *sgn = 1;
  213.         ++str;
  214.     } else if (*str == '+')
  215.         ++str;
  216.    
  217.     if (base) {
  218.         if ((base == 1) || (base > 36)) {
  219.             /* FIXME: set errno to EINVAL */
  220.             return 0;
  221.         }
  222.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
  223.             str += 2;
  224.         }
  225.     } else {
  226.         base = 10;
  227.        
  228.         if (*str == '0') {
  229.             base = 8;
  230.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  231.                 base = 16;
  232.                 str += 2;
  233.             }
  234.         }
  235.     }
  236.    
  237.     tmpptr = str;
  238.  
  239.     while (*str) {
  240.         c = *str;
  241.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 : (c <= '9' ? c - '0' : 0xff)));
  242.         if (c > base) {
  243.             break;
  244.         }
  245.        
  246.         a = (result & 0xff) * base + c;
  247.         b = (result >> 8) * base + (a >> 8);
  248.        
  249.         if (b > (ULONG_MAX >> 8)) {
  250.             /* overflow */
  251.             /* FIXME: errno = ERANGE*/
  252.             return ULONG_MAX;
  253.         }
  254.    
  255.         result = (b << 8) + (a & 0xff);
  256.         ++str;
  257.     }
  258.    
  259.     if (str == tmpptr) {
  260.         /* no number was found => first invalid character is the first character of the string */
  261.         /* FIXME: set errno to EINVAL */
  262.         str = nptr;
  263.         result = 0;
  264.     }
  265.    
  266.     if (endptr)
  267.         *endptr = (char *) str;
  268.  
  269.     if (nptr == str) {
  270.         /*FIXME: errno = EINVAL*/
  271.         return 0;
  272.     }
  273.  
  274.     return result;
  275. }
  276.  
  277. /** Convert initial part of string to long int according to given base.
  278.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  279.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  280.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  281.  * Otherwise the base 0 is taken as decimal.
  282.  * @param nptr pointer to string
  283.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  284.  * @param base zero or number between 2 and 36 inclusive
  285.  * @return result of conversion.
  286.  */
  287. long int strtol(const char *nptr, char **endptr, int base)
  288. {
  289.     char sgn = 0;
  290.     unsigned long number = 0;
  291.    
  292.     number = _strtoul(nptr, endptr, base, &sgn);
  293.  
  294.     if (number > LONG_MAX) {
  295.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  296.             /* FIXME: set 0 to errno */
  297.             return number;     
  298.         }
  299.         /* FIXME: set ERANGE to errno */
  300.         return (sgn ? LONG_MIN : LONG_MAX);
  301.     }
  302.    
  303.     return (sgn ? -number : number);
  304. }
  305.  
  306.  
  307. /** Convert initial part of string to unsigned long according to given base.
  308.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  309.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  310.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  311.  * Otherwise the base 0 is taken as decimal.
  312.  * @param nptr pointer to string
  313.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  314.  * @param base zero or number between 2 and 36 inclusive
  315.  * @return result of conversion.
  316.  */
  317. unsigned long strtoul(const char *nptr, char **endptr, int base)
  318. {
  319.     char sgn = 0;
  320.     unsigned long number = 0;
  321.    
  322.     number = _strtoul(nptr, endptr, base, &sgn);
  323.  
  324.     return (sgn ? -number : number);
  325. }
  326.  
  327. char *strcpy(char *dest, const char *src)
  328. {
  329.     char *orig = dest;
  330.    
  331.     while ((*(dest++) = *(src++)));
  332.     return orig;
  333. }
  334.  
  335. char *strncpy(char *dest, const char *src, size_t n)
  336. {
  337.     char *orig = dest;
  338.    
  339.     while ((*(dest++) = *(src++)) && --n);
  340.     return orig;
  341. }
  342.  
  343. /** @}
  344.  */
  345.