summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/APIchanges3
-rw-r--r--libavutil/avstring.c18
-rw-r--r--libavutil/avstring.h42
-rw-r--r--libavutil/bprint.c45
-rw-r--r--libavutil/bprint.h17
-rw-r--r--libavutil/version.h4
-rw-r--r--tools/ffescape.c93
7 files changed, 147 insertions, 75 deletions
diff --git a/doc/APIchanges b/doc/APIchanges
index 8535d9fe36..a1e81808e7 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,9 @@ libavutil: 2012-10-22
API changes, most recent first:
+2013-03-07 - xxxxxx - lavu 52.18.100 - avstring.h,bprint.h
+ Add av_escape() and av_bprint_escape() API.
+
2013-02-24 - xxxxxx - lavfi 3.41.100 - buffersink.h
Add sample_rates field to AVABufferSinkParams.
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, \
diff --git a/tools/ffescape.c b/tools/ffescape.c
index d777fe4572..0530d28c6d 100644
--- a/tools/ffescape.c
+++ b/tools/ffescape.c
@@ -42,80 +42,16 @@ static void usage(void)
printf("\n"
"Options:\n"
"-e echo each input line on output\n"
+ "-f flag select an escape flag, can assume the values 'whitespace' and 'strict'\n"
"-h print this help\n"
"-i INFILE set INFILE as input file, stdin if omitted\n"
"-l LEVEL set the number of escaping levels, 1 if omitted\n"
- "-m ESCAPE_MODE select escape mode between 'full', 'lazy', 'quote', default is 'lazy'\n"
+ "-m ESCAPE_MODE select escape mode between 'auto', 'backslash', 'quote'\n"
"-o OUTFILE set OUTFILE as output file, stdout if omitted\n"
"-p PROMPT set output prompt, is '=> ' by default\n"
"-s SPECIAL_CHARS set the list of special characters\n");
}
-#define WHITESPACES " \n\t"
-
-enum EscapeMode {
- ESCAPE_MODE_FULL,
- ESCAPE_MODE_LAZY,
- ESCAPE_MODE_QUOTE,
-};
-
-static int escape(char **dst, const char *src, const char *special_chars,
- enum EscapeMode mode)
-{
- AVBPrint dstbuf;
-
- av_bprint_init(&dstbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
-
- switch (mode) {
- case ESCAPE_MODE_FULL:
- case ESCAPE_MODE_LAZY:
- /* \-escape characters */
-
- if (mode == ESCAPE_MODE_LAZY && strchr(WHITESPACES, *src))
- av_bprintf(&dstbuf, "\\%c", *src++);
-
- for (; *src; src++) {
- if ((special_chars && strchr(special_chars, *src)) ||
- strchr("'\\", *src) ||
- (mode == ESCAPE_MODE_FULL && strchr(WHITESPACES, *src)))
- av_bprintf(&dstbuf, "\\%c", *src);
- else
- av_bprint_chars(&dstbuf, *src, 1);
- }
-
- if (mode == ESCAPE_MODE_LAZY && strchr(WHITESPACES, dstbuf.str[dstbuf.len-1])) {
- char c = dstbuf.str[dstbuf.len-1];
- dstbuf.str[dstbuf.len-1] = '\\';
- av_bprint_chars(&dstbuf, c, 1);
- }
- break;
-
- case ESCAPE_MODE_QUOTE:
- /* enclose between '' the string */
- 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;
-
- default:
- /* unknown escape mode */
- return AVERROR(EINVAL);
- }
-
- if (!av_bprint_is_complete(&dstbuf)) {
- av_bprint_finalize(&dstbuf, NULL);
- return AVERROR(ENOMEM);
- } else {
- av_bprint_finalize(&dstbuf, dst);
- return 0;
- }
-}
-
int main(int argc, char **argv)
{
AVBPrint src;
@@ -123,13 +59,14 @@ int main(int argc, char **argv)
const char *outfilename = NULL, *infilename = NULL;
FILE *outfile = NULL, *infile = NULL;
const char *prompt = "=> ";
- enum EscapeMode escape_mode = ESCAPE_MODE_LAZY;
+ enum AVEscapeMode escape_mode = AV_ESCAPE_MODE_AUTO;
+ int escape_flags = 0;
int level = 1;
int echo = 0;
char *special_chars = NULL;
int c;
- while ((c = getopt(argc, argv, "ehi:l:o:m:p:s:")) != -1) {
+ while ((c = getopt(argc, argv, "ef:hi:l:o:m:p:s:")) != -1) {
switch (c) {
case 'e':
echo = 1;
@@ -140,6 +77,16 @@ int main(int argc, char **argv)
case 'i':
infilename = optarg;
break;
+ case 'f':
+ if (!strcmp(optarg, "whitespace")) escape_flags |= AV_ESCAPE_FLAG_WHITESPACE;
+ else if (!strcmp(optarg, "strict")) escape_flags |= AV_ESCAPE_FLAG_STRICT;
+ else {
+ av_log(NULL, AV_LOG_ERROR,
+ "Invalid value '%s' for option -f, "
+ "valid arguments are 'whitespace', and 'strict'\n", optarg);
+ return 1;
+ }
+ break;
case 'l':
{
char *tail;
@@ -154,13 +101,13 @@ int main(int argc, char **argv)
break;
}
case 'm':
- if (!strcmp(optarg, "full")) escape_mode = ESCAPE_MODE_FULL;
- else if (!strcmp(optarg, "lazy")) escape_mode = ESCAPE_MODE_LAZY;
- else if (!strcmp(optarg, "quote")) escape_mode = ESCAPE_MODE_QUOTE;
+ if (!strcmp(optarg, "auto")) escape_mode = AV_ESCAPE_MODE_AUTO;
+ else if (!strcmp(optarg, "backslash")) escape_mode = AV_ESCAPE_MODE_BACKSLASH;
+ else if (!strcmp(optarg, "quote")) escape_mode = AV_ESCAPE_MODE_QUOTE;
else {
av_log(NULL, AV_LOG_ERROR,
"Invalid value '%s' for option -m, "
- "valid arguments are 'full', 'lazy', 'quote'\n", optarg);
+ "valid arguments are 'backslash', and 'quote'\n", optarg);
return 1;
}
break;
@@ -219,7 +166,7 @@ int main(int argc, char **argv)
/* escape */
dst_buf = src_buf;
while (level--) {
- if (escape(&dst_buf, src_buf, special_chars, escape_mode) < 0) {
+ if (av_escape(&dst_buf, src_buf, special_chars, escape_mode, escape_flags) < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not escape string\n");
return 1;
}