/* cStringBuffer: a file-like string buffer. Copyright (C) 2004 Mooneer Salem This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Include necessary includes. */ #include #include #include #include #include #include #include "config.h" #ifdef HAVE_PTHREAD_H #include #endif #include "csb_private.h" #include "csb.h" /* csb_puts(): Print string to file buffer. Parameters: buf: The buffer to print to. string: The string to print. Returns: true on success, false otherwise. */ int csb_puts(csb_buf *buf, /*@unique@*/ const char *str) /*@modifies buf->fileptr, buf->string, buf->stringsize, buf->length, buf->ungetc_buffer@*/ { const size_t str_size = strlen(str); /* Do some sanity checks to make sure we're getting a valid buffer. */ assert(buf != NULL && buf->string != NULL); /* Dynamically make the buffer bigger until we're sure the string fits. */ CSB_RESIZE_TO_FIT(buf, str); /* "Print" the string to the buffer at its current position. When done, reset the size of the string and seek to the end of the combined string. */ strncpy (buf->fileptr, str, str_size); buf->fileptr += str_size; if (buf->fileptr >= buf->string + buf->stringsize) { buf->stringsize = (size_t)((unsigned long)(buf->fileptr) - (unsigned long)(buf->string)); *buf->fileptr = '\0'; } /* Return TRUE; it was successful. */ return (TRUE); } /* csb_putc(): Print a character to file buffer. Parameters: buf: The buffer to print to. ch: The character to print. Returns: true on success, false otherwise. */ int csb_putc(csb_buf *buf, char ch) /*@modifies buf->fileptr, buf->string, buf->stringsize, buf->length, buf->ungetc_buffer, buf->ungetc_length@*/ { /* Declare variables. */ char str[2]; /* Initialize the string to be the character passed in followed by '\0'. */ str[0] = ch; str[1] = '\0'; /* Send the string to csb_puts() since there's common code in there. */ return (csb_puts(buf, str)); } /* csb_write(): write binary data to buffer. Parameters: buf: Buffer to operate on. data: Data to write. length: The size of the data to write. Returns: true on success, false otherwise. */ int csb_write(csb_buf *buf, /*@unique@*/ const void *data, size_t length) /*@modifies buf->fileptr, buf->string, buf->stringsize, buf->length, buf->ungetc_buffer@*/ { /* Perform sanity checks to make sure we have a valid buffer. */ assert(buf != NULL && buf->string != NULL); /* Grow the buffer to the needed size. */ /*while (buf->stringsize + length > buf->length) { csb_addchunk(buf); }*/ if (buf->stringsize + length > buf->length) { (void)csb_prealloc(buf, buf->stringsize + length); } /* Copy the data to the position of the file pointer. */ memcpy(buf->fileptr, data, length); buf->fileptr += length; /* Adjust the size of the string and move the file pointer to the end of the string. */ if (buf->stringsize < (size_t)((unsigned long)(buf->fileptr) - (unsigned long)(buf->string))) { buf->stringsize = (size_t)((unsigned long)(buf->fileptr) - (unsigned long)(buf->string)); *buf->fileptr = '\0'; } /* Return true, it was a success. */ return(TRUE); } /* csb_printf(): write formatted output to the buffer. Parameters: buf: Buffer to print to. fmt: The format of the output (see the man page for printf) ...: each parameter specified in fmt. Returns: true on success, false otherwise. */ int csb_printf(csb_buf *buf, const char *fmt, ...) /*@modifies buf->fileptr, buf->string, buf->stringsize, buf->length, buf->ungetc_buffer@*/ { /* Declare variables. */ va_list ap; int retval; /* Perform sanity checks to make sure we have a valid buffer. */ assert(buf != NULL && buf->string != NULL); /* Pass the parameters to the system prinf. */ va_start(ap, fmt); retval = vsnprintf (buf->fileptr, buf->length - buf->stringsize - 1, fmt, ap); if (retval >= 0) { if (retval > (int)(buf->length - buf->stringsize - 1)) { /* Grow the buffer to the needed size. */ /*while (buf->stringsize + retval + 1 > buf->length) csb_addchunk (buf);*/ if (buf->stringsize + retval + 1 > buf->length) { (void)csb_prealloc(buf, buf->stringsize + retval + 1); } retval = vsnprintf (buf->fileptr, buf->length - buf->stringsize - 1, fmt, ap); } buf->fileptr += retval; /* Adjust the size of the string and move the file pointer to the end of the string. */ buf->stringsize = (size_t)((unsigned long)(buf->fileptr) - (unsigned long)(buf->string)); } va_end(ap); /* Return the return value of csb_puts(). */ return (retval); }