Complete writer interface

This commit is contained in:
Mid 2025-01-04 10:44:33 +02:00
parent 251adf906b
commit 1476dbdd57
3 changed files with 59 additions and 9 deletions

View File

@ -2,6 +2,7 @@
#define EEBIE_H
#include<stdint.h>
#include<stddef.h>
typedef enum EBMLElementType {
EBML_SIGNED_INTEGER,
@ -15,13 +16,18 @@ typedef enum EBMLElementType {
EBML_BINARY,
} EBMLElementType;
typedef struct EBMLBinary {
uint8_t *ptr;
size_t length;
} EBMLBinary;
typedef union EBMLPrimitive {
int64_t sInt;
uint64_t uInt;
float flt4;
double flt8;
const char *string;
const uint8_t *binary;
const EBMLBinary binary;
uint64_t date;
} EBMLPrimitive;

View File

@ -2,7 +2,8 @@
#include<string.h>
#include<endian.h>
#include<stdlib.h>
#include<stddef.h>
#include<assert.h>
static uint64_t VARINT_MASKS[] = {0, 0x80L, 0xC000L, 0xE00000L, 0xF0000000L, 0xF800000000L, 0xFC0000000000L, 0xFE000000000000L, 0L};
@ -41,7 +42,7 @@ static void advance(EBMLWriter *this, uint64_t amount) {
static void add(EBMLWriter *this, const void *data, size_t length) {
if(this->bufferLen + length > this->bufferCapacity) {
this->buffer = realloc(this->buffer, (this->bufferLen + length + 1023) & ~1023);
this->buffer = this->eventAlloc(this, this->buffer, (this->bufferLen + length + 1023) & ~1023);
}
memcpy(this->buffer + this->bufferLen, data, length);
@ -61,8 +62,18 @@ static void add_varint(EBMLWriter *this, uint64_t i) {
void ebml_writer_init(EBMLWriter *this) {
memset(this, 0, sizeof(EBMLWriter));
}
this->buffer = calloc(this->bufferCapacity = 1024, 1);
void ebml_writer_free(EBMLWriter *this) {
this->eventAlloc(this, this->buffer, 0);
}
void ebml_writer_push_ind(EBMLWriter *this, uint64_t id) {
add_varint(this, id);
add(this, &(uint64_t) {htobe64(0x01FFFFFFFFFFFFFFL)}, sizeof(uint64_t)); // UNKNOWN-SIZED ELEMENT
while(!ebml_writer_flush(this));
}
void ebml_writer_push(EBMLWriter *this, uint64_t id) {
@ -74,6 +85,24 @@ void ebml_writer_push(EBMLWriter *this, uint64_t id) {
}
void ebml_writer_pop(EBMLWriter *this) {
this->currentDepth--;
uint64_t newSize = this->stack[this->currentDepth];
uint64_t *s = (uint64_t*) &this->buffer[this->bufferLen - newSize - 8];
*s = htobe64(0x0100000000000000L | newSize);
if(this->currentDepth == 0) {
while(!ebml_writer_flush(this));
}
}
bool ebml_writer_flush(EBMLWriter *this) {
size_t written = this->eventWrite(this, this->buffer, this->bufferLen);
memmove(this->buffer, this->buffer + written, this->bufferLen - written);
this->bufferLen -= written;
return this->bufferLen == 0;
}
void ebml_writer_put(EBMLWriter *this, uint64_t id, EBMLElementType type, EBMLPrimitive primitive) {
@ -89,9 +118,11 @@ void ebml_writer_put(EBMLWriter *this, uint64_t id, EBMLElementType type, EBMLPr
len = 8;
} else if(type == EBML_STRING) {
len = strlen(primitive.string);
} else if(type == EBML_BINARY) {
len = primitive.binary.length;
} else if(type == EBML_DATE) {
len = 8;
} else abort();
} else assert(0);
add_varint(this, encode_int(len));
@ -100,13 +131,17 @@ void ebml_writer_put(EBMLWriter *this, uint64_t id, EBMLElementType type, EBMLPr
add(this, (uint8_t*) &primitive.uInt + 8 - len, len);
} else if(type == EBML_FLOAT4) {
uint32_t fl = *(uint32_t*) &primitive.flt4;
fl = htobe32(fl);
add(this, &fl, 4);
} else if(type == EBML_FLOAT8) {
uint64_t fl = *(uint64_t*) &primitive.flt8;
fl = htobe64(fl);
add(this, &fl, 8);
} else if(type == EBML_STRING) {
add(this, primitive.string, len);
} else if(type == EBML_BINARY) {
add(this, primitive.binary.ptr, primitive.binary.length);
} else if(type == EBML_DATE) {
add(this, &primitive.date, 8);
} else abort();
} else assert(0);
}

View File

@ -4,16 +4,21 @@
#include"ebml.h"
#include<stddef.h>
#include<stdbool.h>
#define EBML_WRITE_MAXIMUM_DEPTH 128
typedef size_t(*EBMLWriteCallback)(void *ud, const void *data, size_t length);
struct EBMLWriter;
typedef struct {
typedef size_t(*EBMLEventWrite)(struct EBMLWriter*, const void *data, size_t length);
typedef void*(*EBMLEventAlloc)(struct EBMLWriter*, void *data, size_t length);
typedef struct EBMLWriter {
int currentDepth;
uint64_t stack[EBML_WRITE_MAXIMUM_DEPTH];
EBMLWriteCallback callbackWrite;
EBMLEventWrite eventWrite;
EBMLEventAlloc eventAlloc;
uint8_t *buffer;
size_t bufferLen;
@ -23,10 +28,14 @@ typedef struct {
} EBMLWriter;
void ebml_writer_init(EBMLWriter *this);
void ebml_writer_free(EBMLWriter *this);
void ebml_writer_push_ind(EBMLWriter *this, uint64_t id);
void ebml_writer_push(EBMLWriter *this, uint64_t id);
void ebml_writer_pop(EBMLWriter *this);
bool ebml_writer_flush(EBMLWriter *this);
void ebml_writer_put(EBMLWriter *this, uint64_t id, EBMLElementType type, EBMLPrimitive primitive);
#endif