[FFmpeg-devel] [PATCH] WIP/lavu: add string interpolation helper.
Clément Bœsch
ubitux at gmail.com
Wed Feb 1 12:01:02 CET 2012
From: Clément Bœsch <clement.boesch at smartjog.com>
---
Hi,
Just a PoC to do some string interpolation easily. This can have various
applications, for instance in segmenter, the -report option or drawtext filter.
Right now, the hash function is just a simple additive one (feel free to
propose anything better), with a fixed size hashtable + linked list in case of
collisions.
Please comment,
PS: the test doesn't do much for collisions, just reduce the hashtable to 2
entries and you'll get some.
---
libavutil/Makefile | 2 +-
libavutil/stringinterp.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++
libavutil/stringinterp.h | 36 ++++++++++
3 files changed, 212 insertions(+), 1 deletions(-)
create mode 100644 libavutil/stringinterp.c
create mode 100644 libavutil/stringinterp.h
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 2cd763c..da3fe7b 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -80,7 +80,7 @@ OBJS-$(ARCH_X86) += x86/cpu.o
TESTPROGS = adler32 aes avstring base64 cpu crc des eval file fifo lfg lls \
- md5 opt pca parseutils rational sha tree
+ md5 opt pca parseutils rational sha tree stringinterp
TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
TOOLS = ffeval
diff --git a/libavutil/stringinterp.c b/libavutil/stringinterp.c
new file mode 100644
index 0000000..dfd0020
--- /dev/null
+++ b/libavutil/stringinterp.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2012 Clément Bœsch
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * string interpolation
+ */
+
+#include "avutil.h"
+#include "avstring.h"
+#include "stringinterp.h"
+
+struct node {
+ const char *key;
+ const char *value;
+ struct node *next;
+};
+
+typedef struct AVStringInter {
+ struct node *hashtable[128];
+} AVStringInter;
+
+AVStringInter *av_stringinterp_alloc(void)
+{
+ AVStringInter *ctx = av_mallocz(sizeof(*ctx));
+ return ctx;
+}
+
+void av_stringinterp_free(AVStringInter **ctx)
+{
+ int i;
+ AVStringInter *s = *ctx;
+ for (i = 0; i < FF_ARRAY_ELEMS(s->hashtable); i++) {
+ struct node *tmp, *node = s->hashtable[i];
+ while (node) {
+ tmp = node;
+ node = node->next;
+ av_freep(&tmp);
+ }
+ }
+ av_freep(ctx);
+}
+
+static uint32_t get_hash(const char *key, size_t len, int tbl_len)
+{
+ size_t i;
+ uint32_t hash = (uint32_t)len;
+ for (i = 0; i < len; i++)
+ hash += key[i];
+ return hash % tbl_len;
+}
+
+static struct node *new_node(const char *key, const char *value)
+{
+ struct node *node = av_mallocz(sizeof(*node));
+ node->key = key;
+ node->value = value;
+ return node;
+}
+
+int av_stringinterp_ref(AVStringInter *ctx, const char *key, const char *value)
+{
+ int id = get_hash(key, strlen(key), FF_ARRAY_ELEMS(ctx->hashtable));
+ struct node *node = ctx->hashtable[id];
+ struct node *insert_after = NULL;
+
+ while (node) {
+ if (!strcmp(key, node->key)) {
+ node->value = value;
+ return 0;
+ }
+ insert_after = node;
+ node = node->next;
+ }
+ if (insert_after)
+ insert_after->next = new_node(key, value);
+ else
+ ctx->hashtable[id] = new_node(key, value);
+ return 0;
+}
+
+static const char *get_value(AVStringInter *ctx, const char *key)
+{
+ int id;
+ size_t keylen;
+ const char *p = strchr(key, ')');
+ struct node *node;
+
+ if (!p)
+ return NULL;
+ keylen = p - key;
+ id = get_hash(key, keylen, FF_ARRAY_ELEMS(ctx->hashtable));
+ for (node = ctx->hashtable[id]; node; node = node->next)
+ if (!strncmp(key, node->key, keylen))
+ return node->value;
+ return NULL;
+}
+
+char *av_stringinterp_interpolate(AVStringInter *ctx, const char *s)
+{
+ char res[256]; // FIXME
+ char *p = res;
+ char *pend = p + sizeof(res);
+
+ while (*s) {
+ if (*s == '%' && *(s+1) == '(') {
+ const char *value = get_value(ctx, s + 2);
+ if (value) {
+ p += snprintf(p, pend-p, "%s", value);
+ s = strchr(s, ')') + 1;
+ continue;
+ }
+ }
+ p += snprintf(p, pend-p, "%c", *s);
+ s++;
+ }
+ return av_strdup(res);
+}
+
+#ifdef TEST
+#undef printf
+static void dump_table(AVStringInter *ctx)
+{
+ int i;
+ printf("Hashtable dump:\n");
+ for (i = 0; i < FF_ARRAY_ELEMS(ctx->hashtable); i++) {
+ struct node *node = ctx->hashtable[i];
+ if (!node)
+ continue;
+ printf(" [%02d/%02d]:", i, FF_ARRAY_ELEMS(ctx->hashtable));
+ while (node) {
+ printf(" \"%s\"=>\"%s\"", node->key, node->value);
+ node = node->next;
+ }
+ printf("\n");
+ }
+}
+
+int main(int ac, char **av)
+{
+ AVStringInter *si = av_stringinterp_alloc();
+ char *res;
+
+ av_stringinterp_ref(si, "ts1", "0.4123");
+ av_stringinterp_ref(si, "ts2", "54.153");
+ av_stringinterp_ref(si, "filename", "FooBar");
+ av_stringinterp_ref(si, "ext", ".mpg");
+ av_stringinterp_ref(si, "ext", ".mp4");
+
+ dump_table(si);
+
+ res = av_stringinterp_interpolate(si, "%(filename)_%(ts1)-%(ts2)_%(nokey)%(ext)");
+ printf("%s\n", res);
+ av_free(res);
+ av_stringinterp_free(&si);
+ return 0;
+}
+#endif
diff --git a/libavutil/stringinterp.h b/libavutil/stringinterp.h
new file mode 100644
index 0000000..9f75ae9
--- /dev/null
+++ b/libavutil/stringinterp.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 Clément Bœsch
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * string interpolation header
+ */
+
+#ifndef AVUTIL_STRINGINTERP_H
+#define AVUTIL_STRINGINTERP_H
+
+typedef struct AVStringInter AVStringInter;
+
+AVStringInter *av_stringinterp_alloc(void);
+void av_stringinterp_free(AVStringInter **ctx);
+int av_stringinterp_ref(AVStringInter *ctx, const char *key, const char *value);
+char *av_stringinterp_interpolate(AVStringInter *ctx, const char *s);
+
+#endif/* AVUTIL_STRINGINTERP_H */
--
1.7.8.3
More information about the ffmpeg-devel
mailing list