ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/dynbuf.C
(Generate patch)

Comparing deliantra/server/server/dynbuf.C (file contents):
Revision 1.15 by root, Mon May 28 21:28:36 2007 UTC vs.
Revision 1.35 by root, Tue Jan 3 11:25:36 2012 UTC

1/* 1/*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * 5 *
6 * Crossfire TRT is free software; you can redistribute it and/or modify it 6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * under the terms of the GNU General Public License as published by the Free 7 * the terms of the Affero GNU General Public License as published by the
8 * Software Foundation; either version 2 of the License, or (at your option) 8 * Free Software Foundation, either version 3 of the License, or (at your
9 * any later version. 9 * option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, but 11 * This program is distributed in the hope that it will be useful,
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License along 16 * You should have received a copy of the Affero GNU General Public License
17 * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51 17 * and the GNU General Public License along with this program. If not, see
18 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * <http://www.gnu.org/licenses/>.
19 * 19 *
20 * The authors can be reached via e-mail to <crossfire@schmorp.de> 20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */ 21 */
22 22
23#include "global.h" 23#include "global.h"
24 24
25#include <cstdio> 25#include <cstdio>
26 26
27dynbuf::dynbuf (int initial, int extend) 27void
28dynbuf::init (int initial)
28{ 29{
29 ext = extend; 30 cextend = extend;
30 _size = 0; 31 _size = 0;
31 32
32 first = last = (chunk *)salloc<char> (sizeof (chunk) + initial); 33 first = last = (chunk *)salloc<char> (sizeof (chunk) + initial);
33 first->alloc = sizeof (chunk) + initial; 34 first->alloc = sizeof (chunk) + initial;
34 first->next = 0; 35 first->next = 0;
35 36
36 ptr = first->data; 37 ptr = first->data;
37 end = ptr + initial; 38 end = ptr + initial;
38} 39}
39 40
40dynbuf::~dynbuf () 41// frees a full chain and sets the pointer to zero
41{
42 _clear ();
43}
44
45void 42void
46dynbuf::_clear () 43dynbuf::free (chunk *&chain)
47{ 44{
48 while (first) 45 while (chain)
49 { 46 {
50 chunk *next = first->next; 47 chunk *next = chain->next;
51 48
52 sfree<char> ((char *)first, first->alloc); 49 sfree<char> ((char *)chain, chain->alloc);
53 first = next; 50 chain = next;
54 } 51 }
55} 52}
56 53
57void 54void
58dynbuf::clear () 55dynbuf::clear ()
59{ 56{
60 _clear (); 57 cextend = extend;
58 free (first->next);
59
61 _size = 0; 60 _size = 0;
62
63 first = last = (chunk *)salloc<char> (sizeof (chunk) + ext);
64 first->alloc = sizeof (chunk) + ext;
65 first->next = 0;
66
67 ptr = first->data; 61 ptr = first->data;
68 end = ptr + ext; 62 end = ptr + first->alloc - sizeof (chunk);
63 last = first;
69} 64}
70 65
71void 66void
72dynbuf::finish () 67dynbuf::finalise ()
73{ 68{
74 // finalise current chunk 69 // finalise current chunk
75 _size += last->size = ptr - last->data; 70 _size += last->size = ptr - last->data;
76} 71}
77 72
78void 73void
79dynbuf::_reserve (int size) 74dynbuf::reserve (int size)
80{ 75{
81 finish (); 76 finalise ();
82 77
83 do 78 do
84 { 79 {
85 ext += ext >> 1; 80 cextend += cextend >> 1;
86 ext = (ext + 15) & ~15; 81 cextend = (cextend + 15) & ~15;
87 } 82 }
88 while (ext < size); 83 while (cextend < size);
89 84
90 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + ext); 85 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + cextend);
91 add->alloc = sizeof (chunk) + ext; 86 add->alloc = sizeof (chunk) + cextend;
92 add->next = 0; 87 add->next = 0;
93 88
94 last->next = add; 89 last->next = add;
95 last = add; 90 last = add;
96 91
97 ptr = last->data; 92 ptr = last->data;
98 end = ptr + ext; 93 end = ptr + cextend;
99} 94}
100 95
101void 96void
102dynbuf::linearise (void *data) 97dynbuf::linearise (void *data)
103{ 98{
109 data = (void *)(((char *)data) + c->size); 104 data = (void *)(((char *)data) + c->size);
110 } 105 }
111} 106}
112 107
113char * 108char *
114dynbuf::linearise () 109dynbuf::_linearise (int extra)
115{ 110{
116 if (first->next) 111 finalise ();
117 {
118 finish ();
119 112
120 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + _size); 113 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + _size + extra);
121 add->alloc = sizeof (chunk) + _size; 114 add->alloc = sizeof (chunk) + _size;
122 add->next = 0; 115 add->next = 0;
123 116
124 linearise ((void *)add->data); 117 linearise ((void *)add->data);
125 _clear (); 118 free (first);
126 119
127 first = last = add; 120 first = last = add;
128 ptr = last->data + _size; 121 ptr = last->data + _size;
129 end = ptr; 122 end = ptr + extra;
130 _size = 0; 123 _size = 0;
131 }
132 124
133 return first->data; 125 return first->data;
134} 126}
135 127
136dynbuf::operator std::string () 128dynbuf::operator std::string ()
138 // could optimise 130 // could optimise
139 return std::string (linearise (), size ()); 131 return std::string (linearise (), size ());
140} 132}
141 133
142void 134void
135dynbuf::splice (int offset, int olen, const char *s, int slen)
136{
137 // how much bytes to extend (negative if shrinking)
138 int adjust = slen - olen;
139
140 // linearise, unless everything fits in the last chunk
141 if (offset < _size || room () < adjust)
142 _linearise (max (adjust, 0));
143
144 offset -= _size; // offset into chunk
145
146 // now move tail to final position
147 char *pos = last->data + offset;
148 char *src = pos + olen;
149 char *dst = pos + slen;
150 memmove (dst, src, ptr - src);
151
152 // now copy new content
153 memcpy (pos, s, slen);
154
155 // finally adjust length
156 ptr += adjust;
157}
158
159void
143dynbuf_text::printf (const char *format, ...) 160dynbuf_text::vprintf (const char *format, va_list ap)
144{ 161{
145 int len; 162 int len;
146 163
147 { 164 {
148 force (128); 165 force (128);
149 166
150 va_list ap; 167 va_list apc;
151 va_start (ap, format); 168 va_copy (apc, ap);
152 len = vsnprintf (ptr, end - ptr, format, ap); 169 len = vsnprintf (ptr, end - ptr, format, apc);
153 va_end (ap); 170 va_end (apc);
154 171
155 assert (len >= 0); // shield against broken vsnprintf's 172 assert (len >= 0); // shield against broken vsnprintf's
156 173
157 // was enough room available 174 // was enough room available
158 if (ptr + len < end) 175 if (ptr + len < end)
161 return; 178 return;
162 } 179 }
163 } 180 }
164 181
165 // longer, try harder 182 // longer, try harder
183 vsnprintf (force (len + 1), len + 1, format, ap);
184
185 ptr += len;
186}
187
188void
189dynbuf_text::printf (const char *format, ...)
190{
166 va_list ap; 191 va_list ap;
167 va_start (ap, format); 192 va_start (ap, format);
168 vsnprintf (force (len + 1), len + 1, format, ap); 193 vprintf (format, ap);
169 va_end (ap); 194 va_end (ap);
170
171 ptr += len;
172} 195}
173 196
174// simply return a mask with "bits" bits set 197// simply return a mask with "bits" bits set
175inline uint64 198static inline uint64
176m (int b) 199m (int b)
177{ 200{
178 return (uint64 (1) << b) - 1; 201 return (uint64 (1) << b) - 1;
179} 202}
180 203
181// convert 9 digits to ascii, using only a single multiplication 204// convert 9 digits to ascii, using only a single multiplication
182// (depending on cpu and compiler). 205// (depending on cpu and compiler).
183// will generate a single 0 as output when v=lz=0 206// will generate a single 0 as output when v=lz=0
184inline char * 207static inline char *
185i2a_9 (char *ptr, uint32 v, bool lz) 208i2a_9 (char *ptr, uint32 v, bool lz)
186{ 209{
187 // convert to 4.56 fixed-point representation 210 // convert to 4.56 fixed-point representation
188 // this should be optimal on 64 bit cpus, and rather 211 // this should be optimal on 64 bit cpus, and rather
189 // slow on 32 bit cpus. go figure :) 212 // slow on 32 bit cpus. go figure :)
232 255
233 *ptr = '-'; ptr += i < 0 ? 1 : 0; 256 *ptr = '-'; ptr += i < 0 ? 1 : 0;
234 uint32 u = i < 0 ? -i : i; 257 uint32 u = i < 0 ? -i : i;
235 258
236 if (expect_true (u < 10)) // we have a lot of single-digit numbers, so optimise 259 if (expect_true (u < 10)) // we have a lot of single-digit numbers, so optimise
237 fadd (char (u + '0')); 260 *ptr++ = u + '0';
261 else if (expect_true (u < 100)) // we have a lot of double-digit numbers, too :)
262 {
263 // let the compiler figure out sth. efficient here
264 *ptr++ = u / 10 + '0';
265 *ptr++ = u % 10 + '0';
266 }
238 else if (expect_true (u < 1000000000)) // 9 0's 267 else if (expect_true (u < 1000000000)) // 9 0's
239 ptr = i2a_9 (ptr, u, false); 268 ptr = i2a_9 (ptr, u, false);
240 else 269 else
241 { 270 {
242 sint32 div = u / 1000000000; 271 uint32 div = u / 1000000000;
243 uint32 rem = u % 1000000000; 272 uint32 rem = u % 1000000000;
244 273
245 ptr = i2a_9 (ptr, div, false); 274 ptr = i2a_9 (ptr, div, false);
246 ptr = i2a_9 (ptr, rem, true); 275 ptr = i2a_9 (ptr, rem, true);
247 } 276 }
259 // (#19) and two 9 digit parts (9..18 and 0..8) 288 // (#19) and two 9 digit parts (9..18 and 0..8)
260 289
261 // good compilers will only use multiplications here 290 // good compilers will only use multiplications here
262 291
263 if (u < 10) // we have a lot of single-digit numbers, so optimise 292 if (u < 10) // we have a lot of single-digit numbers, so optimise
264 fadd (char (u + '0')); 293 *ptr++ = u + '0';
265 else if (expect_true (u < 1000000000)) // 9 0's 294 else if (expect_true (u < 1000000000)) // 9 0's
266 ptr = i2a_9 (ptr, u, false); 295 ptr = i2a_9 (ptr, u, false);
267 else if (expect_true (u < UINT64_C (1000000000000000000))) // 18 0's 296 else if (expect_true (u < UINT64_C (1000000000000000000))) // 18 0's
268 { 297 {
269 sint32 div = u / 1000000000; 298 uint32 div = u / 1000000000;
270 uint32 rem = u % 1000000000; 299 uint32 rem = u % 1000000000;
271 300
272 ptr = i2a_9 (ptr, div, false); 301 ptr = i2a_9 (ptr, div, false);
273 ptr = i2a_9 (ptr, rem, true); 302 ptr = i2a_9 (ptr, rem, true);
274 } 303 }
275 else 304 else
276 { 305 {
277 // a biggy 306 // a biggy, split off the topmost digit
278 sint32 div = u / UINT64_C (1000000000000000000); 307 uint32 div = u / UINT64_C (1000000000000000000);
279 uint64 rem = u % UINT64_C (1000000000000000000); 308 uint64 rem = u % UINT64_C (1000000000000000000);
280 309
281 fadd (char (div + '0')); 310 *ptr++ = div + '0';
311
282 u = rem; 312 u = rem;
283 313
284 { 314 {
285 sint32 div = u / 1000000000; 315 uint32 div = u / 1000000000;
286 uint32 rem = u % 1000000000; 316 uint32 rem = u % 1000000000;
287 317
288 ptr = i2a_9 (ptr, div, true); 318 ptr = i2a_9 (ptr, div, true);
289 ptr = i2a_9 (ptr, rem, true); 319 ptr = i2a_9 (ptr, rem, true);
290 } 320 }
291 } 321 }
322}
323
324dynbuf_text::operator char *()
325{
326 *this << '\0';
327 linearise ();
328 --ptr;
329 return first->data;
330}
331
332void
333dynbuf_text::add_abilities (const char *name, uint32 abilities)
334{
335 if (!abilities)
336 return;
337
338 *this << '(' << name;
339
340 const char *sep = ": ";
341 for_all_bits_sparse_32 (abilities, i)
342 {
343 *this << sep; sep = ", ";
344 *this << attacks [i];
345 }
346
347 *this << ')';
348}
349
350void
351dynbuf_text::add_paths (const char *name, uint32 paths)
352{
353 if (!paths)
354 return;
355
356 *this << '(' << name;
357
358 const char *sep = ": ";
359 for (int i = 0; i < NRSPELLPATHS; ++i)
360 if (paths & (1 << i))
361 {
362 *this << sep; sep = ", ";
363 *this << spellpathnames [i];
364 }
365
366 *this << ')';
292} 367}
293 368
294#if 0 369#if 0
295struct dynbuf_test_class { 370struct dynbuf_test_class {
296 dynbuf_test_class () 371 dynbuf_test_class ()
318 393
319 exit (0); 394 exit (0);
320 } 395 }
321} dynbuf_test; 396} dynbuf_test;
322#endif 397#endif
398

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines