2016-05-10 14:46:58 +09:00
# include "debug.h"
2016-07-07 11:06:58 -03:00
# include "util.h"
2012-03-14 12:29:29 -03:00
# include <linux/kernel.h>
2009-04-20 15:00:56 +02:00
int prefixcmp ( const char * str , const char * prefix )
{
for ( ; ; str + + , prefix + + )
if ( ! * prefix )
return 0 ;
else if ( * str ! = * prefix )
return ( unsigned char ) * prefix - ( unsigned char ) * str ;
}
/*
* Used as the default - > buf value , so that people can always assume
* buf is non NULL and - > buf is NUL terminated even for a freshly
* initialized strbuf .
*/
char strbuf_slopbuf [ 1 ] ;
2016-05-10 14:46:58 +09:00
int strbuf_init ( struct strbuf * sb , ssize_t hint )
2009-04-20 15:00:56 +02:00
{
sb - > alloc = sb - > len = 0 ;
sb - > buf = strbuf_slopbuf ;
if ( hint )
2016-05-10 14:46:58 +09:00
return strbuf_grow ( sb , hint ) ;
return 0 ;
2009-04-20 15:00:56 +02:00
}
void strbuf_release ( struct strbuf * sb )
{
if ( sb - > alloc ) {
2013-12-27 16:55:14 -03:00
zfree ( & sb - > buf ) ;
2009-04-20 15:00:56 +02:00
strbuf_init ( sb , 0 ) ;
}
}
char * strbuf_detach ( struct strbuf * sb , size_t * sz )
{
char * res = sb - > alloc ? sb - > buf : NULL ;
if ( sz )
* sz = sb - > len ;
strbuf_init ( sb , 0 ) ;
return res ;
}
2016-05-10 14:46:58 +09:00
int strbuf_grow ( struct strbuf * sb , size_t extra )
2009-04-20 15:00:56 +02:00
{
2016-05-10 14:46:58 +09:00
char * buf ;
size_t nr = sb - > len + extra + 1 ;
if ( nr < sb - > alloc )
return 0 ;
if ( nr < = sb - > len )
return - E2BIG ;
if ( alloc_nr ( sb - > alloc ) > nr )
nr = alloc_nr ( sb - > alloc ) ;
/*
* Note that sb - > buf = = strbuf_slopbuf if sb - > alloc = = 0 , and it is
* a static variable . Thus we have to avoid passing it to realloc .
*/
buf = realloc ( sb - > alloc ? sb - > buf : NULL , nr * sizeof ( * buf ) ) ;
if ( ! buf )
return - ENOMEM ;
sb - > buf = buf ;
sb - > alloc = nr ;
return 0 ;
2009-04-20 15:00:56 +02:00
}
2016-05-10 14:46:58 +09:00
int strbuf_addch ( struct strbuf * sb , int c )
2016-03-23 16:56:56 -03:00
{
2016-05-10 14:46:58 +09:00
int ret = strbuf_grow ( sb , 1 ) ;
if ( ret )
return ret ;
2016-03-23 16:56:56 -03:00
sb - > buf [ sb - > len + + ] = c ;
sb - > buf [ sb - > len ] = ' \0 ' ;
2016-05-10 14:46:58 +09:00
return 0 ;
2016-03-23 16:56:56 -03:00
}
2016-05-10 14:46:58 +09:00
int strbuf_add ( struct strbuf * sb , const void * data , size_t len )
2009-04-20 15:00:56 +02:00
{
2016-05-10 14:46:58 +09:00
int ret = strbuf_grow ( sb , len ) ;
if ( ret )
return ret ;
2009-04-20 15:00:56 +02:00
memcpy ( sb - > buf + sb - > len , data , len ) ;
2016-05-10 14:46:58 +09:00
return strbuf_setlen ( sb , sb - > len + len ) ;
2009-04-20 15:00:56 +02:00
}
2016-05-10 14:46:58 +09:00
static int strbuf_addv ( struct strbuf * sb , const char * fmt , va_list ap )
2009-04-20 15:00:56 +02:00
{
2016-05-10 14:46:58 +09:00
int len , ret ;
2015-10-25 00:49:27 +09:00
va_list ap_saved ;
2009-04-20 15:00:56 +02:00
2016-05-10 14:46:58 +09:00
if ( ! strbuf_avail ( sb ) ) {
ret = strbuf_grow ( sb , 64 ) ;
if ( ret )
return ret ;
}
2015-10-25 00:49:27 +09:00
va_copy ( ap_saved , ap ) ;
2012-10-23 22:44:50 +09:00
len = vsnprintf ( sb - > buf + sb - > len , sb - > alloc - sb - > len , fmt , ap ) ;
2009-04-20 15:00:56 +02:00
if ( len < 0 )
2016-05-10 14:46:58 +09:00
return len ;
2009-04-20 15:00:56 +02:00
if ( len > strbuf_avail ( sb ) ) {
2016-05-10 14:46:58 +09:00
ret = strbuf_grow ( sb , len ) ;
if ( ret )
return ret ;
2015-10-25 00:49:27 +09:00
len = vsnprintf ( sb - > buf + sb - > len , sb - > alloc - sb - > len , fmt , ap_saved ) ;
va_end ( ap_saved ) ;
2009-04-20 15:00:56 +02:00
if ( len > strbuf_avail ( sb ) ) {
2016-05-10 14:46:58 +09:00
pr_debug ( " this should not happen, your vsnprintf is broken " ) ;
return - EINVAL ;
2009-04-20 15:00:56 +02:00
}
}
2016-05-10 14:46:58 +09:00
return strbuf_setlen ( sb , sb - > len + len ) ;
2009-04-20 15:00:56 +02:00
}
2016-05-10 14:46:58 +09:00
int strbuf_addf ( struct strbuf * sb , const char * fmt , . . . )
2015-10-25 00:49:27 +09:00
{
va_list ap ;
2016-05-10 14:46:58 +09:00
int ret ;
2015-10-25 00:49:27 +09:00
va_start ( ap , fmt ) ;
2016-05-10 14:46:58 +09:00
ret = strbuf_addv ( sb , fmt , ap ) ;
2015-10-25 00:49:27 +09:00
va_end ( ap ) ;
2016-05-10 14:46:58 +09:00
return ret ;
2015-10-25 00:49:27 +09:00
}
2009-07-01 12:37:06 +02:00
ssize_t strbuf_read ( struct strbuf * sb , int fd , ssize_t hint )
2009-04-20 15:00:56 +02:00
{
size_t oldlen = sb - > len ;
size_t oldalloc = sb - > alloc ;
2016-05-10 14:46:58 +09:00
int ret ;
ret = strbuf_grow ( sb , hint ? hint : 8192 ) ;
if ( ret )
return ret ;
2009-04-20 15:00:56 +02:00
for ( ; ; ) {
ssize_t cnt ;
cnt = read ( fd , sb - > buf + sb - > len , sb - > alloc - sb - > len - 1 ) ;
if ( cnt < 0 ) {
if ( oldalloc = = 0 )
strbuf_release ( sb ) ;
else
strbuf_setlen ( sb , oldlen ) ;
2016-05-10 14:46:58 +09:00
return cnt ;
2009-04-20 15:00:56 +02:00
}
if ( ! cnt )
break ;
sb - > len + = cnt ;
2016-05-10 14:46:58 +09:00
ret = strbuf_grow ( sb , 8192 ) ;
if ( ret )
return ret ;
2009-04-20 15:00:56 +02:00
}
sb - > buf [ sb - > len ] = ' \0 ' ;
return sb - > len - oldlen ;
}