diff --git a/meson.build b/meson.build index 6e310f1..2a32d21 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ libtoml_dep = dependency( exe = executable( 'smeargle', - ['src/main.c', 'src/font.c', 'src/script.c'], + ['src/main.c', 'src/node.c', 'src/font.c', 'src/script.c'], dependencies: libtoml_dep, install: true ) \ No newline at end of file diff --git a/src/font.c b/src/font.c index c43fc8b..05778dc 100644 --- a/src/font.c +++ b/src/font.c @@ -4,19 +4,15 @@ #include "util.h" #include "font.h" -void *fontdb; - -int font_compare(const void *a, const void *b) { - const font_t *x = (const font_t *)a; - const font_t *y = (const font_t *)b; +int font_compare(const node_t *a, const node_t *b) { + const font_t *x = (const font_t *)a->data; + const font_t *y = (const font_t *)b->data; return strcmp(x->name, y->name); } -font_t *load_fonts(toml_table_t *table, const char *base_path) { - font_t *fonts = calloc(32, sizeof(font_t)); - font_t *fontptr = fonts; - fontdb = NULL; +node_t *load_fonts(toml_table_t *table, const char *base_path) { + node_t *root = NULL; // vast majority of projects should have only 1-2 fonts, but let's offer // some room in case there's more. @@ -24,23 +20,24 @@ font_t *load_fonts(toml_table_t *table, const char *base_path) { const char *key = toml_key_in(table, i); if (!key) break; char fullname[200]; + font_t font; toml_datum_t filename = toml_string_in(table, key); if (!filename.ok) { error("couldn't load font ", key); } snprintf(fullname, 200, "%s/%s", base_path, filename.u.s); - fonts[i] = font_create(key, fullname); - - tsearch((void *)fontptr, (void **)fontdb, font_compare); - fontptr++; + font = font_create(key, fullname); + root = node_insert(root, &font, font_compare); } - return fonts; + return root; } -font_t *font_find(const char *key) { - font_t *font = (font_t *)tfind(key, (void **)fontdb, font_compare); +font_t *font_find(node_t *root, const char *key) { + font_t search = {.name = key}; + node_t *node = node_search(root, &search, font_compare); + font_t *font = (font_t *)node->data; - if (!font) { + if (font == NULL) { error("couldn't find requested font ", key); } diff --git a/src/font.h b/src/font.h index 568e193..7f6dcb3 100644 --- a/src/font.h +++ b/src/font.h @@ -1,6 +1,8 @@ #ifndef _SMEARGLE_FONT_H #define _SMEARGLE_FONT_H +#include "node.h" + typedef struct map_t { const char *glyph; unsigned int index; @@ -9,8 +11,8 @@ typedef struct map_t { } map_t; typedef struct { - char *name; - char *image_filename; + const char *name; + const char *image_filename; unsigned char bits_per_pixel; unsigned int width; unsigned int height; @@ -20,8 +22,8 @@ typedef struct { extern void *fontdb; -font_t *load_fonts(toml_table_t *table, const char *base_path); -font_t *font_find(const char *key); +node_t *load_fonts(toml_table_t *table, const char *base_path); +font_t *font_find(node_t *root, const char *key); font_t font_create(const char *name, const char *filename); void font_destroy(font_t font); unsigned int map_create(toml_table_t *table, map_t **map); diff --git a/src/main.c b/src/main.c index 31286e7..1ac7c04 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,8 @@ #include #include "util.h" +#include "node.h" +#include "font.h" #include "script.h" #define ERRBUFSZ 200 @@ -40,7 +42,7 @@ int main(int argc, char **argv) { if (!font) { error("couldn't find font table in ", argv[1]); } - font_t *fonts = load_fonts(font, base_path); + node_t *fonts = load_fonts(font, base_path); toml_array_t *scripts = toml_array_in(conf, "script"); diff --git a/src/node.c b/src/node.c new file mode 100644 index 0000000..e6a3c78 --- /dev/null +++ b/src/node.c @@ -0,0 +1,91 @@ + +#include +#include "node.h" + +node_t *node_create(void *data) { + node_t *temp = malloc(sizeof(node_t)); + + temp->data = data; + temp->left = temp->right = NULL; + + return temp; +} + +node_t *node_search(node_t *root, void *data, node_comparator func) { + int cmp; + if (root == NULL) { + return root; + } + + node_t *temp = node_create(data); + cmp = func(root, temp); + free(temp); + + if (cmp == 0) { + return root; + } + + if (cmp < 0) { + return node_search(root->left, data, func); + } else { + return node_search(root->right, data, func); + } +} + +node_t *node_insert(node_t *node, void *data, node_comparator func) { + if (node == NULL) { + return node_create(data); + } + + node_t *temp = node_create(data); + int cmp = func(node, temp); + free(temp); + + if (cmp < 0) { + node->left = node_insert(node->left, data, func); + } else { + node->right = node_insert(node->right, data, func); + } + return node; +} + +node_t *node_find_leftmost(node_t *root) { + if (root == NULL) { + return NULL; + } else if (root->left != NULL) { + return node_find_leftmost(root->left); + } + return root; +} + +node_t *node_remove(node_t *root, void *data, node_comparator func) { + if (root == NULL) { + return NULL; + } + node_t *temp = node_create(data); + int cmp = func(root, temp); + free(temp); + + if (cmp > 0) { + root->right = node_remove(root->right, data, func); + } else if (cmp < 0) { + root->left = node_remove(root->left, data, func); + } else { + if ((root->left == NULL) && (root->right == NULL)) { + free(root); + return NULL; + } else if ((root->left == NULL) || (root->right == NULL)) { + if (root->left == NULL) { + temp = root->right; + } else { + temp = root->left; + } + free(temp); + } else { + temp = node_find_leftmost(root->right); + root->data = temp->data; + root->right = node_remove(root->right, temp->data, func); + } + } + return root; +} diff --git a/src/node.h b/src/node.h new file mode 100644 index 0000000..c9c856a --- /dev/null +++ b/src/node.h @@ -0,0 +1,17 @@ +#ifndef _SMEARGLE_NODE_H +#define _SMEARGLE_NODE_H + +typedef struct node_t { + void *data; + struct node_t *left, *right; +} node_t; + +typedef int(node_comparator)(const node_t *a, const node_t *b); + +node_t *node_create(void *data); +node_t *node_search(node_t *root, void *data, node_comparator func); +node_t *node_insert(node_t *node, void *data, node_comparator func); +node_t *node_find_leftmost(node_t *root); +node_t *node_remove(node_t *root, void *data, node_comparator func); + +#endif \ No newline at end of file diff --git a/src/script.c b/src/script.c index 73328e1..f918246 100644 --- a/src/script.c +++ b/src/script.c @@ -5,7 +5,7 @@ #include "font.h" #include "util.h" -script_t script_create(toml_table_t *table, const char *base_path, font_t *fonts) { +script_t script_create(toml_table_t *table, const char *base_path, node_t *fonts) { script_t script; #define TOML_GET_KEY(var, key, func) toml_datum_t (var) = func(table, (key));\ @@ -29,7 +29,11 @@ script_t script_create(toml_table_t *table, const char *base_path, font_t *fonts TOML_GET_KEY(little_endian, "little_endian", toml_bool_in) #undef TOML_GET_KEY - font_t *font = font_find(font_name.u.s); + node_t *node = font_find(fonts, font_name.u.s); + if (node == NULL) { + error("couldn't find font ", font_name.u.s); + } + font_t *font = node->data; script.filename = filename.u.s; script.font = *font; diff --git a/src/script.h b/src/script.h index a8871a8..0ed2608 100644 --- a/src/script.h +++ b/src/script.h @@ -6,6 +6,7 @@ #include #include "font.h" +#include "node.h" typedef struct { char *name; @@ -22,7 +23,7 @@ typedef struct { bool little_endian; } script_t; -script_t script_create(toml_table_t *table, const char *base_path, font_t *fonts); +script_t script_create(toml_table_t *table, const char *base_path, node_t *fonts); void script_destroy(script_t script); #endif diff --git a/src/util.h b/src/util.h index c505446..8e86fa7 100644 --- a/src/util.h +++ b/src/util.h @@ -5,7 +5,6 @@ #include #include #include -#include static void error(const char *msg, const char *msg1) { fprintf(stderr, "Error: %s%s\n", msg, msg1 ? msg1 : "");