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.6 by root, Tue Dec 26 08:54:59 2006 UTC vs.
Revision 1.11 by root, Sat May 26 15:44:08 2007 UTC

2 2
3#include <cstdio> 3#include <cstdio>
4 4
5dynbuf::dynbuf (int initial, int extend) 5dynbuf::dynbuf (int initial, int extend)
6{ 6{
7 ext = extend;
7 _size = 0; 8 _size = 0;
8 ext = extend; 9
9 first = last = (chunk *) new char[sizeof (chunk) + initial]; 10 first = last = (chunk *)salloc<char> (sizeof (chunk) + initial);
10 11 first->alloc = sizeof (chunk) + initial;
11 first->next = 0; 12 first->next = 0;
12 room = initial; 13
13 ptr = first->data; 14 ptr = first->data;
15 end = ptr + initial;
14} 16}
15 17
16dynbuf::~dynbuf () 18dynbuf::~dynbuf ()
17{ 19{
18 clear (); 20 _clear ();
21}
22
23void
24dynbuf::_clear ()
25{
26 while (first)
27 {
28 chunk *next = first->next;
29
30 sfree<char> ((char *)first, first->alloc);
31 first = next;
32 }
19} 33}
20 34
21void 35void
22dynbuf::clear () 36dynbuf::clear ()
23{ 37{
24 while (first) 38 _clear ();
25 { 39 _size = 0;
26 chunk *next = first->next;
27 40
28 delete[](char *) first; 41 first = last = (chunk *)salloc<char> (sizeof (chunk) + ext);
29 first = next; 42 first->alloc = sizeof (chunk) + ext;
30 } 43 first->next = 0;
44
45 ptr = first->data;
46 end = ptr + ext;
31} 47}
32 48
33void 49void
34dynbuf::finish () 50dynbuf::finish ()
35{ 51{
47 ext += ext >> 1; 63 ext += ext >> 1;
48 ext = (ext + 15) & ~15; 64 ext = (ext + 15) & ~15;
49 } 65 }
50 while (ext < size); 66 while (ext < size);
51 67
52 chunk *add = (chunk *) new char[sizeof (chunk) + ext]; 68 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + ext);
53 69 add->alloc = sizeof (chunk) + ext;
54 add->next = 0; 70 add->next = 0;
55 71
56 last->next = add; 72 last->next = add;
57 last = add; 73 last = add;
58 74
59 room = ext;
60 ptr = last->data; 75 ptr = last->data;
76 end = ptr + ext;
61} 77}
62 78
63void 79void
64dynbuf::linearise (void *data) 80dynbuf::linearise (void *data)
65{ 81{
66 char *p = (char *) data;
67
68 last->size = ptr - last->data; 82 last->size = ptr - last->data;
69 83
70 for (chunk * c = first; c; c = c->next) 84 for (chunk *c = first; c; c = c->next)
71 { 85 {
72 memcpy (p, c->data, c->size); 86 memcpy (data, c->data, c->size);
73 p += c->size; 87 data = (void *)(((char *)data) + c->size);
74 } 88 }
75} 89}
76 90
77char * 91char *
78dynbuf::linearise () 92dynbuf::linearise ()
79{ 93{
80 if (first->next) 94 if (first->next)
81 { 95 {
82 finish (); 96 finish ();
83 97
84 chunk *add = (chunk *) new char[sizeof (chunk) + _size]; 98 chunk *add = (chunk *) salloc<char> (sizeof (chunk) + _size);
85 99 add->alloc = sizeof (chunk) + _size;
86 add->next = 0; 100 add->next = 0;
101
87 linearise ((void *) add->data); 102 linearise ((void *)add->data);
88 clear (); 103 _clear ();
89 104
90 first = last = add; 105 first = last = add;
91 ptr = last->data + _size; 106 ptr = last->data + _size;
107 end = ptr;
92 _size = 0; 108 _size = 0;
93 room = 0;
94 } 109 }
95 110
96 return first->data; 111 return first->data;
97} 112}
98 113
114dynbuf::operator std::string ()
115{
116 // could optimise
117 return std::string (linearise (), size ());
118}
119
99void 120void
121dynbuf_text::printf (const char *format, ...)
122{
123 int len;
124
125 {
126 force (128);
127
128 va_list ap;
129 va_start (ap, format);
130 len = vsnprintf (ptr, end - ptr, format, ap);
131 va_end (ap);
132
133 assert (len >= 0); // shield against broken vsnprintf's
134
135 // was enough room available
136 if (ptr + len < end)
137 {
138 alloc (len);
139 return;
140 }
141 }
142
143 // longer, try harder
144 va_list ap;
145 va_start (ap, format);
146 vsnprintf (force (len + 1), len + 1, format, ap);
147 va_end (ap);
148
149 alloc (len);
150}
151
152// simply return a mask with "bits" bits set
153inline uint64
154m (int b)
155{
156 return (uint64 (1) << b) - 1;
157}
158
159// convert 9 digits to ascii, using only a single multiplication
160// (depending on cpu and compiler).
161// will generate a single 0 as output when v=lz=0
162inline char *
163i2a_9 (char *ptr, uint32 v, bool lz)
164{
165 // convert to 4.56 fixed-point representation
166 // this should be optimal on 64 bit cpus, and rather
167 // slow on 32 bit cpus. go figure :)
168 const int bits = 7*8; // 8 bits per post-comma digit
169
170 uint64 u = v * ((m (bits) + 100000000) / 100000000); // 10**8
171
172 if (lz)
173 {
174 // output leading zeros
175 // good compilers will compile this into only shifts, masks and adds
176 *ptr++ = char (u >> (bits - 0)) + '0'; u = (u & m (bits - 0)) * 5;
177 *ptr++ = char (u >> (bits - 1)) + '0'; u = (u & m (bits - 1)) * 5;
178 *ptr++ = char (u >> (bits - 2)) + '0'; u = (u & m (bits - 2)) * 5;
179 *ptr++ = char (u >> (bits - 3)) + '0'; u = (u & m (bits - 3)) * 5;
180 *ptr++ = char (u >> (bits - 4)) + '0'; u = (u & m (bits - 4)) * 5;
181 *ptr++ = char (u >> (bits - 5)) + '0'; u = (u & m (bits - 5)) * 5;
182 *ptr++ = char (u >> (bits - 6)) + '0'; u = (u & m (bits - 6)) * 5;
183 *ptr++ = char (u >> (bits - 7)) + '0'; u = (u & m (bits - 7)) * 5;
184 *ptr++ = char (u >> (bits - 8)) + '0';
185 }
186 else
187 {
188 // do not output leading zeroes (except if v == 0)
189 // good compilers will compile this into completely branchless code
190 char digit, nz = 0;
191
192 digit = (u >> (bits - 0)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 0)) * 5;
193 digit = (u >> (bits - 1)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 1)) * 5;
194 digit = (u >> (bits - 2)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 2)) * 5;
195 digit = (u >> (bits - 3)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 3)) * 5;
196 digit = (u >> (bits - 4)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 4)) * 5;
197 digit = (u >> (bits - 5)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 5)) * 5;
198 digit = (u >> (bits - 6)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 6)) * 5;
199 digit = (u >> (bits - 7)); *ptr = digit + '0'; nz |= digit; ptr += nz ? 1 : 0; u = (u & m (bits - 7)) * 5;
200 digit = (u >> (bits - 8)); *ptr = digit + '0'; nz |= digit; ptr += 1;
201 }
202
203 return ptr;
204}
205
206void
100dynbuf::add (sint32 i) 207dynbuf_text::add (sint32 i)
101{ 208{
102 char buf[max_sint32_size]; 209 force (11); // 10 digits + '-'
103 char *p = buf + sizeof (buf);
104 char neg;
105 210
106 uint32 val; 211 *ptr = '-'; ptr += i < 0 ? 1 : 0;
212 uint32 u = i < 0 ? -i : i;
213
214 if (expect_true (u < 10)) // we have a lot of single-digit numbers, so optimise
215 fadd (char (u + '0'));
216 else if (expect_true (u < 1000000000)) // 9 0's
217 ptr = i2a_9 (ptr, u, false);
218 else
219 {
220 sint32 div = u / 1000000000;
221 uint32 rem = u % 1000000000;
222
223 ptr = i2a_9 (ptr, div, false);
224 ptr = i2a_9 (ptr, rem, true);
225 }
226}
227
228void
229dynbuf_text::add (sint64 i)
230{
231 force (20); // 19 digits + '-'
232
233 *ptr = '-'; ptr += i < 0 ? 1 : 0;
234 uint64 u = i < 0 ? -i : i;
107 235
108 if (i < 0) 236 if (i < 0)
109 { 237 {
110 neg = '-'; 238 fadd ('-');
111 val = -i; 239 u = -i;
112 } 240 }
113 else 241 else
114 {
115 neg = 0;
116 val = i; 242 u = i;
243
244 // split the number into a 1-digit part
245 // (#19) and two 9 digit parts (9..18 and 0..8)
246
247 // good compilers will only use multiplications here
248
249 if (u < 10) // we have a lot of single-digit numbers, so optimise
250 fadd (char (u + '0'));
251 else if (expect_true (u < 1000000000)) // 9 0's
252 ptr = i2a_9 (ptr, u, false);
253 else if (expect_true (u < UINT64_C (1000000000000000000))) // 18 0's
117 } 254 {
118
119 do
120 {
121 uint32 div = val / 10; 255 sint32 div = u / 1000000000;
122 *--p = '0' + char (val - div * 10); 256 uint32 rem = u % 1000000000;
123 257
124 val = div; 258 ptr = i2a_9 (ptr, div, false);
125 } 259 ptr = i2a_9 (ptr, rem, true);
126 while (val);
127
128 if (neg)
129 *--p = neg;
130
131 add ((void *) p, buf + sizeof (buf) - p);
132}
133
134void
135dynbuf::add (sint64 i)
136{
137 if (i > -10000000 && i < 10000000)
138 {
139 add (sint32 (i));
140 return;
141 }
142
143 char buf[max_sint64_size];
144 char *p = buf + sizeof (buf);
145 char neg;
146
147 uint64 val;
148
149 if (i < 0)
150 {
151 neg = '-';
152 val = -i;
153 } 260 }
154 else 261 else
155 { 262 {
156 neg = 0; 263 // a biggy
157 val = i; 264 sint32 div = u / UINT64_C (1000000000000000000);
158 } 265 uint64 rem = u % UINT64_C (1000000000000000000);
159 266
160 do 267 fadd (char (div + '0'));
268 u = rem;
269
161 { 270 {
162 uint64 div = val / 10; 271 sint32 div = u / 1000000000;
163 *--p = '0' + char (val - div * 10); 272 uint32 rem = u % 1000000000;
164 273
165 val = div; 274 ptr = i2a_9 (ptr, div, true);
275 ptr = i2a_9 (ptr, rem, true);
166 } 276 }
167 while (val); 277 }
168
169 if (neg)
170 *--p = neg;
171
172 add ((void *) p, buf + sizeof (buf) - p);
173} 278}
279
280#if 0
281struct dynbuf_test_class {
282 dynbuf_test_class ()
283 {
284 sint64 s = 0;
285 for (int i = 0; i < 10000000; ++i)
286 {
287 char b1[256], b2[256];
288
289 dynbuf_text db;
290 db.add (s);
291 db.add (char (0));
292
293 db.linearise (b1);
294 sprintf (b2, "%ld", s);
295
296 if (strcmp (b1, b2))
297 printf ("<%s,%s>\n", b1, b2);
298
299 if (i < 20)
300 s = (sint64) pow (10., i);
301 else
302 s = (sint64) exp (random () * (43.6682723752766 / RAND_MAX));
303 }
304
305 exit (0);
306 }
307} dynbuf_test;
308#endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines