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] = {
|
||||
.loadSync = assetMeshLoaderSync,
|
||||
.loadAsync = NULL,
|
||||
.loadAsync = assetMeshLoaderAsync,
|
||||
.dispose = assetMeshDispose
|
||||
},
|
||||
|
||||
@@ -24,19 +24,19 @@ assetloadercallbacks_t ASSET_LOADER_CALLBACKS[ASSET_LOADER_TYPE_COUNT] = {
|
||||
|
||||
[ASSET_LOADER_TYPE_TILESET] = {
|
||||
.loadSync = assetTilesetLoaderSync,
|
||||
.loadAsync = NULL,
|
||||
.loadAsync = assetTilesetLoaderAsync,
|
||||
.dispose = assetTilesetDispose
|
||||
},
|
||||
|
||||
[ASSET_LOADER_TYPE_LOCALE] = {
|
||||
.loadSync = assetLocaleLoaderSync,
|
||||
.loadAsync = NULL,
|
||||
.loadAsync = assetLocaleLoaderAsync,
|
||||
.dispose = assetLocaleDispose
|
||||
},
|
||||
|
||||
[ASSET_LOADER_TYPE_JSON] = {
|
||||
.loadSync = assetJsonLoaderSync,
|
||||
.loadAsync = NULL,
|
||||
.loadAsync = assetJsonLoaderAsync,
|
||||
.dispose = assetJsonDispose
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,29 +12,28 @@
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "asset/loader/assetentry.h"
|
||||
|
||||
errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
||||
errorret_t assetMeshLoaderAsync(assetloading_t *loading) {
|
||||
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;
|
||||
assetfile_t *file = &loading->loading.mesh.file;
|
||||
assetmeshinputaxis_t axis = loading->entry->input->mesh;
|
||||
|
||||
assetLoaderErrorChain(loading, assetFileInit(
|
||||
file, loading->entry->name, NULL, NULL
|
||||
));
|
||||
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
||||
assetLoaderErrorChain(loading, assetFileOpen(file));
|
||||
|
||||
// Skip the 80-byte STL header
|
||||
// Skip the 80-byte STL header.
|
||||
assetLoaderErrorChain(loading, assetFileRead(file, NULL, 80));
|
||||
if(file->lastRead != 80) {
|
||||
assetLoaderErrorThrow(loading, "Failed to skip STL header.");
|
||||
}
|
||||
|
||||
uint32_t triangleCount;
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileRead(file, &triangleCount, sizeof(uint32_t))
|
||||
);
|
||||
assetLoaderErrorChain(loading, assetFileRead(file, &triangleCount, sizeof(uint32_t)));
|
||||
if(file->lastRead != sizeof(uint32_t)) {
|
||||
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;
|
||||
|
||||
for(uint8_t k = 0; k < 3; k++) {
|
||||
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(
|
||||
triData.positions[j][k]
|
||||
);
|
||||
verts[i * 3 + j].pos[k] = endianLittleToHostFloat(triData.positions[j][k]);
|
||||
}
|
||||
|
||||
switch(axis) {
|
||||
@@ -124,12 +121,42 @@ errorret_t assetMeshLoaderSync(assetloading_t *loading) {
|
||||
}
|
||||
assetFileDispose(file);
|
||||
|
||||
ret = meshInit(
|
||||
&out->mesh, MESH_PRIMITIVE_TYPE_TRIANGLES, triangleCount * 3, verts
|
||||
loading->loading.mesh.triangleCount = triangleCount;
|
||||
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)) {
|
||||
loading->entry->state = ASSET_ENTRY_STATE_ERROR;
|
||||
memoryFree(verts);
|
||||
memoryFree(out->vertices);
|
||||
out->vertices = NULL;
|
||||
assetLoaderErrorChain(loading, ret);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,17 @@ typedef enum {
|
||||
|
||||
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 {
|
||||
assetfile_t file;
|
||||
assetmeshloadingstate_t state;
|
||||
uint32_t triangleCount;
|
||||
} assetmeshloaderloading_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -44,5 +53,6 @@ typedef struct {
|
||||
|
||||
assertStructSize(assetmeshstltriangle_t, 50);
|
||||
|
||||
errorret_t assetMeshLoaderAsync(assetloading_t *loading);
|
||||
errorret_t assetMeshLoaderSync(assetloading_t *loading);
|
||||
errorret_t assetMeshDispose(assetentry_t *entry);
|
||||
|
||||
@@ -12,67 +12,97 @@
|
||||
#include "asset/loader/assetloading.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) {
|
||||
assertNotNull(loading, "Loading cannot be NULL");
|
||||
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;
|
||||
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileInit(file, loading->entry->name, NULL, NULL)
|
||||
);
|
||||
|
||||
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);
|
||||
if(data[0] != 'D' || data[1] != 'T' || data[2] != 'F') {
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Invalid tileset header");
|
||||
}
|
||||
|
||||
if(entire[3] != 0x00) {
|
||||
memoryFree(entire);
|
||||
if(data[3] != 0x00) {
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Unsupported tileset version");
|
||||
}
|
||||
|
||||
out->tileWidth = endianLittleToHost16(*(uint16_t *)(entire + 4));
|
||||
out->tileHeight = endianLittleToHost16(*(uint16_t *)(entire + 6));
|
||||
out->columns = endianLittleToHost16(*(uint16_t *)(entire + 8));
|
||||
out->rows = endianLittleToHost16(*(uint16_t *)(entire + 10));
|
||||
out->tileWidth = endianLittleToHost16(*(uint16_t *)(data + 4));
|
||||
out->tileHeight = endianLittleToHost16(*(uint16_t *)(data + 6));
|
||||
out->columns = endianLittleToHost16(*(uint16_t *)(data + 8));
|
||||
out->rows = endianLittleToHost16(*(uint16_t *)(data + 10));
|
||||
|
||||
if(out->tileWidth == 0) {
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Tile width cannot be 0");
|
||||
}
|
||||
|
||||
if(out->tileHeight == 0) {
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Tile height cannot be 0");
|
||||
}
|
||||
if(out->columns == 0) {
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Column count cannot be 0");
|
||||
}
|
||||
if(out->rows == 0) {
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Row count cannot be 0");
|
||||
}
|
||||
|
||||
out->uv[0] = endianLittleToHostFloat(*(float *)(entire + 16));
|
||||
out->uv[1] = endianLittleToHostFloat(*(float *)(entire + 20));
|
||||
out->uv[0] = endianLittleToHostFloat(*(float *)(data + 16));
|
||||
out->uv[1] = endianLittleToHostFloat(*(float *)(data + 20));
|
||||
|
||||
if(out->uv[1] < 0.0f || out->uv[1] > 1.0f) {
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
assetLoaderErrorThrow(loading, "Invalid v0 value in tileset");
|
||||
}
|
||||
|
||||
out->tileCount = out->columns * out->rows;
|
||||
memoryFree(entire);
|
||||
memoryFree(data);
|
||||
loading->loading.tileset.data = NULL;
|
||||
|
||||
loading->entry->state = ASSET_ENTRY_STATE_LOADED;
|
||||
errorOk();
|
||||
|
||||
@@ -16,11 +16,45 @@ typedef struct {
|
||||
void *nothing;
|
||||
} 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 {
|
||||
assetfile_t file;
|
||||
assettilesetloadingstate_t state;
|
||||
|
||||
uint8_t *data;
|
||||
} assettilesetloaderloading_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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -11,40 +11,63 @@
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "asset/loader/assetentry.h"
|
||||
|
||||
errorret_t assetJsonLoaderSync(assetloading_t *loading) {
|
||||
errorret_t assetJsonLoaderAsync(assetloading_t *loading) {
|
||||
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;
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileInit(file, loading->entry->name, NULL, NULL)
|
||||
);
|
||||
assetLoaderErrorChain(loading, assetFileInit(file, loading->entry->name, NULL, NULL));
|
||||
|
||||
if(file->size > ASSET_JSON_FILE_SIZE_MAX) {
|
||||
assetLoaderErrorThrow(loading, "JSON exceeds maximum allowed size");
|
||||
}
|
||||
|
||||
uint8_t *buffer = memoryAllocate(file->size);
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileOpen(file)
|
||||
);
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileRead(file, buffer, file->size)
|
||||
);
|
||||
assetLoaderErrorChain(loading, assetFileOpen(file));
|
||||
assetLoaderErrorChain(loading, assetFileRead(file, buffer, file->size));
|
||||
assertTrue(file->lastRead == file->size, "Failed to read entire JSON file.");
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileClose(file)
|
||||
);
|
||||
assetLoaderErrorChain(
|
||||
loading, assetFileDispose(file)
|
||||
);
|
||||
assetLoaderErrorChain(loading, assetFileClose(file));
|
||||
assetLoaderErrorChain(loading, assetFileDispose(file));
|
||||
|
||||
loading->loading.json.buffer = buffer;
|
||||
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(
|
||||
(char *)buffer,
|
||||
file->size,
|
||||
loading->loading.json.file.size,
|
||||
YYJSON_READ_ALLOW_COMMENTS | YYJSON_READ_ALLOW_TRAILING_COMMAS
|
||||
);
|
||||
memoryFree(buffer);
|
||||
loading->loading.json.buffer = NULL;
|
||||
|
||||
if(!loading->entry->data.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 { 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 {
|
||||
assetfile_t file;
|
||||
assetjsonloadingstate_t state;
|
||||
uint8_t *buffer;
|
||||
} assetjsonloaderloading_t;
|
||||
|
||||
typedef yyjson_doc * assetjsonoutput_t;
|
||||
|
||||
errorret_t assetJsonLoaderAsync(assetloading_t *loading);
|
||||
errorret_t assetJsonLoaderSync(assetloading_t *loading);
|
||||
errorret_t assetJsonDispose(assetentry_t *entry);
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
#include "asset/loader/assetloading.h"
|
||||
#include "asset/loader/assetentry.h"
|
||||
|
||||
errorret_t assetLocaleLoaderSync(assetloading_t *loading) {
|
||||
errorret_t assetLocaleLoaderAsync(assetloading_t *loading) {
|
||||
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;
|
||||
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, 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;
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -14,8 +14,16 @@ typedef struct assetentry_s assetentry_t;
|
||||
/** Input passed to the locale loader — currently unused. */
|
||||
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. */
|
||||
typedef struct { void *nothing; } assetlocaleloaderloading_t;
|
||||
typedef struct {
|
||||
assetlocaleloaderstate_t state;
|
||||
} assetlocaleloaderloading_t;
|
||||
|
||||
/** Maximum number of distinct plural forms a locale file may declare. */
|
||||
#define ASSET_LOCALE_FILE_PLURAL_FORM_COUNT 6
|
||||
@@ -96,10 +104,19 @@ typedef struct {
|
||||
typedef assetlocalefile_t assetlocaleoutput_t;
|
||||
|
||||
/**
|
||||
* Synchronous loader callback. Opens and validates the locale file, reads the
|
||||
* PO header, and parses plural-form rules. Sets entry state to
|
||||
* `ASSET_ENTRY_STATE_LOADED` on success or `ASSET_ENTRY_STATE_ERROR` on
|
||||
* failure.
|
||||
* Asynchronous loader callback. Opens the locale file, reads the PO header,
|
||||
* and parses plural-form rules. All I/O happens here so the main thread is
|
||||
* not blocked. Sets entry state to `ASSET_ENTRY_STATE_PENDING_SYNC` on
|
||||
* 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.
|
||||
* @return OK on success, error otherwise.
|
||||
|
||||
Reference in New Issue
Block a user