#include "../../include/ground.h" #include #include static GroundValue readValue(FILE* f) { GroundValue v = {0}; uint8_t tag; if (fread(&tag, 1, 1, f) != 1) { Ground.Log.Error("failed to read value type in Ground.Bytecode.load"); Ground.Flags.error = true; return v; } switch (tag) { case 0: { v.type.type = GroundType_Int; fread(&v.as.Int, 8, 1, f); break; } case 1: { v.type.type = GroundType_Double; fread(&v.as.Double, 8, 1, f); break; } case 2: { v.type.type = GroundType_Char; fread(&v.as.Char, 1, 1, f); break; } case 3: { v.type.type = GroundType_Bool; fread(&v.as.Bool, 1, 1, f); break; } case 4: { v.type.type = GroundType_String; uint64_t len; fread(&len, 8, 1, f); v.as.String.cstr = malloc(len + 1); if (v.as.String.cstr == NULL) { Ground.Log.Error("malloc failed in Ground.Bytecode.load"); Ground.Flags.error = true; return v; } fread(v.as.String.cstr, 1, len, f); v.as.String.cstr[len] = '\0'; v.as.String.len = len; break; } default: { Ground.Log.Error("unknown value type in Ground.Bytecode.load"); Ground.Flags.error = true; break; } } return v; } GroundBytecode _GroundBytecodeLoad(const char* path) { GroundBytecode bc = {0}; FILE* f = fopen(path, "rb"); if (f == NULL) { Ground.Log.Error("failed to open file for reading in Ground.Bytecode.load"); Ground.Flags.error = true; return bc; } char magic[8]; memset(magic, 0, 8); if (fread(magic, 7, 1, f) != 1 || memcmp(magic, "GRNDbc", 6) != 0) { Ground.Log.Error("bad magic in Ground.Bytecode.load"); Ground.Flags.error = true; fclose(f); return bc; } uint32_t version; fread(&version, 4, 1, f); uint64_t count; fread(&count, 8, 1, f); if (count > 0) { bc.heap.heap = malloc(sizeof(GroundValue) * count); if (bc.heap.heap == NULL) { Ground.Log.Error("malloc failed in Ground.Bytecode.load"); Ground.Flags.error = true; fclose(f); return bc; } for (uint64_t i = 0; i < count; i++) { bc.heap.heap[i] = readValue(f); if (Ground.Flags.error) { fclose(f); return bc; } } bc.heap.capacity = count; bc.heap.len = count; } fread(&count, 8, 1, f); if (count > 0) { bc.program.at = malloc(sizeof(GroundBytecodeInstruction) * count); if (bc.program.at == NULL) { Ground.Log.Error("malloc failed in Ground.Bytecode.load"); Ground.Flags.error = true; fclose(f); return bc; } bc.program.capacity = count; bc.program.len = count; for (uint64_t i = 0; i < count; i++) { uint8_t type; fread(&type, 1, 1, f); bc.program.at[i].type = (enum GroundInstructionType)type; uint64_t argCount; fread(&argCount, 8, 1, f); if (argCount > 0) { bc.program.at[i].args.at = malloc(sizeof(GroundSize) * argCount); if (bc.program.at[i].args.at == NULL) { Ground.Log.Error("malloc failed in Ground.Bytecode.load"); Ground.Flags.error = true; fclose(f); return bc; } fread(bc.program.at[i].args.at, sizeof(GroundSize), argCount, f); } else { bc.program.at[i].args.at = NULL; } bc.program.at[i].args.len = argCount; bc.program.at[i].args.capacity = argCount; } } fclose(f); return bc; }