#include "global.h" #include dynbuf::dynbuf (int initial, int extend) { ext = extend; _size = 0; first = last = (chunk *)salloc (sizeof (chunk) + initial); first->alloc = sizeof (chunk) + initial; first->next = 0; ptr = first->data; end = ptr + initial; } dynbuf::~dynbuf () { _clear (); } void dynbuf::_clear () { while (first) { chunk *next = first->next; sfree ((char *)first, first->alloc); first = next; } } void dynbuf::clear () { _clear (); _size = 0; first = last = (chunk *)salloc (sizeof (chunk) + ext); first->alloc = sizeof (chunk) + ext; first->next = 0; ptr = first->data; end = ptr + ext; } void dynbuf::finish () { // finalise current chunk _size += last->size = ptr - last->data; } void dynbuf::_reserve (int size) { finish (); do { ext += ext >> 1; ext = (ext + 15) & ~15; } while (ext < size); chunk *add = (chunk *) salloc (sizeof (chunk) + ext); add->alloc = sizeof (chunk) + ext; add->next = 0; last->next = add; last = add; ptr = last->data; end = ptr + ext; } void dynbuf::linearise (void *data) { last->size = ptr - last->data; for (chunk *c = first; c; c = c->next) { memcpy (data, c->data, c->size); data = (void *)(((char *)data) + c->size); } } char * dynbuf::linearise () { if (first->next) { finish (); chunk *add = (chunk *) salloc (sizeof (chunk) + _size); add->alloc = sizeof (chunk) + _size; add->next = 0; linearise ((void *)add->data); _clear (); first = last = add; ptr = last->data + _size; end = ptr; _size = 0; } return first->data; } dynbuf::operator std::string () { // could optimise return std::string (linearise (), size ()); } void dynbuf_text::printf (const char *format, ...) { int len; { force (128); va_list ap; va_start (ap, format); len = vsnprintf (ptr, end - ptr, format, ap); va_end (ap); assert (len >= 0); // shield against broken vsnprintf's // was enough room available if (ptr + len < end) { alloc (len); return; } } // longer, try harder va_list ap; va_start (ap, format); vsnprintf (force (len + 1), len + 1, format, ap); va_end (ap); alloc (len); } void dynbuf_text::add (sint32 i) { char buf[max_sint32_size]; char *p = buf + sizeof (buf); char neg; uint32 val; if (i < 0) { neg = '-'; val = -i; } else { neg = 0; val = i; } do { uint32 div = val / 10; *--p = '0' + char (val - div * 10); val = div; } while (val); if (neg) *--p = neg; add ((void *) p, buf + sizeof (buf) - p); } void dynbuf_text::add (sint64 i) { if (i > -10000000 && i < 10000000) { add (sint32 (i)); return; } char buf[max_sint64_size]; char *p = buf + sizeof (buf); char neg; uint64 val; if (i < 0) { neg = '-'; val = -i; } else { neg = 0; val = i; } do { uint64 div = val / 10; *--p = '0' + char (val - div * 10); val = div; } while (val); if (neg) *--p = neg; add ((void *) p, buf + sizeof (buf) - p); }