diff --git a/inc/lektor/macro.h b/inc/lektor/macro.h index 712ae9f9a6799646dd2bace4b3d459746631f940..f5a3209085b35d737e6533afefe815e883b2b4bd 100644 --- a/inc/lektor/macro.h +++ b/inc/lektor/macro.h @@ -55,6 +55,20 @@ fprintf(stderr, " ! %s: %s\n", __func__, msg); \ return ret; \ } +#define GOTO_IF(cond, msg, label) \ + if (cond) { \ + fprintf(stderr, " ! %s: %s\n", __func__, msg); \ + goto label; \ + } +#define GOTO_UNLESS(cond, msg, label) GOTO_IF(!(cond), msg, ret) #define RETURN_UNLESS(cond, msg, ret) RETURN_IF(!(cond), msg, ret) #define NOTHING /* Usefull to return nothing. */ + +#define STRTOL(ret, str, endptr, err_flag) \ +{ \ + err_flag = 0; \ + errno = 0; \ + ret = str == NULL ? 0 : strtol(str, &(endptr), 0); \ + err_flag = errno != 0 || endptr == str; \ +} diff --git a/meson.build b/meson.build index 6efa4f3825ea75c16910c5109784d5c2e33f67ef..1184051085b5884573f28add51451d9bcd561f50 100644 --- a/meson.build +++ b/meson.build @@ -53,7 +53,6 @@ includes = include_directories('inc') # Server core_deps = [ dependency('sqlite3', version : '>= 3.31.0') - , dependency('libpcre') , dependency('libcurl') , dependency('json-c') , dependency('threads', required : true) diff --git a/src/main/lktadm.c b/src/main/lktadm.c index cb4a68bd24f944484547066f4a6957547ff0f40f..f43d40c28a220f563898e39caa91ef846e29a500 100644 --- a/src/main/lktadm.c +++ b/src/main/lktadm.c @@ -66,16 +66,23 @@ open_db(void) noreturn void help(void) { - printf("Usage for lktadm:\n\n" - " --init: init metadata for all the database according to the root of\n" - " the root of the base\n\n" - " --file <file.mkv, ...>: set automatically metadata for the file file.mkv\n\n" - " --prompt-file <file.mkv, ...>: prompt metadata to put for the file file.mkv\n\n" - " --populate-all: populate the database with whate is found in the fs\n\n" - " --cat <file.mkv, ...>: print the metadata of files\n\n" - " --get-id <id>: print metadata from kurisu with an id\n\n" - " --down-id <id> <path>: download a kara from kurisu to a path\n\n" - " --default-conf: output to stdout the default configuration file\n\n"); + static const char *help__ = + "USAGE lktadm <COMMAND> [ARGS [...]]:\n" + "\n" + "COMMANDS:\n" + " init the init sub command\n" + " get <id> get the metadata of a kara from kurisu\n" + " download <id> <path> download\n" + " cat <path> display the metadata of a mkv file\n" + " conf prints the default config file to stdout\n" + "\n" + "INIT COMMANDS:\n" + " database write the default empty database\n" + " popualte populate the database from the filesystem\n" + " metadata write metadata to mkv files on the disk using theirs path\n" + " file <path> init the metadata for a single file by its path\n" + "\n"; + write(1, help__, strlen(help__)); exit(EXIT_SUCCESS); } @@ -131,6 +138,7 @@ init_populate__(struct lkt_cmd_args *args) noreturn void init_file__(struct lkt_cmd_args *args) { + open_db(); int i; for (i = 0; i < args->argc; ++i) metadata_set_file((char *) args->argv[i], mkvpropedit); @@ -272,6 +280,7 @@ static struct lkt_cmd_opt options_init[] = { { .name = "database", .call = init_database__ }, { .name = "populate", .call = init_populate__ }, { .name = "metadata", .call = init_metadata__ }, + { .name = "file", .call = init_file__ }, LKT_OPT_NULL, }; @@ -293,5 +302,5 @@ static struct lkt_cmd_opt options[] = { int main(int argc, const char **argv) { - lkt_cmd_parse(options, argc, argv, help); + lkt_cmd_parse(options, argc - 1, argv + 1, help); } diff --git a/src/mkv/write.c b/src/mkv/write.c index c29dd79ff08ee87b66cad1430dd10b167aaad400..4ebd6b9cc5f84903e83db2c6acb2fab6c366a534 100644 --- a/src/mkv/write.c +++ b/src/mkv/write.c @@ -1,8 +1,9 @@ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE +#include <lektor/macro.h> +#include <lektor/defines.h> #include <lektor/mkv.h> -#include <pcre.h> #include <stdbool.h> #include <stdio.h> #include <unistd.h> @@ -14,6 +15,8 @@ #include <fcntl.h> #include <sys/stat.h> #include <sys/wait.h> +#include <sys/types.h> +#include <regex.h> static const char *METADATA_TEMPLATE = " <?xml version=\"1.0\" encoding=\"UTF-8\"?> " @@ -138,88 +141,51 @@ error: static bool metadata_from_path(char *const mkvfile, struct kara_metadata *meta) { - pcre *regex = NULL; - pcre_extra *pcre_extra = NULL; - bool sta = false; - const int sub_str_vec_len = 30; - int pcre_error_offset, pcre_exec_ret, sub_str_vec[sub_str_vec_len], i, num; - char num_str[LEKTOR_TAG_MAX]; - const char *substr; - char *copy_to; + static regex_t regex; + static int regex_init = 0; + const size_t nmatch = 10; + regmatch_t pmatch[nmatch]; + int reti, sta = false; + char msgbuf[LEKTOR_TAG_MAX]; + char *endptr; static const char *rgx = - "^\\/(?:.+)\\/(vo|va|amv|cdg|autres|vocaloid)\\/" - "(jp|fr|en|ru|sp|it|ch|latin|multi|undefined)\\/(.+)\\/" - "(.+) - (OP|ED|IS|AMV|VOCA|PV|MV|LIVE)(\\d*) - (.+)\\.mkv$"; - const char *pcre_error_str = NULL; - - if ((regex = pcre_compile(rgx, 0, &pcre_error_str, &pcre_error_offset, NULL)) == NULL) { - fprintf(stderr, " ! metadata_from_path: failed to compile regex\n"); - return false; - } + "^/(.+)/(vo|va|amv|cdg|autres|vocaloid)/" + "(jp|fr|en|ru|sp|it|ch|latin|multi|undefined)/(.+)/" + "(.+) - (OP|ED|IS|AMV|VOCA|PV|MV|LIVE)([[:digit:]]*) - (.+)\\.mkv$"; - pcre_extra = pcre_study(regex, 0, &pcre_error_str); - - if (pcre_error_str != NULL) { - fprintf(stderr, " ! metadata_from_path: failed to study regex: %s\n", pcre_error_str); - goto error; - } + if (!regex_init) + GOTO_IF(regcomp(®ex, rgx, REG_EXTENDED), "Failed to compile regex", error); memset(meta, 0, sizeof(struct kara_metadata)); - memset(num_str, 0, LEKTOR_TAG_MAX * sizeof(char)); - pcre_exec_ret = pcre_exec(regex, pcre_extra, mkvfile, strlen(mkvfile), 0, 0, - sub_str_vec, sub_str_vec_len); - - if (pcre_exec_ret < 0) { - fprintf(stderr, " ! metadata_from_path: PCRE error\n"); + memset(msgbuf, 0, LEKTOR_TAG_MAX * sizeof(char)); + + reti = regexec(®ex, mkvfile, nmatch, pmatch, 0); + if (!reti) { + /* Match */ + memcpy(meta->category, mkvfile + pmatch[2].rm_so, pmatch[2].rm_eo - pmatch[2].rm_so); + memcpy(meta->language, mkvfile + pmatch[3].rm_so, pmatch[3].rm_eo - pmatch[3].rm_so); + memcpy(meta->author_name, mkvfile + pmatch[4].rm_so, pmatch[4].rm_eo - pmatch[4].rm_so); + memcpy(meta->source_name, mkvfile + pmatch[5].rm_so, pmatch[5].rm_eo - pmatch[5].rm_so); + memcpy(meta->song_type, mkvfile + pmatch[6].rm_so, pmatch[6].rm_eo - pmatch[6].rm_so); + memcpy(msgbuf, mkvfile + pmatch[7].rm_so, pmatch[7].rm_eo - pmatch[7].rm_so); + memcpy(meta->song_name, mkvfile + pmatch[8].rm_so, pmatch[8].rm_eo - pmatch[8].rm_so); + } else if (REG_NOMATCH == reti) { + fprintf(stderr, "No match for: %s\n", mkvfile); goto error; - } - - if (pcre_exec_ret == 0) { - // To much -> error in our case // - fprintf(stderr, " ! metadata_from_path: To much matches found for file: %s\n", mkvfile); + } else { + regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); + fprintf(stderr, "Failed to execute regex: %s\n", msgbuf); goto error; } - for (i = 1; i < pcre_exec_ret; ++i) { - pcre_get_substring(mkvfile, sub_str_vec, pcre_exec_ret, i, &substr); - - if (i == 1) - copy_to = meta->song_type; - else if (i == 2) - copy_to = meta->language; - else if (i == 3) - copy_to = meta->author_name; - else if (i == 4) - copy_to = meta->source_name; - else if (i == 5) - copy_to = meta->category; - else if (i == 6) - copy_to = num_str; - else if (i == 7) - copy_to = meta->song_name; - else { - pcre_free_substring(substr); - goto error; - } + STRTOL(meta->song_number, msgbuf, endptr, reti); + if (reti || meta->song_number <= 0) + meta->song_number = 1; - snprintf(copy_to, LEKTOR_TAG_MAX, "%s", substr); - pcre_free_substring(substr); - } - - meta->song_number = ((num = atoi(num_str)) <= 0) ? 1 : num; sta = true; error: - pcre_free(regex); - - if (pcre_extra != NULL) { -#ifdef PCRE_CONFIG_JIT - pcre_free_study(pcre_extra); -#else - pcre_free(pcre_extra); -#endif - } - + regfree(®ex); return sta; }