@@ -28,9 +28,9 @@ struct Outbuffer
2828{
2929 @safe :
3030
31- ubyte * buf; // the buffer itself
32- ubyte * pend; // pointer past the end of the buffer
33- private ubyte * p; // current position in buffer
31+ ubyte * buf; // the buffer itself
32+ private ubyte * pend; // pointer past the end of the buffer
33+ private ubyte * p; // current position in buffer
3434
3535 nothrow :
3636 this (size_t initialSize)
@@ -43,17 +43,16 @@ struct Outbuffer
4343 @trusted
4444 void dtor ()
4545 {
46- if ( auto slice = this .extractSlice())
47- free(slice.ptr) ;
46+ free(buf);
47+ buf = p = pend = null ;
4848 }
4949
5050 void reset ()
5151 {
5252 p = buf;
5353 }
5454
55- // Returns: A slice to the data written so far
56- extern (D ) inout (ubyte )[] opSlice (size_t from, size_t to) inout
55+ private extern (D ) inout (ubyte )[] opSlice (size_t from, size_t to) inout
5756 @trusted pure nothrow @nogc
5857 {
5958 assert (this .buf, " Attempt to dereference a null pointer" );
@@ -62,10 +61,10 @@ struct Outbuffer
6261 return this .buf[from .. to];
6362 }
6463
65- // / Ditto
64+ // Returns: A slice to the data written so far
6665 extern (D ) inout (ubyte )[] opSlice () inout @trusted pure nothrow @nogc
6766 {
68- return this .buf[0 .. this .p - this .buf ];
67+ return this .buf[0 .. length ];
6968 }
7069
7170 extern (D ) ubyte [] extractSlice() @safe pure nothrow @nogc
@@ -90,31 +89,41 @@ struct Outbuffer
9089
9190 // Reserve nbytes in buffer
9291 @trusted
93- void enlarge (size_t nbytes)
92+ private void enlarge (size_t nbytes)
9493 {
9594 pragma (inline, false ); // do not inline slow path
96- const size_t oldlen = pend - buf;
97- const size_t used = p - buf;
9895
99- size_t len = used + nbytes;
100- // No need to reallocate
101- if (nbytes < (pend - p))
102- return ;
96+ debug assert (nbytes > pend - p, " You should call this function from reserve() only." );
10397
104- const size_t newlen = oldlen + (oldlen >> 1 ); // oldlen * 1.5
105- if (len < newlen)
106- len = newlen;
107- len = (len + 15 ) & ~ 15 ;
98+ if (buf is null )
99+ {
100+ // Special-case the overwhelmingly most frequent situation
101+ if (nbytes < 64 ) nbytes = 64 ;
102+ p = buf = cast (ubyte * ) malloc(nbytes);
103+ pend = buf + nbytes;
104+ }
105+ else
106+ {
107+ const size_t used = p - buf;
108+ const size_t oldlen = pend - buf;
109+ // Ensure exponential growth, oldlen * 2 for small sizes, oldlen * 1.5 for big sizes
110+ const size_t minlen = oldlen + (oldlen >> (oldlen > 1024 * 64 ));
108111
109- buf = cast (ubyte * ) realloc(buf,len);
112+ size_t len = used + nbytes;
113+ if (len < minlen)
114+ len = minlen;
115+ // Round up to cache line size
116+ len = (len + 63 ) & ~ 63 ;
117+
118+ buf = cast (ubyte * ) realloc(buf, len);
119+
120+ pend = buf + len;
121+ p = buf + used;
122+ }
110123 if (! buf)
111124 err_nomem();
112-
113- pend = buf + len;
114- p = buf + used;
115125 }
116126
117-
118127 // Write n zeros; return pointer to start of zeros
119128 @trusted
120129 void * writezeros(size_t n)
@@ -207,7 +216,7 @@ struct Outbuffer
207216 * Writes a 32 bit int, no reserve check.
208217 */
209218 @trusted
210- void write32n (int v)
219+ private void write32n (int v)
211220 {
212221 * cast (int * )p = v;
213222 p += 4 ;
@@ -226,7 +235,7 @@ struct Outbuffer
226235 * Writes a 64 bit long, no reserve check
227236 */
228237 @trusted
229- void write64n (long v)
238+ private void write64n (long v)
230239 {
231240 * cast (long * )p = v;
232241 p += 8 ;
@@ -245,7 +254,7 @@ struct Outbuffer
245254 * Writes a 32 bit float.
246255 */
247256 @trusted
248- void writeFloat (float v)
257+ private void writeFloat (float v)
249258 {
250259 reserve (float .sizeof);
251260 * cast (float * )p = v;
@@ -256,7 +265,7 @@ struct Outbuffer
256265 * Writes a 64 bit double.
257266 */
258267 @trusted
259- void writeDouble (double v)
268+ private void writeDouble (double v)
260269 {
261270 reserve (double .sizeof);
262271 * cast (double * )p = v;
@@ -298,7 +307,7 @@ struct Outbuffer
298307 * Inserts string at beginning of buffer.
299308 */
300309 @trusted
301- void prependBytes (const (char )* s)
310+ private void prependBytes (const (char )* s)
302311 {
303312 prepend(s, strlen (s));
304313 }
@@ -307,7 +316,7 @@ struct Outbuffer
307316 * Inserts bytes at beginning of buffer.
308317 */
309318 @trusted
310- void prepend (const (void )* b, size_t len)
319+ private void prepend (const (void )* b, size_t len)
311320 {
312321 reserve (len);
313322 memmove(buf + len,buf,p - buf);
@@ -319,7 +328,7 @@ struct Outbuffer
319328 * Bracket buffer contents with c1 and c2.
320329 */
321330 @trusted
322- void bracket (char c1,char c2)
331+ private void bracket (char c1,char c2)
323332 {
324333 reserve (2 );
325334 memmove(buf + 1 ,buf,p - buf);
0 commit comments