diff --git a/.helix/config.toml b/.helix/config.toml new file mode 100644 index 0000000..100e27b --- /dev/null +++ b/.helix/config.toml @@ -0,0 +1,3 @@ +[keys.normal."+"] +m = ":sh make build" +t = ":sh make test" diff --git a/Makefile b/Makefile index e6ba46d..9e2c356 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,6 @@ build: ##### Compile kwil ##### gcc -o bin/kwil src/**.c -g -Itest_include -Wall -run: test: build ##### Run kwil on test files ##### diff --git a/src/kwil.c b/src/kwil.c index 1d7ba2d..d431a7c 100644 --- a/src/kwil.c +++ b/src/kwil.c @@ -37,7 +37,7 @@ enum kwil_field_tag_t kwil_field_tag_from_string(const char* str) { } else if(strcmp(str, "unsigned") == 0) { return KWIL_FIELD_UNSIGNED; } else { - return KWIL_FIELD_UNKNOWN; + return KWIL_FIELD_CUSTOM; } } @@ -81,7 +81,7 @@ int kwil_free_enum(struct kwil_enum_t* self) { int kwil_init_field(struct kwil_field_t* self, const char* field_name, const char* type_str) { *self = (struct kwil_field_t){ - .type_tag = KWIL_FIELD_UNKNOWN, + .type_tag = KWIL_FIELD_CUSTOM, .type_ptr = NULL, }; diff --git a/src/kwil_def.h b/src/kwil_def.h index 3502418..6a41e1c 100644 --- a/src/kwil_def.h +++ b/src/kwil_def.h @@ -5,12 +5,11 @@ // Type tag for kwil fields enum kwil_field_tag_t { - KWIL_FIELD_UNKNOWN = 0, // the field's type is invalid/not known to kwil KWIL_FIELD_FLOAT = 1, // the field is a float KWIL_FIELD_INT = 2, // the field is an int KWIL_FIELD_UNSIGNED = 3, // the field is an unsigned int KWIL_FIELD_CHAR = 4, // the field is a character - KWIL_FIELD_CUSTOM = 6 // the field is a KWIL_STRUCT or KWIL_ENUM + KWIL_FIELD_CUSTOM = 6, // the field is a KWIL_STRUCT or KWIL_ENUM }; extern enum kwil_field_tag_t kwil_field_tag_from_string(const char* str); diff --git a/src/kwil_deserialize.c b/src/kwil_deserialize.c new file mode 100644 index 0000000..da3aea3 --- /dev/null +++ b/src/kwil_deserialize.c @@ -0,0 +1,119 @@ +#include "kwil_deserialize.h" +#include "kwil_generate.h" +#include + +static +void generate_read_to_comma(FILE* file) { + fprintf(file, " while(*reader == ' ' || *reader == ':') { reader++; }\\\n" + " writer = buffer;\\\n" + " do {\\\n" + " *writer = *reader;\\\n" + " writer++; reader++;\\\n" + " } while(*reader != ',' && *reader != '}');\\\n" + " *writer = '\\0';\\\n"); +} + +static +void generate_read_name(FILE* file) { + fprintf(file, " while(*reader != '\"') { reader++; }\\\n" + " reader++;\\\n" + " writer = buffer;\\\n" + " do {\\\n" + " *writer = *reader;\\\n" + " writer++; reader++;\\\n" + " } while(*reader != '\"');\\\n" + " *writer = '\\0';\\\n" + " do {\\\n" + " reader++;\\\n" + " } while(*reader != ':');\\\n"); +} + +static +void generate_read_field(FILE* file, struct kwil_field_t* field) { + fprintf(file, "if(strcmp(buffer, \"%s\") == 0) {\\\n", field->name_str); + char prefix[48]; + switch(field->type_tag) { + case KWIL_FIELD_CUSTOM: + kwil_typename_to_prefix(field->type_str, prefix, 47); + fprintf(file, " while(*reader != '{' && *reader != '\"') { reader++; }\\\n" + " dest.%s = %s_from_json(reader);\\\n", field->name_str, prefix); + fprintf(file, " counter = 0;\\\n" + " do {\\\n" + " if(*reader == '}') counter--;\\\n" + " else if(*reader == '{') counter++;\\\n" + " reader++;\\\n" + " } while(counter > 0 || (counter == 0 && *reader != ','));\\\n" + " if(*reader == '\\0') {\\\n" + " reader--;\\\n" + " } else {\\\n" + " reader++;\\\n" + " }\\\n"); + break; + case KWIL_FIELD_FLOAT: + generate_read_to_comma(file); + fprintf(file, " dest.%s = atof(buffer);\\\n", field->name_str); + break; + case KWIL_FIELD_INT: + case KWIL_FIELD_UNSIGNED: + generate_read_to_comma(file); + fprintf(file, " dest.%s = atoi(buffer);\\\n", field->name_str); + break; + case KWIL_FIELD_CHAR: + generate_read_to_comma(file); + if(field->array_dynamic) { + fprintf(file, " dest.%s = malloc(strlen(buffer)-1);\\\n" + " dest.%s[0] = '\\0';\\\n", field->name_str, field->name_str); + } + if(field->array_length > 0 || field->array_dynamic) { + fprintf(file, " strncpy(dest.%s, buffer+1, strlen(buffer)-2);\\\n", field->name_str); + } + break; + } + + fprintf(file, " } else "); +} + +int kwil_struct_generate_from_json(struct kwil_struct_t* self, const char* type_name, FILE* file) { + char prefix[48]; + kwil_typename_to_prefix(type_name, prefix, 47); + fprintf(file, "struct %s %s_from_json(const char* json) {\\\n" + " struct %s dest;\\\n" + " memset(&dest, 0x0, sizeof(struct %s));", + type_name, prefix, type_name, type_name); + + fprintf(file, " const char* reader = json;\\\n" + " char buffer[48];\\\n" + " char* writer = buffer;\\\n" + " buffer[47] = '\\0';\\\n" + " int counter = 0;counter = counter;\\\n" + " do {\\\n"); + + generate_read_name(file); + fprintf(file, " "); + for(int field = 0; field < self->fields_len; ++field) { + generate_read_field(file, &self->fields[field]); + } + fprintf(file, " {}\\\n"); + + fprintf(file, " } while(*reader != '}');\\\n"); + fprintf(file, " return dest;\\\n" + "}\\\n"); + + return 0; +} + +int kwil_enum_generate_from_json(struct kwil_enum_t* self, const char* type_name, FILE* file) { + char prefix[48]; + kwil_typename_to_prefix(type_name, prefix, 47); + fprintf(file, "enum %s %s_from_json(const char* json) {\\\n", + type_name, prefix); + fprintf(file, " "); + for(int option = 0; option < self->enum_values_len; ++option) { + fprintf(file, "if(strncmp(\"\\\"%s\\\"\", json, %zu) == 0) {\\\n" + " return %s;\\\n" + " } else ", self->enum_values[option].name, strlen(self->enum_values[option].name) + 1, self->enum_values[option].name); + } + fprintf(file, " { return %s; }\\\n" + "}\\\n", self->enum_values[0].name); + return 0; +} diff --git a/src/kwil_deserialize.h b/src/kwil_deserialize.h new file mode 100644 index 0000000..a93f703 --- /dev/null +++ b/src/kwil_deserialize.h @@ -0,0 +1,10 @@ +#ifndef _kwil_deserialize_H +#define _kwil_deserialize_H + +#include "kwil_def.h" +#include + +int kwil_struct_generate_from_json(struct kwil_struct_t* self, const char* type_name, FILE* file); +int kwil_enum_generate_from_json(struct kwil_enum_t* self, const char* type_name, FILE* file); + +#endif diff --git a/src/kwil_generate.c b/src/kwil_generate.c index d810de0..f640ca4 100644 --- a/src/kwil_generate.c +++ b/src/kwil_generate.c @@ -1,40 +1,10 @@ #include "kwil_generate.h" -#include -#include +#include "kwil_serialize.h" +#include "kwil_deserialize.h" + #include - -static -int kwil_header_generated_file_name(struct kwil_header_t* self, char** out) { - int len = strlen(self->file_name); - char* filename = malloc(len + 5); - strncpy(filename, self->file_name, len-2); - strcpy(filename + len-2, ".kwil.h"); - *out = filename; - return len; -} - -static -int kwil_typename_to_prefix(const char* restrict type_name, char* out_prefix, size_t out_size) { - if(strncmp("enum ", type_name, 5) == 0) { - type_name += 5; - } else if(strncmp("struct ", type_name, 7) == 0) { - type_name += 7; - } - - int len = strlen(type_name); - if(len > out_size) { - return 1; - } - - // generate a function prefix for a type name - strcpy(out_prefix, type_name); - - // remove _t postfix if relevant - if(strcmp(out_prefix + len -3, "_t") == 0) { - *(out_prefix + len - 3) = '\0'; - } - return strlen(out_prefix); -} +#include +#include int kwil_header_generate(struct kwil_header_t* self) { char file_buffer[255]; @@ -61,10 +31,12 @@ int kwil_header_generate(struct kwil_header_t* self) { case KWIL_TYPE_STRUCT: kwil_struct_generate_json_length(&type->struct_type, file, type->type_name); kwil_struct_generate_to_json(&type->struct_type, file, type->type_name); + kwil_struct_generate_from_json(&type->struct_type, type->type_name, file); break; case KWIL_TYPE_ENUM: kwil_enum_generate_json_length(&type->enum_type, file, type->type_name); kwil_enum_generate_to_json(&type->enum_type, file, type->type_name); + kwil_enum_generate_from_json(&type->enum_type, type->type_name, file); break; } } @@ -76,146 +48,33 @@ int kwil_header_generate(struct kwil_header_t* self) { return 0; } -static -void kwil_field_generate_to_string(struct kwil_field_t* self, FILE* file) { - char custom_type_prefix[48]; - switch(self->type_tag) { - case KWIL_FIELD_CHAR: - if(self->array_length > 0 || self->array_dynamic) { - fprintf(file, " if(src->%s != NULL) {\\\n" - " json_len += sprintf(json + json_len, \"\\\"%%s\\\"\", src->%s);\\\n" - " }\\\n", - self->name_str, self->name_str); - } - break; - case KWIL_FIELD_INT: - fprintf(file, " json_len += sprintf(json + json_len, \"%%d\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_FLOAT: - fprintf(file, " json_len += sprintf(json + json_len, \"%%f\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_UNSIGNED: - fprintf(file, " json_len += sprintf(json + json_len, \"%%u\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_UNKNOWN: - case KWIL_FIELD_CUSTOM: - kwil_typename_to_prefix(self->type_str, custom_type_prefix, 47); - fprintf(file, " json_len += %s_to_json(&src->%s, json + json_len);\\\n", custom_type_prefix, self->name_str); - break; - } +int kwil_header_generated_file_name(struct kwil_header_t* self, char** out) { + int len = strlen(self->file_name); + char* filename = malloc(len + 5); + strncpy(filename, self->file_name, len-2); + strcpy(filename + len-2, ".kwil.h"); + *out = filename; + return len; } -static -void kwil_field_get_serialized_length(struct kwil_field_t* self, FILE* file) { - char custom_type_prefix[48]; - size_t len = strlen(self->name_str) + 4; // "name": , - - fprintf(file, " /* length of %s */\\\n" - " json_capacity += %zu", - self->name_str, len); - - switch(self->type_tag) { - case KWIL_FIELD_CHAR: - if(self->array_dynamic || self->array_length > 0) { - fprintf(file, " + strlen(src->%s);\\\n", self->name_str); - } else { - fprintf(file, " + 3;\\\n"); - } - break; - case KWIL_FIELD_INT: - fprintf(file, "+ snprintf(NULL, 0, \"%%d\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_UNSIGNED: - fprintf(file, " + snprintf(NULL, 0, \"%%du\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_FLOAT: - fprintf(file, " + snprintf(NULL, 0, \"%%f\", src->%s);\\\n", self->name_str); - break; - case KWIL_FIELD_CUSTOM: - case KWIL_FIELD_UNKNOWN: - kwil_typename_to_prefix(self->type_str, custom_type_prefix, 47); - fprintf(file, " + %s_json_length(&src->%s);\\\n", custom_type_prefix, self->name_str); - break; - } -} - -int kwil_struct_generate_json_length(struct kwil_struct_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(struct %s* src) {\\\n" - " size_t json_capacity = 2;\\\n",// allocate at least two for "{}\0" - prefix, type_name); - for(int field_index = 0; field_index < self->fields_len; ++field_index) { - kwil_field_get_serialized_length(self->fields + field_index, file); - } - fprintf(file, " return json_capacity;\\\n" - "}\\\n"); - return 0; -} - -int kwil_struct_generate_to_json(struct kwil_struct_t* self, FILE* file, const char* type_name) { - char prefix[48]; - kwil_typename_to_prefix(type_name, prefix, 47); - - fprintf(file, "int %s_to_json(struct %s* src, char* json) {\\\n" - , prefix, type_name); - - fprintf(file, " int json_len = 1;\\\n" - " strcpy(json, \"{\");\\\n"); - - for(int field_index = 0; field_index < self->fields_len; ++field_index) { - kwil_field_generate_to_json(self->fields + field_index, file); +int kwil_typename_to_prefix(const char* restrict type_name, char* restrict out_prefix, size_t out_size) { + if(strncmp("enum ", type_name, 5) == 0) { + type_name += 5; + } else if(strncmp("struct ", type_name, 7) == 0) { + type_name += 7; } - fprintf(file, " strcpy(json + json_len - 1, \"}\");\\\n" - " return json_len;\\\n" - "}\\\n"); - fflush(file); - - return 0; -} - -int kwil_field_generate_to_json(struct kwil_field_t* self, FILE* file) { - fprintf(file, " /* field: %s */\\\n", self->name_str); - fprintf(file, " json_len += sprintf(json + json_len, \"\\\"%s\\\":\");\\\n", - self->name_str); - kwil_field_generate_to_string(self, file); - fprintf(file, " strcpy(json + json_len, \",\");\\\n" - " ++json_len;\\\n"); - 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" - " return 2;\\\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); + int len = strlen(type_name); + if(len > out_size) { + return 1; } - fprintf(file, " }\\\n" - " return sprintf(out, \"\\\"\\\"\");\\\n" - "}\\\n"); - return 0; -} + // generate a function prefix for a type name + strcpy(out_prefix, type_name); + // remove _t postfix if relevant + if(strcmp(out_prefix + len -3, "_t") == 0) { + *(out_prefix + len - 3) = '\0'; + } + return strlen(out_prefix); +} diff --git a/src/kwil_generate.h b/src/kwil_generate.h index 2b4f468..cfcb054 100644 --- a/src/kwil_generate.h +++ b/src/kwil_generate.h @@ -2,17 +2,9 @@ #define _kwil_generate_H #include "kwil_def.h" -#include extern int kwil_header_generate(struct kwil_header_t* self); +extern int kwil_header_generated_file_name(struct kwil_header_t* self, char** out); +extern int kwil_typename_to_prefix(const char* restrict type_name, char* restrict out_prefix, size_t out_size); -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 +#endif diff --git a/src/kwil_serialize.c b/src/kwil_serialize.c new file mode 100644 index 0000000..a93c9fa --- /dev/null +++ b/src/kwil_serialize.c @@ -0,0 +1,148 @@ +#include "kwil_serialize.h" +#include "kwil_generate.h" +#include +#include +#include + +static +void kwil_field_generate_to_string(struct kwil_field_t* self, FILE* file) { + char custom_type_prefix[48]; + switch(self->type_tag) { + case KWIL_FIELD_CHAR: + if(self->array_length > 0 || self->array_dynamic) { + fprintf(file, " if(src->%s != NULL) {\\\n" + " json_len += sprintf(json + json_len, \"\\\"%%s\\\"\", src->%s);\\\n" + " }\\\n", + self->name_str, self->name_str); + } + break; + case KWIL_FIELD_INT: + fprintf(file, " json_len += sprintf(json + json_len, \"%%d\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_FLOAT: + fprintf(file, " json_len += sprintf(json + json_len, \"%%f\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_UNSIGNED: + fprintf(file, " json_len += sprintf(json + json_len, \"%%u\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_CUSTOM: + kwil_typename_to_prefix(self->type_str, custom_type_prefix, 47); + fprintf(file, " json_len += %s_to_json(&src->%s, json + json_len);\\\n", custom_type_prefix, self->name_str); + break; + } +} + +static +void kwil_field_get_serialized_length(struct kwil_field_t* self, FILE* file) { + char custom_type_prefix[48]; + size_t len = strlen(self->name_str) + 4; // length of two quotes, a colon, and a comma + + fprintf(file, " /* length of %s */\\\n" + " json_capacity += %zu", + self->name_str, len); + + switch(self->type_tag) { + case KWIL_FIELD_CHAR: + if(self->array_dynamic || self->array_length > 0) { + fprintf(file, " + strlen(src->%s) + 2;\\\n", self->name_str); + } else { + fprintf(file, " + 3;\\\n"); + } + break; + case KWIL_FIELD_INT: + fprintf(file, "+ snprintf(NULL, 0, \"%%d\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_UNSIGNED: + fprintf(file, " + snprintf(NULL, 0, \"%%du\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_FLOAT: + fprintf(file, " + snprintf(NULL, 0, \"%%f\", src->%s);\\\n", self->name_str); + break; + case KWIL_FIELD_CUSTOM: + kwil_typename_to_prefix(self->type_str, custom_type_prefix, 47); + fprintf(file, " + %s_json_length(&src->%s);\\\n", custom_type_prefix, self->name_str); + break; + } +} + +int kwil_struct_generate_json_length(struct kwil_struct_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(struct %s* src) {\\\n" + " size_t json_capacity = 0;\\\n", + prefix, type_name); + for(int field_index = 0; field_index < self->fields_len; ++field_index) { + kwil_field_get_serialized_length(self->fields + field_index, file); + } + fprintf(file, " return json_capacity;\\\n" + "}\\\n"); + return 0; +} + +int kwil_struct_generate_to_json(struct kwil_struct_t* self, FILE* file, const char* type_name) { + char prefix[48]; + kwil_typename_to_prefix(type_name, prefix, 47); + + fprintf(file, "int %s_to_json(struct %s* src, char* json) {\\\n" + , prefix, type_name); + + fprintf(file, " int json_len = 1;\\\n" + " strcpy(json, \"{\");\\\n"); + + for(int field_index = 0; field_index < self->fields_len; ++field_index) { + kwil_field_generate_to_json(self->fields + field_index, file); + } + + fprintf(file, " strcpy(json + json_len - 1, \"}\");\\\n" + " return json_len;\\\n" + "}\\\n"); + fflush(file); + + return 0; +} + +int kwil_field_generate_to_json(struct kwil_field_t* self, FILE* file) { + fprintf(file, " /* field: %s */\\\n", self->name_str); + fprintf(file, " json_len += sprintf(json + json_len, \"\\\"%s\\\":\");\\\n", + self->name_str); + kwil_field_generate_to_string(self, file); + fprintf(file, " strcpy(json + json_len, \",\");\\\n" + " ++json_len;\\\n"); + 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 + 2;\\\n", + self->enum_values[option_index].name, + strlen(self->enum_values[option_index].name)); + } + fprintf(file, " }\\\n" + " return 2;\\\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" + " return sprintf(out, \"\\\"\\\"\");\\\n" + "}\\\n"); + return 0; +} + diff --git a/src/kwil_serialize.h b/src/kwil_serialize.h new file mode 100644 index 0000000..c217ee5 --- /dev/null +++ b/src/kwil_serialize.h @@ -0,0 +1,16 @@ +#ifndef _kwil_serialize_H +#define _kwil_serialize_H + +#include "kwil_def.h" +#include + +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_serialize_H diff --git a/test_files/header.h b/test_files/header.h index ba3014b..f2b316c 100644 --- a/test_files/header.h +++ b/test_files/header.h @@ -31,13 +31,10 @@ struct struct_B { KWIL_FIELD() float f; - float f_NOT_KWIL; - int i_NOT_KWIL; - KWIL_FIELD() int i; - KWIL_FIELD() - char* str; + //KWIL_FIELD() + //char* str; KWIL_FIELD() char str_static[44]; diff --git a/test_files/header.kwil.h b/test_files/header.kwil.h index e7de2eb..5ef4451 100644 --- a/test_files/header.kwil.h +++ b/test_files/header.kwil.h @@ -2,9 +2,9 @@ #define KWIL_GEN_IMPL(...)\ 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;\ + case VALUE_A: return 7 + 2;\ + case VALUE_B: return 7 + 2;\ + case VALUE_C: return 7 + 2;\ }\ return 2;\ }\ @@ -19,8 +19,17 @@ size_t enum_A_to_json(enum enum_A* src, char* out) {\ }\ return sprintf(out, "\"\"");\ }\ +enum enum_A enum_A_from_json(const char* json) {\ + if(strncmp("\"VALUE_A\"", json, 8) == 0) {\ + return VALUE_A;\ + } else if(strncmp("\"VALUE_B\"", json, 8) == 0) {\ + return VALUE_B;\ + } else if(strncmp("\"VALUE_C\"", json, 8) == 0) {\ + return VALUE_C;\ + } else { return VALUE_A; }\ +}\ size_t struct_A_json_length(struct struct_A* src) {\ - size_t json_capacity = 2;\ + size_t json_capacity = 0;\ /* length of b */\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->b);\ /* length of a */\ @@ -28,7 +37,7 @@ size_t struct_A_json_length(struct struct_A* src) {\ /* length of u */\ json_capacity += 5 + snprintf(NULL, 0, "%du", src->u);\ /* length of dyn_str */\ - json_capacity += 11 + strlen(src->dyn_str);\ + json_capacity += 11 + strlen(src->dyn_str) + 2;\ return json_capacity;\ }\ int struct_A_to_json(struct struct_A* src, char* json) {\ @@ -59,16 +68,75 @@ int struct_A_to_json(struct struct_A* src, char* json) {\ strcpy(json + json_len - 1, "}");\ return json_len;\ }\ +struct struct_A struct_A_from_json(const char* json) {\ + struct struct_A dest;\ + memset(&dest, 0x0, sizeof(struct struct_A)); const char* reader = json;\ + char buffer[48];\ + char* writer = buffer;\ + buffer[47] = '\0';\ + int counter = 0;counter = counter;\ + do {\ + while(*reader != '"') { reader++; }\ + reader++;\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != '"');\ + *writer = '\0';\ + do {\ + reader++;\ + } while(*reader != ':');\ + if(strcmp(buffer, "b") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.b = atoi(buffer);\ + } else if(strcmp(buffer, "a") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.a = atof(buffer);\ + } else if(strcmp(buffer, "u") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.u = atoi(buffer);\ + } else if(strcmp(buffer, "dyn_str") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.dyn_str = malloc(strlen(buffer)-1);\ + dest.dyn_str[0] = '\0';\ + strncpy(dest.dyn_str, buffer+1, strlen(buffer)-2);\ + } else {}\ + } while(*reader != '}');\ + return dest;\ +}\ size_t struct_B_json_length(struct struct_B* src) {\ - size_t json_capacity = 2;\ + size_t json_capacity = 0;\ /* length of f */\ json_capacity += 5 + snprintf(NULL, 0, "%f", src->f);\ /* length of i */\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->i);\ - /* length of str */\ - json_capacity += 7 + strlen(src->str);\ /* length of str_static */\ - json_capacity += 14 + strlen(src->str_static);\ + json_capacity += 14 + strlen(src->str_static) + 2;\ /* length of other_struct */\ json_capacity += 16 + struct_A_json_length(&src->other_struct);\ /* length of other_struct_typedef */\ @@ -92,13 +160,6 @@ int struct_B_to_json(struct struct_B* src, char* json) {\ json_len += sprintf(json + json_len, "%d", src->i);\ strcpy(json + json_len, ",");\ ++json_len;\ - /* field: str */\ - json_len += sprintf(json + json_len, "\"str\":");\ - if(src->str != NULL) {\ - json_len += sprintf(json + json_len, "\"%s\"", src->str);\ - }\ - strcpy(json + json_len, ",");\ - ++json_len;\ /* field: str_static */\ json_len += sprintf(json + json_len, "\"str_static\":");\ if(src->str_static != NULL) {\ @@ -129,4 +190,110 @@ int struct_B_to_json(struct struct_B* src, char* json) {\ strcpy(json + json_len - 1, "}");\ return json_len;\ }\ +struct struct_B struct_B_from_json(const char* json) {\ + struct struct_B dest;\ + memset(&dest, 0x0, sizeof(struct struct_B)); const char* reader = json;\ + char buffer[48];\ + char* writer = buffer;\ + buffer[47] = '\0';\ + int counter = 0;counter = counter;\ + do {\ + while(*reader != '"') { reader++; }\ + reader++;\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != '"');\ + *writer = '\0';\ + do {\ + reader++;\ + } while(*reader != ':');\ + if(strcmp(buffer, "f") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.f = atof(buffer);\ + } else if(strcmp(buffer, "i") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + dest.i = atoi(buffer);\ + } else if(strcmp(buffer, "str_static") == 0) {\ + while(*reader == ' ' || *reader == ':') { reader++; }\ + writer = buffer;\ + do {\ + *writer = *reader;\ + writer++; reader++;\ + } while(*reader != ',' && *reader != '}');\ + *writer = '\0';\ + strncpy(dest.str_static, buffer+1, strlen(buffer)-2);\ + } else if(strcmp(buffer, "other_struct") == 0) {\ + while(*reader != '{' && *reader != '"') { reader++; }\ + dest.other_struct = struct_A_from_json(reader);\ + counter = 0;\ + do {\ + if(*reader == '}') counter--;\ + else if(*reader == '{') counter++;\ + reader++;\ + } while(counter > 0 || (counter == 0 && *reader != ','));\ + if(*reader == '\0') {\ + reader--;\ + } else {\ + reader++;\ + }\ + } else if(strcmp(buffer, "other_struct_typedef") == 0) {\ + while(*reader != '{' && *reader != '"') { reader++; }\ + dest.other_struct_typedef = struct_A_from_json(reader);\ + counter = 0;\ + do {\ + if(*reader == '}') counter--;\ + else if(*reader == '{') counter++;\ + reader++;\ + } while(counter > 0 || (counter == 0 && *reader != ','));\ + if(*reader == '\0') {\ + reader--;\ + } else {\ + reader++;\ + }\ + } else if(strcmp(buffer, "other_enum") == 0) {\ + while(*reader != '{' && *reader != '"') { reader++; }\ + dest.other_enum = enum_A_from_json(reader);\ + counter = 0;\ + do {\ + if(*reader == '}') counter--;\ + else if(*reader == '{') counter++;\ + reader++;\ + } while(counter > 0 || (counter == 0 && *reader != ','));\ + if(*reader == '\0') {\ + reader--;\ + } else {\ + reader++;\ + }\ + } else if(strcmp(buffer, "other_enum_typedef") == 0) {\ + while(*reader != '{' && *reader != '"') { reader++; }\ + dest.other_enum_typedef = enum_A_from_json(reader);\ + counter = 0;\ + do {\ + if(*reader == '}') counter--;\ + else if(*reader == '{') counter++;\ + reader++;\ + } while(counter > 0 || (counter == 0 && *reader != ','));\ + if(*reader == '\0') {\ + reader--;\ + } else {\ + reader++;\ + }\ + } else {}\ + } while(*reader != '}');\ + return dest;\ +}\ diff --git a/test_files/implementation.c b/test_files/implementation.c index 0877ee9..b160ab9 100644 --- a/test_files/implementation.c +++ b/test_files/implementation.c @@ -19,10 +19,8 @@ int main(int argc, char* argv[]) { struct struct_B b = { .f = 123.0, - .f_NOT_KWIL = 0, - .i_NOT_KWIL = 0, .i = 3, - .str = "SNALE!!", + .str_static = "", .other_struct = a, .other_struct_typedef = { .b = -20, .u = 13, .a = -3.14, .dyn_str = "AWESOMEE" @@ -31,21 +29,39 @@ int main(int argc, char* argv[]) { .other_enum_typedef = VALUE_C }; - int required = struct_B_json_length(&b); - char* json = malloc(required); + int allocate_bytes = struct_B_json_length(&b)+1; + char* json = malloc(allocate_bytes); 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); + printf("allocated %d bytes for json of struct_B\n", allocate_bytes); + printf("returned length of json string: %d\n", json_len); + printf("actual length of json string: %zu\n\n", strlen(json)); + printf("struct_B as json:\n%s\n\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", required, json_len); + if (real_len != allocate_bytes) { + printf("Json Length (%d) does not match allocated space (%d)\n", json_len, + allocate_bytes); + free(json); return 1; } + struct struct_B deserialized = struct_B_from_json(json); + + + allocate_bytes = struct_B_json_length(&b); + char* reserialized_json = malloc(allocate_bytes); + struct_B_to_json(&deserialized, reserialized_json); + printf("deserialzed (serialized):\n%s\n\n", json); + + if(strcmp(json, reserialized_json) != 0) { + printf("Deserialized struct does not match original\n"); + free(json); + return 2; + } + + free(json); return 0; }