mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
started cundump.c:cosmoD_undump(); minor fixes
This commit is contained in:
parent
465f4d5e4a
commit
f116efa02c
15
src/cdump.c
15
src/cdump.c
@ -92,18 +92,12 @@ static void writeCObjFunction(DumpState *dstate, CObjFunction *obj)
|
|||||||
writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count);
|
writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count);
|
||||||
|
|
||||||
/* write constants */
|
/* write constants */
|
||||||
|
writeSize(dstate, obj->chunk.constants.count);
|
||||||
for (int i = 0; i < obj->chunk.constants.count; i++) {
|
for (int i = 0; i < obj->chunk.constants.count; i++) {
|
||||||
writeCValue(dstate, obj->chunk.constants.values[i]);
|
writeCValue(dstate, obj->chunk.constants.values[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WRITE_VAR(dstate, type, expression) \
|
|
||||||
{ \
|
|
||||||
type _tmp = expression; \
|
|
||||||
writeBlock(dstate, &_tmp, sizeof(_tmp)); \
|
|
||||||
break; \
|
|
||||||
}
|
|
||||||
|
|
||||||
static void writeCObj(DumpState *dstate, CObj *obj)
|
static void writeCObj(DumpState *dstate, CObj *obj)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -132,6 +126,13 @@ static void writeCObj(DumpState *dstate, CObj *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WRITE_VAR(dstate, type, expression) \
|
||||||
|
{ \
|
||||||
|
type _tmp = expression; \
|
||||||
|
writeBlock(dstate, &_tmp, sizeof(_tmp)); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
static void writeCValue(DumpState *dstate, CValue val)
|
static void writeCValue(DumpState *dstate, CValue val)
|
||||||
{
|
{
|
||||||
CosmoType t = GET_TYPE(val);
|
CosmoType t = GET_TYPE(val);
|
||||||
|
@ -13,6 +13,7 @@ typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const
|
|||||||
|
|
||||||
bool cosmoD_isBigEndian();
|
bool cosmoD_isBigEndian();
|
||||||
|
|
||||||
|
/* returns non-zero on error */
|
||||||
int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData);
|
int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData);
|
||||||
|
|
||||||
#endif
|
#endif
|
194
src/cundump.c
Normal file
194
src/cundump.c
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
#include "cdump.h"
|
||||||
|
#include "cundump.h"
|
||||||
|
#include "cvm.h"
|
||||||
|
#include "cchunk.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CState *state;
|
||||||
|
const void *userData;
|
||||||
|
cosmo_Reader reader;
|
||||||
|
int readerStatus;
|
||||||
|
} UndumpState;
|
||||||
|
|
||||||
|
#define check(e) if (!e) return false;
|
||||||
|
|
||||||
|
static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader,
|
||||||
|
const void *userData)
|
||||||
|
{
|
||||||
|
udstate->state = state;
|
||||||
|
udstate->userData = userData;
|
||||||
|
udstate->reader = reader;
|
||||||
|
udstate->readerStatus = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readBlock(UndumpState *udstate, void *data, size_t size)
|
||||||
|
{
|
||||||
|
if (udstate->readerStatus == 0) {
|
||||||
|
udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return udstate->readerStatus == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readu8(UndumpState *udstate, uint8_t *d)
|
||||||
|
{
|
||||||
|
return readBlock(udstate, d, sizeof(uint8_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readu16(UndumpState *udstate, uint16_t *d)
|
||||||
|
{
|
||||||
|
return readBlock(udstate, d, sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readSize(UndumpState *udstate, size_t *d)
|
||||||
|
{
|
||||||
|
return readBlock(udstate, d, sizeof(size_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readVector(UndumpState *udstate, void **data, size_t *size)
|
||||||
|
{
|
||||||
|
check(readSize(udstate, size));
|
||||||
|
*data = cosmoM_malloc(udstate->state, *size);
|
||||||
|
return readBlock(udstate, *data, *size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define checku8(udstate, d, tmp) \
|
||||||
|
check(readu8(udstate, &tmp)); \
|
||||||
|
if (d != tmp) { \
|
||||||
|
cosmoV_error(udstate->state, "bad header!"); \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkHeader(UndumpState *udstate) {
|
||||||
|
char magic[COSMO_MAGIC_LEN];
|
||||||
|
uint8_t tmp;
|
||||||
|
|
||||||
|
/* check header */
|
||||||
|
readBlock(udstate, magic, COSMO_MAGIC_LEN);
|
||||||
|
if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) {
|
||||||
|
cosmoV_error(udstate->state, "bad header!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after the magic, we read some platform information */
|
||||||
|
checku8(udstate, cosmoD_isBigEndian(), tmp);
|
||||||
|
checku8(udstate, sizeof(cosmo_Number), tmp);
|
||||||
|
checku8(udstate, sizeof(size_t), tmp);
|
||||||
|
checku8(udstate, sizeof(int), tmp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef checku8
|
||||||
|
|
||||||
|
static bool readCObjString(UndumpState *udstate, CObjString **str)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
char *data;
|
||||||
|
|
||||||
|
check(readu32(udstate, &size));
|
||||||
|
if (size == 0) { /* empty string */
|
||||||
|
*str = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = cosmoM_malloc(udstate->state, size+1);
|
||||||
|
check(readBlock(udstate, (void *)&data, size));
|
||||||
|
data[size] = '\0'; /* add NULL-terminator */
|
||||||
|
|
||||||
|
*str = cosmoO_takeString(udstate->state, data, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) {
|
||||||
|
*func = cosmoO_newFunction(udstate->state);
|
||||||
|
|
||||||
|
check(readCObjString(udstate, &(*func)->name));
|
||||||
|
check(readCObjString(udstate, &(*func)->module));
|
||||||
|
|
||||||
|
check(readu32(udstate, &(*func)->args));
|
||||||
|
check(readu32(udstate, &(*func)->upvals));
|
||||||
|
check(readu8(udstate, &(*func)->variadic));
|
||||||
|
|
||||||
|
/* read chunk info */
|
||||||
|
check(readVector(udstate, (void **)&(*func)->chunk.buf, &(*func)->chunk.count));
|
||||||
|
check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, &(*func)->chunk.count));
|
||||||
|
|
||||||
|
/* read constants */
|
||||||
|
size_t constants;
|
||||||
|
check(readSize(udstate, &constants));
|
||||||
|
for (int i = 0; i < constants; i++) {
|
||||||
|
CValue val;
|
||||||
|
check(readCValue(udstate, &val));
|
||||||
|
addConstant(udstate->state, &(*func)->chunk, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readCObj(UndumpState *udstate, CObj **obj)
|
||||||
|
{
|
||||||
|
uint8_t type;
|
||||||
|
check(readu8(udstate, &type));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case COBJ_STRING:
|
||||||
|
return readCObjString(udstate, (CObjString **)obj);
|
||||||
|
case COBJ_FUNCTION:
|
||||||
|
return readCObjFunction(udstate, (CObjFunction **)obj);
|
||||||
|
default:
|
||||||
|
cosmoV_error(udstate->state, "unknown object type!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_VAR(udstate, val, type, creator) \
|
||||||
|
{ \
|
||||||
|
type _tmp; \
|
||||||
|
check(readBlock(udstate, &_tmp, sizeof(type))); \
|
||||||
|
*val = creator(_tmp); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool readCValue(UndumpState *udstate, CValue *val) {
|
||||||
|
uint8_t type;
|
||||||
|
check(readu8(udstate, &type));
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case COSMO_TNUMBER:
|
||||||
|
READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber)
|
||||||
|
case COSMO_TBOOLEAN:
|
||||||
|
READ_VAR(udstate, val, bool, cosmoV_newBoolean)
|
||||||
|
case COSMO_TREF: {
|
||||||
|
CObj *obj;
|
||||||
|
check(readCObj(udstate, (CObj **)&obj));
|
||||||
|
*val = cosmoV_newRef(obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case COSMO_TNIL:
|
||||||
|
*val = cosmoV_newNil();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData) {
|
||||||
|
UndumpState udstate;
|
||||||
|
initUndumpState(state, &udstate, writer, userData);
|
||||||
|
|
||||||
|
if (!checkHeader(&udstate)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readCObjFunction(&udstate, &func)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return udstate.readerStatus;
|
||||||
|
}
|
14
src/cundump.h
Normal file
14
src/cundump.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef COSMO_UNDUMP_H
|
||||||
|
#define COSMO_UNDUMP_H
|
||||||
|
|
||||||
|
#include "cobj.h"
|
||||||
|
#include "cosmo.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud);
|
||||||
|
|
||||||
|
/* returns non-zero on error */
|
||||||
|
int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user