aboutsummaryrefslogtreecommitdiff
path: root/booki.c
diff options
context:
space:
mode:
Diffstat (limited to 'booki.c')
-rw-r--r--booki.c307
1 files changed, 184 insertions, 123 deletions
diff --git a/booki.c b/booki.c
index b7bb92f..83858e9 100644
--- a/booki.c
+++ b/booki.c
@@ -7,14 +7,35 @@
#include <sys/wait.h>
#include <unistd.h>
-#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");