2009-04-20 17:00:56 +04:00
# include "cache.h"
2012-03-14 19:29:29 +04:00
# include <linux/kernel.h>
2009-04-20 17:00:56 +04: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 ] ;
2009-07-01 14:37:06 +04:00
void strbuf_init ( struct strbuf * sb , ssize_t hint )
2009-04-20 17:00:56 +04:00
{
sb - > alloc = sb - > len = 0 ;
sb - > buf = strbuf_slopbuf ;
if ( hint )
strbuf_grow ( sb , hint ) ;
}
void strbuf_release ( struct strbuf * sb )
{
if ( sb - > alloc ) {
free ( sb - > buf ) ;
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 ;
}
void strbuf_grow ( struct strbuf * sb , size_t extra )
{
if ( sb - > len + extra + 1 < = sb - > len )
die ( " you want to use way too much memory " ) ;
if ( ! sb - > alloc )
sb - > buf = NULL ;
ALLOC_GROW ( sb - > buf , sb - > len + extra + 1 , sb - > alloc ) ;
}
2010-05-19 01:29:23 +04:00
static void strbuf_splice ( struct strbuf * sb , size_t pos , size_t len ,
2009-04-20 17:00:56 +04:00
const void * data , size_t dlen )
{
if ( pos + len < pos )
die ( " you want to use way too much memory " ) ;
if ( pos > sb - > len )
die ( " `pos' is too far after the end of the buffer " ) ;
if ( pos + len > sb - > len )
die ( " `pos + len' is too far after the end of the buffer " ) ;
if ( dlen > = len )
strbuf_grow ( sb , dlen - len ) ;
memmove ( sb - > buf + pos + dlen ,
sb - > buf + pos + len ,
sb - > len - pos - len ) ;
memcpy ( sb - > buf + pos , data , dlen ) ;
strbuf_setlen ( sb , sb - > len + dlen - len ) ;
}
void strbuf_remove ( struct strbuf * sb , size_t pos , size_t len )
{
strbuf_splice ( sb , pos , len , NULL , 0 ) ;
}
void strbuf_add ( struct strbuf * sb , const void * data , size_t len )
{
strbuf_grow ( sb , len ) ;
memcpy ( sb - > buf + sb - > len , data , len ) ;
strbuf_setlen ( sb , sb - > len + len ) ;
}
void strbuf_addf ( struct strbuf * sb , const char * fmt , . . . )
{
int len ;
va_list ap ;
if ( ! strbuf_avail ( sb ) )
strbuf_grow ( sb , 64 ) ;
va_start ( ap , fmt ) ;
2012-10-23 17:44:50 +04:00
len = vsnprintf ( sb - > buf + sb - > len , sb - > alloc - sb - > len , fmt , ap ) ;
2009-04-20 17:00:56 +04:00
va_end ( ap ) ;
if ( len < 0 )
2012-10-23 17:44:50 +04:00
die ( " your vsnprintf is broken " ) ;
2009-04-20 17:00:56 +04:00
if ( len > strbuf_avail ( sb ) ) {
strbuf_grow ( sb , len ) ;
va_start ( ap , fmt ) ;
2012-10-23 17:44:50 +04:00
len = vsnprintf ( sb - > buf + sb - > len , sb - > alloc - sb - > len , fmt , ap ) ;
2009-04-20 17:00:56 +04:00
va_end ( ap ) ;
if ( len > strbuf_avail ( sb ) ) {
2012-10-23 17:44:50 +04:00
die ( " this should not happen, your vsnprintf is broken " ) ;
2009-04-20 17:00:56 +04:00
}
}
strbuf_setlen ( sb , sb - > len + len ) ;
}
2009-07-01 14:37:06 +04:00
ssize_t strbuf_read ( struct strbuf * sb , int fd , ssize_t hint )
2009-04-20 17:00:56 +04:00
{
size_t oldlen = sb - > len ;
size_t oldalloc = sb - > alloc ;
strbuf_grow ( sb , hint ? hint : 8192 ) ;
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 ) ;
return - 1 ;
}
if ( ! cnt )
break ;
sb - > len + = cnt ;
strbuf_grow ( sb , 8192 ) ;
}
sb - > buf [ sb - > len ] = ' \0 ' ;
return sb - > len - oldlen ;
}