18 #ifndef STXXL_COMMON_BINARY_BUFFER_HEADER
19 #define STXXL_COMMON_BINARY_BUFFER_HEADER
56 : m_data(NULL), m_size(0), m_capacity(0)
61 : m_data(NULL), m_size(0), m_capacity(0)
68 : m_data(NULL), m_size(0), m_capacity(0)
75 : m_data(NULL), m_size(0), m_capacity(0)
82 : m_data(NULL), m_size(0), m_capacity(0)
84 assign(str.data(), str.size());
94 inline const char *
data()
const
118 inline std::string
str()
const
120 return std::string(reinterpret_cast<const char*>(m_data), m_size);
127 assert(n <= m_capacity);
139 m_data =
static_cast<char*
>(realloc(m_data, m_capacity));
149 if (m_data) free(m_data);
151 m_size = m_capacity = 0;
159 const char* data = m_data;
161 m_size = m_capacity = 0;
176 if (len > m_capacity) alloc(len);
178 memcpy(m_data, data, len);
207 size_t rem = m_size % n;
210 size_t add = n - rem;
211 if (m_size + add > m_capacity) dynalloc(m_size + add);
212 memset(m_data + m_size, 0, add);
215 assert((m_size % n) == 0);
227 size_t newsize = m_capacity;
229 while (newsize < n) {
230 if (newsize < 256) newsize = 512;
231 else if (newsize < 1024 * 1024) newsize = 2 * newsize;
232 else newsize += 1024 * 1024;
246 if (m_size + len > m_capacity) dynalloc(m_size + len);
248 memcpy(m_data + m_size, data, len);
257 return append(bb.
data(), bb.
size());
264 return append(s.data(), s.size());
269 template <
typename Type>
272 if (m_size +
sizeof(Type) > m_capacity) dynalloc(m_size +
sizeof(Type));
274 *
reinterpret_cast<Type*
>(m_data + m_size) = item;
275 m_size +=
sizeof(Type);
284 put<uint8>(
uint8(v));
286 else if (v < 128 * 128) {
287 put<uint8>((
uint8)(((v >> 0) & 0x7F) | 0x80));
288 put<uint8>((
uint8)((v >> 7) & 0x7F));
290 else if (v < 128 * 128 * 128) {
291 put<uint8>((
uint8)(((v >> 0) & 0x7F) | 0x80));
292 put<uint8>((
uint8)(((v >> 7) & 0x7F) | 0x80));
293 put<uint8>((
uint8)((v >> 14) & 0x7F));
295 else if (v < 128 * 128 * 128 * 128) {
296 put<uint8>((
uint8)(((v >> 0) & 0x7F) | 0x80));
297 put<uint8>((
uint8)(((v >> 7) & 0x7F) | 0x80));
298 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
299 put<uint8>((
uint8)((v >> 21) & 0x7F));
302 put<uint8>((
uint8)(((v >> 0) & 0x7F) | 0x80));
303 put<uint8>((
uint8)(((v >> 7) & 0x7F) | 0x80));
304 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
305 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
306 put<uint8>((
uint8)((v >> 28) & 0x7F));
315 return put_varint((
uint32)v);
322 put<uint8>(
uint8(v));
324 else if (v < 128 * 128) {
325 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
326 put<uint8>((
uint8)((v >> 07) & 0x7F));
328 else if (v < 128 * 128 * 128) {
329 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
330 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
331 put<uint8>((
uint8)((v >> 14) & 0x7F));
333 else if (v < 128 * 128 * 128 * 128) {
334 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
335 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
336 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
337 put<uint8>((
uint8)((v >> 21) & 0x7F));
339 else if (v < ((
uint64)128) * 128 * 128 * 128 * 128) {
340 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
341 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
342 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
343 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
344 put<uint8>((
uint8)((v >> 28) & 0x7F));
346 else if (v < ((
uint64)128) * 128 * 128 * 128 * 128 * 128) {
347 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
348 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
349 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
350 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
351 put<uint8>((
uint8)(((v >> 28) & 0x7F) | 0x80));
352 put<uint8>((
uint8)((v >> 35) & 0x7F));
354 else if (v < ((
uint64)128) * 128 * 128 * 128 * 128 * 128 * 128) {
355 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
356 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
357 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
358 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
359 put<uint8>((
uint8)(((v >> 28) & 0x7F) | 0x80));
360 put<uint8>((
uint8)(((v >> 35) & 0x7F) | 0x80));
361 put<uint8>((
uint8)((v >> 42) & 0x7F));
363 else if (v < ((
uint64)128) * 128 * 128 * 128 * 128 * 128 * 128 * 128) {
364 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
365 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
366 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
367 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
368 put<uint8>((
uint8)(((v >> 28) & 0x7F) | 0x80));
369 put<uint8>((
uint8)(((v >> 35) & 0x7F) | 0x80));
370 put<uint8>((
uint8)(((v >> 42) & 0x7F) | 0x80));
371 put<uint8>((
uint8)((v >> 49) & 0x7F));
373 else if (v < ((
uint64)128) * 128 * 128 * 128 * 128 * 128 * 128 * 128 * 128) {
374 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
375 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
376 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
377 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
378 put<uint8>((
uint8)(((v >> 28) & 0x7F) | 0x80));
379 put<uint8>((
uint8)(((v >> 35) & 0x7F) | 0x80));
380 put<uint8>((
uint8)(((v >> 42) & 0x7F) | 0x80));
381 put<uint8>((
uint8)(((v >> 49) & 0x7F) | 0x80));
382 put<uint8>((
uint8)((v >> 56) & 0x7F));
385 put<uint8>((
uint8)(((v >> 00) & 0x7F) | 0x80));
386 put<uint8>((
uint8)(((v >> 07) & 0x7F) | 0x80));
387 put<uint8>((
uint8)(((v >> 14) & 0x7F) | 0x80));
388 put<uint8>((
uint8)(((v >> 21) & 0x7F) | 0x80));
389 put<uint8>((
uint8)(((v >> 28) & 0x7F) | 0x80));
390 put<uint8>((
uint8)(((v >> 35) & 0x7F) | 0x80));
391 put<uint8>((
uint8)(((v >> 42) & 0x7F) | 0x80));
392 put<uint8>((
uint8)(((v >> 49) & 0x7F) | 0x80));
393 put<uint8>((
uint8)(((v >> 56) & 0x7F) | 0x80));
394 put<uint8>((
uint8)((v >> 63) & 0x7F));
409 return put_string(str.data(), str.size());
415 return put_string(bb.
data(), bb.
size());
436 : m_data(bb.data()), m_size(bb.size())
441 : m_data(reinterpret_cast<const char*>(data)), m_size(n)
446 : m_data(str.data()), m_size(str.size())
458 inline std::string
str()
const
459 {
return std::string(reinterpret_cast<const char*>(m_data), m_size); }
464 if (m_size != br.
m_size)
return false;
465 return memcmp(m_data, br.
m_data, m_size) == 0;
471 if (m_size != br.
m_size)
return true;
472 return memcmp(m_data, br.
m_data, m_size) != 0;
518 return (m_curr + n <= m_size);
525 if (!cursor_available(n))
526 throw (std::underflow_error(
"binary_reader underrun"));
532 return (m_curr == m_size);
548 check_available(datalen);
549 memcpy(outdata, m_data + m_curr, datalen);
557 inline std::string
read(
size_t datalen)
559 check_available(datalen);
560 std::string out(m_data + m_curr, datalen);
567 template <
typename Type>
570 check_available(
sizeof(Type));
572 Type ret = *
reinterpret_cast<const Type*
>(m_data + m_curr);
573 m_curr +=
sizeof(Type);
581 uint32 u, v = get<uint8>();
582 if (!(v & 0x80))
return v;
584 u = get<uint8>(), v |= (u & 0x7F) << 7;
585 if (!(u & 0x80))
return v;
586 u = get<uint8>(), v |= (u & 0x7F) << 14;
587 if (!(u & 0x80))
return v;
588 u = get<uint8>(), v |= (u & 0x7F) << 21;
589 if (!(u & 0x80))
return v;
592 throw (std::overflow_error(
"Overflow during varint decoding."));
593 v |= (u & 0x7F) << 28;
600 uint64 u, v = get<uint8>();
601 if (!(v & 0x80))
return v;
603 u = get<uint8>(), v |= (u & 0x7F) << 7;
604 if (!(u & 0x80))
return v;
605 u = get<uint8>(), v |= (u & 0x7F) << 14;
606 if (!(u & 0x80))
return v;
607 u = get<uint8>(), v |= (u & 0x7F) << 21;
608 if (!(u & 0x80))
return v;
609 u = get<uint8>(), v |= (u & 0x7F) << 28;
610 if (!(u & 0x80))
return v;
611 u = get<uint8>(), v |= (u & 0x7F) << 35;
612 if (!(u & 0x80))
return v;
613 u = get<uint8>(), v |= (u & 0x7F) << 42;
614 if (!(u & 0x80))
return v;
615 u = get<uint8>(), v |= (u & 0x7F) << 49;
616 if (!(u & 0x80))
return v;
617 u = get<uint8>(), v |= (u & 0x7F) << 56;
618 if (!(u & 0x80))
return v;
621 throw (std::overflow_error(
"Overflow during varint64 decoding."));
622 v |= (u & 0x7F) << 63;
629 uint32 len = get_varint();
637 uint32 len = get_varint();
650 #endif // !STXXL_COMMON_BINARY_BUFFER_HEADER
uint64 get_varint64()
Fetch a 64-bit varint from the buffer at the cursor.
binary_buffer & assign(const binary_buffer &other)
Copy the contents of another buffer object into this buffer, overwrites all current data...
binary_buffer_ref(const std::string &str)
Constructor, assign memory area from string, does NOT copy.
binary_buffer & put_varint(int v)
Append a varint to the buffer.
size_t capacity() const
Return the currently allocated buffer capacity.
binary_buffer_ref represents a memory area as pointer and valid length.
binary_buffer_ref(const binary_buffer &bb)
Constructor, assign memory area from binary_buffer.
binary_buffer & set_size(size_t n)
Set the valid bytes in the buffer, use if the buffer is filled directly.
size_t size() const
Return the currently used length in bytes.
size_t size() const
Return the currently valid length in bytes.
uint32 get_varint()
Fetch a varint with up to 32-bit from the buffer at the cursor.
unsigned long long int uint64
binary_buffer_ref get_binary_buffer_ref()
Fetch a binary_buffer_ref to a binary string or blob which was put via put_string(). Does NOT copy the data.
size_t m_size
Size of valid data.
char * m_data
Allocated buffer pointer.
const char * data() const
Return a pointer to the currently kept memory area.
binary_buffer & clear()
Clears the memory contents, does not deallocate the memory.
binary_buffer & put_varint(uint64 v)
Append a varint to the buffer.
binary_buffer(const binary_buffer &other)
Copy-Constructor, duplicates memory content.
std::string read(size_t datalen)
Fetch a number of unstructured bytes from the buffer as std::string, advancing the cursor...
binary_reader & read(void *outdata, size_t datalen)
Fetch a number of unstructured bytes from the buffer, advancing the cursor.
binary_buffer & dealloc()
Deallocates the kept memory space (we use dealloc() instead of free() as a name, because sometimes "f...
bool cursor_available(size_t n) const
Check that n bytes are available at the cursor.
size_t curr() const
Return the current read cursor.
binary_reader represents a binary_buffer_ref with an additional cursor with which the memory can be r...
binary_buffer(size_t n)
Constructor, create object with n bytes pre-allocated.
~binary_buffer()
Destroys the memory space.
binary_buffer & put_string(const char *data, size_t len)
Put a string by saving it's length followed by the data itself.
const void * data() const
Return a pointer to the currently kept memory area.
binary_buffer & put(const Type item)
Put (append) a single item of the template type T to the buffer. Be careful with implicit type conver...
binary_buffer & put_string(const std::string &str)
Put a string by saving it's length followed by the data itself.
void check_available(size_t n) const
Throws a std::underflow_error unless n bytes are available at the cursor.
binary_buffer()
Create a new empty object.
binary_buffer(const std::string &str)
Constructor from std::string, copies string content.
binary_reader & skip(size_t n)
Advance the cursor given number of bytes without reading them.
binary_buffer & align(size_t n)
Align the size of the buffer to a multiple of n. Fills up with 0s.
binary_buffer & append(const std::string &s)
Append to contents of a std::string, excluding the null (which isn't contained in the string size any...
bool operator!=(const uint_pair &b) const
inequality checking operator
size_t m_curr
Current read cursor.
const char * m_data
Allocated buffer pointer.
#define STXXL_BEGIN_NAMESPACE
std::string str() const
Explicit conversion to std::string (copies memory of course).
binary_buffer & dynalloc(size_t n)
Dynamically allocate more memory. At least n bytes will be available, probably more to compensate fut...
binary_reader(const void *data, size_t n)
Constructor, assign memory area from pointer and length.
binary_buffer & append(const class binary_buffer &bb)
Append the contents of a different buffer object to this one.
binary_buffer represents a dynamically growable area of memory, which can be modified by appending in...
size_t m_capacity
Total capacity of buffer.
bool empty() const
Return true if the cursor is at the end of the buffer.
binary_reader & rewind()
Reset the read cursor.
char * data()
Return a writeable pointer to the currently kept memory area.
binary_buffer & append(const void *data, size_t len)
Append a memory range to the buffer.
binary_reader(const std::string &str)
Constructor, assign memory area from string, does NOT copy.
size_t m_size
Size of valid data.
std::string str() const
Explicit conversion to std::string (copies memory of course).
const char * detach()
Detach the memory from the object, returns the memory pointer.
binary_buffer(const void *data, size_t n)
Constructor, copy memory area.
std::string get_string()
Fetch a string which was put via put_string().
binary_buffer_ref(const void *data, size_t n)
Constructor, assign memory area from pointer and length.
binary_buffer & assign(const void *data, size_t len)
Copy a memory range into the buffer, overwrites all current data. Roughly equivalent to clear() follo...
binary_buffer & put_varint(uint32 v)
Append a varint to the buffer.
binary_reader(const binary_buffer_ref &br)
Constructor, assign memory area from binary_buffer.
binary_buffer & put_string(const binary_buffer &bb)
Put a binary_buffer by saving it's length followed by the data itself.
binary_buffer & alloc(size_t n)
Make sure that at least n bytes are allocated.
bool operator==(const uint_pair &b) const
equality checking operator
#define STXXL_END_NAMESPACE