Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2008 Crossfire Development Team 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 The authors can be reached via e-mail at crossfire-devel@real-time.com 00021 */ 00022 00023 #include <stdarg.h> 00024 #include <stdlib.h> 00025 #include <string.h> 00026 00027 #include "global.h" 00028 #include "libproto.h" 00029 #include "stringbuffer.h" 00030 00031 00032 struct StringBuffer { 00037 char *buf; 00038 00044 size_t pos; 00045 00049 size_t size; 00050 }; 00051 00052 00061 static void stringbuffer_ensure(StringBuffer *sb, size_t len); 00062 00063 00064 StringBuffer *stringbuffer_new(void) { 00065 StringBuffer *sb; 00066 00067 sb = malloc(sizeof(*sb)); 00068 if (sb == NULL) { 00069 fatal(OUT_OF_MEMORY); 00070 } 00071 00072 sb->size = 256; 00073 sb->buf = malloc(sb->size); 00074 sb->pos = 0; 00075 return sb; 00076 } 00077 00078 char *stringbuffer_finish(StringBuffer *sb) { 00079 char *result; 00080 00081 sb->buf[sb->pos] = '\0'; 00082 result = sb->buf; 00083 free(sb); 00084 return result; 00085 } 00086 00087 sstring stringbuffer_finish_shared(StringBuffer *sb) { 00088 char *str; 00089 sstring result; 00090 00091 str = stringbuffer_finish(sb); 00092 result = add_string(str); 00093 free(str); 00094 return result; 00095 } 00096 00097 void stringbuffer_append_string(StringBuffer *sb, const char *str) { 00098 size_t len; 00099 00100 len = strlen(str); 00101 stringbuffer_ensure(sb, len+1); 00102 memcpy(sb->buf+sb->pos, str, len); 00103 sb->pos += len; 00104 } 00105 00106 void stringbuffer_append_printf(StringBuffer *sb, const char *format, ...) { 00107 size_t size; 00108 00109 size = 100; /* arbitrary guess */ 00110 for (;;) { 00111 int n; 00112 va_list arg; 00113 00114 stringbuffer_ensure(sb, size); 00115 00116 va_start(arg, format); 00117 n = vsnprintf(sb->buf+sb->pos, size, format, arg); 00118 va_end(arg); 00119 00120 if (n > -1 && (size_t)n < size) { 00121 sb->pos += (size_t)n; 00122 break; 00123 } 00124 00125 if (n > -1) { 00126 size = n+1; /* precisely what is needed */ 00127 } else { 00128 size *= 2; /* twice the old size */ 00129 } 00130 } 00131 } 00132 00133 void stringbuffer_append_stringbuffer(StringBuffer *sb, const StringBuffer *sb2) { 00134 stringbuffer_ensure(sb, sb2->pos+1); 00135 memcpy(sb->buf+sb->pos, sb2->buf, sb2->pos); 00136 sb->pos += sb2->pos; 00137 } 00138 00139 static void stringbuffer_ensure(StringBuffer *sb, size_t len) { 00140 char *tmp; 00141 size_t new_size; 00142 00143 if (sb->pos+len <= sb->size) { 00144 return; 00145 } 00146 00147 new_size = sb->pos+len+256; 00148 tmp = realloc(sb->buf, new_size); 00149 if (tmp == NULL) { 00150 fatal(OUT_OF_MEMORY); 00151 } 00152 sb->buf = tmp; 00153 sb->size = new_size; 00154 }