feat: use dynamic arrays and string builder
This commit is contained in:
84
cmeta.h
84
cmeta.h
@@ -15,21 +15,6 @@ typedef struct {
|
|||||||
} Struct_Info;
|
} Struct_Info;
|
||||||
|
|
||||||
// AUTO GENERATED CODE //
|
// AUTO GENERATED CODE //
|
||||||
static Struct_Info foo_struct_info = { // cmeta.h:214
|
|
||||||
.name = "Foo_Struct", // cmeta.h:215
|
|
||||||
.fields_count = 1, // cmeta.h:216
|
|
||||||
.fields = (Field_Info[1]) { // cmeta.h:217
|
|
||||||
{ .type = "int", .name = "int_field" }, // cmeta.h:219
|
|
||||||
}, // cmeta.h:221
|
|
||||||
}; // cmeta.h:222
|
|
||||||
static Struct_Info bar_struct_info = { // cmeta.h:214
|
|
||||||
.name = "Bar_Struct", // cmeta.h:215
|
|
||||||
.fields_count = 2, // cmeta.h:216
|
|
||||||
.fields = (Field_Info[2]) { // cmeta.h:217
|
|
||||||
{ .type = "int", .name = "int_field" }, // cmeta.h:219
|
|
||||||
{ .type = "long", .name = "long_fields" }, // cmeta.h:219
|
|
||||||
}, // cmeta.h:221
|
|
||||||
}; // cmeta.h:222
|
|
||||||
// AUTO GENERATED CODE //
|
// AUTO GENERATED CODE //
|
||||||
|
|
||||||
// #define CMETA_COMPTIME
|
// #define CMETA_COMPTIME
|
||||||
@@ -51,12 +36,24 @@ typedef struct {
|
|||||||
char* name;
|
char* name;
|
||||||
} Parsed_Field_Info;
|
} Parsed_Field_Info;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Parsed_Field_Info* items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Parsed_Field_Infos;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* name;
|
char* name;
|
||||||
size_t fields_count;
|
size_t fields_count;
|
||||||
Parsed_Field_Info *fields;
|
Parsed_Field_Info *fields;
|
||||||
} Parsed_Struct_Info;
|
} Parsed_Struct_Info;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Parsed_Struct_Info* items;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Parsed_Struct_Infos;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* data;
|
char* data;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
@@ -81,6 +78,18 @@ void sb_append(String_Builder* sb, const char* data) {
|
|||||||
sb->data[sb->length] = '\0';
|
sb->data[sb->length] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define da_append(da, item) \
|
||||||
|
do { \
|
||||||
|
if ((da)->count + 1 > (da)->capacity) { \
|
||||||
|
size_t new_capacity = (da)->capacity == 0 ? 64 : (da)->capacity * 2; \
|
||||||
|
while ((da)->count + 1 > new_capacity) { \
|
||||||
|
new_capacity *= 2; \
|
||||||
|
} \
|
||||||
|
(da)->items = realloc((da)->items, new_capacity * sizeof(*(da)->items)); \
|
||||||
|
} \
|
||||||
|
(da)->items[(da)->count++] = (item); \
|
||||||
|
} while (0) \
|
||||||
|
|
||||||
bool lexer_expect_keyword(const char* expected) {
|
bool lexer_expect_keyword(const char* expected) {
|
||||||
stb_c_lexer_get_token(&lexer);
|
stb_c_lexer_get_token(&lexer);
|
||||||
|
|
||||||
@@ -132,8 +141,7 @@ bool parse_struct(Parsed_Struct_Info* info) {
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
char* name = NULL;
|
char* name = NULL;
|
||||||
|
|
||||||
size_t fields_count = 0;
|
Parsed_Field_Infos fields = {0};
|
||||||
Parsed_Field_Info fields[16] = {0}; // TODO: use dynamic array
|
|
||||||
|
|
||||||
if (!lexer_expect_keyword("typedef")) goto fail;
|
if (!lexer_expect_keyword("typedef")) goto fail;
|
||||||
if (!lexer_expect_keyword("struct")) goto fail;
|
if (!lexer_expect_keyword("struct")) goto fail;
|
||||||
@@ -155,9 +163,11 @@ bool parse_struct(Parsed_Struct_Info* info) {
|
|||||||
if (!lexer_expect(CLEX_id, "field name")) goto fail;
|
if (!lexer_expect(CLEX_id, "field name")) goto fail;
|
||||||
char* field_name = strdup(lexer.string);
|
char* field_name = strdup(lexer.string);
|
||||||
|
|
||||||
fields[fields_count].type = field_type;
|
Parsed_Field_Info field = {
|
||||||
fields[fields_count].name = field_name;
|
.type = field_type,
|
||||||
fields_count += 1;
|
.name = field_name,
|
||||||
|
};
|
||||||
|
da_append(&fields, field);
|
||||||
|
|
||||||
if(!lexer_expect(';', NULL)) goto fail;
|
if(!lexer_expect(';', NULL)) goto fail;
|
||||||
}
|
}
|
||||||
@@ -166,21 +176,22 @@ bool parse_struct(Parsed_Struct_Info* info) {
|
|||||||
name = strdup(lexer.string);
|
name = strdup(lexer.string);
|
||||||
|
|
||||||
info->name = name;
|
info->name = name;
|
||||||
info->fields_count = fields_count;
|
info->fields_count = fields.count;
|
||||||
info->fields = (Parsed_Field_Info*)calloc(fields_count, sizeof(Parsed_Field_Info));
|
info->fields = (Parsed_Field_Info*)calloc(info->fields_count, sizeof(Parsed_Field_Info));
|
||||||
for(size_t i = 0; i < fields_count; i += 1) {
|
for(size_t i = 0; i < info->fields_count; i += 1) {
|
||||||
info->fields[i].type = fields[i].type;
|
info->fields[i].type = fields.items[i].type;
|
||||||
info->fields[i].name = fields[i].name;
|
info->fields[i].name = fields.items[i].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
fail:
|
fail:
|
||||||
if(!result) {
|
if(!result) {
|
||||||
free(name);
|
free(name);
|
||||||
for(size_t i = 0; i < fields_count; i += 1) {
|
for(size_t i = 0; i < fields.count; i += 1) {
|
||||||
free(fields[i].name);
|
free(fields.items[i].name);
|
||||||
free(fields[i].type);
|
free(fields.items[i].type);
|
||||||
}
|
}
|
||||||
|
free(fields.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -254,7 +265,7 @@ fail:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generate_output_file(const char* output_path, Parsed_Struct_Info *struct_infos, size_t struct_infos_count) {
|
bool generate_output_file(const char* output_path, Parsed_Struct_Infos struct_infos) {
|
||||||
const char* GENERATION_MARK = "// AUTO GENERATED CODE //\n";
|
const char* GENERATION_MARK = "// AUTO GENERATED CODE //\n";
|
||||||
const size_t GENERATION_MARK_LEN = strlen(GENERATION_MARK);
|
const size_t GENERATION_MARK_LEN = strlen(GENERATION_MARK);
|
||||||
|
|
||||||
@@ -287,8 +298,8 @@ bool generate_output_file(const char* output_path, Parsed_Struct_Info *struct_in
|
|||||||
// write up to the generation mark, including it
|
// write up to the generation mark, including it
|
||||||
fwrite(header_content, generate_begin + GENERATION_MARK_LEN - header_content, 1, stream);
|
fwrite(header_content, generate_begin + GENERATION_MARK_LEN - header_content, 1, stream);
|
||||||
|
|
||||||
for (size_t i = 0; i < struct_infos_count; i += 1) {
|
for (size_t i = 0; i < struct_infos.count; i += 1) {
|
||||||
generate_struct_info(stream, struct_infos[i]);
|
generate_struct_info(stream, struct_infos.items[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(generate_end, strlen(generate_end), 1, stream);
|
fwrite(generate_end, strlen(generate_end), 1, stream);
|
||||||
@@ -315,7 +326,6 @@ bool preprocess_file(const char* file_path, String_Builder* result) {
|
|||||||
size_t line_num = 0;
|
size_t line_num = 0;
|
||||||
char file_name[512];
|
char file_name[512];
|
||||||
|
|
||||||
// TODO: use dynamic array instead
|
|
||||||
size_t cursor = 0;
|
size_t cursor = 0;
|
||||||
result->length = 0;
|
result->length = 0;
|
||||||
|
|
||||||
@@ -351,8 +361,7 @@ bool process_file(const char* input_file) {
|
|||||||
stb_c_lexer_init(&lexer, input_content.data, input_content.data + input_content.length, string_store, sizeof(string_store) / sizeof(char));
|
stb_c_lexer_init(&lexer, input_content.data, input_content.data + input_content.length, string_store, sizeof(string_store) / sizeof(char));
|
||||||
|
|
||||||
// find and parse all structs
|
// find and parse all structs
|
||||||
size_t struct_infos_count = 0;
|
Parsed_Struct_Infos struct_infos = {0};
|
||||||
Parsed_Struct_Info struct_infos[16]; // TODO: use dynamic array
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
char* mark = lexer.parse_point;
|
char* mark = lexer.parse_point;
|
||||||
@@ -361,13 +370,14 @@ bool process_file(const char* input_file) {
|
|||||||
if (lexer.token == CLEX_id && strcmp(lexer.string, "typedef") == 0) {
|
if (lexer.token == CLEX_id && strcmp(lexer.string, "typedef") == 0) {
|
||||||
lexer.parse_point = mark;
|
lexer.parse_point = mark;
|
||||||
|
|
||||||
if (parse_struct(&struct_infos[struct_infos_count])) {
|
Parsed_Struct_Info struct_info = {0};
|
||||||
struct_infos_count += 1;
|
if (parse_struct(&struct_info)) {
|
||||||
|
da_append(&struct_infos, struct_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!generate_output_file(__FILE__, struct_infos, struct_infos_count)) return false;
|
if (!generate_output_file(__FILE__, struct_infos)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user