2009-11-15 20:36:53 +09:00
# include "util.h"
2010-04-04 17:13:18 +09:00
# include "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 ) ;
}