X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mysql_selector.c;h=f8885f9a0f50ea0dd185e4cbecbc3a0ab17d1d0e;hp=91972e84ab0c179fba33129a811d171bd1c00021;hb=7598d7747435c4de259df09bdb82911ff893113d;hpb=f05276c4bf63c327da914ed4aae2568f38e47892 diff --git a/mysql_selector.c b/mysql_selector.c index 91972e84..f8885f9a 100644 --- a/mysql_selector.c +++ b/mysql_selector.c @@ -28,6 +28,7 @@ #include "db.h" #include #include +#include #include "error.h" #include "net.h" #include "string.h" @@ -39,6 +40,18 @@ extern struct misc_meta_data *mmd; static void *mysql_ptr = NULL; +/** + * contains name/replacement pairs used by s_a_r_list() + * + * \sa s_a_r() + */ +struct para_macro { + /** the name of the macro */ + const char *name; + /** the replacement text */ + const char *replacement; +}; + static struct para_macro macro_list[] = { { .name = "IS_N_SET", .replacement = "(data.%s != '1')" @@ -63,6 +76,93 @@ static struct para_macro macro_list[] = { } }; +/** + * simple search and replace routine + * + * \param src source string + * \param macro_name the name of the macro + * \param replacement the replacement format string + * + * In \p src, replace each occurence of \p macro_name(arg) by the string + * determined by the \p replacement format string. \p replacement may (but + * needs not) contain a single string conversion specifier (%s) which gets + * replaced by \p arg. + * + * \return A string in which all matches in \p src are replaced, or \p NULL if + * an syntax error was encountered. Caller must free the result. + * + * \sa regcomp(3) + */ +__must_check __malloc static char *s_a_r(const char *src, const char* macro_name, + const char *replacement) +{ + regex_t preg; + size_t nmatch = 1; + regmatch_t pmatch[1]; + int eflags = 0; + char *dest = NULL; + const char *bufptr = src; + + if (!macro_name || !replacement || !src) + return para_strdup(src); + regcomp(&preg, macro_name, 0); + while (regexec(&preg, bufptr, nmatch, pmatch, eflags) + != REG_NOMATCH) { + char *tmp, *arg, *o_bracket, *c_bracket; + + o_bracket = strchr(bufptr + pmatch[0].rm_so, '('); + c_bracket = o_bracket? strchr(o_bracket, ')') : NULL; + if (!c_bracket) + goto out; + tmp = para_strdup(bufptr); + tmp[pmatch[0].rm_so] = '\0'; + dest = para_strcat(dest, tmp); + free(tmp); + + arg = para_strdup(o_bracket + 1); + arg[c_bracket - o_bracket - 1] = '\0'; + tmp = make_message(replacement, arg); + free(arg); + dest = para_strcat(dest, tmp); + free(tmp); + bufptr = c_bracket; + bufptr++; + } + dest = para_strcat(dest, bufptr); +// PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); +out: + regfree(&preg); + return dest; +} + +/** + * replace a string according to a list of macros + * + * \param macro_list the array containing a macro/replacement pairs. + * \param src the source string + * + * This function just calls s_a_r() for each element of \p macro_list. + * + * \return \p NULL if one of the underlying calls to \p s_a_r returned \p NULL. + * Otherwise the completely expanded version of \p src is returned. + */ +__must_check __malloc static char *s_a_r_list(struct para_macro *macro_list, char *src) +{ + struct para_macro *mp = macro_list; + char *ret = NULL, *tmp = para_strdup(src); + + while (mp->name) { + ret = s_a_r(tmp, mp->name, mp->replacement); + free(tmp); + if (!ret) /* syntax error */ + return NULL; + tmp = ret; + mp++; + } + //PARA_DEBUG_LOG("%s: returning %s\n", __func__, dest); + return ret; +} + static int real_query(const char *query) { if (!mysql_ptr) @@ -2152,8 +2252,15 @@ static void shutdown_connection(void) /** * the init function of the mysql-based audio file selector * - * Check the command line options and initialize all function pointers of \a db. - * Connect to the mysql server and initialize the info string. + * \param db pointer to the struct to initialize + * + * Check the command line options and initialize all function pointers of \a + * db. Connect to the mysql server and initialize the info string. + * + * \return This function returns success even if it could not connect + * to the mysql server. This is because the connect is expected to fail + * if there the paraslash database is not yet created. This gives the + * user a chance to send the "cdb" to create the database. * * \sa struct audio_file_selector, misc_meta_data::selector_info, * random_selector.c