Subversion Repositories HelenOS

Rev

Rev 3729 | Rev 3731 | Go to most recent revision | 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 <unistd.h>
  38. #include <ctype.h>
  39. #include <limits.h>
  40. #include <align.h>
  41. #include <sys/types.h>
  42. #include <malloc.h>
  43.  
  44. /** Fill memory block with a constant value. */
  45. void *memset(void *dest, int b, size_t n)
  46. {
  47.     char *pb;
  48.     unsigned long *pw;
  49.     size_t word_size;
  50.     size_t n_words;
  51.  
  52.     unsigned long pattern;
  53.     size_t i;
  54.     size_t fill;
  55.  
  56.     /* Fill initial segment. */
  57.     word_size = sizeof(unsigned long);
  58.     fill = word_size - ((uintptr_t) dest & (word_size - 1));
  59.     if (fill > n) fill = n;
  60.  
  61.     pb = dest;
  62.  
  63.     i = fill;
  64.     while (i-- != 0)
  65.         *pb++ = b;
  66.  
  67.     /* Compute remaining size. */
  68.     n -= fill;
  69.     if (n == 0) return dest;
  70.  
  71.     n_words = n / word_size;
  72.     n = n % word_size;
  73.     pw = (unsigned long *) pb;
  74.  
  75.     /* Create word-sized pattern for aligned segment. */
  76.     pattern = 0;
  77.     i = word_size;
  78.     while (i-- != 0)
  79.         pattern = (pattern << 8) | (uint8_t) b;
  80.  
  81.     /* Fill aligned segment. */
  82.     i = n_words;
  83.     while (i-- != 0)
  84.         *pw++ = pattern;
  85.  
  86.     pb = (char *) pw;
  87.  
  88.     /* Fill final segment. */
  89.     i = n;
  90.     while (i-- != 0)
  91.         *pb++ = b;
  92.  
  93.     return dest;
  94. }
  95.  
  96. struct along {
  97.     unsigned long n;
  98. } __attribute__ ((packed));
  99.  
  100. static void *unaligned_memcpy(void *dst, const void *src, size_t n)
  101. {
  102.     int i, j;
  103.     struct along *adst = dst;
  104.     const struct along *asrc = src;
  105.  
  106.     for (i = 0; i < n / sizeof(unsigned long); i++)
  107.         adst[i].n = asrc[i].n;
  108.        
  109.     for (j = 0; j < n % sizeof(unsigned long); j++)
  110.         ((unsigned char *) (((unsigned long *) dst) + i))[j] =
  111.             ((unsigned char *) (((unsigned long *) src) + i))[j];
  112.        
  113.     return (char *) dst;
  114. }
  115.  
  116. /** Copy memory block. */
  117. void *memcpy(void *dst, const void *src, size_t n)
  118. {
  119.     size_t i;
  120.     size_t mod, fill;
  121.     size_t word_size;
  122.     size_t n_words;
  123.  
  124.     const unsigned long *srcw;
  125.     unsigned long *dstw;
  126.     const uint8_t *srcb;
  127.     uint8_t *dstb;
  128.  
  129.     word_size = sizeof(unsigned long);
  130.  
  131.     /*
  132.      * Are source and destination addresses congruent modulo word_size?
  133.      * If not, use unaligned_memcpy().
  134.      */
  135.  
  136.     if (((uintptr_t) dst & (word_size - 1)) !=
  137.         ((uintptr_t) src & (word_size - 1)))
  138.         return unaligned_memcpy(dst, src, n);
  139.  
  140.     /*
  141.      * mod is the address modulo word size. fill is the length of the
  142.      * initial buffer segment before the first word boundary.
  143.      * If the buffer is very short, use unaligned_memcpy(), too.
  144.      */
  145.  
  146.     mod = (uintptr_t) dst & (word_size - 1);
  147.     fill = word_size - mod;
  148.     if (fill > n) fill = n;
  149.  
  150.     /* Copy the initial segment. */
  151.  
  152.     srcb = src;
  153.     dstb = dst;
  154.  
  155.     i = fill;
  156.     while (i-- != 0)
  157.         *dstb++ = *srcb++;
  158.  
  159.     /* Compute remaining length. */
  160.  
  161.     n -= fill;
  162.     if (n == 0) return dst;
  163.  
  164.     /* Pointers to aligned segment. */
  165.  
  166.     dstw = (unsigned long *) dstb;
  167.     srcw = (const unsigned long *) srcb;
  168.  
  169.     n_words = n / word_size;    /* Number of whole words to copy. */
  170.     n -= n_words * word_size;   /* Remaining bytes at the end. */
  171.  
  172.     /* "Fast" copy. */
  173.     i = n_words;
  174.     while (i-- != 0)
  175.         *dstw++ = *srcw++;
  176.  
  177.     /*
  178.      * Copy the rest.
  179.      */
  180.  
  181.     srcb = (const uint8_t *) srcw;
  182.     dstb = (uint8_t *) dstw;
  183.  
  184.     i = n;
  185.     while (i-- != 0)
  186.         *dstb++ = *srcb++;
  187.  
  188.     return dst;
  189. }
  190.  
  191. /** Move memory block with possible overlapping. */
  192. void *memmove(void *dst, const void *src, size_t n)
  193. {
  194.     uint8_t *dp, *sp;
  195.  
  196.     /* Nothing to do? */
  197.     if (src == dst)
  198.         return dst;
  199.  
  200.     /* Non-overlapping? */
  201.     if (dst >= src + n || src >= dst + n) {
  202.         return memcpy(dst, src, n);
  203.     }
  204.  
  205.     /* Which direction? */
  206.     if (src > dst) {
  207.         /* Forwards. */
  208.         sp = src;
  209.         dp = dst;
  210.  
  211.         while (n-- != 0)
  212.             *dp++ = *sp++;
  213.     } else {
  214.         /* Backwards. */
  215.         sp = src + (n - 1);
  216.         dp = dst + (n - 1);
  217.  
  218.         while (n-- != 0)
  219.             *dp-- = *sp--;
  220.     }
  221.  
  222.     return dst;
  223. }
  224.  
  225. /** Compare two memory areas.
  226.  *
  227.  * @param s1        Pointer to the first area to compare.
  228.  * @param s2        Pointer to the second area to compare.
  229.  * @param len       Size of the first area in bytes. Both areas must have
  230.  *          the same length.
  231.  * @return      If len is 0, return zero. If the areas match, return
  232.  *          zero. Otherwise return non-zero.
  233.  */
  234. int bcmp(const char *s1, const char *s2, size_t len)
  235. {
  236.     for (; len && *s1++ == *s2++; len--)
  237.         ;
  238.     return len;
  239. }
  240.  
  241. /** Count the number of characters in the string, not including terminating 0.
  242.  *
  243.  * @param str       String.
  244.  * @return      Number of characters in string.
  245.  */
  246. size_t strlen(const char *str)
  247. {
  248.     size_t counter = 0;
  249.  
  250.     while (str[counter] != 0)
  251.         counter++;
  252.  
  253.     return counter;
  254. }
  255.  
  256. int strcmp(const char *a, const char *b)
  257. {
  258.     int c = 0;
  259.    
  260.     while (a[c] && b[c] && (!(a[c] - b[c])))
  261.         c++;
  262.    
  263.     return (a[c] - b[c]);
  264. }
  265.  
  266. int strncmp(const char *a, const char *b, size_t n)
  267. {
  268.     size_t c = 0;
  269.  
  270.     while (c < n && a[c] && b[c] && (!(a[c] - b[c])))
  271.         c++;
  272.    
  273.     return ( c < n ? a[c] - b[c] : 0);
  274.    
  275. }
  276.  
  277. int stricmp(const char *a, const char *b)
  278. {
  279.     int c = 0;
  280.    
  281.     while (a[c] && b[c] && (!(tolower(a[c]) - tolower(b[c]))))
  282.         c++;
  283.    
  284.     return (tolower(a[c]) - tolower(b[c]));
  285. }
  286.  
  287. /** Return pointer to the first occurence of character c in string.
  288.  *
  289.  * @param str       Scanned string.
  290.  * @param c     Searched character (taken as one byte).
  291.  * @return      Pointer to the matched character or NULL if it is not
  292.  *          found in given string.
  293.  */
  294. char *strchr(const char *str, int c)
  295. {
  296.     while (*str != '\0') {
  297.         if (*str == (char) c)
  298.             return (char *) str;
  299.         str++;
  300.     }
  301.  
  302.     return NULL;
  303. }
  304.  
  305. /** Return pointer to the last occurence of character c in string.
  306.  *
  307.  * @param str       Scanned string.
  308.  * @param c     Searched character (taken as one byte).
  309.  * @return      Pointer to the matched character or NULL if it is not
  310.  *          found in given string.
  311.  */
  312. char *strrchr(const char *str, int c)
  313. {
  314.     char *retval = NULL;
  315.  
  316.     while (*str != '\0') {
  317.         if (*str == (char) c)
  318.             retval = (char *) str;
  319.         str++;
  320.     }
  321.  
  322.     return (char *) retval;
  323. }
  324.  
  325. /** Convert string to a number.
  326.  * Core of strtol and strtoul functions.
  327.  *
  328.  * @param nptr      Pointer to string.
  329.  * @param endptr    If not NULL, function stores here pointer to the first
  330.  *          invalid character.
  331.  * @param base      Zero or number between 2 and 36 inclusive.
  332.  * @param sgn       It's set to 1 if minus found.
  333.  * @return      Result of conversion.
  334.  */
  335. static unsigned long
  336. _strtoul(const char *nptr, char **endptr, int base, char *sgn)
  337. {
  338.     unsigned char c;
  339.     unsigned long result = 0;
  340.     unsigned long a, b;
  341.     const char *str = nptr;
  342.     const char *tmpptr;
  343.    
  344.     while (isspace(*str))
  345.         str++;
  346.    
  347.     if (*str == '-') {
  348.         *sgn = 1;
  349.         ++str;
  350.     } else if (*str == '+')
  351.         ++str;
  352.    
  353.     if (base) {
  354.         if ((base == 1) || (base > 36)) {
  355.             /* FIXME: set errno to EINVAL */
  356.             return 0;
  357.         }
  358.         if ((base == 16) && (*str == '0') && ((str[1] == 'x') ||
  359.             (str[1] == 'X'))) {
  360.             str += 2;
  361.         }
  362.     } else {
  363.         base = 10;
  364.        
  365.         if (*str == '0') {
  366.             base = 8;
  367.             if ((str[1] == 'X') || (str[1] == 'x'))  {
  368.                 base = 16;
  369.                 str += 2;
  370.             }
  371.         }
  372.     }
  373.    
  374.     tmpptr = str;
  375.  
  376.     while (*str) {
  377.         c = *str;
  378.         c = (c >= 'a' ? c - 'a' + 10 : (c >= 'A' ? c - 'A' + 10 :
  379.             (c <= '9' ? c - '0' : 0xff)));
  380.         if (c > base) {
  381.             break;
  382.         }
  383.        
  384.         a = (result & 0xff) * base + c;
  385.         b = (result >> 8) * base + (a >> 8);
  386.        
  387.         if (b > (ULONG_MAX >> 8)) {
  388.             /* overflow */
  389.             /* FIXME: errno = ERANGE*/
  390.             return ULONG_MAX;
  391.         }
  392.    
  393.         result = (b << 8) + (a & 0xff);
  394.         ++str;
  395.     }
  396.    
  397.     if (str == tmpptr) {
  398.         /*
  399.          * No number was found => first invalid character is the first
  400.          * character of the string.
  401.          */
  402.         /* FIXME: set errno to EINVAL */
  403.         str = nptr;
  404.         result = 0;
  405.     }
  406.    
  407.     if (endptr)
  408.         *endptr = (char *) str;
  409.  
  410.     if (nptr == str) {
  411.         /*FIXME: errno = EINVAL*/
  412.         return 0;
  413.     }
  414.  
  415.     return result;
  416. }
  417.  
  418. /** Convert initial part of string to long int according to given base.
  419.  * The number may begin with an arbitrary number of whitespaces followed by
  420.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  421.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  422.  * and the number begin with a zero, number will be taken as octal one (as with
  423.  * base 8). Otherwise the base 0 is taken as decimal.
  424.  *
  425.  * @param nptr      Pointer to string.
  426.  * @param endptr    If not NULL, function stores here pointer to the first
  427.  *          invalid character.
  428.  * @param base      Zero or number between 2 and 36 inclusive.
  429.  * @return      Result of conversion.
  430.  */
  431. long int strtol(const char *nptr, char **endptr, int base)
  432. {
  433.     char sgn = 0;
  434.     unsigned long number = 0;
  435.    
  436.     number = _strtoul(nptr, endptr, base, &sgn);
  437.  
  438.     if (number > LONG_MAX) {
  439.         if ((sgn) && (number == (unsigned long) (LONG_MAX) + 1)) {
  440.             /* FIXME: set 0 to errno */
  441.             return number;     
  442.         }
  443.         /* FIXME: set ERANGE to errno */
  444.         return (sgn ? LONG_MIN : LONG_MAX);
  445.     }
  446.    
  447.     return (sgn ? -number : number);
  448. }
  449.  
  450.  
  451. /** Convert initial part of string to unsigned long according to given base.
  452.  * The number may begin with an arbitrary number of whitespaces followed by
  453.  * optional sign (`+' or `-'). If the base is 0 or 16, the prefix `0x' may be
  454.  * inserted and the number will be taken as hexadecimal one. If the base is 0
  455.  * and the number begin with a zero, number will be taken as octal one (as with
  456.  * base 8). Otherwise the base 0 is taken as decimal.
  457.  *
  458.  * @param nptr      Pointer to string.
  459.  * @param endptr    If not NULL, function stores here pointer to the first
  460.  *          invalid character
  461.  * @param base      Zero or number between 2 and 36 inclusive.
  462.  * @return      Result of conversion.
  463.  */
  464. unsigned long strtoul(const char *nptr, char **endptr, int base)
  465. {
  466.     char sgn = 0;
  467.     unsigned long number = 0;
  468.    
  469.     number = _strtoul(nptr, endptr, base, &sgn);
  470.  
  471.     return (sgn ? -number : number);
  472. }
  473.  
  474. char *strcpy(char *dest, const char *src)
  475. {
  476.     char *orig = dest;
  477.    
  478.     while ((*(dest++) = *(src++)))
  479.         ;
  480.     return orig;
  481. }
  482.  
  483. char *strncpy(char *dest, const char *src, size_t n)
  484. {
  485.     char *orig = dest;
  486.    
  487.     while ((*(dest++) = *(src++)) && --n)
  488.         ;
  489.     return orig;
  490. }
  491.  
  492. char *strcat(char *dest, const char *src)
  493. {
  494.     char *orig = dest;
  495.     while (*dest++)
  496.         ;
  497.     --dest;
  498.     while ((*dest++ = *src++))
  499.         ;
  500.     return orig;
  501. }
  502.  
  503. char * strdup(const char *s1)
  504. {
  505.     size_t len = strlen(s1) + 1;
  506.     void *ret = malloc(len);
  507.  
  508.     if (ret == NULL)
  509.         return (char *) NULL;
  510.  
  511.     return (char *) memcpy(ret, s1, len);
  512. }
  513.  
  514. char *strtok(char *s, const char *delim)
  515. {
  516.     static char *next;
  517.  
  518.     return strtok_r(s, delim, &next);
  519. }
  520.  
  521. char *strtok_r(char *s, const char *delim, char **next)
  522. {
  523.     char *start, *end;
  524.  
  525.     if (s == NULL)
  526.         s = *next;
  527.  
  528.     /* Skip over leading delimiters. */
  529.     while (*s && (strchr(delim, *s) != NULL)) ++s;
  530.     start = s;
  531.  
  532.     /* Skip over token characters. */
  533.     while (*s && (strchr(delim, *s) == NULL)) ++s;
  534.     end = s;
  535.     *next = (*s ? s + 1 : s);
  536.  
  537.     if (start == end) {
  538.         return NULL;    /* No more tokens. */
  539.     }
  540.  
  541.     /* Overwrite delimiter with NULL terminator. */
  542.     *end = '\0';
  543.     return start;
  544. }
  545.  
  546. /** @}
  547.  */
  548.