diff --git a/.helix/config.toml b/.helix/config.toml deleted file mode 100644 index 100e27b..0000000 --- a/.helix/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -[keys.normal."+"] -m = ":sh make build" -t = ":sh make test" diff --git a/Makefile b/Makefile index 9e2c356..e6ba46d 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ build: ##### Compile kwil ##### gcc -o bin/kwil src/**.c -g -Itest_include -Wall +run: test: build ##### Run kwil on test files ##### diff --git a/README.md b/README.md index 5be3f59..5e513e0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,13 @@ # Kwil Header tool - An in-development command line tool for generating serialization code from C header files. -Kwil aims to be a non-intrusive drop-in (and if necessary drop-out) solution to automate the annoying task of writing deserialization and serialization code. - -Currently aiming for json support, though adding (optional) support for other formats is strongly considered for implementing at a later time. - - Features: +[x] Generate `*_json_length` and `*_to_json`functions for structs and enums marked with `KWIL_STRUCT()` or `KWIL_ENUM()` +[ ] Generate `*_from_json` functins for structs. +[ ] Dynamic array length specifiers (e.g: `KWIL_FIELD(LEN=13` or `KWIL_FIELD(LEN=`) -- [x] Generate `*_json_length` and `*_to_json`functions for structs and enums marked with `KWIL_STRUCT()` or `KWIL_ENUM()` +## Example +```c +#include "kwil.h" // kwil.h header contains empty KWIL_STRUCT() KWIL_ENUM() and KWIL_FIELD() macros -- [ ] Generate `*_from_json` functions for structs. - -- [ ] Dynamic array length specifiers (e.g: `KWIL_FIELD(LEN=13` or `KWIL_FIELD(LEN=src->field_length`) +``` \ No newline at end of file diff --git a/src/kwil.c b/src/kwil.c index d431a7c..1d7ba2d 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_CUSTOM; + return KWIL_FIELD_UNKNOWN; } } @@ -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_CUSTOM, + .type_tag = KWIL_FIELD_UNKNOWN, .type_ptr = NULL, }; diff --git a/src/kwil_def.h b/src/kwil_def.h index 6a41e1c..3502418 100644 --- a/src/kwil_def.h +++ b/src/kwil_def.h @@ -5,11 +5,12 @@ // 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 deleted file mode 100644 index da3aea3..0000000 --- a/src/kwil_deserialize.c +++ /dev/null @@ -1,119 +0,0 @@ -#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 deleted file mode 100644 index a93f703..0000000 --- a/src/kwil_deserialize.h +++ /dev/null @@ -1,10 +0,0 @@ -#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 f640ca4..d810de0 100644 --- a/src/kwil_generate.c +++ b/src/kwil_generate.c @@ -1,10 +1,40 @@ #include "kwil_generate.h" -#include "kwil_serialize.h" -#include "kwil_deserialize.h" - -#include +#include #include -#include +#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); +} int kwil_header_generate(struct kwil_header_t* self) { char file_buffer[255]; @@ -31,12 +61,10 @@ 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; } } @@ -48,33 +76,146 @@ int kwil_header_generate(struct kwil_header_t* self) { return 0; } -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_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_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; - } +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": , - int len = strlen(type_name); - if(len > out_size) { - return 1; - } + fprintf(file, " /* length of %s */\\\n" + " json_capacity += %zu", + self->name_str, len); - // 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'; + 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; } - return strlen(out_prefix); } + +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); + } + + 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); + } + + fprintf(file, " }\\\n" + " return sprintf(out, \"\\\"\\\"\");\\\n" + "}\\\n"); + return 0; +} + diff --git a/src/kwil_generate.h b/src/kwil_generate.h index cfcb054..2b4f468 100644 --- a/src/kwil_generate.h +++ b/src/kwil_generate.h @@ -2,9 +2,17 @@ #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); -#endif +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_serialize.c b/src/kwil_serialize.c deleted file mode 100644 index a93c9fa..0000000 --- a/src/kwil_serialize.c +++ /dev/null @@ -1,148 +0,0 @@ -#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 deleted file mode 100644 index c217ee5..0000000 --- a/src/kwil_serialize.h +++ /dev/null @@ -1,16 +0,0 @@ -#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 f2b316c..ba3014b 100644 --- a/test_files/header.h +++ b/test_files/header.h @@ -31,10 +31,13 @@ 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 5ef4451..e7de2eb 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 + 2;\ - case VALUE_B: return 7 + 2;\ - case VALUE_C: return 7 + 2;\ + case VALUE_A: return 7;\ + case VALUE_B: return 7;\ + case VALUE_C: return 7;\ }\ return 2;\ }\ @@ -19,17 +19,8 @@ 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 = 0;\ + size_t json_capacity = 2;\ /* length of b */\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->b);\ /* length of a */\ @@ -37,7 +28,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) + 2;\ + json_capacity += 11 + strlen(src->dyn_str);\ return json_capacity;\ }\ int struct_A_to_json(struct struct_A* src, char* json) {\ @@ -68,75 +59,16 @@ 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 = 0;\ + size_t json_capacity = 2;\ /* 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) + 2;\ + json_capacity += 14 + strlen(src->str_static);\ /* length of other_struct */\ json_capacity += 16 + struct_A_json_length(&src->other_struct);\ /* length of other_struct_typedef */\ @@ -160,6 +92,13 @@ 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) {\ @@ -190,110 +129,4 @@ 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 b160ab9..0877ee9 100644 --- a/test_files/implementation.c +++ b/test_files/implementation.c @@ -19,8 +19,10 @@ int main(int argc, char* argv[]) { struct struct_B b = { .f = 123.0, + .f_NOT_KWIL = 0, + .i_NOT_KWIL = 0, .i = 3, - .str_static = "", + .str = "SNALE!!", .other_struct = a, .other_struct_typedef = { .b = -20, .u = 13, .a = -3.14, .dyn_str = "AWESOMEE" @@ -29,39 +31,21 @@ int main(int argc, char* argv[]) { .other_enum_typedef = VALUE_C }; - int allocate_bytes = struct_B_json_length(&b)+1; - char* json = malloc(allocate_bytes); + 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", 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); + 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); - if (real_len != allocate_bytes) { - printf("Json Length (%d) does not match allocated space (%d)\n", json_len, - allocate_bytes); - free(json); + free(json); + if(real_len != json_len) { + printf("Json Length (%d) does not match allocated space (%d)\n", required, json_len); 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; }