nostrdb: pull latest, adding flatcc and lmdb
This commit is contained in:
269
nostrdb/flatcc/emitter.c
Normal file
269
nostrdb/flatcc/emitter.c
Normal file
@@ -0,0 +1,269 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "flatcc_rtconfig.h"
|
||||
#include "flatcc_emitter.h"
|
||||
|
||||
static int advance_front(flatcc_emitter_t *E)
|
||||
{
|
||||
flatcc_emitter_page_t *p = 0;
|
||||
|
||||
if (E->front && E->front->prev != E->back) {
|
||||
E->front->prev->page_offset = E->front->page_offset - FLATCC_EMITTER_PAGE_SIZE;
|
||||
E->front = E->front->prev;
|
||||
goto done;
|
||||
}
|
||||
if (!(p = FLATCC_EMITTER_ALLOC(sizeof(flatcc_emitter_page_t)))) {
|
||||
return -1;
|
||||
}
|
||||
E->capacity += FLATCC_EMITTER_PAGE_SIZE;
|
||||
if (E->front) {
|
||||
p->prev = E->back;
|
||||
p->next = E->front;
|
||||
E->front->prev = p;
|
||||
E->back->next = p;
|
||||
E->front = p;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* The first page is shared between front and back to avoid
|
||||
* double unecessary extra allocation.
|
||||
*/
|
||||
E->front = p;
|
||||
E->back = p;
|
||||
p->next = p;
|
||||
p->prev = p;
|
||||
E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_cursor = E->front_cursor;
|
||||
E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_left = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
|
||||
p->page_offset = -(flatbuffers_soffset_t)E->front_left;
|
||||
return 0;
|
||||
done:
|
||||
E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE;
|
||||
E->front_left = FLATCC_EMITTER_PAGE_SIZE;
|
||||
E->front->page_offset = E->front->next->page_offset - FLATCC_EMITTER_PAGE_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int advance_back(flatcc_emitter_t *E)
|
||||
{
|
||||
flatcc_emitter_page_t *p = 0;
|
||||
|
||||
if (E->back && E->back->next != E->front) {
|
||||
E->back = E->back->next;
|
||||
goto done;
|
||||
}
|
||||
if (!(p = FLATCC_EMITTER_ALLOC(sizeof(flatcc_emitter_page_t)))) {
|
||||
return -1;
|
||||
}
|
||||
E->capacity += FLATCC_EMITTER_PAGE_SIZE;
|
||||
if (E->back) {
|
||||
p->prev = E->back;
|
||||
p->next = E->front;
|
||||
E->front->prev = p;
|
||||
E->back->next = p;
|
||||
E->back = p;
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* The first page is shared between front and back to avoid
|
||||
* double unecessary extra allocation.
|
||||
*/
|
||||
E->front = p;
|
||||
E->back = p;
|
||||
p->next = p;
|
||||
p->prev = p;
|
||||
E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_cursor = E->front_cursor;
|
||||
E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_left = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
|
||||
p->page_offset = -(flatbuffers_soffset_t)E->front_left;
|
||||
return 0;
|
||||
done:
|
||||
E->back_cursor = E->back->page;
|
||||
E->back_left = FLATCC_EMITTER_PAGE_SIZE;
|
||||
E->back->page_offset = E->back->prev->page_offset + FLATCC_EMITTER_PAGE_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_front(flatcc_emitter_t *E, uint8_t *data, size_t size)
|
||||
{
|
||||
size_t k;
|
||||
|
||||
data += size;
|
||||
while (size) {
|
||||
k = size;
|
||||
if (k > E->front_left) {
|
||||
k = E->front_left;
|
||||
if (k == 0) {
|
||||
if (advance_front(E)) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
E->front_cursor -= k;
|
||||
E->front_left -= k;
|
||||
data -= k;
|
||||
size -= k;
|
||||
memcpy(E->front_cursor, data, k);
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_back(flatcc_emitter_t *E, uint8_t *data, size_t size)
|
||||
{
|
||||
size_t k;
|
||||
|
||||
while (size) {
|
||||
k = size;
|
||||
if (k > E->back_left) {
|
||||
k = E->back_left;
|
||||
if (k == 0) {
|
||||
if (advance_back(E)) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
memcpy(E->back_cursor, data, k);
|
||||
size -= k;
|
||||
data += k;
|
||||
E->back_cursor += k;
|
||||
E->back_left -= k;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flatcc_emitter_recycle_page(flatcc_emitter_t *E, flatcc_emitter_page_t *p)
|
||||
{
|
||||
if (p == E->front || p == E->back) {
|
||||
return -1;
|
||||
}
|
||||
p->next->prev = p->prev;
|
||||
p->prev->next = p->next;
|
||||
p->prev = E->front->prev;
|
||||
p->next = E->front;
|
||||
p->prev->next = p;
|
||||
p->next->prev = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void flatcc_emitter_reset(flatcc_emitter_t *E)
|
||||
{
|
||||
flatcc_emitter_page_t *p = E->front;
|
||||
|
||||
if (!E->front) {
|
||||
return;
|
||||
}
|
||||
E->back = E->front;
|
||||
E->front_cursor = E->front->page + FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_cursor = E->front_cursor;
|
||||
E->front_left = FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->back_left = FLATCC_EMITTER_PAGE_SIZE - FLATCC_EMITTER_PAGE_SIZE / 2;
|
||||
E->front->page_offset = -(flatbuffers_soffset_t)E->front_left;
|
||||
/* Heuristic to reduce peak allocation over time. */
|
||||
if (E->used_average == 0) {
|
||||
E->used_average = E->used;
|
||||
}
|
||||
E->used_average = E->used_average * 3 / 4 + E->used / 4;
|
||||
E->used = 0;
|
||||
while (E->used_average * 2 < E->capacity && E->back->next != E->front) {
|
||||
/* We deallocate the page after back since it is less likely to be hot in cache. */
|
||||
p = E->back->next;
|
||||
E->back->next = p->next;
|
||||
p->next->prev = E->back;
|
||||
FLATCC_EMITTER_FREE(p);
|
||||
E->capacity -= FLATCC_EMITTER_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void flatcc_emitter_clear(flatcc_emitter_t *E)
|
||||
{
|
||||
flatcc_emitter_page_t *p = E->front;
|
||||
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
p->prev->next = 0;
|
||||
while (p->next) {
|
||||
p = p->next;
|
||||
FLATCC_EMITTER_FREE(p->prev);
|
||||
}
|
||||
FLATCC_EMITTER_FREE(p);
|
||||
memset(E, 0, sizeof(*E));
|
||||
}
|
||||
|
||||
int flatcc_emitter(void *emit_context,
|
||||
const flatcc_iovec_t *iov, int iov_count,
|
||||
flatbuffers_soffset_t offset, size_t len)
|
||||
{
|
||||
flatcc_emitter_t *E = emit_context;
|
||||
uint8_t *p;
|
||||
|
||||
E->used += len;
|
||||
if (offset < 0) {
|
||||
if (len <= E->front_left) {
|
||||
E->front_cursor -= len;
|
||||
E->front_left -= len;
|
||||
p = E->front_cursor;
|
||||
goto copy;
|
||||
}
|
||||
iov += iov_count;
|
||||
while (iov_count--) {
|
||||
--iov;
|
||||
if (copy_front(E, iov->iov_base, iov->iov_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (len <= E->back_left) {
|
||||
p = E->back_cursor;
|
||||
E->back_cursor += len;
|
||||
E->back_left -= len;
|
||||
goto copy;
|
||||
}
|
||||
while (iov_count--) {
|
||||
if (copy_back(E, iov->iov_base, iov->iov_len)) {
|
||||
return -1;
|
||||
}
|
||||
++iov;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
copy:
|
||||
while (iov_count--) {
|
||||
memcpy(p, iov->iov_base, iov->iov_len);
|
||||
p += iov->iov_len;
|
||||
++iov;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *flatcc_emitter_copy_buffer(flatcc_emitter_t *E, void *buf, size_t size)
|
||||
{
|
||||
flatcc_emitter_page_t *p;
|
||||
size_t len;
|
||||
|
||||
if (size < E->used) {
|
||||
return 0;
|
||||
}
|
||||
if (!E->front) {
|
||||
return 0;
|
||||
}
|
||||
if (E->front == E->back) {
|
||||
memcpy(buf, E->front_cursor, E->used);
|
||||
return buf;
|
||||
}
|
||||
len = FLATCC_EMITTER_PAGE_SIZE - E->front_left;
|
||||
memcpy(buf, E->front_cursor, len);
|
||||
buf = (uint8_t *)buf + len;
|
||||
p = E->front->next;
|
||||
while (p != E->back) {
|
||||
memcpy(buf, p->page, FLATCC_EMITTER_PAGE_SIZE);
|
||||
buf = (uint8_t *)buf + FLATCC_EMITTER_PAGE_SIZE;
|
||||
p = p->next;
|
||||
}
|
||||
memcpy(buf, p->page, FLATCC_EMITTER_PAGE_SIZE - E->back_left);
|
||||
return buf;
|
||||
}
|
||||
Reference in New Issue
Block a user