2009-09-24 18:02:18 +02:00
# ifndef __PERF_STRBUF_H
# define __PERF_STRBUF_H
2009-04-20 15:00:56 +02:00
/*
* Strbuf ' s can be use in many ways : as a byte array , or to store arbitrary
* long , overflow safe strings .
*
* Strbufs has some invariants that are very important to keep in mind :
*
* 1. the - > buf member is always malloc - ed , hence strbuf ' s can be used to
* build complex strings / buffers whose final size isn ' t easily known .
*
* It is NOT legal to copy the - > buf pointer away .
* ` strbuf_detach ' is the operation that detachs a buffer from its shell
* while keeping the shell valid wrt its invariants .
*
* 2. the - > buf member is a byte array that has at least - > len + 1 bytes
* allocated . The extra byte is used to store a ' \0 ' , allowing the - > buf
* member to be a valid C - string . Every strbuf function ensure this
* invariant is preserved .
*
* Note that it is OK to " play " with the buffer directly if you work it
* that way :
*
* strbuf_grow ( sb , SOME_SIZE ) ;
* . . . Here , the memory array starting at sb - > buf , and of length
* . . . strbuf_avail ( sb ) is all yours , and you are sure that
* . . . strbuf_avail ( sb ) is at least SOME_SIZE .
* strbuf_setlen ( sb , sb - > len + SOME_OTHER_SIZE ) ;
*
* Of course , SOME_OTHER_SIZE must be smaller or equal to strbuf_avail ( sb ) .
*
* Doing so is safe , though if it has to be done in many places , adding the
* missing API to the strbuf module is the way to go .
*
* XXX : do _not_ assume that the area that is yours is of size - > alloc - 1
* even if it ' s true in the current implementation . Alloc is somehow a
* " private " member that should not be messed with .
*/
# include <assert.h>
2015-10-25 00:49:27 +09:00
# include <stdarg.h>
2016-07-07 11:06:58 -03:00
# include <stddef.h>
# include <string.h>
# include <sys/types.h>
2009-04-20 15:00:56 +02:00
extern char strbuf_slopbuf [ ] ;
struct strbuf {
size_t alloc ;
size_t len ;
char * buf ;
} ;
# define STRBUF_INIT { 0, 0, strbuf_slopbuf }
/*----- strbuf life cycle -----*/
2016-05-10 14:46:58 +09:00
int strbuf_init ( struct strbuf * buf , ssize_t hint ) ;
2016-03-23 15:06:35 -03:00
void strbuf_release ( struct strbuf * buf ) ;
char * strbuf_detach ( struct strbuf * buf , size_t * ) ;
2009-04-20 15:00:56 +02:00
/*----- strbuf size related -----*/
2009-07-01 12:37:06 +02:00
static inline ssize_t strbuf_avail ( const struct strbuf * sb ) {
2009-04-20 15:00:56 +02:00
return sb - > alloc ? sb - > alloc - sb - > len - 1 : 0 ;
}
2016-05-10 14:46:58 +09:00
int strbuf_grow ( struct strbuf * buf , size_t ) ;
2009-04-20 15:00:56 +02:00
2016-05-10 14:46:58 +09:00
static inline int strbuf_setlen ( struct strbuf * sb , size_t len ) {
if ( ! sb - > alloc ) {
2016-10-03 11:07:24 -03:00
int ret = strbuf_grow ( sb , 0 ) ;
2016-05-10 14:46:58 +09:00
if ( ret )
return ret ;
}
2009-04-20 15:00:56 +02:00
assert ( len < sb - > alloc ) ;
sb - > len = len ;
sb - > buf [ len ] = ' \0 ' ;
2016-05-10 14:46:58 +09:00
return 0 ;
2009-04-20 15:00:56 +02:00
}
/*----- add data in your buffer -----*/
2016-05-10 14:46:58 +09:00
int strbuf_addch ( struct strbuf * sb , int c ) ;
2009-04-20 15:00:56 +02:00
2016-05-10 14:46:58 +09:00
int strbuf_add ( struct strbuf * buf , const void * , size_t ) ;
static inline int strbuf_addstr ( struct strbuf * sb , const char * s ) {
return strbuf_add ( sb , s , strlen ( s ) ) ;
2009-04-20 15:00:56 +02:00
}
__attribute__ ( ( format ( printf , 2 , 3 ) ) )
2016-05-10 14:46:58 +09:00
int strbuf_addf ( struct strbuf * sb , const char * fmt , . . . ) ;
2009-04-20 15:00:56 +02:00
/* XXX: if read fails, any partial read is undone */
2016-03-23 15:06:35 -03:00
ssize_t strbuf_read ( struct strbuf * , int fd , ssize_t hint ) ;
2009-04-20 15:00:56 +02:00
2009-09-24 18:02:18 +02:00
# endif /* __PERF_STRBUF_H */