#ifndef dbuf_H_ #define dbuf_H_ #include #ifdef __cplusplus extern "C" { #endif /** * dbuf is a generic buffer that will grow automatically. * call buf_ensure() to reserve space, and don't write more data * than you told buf_ensure() to reserve. * * You write data to buf->end * When finished writing data * you call dbuf_added/( with the no. of bytes you've added. * * You read data from buf->start, the buffer has dbuf_len() bytes of data * When you've read and processed the data, call dbuf_take() * to indicate you're done with the data. * * typically(but add error checking) * @code * DBuf buf; * dbuf_init(&buf,4096); * for(;;) { * dbuf_ensure(buf,4096); * size_t len = fread(buf,4096,1,f); * dbuf_added(&buf,len); * char *end; * while((end = memchr(buf.start,'\n',dbuf_len(&dbuf))) != NULL) { //look for a newline * ++end; * int linelen = end - buf.start; * process_line(buf.start,linelen); * dbuf_take(&dbuf,linelen); * } * } * @endcode */ typedef struct DBuf DBuf; struct DBuf { /** Start of user data */ unsigned char *start; /** End of user data */ unsigned char *end; /** Start of underlying buffer. Internal use.*/ unsigned char *bufstart; /** End of underlying buffer. Internal use.*/ unsigned char *bufend; }; /** Free the internals of a DBuf, does not free buf itself. * Does nothing if buf == NULL * * @param buf buffer to free */ void uc_dbuf_free(DBuf *buf); /** Initialize a dbuf. * * @param buf buffer to initialize * @param initlen inital capacity of the buffer * @return 0 on success */ int uc_dbuf_init(DBuf *buf,size_t initlen); /** Get length of user data in the buffer * * @param buf buffer to get length of * @return length of the user data */ size_t uc_dbuf_len(DBuf *buf); /** Allocated size of the buffer * * @param buf buffer to get allocated length of * @return allocated length of the underlying buffer */ size_t uc_dbuf_buflen(DBuf *buf); /** Get remaining space in the buffer * * @param buf buffer * @return remaining space (after buf->end) in the buffer */ size_t uc_dbuf_remaining(DBuf *buf); /** ensure the buffer can hold 'capacity' no of bytes, * * @param buf buffer * @param capacity ensure there is room for capacity bytes after buf->end * @return 0 on success */ int uc_dbuf_ensure(DBuf *buf,size_t capacity); /** Trim the buffer to hold no more space than needed. * * @param buf buffer to trum */ void uc_dbuf_trim(DBuf *buf); /** Indicate you've taken 'len' bytes out of the buffer. * Advances buf->start by len bytes * This may re-set buf->start and buf->end if e.g. all data * is taken out of the buffer. * * @param buf buffer * @param len length that was taken out of the buffer * @return 0 on success. Non-zero if len is larger than the bufer capacity */ int uc_dbuf_take(DBuf *buf,size_t len); /** Indicate you've added 'len' bytes to the buffer * Advances buf->end by len bytes * User must always make sure (e.g. by using uc_dbuf_ensure) * that the buffer has the capacity to add @len bytes * * @param buf buffer * @param len length that was added to the buffer. */ void uc_dbuf_added(DBuf *buf,size_t len); #ifdef __cplusplus } #endif #endif