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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines