79#ifndef DYNAMIC_BUFFER_H
80#define DYNAMIC_BUFFER_H
83#define DB_VERSION_MAJOR 0
84#define DB_VERSION_MINOR 2
85#define DB_VERSION_PATCH 2
86#define DB_VERSION_STRING "0.2.2"
106#define DB_MALLOC malloc
111#define DB_REALLOC realloc
121#define DB_ASSERT assert
125#ifndef DB_ATOMIC_REFCOUNT
126#define DB_ATOMIC_REFCOUNT 0
129#if DB_ATOMIC_REFCOUNT
130#include <stdatomic.h>
132#define DB_REFCOUNT_INIT(n) ATOMIC_VAR_INIT(n)
133#define DB_REFCOUNT_LOAD(ptr) atomic_load(ptr)
134#define DB_REFCOUNT_INCREMENT(ptr) (atomic_fetch_add(ptr, 1) + 1)
135#define DB_REFCOUNT_DECREMENT(ptr) (atomic_fetch_sub(ptr, 1) - 1)
138#define DB_REFCOUNT_INIT(n) (n)
139#define DB_REFCOUNT_LOAD(ptr) (*(ptr))
140#define DB_REFCOUNT_INCREMENT(ptr) (++(*(ptr)))
141#define DB_REFCOUNT_DECREMENT(ptr) (--(*(ptr)))
146#ifdef DB_IMPLEMENTATION
747#ifdef DB_IMPLEMENTATION
756typedef struct db_internal {
767static inline db_internal* db_meta(
db_buffer buf) {
768 return (db_internal*)((
char*)(buf) -
sizeof(db_internal));
775static db_buffer db_alloc(
size_t capacity) {
777 size_t total_size =
sizeof(db_internal) + capacity;
780 if (total_size <
sizeof(db_internal) || total_size < capacity) {
785 DB_ASSERT(block &&
"db_alloc: memory allocation failed");
788 db_internal* meta = (db_internal*)block;
791 meta->capacity = capacity;
794 return (
db_buffer)((
char*)block +
sizeof(db_internal));
805 void* block = (
char*)buf -
sizeof(db_internal);
812 return db_alloc(capacity);
816 DB_ASSERT((data || size == 0) &&
"db_new_with_data: data cannot be NULL when size > 0");
822 memcpy(buf, data, size);
823 db_meta(buf)->size = size;
830 DB_ASSERT((data || (size == 0 && capacity == 0)) &&
"db_new_from_owned_data: data cannot be NULL with non-zero size/capacity");
831 DB_ASSERT(capacity >= size &&
"db_new_from_owned_data: capacity must be >= size");
839 memcpy(buf, data, size);
840 db_meta(buf)->size = size;
847 DB_ASSERT(buf &&
"db_retain: buf cannot be NULL");
853 DB_ASSERT(buf_ptr &&
"db_release: buf_ptr cannot be NULL");
854 if (!*buf_ptr)
return;
867 DB_ASSERT(buf &&
"db_size: buf cannot be NULL");
868 return db_meta(buf)->size;
872 DB_ASSERT(buf &&
"db_capacity: buf cannot be NULL");
873 return db_meta(buf)->capacity;
877 DB_ASSERT(buf &&
"db_is_empty: buf cannot be NULL");
878 return db_meta(buf)->size == 0;
882 DB_ASSERT(buf &&
"db_refcount: buf cannot be NULL");
887 DB_ASSERT(buf &&
"db_slice: buf cannot be NULL");
889 size_t buf_size = db_meta(buf)->size;
890 if (offset > buf_size || offset + length > buf_size) {
900 memcpy(slice, buf + offset, length);
901 db_meta(slice)->size = length;
908 DB_ASSERT(buf &&
"db_slice_from: buf cannot be NULL");
909 size_t buf_size = db_meta(buf)->size;
910 if (offset > buf_size)
return NULL;
911 return db_slice(buf, offset, buf_size - offset);
915 DB_ASSERT(buf &&
"db_slice_to: buf cannot be NULL");
916 if (length > db_meta(buf)->size)
return NULL;
923 DB_ASSERT(buf &&
"db_append: buf cannot be NULL");
924 DB_ASSERT((data || size == 0) &&
"db_append: data cannot be NULL when size > 0");
930 size_t old_size = db_meta(buf)->size;
931 size_t new_size = old_size + size;
937 memcpy(result, buf, old_size);
940 memcpy(result + old_size, data, size);
943 db_meta(result)->size = new_size;
955static int db_internal_ensure_unique(
db_buffer* builder_data) {
956 if (!*builder_data)
return -1;
963 size_t current_size =
db_size(*builder_data);
968 *builder_data = new_buf;
979static int db_internal_ensure_capacity(
db_buffer* builder_data,
size_t* builder_capacity,
size_t required_capacity) {
980 if (*builder_capacity >= required_capacity) {
984 size_t new_capacity = *builder_capacity;
985 if (new_capacity == 0) {
989 while (new_capacity < required_capacity) {
994 db_internal* meta = db_meta(*builder_data);
997 size_t new_block_size =
sizeof(db_internal) + new_capacity;
1000 db_internal* new_meta = (db_internal*)
DB_REALLOC(meta, new_block_size);
1001 DB_ASSERT(new_meta &&
"db_internal_ensure_capacity: memory reallocation failed");
1004 new_meta->capacity = new_capacity;
1007 *builder_data = (
db_buffer)((
char*)new_meta +
sizeof(db_internal));
1008 *builder_capacity = new_capacity;
1020static int db_internal_append(
db_buffer* builder_data,
size_t* builder_capacity,
const void* data,
size_t size) {
1021 if (size == 0)
return 0;
1023 if (db_internal_ensure_unique(builder_data) != 0) {
1027 size_t current_size =
db_size(*builder_data);
1028 size_t needed_capacity = current_size + size;
1030 if (db_internal_ensure_capacity(builder_data, builder_capacity, needed_capacity) != 0) {
1035 memcpy(*builder_data + current_size, data, size);
1036 db_meta(*builder_data)->size = current_size + size;
1042 DB_ASSERT(buf1 &&
"db_concat: buf1 cannot be NULL");
1043 DB_ASSERT(buf2 &&
"db_concat: buf2 cannot be NULL");
1045 size_t size1 = db_meta(buf1)->size;
1046 size_t size2 = db_meta(buf2)->size;
1047 size_t total_size = size1 + size2;
1049 if (total_size == 0)
return db_new(0);
1055 memcpy(result, buf1, size1);
1059 memcpy(result + size1, buf2, size2);
1062 db_meta(result)->size = total_size;
1067 if (!buffers || count == 0)
return db_new(0);
1070 size_t total_size = 0;
1071 for (
size_t i = 0; i < count; i++) {
1073 total_size += db_meta(buffers[i])->size;
1081 for (
size_t i = 0; i < count; i++) {
1083 size_t size = db_meta(buffers[i])->size;
1085 memcpy(result + offset, buffers[i], size);
1091 db_meta(result)->size = total_size;
1096 DB_ASSERT(buf1 &&
"db_equals: buf1 cannot be NULL");
1097 DB_ASSERT(buf2 &&
"db_equals: buf2 cannot be NULL");
1099 if (buf1 == buf2)
return true;
1101 size_t size1 = db_meta(buf1)->size;
1102 size_t size2 = db_meta(buf2)->size;
1103 if (size1 != size2)
return false;
1105 return memcmp(buf1, buf2, size1) == 0;
1109 DB_ASSERT(buf1 &&
"db_compare: buf1 cannot be NULL");
1110 DB_ASSERT(buf2 &&
"db_compare: buf2 cannot be NULL");
1112 if (buf1 == buf2)
return 0;
1114 size_t size1 = db_meta(buf1)->size;
1115 size_t size2 = db_meta(buf2)->size;
1116 size_t min_size = size1 < size2 ? size1 : size2;
1118 int result = memcmp(buf1, buf2, min_size);
1120 if (result != 0)
return result;
1123 if (size1 < size2)
return -1;
1124 if (size1 > size2)
return 1;
1132#define db_write write
1136#define db_write write
1140 DB_ASSERT(buf_ptr && *buf_ptr &&
"db_read_fd: buf_ptr and *buf_ptr cannot be NULL");
1141 DB_ASSERT(fd >= 0 &&
"db_read_fd: invalid file descriptor");
1144 size_t read_size = max_bytes == 0 ? 4096 : max_bytes;
1145 char* temp_buffer = (
char*)
DB_MALLOC(read_size);
1146 DB_ASSERT(temp_buffer &&
"db_read_fd: memory allocation failed");
1148 ssize_t bytes_read = db_read(fd, temp_buffer, read_size);
1149 if (bytes_read > 0) {
1165 DB_ASSERT(buf &&
"db_write_fd: buf cannot be NULL");
1166 DB_ASSERT(fd >= 0 &&
"db_write_fd: invalid file descriptor");
1167 size_t size = db_meta(buf)->size;
1168 if (size == 0)
return 0;
1170 return db_write(fd, buf, size);
1174 if (!filename)
return NULL;
1176 FILE* file = fopen(filename,
"rb");
1177 if (!file)
return NULL;
1180 fseek(file, 0, SEEK_END);
1181 long file_size = ftell(file);
1182 fseek(file, 0, SEEK_SET);
1184 if (file_size < 0) {
1195 size_t bytes_read = fread(buf, 1, file_size, file);
1198 db_meta(buf)->size = bytes_read;
1203 DB_ASSERT(buf &&
"db_write_file: buf cannot be NULL");
1204 if (!filename)
return false;
1206 FILE* file = fopen(filename,
"wb");
1207 if (!file)
return false;
1209 bool success =
true;
1210 size_t size = db_meta(buf)->size;
1212 size_t written = fwrite(buf, 1, size, file);
1213 success = (written == size);
1222 DB_ASSERT(buf &&
"db_to_hex: buf cannot be NULL");
1224 size_t size = db_meta(buf)->size;
1227 size_t hex_size = size * 2;
1231 const char* hex_chars = uppercase ?
"0123456789ABCDEF" :
"0123456789abcdef";
1232 const uint8_t* data = (
const uint8_t*)buf;
1233 char* hex_data = hex_buf;
1235 for (
size_t i = 0; i < size; i++) {
1236 hex_data[i * 2] = hex_chars[data[i] >> 4];
1237 hex_data[i * 2 + 1] = hex_chars[data[i] & 0x0F];
1240 db_meta(hex_buf)->size = hex_size;
1244static int hex_char_to_value(
char c) {
1245 if (c >=
'0' && c <=
'9')
return c -
'0';
1246 if (c >=
'A' && c <=
'F')
return c -
'A' + 10;
1247 if (c >=
'a' && c <=
'f')
return c -
'a' + 10;
1252 if (!hex_string || length % 2 != 0)
return NULL;
1254 size_t byte_length = length / 2;
1258 uint8_t* data = (uint8_t*)buf;
1260 for (
size_t i = 0; i < byte_length; i++) {
1261 int high = hex_char_to_value(hex_string[i * 2]);
1262 int low = hex_char_to_value(hex_string[i * 2 + 1]);
1264 if (high < 0 || low < 0) {
1269 data[i] = (uint8_t)((high << 4) | low);
1272 db_meta(buf)->size = byte_length;
1277 const char* name = label ? label :
"buffer";
1280 printf(
"%s: NULL\n", name);
1284 db_internal* meta = db_meta(buf);
1285 size_t size = meta->size;
1286 size_t capacity = meta->capacity;
1289 printf(
"%s: size=%zu, capacity=%zu, refcount=%d\n",
1290 name, size, capacity, refcount);
1295 const uint8_t* data = (
const uint8_t*)buf;
1296 size_t print_size = size < 16 ? size : 16;
1298 for (
size_t i = 0; i < print_size; i++) {
1299 printf(
"%02x ", data[i]);
1303 printf(
"... (%zu more bytes)", size - 16);
1311struct db_builder_internal {
1317struct db_reader_internal {
1326 struct db_builder_internal* builder = (
struct db_builder_internal*)
DB_MALLOC(
sizeof(
struct db_builder_internal));
1327 DB_ASSERT(builder &&
"db_builder_new: memory allocation failed");
1333 builder->data = buf;
1334 builder->capacity = initial_capacity;
1340 DB_ASSERT(buf &&
"db_builder_from_buffer: buf cannot be NULL");
1342 struct db_builder_internal* builder = (
struct db_builder_internal*)
DB_MALLOC(
sizeof(
struct db_builder_internal));
1343 DB_ASSERT(builder &&
"db_builder_from_buffer: memory allocation failed");
1354 DB_ASSERT(builder &&
"db_builder_retain: builder cannot be NULL");
1360 DB_ASSERT(builder_ptr &&
"db_builder_release: builder_ptr cannot be NULL");
1361 if (!*builder_ptr)
return;
1364 *builder_ptr = NULL;
1374 DB_ASSERT(builder_ptr &&
"db_builder_finish: builder_ptr cannot be NULL");
1375 DB_ASSERT(*builder_ptr &&
"db_builder_finish: builder cannot be NULL");
1377 struct db_builder_internal* builder = *builder_ptr;
1381 builder->data = NULL;
1383 *builder_ptr = NULL;
1389 DB_ASSERT(builder &&
"db_builder_size: builder cannot be NULL");
1390 return db_size(builder->data);
1394 DB_ASSERT(builder &&
"db_builder_capacity: builder cannot be NULL");
1395 return builder->capacity;
1399 DB_ASSERT(builder &&
"db_builder_clear: builder cannot be NULL");
1403 builder->data =
db_new(builder->capacity);
1409 DB_ASSERT(builder &&
"db_builder_append_uint8: builder cannot be NULL");
1411 return db_internal_append(&builder->data, &builder->capacity, &value, 1);
1415 DB_ASSERT(builder &&
"db_builder_append_uint16_le: builder cannot be NULL");
1417 uint8_t bytes[2] = {
1418 (uint8_t)(value & 0xFF),
1419 (uint8_t)((value >> 8) & 0xFF)
1422 return db_internal_append(&builder->data, &builder->capacity, bytes, 2);
1426 DB_ASSERT(builder &&
"db_builder_append_uint16_be: builder cannot be NULL");
1428 uint8_t bytes[2] = {
1429 (uint8_t)((value >> 8) & 0xFF),
1430 (uint8_t)(value & 0xFF)
1433 return db_internal_append(&builder->data, &builder->capacity, bytes, 2);
1437 DB_ASSERT(builder &&
"db_builder_append_uint32_le: builder cannot be NULL");
1439 uint8_t bytes[4] = {
1440 (uint8_t)(value & 0xFF),
1441 (uint8_t)((value >> 8) & 0xFF),
1442 (uint8_t)((value >> 16) & 0xFF),
1443 (uint8_t)((value >> 24) & 0xFF)
1446 return db_internal_append(&builder->data, &builder->capacity, bytes, 4);
1450 DB_ASSERT(builder &&
"db_builder_append_uint32_be: builder cannot be NULL");
1452 uint8_t bytes[4] = {
1453 (uint8_t)((value >> 24) & 0xFF),
1454 (uint8_t)((value >> 16) & 0xFF),
1455 (uint8_t)((value >> 8) & 0xFF),
1456 (uint8_t)(value & 0xFF)
1459 return db_internal_append(&builder->data, &builder->capacity, bytes, 4);
1463 DB_ASSERT(builder &&
"db_builder_append_uint64_le: builder cannot be NULL");
1465 uint8_t bytes[8] = {
1466 (uint8_t)(value & 0xFF),
1467 (uint8_t)((value >> 8) & 0xFF),
1468 (uint8_t)((value >> 16) & 0xFF),
1469 (uint8_t)((value >> 24) & 0xFF),
1470 (uint8_t)((value >> 32) & 0xFF),
1471 (uint8_t)((value >> 40) & 0xFF),
1472 (uint8_t)((value >> 48) & 0xFF),
1473 (uint8_t)((value >> 56) & 0xFF)
1476 return db_internal_append(&builder->data, &builder->capacity, bytes, 8);
1480 DB_ASSERT(builder &&
"db_builder_append_uint64_be: builder cannot be NULL");
1482 uint8_t bytes[8] = {
1483 (uint8_t)((value >> 56) & 0xFF),
1484 (uint8_t)((value >> 48) & 0xFF),
1485 (uint8_t)((value >> 40) & 0xFF),
1486 (uint8_t)((value >> 32) & 0xFF),
1487 (uint8_t)((value >> 24) & 0xFF),
1488 (uint8_t)((value >> 16) & 0xFF),
1489 (uint8_t)((value >> 8) & 0xFF),
1490 (uint8_t)(value & 0xFF)
1493 return db_internal_append(&builder->data, &builder->capacity, bytes, 8);
1497 DB_ASSERT(builder &&
"db_builder_append: builder cannot be NULL");
1498 DB_ASSERT((data || size == 0) &&
"db_builder_append: data cannot be NULL when size > 0");
1500 if (size == 0)
return 0;
1502 return db_internal_append(&builder->data, &builder->capacity, data, size);
1506 DB_ASSERT(builder &&
"db_builder_append_cstring: builder cannot be NULL");
1507 DB_ASSERT(str &&
"db_builder_append_cstring: str cannot be NULL");
1509 size_t len = strlen(str);
1514 DB_ASSERT(builder &&
"db_builder_append_buffer: builder cannot be NULL");
1515 DB_ASSERT(buf &&
"db_builder_append_buffer: buf cannot be NULL");
1523 DB_ASSERT(buf &&
"db_reader_new: buf cannot be NULL");
1525 struct db_reader_internal* reader = (
struct db_reader_internal*)
DB_MALLOC(
sizeof(
struct db_reader_internal));
1526 DB_ASSERT(reader &&
"db_reader_new: memory allocation failed");
1530 reader->position = 0;
1536 DB_ASSERT(reader &&
"db_reader_retain: reader cannot be NULL");
1542 DB_ASSERT(reader_ptr &&
"db_reader_release: reader_ptr cannot be NULL");
1543 if (!*reader_ptr)
return;
1561 DB_ASSERT(reader &&
"reader cannot be NULL");
1562 return reader->position;
1566 DB_ASSERT(reader &&
"reader cannot be NULL");
1567 size_t buffer_size = db_meta(reader->buf)->size;
1568 return (reader->position < buffer_size) ? (buffer_size - reader->position) : 0;
1572 DB_ASSERT(reader &&
"reader cannot be NULL");
1577 DB_ASSERT(reader &&
"reader cannot be NULL");
1578 size_t buffer_size = db_meta(reader->buf)->size;
1579 DB_ASSERT(position <= buffer_size &&
"db_reader_seek: cannot seek past buffer end");
1580 reader->position = position;
1584 DB_ASSERT(reader &&
"reader cannot be NULL");
1587 uint8_t value = *(uint8_t*)(reader->buf + reader->position);
1588 reader->position += 1;
1594 DB_ASSERT(reader &&
"reader cannot be NULL");
1597 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1598 uint16_t value = (uint16_t)ptr[0] | ((uint16_t)ptr[1] << 8);
1599 reader->position += 2;
1605 DB_ASSERT(reader &&
"reader cannot be NULL");
1608 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1609 uint16_t value = ((uint16_t)ptr[0] << 8) | (uint16_t)ptr[1];
1610 reader->position += 2;
1616 DB_ASSERT(reader &&
"reader cannot be NULL");
1619 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1620 uint32_t value = (uint32_t)ptr[0] |
1621 ((uint32_t)ptr[1] << 8) |
1622 ((uint32_t)ptr[2] << 16) |
1623 ((uint32_t)ptr[3] << 24);
1624 reader->position += 4;
1630 DB_ASSERT(reader &&
"reader cannot be NULL");
1633 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1634 uint32_t value = ((uint32_t)ptr[0] << 24) |
1635 ((uint32_t)ptr[1] << 16) |
1636 ((uint32_t)ptr[2] << 8) |
1638 reader->position += 4;
1644 DB_ASSERT(reader &&
"reader cannot be NULL");
1647 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1648 uint64_t value = (uint64_t)ptr[0] |
1649 ((uint64_t)ptr[1] << 8) |
1650 ((uint64_t)ptr[2] << 16) |
1651 ((uint64_t)ptr[3] << 24) |
1652 ((uint64_t)ptr[4] << 32) |
1653 ((uint64_t)ptr[5] << 40) |
1654 ((uint64_t)ptr[6] << 48) |
1655 ((uint64_t)ptr[7] << 56);
1656 reader->position += 8;
1662 DB_ASSERT(reader &&
"reader cannot be NULL");
1665 const uint8_t* ptr = (
const uint8_t*)(reader->buf + reader->position);
1666 uint64_t value = ((uint64_t)ptr[0] << 56) |
1667 ((uint64_t)ptr[1] << 48) |
1668 ((uint64_t)ptr[2] << 40) |
1669 ((uint64_t)ptr[3] << 32) |
1670 ((uint64_t)ptr[4] << 24) |
1671 ((uint64_t)ptr[5] << 16) |
1672 ((uint64_t)ptr[6] << 8) |
1674 reader->position += 8;
1680 DB_ASSERT(reader &&
"reader cannot be NULL");
1681 DB_ASSERT((data || size == 0) &&
"db_read_bytes: data cannot be NULL when size > 0");
1685 memcpy(data, reader->buf + reader->position, size);
1686 reader->position += size;
#define DB_REFCOUNT_LOAD(ptr)
Definition dynamic_buffer.h:139
#define DB_DEF
Definition dynamic_buffer.h:153
#define DB_REALLOC
Definition dynamic_buffer.h:111
#define DB_FREE
Definition dynamic_buffer.h:116
#define DB_REFCOUNT_INCREMENT(ptr)
Definition dynamic_buffer.h:140
int db_refcount_t
Definition dynamic_buffer.h:137
#define DB_ASSERT
Definition dynamic_buffer.h:121
#define DB_MALLOC
Definition dynamic_buffer.h:106
char * db_buffer
Buffer handle - points directly to buffer data.
Definition dynamic_buffer.h:173
#define DB_REFCOUNT_DECREMENT(ptr)
Definition dynamic_buffer.h:141
#define DB_REFCOUNT_INIT(n)
Definition dynamic_buffer.h:138
DB_DEF int db_refcount(db_buffer buf)
Get current reference count.
DB_DEF size_t db_capacity(db_buffer buf)
Get current capacity of buffer in bytes.
DB_DEF bool db_is_empty(db_buffer buf)
Check if buffer is empty.
DB_DEF size_t db_size(db_buffer buf)
Get current size of buffer in bytes.
DB_DEF int db_builder_append_uint32_le(db_builder builder, uint32_t value)
Write uint32 value in little-endian format.
DB_DEF int db_builder_append_uint64_be(db_builder builder, uint64_t value)
Write uint64 value in big-endian format.
DB_DEF db_buffer db_builder_finish(db_builder *builder_ptr)
Finalize builder and return the constructed buffer.
DB_DEF int db_builder_append_uint16_be(db_builder builder, uint16_t value)
Write uint16 value in big-endian format.
DB_DEF size_t db_builder_size(db_builder builder)
Get current write position in builder.
DB_DEF db_builder db_builder_new(size_t initial_capacity)
Create a new buffer builder.
DB_DEF int db_builder_append_uint8(db_builder builder, uint8_t value)
Write uint8 value.
DB_DEF void db_builder_clear(db_builder builder)
Clear builder contents.
struct db_builder_internal * db_builder
Opaque builder handle for constructing buffers efficiently.
Definition dynamic_buffer.h:462
DB_DEF db_builder db_builder_from_buffer(db_buffer buf)
Create builder from existing buffer (continues at end)
DB_DEF int db_builder_append(db_builder builder, const void *data, size_t size)
Write raw bytes.
DB_DEF int db_builder_append_buffer(db_builder builder, db_buffer buf)
Append buffer contents.
DB_DEF void db_builder_release(db_builder *builder_ptr)
Decrease builder reference count and potentially free builder.
DB_DEF int db_builder_append_uint16_le(db_builder builder, uint16_t value)
Write uint16 value in little-endian format.
DB_DEF db_builder db_builder_retain(db_builder builder)
Increase builder reference count (share ownership)
DB_DEF int db_builder_append_uint64_le(db_builder builder, uint64_t value)
Write uint64 value in little-endian format.
DB_DEF int db_builder_append_uint32_be(db_builder builder, uint32_t value)
Write uint32 value in big-endian format.
DB_DEF size_t db_builder_capacity(db_builder builder)
Get current capacity of builder.
DB_DEF int db_builder_append_cstring(db_builder builder, const char *str)
Write null-terminated string (without null terminator)
DB_DEF int db_compare(db_buffer buf1, db_buffer buf2)
Compare buffer contents lexicographically.
DB_DEF bool db_equals(db_buffer buf1, db_buffer buf2)
Compare two buffers for equality.
DB_DEF db_buffer db_concat(db_buffer buf1, db_buffer buf2)
Concatenate two buffers into a new buffer.
DB_DEF db_buffer db_concat_many(db_buffer *buffers, size_t count)
Concatenate multiple buffers into a new buffer.
DB_DEF ssize_t db_read_fd(db_buffer *buf_ptr, int fd, size_t max_bytes)
Read data from file descriptor into buffer.
DB_DEF db_buffer db_read_file(const char *filename)
Read entire file into a new buffer.
DB_DEF ssize_t db_write_fd(db_buffer buf, int fd)
Write buffer contents to file descriptor.
DB_DEF bool db_write_file(db_buffer buf, const char *filename)
Write buffer contents to file.
DB_DEF db_buffer db_retain(db_buffer buf)
Increase reference count (share ownership)
DB_DEF db_buffer db_new_with_data(const void *data, size_t size)
Create a new buffer initialized with data (copies the data)
DB_DEF db_buffer db_new_from_owned_data(void *data, size_t size, size_t capacity)
Create a new buffer by copying existing data.
DB_DEF void db_release(db_buffer *buf_ptr)
Decrease reference count and potentially free buffer.
DB_DEF db_buffer db_new(size_t capacity)
Create a new empty buffer with specified capacity.
DB_DEF db_buffer db_append(db_buffer buf, const void *data, size_t size)
Create new buffer with data appended.
DB_DEF uint64_t db_read_uint64_le(db_reader reader)
Read uint64 value in little-endian format.
DB_DEF size_t db_reader_remaining(db_reader reader)
Get number of bytes remaining.
DB_DEF db_reader db_reader_new(db_buffer buf)
Create a new buffer reader.
DB_DEF uint64_t db_read_uint64_be(db_reader reader)
Read uint64 value in big-endian format.
DB_DEF void db_read_bytes(db_reader reader, void *data, size_t size)
Read raw bytes.
DB_DEF void db_reader_release(db_reader *reader_ptr)
Decrease reader reference count and potentially free reader.
struct db_reader_internal * db_reader
Opaque reader handle for parsing buffers.
Definition dynamic_buffer.h:621
DB_DEF size_t db_reader_position(db_reader reader)
Get current read position.
DB_DEF uint16_t db_read_uint16_le(db_reader reader)
Read uint16 value in little-endian format.
DB_DEF uint8_t db_read_uint8(db_reader reader)
Read uint8 value.
DB_DEF void db_reader_free(db_reader *reader_ptr)
Free reader resources (legacy name, use db_reader_release instead)
DB_DEF db_reader db_reader_retain(db_reader reader)
Increase reader reference count (share ownership)
DB_DEF uint16_t db_read_uint16_be(db_reader reader)
Read uint16 value in big-endian format.
DB_DEF void db_reader_seek(db_reader reader, size_t position)
Seek to specific position.
DB_DEF uint32_t db_read_uint32_le(db_reader reader)
Read uint32 value in little-endian format.
DB_DEF bool db_reader_can_read(db_reader reader, size_t bytes)
Check if reader can read specified number of bytes.
DB_DEF uint32_t db_read_uint32_be(db_reader reader)
Read uint32 value in big-endian format.
DB_DEF db_buffer db_slice(db_buffer buf, size_t offset, size_t length)
Create a slice of the buffer (creates independent copy)
DB_DEF db_buffer db_slice_from(db_buffer buf, size_t offset)
Create a slice from offset to end of buffer.
DB_DEF db_buffer db_slice_to(db_buffer buf, size_t length)
Create a slice from start to specified length.
DB_DEF db_buffer db_to_hex(db_buffer buf, bool uppercase)
Create a hexadecimal representation of buffer contents.
DB_DEF db_buffer db_from_hex(const char *hex_string, size_t length)
Create buffer from hexadecimal string.
DB_DEF void db_debug_print(db_buffer buf, const char *label)
Print buffer information for debugging.