X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/8818b7fca12456e62410ef914a7bef250a0633c9..a4d8ba8f5aee04e305a1eb43d94bd97039f72167:/server/trackdb.c diff --git a/server/trackdb.c b/server/trackdb.c index 4be5f25..2318bd9 100644 --- a/server/trackdb.c +++ b/server/trackdb.c @@ -44,7 +44,6 @@ #include "configuration.h" #include "syscalls.h" #include "wstat.h" -#include "words.h" #include "printf.h" #include "filepart.h" #include "trackname.h" @@ -53,6 +52,8 @@ #include "cache.h" #include "eventlog.h" #include "hash.h" +#include "unicode.h" +#include "unidata.h" #define RESCAN "disorder-rescan" #define DEADLOCK "disorder-deadlock" @@ -284,8 +285,10 @@ static DB *open_db(const char *path, return db; } -/* open track databases */ -void trackdb_open(void) { +/** @brief Open track databases + * @param dbupgrade Non-0 to allow non-current database versions + */ +void trackdb_open(int dbupgrade) { int newdb, err; /* sanity checks */ @@ -300,18 +303,31 @@ void trackdb_open(void) { s = trackdb_get_global("_dbversion"); oldversion = s ? atol(s) : 1; - if(oldversion != config->dbversion) { + if(oldversion > config->dbversion) { + /* Database is from the future */ + fatal(0, "this version of DisOrder is too old for database version %ld", + oldversion); + } + if(oldversion < config->dbversion && !dbupgrade) { /* This database needs upgrading. This isn't implemented yet so we just * fail. */ fatal(0, "database needs upgrading from %ld to %ld", oldversion, config->dbversion); } + if(oldversion == config->dbversion && dbupgrade) { + /* This doesn't make any sense */ + fatal(0, "database is already at current version"); + } newdb = 0; /* Close the database again, we'll open it property below */ if((err = trackdb_globaldb->close(trackdb_globaldb, 0))) fatal(0, "error closing global.db: %s", db_strerror(err)); trackdb_globaldb = 0; } else { + if(dbupgrade) { + /* Cannot upgrade a new database */ + fatal(0, "cannot upgrade a database that does not exist"); + } /* This is a brand new database */ newdb = 1; } @@ -326,8 +342,8 @@ void trackdb_open(void) { trackdb_globaldb = open_db("global.db", 0, DB_HASH, DB_CREATE, 0666); trackdb_noticeddb = open_db("noticed.db", DB_DUPSORT, DB_BTREE, DB_CREATE, 0666); - /* Stash the database version */ - if(newdb) { + if(newdb && !dbupgrade) { + /* Stash the database version */ char buf[32]; snprintf(buf, sizeof buf, "%ld", config->dbversion); @@ -573,24 +589,50 @@ static int is_display_pref(const char *name) { return !strncmp(name, prefix, (sizeof prefix) - 1); } +/** @brief Word_Break property tailor that treats underscores as spaces */ +static int tailor_underscore_Word_Break_Other(uint32_t c) { + switch(c) { + default: + return -1; + case 0x005F: /* LOW LINE (SPACING UNDERSCORE) */ + return unicode_Word_Break_Other; + } +} + +/** @brief Normalize and split a string using a given tailoring */ +static void word_split(struct vector *v, + const char *s, + unicode_property_tailor *pt) { + size_t nw, nt32, i; + uint32_t *t32, **w32; + + /* Convert to UTF-32 */ + if(!(t32 = utf8_to_utf32(s, strlen(s), &nt32))) + return; + /* Erase case distinctions */ + if(!(t32 = utf32_casefold_compat(t32, nt32, &nt32))) + return; + /* Split into words, treating _ as a space */ + w32 = utf32_word_split(t32, nt32, &nw, pt); + /* Convert words back to UTF-8 and append to result */ + for(i = 0; i < nw; ++i) + vector_append(v, utf32_to_utf8(w32[i], utf32_len(w32[i]), 0)); +} + /* compute the words of a track name */ static char **track_to_words(const char *track, const struct kvp *p) { struct vector v; - char **w; - int nw; const char *rootless = track_rootless(track); if(!rootless) rootless = track; /* bodge */ vector_init(&v); - if((w = words(casefold(strip_extension(rootless)), &nw))) - vector_append_many(&v, w, nw); - + rootless = strip_extension(rootless); + word_split(&v, strip_extension(rootless), tailor_underscore_Word_Break_Other); for(; p; p = p->next) if(is_display_pref(p->name)) - if((w = words(casefold(p->value), &nw))) - vector_append_many(&v, w, nw); + word_split(&v, p->value, 0); vector_terminate(&v); return dedupe(v.vec, v.nvec); } @@ -1739,7 +1781,7 @@ char **trackdb_search(char **wordlist, int nwordlist, int *ntracks) { /* casefold all the words */ w = xmalloc(nwordlist * sizeof (char *)); for(n = 0; n < nwordlist; ++n) { - w[n] = casefold(wordlist[n]); + w[n] = utf8_casefold_compat(wordlist[n], strlen(wordlist[n]), 0); if(checktag(w[n])) ++ntags; /* count up tags */ } /* find the longest non-stopword */