@@ -310,46 +310,72 @@ void outputStream::print_data(void* data, size_t len, bool with_ascii) {
310
310
}
311
311
}
312
312
313
- stringStream::stringStream (size_t initial_size) : outputStream() {
314
- buffer_length = initial_size;
315
- buffer = NEW_C_HEAP_ARRAY (char , buffer_length, mtInternal);
316
- buffer_pos = 0 ;
317
- buffer_fixed = false ;
313
+ stringStream::stringStream (size_t initial_capacity) :
314
+ outputStream(),
315
+ _buffer(_small_buffer),
316
+ _written(0 ),
317
+ _capacity(sizeof (_small_buffer)),
318
+ _is_fixed(false )
319
+ {
320
+ if (initial_capacity > _capacity) {
321
+ grow (initial_capacity);
322
+ }
318
323
zero_terminate ();
319
324
}
320
325
321
326
// useful for output to fixed chunks of memory, such as performance counters
322
- stringStream::stringStream (char * fixed_buffer, size_t fixed_buffer_size) : outputStream() {
323
- buffer_length = fixed_buffer_size;
324
- buffer = fixed_buffer;
325
- buffer_pos = 0 ;
326
- buffer_fixed = true ;
327
+ stringStream::stringStream (char * fixed_buffer, size_t fixed_buffer_size) :
328
+ outputStream(),
329
+ _buffer(fixed_buffer),
330
+ _written(0 ),
331
+ _capacity(fixed_buffer_size),
332
+ _is_fixed(true )
333
+ {
327
334
zero_terminate ();
328
335
}
329
336
337
+ // Grow backing buffer to desired capacity. Don't call for fixed buffers
338
+ void stringStream::grow (size_t new_capacity) {
339
+ assert (!_is_fixed, " Don't call for caller provided buffers" );
340
+ assert (new_capacity > _capacity, " Sanity" );
341
+ assert (new_capacity > sizeof (_small_buffer), " Sanity" );
342
+ if (_buffer == _small_buffer) {
343
+ _buffer = NEW_C_HEAP_ARRAY (char , new_capacity, mtInternal);
344
+ _capacity = new_capacity;
345
+ if (_written > 0 ) {
346
+ ::memcpy (_buffer, _small_buffer, _written);
347
+ }
348
+ zero_terminate ();
349
+ } else {
350
+ _buffer = REALLOC_C_HEAP_ARRAY (char , _buffer, new_capacity, mtInternal);
351
+ _capacity = new_capacity;
352
+ }
353
+ }
354
+
330
355
void stringStream::write (const char * s, size_t len) {
331
- size_t write_len = len; // number of non-null bytes to write
332
- size_t end = buffer_pos + len + 1 ; // position after write and final '\0'
333
- if (end > buffer_length) {
334
- if (buffer_fixed) {
335
- // if buffer cannot resize, silently truncate
336
- end = buffer_length;
337
- write_len = end - buffer_pos - 1 ; // leave room for the final '\0'
338
- } else {
339
- // For small overruns, double the buffer. For larger ones,
340
- // increase to the requested size.
341
- if (end < buffer_length * 2 ) {
342
- end = buffer_length * 2 ;
343
- }
344
- buffer = REALLOC_C_HEAP_ARRAY (char , buffer, end, mtInternal);
345
- buffer_length = end;
356
+ assert (_capacity >= _written + 1 , " Sanity" );
357
+ if (len == 0 ) {
358
+ return ;
359
+ }
360
+ const size_t reasonable_max_len = 1 * G;
361
+ if (len >= reasonable_max_len) {
362
+ assert (false , " bad length? (" SIZE_FORMAT " )" , len);
363
+ return ;
364
+ }
365
+ size_t write_len = 0 ;
366
+ if (_is_fixed) {
367
+ write_len = MIN2 (len, _capacity - _written - 1 );
368
+ } else {
369
+ write_len = len;
370
+ size_t needed = _written + len + 1 ;
371
+ if (needed > _capacity) {
372
+ grow (MAX2 (needed, _capacity * 2 ));
346
373
}
347
374
}
348
- // invariant: buffer is always null-terminated
349
- guarantee (buffer_pos + write_len + 1 <= buffer_length, " stringStream oob" );
375
+ assert (_written + write_len + 1 <= _capacity, " stringStream oob" );
350
376
if (write_len > 0 ) {
351
- memcpy (buffer + buffer_pos , s, write_len);
352
- buffer_pos += write_len;
377
+ :: memcpy (_buffer + _written , s, write_len);
378
+ _written += write_len;
353
379
zero_terminate ();
354
380
}
355
381
@@ -360,21 +386,22 @@ void stringStream::write(const char* s, size_t len) {
360
386
}
361
387
362
388
void stringStream::zero_terminate () {
363
- assert (buffer != NULL &&
364
- buffer_pos < buffer_length , " sanity" );
365
- buffer[buffer_pos ] = ' \0 ' ;
389
+ assert (_buffer != NULL &&
390
+ _written < _capacity , " sanity" );
391
+ _buffer[_written ] = ' \0 ' ;
366
392
}
367
393
368
394
void stringStream::reset () {
369
- buffer_pos = 0 ; _precount = 0 ; _position = 0 ;
395
+ _written = 0 ; _precount = 0 ; _position = 0 ;
396
+ _newlines = 0 ;
370
397
zero_terminate ();
371
398
}
372
399
373
400
char * stringStream::as_string (bool c_heap) const {
374
401
char * copy = c_heap ?
375
- NEW_C_HEAP_ARRAY (char , buffer_pos + 1 , mtInternal) : NEW_RESOURCE_ARRAY (char , buffer_pos + 1 );
376
- strncpy (copy, buffer, buffer_pos );
377
- copy[buffer_pos ] = 0 ; // terminating null
402
+ NEW_C_HEAP_ARRAY (char , _written + 1 , mtInternal) : NEW_RESOURCE_ARRAY (char , _written + 1 );
403
+ ::memcpy (copy, _buffer, _written );
404
+ copy[_written ] = 0 ; // terminating null
378
405
if (c_heap) {
379
406
// Need to ensure our content is written to memory before we return
380
407
// the pointer to it.
@@ -384,8 +411,8 @@ char* stringStream::as_string(bool c_heap) const {
384
411
}
385
412
386
413
stringStream::~stringStream () {
387
- if (buffer_fixed == false && buffer != NULL ) {
388
- FREE_C_HEAP_ARRAY (char , buffer );
414
+ if (!_is_fixed && _buffer != _small_buffer ) {
415
+ FREE_C_HEAP_ARRAY (char , _buffer );
389
416
}
390
417
}
391
418
0 commit comments