Complete writer interface
This commit is contained in:
parent
251adf906b
commit
1476dbdd57
@ -2,6 +2,7 @@
|
|||||||
#define EEBIE_H
|
#define EEBIE_H
|
||||||
|
|
||||||
#include<stdint.h>
|
#include<stdint.h>
|
||||||
|
#include<stddef.h>
|
||||||
|
|
||||||
typedef enum EBMLElementType {
|
typedef enum EBMLElementType {
|
||||||
EBML_SIGNED_INTEGER,
|
EBML_SIGNED_INTEGER,
|
||||||
@ -15,13 +16,18 @@ typedef enum EBMLElementType {
|
|||||||
EBML_BINARY,
|
EBML_BINARY,
|
||||||
} EBMLElementType;
|
} EBMLElementType;
|
||||||
|
|
||||||
|
typedef struct EBMLBinary {
|
||||||
|
uint8_t *ptr;
|
||||||
|
size_t length;
|
||||||
|
} EBMLBinary;
|
||||||
|
|
||||||
typedef union EBMLPrimitive {
|
typedef union EBMLPrimitive {
|
||||||
int64_t sInt;
|
int64_t sInt;
|
||||||
uint64_t uInt;
|
uint64_t uInt;
|
||||||
float flt4;
|
float flt4;
|
||||||
double flt8;
|
double flt8;
|
||||||
const char *string;
|
const char *string;
|
||||||
const uint8_t *binary;
|
const EBMLBinary binary;
|
||||||
uint64_t date;
|
uint64_t date;
|
||||||
} EBMLPrimitive;
|
} EBMLPrimitive;
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include<string.h>
|
#include<string.h>
|
||||||
#include<endian.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};
|
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) {
|
static void add(EBMLWriter *this, const void *data, size_t length) {
|
||||||
if(this->bufferLen + length > this->bufferCapacity) {
|
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);
|
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) {
|
void ebml_writer_init(EBMLWriter *this) {
|
||||||
memset(this, 0, sizeof(EBMLWriter));
|
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) {
|
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) {
|
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) {
|
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;
|
len = 8;
|
||||||
} else if(type == EBML_STRING) {
|
} else if(type == EBML_STRING) {
|
||||||
len = strlen(primitive.string);
|
len = strlen(primitive.string);
|
||||||
|
} else if(type == EBML_BINARY) {
|
||||||
|
len = primitive.binary.length;
|
||||||
} else if(type == EBML_DATE) {
|
} else if(type == EBML_DATE) {
|
||||||
len = 8;
|
len = 8;
|
||||||
} else abort();
|
} else assert(0);
|
||||||
|
|
||||||
add_varint(this, encode_int(len));
|
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);
|
add(this, (uint8_t*) &primitive.uInt + 8 - len, len);
|
||||||
} else if(type == EBML_FLOAT4) {
|
} else if(type == EBML_FLOAT4) {
|
||||||
uint32_t fl = *(uint32_t*) &primitive.flt4;
|
uint32_t fl = *(uint32_t*) &primitive.flt4;
|
||||||
|
fl = htobe32(fl);
|
||||||
add(this, &fl, 4);
|
add(this, &fl, 4);
|
||||||
} else if(type == EBML_FLOAT8) {
|
} else if(type == EBML_FLOAT8) {
|
||||||
uint64_t fl = *(uint64_t*) &primitive.flt8;
|
uint64_t fl = *(uint64_t*) &primitive.flt8;
|
||||||
|
fl = htobe64(fl);
|
||||||
add(this, &fl, 8);
|
add(this, &fl, 8);
|
||||||
} else if(type == EBML_STRING) {
|
} else if(type == EBML_STRING) {
|
||||||
add(this, primitive.string, len);
|
add(this, primitive.string, len);
|
||||||
|
} else if(type == EBML_BINARY) {
|
||||||
|
add(this, primitive.binary.ptr, primitive.binary.length);
|
||||||
} else if(type == EBML_DATE) {
|
} else if(type == EBML_DATE) {
|
||||||
add(this, &primitive.date, 8);
|
add(this, &primitive.date, 8);
|
||||||
} else abort();
|
} else assert(0);
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,21 @@
|
|||||||
#include"ebml.h"
|
#include"ebml.h"
|
||||||
|
|
||||||
#include<stddef.h>
|
#include<stddef.h>
|
||||||
|
#include<stdbool.h>
|
||||||
|
|
||||||
#define EBML_WRITE_MAXIMUM_DEPTH 128
|
#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;
|
int currentDepth;
|
||||||
uint64_t stack[EBML_WRITE_MAXIMUM_DEPTH];
|
uint64_t stack[EBML_WRITE_MAXIMUM_DEPTH];
|
||||||
|
|
||||||
EBMLWriteCallback callbackWrite;
|
EBMLEventWrite eventWrite;
|
||||||
|
EBMLEventAlloc eventAlloc;
|
||||||
|
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
size_t bufferLen;
|
size_t bufferLen;
|
||||||
@ -23,10 +28,14 @@ typedef struct {
|
|||||||
} EBMLWriter;
|
} EBMLWriter;
|
||||||
|
|
||||||
void ebml_writer_init(EBMLWriter *this);
|
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_push(EBMLWriter *this, uint64_t id);
|
||||||
void ebml_writer_pop(EBMLWriter *this);
|
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);
|
void ebml_writer_put(EBMLWriter *this, uint64_t id, EBMLElementType type, EBMLPrimitive primitive);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user