Subversion Repositories HelenOS

Rev

Rev 1197 | Rev 1319 | 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. #include <string.h>
  30. #include <unistd.h>
  31. #include <ctype.h>
  32. #include <limits.h>
  33.  
  34.  
  35. /* Dummy implementation of mem/ functions */
  36.  
  37. void * memset(void *s, int c, size_t n)
  38. {
  39.     char *os = s;
  40.     while (n--)
  41.         *(os++) = c;
  42.     return s;
  43. }
  44.  
  45. void * memcpy(void *dest, void *src, size_t n)
  46. {
  47.     char *os = src;
  48.     char *odst = dest;
  49.     while (n--)
  50.         *(odst++) = *(os++);
  51.     return dest;
  52. }
  53.  
  54. /** Count the number of characters in the string, not including terminating 0.
  55.  * @param str string
  56.  * @return number of characters in string.
  57.  */
  58. size_t strlen(const char *str)
  59. {
  60.     size_t counter = 0;
  61.  
  62.     while (str[counter] != 0) {
  63.         counter++;
  64.     }
  65.  
  66.     return counter;
  67. }
  68.  
  69. /** Return pointer to the first occurence of character c in string
  70.  * @param str scanned string
  71.  * @param c searched character (taken as one byte)
  72.  * @return pointer to the matched character or NULL if it is not found in given string.
  73.  */
  74. char *strchr(const char *str, int c)
  75. {
  76.     while (*str != '\0') {
  77.         if (*str == (char)c)
  78.             return (char *)str;
  79.         str++;
  80.     }
  81.  
  82.     return NULL;
  83. }
  84.  
  85. /** Return pointer to the last occurence of character c in string
  86.  * @param str scanned string
  87.  * @param c searched character (taken as one byte)
  88.  * @return pointer to the matched character or NULL if it is not found in given string.
  89.  */
  90. char *strrchr(const char *str, int c)
  91. {
  92.     char *retval = NULL;
  93.  
  94.     while (*str != '\0') {
  95.         if (*str == (char)c)
  96.             retval = (char *)str;
  97.         str++;
  98.     }
  99.  
  100.     return (char *)retval;
  101. }
  102.  
  103. /** Convert string to a number.
  104.  * Core of strtol and strtoul functions.
  105.  * @param nptr pointer to string
  106.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  107.  * @param base zero or number between 2 and 36 inclusive
  108.  * @param sgn its set to 1 if minus found
  109.  * @return result of conversion.
  110.  */
  111. static unsigned long _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  112. {
  113.     unsigned char c;
  114.     unsigned long result = 0;
  115.     unsigned long a, b;
  116.     const char *str = nptr;
  117.     const char *tmpptr;
  118.    
  119.     while (isspace(*str))
  120.         str++;
  121.    
  122.     if (*str == '-') {
  123.         *sgn = 1;
  124.         ++str;
  125.     } else if (*str == '+')
  126.         ++str;
  127.    
  128.     if (base) {
  129.         if ((base == 1) || (base > 36)) {
  130.             /* FIXME: set errno to EINVAL */
  131.             return 0;
  132.         }
  133.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
  134.             str += 2;
  135.         }
  136.     } else {
  137.         base = 10;
  138.        
  139.         if (*str == '0') {
  140.             base = 8;
  141.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  142.                 base = 16;
  143.                 str += 2;
  144.             }
  145.         }
  146.     }
  147.    
  148.     tmpptr = str;
  149.  
  150.     while (*str) {
  151.         c = *str;
  152.         c = ( c >= 'a'? c-'a'+10:(c >= 'A'?c-'A'+10:(c <= '9'?c-'0':0xff)));
  153.         if (c > base) {
  154.             break;
  155.         }
  156.        
  157.         a = (result & 0xff) * base + c;
  158.         b = (result >> 8) * base + (a >> 8);
  159.        
  160.         if (b > (ULONG_MAX >> 8)) {
  161.             /* overflow */
  162.             /* FIXME: errno = ERANGE*/
  163.             return ULONG_MAX;
  164.         }
  165.    
  166.         result = (b << 8) + (a & 0xff);
  167.         ++str;
  168.     }
  169.    
  170.     if (str == tmpptr) {
  171.         /* no number was found => first invalid character is the first character of the string */
  172.         /* FIXME: set errno to EINVAL */
  173.         str = nptr;
  174.         result = 0;
  175.     }
  176.    
  177.     if (endptr)
  178.         *endptr = (char *)str;
  179.  
  180.     if (nptr == str) {
  181.         /*FIXME: errno = EINVAL*/
  182.         return 0;
  183.     }
  184.  
  185.     return result;
  186. }
  187.  
  188. /** Convert initial part of string to long int according to given base.
  189.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  190.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  191.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  192.  * Otherwise the base 0 is taken as decimal.
  193.  * @param nptr pointer to string
  194.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  195.  * @param base zero or number between 2 and 36 inclusive
  196.  * @return result of conversion.
  197.  */
  198. long int strtol(const char *nptr, char **endptr, int base)
  199. {
  200.     char sgn = 0;
  201.     unsigned long number = 0;
  202.    
  203.     number = _strtoul(nptr, endptr, base, &sgn);
  204.  
  205.     if (number > LONG_MAX) {
  206.         if ((sgn) && (number == (unsigned long)(LONG_MAX) + 1)) {
  207.             /* FIXME: set 0 to errno */
  208.             return number;     
  209.         }
  210.         /* FIXME: set ERANGE to errno */
  211.         return (sgn?LONG_MIN:LONG_MAX);
  212.     }
  213.    
  214.     return (sgn?-number:number);
  215. }
  216.  
  217.  
  218. /** Convert initial part of string to unsigned long according to given base.
  219.  * The number may begin with an arbitrary number of whitespaces followed by optional sign (`+' or `-').
  220.  * If the base is 0 or 16, the prefix `0x' may be inserted and the number will be taken as hexadecimal one.
  221.  * If the base is 0 and the number begin with a zero, number will be taken as octal one (as with base 8).
  222.  * Otherwise the base 0 is taken as decimal.
  223.  * @param nptr pointer to string
  224.  * @param endptr if not NULL, function stores here pointer to the first invalid character
  225.  * @param base zero or number between 2 and 36 inclusive
  226.  * @return result of conversion.
  227.  */
  228. unsigned long strtoul(const char *nptr, char **endptr, int base)
  229. {
  230.     char sgn = 0;
  231.     unsigned long number = 0;
  232.    
  233.     number = _strtoul(nptr, endptr, base, &sgn);
  234.  
  235.     return (sgn?-number:number);
  236. }
  237.