[FFmpeg-devel] [PATCH 1/2] lavu: add av_bprintf and related.

Nicolas George nicolas.george at normalesup.org
Wed Feb 1 21:37:00 CET 2012


Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
 libavutil/avstring.c |   91 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/avstring.h |   40 ++++++++++++++++++++++
 2 files changed, 131 insertions(+), 0 deletions(-)


Sorry for the noise, I did not think I would have time to finish it so soon
and did not want to risk someone else working on the same thing at the same
time.


diff --git a/libavutil/avstring.c b/libavutil/avstring.c
index 76f6bb2..17d9b72 100644
--- a/libavutil/avstring.c
+++ b/libavutil/avstring.c
@@ -210,6 +210,97 @@ int av_strncasecmp(const char *a, const char *b, size_t n)
     return c1 - c2;
 }
 
+int av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
+{
+    char *str = NULL;
+
+    if (size_init) {
+        if (size_max < size_init)
+            return AVERROR(EINVAL);
+        str = av_malloc(size_init);
+        if (!str)
+            return AVERROR(ENOMEM);
+        *str = 0;
+    } else {
+        if (size_max)
+            return AVERROR(EINVAL);
+    }
+    buf->str      = str;
+    buf->len      = 0;
+    buf->size     = size_init;
+    buf->size_max = size_max;
+    return 0;
+}
+
+static int av_bprint_grow(AVBPrint *buf)
+{
+    unsigned new_size = buf->size > buf->size_max / 2 ? buf->size_max :
+                                                        buf->size * 2;
+    char *new_str = av_realloc(buf->str, new_size);
+    if (!new_str)
+        return -1;
+    buf->str  = new_str;
+    buf->size = new_size;
+    return 0;
+}
+
+#define av_bprint_room(buf) ((buf)->size - FFMIN((buf)->len, (buf)->size))
+
+void av_bprintf(AVBPrint *buf, const char *fmt, ...)
+{
+    unsigned room;
+    char *dst;
+    va_list vl;
+    int add;
+
+    while (1) {
+        room = av_bprint_room(buf);
+        dst = room ? buf->str + buf->len : NULL;
+        va_start(vl, fmt);
+        add = vsnprintf(dst, room, fmt, vl);
+        va_end(vl);
+        if (add <= 0)
+            return;
+        if (add < room || buf->size == buf->size_max)
+            break;
+        if (av_bprint_grow(buf))
+            break;
+    }
+    add = FFMIN(add, UINT_MAX - 5 - buf->len);
+    buf->len += add;
+}
+
+void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
+{
+    unsigned room, real_n;
+
+    while (1) {
+        room = av_bprint_room(buf);
+        if (n < room || buf->size == buf->size_max)
+            break;
+        if (av_bprint_grow(buf))
+            break;
+    }
+    if (room) {
+        real_n = FFMIN(n, room - 1);
+        memset(buf->str + buf->len, c, real_n);
+        buf->str[buf->len + real_n] = 0;
+    }
+    buf->len += FFMIN(n, UINT_MAX - 5 - buf->len);
+}
+
+void av_bprint_shrink(AVBPrint *buf)
+{
+
+    if (buf->len + 1 < buf->size) { 
+        char *str;
+        buf->size = buf->size_max = buf->len + 1;
+        str = av_realloc(buf->str, buf->size);
+        if (str)
+            buf->str = str;
+    }
+}
+
 #ifdef TEST
 
 #undef printf
diff --git a/libavutil/avstring.h b/libavutil/avstring.h
index f73d6e7..8917ec8 100644
--- a/libavutil/avstring.h
+++ b/libavutil/avstring.h
@@ -203,6 +203,46 @@ int av_strcasecmp(const char *a, const char *b);
 int av_strncasecmp(const char *a, const char *b, size_t n);
 
 /**
+ * Buffer to print data progressively
+ * The string buffer grows as necessary and is always 0-terminated.
+ * The length of the string can go beyond the allocated size: the buffer is
+ * then truncated, but the functions still keep account of the required
+ * size.
+ * The string buffer can be stolen and/or freed using av_free.
+ * If size == 0, no allocation is made, the system only counts the size.
+ */
+typedef struct AVBPrint {
+    char *str;         /** string so far; or NULL if size == 0 */
+    unsigned len;      /** length so far */
+    unsigned size;     /** allocated memory */
+    unsigned size_max; /** maximum allocated memory */
+} AVBPrint;
+
+/**
+ * Init a print buffer
+ * @param buf        buffer to init
+ * @param size_init  initial size (including the final 0)
+ * @param size_max   maximum size
+ * @return  0 or error code (probably AVERROR(ENOMEM))
+ */
+int av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max);
+
+/**
+ * Append a formated string to a print buffer
+ */
+void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3);
+
+/**
+ * Append n times char c to a print buffer
+ */
+void av_bprint_chars(AVBPrint *buf, char c, unsigned n);
+
+/**
+ * Shrinks the allocated buffer to fit the string.
+ */
+void av_bprint_shrink(AVBPrint *buf);
+
+/**
  * @}
  */
 
-- 
1.7.8.3



More information about the ffmpeg-devel mailing list