/* * Copyright (C) 2007 Tildeslash Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * There are special exceptions to the terms and conditions of the GPL * as it is applied to this software. View the full text of the exception * in the file EXCEPTIONS accompanying this software distribution. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Config.h" #include #include "Util.h" #include "StringBuffer.h" /** * Implementation of the StringBuffer interface. * * @version \$Id: StringBuffer.c,v 1.16 2007/01/02 10:29:52 hauk Exp $ * @file */ /* ----------------------------------------------------------- Definitions */ #define BUFFER_SIZE 256 #define T StringBuffer_T struct T { int used; int length; uchar_T *buffer; }; /* ------------------------------------------------------------ Prototypes */ static void doAppend(T S, const char *s, va_list ap); /* ----------------------------------------------------- Protected methods */ #ifdef PACKAGE_PROTECTED #pragma GCC visibility push(hidden) #endif T StringBuffer_new(const char *s) { T S; NEW(S); S->used= 0; S->length= BUFFER_SIZE; S->buffer= ALLOC(BUFFER_SIZE); return StringBuffer_append(S, s); } void StringBuffer_free(T *S) { assert(S && *S); FREE((*S)->buffer); FREE(*S); } T StringBuffer_append(T S, const char *s, ...) { va_list ap; assert(S); if(s && *s) { va_start(ap, s); doAppend(S, s, ap); va_end(ap); } return S; } T StringBuffer_vappend(T S, const char *s, va_list ap) { assert(S); if(s && *s) doAppend(S, s, ap); return S; } int StringBuffer_length(T S) { assert(S); return S->used; } void StringBuffer_clear(T S) { assert(S); S->used= 0; *S->buffer= 0; } const char *StringBuffer_toString(T S) { assert(S); return S->buffer; } #ifdef PACKAGE_PROTECTED #pragma GCC visibility pop #endif /* ------------------------------------------------------- Private methods */ static void doAppend(T S, const char *s, va_list ap) { while(TRUE) { int n= vsnprintf(&S->buffer[S->used], S->length-S->used, s, ap); if(n > -1 && (S->used + n) < S->length) { S->used+= n; break; } if(n > -1) S->length+= BUFFER_SIZE + n; else S->length*= 2; RESIZE(S->buffer, S->length); } }