Merge branch 'main' into readme
commit
16dfcfd41e
|
@ -0,0 +1,3 @@
|
|||
[keys.normal."+"]
|
||||
m = ":sh make build"
|
||||
t = ":sh make test"
|
1
Makefile
1
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 #####
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -1,40 +1,10 @@
|
|||
#include "kwil_generate.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include "kwil_serialize.h"
|
||||
#include "kwil_deserialize.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -2,17 +2,9 @@
|
|||
#define _kwil_generate_H
|
||||
|
||||
#include "kwil_def.h"
|
||||
#include <stdio.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;\
|
||||
}\
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue