/* * Copyright (c) 2022 Omar Polo * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include "db.h" #include "fts.h" #include "tokenize.h" struct doclist { uint32_t *ids; size_t len; }; int fts(struct db *db, const char *query, db_hit_cb cb, void *data) { struct doclist *xs = NULL; size_t i, len; char **toks, **t; int ret = 0; if ((toks = tokenize(query)) == NULL) return -1; len = 0; for (t = toks; *t != NULL; ++t) len++; if (len == 0) goto done; if ((xs = calloc(len, sizeof(*xs))) == NULL) { freetoks(toks); return -1; } for (i = 0; i < len; ++i) { xs[i].ids = db_word_docs(db, toks[i], &xs[i].len); if (xs[i].ids == NULL || xs[i].len == 0) goto done; } for (;;) { struct db_entry e; uint32_t mdoc; mdoc = xs[0].ids[0]; for (i = 1; i < len; ++i) { if (xs[i].ids[0] > mdoc) goto next; while (xs[i].ids[0] < mdoc) { if (--xs[i].len == 0) goto done; xs[i].ids++; } if (xs[i].ids[0] != mdoc) goto next; } if (db_doc_by_id(db, mdoc, &e) == -1) { ret = -1; goto done; } if (cb(db, &e, data) == -1) { ret = -1; goto done; } next: if (--xs[0].len == 0) goto done; xs[0].ids++; } done: free(xs); freetoks(toks); return ret; }