2005-04-17 02:20:36 +04:00
/*
* linux / lib / string . c
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
*/
/*
* stupid library routines . . The optimized versions should generally be found
* as inline code in < asm - xx / string . h >
*
* These are buggy as well . .
*
* * Fri Jun 25 1999 , Ingo Oeser < ioe @ informatik . tu - chemnitz . de >
* - Added strsep ( ) which will replace strtok ( ) soon ( because strsep ( ) is
* reentrant and should be faster ) . Use only strsep ( ) in new code , please .
*
* * Sat Feb 09 2002 , Jason Thomas < jason @ topic . com . au > ,
* Matthew Hawkins < matt @ mh . dropbear . id . au >
* - Kissed strtok ( ) goodbye
*/
# include <linux/types.h>
# include <linux/string.h>
# include <linux/ctype.h>
2012-01-21 03:35:53 +04:00
# include <linux/bug.h>
2005-04-17 02:20:36 +04:00
# include <linux/module.h>
# ifndef __HAVE_ARCH_STRNICMP
/**
* strnicmp - Case insensitive , length - limited string comparison
* @ s1 : One string
* @ s2 : The other string
* @ len : the maximum number of characters to compare
*/
int strnicmp ( const char * s1 , const char * s2 , size_t len )
{
/* Yes, Virginia, it had better be unsigned */
unsigned char c1 , c2 ;
2010-03-06 00:43:11 +03:00
if ( ! len )
return 0 ;
do {
c1 = * s1 + + ;
c2 = * s2 + + ;
if ( ! c1 | | ! c2 )
break ;
if ( c1 = = c2 )
continue ;
c1 = tolower ( c1 ) ;
c2 = tolower ( c2 ) ;
if ( c1 ! = c2 )
break ;
} while ( - - len ) ;
2005-04-17 02:20:36 +04:00
return ( int ) c1 - ( int ) c2 ;
}
EXPORT_SYMBOL ( strnicmp ) ;
# endif
2007-03-29 12:18:42 +04:00
# ifndef __HAVE_ARCH_STRCASECMP
int strcasecmp ( const char * s1 , const char * s2 )
{
int c1 , c2 ;
do {
c1 = tolower ( * s1 + + ) ;
c2 = tolower ( * s2 + + ) ;
} while ( c1 = = c2 & & c1 ! = 0 ) ;
return c1 - c2 ;
}
EXPORT_SYMBOL ( strcasecmp ) ;
# endif
# ifndef __HAVE_ARCH_STRNCASECMP
int strncasecmp ( const char * s1 , const char * s2 , size_t n )
{
int c1 , c2 ;
do {
c1 = tolower ( * s1 + + ) ;
c2 = tolower ( * s2 + + ) ;
} while ( ( - - n > 0 ) & & c1 = = c2 & & c1 ! = 0 ) ;
return c1 - c2 ;
}
EXPORT_SYMBOL ( strncasecmp ) ;
# endif
2005-04-17 02:20:36 +04:00
# ifndef __HAVE_ARCH_STRCPY
/**
* strcpy - Copy a % NUL terminated string
* @ dest : Where to copy the string to
* @ src : Where to copy the string from
*/
2005-05-06 03:15:17 +04:00
# undef strcpy
2005-10-31 02:02:11 +03:00
char * strcpy ( char * dest , const char * src )
2005-04-17 02:20:36 +04:00
{
char * tmp = dest ;
while ( ( * dest + + = * src + + ) ! = ' \0 ' )
/* nothing */ ;
return tmp ;
}
EXPORT_SYMBOL ( strcpy ) ;
# endif
# ifndef __HAVE_ARCH_STRNCPY
/**
* strncpy - Copy a length - limited , % NUL - terminated string
* @ dest : Where to copy the string to
* @ src : Where to copy the string from
* @ count : The maximum number of bytes to copy
*
* The result is not % NUL - terminated if the source exceeds
* @ count bytes .
2005-05-06 03:16:20 +04:00
*
* In the case where the length of @ src is less than that of
* count , the remainder of @ dest will be padded with % NUL .
*
2005-04-17 02:20:36 +04:00
*/
2005-10-31 02:02:11 +03:00
char * strncpy ( char * dest , const char * src , size_t count )
2005-04-17 02:20:36 +04:00
{
char * tmp = dest ;
while ( count ) {
2005-10-31 02:02:11 +03:00
if ( ( * tmp = * src ) ! = 0 )
src + + ;
2005-04-17 02:20:36 +04:00
tmp + + ;
count - - ;
}
return dest ;
}
EXPORT_SYMBOL ( strncpy ) ;
# endif
# ifndef __HAVE_ARCH_STRLCPY
/**
* strlcpy - Copy a % NUL terminated string into a sized buffer
* @ dest : Where to copy the string to
* @ src : Where to copy the string from
* @ size : size of destination buffer
*
* Compatible with * BSD : the result is always a valid
* NUL - terminated string that fits in the buffer ( unless ,
* of course , the buffer size is zero ) . It does not pad
* out the result like strncpy ( ) does .
*/
size_t strlcpy ( char * dest , const char * src , size_t size )
{
size_t ret = strlen ( src ) ;
if ( size ) {
2005-10-31 02:02:11 +03:00
size_t len = ( ret > = size ) ? size - 1 : ret ;
2005-04-17 02:20:36 +04:00
memcpy ( dest , src , len ) ;
dest [ len ] = ' \0 ' ;
}
return ret ;
}
EXPORT_SYMBOL ( strlcpy ) ;
# endif
# ifndef __HAVE_ARCH_STRCAT
/**
* strcat - Append one % NUL - terminated string to another
* @ dest : The string to be appended to
* @ src : The string to append to it
*/
2005-05-06 03:15:17 +04:00
# undef strcat
2005-10-31 02:02:11 +03:00
char * strcat ( char * dest , const char * src )
2005-04-17 02:20:36 +04:00
{
char * tmp = dest ;
while ( * dest )
dest + + ;
while ( ( * dest + + = * src + + ) ! = ' \0 ' )
;
return tmp ;
}
EXPORT_SYMBOL ( strcat ) ;
# endif
# ifndef __HAVE_ARCH_STRNCAT
/**
* strncat - Append a length - limited , % NUL - terminated string to another
* @ dest : The string to be appended to
* @ src : The string to append to it
* @ count : The maximum numbers of bytes to copy
*
2007-02-10 12:45:59 +03:00
* Note that in contrast to strncpy ( ) , strncat ( ) ensures the result is
2005-04-17 02:20:36 +04:00
* terminated .
*/
2005-10-31 02:02:11 +03:00
char * strncat ( char * dest , const char * src , size_t count )
2005-04-17 02:20:36 +04:00
{
char * tmp = dest ;
if ( count ) {
while ( * dest )
dest + + ;
while ( ( * dest + + = * src + + ) ! = 0 ) {
if ( - - count = = 0 ) {
* dest = ' \0 ' ;
break ;
}
}
}
return tmp ;
}
EXPORT_SYMBOL ( strncat ) ;
# endif
# ifndef __HAVE_ARCH_STRLCAT
/**
* strlcat - Append a length - limited , % NUL - terminated string to another
* @ dest : The string to be appended to
* @ src : The string to append to it
* @ count : The size of the destination buffer .
*/
size_t strlcat ( char * dest , const char * src , size_t count )
{
size_t dsize = strlen ( dest ) ;
size_t len = strlen ( src ) ;
size_t res = dsize + len ;
/* This would be a bug */
BUG_ON ( dsize > = count ) ;
dest + = dsize ;
count - = dsize ;
if ( len > = count )
len = count - 1 ;
memcpy ( dest , src , len ) ;
dest [ len ] = 0 ;
return res ;
}
EXPORT_SYMBOL ( strlcat ) ;
# endif
# ifndef __HAVE_ARCH_STRCMP
/**
* strcmp - Compare two strings
* @ cs : One string
* @ ct : Another string
*/
2005-05-06 03:15:17 +04:00
# undef strcmp
2005-10-31 02:02:11 +03:00
int strcmp ( const char * cs , const char * ct )
2005-04-17 02:20:36 +04:00
{
2009-11-19 00:31:52 +03:00
unsigned char c1 , c2 ;
2005-04-17 02:20:36 +04:00
while ( 1 ) {
2009-11-19 00:31:52 +03:00
c1 = * cs + + ;
c2 = * ct + + ;
if ( c1 ! = c2 )
return c1 < c2 ? - 1 : 1 ;
if ( ! c1 )
2005-04-17 02:20:36 +04:00
break ;
}
2009-11-19 00:31:52 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( strcmp ) ;
# endif
# ifndef __HAVE_ARCH_STRNCMP
/**
* strncmp - Compare two length - limited strings
* @ cs : One string
* @ ct : Another string
* @ count : The maximum number of bytes to compare
*/
2005-10-31 02:02:11 +03:00
int strncmp ( const char * cs , const char * ct , size_t count )
2005-04-17 02:20:36 +04:00
{
2009-11-19 00:31:52 +03:00
unsigned char c1 , c2 ;
2005-04-17 02:20:36 +04:00
while ( count ) {
2009-11-19 00:31:52 +03:00
c1 = * cs + + ;
c2 = * ct + + ;
if ( c1 ! = c2 )
return c1 < c2 ? - 1 : 1 ;
if ( ! c1 )
2005-04-17 02:20:36 +04:00
break ;
count - - ;
}
2009-11-19 00:31:52 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( strncmp ) ;
# endif
# ifndef __HAVE_ARCH_STRCHR
/**
* strchr - Find the first occurrence of a character in a string
* @ s : The string to be searched
* @ c : The character to search for
*/
2005-10-31 02:02:11 +03:00
char * strchr ( const char * s , int c )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:11 +03:00
for ( ; * s ! = ( char ) c ; + + s )
2005-04-17 02:20:36 +04:00
if ( * s = = ' \0 ' )
return NULL ;
2005-10-31 02:02:11 +03:00
return ( char * ) s ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( strchr ) ;
# endif
# ifndef __HAVE_ARCH_STRRCHR
/**
* strrchr - Find the last occurrence of a character in a string
* @ s : The string to be searched
* @ c : The character to search for
*/
2005-10-31 02:02:11 +03:00
char * strrchr ( const char * s , int c )
2005-04-17 02:20:36 +04:00
{
const char * p = s + strlen ( s ) ;
do {
if ( * p = = ( char ) c )
return ( char * ) p ;
} while ( - - p > = s ) ;
return NULL ;
}
EXPORT_SYMBOL ( strrchr ) ;
# endif
# ifndef __HAVE_ARCH_STRNCHR
/**
* strnchr - Find a character in a length limited string
* @ s : The string to be searched
* @ count : The number of characters to be searched
* @ c : The character to search for
*/
char * strnchr ( const char * s , size_t count , int c )
{
for ( ; count - - & & * s ! = ' \0 ' ; + + s )
2005-10-31 02:02:11 +03:00
if ( * s = = ( char ) c )
return ( char * ) s ;
2005-04-17 02:20:36 +04:00
return NULL ;
}
EXPORT_SYMBOL ( strnchr ) ;
# endif
2009-12-15 05:01:04 +03:00
/**
2009-12-22 01:37:22 +03:00
* skip_spaces - Removes leading whitespace from @ str .
* @ str : The string to be stripped .
2009-12-15 05:01:04 +03:00
*
2009-12-22 01:37:22 +03:00
* Returns a pointer to the first non - whitespace character in @ str .
2009-12-15 05:01:04 +03:00
*/
char * skip_spaces ( const char * str )
{
while ( isspace ( * str ) )
+ + str ;
return ( char * ) str ;
}
EXPORT_SYMBOL ( skip_spaces ) ;
2006-06-23 13:05:44 +04:00
/**
2009-12-15 05:01:15 +03:00
* strim - Removes leading and trailing whitespace from @ s .
2006-06-23 13:05:44 +04:00
* @ s : The string to be stripped .
*
* Note that the first trailing whitespace is replaced with a % NUL - terminator
* in the given string @ s . Returns a pointer to the first non - whitespace
* character in @ s .
*/
2009-12-15 05:01:15 +03:00
char * strim ( char * s )
2006-06-23 13:05:44 +04:00
{
size_t size ;
char * end ;
size = strlen ( s ) ;
if ( ! size )
return s ;
end = s + size - 1 ;
2006-10-28 21:38:47 +04:00
while ( end > = s & & isspace ( * end ) )
2006-06-23 13:05:44 +04:00
end - - ;
* ( end + 1 ) = ' \0 ' ;
2011-11-01 04:12:37 +04:00
return skip_spaces ( s ) ;
2006-06-23 13:05:44 +04:00
}
2009-12-15 05:01:15 +03:00
EXPORT_SYMBOL ( strim ) ;
2006-06-23 13:05:44 +04:00
2005-04-17 02:20:36 +04:00
# ifndef __HAVE_ARCH_STRLEN
/**
* strlen - Find the length of a string
* @ s : The string to be sized
*/
2005-10-31 02:02:11 +03:00
size_t strlen ( const char * s )
2005-04-17 02:20:36 +04:00
{
const char * sc ;
for ( sc = s ; * sc ! = ' \0 ' ; + + sc )
/* nothing */ ;
return sc - s ;
}
EXPORT_SYMBOL ( strlen ) ;
# endif
# ifndef __HAVE_ARCH_STRNLEN
/**
* strnlen - Find the length of a length - limited string
* @ s : The string to be sized
* @ count : The maximum number of bytes to search
*/
2005-10-31 02:02:11 +03:00
size_t strnlen ( const char * s , size_t count )
2005-04-17 02:20:36 +04:00
{
const char * sc ;
for ( sc = s ; count - - & & * sc ! = ' \0 ' ; + + sc )
/* nothing */ ;
return sc - s ;
}
EXPORT_SYMBOL ( strnlen ) ;
# endif
# ifndef __HAVE_ARCH_STRSPN
/**
2007-02-10 12:45:59 +03:00
* strspn - Calculate the length of the initial substring of @ s which only contain letters in @ accept
2005-04-17 02:20:36 +04:00
* @ s : The string to be searched
* @ accept : The string to search for
*/
size_t strspn ( const char * s , const char * accept )
{
const char * p ;
const char * a ;
size_t count = 0 ;
for ( p = s ; * p ! = ' \0 ' ; + + p ) {
for ( a = accept ; * a ! = ' \0 ' ; + + a ) {
if ( * p = = * a )
break ;
}
if ( * a = = ' \0 ' )
return count ;
+ + count ;
}
return count ;
}
EXPORT_SYMBOL ( strspn ) ;
# endif
2006-04-11 09:53:57 +04:00
# ifndef __HAVE_ARCH_STRCSPN
2005-04-17 02:20:36 +04:00
/**
2007-02-10 12:45:59 +03:00
* strcspn - Calculate the length of the initial substring of @ s which does not contain letters in @ reject
2005-04-17 02:20:36 +04:00
* @ s : The string to be searched
* @ reject : The string to avoid
*/
size_t strcspn ( const char * s , const char * reject )
{
const char * p ;
const char * r ;
size_t count = 0 ;
for ( p = s ; * p ! = ' \0 ' ; + + p ) {
for ( r = reject ; * r ! = ' \0 ' ; + + r ) {
if ( * p = = * r )
return count ;
}
+ + count ;
}
return count ;
2005-10-31 02:02:11 +03:00
}
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( strcspn ) ;
2006-04-11 09:53:57 +04:00
# endif
2005-04-17 02:20:36 +04:00
# ifndef __HAVE_ARCH_STRPBRK
/**
* strpbrk - Find the first occurrence of a set of characters
* @ cs : The string to be searched
* @ ct : The characters to search for
*/
2005-10-31 02:02:11 +03:00
char * strpbrk ( const char * cs , const char * ct )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:11 +03:00
const char * sc1 , * sc2 ;
2005-04-17 02:20:36 +04:00
2005-10-31 02:02:11 +03:00
for ( sc1 = cs ; * sc1 ! = ' \0 ' ; + + sc1 ) {
for ( sc2 = ct ; * sc2 ! = ' \0 ' ; + + sc2 ) {
2005-04-17 02:20:36 +04:00
if ( * sc1 = = * sc2 )
2005-10-31 02:02:11 +03:00
return ( char * ) sc1 ;
2005-04-17 02:20:36 +04:00
}
}
return NULL ;
}
2006-04-11 09:53:56 +04:00
EXPORT_SYMBOL ( strpbrk ) ;
2005-04-17 02:20:36 +04:00
# endif
# ifndef __HAVE_ARCH_STRSEP
/**
* strsep - Split a string into tokens
* @ s : The string to be searched
* @ ct : The characters to search for
*
* strsep ( ) updates @ s to point after the token , ready for the next call .
*
* It returns empty tokens , too , behaving exactly like the libc function
* of that name . In fact , it was stolen from glibc2 and de - fancy - fied .
* Same semantics , slimmer shape . ; )
*/
2005-10-31 02:02:11 +03:00
char * strsep ( char * * s , const char * ct )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:11 +03:00
char * sbegin = * s ;
char * end ;
2005-04-17 02:20:36 +04:00
if ( sbegin = = NULL )
return NULL ;
end = strpbrk ( sbegin , ct ) ;
if ( end )
* end + + = ' \0 ' ;
* s = end ;
return sbegin ;
}
EXPORT_SYMBOL ( strsep ) ;
# endif
2008-05-01 15:34:42 +04:00
/**
* sysfs_streq - return true if strings are equal , modulo trailing newline
* @ s1 : one string
* @ s2 : another string
*
* This routine returns true iff two strings are equal , treating both
* NUL and newline - then - NUL as equivalent string terminations . It ' s
* geared for use with sysfs input strings , which generally terminate
* with newlines but are compared against values without newlines .
*/
bool sysfs_streq ( const char * s1 , const char * s2 )
{
while ( * s1 & & * s1 = = * s2 ) {
s1 + + ;
s2 + + ;
}
if ( * s1 = = * s2 )
return true ;
if ( ! * s1 & & * s2 = = ' \n ' & & ! s2 [ 1 ] )
return true ;
if ( * s1 = = ' \n ' & & ! s1 [ 1 ] & & ! * s2 )
return true ;
return false ;
}
EXPORT_SYMBOL ( sysfs_streq ) ;
2011-04-19 15:43:45 +04:00
/**
* strtobool - convert common user inputs into boolean values
* @ s : input string
* @ res : result
*
* This routine returns 0 iff the first character is one of ' Yy1Nn0 ' .
* Otherwise it will return - EINVAL . Value pointed to by res is
* updated upon finding a match .
*/
int strtobool ( const char * s , bool * res )
{
switch ( s [ 0 ] ) {
case ' y ' :
case ' Y ' :
case ' 1 ' :
* res = true ;
break ;
case ' n ' :
case ' N ' :
case ' 0 ' :
* res = false ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
EXPORT_SYMBOL ( strtobool ) ;
2005-04-17 02:20:36 +04:00
# ifndef __HAVE_ARCH_MEMSET
/**
* memset - Fill a region of memory with the given value
* @ s : Pointer to the start of the area .
* @ c : The byte to fill the area with
* @ count : The size of the area .
*
* Do not use memset ( ) to access IO space , use memset_io ( ) instead .
*/
2005-10-31 02:02:11 +03:00
void * memset ( void * s , int c , size_t count )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:13 +03:00
char * xs = s ;
2005-04-17 02:20:36 +04:00
while ( count - - )
* xs + + = c ;
return s ;
}
EXPORT_SYMBOL ( memset ) ;
# endif
# ifndef __HAVE_ARCH_MEMCPY
/**
* memcpy - Copy one area of memory to another
* @ dest : Where to copy to
* @ src : Where to copy from
* @ count : The size of the area .
*
* You should not use this function to access IO space , use memcpy_toio ( )
* or memcpy_fromio ( ) instead .
*/
2005-10-31 02:02:11 +03:00
void * memcpy ( void * dest , const void * src , size_t count )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:13 +03:00
char * tmp = dest ;
2006-04-11 09:54:09 +04:00
const char * s = src ;
2005-04-17 02:20:36 +04:00
while ( count - - )
* tmp + + = * s + + ;
return dest ;
}
EXPORT_SYMBOL ( memcpy ) ;
# endif
# ifndef __HAVE_ARCH_MEMMOVE
/**
* memmove - Copy one area of memory to another
* @ dest : Where to copy to
* @ src : Where to copy from
* @ count : The size of the area .
*
* Unlike memcpy ( ) , memmove ( ) copes with overlapping areas .
*/
2005-10-31 02:02:11 +03:00
void * memmove ( void * dest , const void * src , size_t count )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:03:19 +03:00
char * tmp ;
const char * s ;
2005-04-17 02:20:36 +04:00
if ( dest < = src ) {
2005-10-31 02:02:13 +03:00
tmp = dest ;
s = src ;
2005-04-17 02:20:36 +04:00
while ( count - - )
* tmp + + = * s + + ;
2005-10-31 02:02:11 +03:00
} else {
2005-10-31 02:02:13 +03:00
tmp = dest ;
tmp + = count ;
s = src ;
s + = count ;
2005-04-17 02:20:36 +04:00
while ( count - - )
* - - tmp = * - - s ;
2005-10-31 02:02:11 +03:00
}
2005-04-17 02:20:36 +04:00
return dest ;
}
EXPORT_SYMBOL ( memmove ) ;
# endif
# ifndef __HAVE_ARCH_MEMCMP
/**
* memcmp - Compare two areas of memory
* @ cs : One area of memory
* @ ct : Another area of memory
* @ count : The size of the area .
*/
2005-05-06 03:15:17 +04:00
# undef memcmp
2005-10-31 02:02:11 +03:00
int memcmp ( const void * cs , const void * ct , size_t count )
2005-04-17 02:20:36 +04:00
{
const unsigned char * su1 , * su2 ;
int res = 0 ;
2005-10-31 02:02:11 +03:00
for ( su1 = cs , su2 = ct ; 0 < count ; + + su1 , + + su2 , count - - )
2005-04-17 02:20:36 +04:00
if ( ( res = * su1 - * su2 ) ! = 0 )
break ;
return res ;
}
EXPORT_SYMBOL ( memcmp ) ;
# endif
# ifndef __HAVE_ARCH_MEMSCAN
/**
* memscan - Find a character in an area of memory .
* @ addr : The memory area
* @ c : The byte to search for
* @ size : The size of the area .
*
* returns the address of the first occurrence of @ c , or 1 byte past
* the area if @ c is not found
*/
2005-10-31 02:02:11 +03:00
void * memscan ( void * addr , int c , size_t size )
2005-04-17 02:20:36 +04:00
{
2005-10-31 02:02:13 +03:00
unsigned char * p = addr ;
2005-04-17 02:20:36 +04:00
while ( size ) {
if ( * p = = c )
2005-10-31 02:02:11 +03:00
return ( void * ) p ;
2005-04-17 02:20:36 +04:00
p + + ;
size - - ;
}
2005-10-31 02:02:11 +03:00
return ( void * ) p ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( memscan ) ;
# endif
# ifndef __HAVE_ARCH_STRSTR
/**
* strstr - Find the first substring in a % NUL terminated string
* @ s1 : The string to be searched
* @ s2 : The string to search for
*/
2005-10-31 02:02:11 +03:00
char * strstr ( const char * s1 , const char * s2 )
2005-04-17 02:20:36 +04:00
{
2010-01-14 05:53:55 +03:00
size_t l1 , l2 ;
2005-04-17 02:20:36 +04:00
l2 = strlen ( s2 ) ;
if ( ! l2 )
2005-10-31 02:02:11 +03:00
return ( char * ) s1 ;
2005-04-17 02:20:36 +04:00
l1 = strlen ( s1 ) ;
while ( l1 > = l2 ) {
l1 - - ;
2005-10-31 02:02:11 +03:00
if ( ! memcmp ( s1 , s2 , l2 ) )
return ( char * ) s1 ;
2005-04-17 02:20:36 +04:00
s1 + + ;
}
return NULL ;
}
EXPORT_SYMBOL ( strstr ) ;
# endif
2010-01-14 05:53:55 +03:00
# ifndef __HAVE_ARCH_STRNSTR
/**
* strnstr - Find the first substring in a length - limited string
* @ s1 : The string to be searched
* @ s2 : The string to search for
* @ len : the maximum number of characters to search
*/
char * strnstr ( const char * s1 , const char * s2 , size_t len )
{
2010-03-06 00:43:12 +03:00
size_t l2 ;
2010-01-14 05:53:55 +03:00
l2 = strlen ( s2 ) ;
if ( ! l2 )
return ( char * ) s1 ;
2010-03-06 00:43:12 +03:00
while ( len > = l2 ) {
len - - ;
2010-01-14 05:53:55 +03:00
if ( ! memcmp ( s1 , s2 , l2 ) )
return ( char * ) s1 ;
s1 + + ;
}
return NULL ;
}
EXPORT_SYMBOL ( strnstr ) ;
# endif
2005-04-17 02:20:36 +04:00
# ifndef __HAVE_ARCH_MEMCHR
/**
* memchr - Find a character in an area of memory .
* @ s : The memory area
* @ c : The byte to search for
* @ n : The size of the area .
*
* returns the address of the first occurrence of @ c , or % NULL
* if @ c is not found
*/
void * memchr ( const void * s , int c , size_t n )
{
const unsigned char * p = s ;
while ( n - - ! = 0 ) {
if ( ( unsigned char ) c = = * p + + ) {
2005-10-31 02:02:11 +03:00
return ( void * ) ( p - 1 ) ;
2005-04-17 02:20:36 +04:00
}
}
return NULL ;
}
EXPORT_SYMBOL ( memchr ) ;
# endif
2011-11-01 04:08:07 +04:00
static void * check_bytes8 ( const u8 * start , u8 value , unsigned int bytes )
{
while ( bytes ) {
if ( * start ! = value )
return ( void * ) start ;
start + + ;
bytes - - ;
}
return NULL ;
}
/**
* memchr_inv - Find an unmatching character in an area of memory .
* @ start : The memory area
* @ c : Find a character other than c
* @ bytes : The size of the area .
*
* returns the address of the first character other than @ c , or % NULL
* if the whole buffer contains just @ c .
*/
void * memchr_inv ( const void * start , int c , size_t bytes )
{
u8 value = c ;
u64 value64 ;
unsigned int words , prefix ;
if ( bytes < = 16 )
return check_bytes8 ( start , value , bytes ) ;
value64 = value | value < < 8 | value < < 16 | value < < 24 ;
value64 = ( value64 & 0xffffffff ) | value64 < < 32 ;
prefix = 8 - ( ( unsigned long ) start ) % 8 ;
if ( prefix ) {
u8 * r = check_bytes8 ( start , value , prefix ) ;
if ( r )
return r ;
start + = prefix ;
bytes - = prefix ;
}
words = bytes / 8 ;
while ( words ) {
if ( * ( u64 * ) start ! = value64 )
return check_bytes8 ( start , value , 8 ) ;
start + = 8 ;
words - - ;
}
return check_bytes8 ( start , value , bytes % 8 ) ;
}
EXPORT_SYMBOL ( memchr_inv ) ;