[FFmpeg-devel] [PATCH 3/9] fftools/textformat: Introduce common header and deduplicate code
softworkz
ffmpegagent at gmail.com
Mon Apr 14 15:47:00 EEST 2025
From: softworkz <softworkz at hotmail.com>
Signed-off-by: softworkz <softworkz at hotmail.com>
---
fftools/textformat/avtextwriters.h | 2 +-
fftools/textformat/tf_compact.c | 31 ++++-------
fftools/textformat/tf_default.c | 27 +++-------
fftools/textformat/tf_flat.c | 27 +++-------
fftools/textformat/tf_ini.c | 24 +++------
fftools/textformat/tf_internal.h | 85 ++++++++++++++++++++++++++++++
fftools/textformat/tf_json.c | 38 +++++--------
fftools/textformat/tf_xml.c | 35 +++++-------
fftools/textformat/tw_avio.c | 7 +--
fftools/textformat/tw_buffer.c | 7 +--
fftools/textformat/tw_stdout.c | 8 +--
11 files changed, 150 insertions(+), 141 deletions(-)
create mode 100644 fftools/textformat/tf_internal.h
diff --git a/fftools/textformat/avtextwriters.h b/fftools/textformat/avtextwriters.h
index 9438d21802..0c2ed21a6f 100644
--- a/fftools/textformat/avtextwriters.h
+++ b/fftools/textformat/avtextwriters.h
@@ -41,7 +41,7 @@ typedef struct AVTextWriter {
void (*uninit)(AVTextWriterContext *wctx);
void (*writer_w8)(AVTextWriterContext *wctx, int b);
void (*writer_put_str)(AVTextWriterContext *wctx, const char *str);
- void (*writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
+ void (*writer_printf)(AVTextWriterContext *wctx, const char *fmt, va_list vl);
} AVTextWriter;
typedef struct AVTextWriterContext {
diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
index 298b840739..52bc8ad927 100644
--- a/fftools/textformat/tf_compact.c
+++ b/fftools/textformat/tf_compact.c
@@ -25,6 +25,7 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
@@ -33,22 +34,6 @@
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
/* Compact output */
@@ -160,9 +145,12 @@ static av_cold int compact_init(AVTextFormatContext *wctx)
static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
{
CompactContext *compact = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
+
+ if (!section)
+ return;
+
compact->terminate_line[wctx->level] = 1;
compact->has_nested_elems[wctx->level] = 0;
@@ -213,8 +201,11 @@ static void compact_print_section_header(AVTextFormatContext *wctx, const void *
static void compact_print_section_footer(AVTextFormatContext *wctx)
{
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
CompactContext *compact = wctx->priv;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+
+ if (!section)
+ return;
if (!compact->nested_section[wctx->level] &&
compact->terminate_line[wctx->level] &&
diff --git a/fftools/textformat/tf_default.c b/fftools/textformat/tf_default.c
index 3b05d25f36..a9b247c769 100644
--- a/fftools/textformat/tf_default.c
+++ b/fftools/textformat/tf_default.c
@@ -25,26 +25,12 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
/* Default output */
typedef struct DefaultContext {
@@ -82,9 +68,11 @@ static void default_print_section_header(AVTextFormatContext *wctx, const void *
{
DefaultContext *def = wctx->priv;
char buf[32];
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
+
+ if (!section)
+ return;
av_bprint_clear(&wctx->section_pbuf[wctx->level]);
if (parent_section &&
@@ -106,7 +94,8 @@ static void default_print_section_header(AVTextFormatContext *wctx, const void *
static void default_print_section_footer(AVTextFormatContext *wctx)
{
DefaultContext *def = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+
char buf[32];
if (!section)
diff --git a/fftools/textformat/tf_flat.c b/fftools/textformat/tf_flat.c
index 41a6b1c812..c0a8d8c437 100644
--- a/fftools/textformat/tf_flat.c
+++ b/fftools/textformat/tf_flat.c
@@ -25,6 +25,7 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
@@ -32,23 +33,7 @@
#include <libavutil/macros.h>
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-
-/* Flat output */
+ /* Flat output */
typedef struct FlatContext {
const AVClass *class;
@@ -121,9 +106,11 @@ static void flat_print_section_header(AVTextFormatContext *wctx, const void *dat
{
FlatContext *flat = wctx->priv;
AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
+
+ if (!section)
+ return;
/* build section header */
av_bprint_clear(buf);
diff --git a/fftools/textformat/tf_ini.c b/fftools/textformat/tf_ini.c
index ec471fd480..e9a11fde99 100644
--- a/fftools/textformat/tf_ini.c
+++ b/fftools/textformat/tf_ini.c
@@ -25,26 +25,12 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
/* Default output */
typedef struct DefaultContext {
@@ -105,9 +91,11 @@ static void ini_print_section_header(AVTextFormatContext *wctx, const void *data
{
INIContext *ini = wctx->priv;
AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
+
+ if (!section)
+ return;
av_bprint_clear(buf);
if (!parent_section) {
diff --git a/fftools/textformat/tf_internal.h b/fftools/textformat/tf_internal.h
new file mode 100644
index 0000000000..7b326328cb
--- /dev/null
+++ b/fftools/textformat/tf_internal.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * 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
+ * Internal utilities for text formatters.
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_TF_INTERNAL_H
+#define FFTOOLS_TEXTFORMAT_TF_INTERNAL_H
+
+#include "avtextformat.h"
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/**
+ * Safely validate and access a section at a given level
+ */
+static inline const AVTextFormatSection *tf_get_section(AVTextFormatContext *tfc, int level)
+{
+ if (!tfc || level < 0 || level >= SECTION_MAX_NB_LEVELS || !tfc->section[level]) {
+ if (tfc)
+ av_log(tfc, AV_LOG_ERROR, "Invalid section access at level %d\n", level);
+ return NULL;
+ }
+ return tfc->section[level];
+}
+
+/**
+ * Safely access the parent section
+ */
+static inline const AVTextFormatSection *tf_get_parent_section(AVTextFormatContext *tfc, int level)
+{
+ if (level <= 0)
+ return NULL;
+
+ return tf_get_section(tfc, level - 1);
+}
+
+static inline void writer_w8(AVTextFormatContext *wctx, int b)
+{
+ wctx->writer->writer->writer_w8(wctx->writer, b);
+}
+
+static inline void writer_put_str(AVTextFormatContext *wctx, const char *str)
+{
+ wctx->writer->writer->writer_put_str(wctx->writer, str);
+}
+
+static inline void writer_printf(AVTextFormatContext *wctx, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ wctx->writer->writer->writer_printf(wctx->writer, fmt, args);
+ va_end(args);
+}
+
+#endif /* FFTOOLS_TEXTFORMAT_TF_INTERNAL_H */
diff --git a/fftools/textformat/tf_json.c b/fftools/textformat/tf_json.c
index f286838d3c..a8f23a989f 100644
--- a/fftools/textformat/tf_json.c
+++ b/fftools/textformat/tf_json.c
@@ -25,27 +25,12 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-
/* JSON output */
typedef struct JSONContext {
@@ -105,13 +90,14 @@ static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx
static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
{
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
JSONContext *json = wctx->priv;
AVBPrint buf;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- if (wctx->level && wctx->nb_item[wctx->level-1])
+ if (!section)
+ return;
+
if (wctx->level && wctx->nb_item[wctx->level - 1])
writer_put_str(wctx, ",\n");
@@ -145,8 +131,11 @@ static void json_print_section_header(AVTextFormatContext *wctx, const void *dat
static void json_print_section_footer(AVTextFormatContext *wctx)
{
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
JSONContext *json = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (!section)
+ return;
if (wctx->level == 0) {
json->indent_level--;
@@ -179,9 +168,8 @@ static inline void json_print_item_str(AVTextFormatContext *wctx,
static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
{
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
JSONContext *json = wctx->priv;
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
writer_put_str(wctx, json->item_sep);
@@ -192,9 +180,8 @@ static void json_print_str(AVTextFormatContext *wctx, const char *key, const cha
static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
{
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
JSONContext *json = wctx->priv;
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
AVBPrint buf;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
@@ -218,4 +205,3 @@ const AVTextFormatter avtextformatter_json = {
.flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
.priv_class = &json_class,
};
-
diff --git a/fftools/textformat/tf_xml.c b/fftools/textformat/tf_xml.c
index eceeda81e5..fd3d73888e 100644
--- a/fftools/textformat/tf_xml.c
+++ b/fftools/textformat/tf_xml.c
@@ -22,6 +22,7 @@
#include <string.h>
#include "avtextformat.h"
+#include "tf_internal.h"
#include <libavutil/mem.h>
#include <libavutil/avassert.h>
#include <libavutil/bprint.h>
@@ -29,21 +30,6 @@
#include <libavutil/macros.h>
#include <libavutil/opt.h>
-#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
-
-#define DEFINE_FORMATTER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
/* XML output */
typedef struct XMLContext {
@@ -93,9 +79,11 @@ static av_cold int xml_init(AVTextFormatContext *wctx)
static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
{
XMLContext *xml = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
- const struct AVTextFormatSection *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
+
+ if (!section)
+ return;
if (wctx->level == 0) {
const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
@@ -141,7 +129,10 @@ static void xml_print_section_header(AVTextFormatContext *wctx, const void *data
static void xml_print_section_footer(AVTextFormatContext *wctx)
{
XMLContext *xml = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+
+ if (!section)
+ return;
if (wctx->level == 0) {
writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
@@ -161,7 +152,10 @@ static void xml_print_value(AVTextFormatContext *wctx, const char *key,
{
AVBPrint buf;
XMLContext *xml = wctx->priv;
- const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
+
+ if (!section)
+ return;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
@@ -219,4 +213,3 @@ const AVTextFormatter avtextformatter_xml = {
.flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
.priv_class = &xml_class,
};
-
diff --git a/fftools/textformat/tw_avio.c b/fftools/textformat/tw_avio.c
index 3c7492aa06..f9f9cc6d5c 100644
--- a/fftools/textformat/tw_avio.c
+++ b/fftools/textformat/tw_avio.c
@@ -66,14 +66,11 @@ static void io_put_str(AVTextWriterContext *wctx, const char *str)
avio_write(ctx->avio_context, (const unsigned char *)str, (int)strlen(str));
}
-static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+static void io_printf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
{
IOWriterContext *ctx = wctx->priv;
- va_list ap;
- va_start(ap, fmt);
- avio_vprintf(ctx->avio_context, fmt, ap);
- va_end(ap);
+ avio_vprintf(ctx->avio_context, fmt, vl);
}
diff --git a/fftools/textformat/tw_buffer.c b/fftools/textformat/tw_buffer.c
index f8b38414a6..f861722247 100644
--- a/fftools/textformat/tw_buffer.c
+++ b/fftools/textformat/tw_buffer.c
@@ -56,14 +56,11 @@ static void buffer_put_str(AVTextWriterContext *wctx, const char *str)
av_bprintf(ctx->buffer, "%s", str);
}
-static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
{
BufferWriterContext *ctx = wctx->priv;
- va_list vargs;
- va_start(vargs, fmt);
- av_vbprintf(ctx->buffer, fmt, vargs);
- va_end(vargs);
+ av_vbprintf(ctx->buffer, fmt, vl);
}
diff --git a/fftools/textformat/tw_stdout.c b/fftools/textformat/tw_stdout.c
index 23de6f671f..dace55f38a 100644
--- a/fftools/textformat/tw_stdout.c
+++ b/fftools/textformat/tw_stdout.c
@@ -53,13 +53,9 @@ static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str)
printf("%s", str);
}
-static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
+ vprintf(fmt, vl);
}
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list