diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2012-11-10 16:05:53 +0100 |
---|---|---|
committer | Nicolas George <nicolas.george@normalesup.org> | 2012-11-17 19:47:56 +0100 |
commit | 4cd74c81435919e7ed1a30de5d947d3077ac9299 (patch) | |
tree | 7aabaacb4fe90cef65dec800d7194929907be82b | |
parent | f96a653184e63cea91e08ea75ae60d309e431f40 (diff) | |
download | ffmpeg-4cd74c81435919e7ed1a30de5d947d3077ac9299.tar.gz |
lavu/bprint: implement av_bprint_strftime().
-rw-r--r-- | doc/APIchanges | 3 | ||||
-rw-r--r-- | libavutil/bprint.c | 53 | ||||
-rw-r--r-- | libavutil/bprint.h | 16 | ||||
-rw-r--r-- | libavutil/version.h | 2 | ||||
-rw-r--r-- | tests/ref/fate/bprint | 2 |
5 files changed, 74 insertions, 2 deletions
diff --git a/doc/APIchanges b/doc/APIchanges index 1d10af5962..57be6ba735 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2012-11-17 - xxxxxxx - lavu 52.8.100 - bprint.h + Add av_bprint_strftime(). + 2012-11-15 - xxxxxxx - lavu 52.7.100 - opt.h Add av_opt_get_key_value(). diff --git a/libavutil/bprint.c b/libavutil/bprint.c index 9d8e7c18ab..4684ab4979 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -21,6 +21,7 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> +#include <time.h> #include "avassert.h" #include "bprint.h" #include "common.h" @@ -129,6 +130,48 @@ void av_bprint_chars(AVBPrint *buf, char c, unsigned n) av_bprint_grow(buf, n); } +void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm) +{ + unsigned room; + size_t l; + + if (!*fmt) + return; + while (1) { + room = av_bprint_room(buf); + if (room && (l = strftime(buf->str + buf->len, room, fmt, tm))) + break; + /* strftime does not tell us how much room it would need: let us + retry with twice as much until the buffer is large enough */ + room = !room ? strlen(fmt) + 1 : + room <= INT_MAX / 2 ? room * 2 : INT_MAX; + if (av_bprint_alloc(buf, room)) { + /* impossible to grow, try to manage something useful anyway */ + room = av_bprint_room(buf); + if (room < 1024) { + /* if strftime fails because the buffer has (almost) reached + its maximum size, let us try in a local buffer; 1k should + be enough to format any real date+time string */ + char buf2[1024]; + if ((l = strftime(buf2, sizeof(buf2), fmt, tm))) { + av_bprintf(buf, "%s", buf2); + return; + } + } + if (room) { + /* if anything else failed and the buffer is not already + truncated, let us add a stock string and force truncation */ + static const char txt[] = "[truncated strftime output]"; + memset(buf->str + buf->len, '!', room); + memcpy(buf->str + buf->len, txt, FFMIN(sizeof(txt) - 1, room)); + av_bprint_grow(buf, room); /* force truncation */ + } + return; + } + } + av_bprint_grow(buf, l); +} + void av_bprint_get_buffer(AVBPrint *buf, unsigned size, unsigned char **mem, unsigned *actual_size) { @@ -201,6 +244,7 @@ int main(void) { AVBPrint b; char buf[256]; + struct tm testtime = { .tm_year = 100, .tm_mon = 11, .tm_mday = 20 }; av_bprint_init(&b, 0, -1); bprint_pascal(&b, 5); @@ -235,6 +279,15 @@ int main(void) bprint_pascal(&b, 25); printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(buf), b.len); + av_bprint_init(&b, 0, -1); + av_bprint_strftime(&b, "%Y-%m-%d", &testtime); + printf("strftime full: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str); + av_bprint_finalize(&b, NULL); + + av_bprint_init(&b, 0, 8); + av_bprint_strftime(&b, "%Y-%m-%d", &testtime); + printf("strftime truncated: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str); + return 0; } diff --git a/libavutil/bprint.h b/libavutil/bprint.h index c09b61f20f..f3915fe7b1 100644 --- a/libavutil/bprint.h +++ b/libavutil/bprint.h @@ -116,7 +116,7 @@ void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max); void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size); /** - * Append a formated string to a print buffer. + * Append a formatted string to a print buffer. */ void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3); @@ -125,6 +125,20 @@ void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3); */ void av_bprint_chars(AVBPrint *buf, char c, unsigned n); +struct tm; +/** + * Append a formatted date and time to a print buffer. + * + * param buf bprint buffer to use + * param fmt date and time format string, see strftime() + * param tm broken-down time structure to translate + * + * @note due to poor design of the standard strftime function, it may + * produce poor results if the format string expands to a very long text and + * the bprint buffer is near the limit stated by the size_max option. + */ +void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm); + /** * Allocate bytes in the buffer for external use. * diff --git a/libavutil/version.h b/libavutil/version.h index 3f82a974c5..16771ade06 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -75,7 +75,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 7 +#define LIBAVUTIL_VERSION_MINOR 8 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/tests/ref/fate/bprint b/tests/ref/fate/bprint index e027fa16be..b33c1ae6e7 100644 --- a/tests/ref/fate/bprint +++ b/tests/ref/fate/bprint @@ -12,3 +12,5 @@ Short text in automatic buffer: 174/174 Long text in automatic buffer: 1000/2834 Long text count only buffer: 0/2834 Long text count only buffer: 255/2834 +strftime full: 255/10 "2000-12-20" +strftime truncated: 255/10 "2000-12" |