diff --git a/doc/APIchanges b/doc/APIchanges index f8dcc9911f..b1beb9dab8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2014-08-09 API changes, most recent first: +2015-xx-xx - xxxxxxx - lavu 54.22.100 - avstring.h + Add av_append_path_component() + 2015-03-27 - 184084c - lavf 56.27.100 - avio.h url.h New directory listing API. diff --git a/libavutil/avstring.c b/libavutil/avstring.c index 25c65b4238..670801e83f 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -269,6 +269,37 @@ const char *av_dirname(char *path) return path; } +char *av_append_path_component(const char *path, const char *component) +{ + size_t p_len, c_len; + char *fullpath; + + if (!path) + return av_strdup(component); + if (!component) + return av_strdup(path); + + p_len = strlen(path); + c_len = strlen(component); + if (p_len > SIZE_MAX - c_len || p_len + c_len > SIZE_MAX - 2) + return NULL; + fullpath = av_malloc(p_len + c_len + 2); + if (fullpath) { + if (p_len) { + av_strlcpy(fullpath, path, p_len + 1); + if (c_len) { + if (fullpath[p_len - 1] != '/' && component[0] != '/') + fullpath[p_len++] = '/'; + else if (fullpath[p_len - 1] == '/' && component[0] == '/') + p_len--; + } + } + av_strlcpy(&fullpath[p_len], component, c_len + 1); + fullpath[p_len + c_len] = 0; + } + return fullpath; +} + int av_escape(char **dst, const char *src, const char *special_chars, enum AVEscapeMode mode, int flags) { @@ -427,6 +458,7 @@ int av_match_list(const char *name, const char *list, char separator) int main(void) { int i; + char *fullpath; static const char * const strings[] = { "''", "", @@ -467,6 +499,19 @@ int main(void) av_free(q); } + printf("Testing av_append_path_component()\n"); + #define TEST_APPEND_PATH_COMPONENT(path, component, expected) \ + fullpath = av_append_path_component((path), (component)); \ + printf("%s = %s\n", fullpath, expected); \ + av_free(fullpath); + TEST_APPEND_PATH_COMPONENT(NULL, NULL, "(null)") + TEST_APPEND_PATH_COMPONENT("path", NULL, "path"); + TEST_APPEND_PATH_COMPONENT(NULL, "comp", "comp"); + TEST_APPEND_PATH_COMPONENT("path", "comp", "path/comp"); + TEST_APPEND_PATH_COMPONENT("path/", "comp", "path/comp"); + TEST_APPEND_PATH_COMPONENT("path", "/comp", "path/comp"); + TEST_APPEND_PATH_COMPONENT("path/", "/comp", "path/comp"); + TEST_APPEND_PATH_COMPONENT("path/path2/", "/comp/comp2", "path/path2/comp/comp2"); return 0; } diff --git a/libavutil/avstring.h b/libavutil/avstring.h index ffb7aa6bfa..466edaf968 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -276,6 +276,16 @@ const char *av_dirname(char *path); */ int av_match_name(const char *name, const char *names); +/** + * Append path component to the existing path. + * Path separator '/' is placed between when needed. + * Resulting string have to be freed with av_free(). + * @param path base path + * @param component component to be appended + * @return new path or NULL on error. + */ +char *av_append_path_component(const char *path, const char *component); + enum AVEscapeMode { AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. diff --git a/libavutil/version.h b/libavutil/version.h index 4d710dd4e2..30be0f0f89 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -56,7 +56,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 54 -#define LIBAVUTIL_VERSION_MINOR 21 +#define LIBAVUTIL_VERSION_MINOR 22 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/tests/ref/fate/avstring b/tests/ref/fate/avstring index bc231e8148..1ca9be52ed 100644 --- a/tests/ref/fate/avstring +++ b/tests/ref/fate/avstring @@ -25,3 +25,12 @@ Testing av_get_token() |'foo : \ \ ' : blahblah| -> |foo : \ \ | + |: blahblah| |'\fo\o:': blahblah| -> |\fo\o:| + |: blahblah| |\'fo\o\:': foo ' :blahblah| -> |'foo:: foo | + |:blahblah| +Testing av_append_path_component() +(null) = (null) +path = path +comp = comp +path/comp = path/comp +path/comp = path/comp +path/comp = path/comp +path/comp = path/comp +path/path2/comp/comp2 = path/path2/comp/comp2