diff --git a/inc/lektor/database.def b/inc/lektor/database.def new file mode 100644 index 0000000000000000000000000000000000000000..dfbdce2461e203c2f17b0bd66bbb42652d7161f7 --- /dev/null +++ b/inc/lektor/database.def @@ -0,0 +1,31 @@ +/* Types available in the database */ +kara_type("OP") +kara_type("ED") +kara_type("AMV") +kara_type("IS") +kara_type("LIVE") +kara_type("CDG") +kara_type("PV") +kara_type("MV") + +/* Categories available in the database */ +kara_category("vo") +kara_category("va") +kara_category("amv") +kara_category("cdg") +kara_category("autres") +kara_category("vocaloid") + +/* Languages available in the database */ +kara_language("jp") +kara_language("fr") +kara_language("en") +kara_language("ru") +kara_language("sp") +kara_language("it") +kara_language("ch") +kara_language("latin") +kara_language("multi") +kara_language("undefined") + +// vi:syntax=c diff --git a/src/main/lkt.c b/src/main/lkt.c index f6c0987ca2c0b8398f4edb2abee19296cb914196..f5ab077b08979487218fe39e37dd100f5c56e426 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -24,6 +24,7 @@ #include <stdbool.h> #include <stdarg.h> #include <limits.h> +#include <ctype.h> #define LKT_KEY_VALUE_SEP ": \n\t\0" #define fail_if(cond, msg) { if (cond) { LOG_ERROR("LKT", "%s", msg); exit(EXIT_FAILURE); } } @@ -66,6 +67,136 @@ lkt_valid_type(const char *type) STR_MATCH(type, "playlist")); } +enum lkt_query_type { + LKT_QUERY_TYPE_ERROR = 0, + LKT_QUERY_TYPE_ID, + LKT_QUERY_TYPE_LANG, + LKT_QUERY_TYPE_AUTHOR, + LKT_QUERY_TYPE_CAT, + LKT_QUERY_TYPE_TYPE, + LKT_QUERY_TYPE_PLAYLIST, + LKT_QUERY_TYPE_QUERY, +}; + +static inline int +__string_is_lower(const char *str) +{ + while (*str != '\0') { + if (!islower(*str)) + return 1; + } + return 0; +} + +static inline int +__string_is_upper(const char *str) +{ + while (*str != '\0') { + if (!isupper(*str)) + return 1; + } + return 0; +} + +static inline void +__concat_strings(char *const res, size_t len, const char **tab, size_t count) +{ + size_t i; + for (i = 0; i < count - 1; ++i) { + strncat(res, tab[i], len - 1); + strncat(res, " ", len - 1); + } + strncat(res, tab[i], len - 1); +} + +__attribute__((unused)) static int +lkt_get_query_type(struct cmd_args *args, enum lkt_query_type *type, + char *const regex, size_t regex_len) +{ + if (args->argc == 0) { + LOG_ERROR("LKT", "Invalid empty query"); + *type = LKT_QUERY_TYPE_ERROR; + return 1; + } + + /* id, type, lang, category */ + if (args->argc == 1) { + /* Type ?== id */ + long id = 0; + errno = 0; + id = strtol(args->argv[0], NULL, 10); + if (id != 0 && errno == 0) { + *type = LKT_QUERY_TYPE_ID; + safe_snprintf(regex, regex_len, "%ld", id); + return 0; + } + + /* Type ?== type */ + else if (__string_is_upper(args->argv[0])) { +#define kara_category(unused) +#define kara_language(unused) +#define kara_type(tp) \ +if (STR_MATCH(tp, args->argv[0])) { \ + *type = LKT_QUERY_TYPE_TYPE; \ + safe_snprintf(regex, regex_len, "%s", args->argv[0]); \ + return 0; \ +} +#include <lektor/database.def> +#undef kara_category +#undef kara_language +#undef kara_type + } + + /* Type ?== category OR Type ?== lang */ + else if (__string_is_lower(args->argv[0])) { +#define kara_type(unused) +#define kara_category(ct) \ +if (STR_MATCH(ct, args->argv[0])) { \ + *type = LKT_QUERY_TYPE_CAT; \ + safe_snprintf(regex, regex_len, "%s", args->argv[0]); \ + return 0; \ +} +#define kara_language(lg) \ +if (STR_MATCH(lg, args->argv[0])) { \ + *type = LKT_QUERY_TYPE_LANG; \ + safe_snprintf(regex, regex_len, "%s", args->argv[0]); \ + return 0; \ +} +#include <lektor/database.def> +#undef kara_category +#undef kara_language +#undef kara_type + } + } + + memset(regex, 0, regex_len * sizeof(char)); + + /* author, playlist/plt */ + if (args->argc >= 2) { + /* Type ?== author */ + if (STR_MATCH("author", args->argv[0])) { + *type = LKT_QUERY_TYPE_AUTHOR; + __concat_strings(regex, regex_len, args->argv + 1, args->argc - 1); + } + + /* Type ?== playlist */ + else if (STR_MATCH("plt", args->argv[0]) || STR_MATCH("playlist", args->argv[0])) { + *type = LKT_QUERY_TYPE_PLAYLIST; + __concat_strings(regex, regex_len, args->argv + 1, args->argc - 1); + } + + return 0; + } + + /* If 'query' is specified, skip it */ + int index = STR_MATCH("query", args->argv[0]) ? 1 : 0; + strncat(regex, "%", regex_len - 1); + __concat_strings(regex, regex_len, args->argv + index, args->argc - index); + strncat(regex, "%", regex_len - 1); + *type = LKT_QUERY_TYPE_QUERY; + return 0; +} + static int read_socket(FILE *sock, char *buff, size_t max_len) { @@ -1133,10 +1264,9 @@ main(int argc, const char **argv) { __log_level = ERROR; executable_name = "lkt"; - assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */ - if (signal(SIGPIPE, sigpipe__)) { - // LOG_ERROR("SYS", "%s", "Failed to install handler for SIGPIPE signal"); - } + assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */ + if (signal(SIGPIPE, sigpipe__)) + LOG_ERROR("SYS", "Failed to install handler for SIGPIPE signal"); args_t args = { .host = "localhost",