2009-11-15 20:36:53 +09:00
# include "util.h"
2012-09-10 18:50:17 +02:00
# include "linux/string.h"
2009-06-01 22:31:03 -03:00
2009-11-15 20:36:53 +09:00
# define K 1024LL
/*
* perf_atoll ( )
* Parse ( \ d + ) ( b | B | kb | KB | mb | MB | gb | GB | tb | TB ) ( e . g . " 256MB " )
* and return its numeric value
*/
s64 perf_atoll ( const char * str )
{
unsigned int i ;
s64 length = - 1 , unit = 1 ;
if ( ! isdigit ( str [ 0 ] ) )
goto out_err ;
for ( i = 1 ; i < strlen ( str ) ; i + + ) {
switch ( str [ i ] ) {
case ' B ' :
case ' b ' :
break ;
case ' K ' :
if ( str [ i + 1 ] ! = ' B ' )
goto out_err ;
else
goto kilo ;
case ' k ' :
if ( str [ i + 1 ] ! = ' b ' )
goto out_err ;
kilo :
unit = K ;
break ;
case ' M ' :
if ( str [ i + 1 ] ! = ' B ' )
goto out_err ;
else
goto mega ;
case ' m ' :
if ( str [ i + 1 ] ! = ' b ' )
goto out_err ;
mega :
unit = K * K ;
break ;
case ' G ' :
if ( str [ i + 1 ] ! = ' B ' )
goto out_err ;
else
goto giga ;
case ' g ' :
if ( str [ i + 1 ] ! = ' b ' )
goto out_err ;
giga :
unit = K * K * K ;
break ;
case ' T ' :
if ( str [ i + 1 ] ! = ' B ' )
goto out_err ;
else
goto tera ;
case ' t ' :
if ( str [ i + 1 ] ! = ' b ' )
goto out_err ;
tera :
unit = K * K * K * K ;
break ;
case ' \0 ' : /* only specified figures */
unit = 1 ;
break ;
default :
if ( ! isdigit ( str [ i ] ) )
goto out_err ;
break ;
}
}
length = atoll ( str ) * unit ;
goto out ;
out_err :
length = - 1 ;
out :
return length ;
}
2009-11-30 19:20:05 -05:00
/*
* Helper function for splitting a string into an argv - like array .
2011-03-30 22:57:33 -03:00
* originally copied from lib / argv_split . c
2009-11-30 19:20:05 -05:00
*/
static const char * skip_sep ( const char * cp )
{
while ( * cp & & isspace ( * cp ) )
cp + + ;
return cp ;
}
static const char * skip_arg ( const char * cp )
{
while ( * cp & & ! isspace ( * cp ) )
cp + + ;
return cp ;
}
static int count_argc ( const char * str )
{
int count = 0 ;
while ( * str ) {
str = skip_sep ( str ) ;
if ( * str ) {
count + + ;
str = skip_arg ( str ) ;
}
}
return count ;
}
/**
* argv_free - free an argv
* @ argv - the argument vector to be freed
*
* Frees an argv and the strings it points to .
*/
void argv_free ( char * * argv )
{
char * * p ;
for ( p = argv ; * p ; p + + )
free ( * p ) ;
free ( argv ) ;
}
/**
* argv_split - split a string at whitespace , returning an argv
* @ str : the string to be split
* @ argcp : returned argument count
*
* Returns an array of pointers to strings which are split out from
* @ str . This is performed by strictly splitting on white - space ; no
* quote processing is performed . Multiple whitespace characters are
* considered to be a single argument separator . The returned array
* is always NULL - terminated . Returns NULL on memory allocation
* failure .
*/
char * * argv_split ( const char * str , int * argcp )
{
int argc = count_argc ( str ) ;
char * * argv = zalloc ( sizeof ( * argv ) * ( argc + 1 ) ) ;
char * * argvp ;
if ( argv = = NULL )
goto out ;
if ( argcp )
* argcp = argc ;
argvp = argv ;
while ( * str ) {
str = skip_sep ( str ) ;
if ( * str ) {
const char * p = str ;
char * t ;
str = skip_arg ( str ) ;
t = strndup ( p , str - p ) ;
if ( t = = NULL )
goto fail ;
* argvp + + = t ;
}
}
* argvp = NULL ;
out :
return argv ;
fail :
argv_free ( argv ) ;
return NULL ;
}
2009-12-15 10:32:10 -05:00
2010-01-05 17:47:24 -05:00
/* Character class matching */
static bool __match_charclass ( const char * pat , char c , const char * * npat )
{
bool complement = false , ret = true ;
if ( * pat = = ' ! ' ) {
complement = true ;
pat + + ;
}
if ( * pat + + = = c ) /* First character is special */
goto end ;
while ( * pat & & * pat ! = ' ] ' ) { /* Matching */
if ( * pat = = ' - ' & & * ( pat + 1 ) ! = ' ] ' ) { /* Range */
if ( * ( pat - 1 ) < = c & & c < = * ( pat + 1 ) )
goto end ;
if ( * ( pat - 1 ) > * ( pat + 1 ) )
goto error ;
pat + = 2 ;
} else if ( * pat + + = = c )
goto end ;
}
if ( ! * pat )
goto error ;
ret = false ;
end :
while ( * pat & & * pat ! = ' ] ' ) /* Searching closing */
pat + + ;
if ( ! * pat )
goto error ;
* npat = pat + 1 ;
return complement ? ! ret : ret ;
error :
return false ;
}
2010-02-25 08:36:12 -05:00
/* Glob/lazy pattern matching */
static bool __match_glob ( const char * str , const char * pat , bool ignore_space )
2009-12-15 10:32:10 -05:00
{
while ( * str & & * pat & & * pat ! = ' * ' ) {
2010-02-25 08:36:12 -05:00
if ( ignore_space ) {
/* Ignore spaces for lazy matching */
if ( isspace ( * str ) ) {
str + + ;
continue ;
}
if ( isspace ( * pat ) ) {
pat + + ;
continue ;
}
}
2010-01-05 17:47:24 -05:00
if ( * pat = = ' ? ' ) { /* Matches any single character */
2009-12-15 10:32:10 -05:00
str + + ;
pat + + ;
2010-01-05 17:47:24 -05:00
continue ;
} else if ( * pat = = ' [ ' ) /* Character classes/Ranges */
if ( __match_charclass ( pat + 1 , * str , & pat ) ) {
str + + ;
continue ;
} else
2009-12-15 10:32:10 -05:00
return false ;
2010-01-05 17:47:24 -05:00
else if ( * pat = = ' \\ ' ) /* Escaped char match as normal char */
pat + + ;
if ( * str + + ! = * pat + + )
return false ;
2009-12-15 10:32:10 -05:00
}
/* Check wild card */
if ( * pat = = ' * ' ) {
while ( * pat = = ' * ' )
pat + + ;
if ( ! * pat ) /* Tail wild card matches all */
return true ;
while ( * str )
2010-12-17 22:12:00 +09:00
if ( __match_glob ( str + + , pat , ignore_space ) )
2009-12-15 10:32:10 -05:00
return true ;
}
return ! * str & & ! * pat ;
}
2010-02-25 08:36:12 -05:00
/**
* strglobmatch - glob expression pattern matching
* @ str : the target string to match
* @ pat : the pattern string to match
*
* This returns true if the @ str matches @ pat . @ pat can includes wildcards
* ( ' * ' , ' ? ' ) and character classes ( [ CHARS ] , complementation and ranges are
* also supported ) . Also , this supports escape character ( ' \ ' ) to use special
* characters as normal character .
*
* Note : if @ pat syntax is broken , this always returns false .
*/
bool strglobmatch ( const char * str , const char * pat )
{
return __match_glob ( str , pat , false ) ;
}
/**
* strlazymatch - matching pattern strings lazily with glob pattern
* @ str : the target string to match
* @ pat : the pattern string to match
*
* This is similar to strglobmatch , except this ignores spaces in
* the target string .
*/
bool strlazymatch ( const char * str , const char * pat )
{
return __match_glob ( str , pat , true ) ;
}
2011-06-27 16:27:15 +09:00
/**
* strtailcmp - Compare the tail of two strings
* @ s1 : 1 st string to be compared
* @ s2 : 2 nd string to be compared
*
* Return 0 if whole of either string is same as another ' s tail part .
*/
int strtailcmp ( const char * s1 , const char * s2 )
{
int i1 = strlen ( s1 ) ;
int i2 = strlen ( s2 ) ;
while ( - - i1 > = 0 & & - - i2 > = 0 ) {
if ( s1 [ i1 ] ! = s2 [ i2 ] )
return s1 [ i1 ] - s2 [ i2 ] ;
}
return 0 ;
}
2012-10-27 23:18:31 +02:00
/**
* strxfrchar - Locate and replace character in @ s
* @ s : The string to be searched / changed .
* @ from : Source character to be replaced .
* @ to : Destination character .
*
* Return pointer to the changed string .
*/
char * strxfrchar ( char * s , char from , char to )
{
char * p = s ;
while ( ( p = strchr ( p , from ) ) ! = NULL )
* p + + = to ;
return s ;
}
2013-01-22 18:09:41 +09:00
/**
* ltrim - Removes leading whitespace from @ s .
* @ s : The string to be stripped .
*
* Return pointer to the first non - whitespace character in @ s .
*/
char * ltrim ( char * s )
{
int len = strlen ( s ) ;
while ( len & & isspace ( * s ) ) {
len - - ;
s + + ;
}
return s ;
}
2012-06-07 18:23:31 -03:00
/**
* rtrim - Removes trailing whitespace from @ s .
* @ s : The string to be stripped .
*
* Note that the first trailing whitespace is replaced with a % NUL - terminator
* in the given string @ s . Returns @ s .
*/
char * rtrim ( char * s )
{
size_t size = strlen ( s ) ;
char * end ;
if ( ! size )
return s ;
end = s + size - 1 ;
while ( end > = s & & isspace ( * end ) )
end - - ;
* ( end + 1 ) = ' \0 ' ;
return s ;
}
2012-09-10 18:50:17 +02:00
/**
* memdup - duplicate region of memory
* @ src : memory region to duplicate
* @ len : memory region length
*/
void * memdup ( const void * src , size_t len )
{
void * p ;
p = malloc ( len ) ;
if ( p )
memcpy ( p , src , len ) ;
return p ;
}
2013-04-20 11:02:28 -07:00
/**
* str_append - reallocate string and append another
* @ s : pointer to string pointer
* @ len : pointer to len ( initialized )
* @ a : string to append .
*/
int str_append ( char * * s , int * len , const char * a )
{
int olen = * s ? strlen ( * s ) : 0 ;
int nlen = olen + strlen ( a ) + 1 ;
if ( * len < nlen ) {
* len = * len * 2 ;
if ( * len < nlen )
* len = nlen ;
* s = realloc ( * s , * len ) ;
if ( ! * s )
return - ENOMEM ;
if ( olen = = 0 )
* * s = 0 ;
}
strcat ( * s , a ) ;
return 0 ;
}