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 /libavutil/bprint.c | |
parent | f96a653184e63cea91e08ea75ae60d309e431f40 (diff) | |
download | ffmpeg-4cd74c81435919e7ed1a30de5d947d3077ac9299.tar.gz |
lavu/bprint: implement av_bprint_strftime().
Diffstat (limited to 'libavutil/bprint.c')
-rw-r--r-- | libavutil/bprint.c | 53 |
1 files changed, 53 insertions, 0 deletions
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; } |