src: implement own btree

current
Síle Ekaterin Liszka 2023-11-29 21:01:38 -08:00
parent 5d3e174bda
commit 0ed273b7b6
9 changed files with 140 additions and 27 deletions

View File

@ -10,7 +10,7 @@ libtoml_dep = dependency(
exe = executable( exe = executable(
'smeargle', '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, dependencies: libtoml_dep,
install: true install: true
) )

View File

@ -4,19 +4,15 @@
#include "util.h" #include "util.h"
#include "font.h" #include "font.h"
void *fontdb; int font_compare(const node_t *a, const node_t *b) {
const font_t *x = (const font_t *)a->data;
int font_compare(const void *a, const void *b) { const font_t *y = (const font_t *)b->data;
const font_t *x = (const font_t *)a;
const font_t *y = (const font_t *)b;
return strcmp(x->name, y->name); return strcmp(x->name, y->name);
} }
font_t *load_fonts(toml_table_t *table, const char *base_path) { node_t *load_fonts(toml_table_t *table, const char *base_path) {
font_t *fonts = calloc(32, sizeof(font_t)); node_t *root = NULL;
font_t *fontptr = fonts;
fontdb = NULL;
// vast majority of projects should have only 1-2 fonts, but let's offer // vast majority of projects should have only 1-2 fonts, but let's offer
// some room in case there's more. // 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); const char *key = toml_key_in(table, i);
if (!key) break; if (!key) break;
char fullname[200]; char fullname[200];
font_t font;
toml_datum_t filename = toml_string_in(table, key); toml_datum_t filename = toml_string_in(table, key);
if (!filename.ok) { if (!filename.ok) {
error("couldn't load font ", key); error("couldn't load font ", key);
} }
snprintf(fullname, 200, "%s/%s", base_path, filename.u.s); snprintf(fullname, 200, "%s/%s", base_path, filename.u.s);
fonts[i] = font_create(key, fullname); font = font_create(key, fullname);
root = node_insert(root, &font, font_compare);
tsearch((void *)fontptr, (void **)fontdb, font_compare);
fontptr++;
} }
return fonts; return root;
} }
font_t *font_find(const char *key) { font_t *font_find(node_t *root, const char *key) {
font_t *font = (font_t *)tfind(key, (void **)fontdb, font_compare); 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); error("couldn't find requested font ", key);
} }

View File

@ -1,6 +1,8 @@
#ifndef _SMEARGLE_FONT_H #ifndef _SMEARGLE_FONT_H
#define _SMEARGLE_FONT_H #define _SMEARGLE_FONT_H
#include "node.h"
typedef struct map_t { typedef struct map_t {
const char *glyph; const char *glyph;
unsigned int index; unsigned int index;
@ -9,8 +11,8 @@ typedef struct map_t {
} map_t; } map_t;
typedef struct { typedef struct {
char *name; const char *name;
char *image_filename; const char *image_filename;
unsigned char bits_per_pixel; unsigned char bits_per_pixel;
unsigned int width; unsigned int width;
unsigned int height; unsigned int height;
@ -20,8 +22,8 @@ typedef struct {
extern void *fontdb; extern void *fontdb;
font_t *load_fonts(toml_table_t *table, const char *base_path); node_t *load_fonts(toml_table_t *table, const char *base_path);
font_t *font_find(const char *key); font_t *font_find(node_t *root, const char *key);
font_t font_create(const char *name, const char *filename); font_t font_create(const char *name, const char *filename);
void font_destroy(font_t font); void font_destroy(font_t font);
unsigned int map_create(toml_table_t *table, map_t **map); unsigned int map_create(toml_table_t *table, map_t **map);

View File

@ -2,6 +2,8 @@
#include <toml.h> #include <toml.h>
#include "util.h" #include "util.h"
#include "node.h"
#include "font.h"
#include "script.h" #include "script.h"
#define ERRBUFSZ 200 #define ERRBUFSZ 200
@ -40,7 +42,7 @@ int main(int argc, char **argv) {
if (!font) { if (!font) {
error("couldn't find font table in ", argv[1]); 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"); toml_array_t *scripts = toml_array_in(conf, "script");

91
src/node.c Normal file
View File

@ -0,0 +1,91 @@
#include <stdlib.h>
#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;
}

17
src/node.h Normal file
View File

@ -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

View File

@ -5,7 +5,7 @@
#include "font.h" #include "font.h"
#include "util.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; script_t script;
#define TOML_GET_KEY(var, key, func) toml_datum_t (var) = func(table, (key));\ #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) TOML_GET_KEY(little_endian, "little_endian", toml_bool_in)
#undef TOML_GET_KEY #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.filename = filename.u.s;
script.font = *font; script.font = *font;

View File

@ -6,6 +6,7 @@
#include <libgen.h> #include <libgen.h>
#include "font.h" #include "font.h"
#include "node.h"
typedef struct { typedef struct {
char *name; char *name;
@ -22,7 +23,7 @@ typedef struct {
bool little_endian; bool little_endian;
} script_t; } 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); void script_destroy(script_t script);
#endif #endif

View File

@ -5,7 +5,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <search.h>
static void error(const char *msg, const char *msg1) { static void error(const char *msg, const char *msg1) {
fprintf(stderr, "Error: %s%s\n", msg, msg1 ? msg1 : ""); fprintf(stderr, "Error: %s%s\n", msg, msg1 ? msg1 : "");