Subversion Repositories HelenOS

Rev

Rev 3492 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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