From 19deaea93e10e6dc361c555f239c6bbb3b03c114 Mon Sep 17 00:00:00 2001 From: Sara Date: Wed, 13 Sep 2023 10:40:39 +0200 Subject: [PATCH] implemented enum serialization generation --- src/kwil_generate.c | 37 +++++++++++++++++++++++++-- src/kwil_generate.h | 5 ++++ src/kwil_parse.c | 11 +++++--- test_files/header.kwil.h | 51 +++++++++++++++++++++++++++---------- test_files/implementation.c | 29 ++++++++++++++++----- 5 files changed, 106 insertions(+), 27 deletions(-) diff --git a/src/kwil_generate.c b/src/kwil_generate.c index 453f257..119649e 100644 --- a/src/kwil_generate.c +++ b/src/kwil_generate.c @@ -25,6 +25,7 @@ int kwil_typename_to_prefix(const char* restrict type_name, char* out_prefix, si if(len > out_size) { return 1; } + // generate a function prefix for a type name strcpy(out_prefix, type_name); @@ -44,7 +45,7 @@ int kwil_header_generate(struct kwil_header_t* self) { setvbuf(file, file_buffer, _IOLBF, 255); if(!file) { - printf("Failed to open kwil header for writing"); + printf("Failed to open %s for writing", filename); free(filename); return 1; } @@ -62,7 +63,8 @@ int kwil_header_generate(struct kwil_header_t* self) { kwil_struct_generate_to_json(&type->struct_type, file, type->type_name); break; case KWIL_TYPE_ENUM: - //kwil_enum_generate_to_string(&type->enum_type, file, type->type_name); + kwil_enum_generate_json_length(&type->enum_type, file, type->type_name); + kwil_enum_generate_to_json(&type->enum_type, file, type->type_name); break; } } @@ -184,3 +186,34 @@ int kwil_field_generate_to_json(struct kwil_field_t* self, FILE* file) { return 0; } +int kwil_enum_generate_json_length(struct kwil_enum_t* self, FILE* file, const char* type_name) { + char prefix[48]; + kwil_typename_to_prefix(type_name, prefix, 47); + fprintf(file, "size_t %s_json_length(enum %s* src) {\\\n" + " switch(*src) {\\\n", prefix, type_name); + for(int option_index = 0; option_index < self->enum_values_len; ++option_index) { + fprintf(file, " case %s: return %zu;\\\n", + self->enum_values[option_index].name, strlen(self->enum_values[option_index].name)); + } + fprintf(file, " }\\\n" + "}\\\n"); + return 0; +} + +int kwil_enum_generate_to_json(struct kwil_enum_t* self, FILE* file, const char* type_name) { + char prefix[48]; + kwil_typename_to_prefix(type_name, prefix, 47); + fprintf(file, "size_t %s_to_json(enum %s* src, char* out) {\\\n" + " switch(*src) {\\\n", prefix, type_name); + + for(int option_index = 0; option_index < self->enum_values_len; ++option_index) { + fprintf(file, " case %s:\\\n" + " return sprintf(out, \"\\\"%s\\\"\");\\\n", + self->enum_values[option_index].name, self->enum_values[option_index].name); + } + + fprintf(file, " }\\\n" + "}\\\n"); + return 0; +} + diff --git a/src/kwil_generate.h b/src/kwil_generate.h index c55ab19..2b4f468 100644 --- a/src/kwil_generate.h +++ b/src/kwil_generate.h @@ -6,8 +6,13 @@ extern int kwil_header_generate(struct kwil_header_t* self); +extern int kwil_struct_generate_json_length(struct kwil_struct_t* self, FILE* file, const char* type_name); extern int kwil_struct_generate_to_json(struct kwil_struct_t* self, FILE* file, const char* type_name); + extern int kwil_field_generate_to_json(struct kwil_field_t* self, FILE* file); + + +extern int kwil_enum_generate_json_length(struct kwil_enum_t* self, FILE* file, const char* type_name); extern int kwil_enum_generate_to_json(struct kwil_enum_t* self, FILE* file, const char* type_name); #endif // !_kwil_generate_H diff --git a/src/kwil_parse.c b/src/kwil_parse.c index e39e2c4..78f2088 100644 --- a/src/kwil_parse.c +++ b/src/kwil_parse.c @@ -56,18 +56,21 @@ int read_typename(FILE* file, char* out_buf, int max_size) { char buffer[7]; buffer[6] = '\0'; - for(int i = 0; i < 6; ++i) { - buffer[i] = fgetc(file); + c = next_non_whitespace(file); + for(int i = 0; i < 6 && (ispunct(c) || isalnum(c)); ++i) { + buffer[i] = c; + c = fgetc(file); } // next line is not a compatible type declaration, // write null terminator and return zero - if(strncmp(buffer, "struct", 7) != 0 && strncmp(buffer, "enum", 4) != 0) { + if(strncmp(buffer, "struct ", 6) != 0 && strncmp(buffer, "enum ", 4) != 0) { *out_buf = '\0'; + printf("WARNING: KWIL_ENUM or KWIL_STRUCT specifier before incompatible declaration.\n"); return 0; } - // ignore the whitespace after "struct" + // ignore the whitespace after "struct" or "enum" c = next_non_whitespace(file); // write all text until the next whitespace or '{' to the out buffer diff --git a/test_files/header.kwil.h b/test_files/header.kwil.h index 049a99f..123b03d 100644 --- a/test_files/header.kwil.h +++ b/test_files/header.kwil.h @@ -1,7 +1,24 @@ #include #define KWIL_GEN_IMPL(...)\ -int struct_A_to_json(struct struct_A* src, char** out_json) {\ - int json_capacity = 2; \ +size_t enum_A_json_length(enum enum_A* src) {\ + switch(*src) {\ + case VALUE_A: return 7;\ + case VALUE_B: return 7;\ + case VALUE_C: return 7;\ + }\ +}\ +size_t enum_A_to_json(enum enum_A* src, char* out) {\ + switch(*src) {\ + case VALUE_A:\ + return sprintf(out, "\"VALUE_A\"");\ + case VALUE_B:\ + return sprintf(out, "\"VALUE_B\"");\ + case VALUE_C:\ + return sprintf(out, "\"VALUE_C\"");\ + }\ +}\ +size_t struct_A_json_length(struct struct_A* src) {\ + size_t json_capacity = 2;\ /* length of b */\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->b);\ /* length of a */\ @@ -10,10 +27,11 @@ int struct_A_to_json(struct struct_A* src, char** out_json) {\ json_capacity += 5 + snprintf(NULL, 0, "%du", src->u);\ /* length of dyn_str */\ json_capacity += 11 + strlen(src->dyn_str);\ - char* json = malloc(json_capacity);\ + return json_capacity;\ +}\ +int struct_A_to_json(struct struct_A* src, char* json) {\ int json_len = 1;\ strcpy(json, "{");\ - *out_json = json;\ /* field: b */\ json_len += sprintf(json + json_len, "\"b\":");\ json_len += sprintf(json + json_len, "%d", src->b);\ @@ -37,10 +55,10 @@ int struct_A_to_json(struct struct_A* src, char** out_json) {\ strcpy(json + json_len, ",");\ ++json_len;\ strcpy(json + json_len - 1, "}");\ - return json_capacity;\ + return json_len;\ }\ -int struct_B_to_json(struct struct_B* src, char** out_json) {\ - int json_capacity = 2; \ +size_t struct_B_json_length(struct struct_B* src) {\ + size_t json_capacity = 2;\ /* length of f */\ json_capacity += 5 + snprintf(NULL, 0, "%f", src->f);\ /* length of i */\ @@ -50,17 +68,18 @@ int struct_B_to_json(struct struct_B* src, char** out_json) {\ /* length of str_static */\ json_capacity += 14 + strlen(src->str_static);\ /* length of other_struct */\ - json_capacity += 16;\ + json_capacity += 16 + struct_A_json_length(&src->other_struct);\ /* length of other_struct_typedef */\ - json_capacity += 24;\ + json_capacity += 24 + struct_A_json_length(&src->other_struct_typedef);\ /* length of other_enum */\ - json_capacity += 14;\ + json_capacity += 14 + enum_A_json_length(&src->other_enum);\ /* length of other_enum_typedef */\ - json_capacity += 22;\ - char* json = malloc(json_capacity);\ + json_capacity += 22 + enum_A_json_length(&src->other_enum_typedef);\ + return json_capacity;\ +}\ +int struct_B_to_json(struct struct_B* src, char* json) {\ int json_len = 1;\ strcpy(json, "{");\ - *out_json = json;\ /* field: f */\ json_len += sprintf(json + json_len, "\"f\":");\ json_len += sprintf(json + json_len, "%f", src->f);\ @@ -87,21 +106,25 @@ int struct_B_to_json(struct struct_B* src, char** out_json) {\ ++json_len;\ /* field: other_struct */\ json_len += sprintf(json + json_len, "\"other_struct\":");\ + json_len += struct_A_to_json(&src->other_struct, json + json_len);\ strcpy(json + json_len, ",");\ ++json_len;\ /* field: other_struct_typedef */\ json_len += sprintf(json + json_len, "\"other_struct_typedef\":");\ + json_len += struct_A_to_json(&src->other_struct_typedef, json + json_len);\ strcpy(json + json_len, ",");\ ++json_len;\ /* field: other_enum */\ json_len += sprintf(json + json_len, "\"other_enum\":");\ + json_len += enum_A_to_json(&src->other_enum, json + json_len);\ strcpy(json + json_len, ",");\ ++json_len;\ /* field: other_enum_typedef */\ json_len += sprintf(json + json_len, "\"other_enum_typedef\":");\ + json_len += enum_A_to_json(&src->other_enum_typedef, json + json_len);\ strcpy(json + json_len, ",");\ ++json_len;\ strcpy(json + json_len - 1, "}");\ - return json_capacity;\ + return json_len;\ }\ diff --git a/test_files/implementation.c b/test_files/implementation.c index 4a75219..06d5d4d 100644 --- a/test_files/implementation.c +++ b/test_files/implementation.c @@ -9,27 +9,42 @@ KWIL_GEN_IMPL() int main(int argc, char* argv[]) { printf("running kwil test\n"); - struct struct_A b = { + + struct struct_A a = { .b = -10, .u = 13, .a = 1.0, .dyn_str = "WHOOAAAAA" }; - char* json = NULL; - int json_len = struct_A_to_json(&b, &json); - printf("allocated %d bytes for json of struct_A\n", json_len); - printf("struct_A as json:\n%s\n", json); + struct struct_B b = { + .f = 123.0, + .f_NOT_KWIL = 0, + .i_NOT_KWIL = 0, + .i = 3, + .str = "SNALE!!", + .other_struct = a, + .other_struct_typedef = { + .b = -20, .u = 13, .a = -3.14, .dyn_str = "AWESOMEE" + } + }; + + int required = struct_B_json_length(&b); + char* json = malloc(required); + int json_len = struct_B_to_json(&b, json); + + printf("allocated %d bytes for json of struct_B\n", required); + printf("struct_B as json:\n%s\n", json); int real_len = strlen(json); free(json); - if(real_len != json_len) { - printf("Json Length (%d) does not match allocated space %d\n", real_len, json_len); + printf("Json Length (%d) does not match allocated space (%d)\n", required, json_len); return 1; } + return 0; }