From 0bff23e15ea24c5043569dd3984913937cbef9de Mon Sep 17 00:00:00 2001 From: overflowerror Date: Thu, 6 May 2021 14:35:24 +0200 Subject: [PATCH] demarshalling arrays works now --- demo/marshaller.c | 11 +++++++++-- marshaller/codegen.c | 42 ++++++++++++++++++++++++++---------------- src/marshaller.c | 42 +++++++++++++++++++++++++++++++++++++++++- src/marshaller.h | 3 +++ 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/demo/marshaller.c b/demo/marshaller.c index ecd5cdb..4a76607 100644 --- a/demo/marshaller.c +++ b/demo/marshaller.c @@ -16,7 +16,10 @@ int main() { \"user\": {\ \"uid\": 1000,\ \"username\": \"overflowerror\",\ - \"aliases\": null,\ + \"aliases\": [\ + \"foo\",\ + \"bar\"\ + ],\ \"email\": \"overflow@persei.net\"\ }\ }"; @@ -29,7 +32,11 @@ int main() { printf("User.Uid: %lld\n", post->user.uid); printf("User.Username: %s\n", post->user.username); printf("User.Email: %s\n", post->user.email); - printf("\n"); + printf("User.Aliases: "); + for (size_t i = 0; post->user.aliases[i] != NULL; i++) { + printf("%s ", post->user.aliases[i]); + } + printf("\n\n"); free(post->content); post->content = "Just do it."; diff --git a/marshaller/codegen.c b/marshaller/codegen.c index a277d26..ddc23b5 100644 --- a/marshaller/codegen.c +++ b/marshaller/codegen.c @@ -36,7 +36,7 @@ void generatePreamble(FILE* output, char* files[], int fileno) { fprintf(output, "\n"); fprintf(output, "extern void _marshallPanic(const char*, const char*);\n"); - fprintf(output, "extern void _registerMarshaller(int, const char**, jsonValue_t*(*)(void*), void*(*)(jsonValue_t*), void(*)(void*, bool));\n"); + fprintf(output, "extern void _registerMarshaller(int, const char**, size_t, jsonValue_t*(*)(void*), void*(*)(jsonValue_t*), void(*)(void*, bool));\n"); fprintf(output, "\n"); } @@ -121,21 +121,31 @@ char* generateUnmarshallFunction(FILE* output, struct structinfo* info, char* su for (size_t i = 0; i < info->memberno; i++) { struct memberinfo* member = info->members[i]; fprintf(output, "\ttmpValue = json_object_get(v, \"%s\");\n", member->name); - fprintf(output, "\ttmp = _json_unmarshall_value(\"%s\", tmpValue);\n", member->type->type); - fprintf(output, "\tjson_free(tmpValue);\n"); - if (strcmp(member->type->type, "string") == 0) { - fprintf(output, "\td->%s = (char*) tmp;\n", member->name); - } else if (member->type->isPointer) { - fprintf(output, "\td->%s = (%s*) tmp;\n", member->name, member->type->type); + if (member->type->isArray) { + fprintf(output, "\ttmp = _json_unmarshall_array_value(\"%s\", tmpValue);\n", member->type->type); + fprintf(output, "\tjson_free(tmpValue);\n"); + const char* type = member->type->type; + if (strcmp(type, "string") == 0) { + type = "char"; + } + fprintf(output, "\td->%s = (%s**) tmp;\n", member->name, type); } else { - fprintf(output, "\tif (tmp == NULL) {\n"); - fprintf(output, "\t\terrno = EINVAL;\n"); - fprintf(output, "\t\tfree(d);\n"); - fprintf(output, "\t\treturn NULL;\n"); - fprintf(output, "\t} else {\n"); - fprintf(output, "\t\td->%s = *((%s*) tmp);\n", member->name, member->type->type); - fprintf(output, "\t\tfree(tmp);\n"); - fprintf(output, "\t}\n"); + fprintf(output, "\ttmp = _json_unmarshall_value(\"%s\", tmpValue);\n", member->type->type); + fprintf(output, "\tjson_free(tmpValue);\n"); + if (strcmp(member->type->type, "string") == 0) { + fprintf(output, "\td->%s = (char*) tmp;\n", member->name); + } else if (member->type->isPointer) { + fprintf(output, "\td->%s = (%s*) tmp;\n", member->name, member->type->type); + } else { + fprintf(output, "\tif (tmp == NULL) {\n"); + fprintf(output, "\t\terrno = EINVAL;\n"); + fprintf(output, "\t\tfree(d);\n"); + fprintf(output, "\t\treturn NULL;\n"); + fprintf(output, "\t} else {\n"); + fprintf(output, "\t\td->%s = *((%s*) tmp);\n", member->name, member->type->type); + fprintf(output, "\t\tfree(tmp);\n"); + fprintf(output, "\t}\n"); + } } } @@ -199,7 +209,7 @@ void generateCodeStruct(FILE* output, struct structinfo* info) { fprintf(output, "\ttmp[0] = \"%s\";\n", info->names[0]); if (namesno > 1) fprintf(output, "\ttmp[1] = \"%s\";\n", info->names[1]); - fprintf(output, "\t_registerMarshaller(%d, tmp, &%s, &%s, &%s);\n", namesno, marshall, unmarshall, freeStruct); + fprintf(output, "\t_registerMarshaller(%d, tmp, sizeof(%s), &%s, &%s, &%s);\n", namesno, info->names[0], marshall, unmarshall, freeStruct); fprintf(output, "}\n\n"); free(suffix); diff --git a/src/marshaller.c b/src/marshaller.c index 4301939..4721233 100644 --- a/src/marshaller.c +++ b/src/marshaller.c @@ -18,6 +18,7 @@ void _marshallPanic(const char* name, const char* reason) { static struct marshaller { const char* name; + size_t size; jsonValue_t* (*marshaller)(void*); void* (*unmarshaller)(jsonValue_t*); void (*free)(void*, bool); @@ -34,7 +35,7 @@ static struct marshaller* findMarshaller(const char* type) { return NULL; } -void _registerMarshaller(int namesCount, const char** names, jsonValue_t* (*marshaller)(void*), void* (*unmarshaller)(jsonValue_t*), void (*structFree)(void*, bool)) { +void _registerMarshaller(int namesCount, const char** names, size_t size, jsonValue_t* (*marshaller)(void*), void* (*unmarshaller)(jsonValue_t*), void (*structFree)(void*, bool)) { marshallerList = realloc(marshallerList, (sizeof(struct marshaller)) * (marshallerListLength + namesCount)); if (marshallerList == NULL) { _marshallPanic(names[0], NULL); @@ -47,6 +48,7 @@ void _registerMarshaller(int namesCount, const char** names, jsonValue_t* (*mars marshallerList[marshallerListLength++] = (struct marshaller) { .name = names[i], + .size = size, .marshaller = marshaller, .unmarshaller = unmarshaller, .free = structFree @@ -91,6 +93,10 @@ static jsonValue_t* json_marshall_bool(void* value) { } jsonValue_t* _json_marshall_array_value(const char* type, void* value) { + if (value == NULL) { + return json_null(); + } + size_t size; for (size = 0; *(((void**) value) + size) != NULL; size++); @@ -268,6 +274,24 @@ static void* json_unmarshall_string(jsonValue_t* value) { return tmp; } +void* _json_unmarshall_array_value(const char* type, jsonValue_t* value) { + if (value->type != JSON_ARRAY) + return NULL; + + size_t size = value->value.array.size; + + void** array = malloc(sizeof(void*) * (size + 1)); + if (array == NULL) + return NULL; + + for (size_t i = 0; i < size; i++) { + array[i] = _json_unmarshall_value(type, &(value->value.array.entries[i])); + } + array[size] = NULL; + + return array; +} + void* _json_unmarshall_value(const char* type, jsonValue_t* value) { if (value->type == JSON_NULL) { return NULL; @@ -304,11 +328,27 @@ void* _json_unmarshall(const char* type, const char* json) { return NULL; } + if (value->type == JSON_ARRAY) { + json_free(value); + return NULL; + } + void* tmp = _json_unmarshall_value(type, value); json_free(value); return tmp; } +void* _json_unmarshall_array(const char* type, const char* json) { + jsonValue_t* value = json_parse(json); + if (value == NULL) { + return NULL; + } + + void* tmp = _json_unmarshall_array_value(type, value); + json_free(value); + return tmp; +} + void _json_free_struct(const char* type, void* value, bool this) { if (value == NULL) { return; diff --git a/src/marshaller.h b/src/marshaller.h index 5a398eb..a6f5ebf 100644 --- a/src/marshaller.h +++ b/src/marshaller.h @@ -9,13 +9,16 @@ char* _json_marshall(const char* type, void* value); char* _json_marshall_array(const char* type, void* value); void* _json_unmarshall_value(const char* type, jsonValue_t* value); +void* _json_unmarshall_array_value(const char* type, jsonValue_t* value); void* _json_unmarshall(const char* type, const char* json); +void* _json_unmarshall_array(const char* type, const char* json); void _json_free_struct(const char* type, void* value, bool this); #define json_marshall(t, v) _json_marshall(# t, (void*) v) #define json_marshall_array(t, v) _json_marshall_array(# t, (void*) v) #define json_unmarshall(t, j) (t*) _json_unmarshall(#t, j) +#define json_unmarshall_array(t, j) (t*) _json_unmarshall_array(#t, j) #define json_free_struct(t, v) _json_free_struct(#t, v, true)