diff interps/cfunge/cfunge-src/lib/stringbuffer/stringbuffer.c @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interps/cfunge/cfunge-src/lib/stringbuffer/stringbuffer.c	Sun Dec 09 19:30:08 2012 +0000
@@ -0,0 +1,185 @@
+/*
+    This code was taken (and slightly modified to compile in cfunge) from:
+      CrossFire, A Multiplayer game for X-windows
+
+    Copyright (C) 2008 Crossfire Development Team
+
+    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; either version 2 of the License, or
+    (at your option) any later version.
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    The authors can be reached via e-mail at crossfire-devel@real-time.com
+*/
+
+/*
+ * Modifications for cfunge:
+ * - Drop some crossfire specific includes and functions that depended on other
+ *   parts of crossfire.
+ * - Adding stringbuffer_destroy
+ * - Adding GCC attributes.
+ *
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../src/global.h"
+#include <stdbool.h>
+#include "stringbuffer.h"
+
+
+struct StringBuffer {
+    /**
+     * The string buffer. The first {@link #pos} bytes contain the collected
+     * string. It's size is at least {@link #size} bytes.
+     */
+    char *buf;
+
+    /**
+     * The current length of {@link #buf}. The invariant <code>pos <
+     * size</code> always holds; this means there is always enough room to
+     * attach a trailing \0 character.
+     */
+    size_t pos;
+
+    /**
+     * The allocation size of {@link #buf}.
+     */
+    size_t size;
+};
+
+
+/**
+ * Make sure that at least <code>len</code> bytes are available in the passed
+ * string buffer.
+ *
+ * @param sb The string buffer to modify.
+ *
+ * @param len The number of bytes to allocate.
+ */
+FUNGE_ATTR_FAST
+static bool stringbuffer_ensure(StringBuffer *sb, size_t len);
+
+FUNGE_ATTR_FAST
+StringBuffer *stringbuffer_new(void)
+{
+    StringBuffer *sb;
+
+    sb = malloc(sizeof(*sb));
+    if (sb == NULL) {
+        return NULL;
+    }
+
+    sb->size = 256;
+    sb->buf = malloc(sb->size);
+    sb->pos = 0;
+    return sb;
+}
+
+FUNGE_ATTR_FAST
+void stringbuffer_destroy(StringBuffer *sb)
+{
+    free(sb->buf);
+    free(sb);
+}
+
+FUNGE_ATTR_FAST
+char *stringbuffer_finish(StringBuffer * restrict sb, size_t * restrict length)
+{
+    char *result;
+
+    sb->buf[sb->pos] = '\0';
+    if (length)
+        *length = sb->pos;
+    result = sb->buf;
+    free(sb);
+    return result;
+}
+
+FUNGE_ATTR_FAST
+void stringbuffer_append_char(StringBuffer *sb, const char c)
+{
+    stringbuffer_ensure(sb, 2);
+    sb->buf[sb->pos] = c;
+    sb->pos += 1;
+}
+
+FUNGE_ATTR_FAST
+void stringbuffer_append_string(StringBuffer *sb, const char *str)
+{
+    size_t len;
+
+    len = strlen(str);
+    stringbuffer_ensure(sb, len+1);
+    memcpy(sb->buf+sb->pos, str, len);
+    sb->pos += len;
+}
+
+FUNGE_ATTR_FAST
+void stringbuffer_append_printf(StringBuffer *sb, const char *format, ...)
+{
+    size_t size;
+
+    size = 100;                 /* arbitrary guess */
+    for (;;) {
+        int n;
+        va_list arg;
+
+        stringbuffer_ensure(sb, size);
+
+        va_start(arg, format);
+        n = vsnprintf(sb->buf+sb->pos, size, format, arg);
+        va_end(arg);
+
+        if (n > -1 && (size_t)n < size) {
+            sb->pos += (size_t)n;
+            break;
+        }
+
+        if (n > -1) {
+            size = (size_t)(n+1);         /* precisely what is needed */
+        } else {
+            size *= 2;          /* twice the old size */
+        }
+    }
+}
+
+FUNGE_ATTR_FAST
+void stringbuffer_append_stringbuffer(StringBuffer * restrict sb,
+                                      const StringBuffer * restrict sb2)
+{
+    stringbuffer_ensure(sb, sb2->pos+1);
+    memcpy(sb->buf+sb->pos, sb2->buf, sb2->pos);
+    sb->pos += sb2->pos;
+}
+
+FUNGE_ATTR_FAST
+static bool stringbuffer_ensure(StringBuffer *sb, size_t len)
+{
+    char *tmp;
+    size_t new_size;
+
+    if (sb->pos+len <= sb->size) {
+        return true;
+    }
+
+    new_size = sb->pos+len+256;
+    tmp = realloc(sb->buf, new_size);
+    if (tmp == NULL) {
+        return false;
+    }
+    sb->buf = tmp;
+    sb->size = new_size;
+    return true;
+}