Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json: Hash-only fieldname support #916

Merged
merged 11 commits into from
Jul 4, 2024
4 changes: 2 additions & 2 deletions apps/utilities/lsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ static JsonVal lsp_maybe_field(LspContext* ctx, const JsonVal val, const String
if (sentinel_check(val) || json_type(ctx->jDoc, val) != JsonType_Object) {
return sentinel_u32;
}
return json_field(ctx->jDoc, val, fieldName);
return json_field(ctx->jDoc, val, string_hash(fieldName));
}

static JsonVal lsp_maybe_elem(LspContext* ctx, const JsonVal val, const u32 index) {
Expand Down Expand Up @@ -1222,7 +1222,7 @@ static i32 lsp_run_stdio(const ScriptBinder* scriptBinder) {
const String content = lsp_read_sized(&ctx, header.contentLength);

JsonResult jsonResult;
json_read(jDoc, content, &jsonResult);
json_read(jDoc, content, JsonReadFlags_None, &jsonResult);
if (UNLIKELY(jsonResult.type == JsonResultType_Fail)) {
const String jsonErr = json_error_str(jsonResult.error);
file_write_sync(g_fileStdErr, fmt_write_scratch("lsp: Json-Error: {}\n", fmt_text(jsonErr)));
Expand Down
48 changes: 24 additions & 24 deletions libs/asset/src/loader_mesh_gltf.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ static bool gltf_json_field_u32(GltfLoad* ld, const JsonVal v, const String name
if (!gltf_json_check(ld, v, JsonType_Object)) {
return false;
}
const JsonVal jField = json_field(ld->jDoc, v, name);
const JsonVal jField = json_field(ld->jDoc, v, string_hash(name));
if (!gltf_json_check(ld, jField, JsonType_Number)) {
return false;
}
Expand All @@ -305,7 +305,7 @@ static bool gltf_json_field_str(GltfLoad* ld, const JsonVal v, const String name
if (!gltf_json_check(ld, v, JsonType_Object)) {
return false;
}
const JsonVal jField = json_field(ld->jDoc, v, name);
const JsonVal jField = json_field(ld->jDoc, v, string_hash(name));
if (!gltf_json_check(ld, jField, JsonType_String)) {
return false;
}
Expand All @@ -317,7 +317,7 @@ static bool gltf_json_field_vec3(GltfLoad* ld, const JsonVal v, const String nam
if (UNLIKELY(json_type(ld->jDoc, v) != JsonType_Object)) {
return false;
}
const JsonVal jField = json_field(ld->jDoc, v, name);
const JsonVal jField = json_field(ld->jDoc, v, string_hash(name));
bool success = true;
for (u32 i = 0; i != 3; ++i) {
success &= gltf_json_elem_f32(ld, jField, i, &out->comps[i]);
Expand All @@ -329,7 +329,7 @@ static bool gltf_json_field_quat(GltfLoad* ld, const JsonVal v, const String nam
if (UNLIKELY(json_type(ld->jDoc, v) != JsonType_Object)) {
return false;
}
const JsonVal jField = json_field(ld->jDoc, v, name);
const JsonVal jField = json_field(ld->jDoc, v, string_hash(name));
bool success = true;
for (u32 i = 0; i != 4; ++i) {
success &= gltf_json_elem_f32(ld, jField, i, &out->comps[i]);
Expand Down Expand Up @@ -509,7 +509,7 @@ static bool gltf_accessor_check(const String typeString, u32* outCompCount) {
}

static void gltf_buffers_acquire(GltfLoad* ld, EcsWorld* w, AssetManagerComp* man, GltfError* err) {
const JsonVal buffers = json_field(ld->jDoc, ld->jRoot, string_lit("buffers"));
const JsonVal buffers = json_field_lit(ld->jDoc, ld->jRoot, "buffers");
if (!(ld->bufferCount = gltf_json_elem_count(ld, buffers))) {
goto Error;
}
Expand Down Expand Up @@ -541,7 +541,7 @@ static void gltf_buffers_acquire(GltfLoad* ld, EcsWorld* w, AssetManagerComp* ma
}

static void gltf_parse_views(GltfLoad* ld, GltfError* err) {
const JsonVal views = json_field(ld->jDoc, ld->jRoot, string_lit("bufferViews"));
const JsonVal views = json_field_lit(ld->jDoc, ld->jRoot, "bufferViews");
if (!(ld->viewCount = gltf_json_elem_count(ld, views))) {
goto Error;
}
Expand Down Expand Up @@ -575,7 +575,7 @@ static void gltf_parse_views(GltfLoad* ld, GltfError* err) {
}

static void gltf_parse_accessors(GltfLoad* ld, GltfError* err) {
const JsonVal accessors = json_field(ld->jDoc, ld->jRoot, string_lit("accessors"));
const JsonVal accessors = json_field_lit(ld->jDoc, ld->jRoot, "accessors");
if (!(ld->accessCount = gltf_json_elem_count(ld, accessors))) {
goto Error;
}
Expand Down Expand Up @@ -626,15 +626,15 @@ static void gltf_parse_primitives(GltfLoad* ld, GltfError* err) {
/**
* NOTE: This loader only supports a single mesh.
*/
const JsonVal meshes = json_field(ld->jDoc, ld->jRoot, string_lit("meshes"));
const JsonVal meshes = json_field_lit(ld->jDoc, ld->jRoot, "meshes");
if (!gltf_json_elem_count(ld, meshes)) {
goto Error;
}
const JsonVal mesh = json_elem_begin(ld->jDoc, meshes);
if (json_type(ld->jDoc, mesh) != JsonType_Object) {
goto Error;
}
const JsonVal primitives = json_field(ld->jDoc, mesh, string_lit("primitives"));
const JsonVal primitives = json_field_lit(ld->jDoc, mesh, "primitives");
if (!(ld->primCount = gltf_json_elem_count(ld, primitives))) {
goto Error;
}
Expand All @@ -652,7 +652,7 @@ static void gltf_parse_primitives(GltfLoad* ld, GltfError* err) {
}
out->accIndices = sentinel_u32; // Indices are optional.
gltf_json_field_u32(ld, primitive, string_lit("indices"), &out->accIndices);
const JsonVal attributes = json_field(ld->jDoc, primitive, string_lit("attributes"));
const JsonVal attributes = json_field_lit(ld->jDoc, primitive, "attributes");
if (!gltf_json_check(ld, attributes, JsonType_Object)) {
goto Error;
}
Expand Down Expand Up @@ -683,20 +683,20 @@ static void gltf_parse_scene_transform(GltfLoad* ld, GltfError* err) {
ld->sceneTrans.r = geo_quat_ident;
ld->sceneTrans.s = geo_vector(1, 1, 1);

const JsonVal scenes = json_field(ld->jDoc, ld->jRoot, string_lit("scenes"));
const JsonVal scenes = json_field_lit(ld->jDoc, ld->jRoot, "scenes");
if (!gltf_json_elem_count(ld, scenes)) {
goto Success; // Scene transform is optional.
}
const JsonVal scene = json_elem_begin(ld->jDoc, scenes);
if (!gltf_json_check(ld, scene, JsonType_Object)) {
goto Error;
}
const JsonVal rootNodes = json_field(ld->jDoc, scene, string_lit("nodes"));
const JsonVal rootNodes = json_field_lit(ld->jDoc, scene, "nodes");
u32 rootNodeIndex;
if (!gltf_json_elem_u32(ld, rootNodes, 0, &rootNodeIndex)) {
goto Success; // Scene transform is optional.
}
const JsonVal nodes = json_field(ld->jDoc, ld->jRoot, string_lit("nodes"));
const JsonVal nodes = json_field_lit(ld->jDoc, ld->jRoot, "nodes");
if (gltf_json_elem_count(ld, nodes) <= rootNodeIndex) {
goto Error;
}
Expand All @@ -718,7 +718,7 @@ static void gltf_parse_skin(GltfLoad* ld, GltfError* err) {
/**
* NOTE: This loader only supports a single skin.
*/
const JsonVal skins = json_field(ld->jDoc, ld->jRoot, string_lit("skins"));
const JsonVal skins = json_field_lit(ld->jDoc, ld->jRoot, "skins");
if (!gltf_json_elem_count(ld, skins)) {
goto Success; // Skinning is optional.
}
Expand All @@ -729,7 +729,7 @@ static void gltf_parse_skin(GltfLoad* ld, GltfError* err) {
if (!gltf_json_field_u32(ld, skin, string_lit("inverseBindMatrices"), &ld->accBindPoseInvMats)) {
goto Error;
}
const JsonVal joints = json_field(ld->jDoc, skin, string_lit("joints"));
const JsonVal joints = json_field_lit(ld->jDoc, skin, "joints");
if (!gltf_json_check(ld, joints, JsonType_Array)) {
goto Error;
}
Expand Down Expand Up @@ -759,7 +759,7 @@ static void gltf_parse_skin(GltfLoad* ld, GltfError* err) {
}

static void gltf_parse_skeleton_nodes(GltfLoad* ld, GltfError* err) {
const JsonVal nodes = json_field(ld->jDoc, ld->jRoot, string_lit("nodes"));
const JsonVal nodes = json_field_lit(ld->jDoc, ld->jRoot, "nodes");
if (!gltf_json_elem_count(ld, nodes)) {
goto Error;
}
Expand All @@ -776,7 +776,7 @@ static void gltf_parse_skeleton_nodes(GltfLoad* ld, GltfError* err) {
gltf_json_name(ld, node, &out->nameHash);
gltf_json_transform(ld, node, &out->trans);

const JsonVal children = json_field(ld->jDoc, node, string_lit("children"));
const JsonVal children = json_field_lit(ld->jDoc, node, "children");
if (gltf_json_check(ld, children, JsonType_Array)) {

json_for_elems(ld->jDoc, children, child) {
Expand Down Expand Up @@ -824,7 +824,7 @@ static void gltf_clear_anim_channels(GltfAnim* anim) {
}

static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
const JsonVal animations = json_field(ld->jDoc, ld->jRoot, string_lit("animations"));
const JsonVal animations = json_field_lit(ld->jDoc, ld->jRoot, "animations");
if (!(ld->animCount = gltf_json_elem_count(ld, animations))) {
goto Success; // Animations are optional.
}
Expand All @@ -844,7 +844,7 @@ static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
}
gltf_json_name(ld, anim, &outAnim->nameHash);

const JsonVal samplers = json_field(ld->jDoc, anim, string_lit("samplers"));
const JsonVal samplers = json_field_lit(ld->jDoc, anim, "samplers");
if (!gltf_json_check(ld, samplers, JsonType_Array)) {
goto Error;
}
Expand All @@ -862,7 +862,7 @@ static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
if (++samplerCnt == GltfMaxSamplerCount) {
goto Error;
}
const JsonVal interpolation = json_field(ld->jDoc, sampler, string_lit("interpolation"));
const JsonVal interpolation = json_field_lit(ld->jDoc, sampler, "interpolation");
if (!gltf_json_check(ld, interpolation, JsonType_String)) {
continue; // 'interpolation' is optional, default is 'LINEAR'.
}
Expand All @@ -872,7 +872,7 @@ static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
}
}

const JsonVal channels = json_field(ld->jDoc, anim, string_lit("channels"));
const JsonVal channels = json_field_lit(ld->jDoc, anim, "channels");
if (!gltf_json_elem_count(ld, channels)) {
goto Error;
}
Expand All @@ -888,7 +888,7 @@ static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
goto Error;
}

const JsonVal target = json_field(ld->jDoc, channel, string_lit("target"));
const JsonVal target = json_field_lit(ld->jDoc, channel, "target");
if (!gltf_json_check(ld, target, JsonType_Object)) {
goto Error;
}
Expand All @@ -898,7 +898,7 @@ static void gltf_parse_animations(GltfLoad* ld, GltfError* err) {
if (sentinel_check(jointIdx = gltf_node_to_joint_index(ld, nodeIdx))) {
continue; // Channel animates a node that is not part of the skeleton.
}
const JsonVal path = json_field(ld->jDoc, target, string_lit("path"));
const JsonVal path = json_field_lit(ld->jDoc, target, "path");
if (!gltf_json_check(ld, path, JsonType_String)) {
goto Error;
}
Expand Down Expand Up @@ -1518,7 +1518,7 @@ ecs_module_init(asset_gltf_module) {
void asset_load_gltf(EcsWorld* world, const String id, const EcsEntityId entity, AssetSource* src) {
JsonDoc* jsonDoc = json_create(g_allocHeap, 512);
JsonResult jsonRes;
json_read(jsonDoc, src->data, &jsonRes);
json_read(jsonDoc, src->data, JsonReadFlags_HashOnlyFieldNames, &jsonRes);
asset_repo_source_close(src);

if (jsonRes.type != JsonResultType_Success) {
Expand Down
33 changes: 21 additions & 12 deletions libs/data/src/read_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ static void data_register_alloc(const ReadCtx* ctx, const Mem allocation) {
*dynarray_push_t(ctx->allocations, Mem) = allocation;
}

static const DataDeclField* data_field_by_name(const DataDeclStruct* data, const String name) {
const StringHash nameHash = string_hash(name);
static const DataDeclField* data_field_by_name(const DataDeclStruct* data, const StringHash name) {
dynarray_for_t(&data->fields, DataDeclField, fieldDecl) {
if (fieldDecl->id.hash == nameHash) {
if (fieldDecl->id.hash == name) {
return fieldDecl;
}
}
Expand Down Expand Up @@ -189,7 +188,7 @@ static void data_read_json_struct(const ReadCtx* ctx, DataReadResult* res, u32 f
mem_set(ctx->data, 0); // Initialize non-specified memory to zero.

dynarray_for_t(&decl->val_struct.fields, DataDeclField, fieldDecl) {
const JsonVal fieldVal = json_field(ctx->doc, ctx->val, fieldDecl->id.name);
const JsonVal fieldVal = json_field(ctx->doc, ctx->val, fieldDecl->id.hash);

if (sentinel_check(fieldVal)) {
if (fieldDecl->meta.flags & DataFlags_Opt) {
Expand Down Expand Up @@ -223,8 +222,18 @@ static void data_read_json_struct(const ReadCtx* ctx, DataReadResult* res, u32 f

if (UNLIKELY(fieldsRead != json_field_count(ctx->doc, ctx->val))) {
json_for_fields(ctx->doc, ctx->val, field) {
if (!data_field_by_name(&decl->val_struct, field.name)) {
*res = result_fail(DataReadError_UnknownField, "Unknown field: '{}'", fmt_text(field.name));
const StringHash nameHash = json_string_hash(ctx->doc, field.name);
if (!data_field_by_name(&decl->val_struct, nameHash)) {
String name = json_string(ctx->doc, field.name);
if (string_is_empty(name)) {
// Field uses a hash-only name; attempt to retrieve the name from the global string-table.
name = stringtable_lookup(g_stringtable, nameHash);
}
if (string_is_empty(name)) {
*res = result_fail(DataReadError_UnknownField, "Unknown field: '{}'", fmt_int(nameHash));
} else {
*res = result_fail(DataReadError_UnknownField, "Unknown field: '{}'", fmt_text(name));
}
return;
}
}
Expand All @@ -236,7 +245,7 @@ static void data_read_json_struct(const ReadCtx* ctx, DataReadResult* res, u32 f

static const DataDeclChoice* data_read_json_union_choice(const ReadCtx* ctx, DataReadResult* res) {
const DataDecl* decl = data_decl(ctx->reg, ctx->meta.type);
const JsonVal typeVal = json_field(ctx->doc, ctx->val, string_lit("$type"));
const JsonVal typeVal = json_field_lit(ctx->doc, ctx->val, "$type");

if (UNLIKELY(sentinel_check(typeVal))) {
*res = result_fail(DataReadError_UnionTypeMissing, "Union is missing a '$type' field");
Expand All @@ -247,7 +256,7 @@ static const DataDeclChoice* data_read_json_union_choice(const ReadCtx* ctx, Dat
return null;
}

const StringHash valueHash = string_hash(json_string(ctx->doc, typeVal));
const StringHash valueHash = json_string_hash(ctx->doc, typeVal);
dynarray_for_t(&decl->val_union.choices, DataDeclChoice, choice) {
if (choice->id.hash == valueHash) {
*res = result_success();
Expand Down Expand Up @@ -277,7 +286,7 @@ static void data_read_json_union(const ReadCtx* ctx, DataReadResult* res) {

*data_union_tag(&decl->val_union, ctx->data) = choice->tag;

const JsonVal nameVal = json_field(ctx->doc, ctx->val, string_lit("$name"));
const JsonVal nameVal = json_field_lit(ctx->doc, ctx->val, "$name");
if (!sentinel_check(nameVal)) {
if (UNLIKELY(json_type(ctx->doc, nameVal) != JsonType_String)) {
*res = result_fail(DataReadError_UnionInvalidName, "'$name' field has to be a string");
Expand Down Expand Up @@ -316,7 +325,7 @@ static void data_read_json_union(const ReadCtx* ctx, DataReadResult* res) {
data_read_json_struct(&choiceCtx, res, fieldsRead);
} break;
default: {
const JsonVal dataVal = json_field(ctx->doc, ctx->val, string_lit("$data"));
const JsonVal dataVal = json_field_lit(ctx->doc, ctx->val, "$data");
if (UNLIKELY(sentinel_check(dataVal))) {
*res = result_fail(DataReadError_UnionDataMissing, "Union is missing a '$data' field");
return;
Expand Down Expand Up @@ -351,7 +360,7 @@ static void data_read_json_union(const ReadCtx* ctx, DataReadResult* res) {

static void data_read_json_enum_string(const ReadCtx* ctx, DataReadResult* res) {
const DataDecl* decl = data_decl(ctx->reg, ctx->meta.type);
const StringHash valueHash = string_hash(json_string(ctx->doc, ctx->val));
const StringHash valueHash = json_string_hash(ctx->doc, ctx->val);

dynarray_for_t(&decl->val_enum.consts, DataDeclConst, constDecl) {
if (constDecl->id.hash == valueHash) {
Expand Down Expand Up @@ -539,7 +548,7 @@ String data_read_json(
DynArray allocations = dynarray_create_t(g_allocHeap, Mem, 64);

JsonResult jsonRes;
const String rem = json_read(doc, input, &jsonRes);
const String rem = json_read(doc, input, JsonReadFlags_HashOnlyFieldNames, &jsonRes);
if (jsonRes.type != JsonResultType_Success) {
*res = result_fail(
DataReadError_Malformed,
Expand Down
Loading