The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/string.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/lib/string.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  */
    6 
    7 /*
    8  * stupid library routines.. The optimized versions should generally be found
    9  * as inline code in <asm-xx/string.h>
   10  *
   11  * These are buggy as well..
   12  *
   13  * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
   14  * -  Added strsep() which will replace strtok() soon (because strsep() is
   15  *    reentrant and should be faster). Use only strsep() in new code, please.
   16  *
   17  * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>,
   18  *                    Matthew Hawkins <matt@mh.dropbear.id.au>
   19  * -  Kissed strtok() goodbye
   20  */
   21 
   22 #include <linux/types.h>
   23 #include <linux/string.h>
   24 #include <linux/ctype.h>
   25 #include <linux/kernel.h>
   26 #include <linux/export.h>
   27 #include <linux/bug.h>
   28 #include <linux/errno.h>
   29 
   30 #ifndef __HAVE_ARCH_STRNICMP
   31 /**
   32  * strnicmp - Case insensitive, length-limited string comparison
   33  * @s1: One string
   34  * @s2: The other string
   35  * @len: the maximum number of characters to compare
   36  */
   37 int strnicmp(const char *s1, const char *s2, size_t len)
   38 {
   39         /* Yes, Virginia, it had better be unsigned */
   40         unsigned char c1, c2;
   41 
   42         if (!len)
   43                 return 0;
   44 
   45         do {
   46                 c1 = *s1++;
   47                 c2 = *s2++;
   48                 if (!c1 || !c2)
   49                         break;
   50                 if (c1 == c2)
   51                         continue;
   52                 c1 = tolower(c1);
   53                 c2 = tolower(c2);
   54                 if (c1 != c2)
   55                         break;
   56         } while (--len);
   57         return (int)c1 - (int)c2;
   58 }
   59 EXPORT_SYMBOL(strnicmp);
   60 #endif
   61 
   62 #ifndef __HAVE_ARCH_STRCASECMP
   63 int strcasecmp(const char *s1, const char *s2)
   64 {
   65         int c1, c2;
   66 
   67         do {
   68                 c1 = tolower(*s1++);
   69                 c2 = tolower(*s2++);
   70         } while (c1 == c2 && c1 != 0);
   71         return c1 - c2;
   72 }
   73 EXPORT_SYMBOL(strcasecmp);
   74 #endif
   75 
   76 #ifndef __HAVE_ARCH_STRNCASECMP
   77 int strncasecmp(const char *s1, const char *s2, size_t n)
   78 {
   79         int c1, c2;
   80 
   81         do {
   82                 c1 = tolower(*s1++);
   83                 c2 = tolower(*s2++);
   84         } while ((--n > 0) && c1 == c2 && c1 != 0);
   85         return c1 - c2;
   86 }
   87 EXPORT_SYMBOL(strncasecmp);
   88 #endif
   89 
   90 #ifndef __HAVE_ARCH_STRCPY
   91 /**
   92  * strcpy - Copy a %NUL terminated string
   93  * @dest: Where to copy the string to
   94  * @src: Where to copy the string from
   95  */
   96 #undef strcpy
   97 char *strcpy(char *dest, const char *src)
   98 {
   99         char *tmp = dest;
  100 
  101         while ((*dest++ = *src++) != '\0')
  102                 /* nothing */;
  103         return tmp;
  104 }
  105 EXPORT_SYMBOL(strcpy);
  106 #endif
  107 
  108 #ifndef __HAVE_ARCH_STRNCPY
  109 /**
  110  * strncpy - Copy a length-limited, %NUL-terminated string
  111  * @dest: Where to copy the string to
  112  * @src: Where to copy the string from
  113  * @count: The maximum number of bytes to copy
  114  *
  115  * The result is not %NUL-terminated if the source exceeds
  116  * @count bytes.
  117  *
  118  * In the case where the length of @src is less than  that  of
  119  * count, the remainder of @dest will be padded with %NUL.
  120  *
  121  */
  122 char *strncpy(char *dest, const char *src, size_t count)
  123 {
  124         char *tmp = dest;
  125 
  126         while (count) {
  127                 if ((*tmp = *src) != 0)
  128                         src++;
  129                 tmp++;
  130                 count--;
  131         }
  132         return dest;
  133 }
  134 EXPORT_SYMBOL(strncpy);
  135 #endif
  136 
  137 #ifndef __HAVE_ARCH_STRLCPY
  138 /**
  139  * strlcpy - Copy a %NUL terminated string into a sized buffer
  140  * @dest: Where to copy the string to
  141  * @src: Where to copy the string from
  142  * @size: size of destination buffer
  143  *
  144  * Compatible with *BSD: the result is always a valid
  145  * NUL-terminated string that fits in the buffer (unless,
  146  * of course, the buffer size is zero). It does not pad
  147  * out the result like strncpy() does.
  148  */
  149 size_t strlcpy(char *dest, const char *src, size_t size)
  150 {
  151         size_t ret = strlen(src);
  152 
  153         if (size) {
  154                 size_t len = (ret >= size) ? size - 1 : ret;
  155                 memcpy(dest, src, len);
  156                 dest[len] = '\0';
  157         }
  158         return ret;
  159 }
  160 EXPORT_SYMBOL(strlcpy);
  161 #endif
  162 
  163 #ifndef __HAVE_ARCH_STRCAT
  164 /**
  165  * strcat - Append one %NUL-terminated string to another
  166  * @dest: The string to be appended to
  167  * @src: The string to append to it
  168  */
  169 #undef strcat
  170 char *strcat(char *dest, const char *src)
  171 {
  172         char *tmp = dest;
  173 
  174         while (*dest)
  175                 dest++;
  176         while ((*dest++ = *src++) != '\0')
  177                 ;
  178         return tmp;
  179 }
  180 EXPORT_SYMBOL(strcat);
  181 #endif
  182 
  183 #ifndef __HAVE_ARCH_STRNCAT
  184 /**
  185  * strncat - Append a length-limited, %NUL-terminated string to another
  186  * @dest: The string to be appended to
  187  * @src: The string to append to it
  188  * @count: The maximum numbers of bytes to copy
  189  *
  190  * Note that in contrast to strncpy(), strncat() ensures the result is
  191  * terminated.
  192  */
  193 char *strncat(char *dest, const char *src, size_t count)
  194 {
  195         char *tmp = dest;
  196 
  197         if (count) {
  198                 while (*dest)
  199                         dest++;
  200                 while ((*dest++ = *src++) != 0) {
  201                         if (--count == 0) {
  202                                 *dest = '\0';
  203                                 break;
  204                         }
  205                 }
  206         }
  207         return tmp;
  208 }
  209 EXPORT_SYMBOL(strncat);
  210 #endif
  211 
  212 #ifndef __HAVE_ARCH_STRLCAT
  213 /**
  214  * strlcat - Append a length-limited, %NUL-terminated string to another
  215  * @dest: The string to be appended to
  216  * @src: The string to append to it
  217  * @count: The size of the destination buffer.
  218  */
  219 size_t strlcat(char *dest, const char *src, size_t count)
  220 {
  221         size_t dsize = strlen(dest);
  222         size_t len = strlen(src);
  223         size_t res = dsize + len;
  224 
  225         /* This would be a bug */
  226         BUG_ON(dsize >= count);
  227 
  228         dest += dsize;
  229         count -= dsize;
  230         if (len >= count)
  231                 len = count-1;
  232         memcpy(dest, src, len);
  233         dest[len] = 0;
  234         return res;
  235 }
  236 EXPORT_SYMBOL(strlcat);
  237 #endif
  238 
  239 #ifndef __HAVE_ARCH_STRCMP
  240 /**
  241  * strcmp - Compare two strings
  242  * @cs: One string
  243  * @ct: Another string
  244  */
  245 #undef strcmp
  246 int strcmp(const char *cs, const char *ct)
  247 {
  248         unsigned char c1, c2;
  249 
  250         while (1) {
  251                 c1 = *cs++;
  252                 c2 = *ct++;
  253                 if (c1 != c2)
  254                         return c1 < c2 ? -1 : 1;
  255                 if (!c1)
  256                         break;
  257         }
  258         return 0;
  259 }
  260 EXPORT_SYMBOL(strcmp);
  261 #endif
  262 
  263 #ifndef __HAVE_ARCH_STRNCMP
  264 /**
  265  * strncmp - Compare two length-limited strings
  266  * @cs: One string
  267  * @ct: Another string
  268  * @count: The maximum number of bytes to compare
  269  */
  270 int strncmp(const char *cs, const char *ct, size_t count)
  271 {
  272         unsigned char c1, c2;
  273 
  274         while (count) {
  275                 c1 = *cs++;
  276                 c2 = *ct++;
  277                 if (c1 != c2)
  278                         return c1 < c2 ? -1 : 1;
  279                 if (!c1)
  280                         break;
  281                 count--;
  282         }
  283         return 0;
  284 }
  285 EXPORT_SYMBOL(strncmp);
  286 #endif
  287 
  288 #ifndef __HAVE_ARCH_STRCHR
  289 /**
  290  * strchr - Find the first occurrence of a character in a string
  291  * @s: The string to be searched
  292  * @c: The character to search for
  293  */
  294 char *strchr(const char *s, int c)
  295 {
  296         for (; *s != (char)c; ++s)
  297                 if (*s == '\0')
  298                         return NULL;
  299         return (char *)s;
  300 }
  301 EXPORT_SYMBOL(strchr);
  302 #endif
  303 
  304 #ifndef __HAVE_ARCH_STRRCHR
  305 /**
  306  * strrchr - Find the last occurrence of a character in a string
  307  * @s: The string to be searched
  308  * @c: The character to search for
  309  */
  310 char *strrchr(const char *s, int c)
  311 {
  312        const char *p = s + strlen(s);
  313        do {
  314            if (*p == (char)c)
  315                return (char *)p;
  316        } while (--p >= s);
  317        return NULL;
  318 }
  319 EXPORT_SYMBOL(strrchr);
  320 #endif
  321 
  322 #ifndef __HAVE_ARCH_STRNCHR
  323 /**
  324  * strnchr - Find a character in a length limited string
  325  * @s: The string to be searched
  326  * @count: The number of characters to be searched
  327  * @c: The character to search for
  328  */
  329 char *strnchr(const char *s, size_t count, int c)
  330 {
  331         for (; count-- && *s != '\0'; ++s)
  332                 if (*s == (char)c)
  333                         return (char *)s;
  334         return NULL;
  335 }
  336 EXPORT_SYMBOL(strnchr);
  337 #endif
  338 
  339 /**
  340  * skip_spaces - Removes leading whitespace from @str.
  341  * @str: The string to be stripped.
  342  *
  343  * Returns a pointer to the first non-whitespace character in @str.
  344  */
  345 char *skip_spaces(const char *str)
  346 {
  347         while (isspace(*str))
  348                 ++str;
  349         return (char *)str;
  350 }
  351 EXPORT_SYMBOL(skip_spaces);
  352 
  353 /**
  354  * strim - Removes leading and trailing whitespace from @s.
  355  * @s: The string to be stripped.
  356  *
  357  * Note that the first trailing whitespace is replaced with a %NUL-terminator
  358  * in the given string @s. Returns a pointer to the first non-whitespace
  359  * character in @s.
  360  */
  361 char *strim(char *s)
  362 {
  363         size_t size;
  364         char *end;
  365 
  366         size = strlen(s);
  367         if (!size)
  368                 return s;
  369 
  370         end = s + size - 1;
  371         while (end >= s && isspace(*end))
  372                 end--;
  373         *(end + 1) = '\0';
  374 
  375         return skip_spaces(s);
  376 }
  377 EXPORT_SYMBOL(strim);
  378 
  379 #ifndef __HAVE_ARCH_STRLEN
  380 /**
  381  * strlen - Find the length of a string
  382  * @s: The string to be sized
  383  */
  384 size_t strlen(const char *s)
  385 {
  386         const char *sc;
  387 
  388         for (sc = s; *sc != '\0'; ++sc)
  389                 /* nothing */;
  390         return sc - s;
  391 }
  392 EXPORT_SYMBOL(strlen);
  393 #endif
  394 
  395 #ifndef __HAVE_ARCH_STRNLEN
  396 /**
  397  * strnlen - Find the length of a length-limited string
  398  * @s: The string to be sized
  399  * @count: The maximum number of bytes to search
  400  */
  401 size_t strnlen(const char *s, size_t count)
  402 {
  403         const char *sc;
  404 
  405         for (sc = s; count-- && *sc != '\0'; ++sc)
  406                 /* nothing */;
  407         return sc - s;
  408 }
  409 EXPORT_SYMBOL(strnlen);
  410 #endif
  411 
  412 #ifndef __HAVE_ARCH_STRSPN
  413 /**
  414  * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
  415  * @s: The string to be searched
  416  * @accept: The string to search for
  417  */
  418 size_t strspn(const char *s, const char *accept)
  419 {
  420         const char *p;
  421         const char *a;
  422         size_t count = 0;
  423 
  424         for (p = s; *p != '\0'; ++p) {
  425                 for (a = accept; *a != '\0'; ++a) {
  426                         if (*p == *a)
  427                                 break;
  428                 }
  429                 if (*a == '\0')
  430                         return count;
  431                 ++count;
  432         }
  433         return count;
  434 }
  435 
  436 EXPORT_SYMBOL(strspn);
  437 #endif
  438 
  439 #ifndef __HAVE_ARCH_STRCSPN
  440 /**
  441  * strcspn - Calculate the length of the initial substring of @s which does not contain letters in @reject
  442  * @s: The string to be searched
  443  * @reject: The string to avoid
  444  */
  445 size_t strcspn(const char *s, const char *reject)
  446 {
  447         const char *p;
  448         const char *r;
  449         size_t count = 0;
  450 
  451         for (p = s; *p != '\0'; ++p) {
  452                 for (r = reject; *r != '\0'; ++r) {
  453                         if (*p == *r)
  454                                 return count;
  455                 }
  456                 ++count;
  457         }
  458         return count;
  459 }
  460 EXPORT_SYMBOL(strcspn);
  461 #endif
  462 
  463 #ifndef __HAVE_ARCH_STRPBRK
  464 /**
  465  * strpbrk - Find the first occurrence of a set of characters
  466  * @cs: The string to be searched
  467  * @ct: The characters to search for
  468  */
  469 char *strpbrk(const char *cs, const char *ct)
  470 {
  471         const char *sc1, *sc2;
  472 
  473         for (sc1 = cs; *sc1 != '\0'; ++sc1) {
  474                 for (sc2 = ct; *sc2 != '\0'; ++sc2) {
  475                         if (*sc1 == *sc2)
  476                                 return (char *)sc1;
  477                 }
  478         }
  479         return NULL;
  480 }
  481 EXPORT_SYMBOL(strpbrk);
  482 #endif
  483 
  484 #ifndef __HAVE_ARCH_STRSEP
  485 /**
  486  * strsep - Split a string into tokens
  487  * @s: The string to be searched
  488  * @ct: The characters to search for
  489  *
  490  * strsep() updates @s to point after the token, ready for the next call.
  491  *
  492  * It returns empty tokens, too, behaving exactly like the libc function
  493  * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
  494  * Same semantics, slimmer shape. ;)
  495  */
  496 char *strsep(char **s, const char *ct)
  497 {
  498         char *sbegin = *s;
  499         char *end;
  500 
  501         if (sbegin == NULL)
  502                 return NULL;
  503 
  504         end = strpbrk(sbegin, ct);
  505         if (end)
  506                 *end++ = '\0';
  507         *s = end;
  508         return sbegin;
  509 }
  510 EXPORT_SYMBOL(strsep);
  511 #endif
  512 
  513 /**
  514  * sysfs_streq - return true if strings are equal, modulo trailing newline
  515  * @s1: one string
  516  * @s2: another string
  517  *
  518  * This routine returns true iff two strings are equal, treating both
  519  * NUL and newline-then-NUL as equivalent string terminations.  It's
  520  * geared for use with sysfs input strings, which generally terminate
  521  * with newlines but are compared against values without newlines.
  522  */
  523 bool sysfs_streq(const char *s1, const char *s2)
  524 {
  525         while (*s1 && *s1 == *s2) {
  526                 s1++;
  527                 s2++;
  528         }
  529 
  530         if (*s1 == *s2)
  531                 return true;
  532         if (!*s1 && *s2 == '\n' && !s2[1])
  533                 return true;
  534         if (*s1 == '\n' && !s1[1] && !*s2)
  535                 return true;
  536         return false;
  537 }
  538 EXPORT_SYMBOL(sysfs_streq);
  539 
  540 /**
  541  * strtobool - convert common user inputs into boolean values
  542  * @s: input string
  543  * @res: result
  544  *
  545  * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
  546  * Otherwise it will return -EINVAL.  Value pointed to by res is
  547  * updated upon finding a match.
  548  */
  549 int strtobool(const char *s, bool *res)
  550 {
  551         switch (s[0]) {
  552         case 'y':
  553         case 'Y':
  554         case '1':
  555                 *res = true;
  556                 break;
  557         case 'n':
  558         case 'N':
  559         case '':
  560                 *res = false;
  561                 break;
  562         default:
  563                 return -EINVAL;
  564         }
  565         return 0;
  566 }
  567 EXPORT_SYMBOL(strtobool);
  568 
  569 #ifndef __HAVE_ARCH_MEMSET
  570 /**
  571  * memset - Fill a region of memory with the given value
  572  * @s: Pointer to the start of the area.
  573  * @c: The byte to fill the area with
  574  * @count: The size of the area.
  575  *
  576  * Do not use memset() to access IO space, use memset_io() instead.
  577  */
  578 void *memset(void *s, int c, size_t count)
  579 {
  580         char *xs = s;
  581 
  582         while (count--)
  583                 *xs++ = c;
  584         return s;
  585 }
  586 EXPORT_SYMBOL(memset);
  587 #endif
  588 
  589 #ifndef __HAVE_ARCH_MEMCPY
  590 /**
  591  * memcpy - Copy one area of memory to another
  592  * @dest: Where to copy to
  593  * @src: Where to copy from
  594  * @count: The size of the area.
  595  *
  596  * You should not use this function to access IO space, use memcpy_toio()
  597  * or memcpy_fromio() instead.
  598  */
  599 void *memcpy(void *dest, const void *src, size_t count)
  600 {
  601         char *tmp = dest;
  602         const char *s = src;
  603 
  604         while (count--)
  605                 *tmp++ = *s++;
  606         return dest;
  607 }
  608 EXPORT_SYMBOL(memcpy);
  609 #endif
  610 
  611 #ifndef __HAVE_ARCH_MEMMOVE
  612 /**
  613  * memmove - Copy one area of memory to another
  614  * @dest: Where to copy to
  615  * @src: Where to copy from
  616  * @count: The size of the area.
  617  *
  618  * Unlike memcpy(), memmove() copes with overlapping areas.
  619  */
  620 void *memmove(void *dest, const void *src, size_t count)
  621 {
  622         char *tmp;
  623         const char *s;
  624 
  625         if (dest <= src) {
  626                 tmp = dest;
  627                 s = src;
  628                 while (count--)
  629                         *tmp++ = *s++;
  630         } else {
  631                 tmp = dest;
  632                 tmp += count;
  633                 s = src;
  634                 s += count;
  635                 while (count--)
  636                         *--tmp = *--s;
  637         }
  638         return dest;
  639 }
  640 EXPORT_SYMBOL(memmove);
  641 #endif
  642 
  643 #ifndef __HAVE_ARCH_MEMCMP
  644 /**
  645  * memcmp - Compare two areas of memory
  646  * @cs: One area of memory
  647  * @ct: Another area of memory
  648  * @count: The size of the area.
  649  */
  650 #undef memcmp
  651 int memcmp(const void *cs, const void *ct, size_t count)
  652 {
  653         const unsigned char *su1, *su2;
  654         int res = 0;
  655 
  656         for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
  657                 if ((res = *su1 - *su2) != 0)
  658                         break;
  659         return res;
  660 }
  661 EXPORT_SYMBOL(memcmp);
  662 #endif
  663 
  664 #ifndef __HAVE_ARCH_MEMSCAN
  665 /**
  666  * memscan - Find a character in an area of memory.
  667  * @addr: The memory area
  668  * @c: The byte to search for
  669  * @size: The size of the area.
  670  *
  671  * returns the address of the first occurrence of @c, or 1 byte past
  672  * the area if @c is not found
  673  */
  674 void *memscan(void *addr, int c, size_t size)
  675 {
  676         unsigned char *p = addr;
  677 
  678         while (size) {
  679                 if (*p == c)
  680                         return (void *)p;
  681                 p++;
  682                 size--;
  683         }
  684         return (void *)p;
  685 }
  686 EXPORT_SYMBOL(memscan);
  687 #endif
  688 
  689 #ifndef __HAVE_ARCH_STRSTR
  690 /**
  691  * strstr - Find the first substring in a %NUL terminated string
  692  * @s1: The string to be searched
  693  * @s2: The string to search for
  694  */
  695 char *strstr(const char *s1, const char *s2)
  696 {
  697         size_t l1, l2;
  698 
  699         l2 = strlen(s2);
  700         if (!l2)
  701                 return (char *)s1;
  702         l1 = strlen(s1);
  703         while (l1 >= l2) {
  704                 l1--;
  705                 if (!memcmp(s1, s2, l2))
  706                         return (char *)s1;
  707                 s1++;
  708         }
  709         return NULL;
  710 }
  711 EXPORT_SYMBOL(strstr);
  712 #endif
  713 
  714 #ifndef __HAVE_ARCH_STRNSTR
  715 /**
  716  * strnstr - Find the first substring in a length-limited string
  717  * @s1: The string to be searched
  718  * @s2: The string to search for
  719  * @len: the maximum number of characters to search
  720  */
  721 char *strnstr(const char *s1, const char *s2, size_t len)
  722 {
  723         size_t l2;
  724 
  725         l2 = strlen(s2);
  726         if (!l2)
  727                 return (char *)s1;
  728         while (len >= l2) {
  729                 len--;
  730                 if (!memcmp(s1, s2, l2))
  731                         return (char *)s1;
  732                 s1++;
  733         }
  734         return NULL;
  735 }
  736 EXPORT_SYMBOL(strnstr);
  737 #endif
  738 
  739 #ifndef __HAVE_ARCH_MEMCHR
  740 /**
  741  * memchr - Find a character in an area of memory.
  742  * @s: The memory area
  743  * @c: The byte to search for
  744  * @n: The size of the area.
  745  *
  746  * returns the address of the first occurrence of @c, or %NULL
  747  * if @c is not found
  748  */
  749 void *memchr(const void *s, int c, size_t n)
  750 {
  751         const unsigned char *p = s;
  752         while (n-- != 0) {
  753                 if ((unsigned char)c == *p++) {
  754                         return (void *)(p - 1);
  755                 }
  756         }
  757         return NULL;
  758 }
  759 EXPORT_SYMBOL(memchr);
  760 #endif
  761 
  762 static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
  763 {
  764         while (bytes) {
  765                 if (*start != value)
  766                         return (void *)start;
  767                 start++;
  768                 bytes--;
  769         }
  770         return NULL;
  771 }
  772 
  773 /**
  774  * memchr_inv - Find an unmatching character in an area of memory.
  775  * @start: The memory area
  776  * @c: Find a character other than c
  777  * @bytes: The size of the area.
  778  *
  779  * returns the address of the first character other than @c, or %NULL
  780  * if the whole buffer contains just @c.
  781  */
  782 void *memchr_inv(const void *start, int c, size_t bytes)
  783 {
  784         u8 value = c;
  785         u64 value64;
  786         unsigned int words, prefix;
  787 
  788         if (bytes <= 16)
  789                 return check_bytes8(start, value, bytes);
  790 
  791         value64 = value;
  792 #if defined(ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
  793         value64 *= 0x0101010101010101;
  794 #elif defined(ARCH_HAS_FAST_MULTIPLIER)
  795         value64 *= 0x01010101;
  796         value64 |= value64 << 32;
  797 #else
  798         value64 |= value64 << 8;
  799         value64 |= value64 << 16;
  800         value64 |= value64 << 32;
  801 #endif
  802 
  803         prefix = (unsigned long)start % 8;
  804         if (prefix) {
  805                 u8 *r;
  806 
  807                 prefix = 8 - prefix;
  808                 r = check_bytes8(start, value, prefix);
  809                 if (r)
  810                         return r;
  811                 start += prefix;
  812                 bytes -= prefix;
  813         }
  814 
  815         words = bytes / 8;
  816 
  817         while (words) {
  818                 if (*(u64 *)start != value64)
  819                         return check_bytes8(start, value, 8);
  820                 start += 8;
  821                 words--;
  822         }
  823 
  824         return check_bytes8(start, value, bytes % 8);
  825 }
  826 EXPORT_SYMBOL(memchr_inv);

Cache object: d84b4e6bc5c995c0d496c0cb58cde3d6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.