]> granicus.if.org Git - postgis/commitdiff
Improve performance and cut back stringbuffer_t to the minimum.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 23 Feb 2010 21:29:57 +0000 (21:29 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 23 Feb 2010 21:29:57 +0000 (21:29 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@5324 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_wkt.c
liblwgeom/stringbuffer.c
liblwgeom/stringbuffer.h

index da6024ff9583e37b15fc51c26870c8fe212d179a..8f6617e8e1f5de360eeb22d84f6edb2de5242695 100644 (file)
@@ -84,7 +84,7 @@ static char* cu_wkt(char *wkt, uchar variant)
 
 void test_wkt_point(void)
 {
-       CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(0 0 0 0)",WKT_ISO), "POINTZM(0 0 0 0)");
+       CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(0.1111 0.1111 0.1111 0)",WKT_ISO), "POINTZM(0.1111 0.1111 0.1111 0)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(0 0 0 0)",WKT_EXTENDED), "POINT(0 0 0 0)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(0 0 0 0)",WKT_SFSQL), "POINT(0 0)");
 
@@ -95,10 +95,12 @@ void test_wkt_point(void)
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100 100)",WKT_ISO), "POINT(100 100)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100 100)",WKT_EXTENDED), "POINT(100 100)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100 100)",WKT_SFSQL), "POINT(100 100)");
+//     printf("%s\n",cu_wkt("POINT(100 100)",WKT_SFSQL));
 
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100.1 100 12 12)",WKT_ISO), "POINTZM(100.1 100 12 12)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100.1 100 12 12)",WKT_EXTENDED), "POINT(100.1 100 12 12)");
        CU_ASSERT_STRING_EQUAL(cu_wkt("POINT(100.1 100 12 12)",WKT_SFSQL), "POINT(100.1 100)");
+
 }
 
 void test_wkt_linestring(void) 
@@ -150,13 +152,13 @@ void test_wkt_multipolygon(void)
 
 void test_wkt_collection(void) 
 {
+       //printf("%s\n",cu_wkt("GEOMETRYCOLLECTION(MULTIPOLYGON(((100 100 2, 100 200 2, 200 200 2, 200 100 2, 100 100 2))),MULTIPOINT(.5 .5 .5,1 1 1),CURVEPOLYGON((.8 .8 .8,.8 .8 .8,.8 .8 .8)))",WKT_ISO));
        CU_ASSERT_STRING_EQUAL(
        cu_wkt("GEOMETRYCOLLECTION(POLYGON((100 100 2, 100 200 2, 200 200 2, 200 100 2, 100 100 2)),POINT(.5 .5 .5),CIRCULARSTRING(.8 .8 .8,.8 .8 .8,.8 .8 .8))",WKT_ISO), 
            "GEOMETRYCOLLECTIONZ(POLYGONZ((100 100 2,100 200 2,200 200 2,200 100 2,100 100 2)),POINTZ(0.5 0.5 0.5),CIRCULARSTRINGZ(0.8 0.8 0.8,0.8 0.8 0.8,0.8 0.8 0.8))");
        CU_ASSERT_STRING_EQUAL(
        cu_wkt("GEOMETRYCOLLECTION(MULTIPOLYGON(((100 100 2, 100 200 2, 200 200 2, 200 100 2, 100 100 2))),MULTIPOINT(.5 .5 .5,1 1 1),CURVEPOLYGON((.8 .8 .8,.8 .8 .8,.8 .8 .8)))",WKT_ISO), 
            "GEOMETRYCOLLECTIONZ(MULTIPOLYGONZ(((100 100 2,100 200 2,200 200 2,200 100 2,100 100 2))),MULTIPOINTZ(0.5 0.5 0.5,1 1 1),CURVEPOLYGONZ((0.8 0.8 0.8,0.8 0.8 0.8,0.8 0.8 0.8)))");
-       //printf("%s\n",cu_wkt("GEOMETRYCOLLECTION(MULTIPOLYGON(((100 100 2, 100 200 2, 200 200 2, 200 100 2, 100 100 2))),MULTIPOINT(.5 .5 .5,1 1 1),CURVEPOLYGON((.8 .8 .8,.8 .8 .8,.8 .8 .8)))",WKT_ISO));
 }
 
 void test_wkt_circularstring(void) 
index f0cd854782e941a5067bd48ef480aa6855657ecf..51cf790e084cf81ce74cd3e608b7c60f67ebc309 100644 (file)
-/*
+/**********************************************************************
+ * $Id$
  *
+ * PostGIS - Spatial Types for PostgreSQL
  * Copyright 2002 Thamer Alharbash
+ * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
  *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. The names of the authors may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Sringbuffer object:
- *
- * (*) allows printfing into a string,
- * (*) fast string manipulation by keeping track of string length.
- * (*) alignment of string against columns.
- *
- * Internally stringbuffer does not count the terminating null as the length.
- * Therefore the raw string routines will always assume +1 when given length.
- */
-
-#include "liblwgeom.h"
-
-/* * * * * * * * * * * * *
- * raw string routines.  *
- * * * * * * * * * * * * */
-
-/* just malloc out a string. */
-static char *allocate_string(int len)
-{
-       char *s;
-       s = lwalloc(sizeof(char) * len + 1); /* add for null termination. */
-       s[len] = 0;
-       return s;
-}
-
-/* extend a string. */
-static char *extend_string(char *str, int cur_len, int ex_len)
-{
-
-       str = lwrealloc(str, (cur_len * sizeof(char)) + (ex_len * sizeof(char)) + (1 * sizeof(char)));
-       str[cur_len] = 0; /* make sure it's null terminated. */
-
-       return str;
-}
-
-/* get a substring. */
-static char *substring(char *begin, int len)
-{
-       char *new_string;
-
-       new_string = allocate_string(len);
-       memcpy(new_string, begin, len);
-       new_string[len] = 0;
-
-       return new_string;
-}
-
-/* FIXME: get rid of pesky strlen() */
-/* used in aligning -- we try to get words up to end. */
-static char *get_string_align(char *s, int end, int *len)
-{
-       char *cur_ptr;
-
-       if (s == 0 || *s == 0) /* end of string or no string. */
-               return NULL;
-
-       /* if strlen is smaller than len go ahead and just return it. */
-       if (strlen(s) < end)
-       {
-               *len = strlen(s);
-               return strdup(s);
-       }
-
-       /* otherwise we need to hop to len */
-       cur_ptr = &s[end - 1];
-
-       /* now check to see if we have a whitespace behind cur_ptr
-        * if we do return at that point. */
-
-       for (; cur_ptr != s; cur_ptr--)
-       {
-               if (*cur_ptr == ' ' || *cur_ptr == '\t')
-               {
-                       /* copy here and return. */
-                       *len = (cur_ptr - s) + 1;
-                       return (substring(s, *len));
-               }
-       }
-
-       /* keep walking till we find whitspace or end. */
-       for (cur_ptr = &s[end - 1]; *cur_ptr != 0 && *cur_ptr != ' ' && *cur_ptr != '\t'; cur_ptr++);
-
-       *len = (cur_ptr - s) + 1;
-       return (substring(s, *len));
-}
-
-/* zap newlines by placing spaces in their place.
- * we use this before aligning. */
-static void stringbuffer_zap_newline(stringbuffer_t *sb)
-{
+ **********************************************************************/
 
-       stringbuffer_replace_c(sb, '\n', ' ');
-       stringbuffer_replace_c(sb, '\r', ' ');
-}
 
-/* * * * * * * * * * * * * * *
- * stringbuffer routines.    *
- * * * * * * * * * * * * * * */
+#include "liblwgeom.h"
 
-/* create a new stringbuffer */
 stringbuffer_t *stringbuffer_create(void)
 {
        stringbuffer_t *sb;
 
        sb = lwalloc(sizeof(stringbuffer_t));
-       sb->len = 0;
-       sb->capacity = 0;
-       sb->buf = allocate_string(0);
-
+       sb->length = 0;
+       sb->capacity = STRINGBUFFER_STARTSIZE;
+       sb->str = lwalloc(sizeof(char) * STRINGBUFFER_STARTSIZE);
+       memset(sb->str,0,STRINGBUFFER_STARTSIZE);
+       memset(sb->buffer,0,STRINGBUFFER_WORKSIZE);
        return sb;
 }
 
-/* destroy the stringbuffer */
 void stringbuffer_destroy(stringbuffer_t *sb)
 {
-       lwfree(sb->buf);
+       lwfree(sb->str);
        lwfree(sb);
 }
 
-/* clear a string. */
 void stringbuffer_clear(stringbuffer_t *sb)
 {
-       sb->len = 0;
-       sb->buf[0] = 0;
-}
-
-/* append character to stringbuffer */
-void stringbuffer_append_c(stringbuffer_t *sb, char c)
-{
-       if (sb->capacity <= (sb->len))
-       {
-               sb->buf = extend_string(sb->buf, sb->len, STRINGBUFFER_CHUNKSIZE);
-               sb->capacity += STRINGBUFFER_CHUNKSIZE;
-       }
-
-       sb->buf[sb->len] = c;
-       sb->len++;
-       sb->buf[sb->len] = 0;
-}
-
-/* append string to stringbuffer */
-void stringbuffer_append(stringbuffer_t *sb, const char *s)
-{
-       int len = strlen(s);
-
-       /* increase capacity if needed. */
-       if (sb->capacity <= (len + sb->len))
-       {
-
-               /* if we're bigger than the chunksize then allocate len. */
-               if (len > STRINGBUFFER_CHUNKSIZE)
-               {
-
-                       sb->buf = extend_string(sb->buf, sb->capacity, len);
-                       sb->capacity += len;
-
-               }
-               else
-               {
-
-                       /* otherwise allocate chunksize. */
-                       sb->buf = extend_string(sb->buf, sb->capacity, STRINGBUFFER_CHUNKSIZE);
-                       sb->capacity += STRINGBUFFER_CHUNKSIZE;
-               }
-       }
-
-       /* copy new string into place: keep in mind we know all
-        * lengths so strcat() would be less effecient. */
-
-       memcpy(&sb->buf[sb->len], s, len);
-
-       sb->len += len;
-       sb->buf[sb->len] = 0;
-
-       return;
+       sb->str[0] = '\0';
+       sb->length = 0;
+       memset(sb->buffer,0,STRINGBUFFER_WORKSIZE);
 }
 
-/* remove whitespace (including tabs) */
-stringbuffer_t *stringbuffer_trim_whitespace(stringbuffer_t *sb)
+static void stringbuffer_makeroom(stringbuffer_t *sb, size_t length_to_add)
 {
-       char *newbuf;
-       int new_len;
-       int i, j;
-
-       if (sb->len == 0) /* empty string. */
-               return sb;
-
-       /* find beginning of string after tabs and whitespaces. */
-       for (i = 0; i < sb->len && (sb->buf[i] == ' ' || sb->buf[i] == '\t'); i++);
-
-       if (sb->buf[i] != '\0')
-       {
-
-               /* we do have whitespace in the beginning so find the end. */
-               for (j = (sb->len -1); (sb->buf[j] == ' ' || sb->buf[j] == '\t'); j--);
-
-               /* increment j since it's on the non whitespace character. */
-               j++;
-
-               /* create a new string. */
-               new_len = j - i;
-               newbuf = allocate_string(new_len);
-
-               /* copy in. */
-               memcpy(newbuf, &sb->buf[i], (j - i) * sizeof(char));
-               newbuf[new_len] = 0;
-
-               /* free up old. */
-               lwfree(sb->buf);
-
-               /* set new. */
-               sb->buf = newbuf;
-               sb->len = new_len;
-               sb->capacity = new_len;
-
-
-       }
-       else
-       {
-
-               /* zap beginning of string. since its all whitespace. */
-               sb->buf[0] = 0;
-               sb->len = 0;
-       }
-
-       return sb;
-}
+       size_t reqd_capacity = sb->capacity; 
 
-/* get the last occurance of a specific character. useful for slicing. */
-char *stringbuffer_get_last_occurance(stringbuffer_t *sb, char c)
-{
-       char *ptr, *ptrend = NULL;
-       int i;
+       while(reqd_capacity < (length_to_add + sb->length))
+               reqd_capacity *= 2;
 
-       ptr = sb->buf;
-       for (i = 0; i < sb->len; i++)
+       if( reqd_capacity > sb->capacity )
        {
-
-               if (ptr[i] == c)
-                       ptrend = &ptr[i];
+               sb->str = lwrealloc(sb->str, sizeof(char) * reqd_capacity);
+               sb->capacity = reqd_capacity;
        }
-
-       return ptrend;
 }
 
-/* remove the last newline character. */
-void stringbuffer_trim_newline(stringbuffer_t *sb)
+void stringbuffer_append(stringbuffer_t *sb, const char *s)
 {
-       char *ptr;
+       int slen = strlen(s); /* Length of string to append */
+       int slen0 = slen + 1; /* Length including null terminator */
 
-       ptr = stringbuffer_get_last_occurance(sb, '\n');
-       if (ptr != NULL)
-               *ptr = 0;
+       stringbuffer_makeroom(sb, slen0);
 
+       memcpy(sb->str + sb->length, s, slen0);
 
-       ptr = stringbuffer_get_last_occurance(sb, '\r');
-       if (ptr != NULL)
-               *ptr = 0;
+       sb->length += slen;
+       sb->str[sb->length] = '\0';
 
-
-       sb->len = strlen(sb->buf);
-
-       return;
 }
 
-/* return the C string from the buffer. */
 const char *stringbuffer_getstring(stringbuffer_t *sb)
 {
-       return sb->buf;
-}
-
-/* set a string into a stringbuffer */
-void stringbuffer_set(stringbuffer_t *dest, const char *s)
-{
-       stringbuffer_clear(dest); /* zap */
-       stringbuffer_append(dest, s);
-}
-
-/* copy a stringbuffer into another stringbuffer */
-void stringbuffer_copy(stringbuffer_t *dest, stringbuffer_t *src)
-{
-       stringbuffer_set(dest, stringbuffer_getstring(src));
-}
-
-/* replace in stringbuffer occurances of c with replace */
-void stringbuffer_replace_c(stringbuffer_t *sb, char c, char replace)
-{
-       int i;
-
-       for (i = 0; i < sb->len; i++)
-       {
-               if (sb->buf[i] == c)
-                       sb->buf[i] = replace;
-       }
-
-       return;
+       return sb->str;
 }
 
-/* replace in stringbuffer occurances of c with replace */
-void stringbuffer_replace(stringbuffer_t *sb, const char *string, const char *replace)
+void stringbuffer_set(stringbuffer_t *sb, const char *s)
 {
-       char *ptr;
-       int i;
-       int str_len = strlen(string);
-       stringbuffer_t *sb_replace;
-
-       if (string[0] == 0)
-               return; /* nothing to replace. */
-
-       sb_replace = stringbuffer_create();
-       ptr = sb->buf;
-
-       for (i = 0; i < sb->len; i++)
-       {
-
-               if ((sb->len - i) < str_len)
-               {
-
-                       /* copy in. */
-                       stringbuffer_copy(sb, sb_replace);
-
-                       /* append what's left. */
-                       stringbuffer_append(sb, &ptr[i]);
-
-                       /* free up. */
-                       stringbuffer_destroy(sb_replace);
-
-                       /* we're done. */
-                       return;
-               }
-
-               if (ptr[i] == string[0])
-               {
-
-                       /* we know that we have at least enough to complete string. */
-                       if (!memcmp(&ptr[i], string, str_len))
-                       {
-
-                               /* we have a match, replace. */
-                               stringbuffer_append(sb_replace, replace);
-                               i += (str_len - 1);
-                               continue;
-                       }
-               }
-
-               stringbuffer_append_c(sb_replace, ptr[i]);
-       }
-
-       /* we're done: we should only get here if the last string to
-          be replaced ended the string itself. */
-
-       /* copy in. */
-       stringbuffer_copy(sb, sb_replace);
-
-       /* free up. */
-       stringbuffer_destroy(sb_replace);
-
-       /* we're done. */
-       return;
-
+       stringbuffer_clear(sb); 
+       stringbuffer_append(sb, s);
 }
 
-/* align a stringbuffer on begin and end columns. */
-void stringbuffer_align(stringbuffer_t *sb, int begin, int end)
+void stringbuffer_copy(stringbuffer_t *sb, stringbuffer_t *src)
 {
-       char *ptr, *word_string;
-       stringbuffer_t *aligned_string;
-       int len, i;
-
-       stringbuffer_zap_newline(sb);
-
-       aligned_string = stringbuffer_create();
-       ptr = sb->buf;
-
-       while (1)
-       {
-
-               word_string = get_string_align(ptr, end, &len);
-
-               if (word_string == NULL)
-                       break;
-
-               ptr += len;
-
-               for (i = 0; i < begin; i++)
-                       stringbuffer_append(aligned_string, " ");
-
-               stringbuffer_append(aligned_string, word_string);
-               stringbuffer_append(aligned_string, "\n");
-               lwfree(word_string);
-
-       }
-
-       stringbuffer_copy(sb, aligned_string);
-       stringbuffer_destroy(aligned_string);
-
-       return;
+       stringbuffer_set(sb, stringbuffer_getstring(src));
 }
 
-/* stringbuffer_*printf* these all use snprintf/snvprintf internally */
-
-/* append vprintf with alignment. */
-void stringbuffer_avprintf_align(stringbuffer_t *sb, int start, int end, const char *fmt, va_list ap)
+static void stringbuffer_avprintf(stringbuffer_t *sb, const char *fmt, va_list ap)
 {
-       stringbuffer_t *tmp_sb;
-       char *str;
-       int total, len;
+       int len = 0; /* Length of the output */
+       int len0 = 0; /* Length of the output with null terminator */
+       va_list ap2;
+       va_list ap3;
+       
+       va_copy(ap2, ap);
+       va_copy(ap3, ap);
+       
+       /* Print to our static buffer */
+       len = vsnprintf(sb->buffer, STRINGBUFFER_WORKSIZE, fmt, ap);
+       len0 = len + 1;
+       
+       stringbuffer_makeroom(sb, len0);
 
-       /* our first malloc is bogus. */
-       len = 1;
-       str = lwalloc(sizeof(char) * len);
-       total = vsnprintf(str, len, fmt, ap);
-
-       /* total is the real length needed. */
-       lwfree(str);
-       len = total + 1;
-       str = lwalloc(sizeof(char) * len);
-       vsnprintf(str, len, fmt, ap);
-
-       /* now align if we want to align. */
-       if (start != 0 && end != 0)
+       /* This output doesn't fit in our static buffer, allocate a dynamic one */
+       if( len0 > STRINGBUFFER_WORKSIZE )
        {
-
-               tmp_sb = stringbuffer_create();
-
-               stringbuffer_append(tmp_sb, str);
-               stringbuffer_align(tmp_sb, start, end);
-               stringbuffer_append(sb, stringbuffer_getstring(tmp_sb));
-
-               stringbuffer_destroy(tmp_sb);
-
+               char *tmpstr = lwalloc(sizeof(char) * len0);
+               vsnprintf(tmpstr, len0, fmt, ap2);
+               memcpy(sb->str + sb->length, tmpstr, len0);
+               lwfree(tmpstr);
        }
+       /* Copy the result out of the static buffer */
        else
        {
-               stringbuffer_append(sb, str);
+               memcpy(sb->str + sb->length, sb->buffer, len0);
        }
-
-       lwfree(str);
-
-       return;
+       sb->length += len;
+       sb->str[sb->length] = '\0';
 }
 
-/* append printf. */
 void stringbuffer_aprintf(stringbuffer_t *sb, const char *fmt, ...)
 {
        va_list ap;
-
        va_start(ap, fmt);
-
        stringbuffer_avprintf(sb, fmt, ap);
-
-       va_end(ap);
-}
-
-/* append printf with alignment. */
-void stringbuffer_aprintf_align(stringbuffer_t *sb, int start, int end, const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-
-       stringbuffer_avprintf_align(sb, start, end, fmt, ap);
-
        va_end(ap);
 }
 
-/* append vprintf. */
-void stringbuffer_avprintf(stringbuffer_t *sb, const char *fmt, va_list ap)
-{
-       stringbuffer_avprintf_align(sb, 0, 0, fmt, ap);
-}
-
-/* newline marking and sweeping. this wrecks the string inside
- * the stringbuffer. */
-
-/* mark newlines to walk through.
- * our sentinel is the null terminator.
- * two null terminations marks the end of the string.
- * we're guaranteed it is a unique sentinel since
- * we never accept null terminators from outside sources
- * and never build our own strings (obviously!) with
- * null terminators inside of them.
- */
-int stringbuffer_marknewlines(stringbuffer_t *sb)
-{
-       char *c;
-       int newline_count = 0;
-
-       /* first append one null termination to the end
-        * to act as a proper terminator. */
-       stringbuffer_append_c(sb, 0);
-
-
-       c = sb->buf;
-       while (1)
-       {
-
-               if (*c == '\n')
-               {
-                       newline_count++;
-                       *c = 0;
-               }
-
-               c++;
-               if (*c == 0)
-                       break;
-       }
-
-       return newline_count; /* return our line count. */
-}
-
-/* called _after_ newlines are marked. */
-const char *stringbuffer_getnextline(stringbuffer_t *sb, const char *cptr)
-{
-       const char *ptr;
-
-       if (cptr == NULL)
-       {
-
-               /* get first line. */
-               cptr = sb->buf;
-
-       }
-       else
-       {
-
-               for (ptr = cptr; *ptr != 0; ptr++);
-               if (*ptr == 0 && *(ptr + 1) == 0)
-               {
-                       return NULL;
-
-               }
-               else
-               {
-                       cptr = ptr + 1;
-
-               }
-       }
-
-       return cptr;
-}
-
-int stringbuffer_getlen(stringbuffer_t *sb)
-{
-       return sb->len;
-}
-
-void stringbuffer_vasbappend(stringbuffer_t *sb, char *fmt, ... )
+void stringbuffer_vasbappend(stringbuffer_t *sb, const char *fmt, ... )
 {
        va_list ap;
-       char *msg;
-
        va_start(ap, fmt);
-
-       if (!lw_vasprintf (&msg, fmt, ap))
-       {
-               va_end (ap);
-               return;
-       }
-
-       /* Append to the stringbuffer */
-       stringbuffer_append(sb, msg);
-       lwfree(msg);
-
+       stringbuffer_avprintf(sb, fmt, ap);
        va_end(ap);
 }
\ No newline at end of file
index 20959e00561447a227ff6a526cd5a1258c88ea5f..84bbf1205afe51d3dcb3907abb856a7c4f4ff353 100644 (file)
@@ -1,69 +1,40 @@
-/*
+/**********************************************************************
+ * $Id$
  *
+ * PostGIS - Spatial Types for PostgreSQL
  * Copyright 2002 Thamer Alharbash
+ * Copyright 2009 Paul Ramsey <pramsey@cleverelephant.ca>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
  *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. The names of the authors may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Sringbuffer object:
- *
- * (*) allows printfing into a string,
- * (*) fast string manipulation by keeping track of string length.
- * (*) alignment of string against columns.
- *
- * Internally stringbuffer does not count the terminating null as the length.
- * Therefore the raw string routines will always assume +1 when given length.
- */
+ **********************************************************************/
+
 
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <stdio.h>
 
-#define STRINGBUFFER_CHUNKSIZE 16
+#define STRINGBUFFER_STARTSIZE 2
+#define STRINGBUFFER_WORKSIZE 2
 
 typedef struct
 {
-       size_t len;
+       size_t length;
        size_t capacity;
-       char *buf;
+       char buffer[STRINGBUFFER_WORKSIZE];
+       char *str;
 }
 stringbuffer_t;
 
 extern stringbuffer_t *stringbuffer_create(void);
 extern void stringbuffer_destroy(stringbuffer_t *sb);
 extern void stringbuffer_clear(stringbuffer_t *sb);
-extern void stringbuffer_append_c(stringbuffer_t *sb, char c);
+void stringbuffer_set(stringbuffer_t *sb, const char *s);
+void stringbuffer_copy(stringbuffer_t *sb, stringbuffer_t *src);
 extern void stringbuffer_append(stringbuffer_t *sb, const char *s);
-extern stringbuffer_t *stringbuffer_trim_whitespace(stringbuffer_t *sb);
-extern char *stringbuffer_get_last_occurance(stringbuffer_t *sb, char c);
-extern void stringbuffer_trim_newline(stringbuffer_t *sb);
-extern const char *stringbuffer_getstring(stringbuffer_t *sb);
-extern void stringbuffer_set(stringbuffer_t *dest, const char *s);
-extern void stringbuffer_copy(stringbuffer_t *dest, stringbuffer_t *src);
-extern void stringbuffer_replace_c(stringbuffer_t *sb, char c, char replace);
-extern void stringbuffer_replace(stringbuffer_t *sb, const char *string, const char *replace);
-extern void stringbuffer_align(stringbuffer_t *sb, int begin, int end);
-extern void stringbuffer_avprintf_align(stringbuffer_t *sb, int start, int end, const char *fmt, va_list ap);
 extern void stringbuffer_aprintf(stringbuffer_t *sb, const char *fmt, ...);
-extern void stringbuffer_aprintf_align(stringbuffer_t *sb, int start, int end, const char *fmt, ...);
-extern void stringbuffer_avprintf(stringbuffer_t *sb, const char *fmt, va_list ap);
-extern int stringbuffer_marknewlines(stringbuffer_t *sb);
-extern const char *stringbuffer_getnextline(stringbuffer_t *sb, const char *cptr);
-extern int stringbuffer_getlen(stringbuffer_t *sb);
-extern void stringbuffer_vasbappend(stringbuffer_t *sb, char *fmt, ... );
+extern const char *stringbuffer_getstring(stringbuffer_t *sb);
+extern void stringbuffer_vasbappend(stringbuffer_t *sb, const char *fmt, ... );
+