`j2s`: Add 'extern' type and ignored fields.

Closes #14.
This commit is contained in:
Jordan Bancino 2023-11-06 14:19:49 -05:00
parent d242597e73
commit 618bcbbac3
2 changed files with 65 additions and 16 deletions

View File

@ -5,6 +5,16 @@ Cytoplasm. It is intended to be updated with every commit that makes a user-faci
change worth reporting in the change log. As such, it changes frequently between
releases. Final change log entries are published as [Releases](releases).
## v0.4.1
### Tools
#### `j2s`
- Added an option to allow additional fields in structures and ignore them in
encoding and decoding. Note that additional fields are totally untouched—they
are not even initialized to a default value.
## v0.4.0
**Released on November 1, 2023**

View File

@ -309,22 +309,23 @@ Main(Array * args)
ArrayAdd(requiredTypes, StrDuplicate(type));
}
typeFieldsVal = HashMapGet(typeObj, "fields");
if (JsonValueType(typeFieldsVal) != JSON_OBJECT)
{
Log(LOG_ERR, "Validation error: 'types.%s.fields' must be an object.", type);
goto finish;
}
typeFields = JsonValueAsObject(typeFieldsVal);
if (StrEquals(typeType, "struct"))
{
typeFieldsVal = HashMapGet(typeObj, "fields");
if (JsonValueType(typeFieldsVal) != JSON_OBJECT)
{
Log(LOG_ERR, "Validation error: 'types.%s.fields' must be an object.", type);
goto finish;
}
typeFields = JsonValueAsObject(typeFieldsVal);
while (HashMapIterate(typeFields, &fieldName, (void **) &fieldVal))
{
char *fieldType;
int isArrType = 0;
JsonValue *requiredVal;
JsonValue *ignoreVal;
if (JsonValueType(fieldVal) != JSON_OBJECT)
{
@ -379,10 +380,26 @@ Main(Array * args)
Log(LOG_ERR, "Validation error: 'types.%s.fields.%s.required' must be a boolean.", type, fieldName);
goto finish;
}
ignoreVal = HashMapGet(fieldObj, "ignore");
if (ignoreVal && JsonValueType(ignoreVal) != JSON_BOOLEAN)
{
Log(LOG_ERR, "Validation error: 'types.%s.fields.%s.ignore' must be a boolean.", type, fieldName);
goto finish;
}
}
}
else if (StrEquals(typeType, "enum"))
{
typeFieldsVal = HashMapGet(typeObj, "fields");
if (JsonValueType(typeFieldsVal) != JSON_OBJECT)
{
Log(LOG_ERR, "Validation error: 'types.%s.fields' must be an object.", type);
goto finish;
}
typeFields = JsonValueAsObject(typeFieldsVal);
while (HashMapIterate(typeFields, &fieldName, (void **) &fieldVal))
{
char *name;
@ -403,16 +420,17 @@ Main(Array * args)
}
}
}
else if (StrEquals(typeType, "extern"))
{
/*
* No code will be generated for this type. We simply assume that it exists.
*/
}
else
{
Log(LOG_ERR, "Validation error: 'types.%s.type' must be 'struct' or 'enum'.", type);
goto finish;
}
/*
* TODO: Add "extern" type that doesn't actually generate any code,
* but trusts the user that it has been generated somewhere else. This
* is effectively "importing" types.
*/
}
sortedNodes = GraphTopologicalSort(dependencyGraph, &sortedNodesLen);
@ -471,6 +489,12 @@ Main(Array * args)
}
typeType = JsonValueAsString(JsonGet(types, 2, type, "type"));
if (StrEquals(typeType, "extern"))
{
continue;
}
fields = JsonValueAsObject(JsonGet(types, 2, type, "fields"));
StreamPrintf(headerFile, "typedef %s %s\n{\n", typeType, type);
@ -615,11 +639,18 @@ Main(Array * args)
{
char *key = ArrayGet(keys, i);
int required = JsonValueAsBoolean(JsonGet(fields, 2, key, "required"));
int ignore = JsonValueAsBoolean(JsonGet(fields, 2, key, "ignore"));
char *fieldType = JsonValueAsString(JsonGet(fields, 2, key, "type"));
int isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum");
JsonType jsonType = isEnum ? JSON_STRING : TypeToJsonType(fieldType);
char *jsonTypeStr = JsonTypeToStr(jsonType);
if (ignore)
{
StreamPrintf(implFile, " /* Ignored field: %s */\n\n", key);
continue;
}
StreamPrintf(implFile, " val = HashMapGet(json, \"%s\");\n", Trim('_', key));
StreamPrintf(implFile, " if (val)\n {\n");
@ -847,6 +878,13 @@ Main(Array * args)
char *key = ArrayGet(keys, i);
char *fieldType = JsonValueAsString(JsonGet(fields, 2, key, "type"));
int isEnum = StrEquals(JsonValueAsString(JsonGet(types, 2, fieldType, "type")), "enum");
int ignore = JsonValueAsBoolean(JsonGet(fields, 2, key, "ignore"));
if (ignore)
{
StreamPrintf(implFile, " /* Ignored field: %s */\n\n", key);
continue;
}
if (StrEquals(fieldType, "array"))
{
@ -1022,8 +1060,9 @@ Main(Array * args)
else
{
/* Ignore primitives but call the appropriate free
* method on declared types */
if (!isEnum && HashMapGet(types, fieldType))
* method on declared types that aren't "extern". */
char *fieldTypeType = JsonValueAsString(JsonGet(types, 2, fieldType, "type"));
if (!isEnum && HashMapGet(types, fieldType) && !StrEquals(fieldTypeType, "extern"))
{
StreamPrintf(implFile, " %sFree(&val->%s);\n", fieldType, key);
}