Merge branch 'main' into readme

readme
Sara 2023-09-27 13:01:34 +00:00
commit 16dfcfd41e
13 changed files with 543 additions and 218 deletions

3
.helix/config.toml Normal file
View File

@ -0,0 +1,3 @@
[keys.normal."+"]
m = ":sh make build"
t = ":sh make test"

View File

@ -2,7 +2,6 @@ build:
##### Compile kwil ##### ##### Compile kwil #####
gcc -o bin/kwil src/**.c -g -Itest_include -Wall gcc -o bin/kwil src/**.c -g -Itest_include -Wall
run:
test: build test: build
##### Run kwil on test files ##### ##### Run kwil on test files #####

View File

@ -37,7 +37,7 @@ enum kwil_field_tag_t kwil_field_tag_from_string(const char* str) {
} else if(strcmp(str, "unsigned") == 0) { } else if(strcmp(str, "unsigned") == 0) {
return KWIL_FIELD_UNSIGNED; return KWIL_FIELD_UNSIGNED;
} else { } 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) { int kwil_init_field(struct kwil_field_t* self, const char* field_name, const char* type_str) {
*self = (struct kwil_field_t){ *self = (struct kwil_field_t){
.type_tag = KWIL_FIELD_UNKNOWN, .type_tag = KWIL_FIELD_CUSTOM,
.type_ptr = NULL, .type_ptr = NULL,
}; };

View File

@ -5,12 +5,11 @@
// Type tag for kwil fields // Type tag for kwil fields
enum kwil_field_tag_t { 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_FLOAT = 1, // the field is a float
KWIL_FIELD_INT = 2, // the field is an int KWIL_FIELD_INT = 2, // the field is an int
KWIL_FIELD_UNSIGNED = 3, // the field is an unsigned int KWIL_FIELD_UNSIGNED = 3, // the field is an unsigned int
KWIL_FIELD_CHAR = 4, // the field is a character 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); extern enum kwil_field_tag_t kwil_field_tag_from_string(const char* str);

119
src/kwil_deserialize.c Normal file
View File

@ -0,0 +1,119 @@
#include "kwil_deserialize.h"
#include "kwil_generate.h"
#include <string.h>
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;
}

10
src/kwil_deserialize.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _kwil_deserialize_H
#define _kwil_deserialize_H
#include "kwil_def.h"
#include <stdio.h>
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

View File

@ -1,40 +1,10 @@
#include "kwil_generate.h" #include "kwil_generate.h"
#include <inttypes.h> #include "kwil_serialize.h"
#include <stdlib.h> #include "kwil_deserialize.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
static #include <stdio.h>
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) { int kwil_header_generate(struct kwil_header_t* self) {
char file_buffer[255]; char file_buffer[255];
@ -61,10 +31,12 @@ int kwil_header_generate(struct kwil_header_t* self) {
case KWIL_TYPE_STRUCT: case KWIL_TYPE_STRUCT:
kwil_struct_generate_json_length(&type->struct_type, file, type->type_name); 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_to_json(&type->struct_type, file, type->type_name);
kwil_struct_generate_from_json(&type->struct_type, type->type_name, file);
break; break;
case KWIL_TYPE_ENUM: case KWIL_TYPE_ENUM:
kwil_enum_generate_json_length(&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); 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; break;
} }
} }
@ -76,146 +48,33 @@ int kwil_header_generate(struct kwil_header_t* self) {
return 0; return 0;
} }
static int kwil_header_generated_file_name(struct kwil_header_t* self, char** out) {
void kwil_field_generate_to_string(struct kwil_field_t* self, FILE* file) { int len = strlen(self->file_name);
char custom_type_prefix[48]; char* filename = malloc(len + 5);
switch(self->type_tag) { strncpy(filename, self->file_name, len-2);
case KWIL_FIELD_CHAR: strcpy(filename + len-2, ".kwil.h");
if(self->array_length > 0 || self->array_dynamic) { *out = filename;
fprintf(file, " if(src->%s != NULL) {\\\n" return len;
" 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;
}
} }
static int kwil_typename_to_prefix(const char* restrict type_name, char* restrict out_prefix, size_t out_size) {
void kwil_field_get_serialized_length(struct kwil_field_t* self, FILE* file) { if(strncmp("enum ", type_name, 5) == 0) {
char custom_type_prefix[48]; type_name += 5;
size_t len = strlen(self->name_str) + 4; // "name": , } else if(strncmp("struct ", type_name, 7) == 0) {
type_name += 7;
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);
} }
fprintf(file, " strcpy(json + json_len - 1, \"}\");\\\n" int len = strlen(type_name);
" return json_len;\\\n" if(len > out_size) {
"}\\\n"); return 1;
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" // generate a function prefix for a type name
" return sprintf(out, \"\\\"\\\"\");\\\n" strcpy(out_prefix, type_name);
"}\\\n");
return 0;
}
// remove _t postfix if relevant
if(strcmp(out_prefix + len -3, "_t") == 0) {
*(out_prefix + len - 3) = '\0';
}
return strlen(out_prefix);
}

View File

@ -2,17 +2,9 @@
#define _kwil_generate_H #define _kwil_generate_H
#include "kwil_def.h" #include "kwil_def.h"
#include <stdio.h>
extern int kwil_header_generate(struct kwil_header_t* self); 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); #endif
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

148
src/kwil_serialize.c Normal file
View File

@ -0,0 +1,148 @@
#include "kwil_serialize.h"
#include "kwil_generate.h"
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
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;
}

16
src/kwil_serialize.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _kwil_serialize_H
#define _kwil_serialize_H
#include "kwil_def.h"
#include <stdio.h>
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

View File

@ -31,13 +31,10 @@ struct struct_B {
KWIL_FIELD() KWIL_FIELD()
float f; float f;
float f_NOT_KWIL;
int i_NOT_KWIL;
KWIL_FIELD() KWIL_FIELD()
int i; int i;
KWIL_FIELD() //KWIL_FIELD()
char* str; //char* str;
KWIL_FIELD() KWIL_FIELD()
char str_static[44]; char str_static[44];

View File

@ -2,9 +2,9 @@
#define KWIL_GEN_IMPL(...)\ #define KWIL_GEN_IMPL(...)\
size_t enum_A_json_length(enum enum_A* src) {\ size_t enum_A_json_length(enum enum_A* src) {\
switch(*src) {\ switch(*src) {\
case VALUE_A: return 7;\ case VALUE_A: return 7 + 2;\
case VALUE_B: return 7;\ case VALUE_B: return 7 + 2;\
case VALUE_C: return 7;\ case VALUE_C: return 7 + 2;\
}\ }\
return 2;\ return 2;\
}\ }\
@ -19,8 +19,17 @@ size_t enum_A_to_json(enum enum_A* src, char* out) {\
}\ }\
return sprintf(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 struct_A_json_length(struct struct_A* src) {\
size_t json_capacity = 2;\ size_t json_capacity = 0;\
/* length of b */\ /* length of b */\
json_capacity += 5+ snprintf(NULL, 0, "%d", src->b);\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->b);\
/* length of a */\ /* length of a */\
@ -28,7 +37,7 @@ size_t struct_A_json_length(struct struct_A* src) {\
/* length of u */\ /* length of u */\
json_capacity += 5 + snprintf(NULL, 0, "%du", src->u);\ json_capacity += 5 + snprintf(NULL, 0, "%du", src->u);\
/* length of dyn_str */\ /* length of dyn_str */\
json_capacity += 11 + strlen(src->dyn_str);\ json_capacity += 11 + strlen(src->dyn_str) + 2;\
return json_capacity;\ return json_capacity;\
}\ }\
int struct_A_to_json(struct struct_A* src, char* json) {\ 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, "}");\ strcpy(json + json_len - 1, "}");\
return json_len;\ 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 struct_B_json_length(struct struct_B* src) {\
size_t json_capacity = 2;\ size_t json_capacity = 0;\
/* length of f */\ /* length of f */\
json_capacity += 5 + snprintf(NULL, 0, "%f", src->f);\ json_capacity += 5 + snprintf(NULL, 0, "%f", src->f);\
/* length of i */\ /* length of i */\
json_capacity += 5+ snprintf(NULL, 0, "%d", src->i);\ json_capacity += 5+ snprintf(NULL, 0, "%d", src->i);\
/* length of str */\
json_capacity += 7 + strlen(src->str);\
/* length of str_static */\ /* length of str_static */\
json_capacity += 14 + strlen(src->str_static);\ json_capacity += 14 + strlen(src->str_static) + 2;\
/* length of other_struct */\ /* length of other_struct */\
json_capacity += 16 + struct_A_json_length(&src->other_struct);\ json_capacity += 16 + struct_A_json_length(&src->other_struct);\
/* length of other_struct_typedef */\ /* 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);\ json_len += sprintf(json + json_len, "%d", src->i);\
strcpy(json + json_len, ",");\ strcpy(json + json_len, ",");\
++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 */\ /* field: str_static */\
json_len += sprintf(json + json_len, "\"str_static\":");\ json_len += sprintf(json + json_len, "\"str_static\":");\
if(src->str_static != NULL) {\ 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, "}");\ strcpy(json + json_len - 1, "}");\
return json_len;\ 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;\
}\

View File

@ -19,10 +19,8 @@ int main(int argc, char* argv[]) {
struct struct_B b = { struct struct_B b = {
.f = 123.0, .f = 123.0,
.f_NOT_KWIL = 0,
.i_NOT_KWIL = 0,
.i = 3, .i = 3,
.str = "SNALE!!", .str_static = "",
.other_struct = a, .other_struct = a,
.other_struct_typedef = { .other_struct_typedef = {
.b = -20, .u = 13, .a = -3.14, .dyn_str = "AWESOMEE" .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 .other_enum_typedef = VALUE_C
}; };
int required = struct_B_json_length(&b); int allocate_bytes = struct_B_json_length(&b)+1;
char* json = malloc(required); char* json = malloc(allocate_bytes);
int json_len = struct_B_to_json(&b, json); int json_len = struct_B_to_json(&b, json);
printf("allocated %d bytes for json of struct_B\n", required); printf("allocated %d bytes for json of struct_B\n", allocate_bytes);
printf("struct_B as json:\n%s\n", json); 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); 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; 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; return 0;
} }