From 7dad53094ebb5406bc4fb7dbdf77b30e3e190510 Mon Sep 17 00:00:00 2001 From: Ben Winston Date: Mon, 6 May 2024 21:31:31 -0400 Subject: remove toml dependancy --- booki.c | 307 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 184 insertions(+), 123 deletions(-) (limited to 'booki.c') diff --git a/booki.c b/booki.c index b7bb92f..83858e9 100644 --- a/booki.c +++ b/booki.c @@ -7,14 +7,35 @@ #include #include -#include "toml.h" - #define BOOKI_FILE_REL ".local/share/booki/books.toml" #define MAX_SEARCH_OPTS 5 +// STRUCTS +struct es { + int len; + char* ptr; +}; + +struct Book { + struct es id; + struct es title; + struct es author; + int pages; + struct es isbn; + struct es language; + struct es translator; + int published; + + // maybe? + //struct es authors[MAX_AUTHORS]; + //struct es translators[MAX_TRANSLATORS]; +}; + char* BOOKI_FILE; +int PARSE_LINE = 1; + const char* get_last_word(const char* str) { const char* last_space = strrchr(str, ' '); if ((last_space - str) > 0) @@ -23,40 +44,154 @@ const char* get_last_word(const char* str) { return 0; } -bool regex_match(const char* pattern, const char* text) { +struct Book parse_book(char* current_pos) { + struct Book book; + char* attr; + char* value; + char c = *current_pos; + // loop until we hit the extra newline + while (c != '\n') { + // we start at the beginning of a line + attr = current_pos; + while ((c = *current_pos) != '=') { + current_pos++; + } + + // attr should be the name of the attribute, with (possibly) trailing spaces + if (strncmp(attr, "title", 5) == 0) { + // leading spaces + while ((c = *current_pos) != '"') { + current_pos++; + } + + // go past the quote and set the position of the start of value + current_pos++; + value = current_pos; + + // until the next quote + while ((c = *current_pos) != '"') { + current_pos++; + } + + // set the attribute + struct es title; + title.len = current_pos - value; + title.ptr = value; + book.title = title; + } else if (strncmp(attr, "author", 6) == 0) { + // leading spaces + while ((c = *current_pos) != '"') { + current_pos++; + } + + // go past the quote and set the position of the start of value + current_pos++; + value = current_pos; + + // until the next quote + while ((c = *current_pos) != '"') { + current_pos++; + } + + // set the attribute + struct es author; + author.len = current_pos - value; + author.ptr = value; + book.author = author; + } + + // go to (and then past) the newline + while ((c = *current_pos) != '\n') { + current_pos++; + } + PARSE_LINE += 1; + c = *(++current_pos); + } + return book; +} + +char* next_book(char* current_pos) { + char c; + while(*current_pos) { + // first opening bracket + c = *current_pos++; + if (c != '[') { + continue; + } + + // second opening bracket + c = *current_pos++; + if (c != '[') { + continue; + } + + if (strncmp(current_pos, "books", 5) != 0) { + printf("thought i had it, but it's not a book\n"); + continue; + } + current_pos += 5; + + // seek past the closing brackets and the next newline + current_pos += 2; + if (*current_pos != '\n') { + printf("expecting a newline...\n"); + continue; + } + + PARSE_LINE += 1; + current_pos++; + return current_pos; + } + return NULL; +} + +bool regex_match(const char* pattern, const struct es text) { // empty pattern matches everything if (!*pattern) return true; // get lengths int pattern_length = strlen(pattern); - int text_length = strlen(text); - if (pattern_length > text_length) return false; + if (pattern_length > text.len) return false; // we only need to compare while remaining text is // as long or longer than pattern (without special) - for (int i = 0; i <= (text_length - pattern_length); i++) { - if (strncasecmp(pattern, text + i, pattern_length) == 0) return true; + for (int i = 0; i <= (text.len - pattern_length); i++) { + if (strncasecmp(pattern, text.ptr + i, pattern_length) == 0) return true; } return false; } -toml_table_t* get_toml_data(const char* filename) { - FILE* fp; - char errbuf[200]; - - fp = fopen(filename, "r"); +char* load_file(char* filename) { + // open the file + FILE* fp = fopen(filename, "r"); if (!fp) { - printf("can't open file :("); - return 0; + printf("bad file\n"); + return NULL; + } + + // seek to the end + fseek(fp, 0, SEEK_END); + int size = ftell(fp); + rewind(fp); + + char* data = malloc(size); + if (!data) { + printf("couldn't malloc\n"); + return NULL; + } + + int read_size = fread(data, 1, size, fp); + if (read_size != size) { + printf("didn't read everything -- %d read of %d\n", read_size, size); + return NULL; } - toml_table_t* conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); fclose(fp); - return conf; + return data; } static struct option search_options[] = { @@ -108,130 +243,57 @@ struct search_opt parse_search_options(int argc, char* argv[]) { return opt_out; } -char** search(int argc, char* argv[]) { - toml_table_t* data = get_toml_data(BOOKI_FILE); - - if (!data) { - return NULL; - } +void print_book(struct Book book) { + printf("%.*s by %.*s\n", book.title.len, book.title.ptr, book.author.len, book.author.ptr); +} +char** search(int argc, char* argv[]) { struct search_opt search_opts = parse_search_options(argc, argv); bool print = false; // get the books array - toml_array_t* books = toml_array_in(data, "books"); - if (!books) { + char* data = load_file(BOOKI_FILE); + if (!data) { printf("no such array: 'books'"); return NULL; } // book loop - for (int i = 0; ; i++) { - toml_table_t* book = toml_table_at(books, i); - if (!book) break; - - if (search_opts.count == 0) { - print = true; - } else { - toml_datum_t datapoint; - char* field; - bool inner_print = true; - - // loop through all options - int i; - for (i = 0; i < search_opts.count; i++) { - field = search_opts.opts[i]; - - // if the key doesn't exist, we won't print - if (!toml_key_exists(book, field)) { + struct Book book; + char* cur_data = data; + while ((cur_data = next_book(cur_data)) != NULL) { + book = parse_book(cur_data); + + char* field; + int i; + bool print = true; + for (i = 0; i < search_opts.count; i++) { + field = search_opts.opts[i]; + + // compare fields + if (strcmp(field, "title") == 0) { + if (!regex_match(search_opts.args[i], book.title)) break; - } - - // try and get a string - datapoint = toml_string_in(book, field); - if (datapoint.ok) { - if (!regex_match(search_opts.args[i], datapoint.u.s)) { - free(datapoint.u.s); - break; - } - free(datapoint.u.s); - } else { - // try and get an integer - datapoint = toml_int_in(book, field); - int ret; - if (datapoint.ok) { - ret = atoi(search_opts.args[i]); - if (ret == 0) { - printf("not an int: %s\n", search_opts.args[i]); - break; - } else if (ret != datapoint.u.i) { - break; - } - } else { - break; - } - } - } - - // if we made it all the way through the loop, - // we should print - print = i == search_opts.count; - } - - // get title and author for printing - toml_datum_t book_title = toml_string_in(book, "title"); - if (!book_title.ok) { - continue; - } - - // author can be a string or a list - toml_datum_t book_author = toml_string_in(book, "author"); - char author_str[100]; - char* tmp; - if (!book_author.ok) { - toml_array_t* book_author_array = toml_array_in(book, "author"); - if (!book_author_array) { - continue; - } - int len = toml_array_nelem(book_author_array); - tmp = toml_string_at(book_author_array, 0).u.s; - strcpy(author_str, tmp); - free(tmp); - for (int i = 1; i < len; i++) { - book_author = toml_string_at(book_author_array, i); - tmp = book_author.u.s; - if (i == len-1) { - strcat(author_str, " and "); - } else { - strcat(author_str, ", "); - } - strcat(author_str, book_author.u.s); - free(tmp); + } else if (strcmp(field, "author") == 0) { + if (!regex_match(search_opts.args[i], book.author)) + break; + } else { + printf("unsupported field: %s\n", field); + break; } - } else { - strcpy(author_str, book_author.u.s); - free(book_author.u.s); } + print = i == search_opts.count; - // print! if (print) { - printf("%s by %s\n", book_title.u.s, author_str); + print_book(book); + + /* TODO fix if (search_opts.show) { //toml_datum_t d; for (int i = 0; ; i++) { const char* key = toml_key_in(book, i); if (!key) break; - /* - if (strcmp("pages", key) == 0) { - d = toml_int_in(book, key); - if (d.ok) { - printf(" - %s: %d\n", - } - } - */ - - // currently we support strings and ints toml_datum_t s = toml_string_in(book, key); if (s.ok) { @@ -245,17 +307,16 @@ char** search(int argc, char* argv[]) { } } + */ } - - free(book_title.u.s); - //free(book_author.u.s); } - toml_free(data); + free(data); return argv + optind; } + void open() { char* home = getenv("HOME"); -- cgit v1.2.3