From: Andre Noll Date: Sun, 31 Jul 2011 23:08:20 +0000 (+0200) Subject: Make vorbis comment helper functions generic. X-Git-Tag: v0.4.9~2^2~5 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=1b218c4cde1c14c5bfbd8f52321ceb16b006de52 Make vorbis comment helper functions generic. copy_comment() and copy_if_tag_type() are useful also to the new flac audio format handler, so move these functions to string.c and make them public. Rename them to safe_strdup() and key_value_copy() respectively, as this is more to the point. --- diff --git a/spx_afh.c b/spx_afh.c index e693c415..a95f234c 100644 --- a/spx_afh.c +++ b/spx_afh.c @@ -57,31 +57,14 @@ struct private_spx_data { struct spx_header_info shi; }; - -static char *copy_comment(const char *src, int len) -{ - char *p = para_malloc(len + 1); - - if (len > 0) - memcpy(p, src, len); - p[len] = '\0'; - PARA_DEBUG_LOG("%s\n", p); - return p; -} - static bool copy_if_tag_type(const char *tag, int taglen, const char *type, char **p) { - int len = strlen(type); - - if (taglen <= len) - return false; - if (strncasecmp(tag, type, len)) - return false; - if (tag[len] != '=') + char *q = key_value_copy(tag, taglen, type); + if (!q) return false; free(*p); - *p = copy_comment(tag + len + 1, taglen - len - 1); + *p = q; return true; } @@ -100,7 +83,7 @@ static int spx_get_comments(unsigned char *comments, int length, c += 4; if (c + len > end) return -E_SPX_COMMENT; - tags->comment = copy_comment(c, len); + tags->comment = safe_strdup(c, len); c += len; if (c + 4 > end) @@ -129,7 +112,7 @@ static int spx_get_comments(unsigned char *comments, int length, continue; if (copy_if_tag_type(c, len, "comment", &tags->comment)) continue; - tag = copy_comment(c, len); + tag = safe_strdup(c, len); PARA_NOTICE_LOG("unrecognized comment: %s\n", tag); free(tag); } diff --git a/string.c b/string.c index cefb45d6..f7d70353 100644 --- a/string.c +++ b/string.c @@ -793,3 +793,56 @@ int para_regcomp(regex_t *preg, const char *regex, int cflags) free(buf); return -E_REGEX; } + +/** + * strdup() for not necessarily zero-terminated strings. + * + * \param src The source buffer. + * \param len The number of bytes to be copied. + * + * \return A 0-terminated buffer of length \a len + 1. + * + * This is similar to strndup(), which is a GNU extension. However, one + * difference is that strndup() returns \p NULL if insufficient memory was + * available while this function aborts in this case. + * + * \sa strdup(), \ref para_strdup(). + */ +char *safe_strdup(const char *src, size_t len) +{ + char *p; + + assert(len < (size_t)-1); + p = para_malloc(len + 1); + if (len > 0) + memcpy(p, src, len); + p[len] = '\0'; + return p; +} + +/** + * Copy the value of a key=value pair. + * + * This checks whether the given buffer starts with "key=", ignoring case. If + * yes, a copy of the value is returned. The source buffer may not be + * zero-terminated. + * + * \param src The source buffer. + * \param len The number of bytes of the tag. + * \param key Only copy if it is the value of this key. + * + * \return A zero-terminated buffer, or \p NULL if the key was + * not of the given type. + */ +char *key_value_copy(const char *src, size_t len, const char *key) +{ + int keylen = strlen(key); + + if (len <= keylen) + return NULL; + if (strncasecmp(src, key, keylen)) + return NULL; + if (src[keylen] != '=') + return NULL; + return safe_strdup(src + keylen + 1, len - keylen - 1); +} diff --git a/string.h b/string.h index 06f4d3e6..403b9c6f 100644 --- a/string.h +++ b/string.h @@ -83,3 +83,5 @@ int create_argv(const char *buf, const char *delim, char ***result); void free_argv(char **argv); int para_regcomp(regex_t *preg, const char *regex, int cflags); void freep(void *arg); +char *safe_strdup(const char *src, size_t len); +char *key_value_copy(const char *src, size_t len, const char *key);