Asyncify other loaders
This commit is contained in:
@@ -12,7 +12,7 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
|||||||
|
|
||||||
[ASSET_LOADER_TYPE_MESH] = {
|
[ASSET_LOADER_TYPE_MESH] = {
|
||||||
.loadSync = assetMeshLoaderSync,
|
.loadSync = assetMeshLoaderSync,
|
||||||
.loadAsync = NULL,
|
.loadAsync = assetMeshLoaderAsync,
|
||||||
.dispose = assetMeshDispose
|
.dispose = assetMeshDispose
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -24,19 +24,19 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
|||||||
|
|
||||||
[ASSET_LOADER_TYPE_TILESET] = {
|
[ASSET_LOADER_TYPE_TILESET] = {
|
||||||
.loadSync = assetTilesetLoaderSync,
|
.loadSync = assetTilesetLoaderSync,
|
||||||
.loadAsync = NULL,
|
.loadAsync = assetTilesetLoaderAsync,
|
||||||
.dispose = assetTilesetDispose
|
.dispose = assetTilesetDispose
|
||||||
},
|
},
|
||||||
|
|
||||||
[ASSET_LOADER_TYPE_LOCALE] = {
|
[ASSET_LOADER_TYPE_LOCALE] = {
|
||||||
.loadSync = assetLocaleLoaderSync,
|
.loadSync = assetLocaleLoaderSync,
|
||||||
.loadAsync = NULL,
|
.loadAsync = assetLocaleLoaderAsync,
|
||||||
.dispose = assetLocaleDispose
|
.dispose = assetLocaleDispose
|
||||||
},
|
},
|
||||||
|
|
||||||
[ASSET_LOADER_TYPE_JSON] = {
|
[ASSET_LOADER_TYPE_JSON] = {
|
||||||
.loadSync = assetJsonLoaderSync,
|
.loadSync = assetJsonLoaderSync,
|
||||||
.loadAsync = NULL,
|
.loadAsync = assetJsonLoaderAsync,
|
||||||
.dispose = assetJsonDispose
|
.dispose = assetJsonDispose
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,29 +12,28 @@
|
|||||||
#include "asset/loader/assetloading.h"
|
#include "asset/loader/assetloading.h"
|
||||||
#include "asset/loader/assetentry.h"
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
|
||||||
assertNotNull(loading, "Loading cannot be NULL");
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
assertTrue(loading->type == ASSET_LOADER_TYPE_MESH, "Invalid type.");
|
|
||||||
|
if(loading->loading.mesh.state != ASSET_MESH_LOADING_STATE_READ_FILE) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
assetmeshoutput_t *out = &loading->entry->data.mesh;
|
assetmeshoutput_t *out = &loading->entry->data.mesh;
|
||||||
assetfile_t *file = &loading->loading.mesh.file;
|
assetfile_t *file = &loading->loading.mesh.file;
|
||||||
assetmeshinputaxis_t axis = loading->entry->input->mesh;
|
assetmeshinputaxis_t axis = loading->entry->input->mesh;
|
||||||
|
|
||||||
assetLoaderErrorChain(loading, assetFileInit(
|
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
||||||
file, loading->entry->name, NULL, NULL
|
|
||||||
));
|
|
||||||
assetLoaderErrorChain(loading, assetFileOpen(file));
|
assetLoaderErrorChain(loading, assetFileOpen(file));
|
||||||
|
|
||||||
// Skip the 80-byte STL header
|
// Skip the 80-byte STL header.
|
||||||
assetLoaderErrorChain(loading, assetFileRead(file, NULL, 80));
|
assetLoaderErrorChain(loading, assetFileRead(file, NULL, 80));
|
||||||
if(file->lastRead != 80) {
|
if(file->lastRead != 80) {
|
||||||
assetLoaderErrorThrow(loading, "Failed to skip STL header.");
|
assetLoaderErrorThrow(loading, "Failed to skip STL header.");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t triangleCount;
|
uint32_t triangleCount;
|
||||||
assetLoaderErrorChain(
|
assetLoaderErrorChain(loading, assetFileRead(file, &triangleCount, sizeof(uint32_t)));
|
||||||
loading, assetFileRead(file, &triangleCount, sizeof(uint32_t))
|
|
||||||
);
|
|
||||||
if(file->lastRead != sizeof(uint32_t)) {
|
if(file->lastRead != sizeof(uint32_t)) {
|
||||||
assetLoaderErrorThrow(loading, "Failed to read tri count");
|
assetLoaderErrorThrow(loading, "Failed to read tri count");
|
||||||
}
|
}
|
||||||
@@ -76,9 +75,7 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
|||||||
verts[i * 3 + j].uv[1] = 0.0f;
|
verts[i * 3 + j].uv[1] = 0.0f;
|
||||||
|
|
||||||
for(uint8_t k = 0; k < 3; k++) {
|
for(uint8_t k = 0; k < 3; k++) {
|
||||||
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(
|
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(triData.positions[j][k]);
|
||||||
triData.positions[j][k]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(axis) {
|
switch(axis) {
|
||||||
@@ -124,12 +121,42 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
|||||||
}
|
}
|
||||||
assetFileDispose(file);
|
assetFileDispose(file);
|
||||||
|
|
||||||
ret = meshInit(
|
loading->loading.mesh.triangleCount = triangleCount;
|
||||||
&out->mesh, MESH_PRIMITIVE_TYPE_TRIANGLES, triangleCount * 3, verts
|
loading->loading.mesh.state = ASSET_MESH_LOADING_STATE_CREATE_MESH;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
assertTrue(loading->type == ASSET_LOADER_TYPE_MESH, "Invalid type.");
|
||||||
|
|
||||||
|
switch(loading->loading.mesh.state) {
|
||||||
|
case ASSET_MESH_LOADING_STATE_INITIAL:
|
||||||
|
loading->loading.mesh.state = ASSET_MESH_LOADING_STATE_READ_FILE;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
|
||||||
|
errorOk();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSET_MESH_LOADING_STATE_CREATE_MESH:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
assetmeshoutput_t *out = &loading->entry->data.mesh;
|
||||||
|
assertNotNull(out->vertices, "Mesh vertices should have been loaded by now.");
|
||||||
|
|
||||||
|
errorret_t ret = meshInit(
|
||||||
|
&out->mesh,
|
||||||
|
MESH_PRIMITIVE_TYPE_TRIANGLES,
|
||||||
|
loading->loading.mesh.triangleCount * 3,
|
||||||
|
out->vertices
|
||||||
);
|
);
|
||||||
if(errorIsNotOk(ret)) {
|
if(errorIsNotOk(ret)) {
|
||||||
loading->entry->state = ASSET_ENTRY_STATE_ERROR;
|
loading->entry->state = ASSET_ENTRY_STATE_ERROR;
|
||||||
memoryFree(verts);
|
memoryFree(out->vertices);
|
||||||
out->vertices = NULL;
|
out->vertices = NULL;
|
||||||
assetLoaderErrorChain(loading, ret);
|
assetLoaderErrorChain(loading, ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,17 @@ typedef enum {
|
|||||||
|
|
||||||
typedef assetmeshinputaxis_t assetmeshloaderinput_t;
|
typedef assetmeshinputaxis_t assetmeshloaderinput_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_MESH_LOADING_STATE_INITIAL,
|
||||||
|
ASSET_MESH_LOADING_STATE_READ_FILE,
|
||||||
|
ASSET_MESH_LOADING_STATE_CREATE_MESH,
|
||||||
|
ASSET_MESH_LOADING_STATE_DONE
|
||||||
|
} assetmeshloadingstate_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
assetfile_t file;
|
assetfile_t file;
|
||||||
|
assetmeshloadingstate_t state;
|
||||||
|
uint32_t triangleCount;
|
||||||
} assetmeshloaderloading_t;
|
} assetmeshloaderloading_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -44,5 +53,6 @@ typedef struct {
|
|||||||
|
|
||||||
assertStructSize(assetmeshstltriangle_t, 50);
|
assertStructSize(assetmeshstltriangle_t, 50);
|
||||||
|
|
||||||
|
errorret_t assetMeshLoaderAsync(assetloading_t *loading);
|
||||||
errorret_t assetMeshLoaderSync(assetloading_t *loading);
|
errorret_t assetMeshLoaderSync(assetloading_t *loading);
|
||||||
errorret_t assetMeshDispose(assetentry_t *entry);
|
errorret_t assetMeshDispose(assetentry_t *entry);
|
||||||
|
|||||||
@@ -12,67 +12,97 @@
|
|||||||
#include "asset/loader/assetloading.h"
|
#include "asset/loader/assetloading.h"
|
||||||
#include "asset/loader/assetentry.h"
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
|
errorret_t assetTilesetLoaderAsync(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
|
||||||
|
if(loading->loading.tileset.state != ASSET_TILESET_LOADING_STATE_READ_FILE) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(loading->loading.tileset.data, "Data already defined?");
|
||||||
|
|
||||||
|
assetfile_t *file = &loading->loading.tileset.file;
|
||||||
|
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
||||||
|
|
||||||
|
uint8_t *data = memoryAllocate(file->size);
|
||||||
|
assetLoaderErrorChain(loading, assetFileOpen(file));
|
||||||
|
assetLoaderErrorChain(loading, assetFileRead(file, data, file->size));
|
||||||
|
assetLoaderErrorChain(loading, assetFileClose(file));
|
||||||
|
assetLoaderErrorChain(loading, assetFileDispose(file));
|
||||||
|
assertTrue(file->lastRead == file->size, "Failed to read entire tileset file.");
|
||||||
|
|
||||||
|
loading->loading.tileset.data = data;
|
||||||
|
loading->loading.tileset.state = ASSET_TILESET_LOADING_STATE_PARSE;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
errorret_t assetTilesetLoaderSync(assetloading_t *loading) {
|
errorret_t assetTilesetLoaderSync(assetloading_t *loading) {
|
||||||
assertNotNull(loading, "Loading cannot be NULL");
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
assertTrue(loading->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
assertTrue(loading->type == ASSET_LOADER_TYPE_TILESET, "Invalid type.");
|
||||||
|
|
||||||
assetfile_t *file = &loading->loading.tileset.file;
|
switch(loading->loading.tileset.state) {
|
||||||
|
case ASSET_TILESET_LOADING_STATE_INITIAL:
|
||||||
|
loading->loading.tileset.state = ASSET_TILESET_LOADING_STATE_READ_FILE;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
|
||||||
|
errorOk();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSET_TILESET_LOADING_STATE_PARSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *data = loading->loading.tileset.data;
|
||||||
|
assertNotNull(data, "Tileset data should have been loaded by now.");
|
||||||
|
|
||||||
tileset_t *out = &loading->entry->data.tileset;
|
tileset_t *out = &loading->entry->data.tileset;
|
||||||
|
|
||||||
assetLoaderErrorChain(
|
if(data[0] != 'D' || data[1] != 'T' || data[2] != 'F') {
|
||||||
loading, assetFileInit(file, loading->entry->name, NULL, NULL)
|
memoryFree(data);
|
||||||
);
|
|
||||||
|
|
||||||
uint8_t *entire = memoryAllocate(file->size);
|
|
||||||
assetLoaderErrorChain(loading, assetFileOpen(file));
|
|
||||||
assetLoaderErrorChain(loading, assetFileRead(file, entire, file->size));
|
|
||||||
assetLoaderErrorChain(loading, assetFileClose(file));
|
|
||||||
assetLoaderErrorChain(loading, assetFileDispose(file));
|
|
||||||
assertTrue(file->lastRead == file->size, "Failed to read entire file.");
|
|
||||||
|
|
||||||
if(entire[0] != 'D' || entire[1] != 'T' || entire[2] != 'F') {
|
|
||||||
memoryFree(entire);
|
|
||||||
assetLoaderErrorThrow(loading, "Invalid tileset header");
|
assetLoaderErrorThrow(loading, "Invalid tileset header");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entire[3] != 0x00) {
|
if(data[3] != 0x00) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Unsupported tileset version");
|
assetLoaderErrorThrow(loading, "Unsupported tileset version");
|
||||||
}
|
}
|
||||||
|
|
||||||
out->tileWidth = endianLittleToHost16(*(uint16_t *)(entire + 4));
|
out->tileWidth = endianLittleToHost16(*(uint16_t *)(data + 4));
|
||||||
out->tileHeight = endianLittleToHost16(*(uint16_t *)(entire + 6));
|
out->tileHeight = endianLittleToHost16(*(uint16_t *)(data + 6));
|
||||||
out->columns = endianLittleToHost16(*(uint16_t *)(entire + 8));
|
out->columns = endianLittleToHost16(*(uint16_t *)(data + 8));
|
||||||
out->rows = endianLittleToHost16(*(uint16_t *)(entire + 10));
|
out->rows = endianLittleToHost16(*(uint16_t *)(data + 10));
|
||||||
|
|
||||||
if(out->tileWidth == 0) {
|
if(out->tileWidth == 0) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Tile width cannot be 0");
|
assetLoaderErrorThrow(loading, "Tile width cannot be 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(out->tileHeight == 0) {
|
if(out->tileHeight == 0) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Tile height cannot be 0");
|
assetLoaderErrorThrow(loading, "Tile height cannot be 0");
|
||||||
}
|
}
|
||||||
if(out->columns == 0) {
|
if(out->columns == 0) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Column count cannot be 0");
|
assetLoaderErrorThrow(loading, "Column count cannot be 0");
|
||||||
}
|
}
|
||||||
if(out->rows == 0) {
|
if(out->rows == 0) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Row count cannot be 0");
|
assetLoaderErrorThrow(loading, "Row count cannot be 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
out->uv[0] = endianLittleToHostFloat(*(float *)(entire + 16));
|
out->uv[0] = endianLittleToHostFloat(*(float *)(data + 16));
|
||||||
out->uv[1] = endianLittleToHostFloat(*(float *)(entire + 20));
|
out->uv[1] = endianLittleToHostFloat(*(float *)(data + 20));
|
||||||
|
|
||||||
if(out->uv[1] < 0.0f || out->uv[1] > 1.0f) {
|
if(out->uv[1] < 0.0f || out->uv[1] > 1.0f) {
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
assetLoaderErrorThrow(loading, "Invalid v0 value in tileset");
|
assetLoaderErrorThrow(loading, "Invalid v0 value in tileset");
|
||||||
}
|
}
|
||||||
|
|
||||||
out->tileCount = out->columns * out->rows;
|
out->tileCount = out->columns * out->rows;
|
||||||
memoryFree(entire);
|
memoryFree(data);
|
||||||
|
loading->loading.tileset.data = NULL;
|
||||||
|
|
||||||
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -16,11 +16,45 @@ typedef struct {
|
|||||||
void *nothing;
|
void *nothing;
|
||||||
} assettilesetloaderinput_t;
|
} assettilesetloaderinput_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_TILESET_LOADING_STATE_INITIAL,
|
||||||
|
ASSET_TILESET_LOADING_STATE_READ_FILE,
|
||||||
|
ASSET_TILESET_LOADING_STATE_PARSE,
|
||||||
|
ASSET_TILESET_LOADING_STATE_DONE
|
||||||
|
} assettilesetloadingstate_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
assetfile_t file;
|
assetfile_t file;
|
||||||
|
assettilesetloadingstate_t state;
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
} assettilesetloaderloading_t;
|
} assettilesetloaderloading_t;
|
||||||
|
|
||||||
typedef tileset_t assettilesetoutput_t;
|
typedef tileset_t assettilesetoutput_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous loader for tileset assets. Reads the raw DTF file bytes into
|
||||||
|
* the loading buffer so the sync phase can parse without blocking the main
|
||||||
|
* thread on I/O.
|
||||||
|
*
|
||||||
|
* @param loading Loading information for the asset being loaded.
|
||||||
|
* @return Error code indicating success or failure of the load operation.
|
||||||
|
*/
|
||||||
|
errorret_t assetTilesetLoaderAsync(assetloading_t *loading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronous loader for tileset assets. Parses the DTF binary previously
|
||||||
|
* read by the async phase and populates the output tileset_t.
|
||||||
|
*
|
||||||
|
* @param loading Loading information for the asset being loaded.
|
||||||
|
* @return Error code indicating success or failure of the load operation.
|
||||||
|
*/
|
||||||
errorret_t assetTilesetLoaderSync(assetloading_t *loading);
|
errorret_t assetTilesetLoaderSync(assetloading_t *loading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposer for tileset assets.
|
||||||
|
*
|
||||||
|
* @param entry Asset entry containing the tileset to dispose.
|
||||||
|
* @return Error code indicating success or failure of the dispose operation.
|
||||||
|
*/
|
||||||
errorret_t assetTilesetDispose(assetentry_t *entry);
|
errorret_t assetTilesetDispose(assetentry_t *entry);
|
||||||
|
|||||||
@@ -11,40 +11,63 @@
|
|||||||
#include "asset/loader/assetloading.h"
|
#include "asset/loader/assetloading.h"
|
||||||
#include "asset/loader/assetentry.h"
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
errorret_t assetJsonLoaderSync(assetloading_t *loading) {
|
errorret_t assetJsonLoaderAsync(assetloading_t *loading) {
|
||||||
assertNotNull(loading, "Loading cannot be NULL");
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
assertTrue(loading->type == ASSET_LOADER_TYPE_JSON, "Invalid type.");
|
|
||||||
|
if(loading->loading.json.state != ASSET_JSON_LOADING_STATE_READ_FILE) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNull(loading->loading.json.buffer, "Buffer already defined?");
|
||||||
|
|
||||||
assetfile_t *file = &loading->loading.json.file;
|
assetfile_t *file = &loading->loading.json.file;
|
||||||
assetLoaderErrorChain(
|
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
||||||
loading, assetFileInit(file, loading->entry->name, NULL, NULL)
|
|
||||||
);
|
|
||||||
|
|
||||||
if(file->size > ASSET_JSON_FILE_SIZE_MAX) {
|
if(file->size > ASSET_JSON_FILE_SIZE_MAX) {
|
||||||
assetLoaderErrorThrow(loading, "JSON exceeds maximum allowed size");
|
assetLoaderErrorThrow(loading, "JSON exceeds maximum allowed size");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *buffer = memoryAllocate(file->size);
|
uint8_t *buffer = memoryAllocate(file->size);
|
||||||
assetLoaderErrorChain(
|
assetLoaderErrorChain(loading, assetFileOpen(file));
|
||||||
loading, assetFileOpen(file)
|
assetLoaderErrorChain(loading, assetFileRead(file, buffer, file->size));
|
||||||
);
|
|
||||||
assetLoaderErrorChain(
|
|
||||||
loading, assetFileRead(file, buffer, file->size)
|
|
||||||
);
|
|
||||||
assertTrue(file->lastRead == file->size, "Failed to read entire JSON file.");
|
assertTrue(file->lastRead == file->size, "Failed to read entire JSON file.");
|
||||||
assetLoaderErrorChain(
|
assetLoaderErrorChain(loading, assetFileClose(file));
|
||||||
loading, assetFileClose(file)
|
assetLoaderErrorChain(loading, assetFileDispose(file));
|
||||||
);
|
|
||||||
assetLoaderErrorChain(
|
loading->loading.json.buffer = buffer;
|
||||||
loading, assetFileDispose(file)
|
loading->loading.json.state = ASSET_JSON_LOADING_STATE_PARSE;
|
||||||
);
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetJsonLoaderSync(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
assertTrue(loading->type == ASSET_LOADER_TYPE_JSON, "Invalid type.");
|
||||||
|
|
||||||
|
switch(loading->loading.json.state) {
|
||||||
|
case ASSET_JSON_LOADING_STATE_INITIAL:
|
||||||
|
loading->loading.json.state = ASSET_JSON_LOADING_STATE_READ_FILE;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
|
||||||
|
errorOk();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSET_JSON_LOADING_STATE_PARSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *buffer = loading->loading.json.buffer;
|
||||||
|
assertNotNull(buffer, "JSON buffer should have been loaded by now.");
|
||||||
|
|
||||||
loading->entry->data.json = yyjson_read(
|
loading->entry->data.json = yyjson_read(
|
||||||
(char *)buffer,
|
(char *)buffer,
|
||||||
file->size,
|
loading->loading.json.file.size,
|
||||||
YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS
|
YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS
|
||||||
);
|
);
|
||||||
memoryFree(buffer);
|
memoryFree(buffer);
|
||||||
|
loading->loading.json.buffer = NULL;
|
||||||
|
|
||||||
if(!loading->entry->data.json) {
|
if(!loading->entry->data.json) {
|
||||||
assetLoaderErrorThrow(loading, "Failed to parse JSON");
|
assetLoaderErrorThrow(loading, "Failed to parse JSON");
|
||||||
|
|||||||
@@ -15,10 +15,22 @@ typedef struct assetloading_s assetloading_t;
|
|||||||
typedef struct assetentry_s assetentry_t;
|
typedef struct assetentry_s assetentry_t;
|
||||||
|
|
||||||
typedef struct { void *nothing; } assetjsonloaderinput_t;
|
typedef struct { void *nothing; } assetjsonloaderinput_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_JSON_LOADING_STATE_INITIAL,
|
||||||
|
ASSET_JSON_LOADING_STATE_READ_FILE,
|
||||||
|
ASSET_JSON_LOADING_STATE_PARSE,
|
||||||
|
ASSET_JSON_LOADING_STATE_DONE
|
||||||
|
} assetjsonloadingstate_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
assetfile_t file;
|
assetfile_t file;
|
||||||
|
assetjsonloadingstate_t state;
|
||||||
|
uint8_t *buffer;
|
||||||
} assetjsonloaderloading_t;
|
} assetjsonloaderloading_t;
|
||||||
|
|
||||||
typedef yyjson_doc * assetjsonoutput_t;
|
typedef yyjson_doc * assetjsonoutput_t;
|
||||||
|
|
||||||
|
errorret_t assetJsonLoaderAsync(assetloading_t *loading);
|
||||||
errorret_t assetJsonLoaderSync(assetloading_t *loading);
|
errorret_t assetJsonLoaderSync(assetloading_t *loading);
|
||||||
errorret_t assetJsonDispose(assetentry_t *entry);
|
errorret_t assetJsonDispose(assetentry_t *entry);
|
||||||
|
|||||||
@@ -14,9 +14,12 @@
|
|||||||
#include "asset/loader/assetloading.h"
|
#include "asset/loader/assetloading.h"
|
||||||
#include "asset/loader/assetentry.h"
|
#include "asset/loader/assetentry.h"
|
||||||
|
|
||||||
errorret_t assetLocaleLoaderSync(assetloading_t *loading) {
|
errorret_t assetLocaleLoaderAsync(assetloading_t *loading) {
|
||||||
assertNotNull(loading, "Loading cannot be NULL");
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
assertTrue(loading->type == ASSET_LOADER_TYPE_LOCALE, "Invalid type.");
|
|
||||||
|
if(loading->loading.locale.state != ASSET_LOCALE_LOADER_STATE_LOAD_HEADER) {
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
assetlocalefile_t *localeFile = &loading->entry->data.locale;
|
assetlocalefile_t *localeFile = &loading->entry->data.locale;
|
||||||
memoryZero(localeFile, sizeof(assetlocalefile_t));
|
memoryZero(localeFile, sizeof(assetlocalefile_t));
|
||||||
@@ -27,6 +30,29 @@ errorret_t assetLocaleLoaderSync(assetloading_t *loading) {
|
|||||||
assetLoaderErrorChain(loading, assetLocaleGetString(localeFile, "", 0, buffer, sizeof(buffer)));
|
assetLoaderErrorChain(loading, assetLocaleGetString(localeFile, "", 0, buffer, sizeof(buffer)));
|
||||||
assetLoaderErrorChain(loading, assetLocaleParseHeader(localeFile, buffer, sizeof(buffer)));
|
assetLoaderErrorChain(loading, assetLocaleParseHeader(localeFile, buffer, sizeof(buffer)));
|
||||||
|
|
||||||
|
loading->loading.locale.state = ASSET_LOCALE_LOADER_STATE_DONE;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_SYNC;
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetLocaleLoaderSync(assetloading_t *loading) {
|
||||||
|
assertNotNull(loading, "Loading cannot be NULL");
|
||||||
|
assertTrue(loading->type == ASSET_LOADER_TYPE_LOCALE, "Invalid type.");
|
||||||
|
|
||||||
|
switch(loading->loading.locale.state) {
|
||||||
|
case ASSET_LOCALE_LOADER_STATE_INITIAL:
|
||||||
|
loading->loading.locale.state = ASSET_LOCALE_LOADER_STATE_LOAD_HEADER;
|
||||||
|
loading->entry->state = ASSET_ENTRY_STATE_PENDING_ASYNC;
|
||||||
|
errorOk();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASSET_LOCALE_LOADER_STATE_DONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,16 @@ typedef struct assetentry_s assetentry_t;
|
|||||||
/** Input passed to the locale loader — currently unused. */
|
/** Input passed to the locale loader — currently unused. */
|
||||||
typedef struct { void *nothing; } assetlocaleloaderinput_t;
|
typedef struct { void *nothing; } assetlocaleloaderinput_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ASSET_LOCALE_LOADER_STATE_INITIAL,
|
||||||
|
ASSET_LOCALE_LOADER_STATE_LOAD_HEADER,
|
||||||
|
ASSET_LOCALE_LOADER_STATE_DONE
|
||||||
|
} assetlocaleloaderstate_t;
|
||||||
|
|
||||||
/** Per-slot scratch data used while the locale file is loading. */
|
/** Per-slot scratch data used while the locale file is loading. */
|
||||||
typedef struct { void *nothing; } assetlocaleloaderloading_t;
|
typedef struct {
|
||||||
|
assetlocaleloaderstate_t state;
|
||||||
|
} assetlocaleloaderloading_t;
|
||||||
|
|
||||||
/** Maximum number of distinct plural forms a locale file may declare. */
|
/** Maximum number of distinct plural forms a locale file may declare. */
|
||||||
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
||||||
@@ -96,10 +104,19 @@ typedef struct {
|
|||||||
typedef assetlocalefile_t assetlocaleoutput_t;
|
typedef assetlocalefile_t assetlocaleoutput_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronous loader callback. Opens and validates the locale file, reads the
|
* Asynchronous loader callback. Opens the locale file, reads the PO header,
|
||||||
* PO header, and parses plural-form rules. Sets entry state to
|
* and parses plural-form rules. All I/O happens here so the main thread is
|
||||||
* `ASSET_ENTRY_STATE_LOADED` on success or `ASSET_ENTRY_STATE_ERROR` on
|
* not blocked. Sets entry state to `ASSET_ENTRY_STATE_PENDING_SYNC` on
|
||||||
* failure.
|
* success or `ASSET_ENTRY_STATE_ERROR` on failure.
|
||||||
|
*
|
||||||
|
* @param loading The loading slot for this asset entry.
|
||||||
|
* @return OK on success, error otherwise.
|
||||||
|
*/
|
||||||
|
errorret_t assetLocaleLoaderAsync(assetloading_t *loading);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronous loader callback. Confirms the async phase completed and marks
|
||||||
|
* the entry as `ASSET_ENTRY_STATE_LOADED`.
|
||||||
*
|
*
|
||||||
* @param loading The loading slot for this asset entry.
|
* @param loading The loading slot for this asset entry.
|
||||||
* @return OK on success, error otherwise.
|
* @return OK on success, error otherwise.
|
||||||
|
|||||||
Reference in New Issue
Block a user