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;
|
||||
|
||||
// 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 //
|
||||
|
||||
// #define CMETA_COMPTIME
|
||||
@@ -51,12 +36,24 @@ typedef struct {
|
||||
char* name;
|
||||
} Parsed_Field_Info;
|
||||
|
||||
typedef struct {
|
||||
Parsed_Field_Info* items;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} Parsed_Field_Infos;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
size_t fields_count;
|
||||
Parsed_Field_Info *fields;
|
||||
} Parsed_Struct_Info;
|
||||
|
||||
typedef struct {
|
||||
Parsed_Struct_Info* items;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} Parsed_Struct_Infos;
|
||||
|
||||
typedef struct {
|
||||
char* data;
|
||||
size_t capacity;
|
||||
@@ -81,6 +78,18 @@ void sb_append(String_Builder* sb, const char* data) {
|
||||
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) {
|
||||
stb_c_lexer_get_token(&lexer);
|
||||
|
||||
@@ -132,8 +141,7 @@ bool parse_struct(Parsed_Struct_Info* info) {
|
||||
bool result = false;
|
||||
char* name = NULL;
|
||||
|
||||
size_t fields_count = 0;
|
||||
Parsed_Field_Info fields[16] = {0}; // TODO: use dynamic array
|
||||
Parsed_Field_Infos fields = {0};
|
||||
|
||||
if (!lexer_expect_keyword("typedef")) 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;
|
||||
char* field_name = strdup(lexer.string);
|
||||
|
||||
fields[fields_count].type = field_type;
|
||||
fields[fields_count].name = field_name;
|
||||
fields_count += 1;
|
||||
Parsed_Field_Info field = {
|
||||
.type = field_type,
|
||||
.name = field_name,
|
||||
};
|
||||
da_append(&fields, field);
|
||||
|
||||
if(!lexer_expect(';', NULL)) goto fail;
|
||||
}
|
||||
@@ -166,21 +176,22 @@ bool parse_struct(Parsed_Struct_Info* info) {
|
||||
name = strdup(lexer.string);
|
||||
|
||||
info->name = name;
|
||||
info->fields_count = fields_count;
|
||||
info->fields = (Parsed_Field_Info*)calloc(fields_count, sizeof(Parsed_Field_Info));
|
||||
for(size_t i = 0; i < fields_count; i += 1) {
|
||||
info->fields[i].type = fields[i].type;
|
||||
info->fields[i].name = fields[i].name;
|
||||
info->fields_count = fields.count;
|
||||
info->fields = (Parsed_Field_Info*)calloc(info->fields_count, sizeof(Parsed_Field_Info));
|
||||
for(size_t i = 0; i < info->fields_count; i += 1) {
|
||||
info->fields[i].type = fields.items[i].type;
|
||||
info->fields[i].name = fields.items[i].name;
|
||||
}
|
||||
|
||||
result = true;
|
||||
fail:
|
||||
if(!result) {
|
||||
free(name);
|
||||
for(size_t i = 0; i < fields_count; i += 1) {
|
||||
free(fields[i].name);
|
||||
free(fields[i].type);
|
||||
for(size_t i = 0; i < fields.count; i += 1) {
|
||||
free(fields.items[i].name);
|
||||
free(fields.items[i].type);
|
||||
}
|
||||
free(fields.items);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -254,7 +265,7 @@ fail:
|
||||
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 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
|
||||
fwrite(header_content, generate_begin + GENERATION_MARK_LEN - header_content, 1, stream);
|
||||
|
||||
for (size_t i = 0; i < struct_infos_count; i += 1) {
|
||||
generate_struct_info(stream, struct_infos[i]);
|
||||
for (size_t i = 0; i < struct_infos.count; i += 1) {
|
||||
generate_struct_info(stream, struct_infos.items[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
char file_name[512];
|
||||
|
||||
// TODO: use dynamic array instead
|
||||
size_t cursor = 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));
|
||||
|
||||
// find and parse all structs
|
||||
size_t struct_infos_count = 0;
|
||||
Parsed_Struct_Info struct_infos[16]; // TODO: use dynamic array
|
||||
Parsed_Struct_Infos struct_infos = {0};
|
||||
|
||||
while (true) {
|
||||
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) {
|
||||
lexer.parse_point = mark;
|
||||
|
||||
if (parse_struct(&struct_infos[struct_infos_count])) {
|
||||
struct_infos_count += 1;
|
||||
Parsed_Struct_Info struct_info = {0};
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user