Compare commits
2 Commits
251adf906b
...
fb97037243
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fb97037243 | ||
![]() |
1476dbdd57 |
40
README.md
40
README.md
@ -97,7 +97,45 @@ The library is meant to be embedded directly into another project.
|
||||
|
||||
## Writing example
|
||||
|
||||
TBA
|
||||
#include"eebie/writer.h"
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
|
||||
static void *on_alloc(EBMLWriter *w, void *p, size_t sz) {
|
||||
return realloc(p, sz);
|
||||
}
|
||||
|
||||
static size_t on_write(EBMLWriter *w, const void *p, size_t sz) {
|
||||
FILE *fp = w->ud;
|
||||
|
||||
return fwrite(p, 1, sz, fp);
|
||||
}
|
||||
|
||||
int main() {
|
||||
EBMLWriter w;
|
||||
ebml_writer_init(&w);
|
||||
|
||||
FILE *output = fopen("test.ebml", "wb");
|
||||
w.ud = output;
|
||||
|
||||
w.eventWrite = on_write;
|
||||
w.eventAlloc = on_alloc;
|
||||
|
||||
ebml_writer_push(&w, 0x1A45DFA3);
|
||||
ebml_writer_put(&w, 0x4286, EBML_UNSIGNED_INTEGER, (EBMLPrimitive) {.uInt = 1});
|
||||
ebml_writer_put(&w, 0x4282, EBML_STRING, (EBMLPrimitive) {.string = "excrement"});
|
||||
ebml_writer_pop(&w);
|
||||
|
||||
// Unknown-sized element must not have corresponding pop
|
||||
ebml_writer_push_ind(&w, 0x18538067);
|
||||
|
||||
ebml_writer_put(&w, 0x4123, EBML_STRING, (EBMLPrimitive) {.string = "yodel"});
|
||||
|
||||
while(!ebml_writer_flush(&w));
|
||||
|
||||
fclose(output);
|
||||
}
|
||||
|
||||
## `schemagen`
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user