diff options
author | Stefano Sabatini <stefasab@gmail.com> | 2012-12-16 12:17:23 +0100 |
---|---|---|
committer | Stefano Sabatini <stefasab@gmail.com> | 2013-03-07 01:12:04 +0100 |
commit | 9767ec6b865c35f68cb6642fefeacc009f17e638 (patch) | |
tree | 6a887bbb054464e240e17d3d185ba0b2e6b63290 /libavutil | |
parent | 38d40ac18a3855620852e6552114caeb413497eb (diff) | |
download | ffmpeg-9767ec6b865c35f68cb6642fefeacc009f17e638.tar.gz |
lavu: add escape API
The escape API will be useful to perform escaping programmatically, which
is required when crafting argument strings, and will be used for context
printing as well.
This is based on the ffescape tool code, with a few extensions and fixes.
Diffstat (limited to 'libavutil')
-rw-r--r-- | libavutil/avstring.c | 18 | ||||
-rw-r--r-- | libavutil/avstring.h | 42 | ||||
-rw-r--r-- | libavutil/bprint.c | 45 | ||||
-rw-r--r-- | libavutil/bprint.h | 17 | ||||
-rw-r--r-- | libavutil/version.h | 4 |
5 files changed, 124 insertions, 2 deletions
diff --git a/libavutil/avstring.c b/libavutil/avstring.c index 9ad1e12711..45f8d78172 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -28,6 +28,7 @@ #include "common.h" #include "mem.h" #include "avstring.h" +#include "bprint.h" int av_strstart(const char *str, const char *pfx, const char **ptr) { @@ -267,6 +268,23 @@ const char *av_dirname(char *path) return path; } +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags) +{ + AVBPrint dstbuf; + + av_bprint_init(&dstbuf, 1, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_escape(&dstbuf, src, special_chars, mode, flags); + + if (!av_bprint_is_complete(&dstbuf)) { + av_bprint_finalize(&dstbuf, NULL); + return AVERROR(ENOMEM); + } else { + av_bprint_finalize(&dstbuf, dst); + return dstbuf.len; + } +} + #ifdef TEST int main(void) diff --git a/libavutil/avstring.h b/libavutil/avstring.h index 3896b5f2bb..5b078f15ae 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -266,6 +266,48 @@ const char *av_basename(const char *path); */ const char *av_dirname(char *path); +enum AVEscapeMode { + AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode. + AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping. + AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping. +}; + +/** + * Consider spaces special and escape them even in the middle of the + * string. + * + * This is equivalent to adding the whitespace characters to the special + * characters lists, except it is guaranteed to use the exact same list + * of whitespace characters as the rest of libavutil. + */ +#define AV_ESCAPE_FLAG_WHITESPACE 0x01 + +/** + * Escape only specified special characters. + * Without this flag, escape also any characters that may be considered + * special by av_get_token(), such as the single quote. + */ +#define AV_ESCAPE_FLAG_STRICT 0x02 + +/** + * Escape string in src, and put the escaped string in an allocated + * string in *dst, which must be freed with av_free(). + * + * @param dst pointer where an allocated string is put + * @param src string to escape, must be non-NULL + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros + * @return the length of the allocated string, or a negative error code in case of error + * @see av_bprint_escape() + */ +int av_escape(char **dst, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + /** * @} */ diff --git a/libavutil/bprint.c b/libavutil/bprint.c index 4684ab4979..fd7611aaed 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -23,6 +23,7 @@ #include <string.h> #include <time.h> #include "avassert.h" +#include "avstring.h" #include "bprint.h" #include "common.h" #include "error.h" @@ -217,6 +218,50 @@ int av_bprint_finalize(AVBPrint *buf, char **ret_str) return ret; } +#define WHITESPACES " \n\t" + +void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags) +{ + const char *src0 = src; + + if (mode == AV_ESCAPE_MODE_AUTO) + mode = AV_ESCAPE_MODE_BACKSLASH; /* TODO: implement a heuristic */ + + switch (mode) { + case AV_ESCAPE_MODE_QUOTE: + /* enclose the string between '' */ + av_bprint_chars(dstbuf, '\'', 1); + for (; *src; src++) { + if (*src == '\'') + av_bprintf(dstbuf, "'\\''"); + else + av_bprint_chars(dstbuf, *src, 1); + } + av_bprint_chars(dstbuf, '\'', 1); + break; + + /* case AV_ESCAPE_MODE_BACKSLASH or unknown mode */ + default: + /* \-escape characters */ + for (; *src; src++) { + int is_first_last = src == src0 || !*(src+1); + int is_ws = !!strchr(WHITESPACES, *src); + int is_strictly_special = special_chars && strchr(special_chars, *src); + int is_special = + is_strictly_special || strchr("'\\", *src) || + (is_ws && (flags & AV_ESCAPE_FLAG_WHITESPACE)); + + if (is_strictly_special || + (!(flags & AV_ESCAPE_FLAG_STRICT) && + (is_special || (is_ws && is_first_last)))) + av_bprint_chars(dstbuf, '\\', 1); + av_bprint_chars(dstbuf, *src, 1); + } + break; + } +} + #ifdef TEST #undef printf diff --git a/libavutil/bprint.h b/libavutil/bprint.h index f3915fe7b1..df78916f4a 100644 --- a/libavutil/bprint.h +++ b/libavutil/bprint.h @@ -22,6 +22,7 @@ #define AVUTIL_BPRINT_H #include "attributes.h" +#include "avstring.h" /** * Define a structure with extra padding to a fixed size @@ -180,4 +181,20 @@ static inline int av_bprint_is_complete(AVBPrint *buf) */ int av_bprint_finalize(AVBPrint *buf, char **ret_str); +/** + * Escape the content in src and append it to dstbuf. + * + * @param dstbuf already inited destination bprint buffer + * @param src string containing the text to escape + * @param special_chars string containing the special characters which + * need to be escaped, can be NULL + * @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros. + * Any unknown value for mode will be considered equivalent to + * AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without + * notice. + * @param flags flags which control how to escape, see AV_ESCAPE_FLAG_* macros + */ +void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars, + enum AVEscapeMode mode, int flags); + #endif /* AVUTIL_BPRINT_H */ diff --git a/libavutil/version.h b/libavutil/version.h index cf65fff5f3..4cd82268db 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -75,8 +75,8 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 17 -#define LIBAVUTIL_VERSION_MICRO 103 +#define LIBAVUTIL_VERSION_MINOR 18 +#define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ |