summaryrefslogtreecommitdiff
path: root/libavutil/bprint.c
diff options
context:
space:
mode:
authorNicolas George <nicolas.george@normalesup.org>2012-11-10 16:05:53 +0100
committerNicolas George <nicolas.george@normalesup.org>2012-11-17 19:47:56 +0100
commit4cd74c81435919e7ed1a30de5d947d3077ac9299 (patch)
tree7aabaacb4fe90cef65dec800d7194929907be82b /libavutil/bprint.c
parentf96a653184e63cea91e08ea75ae60d309e431f40 (diff)
downloadffmpeg-4cd74c81435919e7ed1a30de5d947d3077ac9299.tar.gz
lavu/bprint: implement av_bprint_strftime().
Diffstat (limited to 'libavutil/bprint.c')
-rw-r--r--libavutil/bprint.c53
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;
}