History

fftools/textformat: Introduce common header and deduplicate code

Also change writer_printf signature in AVTextWriter to use va_list, so that it can be called by the new function writer_printf() in tf_internal.h.

softworkz committed 1 year ago

Commit cee7b8a1 parent e4830b811 files · +160 −141Browse files

Unified · Split

11 files
  1. fftools/textformat/avtextwriters.h +1 −1
  2. fftools/textformat/tf_compact.c +11 −21
  3. fftools/textformat/tf_default.c +8 −19
  4. fftools/textformat/tf_flat.c +6 −19
  5. fftools/textformat/tf_ini.c +6 −18
  6. fftools/textformat/tf_internal.h +85 −0
  7. fftools/textformat/tf_json.c +20 −23
  8. fftools/textformat/tf_xml.c +14 −21
  9. fftools/textformat/tw_avio.c +3 −6
  10. fftools/textformat/tw_buffer.c +3 −6
  11. fftools/textformat/tw_stdout.c +3 −7
fftools/textformat/avtextwriters.h+1−1
@@ -36,7 +36,7 @@ typedef struct AVTextWriter { · 35 unmodified lines
3636 void (*uninit)(AVTextWriterContext *wctx);
3737 void (*writer_w8)(AVTextWriterContext *wctx, int b);
3838 void (*writer_put_str)(AVTextWriterContext *wctx, const char *str);
39− void (*writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
39+ void (*writer_vprintf)(AVTextWriterContext *wctx, const char *fmt, va_list vl);
4040 } AVTextWriter;
4141
4242 typedef struct AVTextWriterContext {
fftools/textformat/tf_compact.c+11−21
@@ -28,23 +28,7 @@ · 27 unmodified lines
2828 #include "libavutil/bprint.h"
2929 #include "libavutil/error.h"
3030 #include "libavutil/opt.h"
31−
32−
33−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
34−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
35−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
36−
37−
38−#define DEFINE_FORMATTER_CLASS(name) \
39−static const char *name##_get_name(void *ctx) \
40−{ \
41− return #name ; \
42−} \
43−static const AVClass name##_class = { \
44− .class_name = #name, \
45− .item_name = name##_get_name, \
46− .option = name##_options \
47−}
31+#include "tf_internal.h"
4832
4933
5034 /* Compact output */
@@ -157,9 +141,12 @@ static av_cold int compact_init(AVTextFormatContext *wctx) · 106 unmodified lines
157141 static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
158142 {
159143 CompactContext *compact = wctx->priv;
160− const struct AVTextFormatSection *section = wctx->section[wctx->level];
161− const struct AVTextFormatSection *parent_section = wctx->level ?
162− wctx->section[wctx->level-1] : NULL;
144+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
145+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
146+
147+ if (!section)
148+ return;
149+
163150 compact->terminate_line[wctx->level] = 1;
164151 compact->has_nested_elems[wctx->level] = 0;
165152
@@ -208,8 +195,11 @@ static void compact_print_section_header(AVTextFormatContext *wctx, const void * · 42 unmodified lines
208195
209196 static void compact_print_section_footer(AVTextFormatContext *wctx)
210197 {
211− const struct AVTextFormatSection *section = wctx->section[wctx->level];
212198 CompactContext *compact = wctx->priv;
199+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
200+
201+ if (!section)
202+ return;
213203
214204 if (!compact->nested_section[wctx->level] &&
215205 compact->terminate_line[wctx->level] &&
fftools/textformat/tf_default.c+8−19
@@ -27,21 +27,7 @@ · 26 unmodified lines
2727 #include "avtextformat.h"
2828 #include "libavutil/bprint.h"
2929 #include "libavutil/opt.h"
30−
31−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
32−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
33−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
34−
35−#define DEFINE_FORMATTER_CLASS(name) \
36−static const char *name##_get_name(void *ctx) \
37−{ \
38− return #name ; \
39−} \
40−static const AVClass name##_class = { \
41− .class_name = #name, \
42− .item_name = name##_get_name, \
43− .option = name##_options \
44−}
30+#include "tf_internal.h"
4531
4632 /* Default output */
4733
@@ -80,9 +66,11 @@ static void default_print_section_header(AVTextFormatContext *wctx, const void * · 32 unmodified lines
8066 {
8167 DefaultContext *def = wctx->priv;
8268 char buf[32];
83− const struct AVTextFormatSection *section = wctx->section[wctx->level];
84− const struct AVTextFormatSection *parent_section = wctx->level ?
85− wctx->section[wctx->level-1] : NULL;
69+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
70+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
71+
72+ if (!section)
73+ return;
8674
8775 av_bprint_clear(&wctx->section_pbuf[wctx->level]);
8876 if (parent_section &&
@@ -104,7 +92,8 @@ static void default_print_section_header(AVTextFormatContext *wctx, const void * · 15 unmodified lines
10492 static void default_print_section_footer(AVTextFormatContext *wctx)
10593 {
10694 DefaultContext *def = wctx->priv;
107− const struct AVTextFormatSection *section = wctx->section[wctx->level];
95+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
96+
10897 char buf[32];
10998
11099 if (!section)
fftools/textformat/tf_flat.c+6−19
@@ -28,22 +28,7 @@ · 27 unmodified lines
2828 #include "libavutil/bprint.h"
2929 #include "libavutil/error.h"
3030 #include "libavutil/opt.h"
31−
32−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
33−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
34−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
35−
36−#define DEFINE_FORMATTER_CLASS(name) \
37−static const char *name##_get_name(void *ctx) \
38−{ \
39− return #name ; \
40−} \
41−static const AVClass name##_class = { \
42− .class_name = #name, \
43− .item_name = name##_get_name, \
44− .option = name##_options \
45−}
46−
31+#include "tf_internal.h"
4732
4833 /* Flat output */
4934
@@ -118,9 +103,11 @@ static void flat_print_section_header(AVTextFormatContext *wctx, const void *dat · 68 unmodified lines
118103 {
119104 FlatContext *flat = wctx->priv;
120105 AVBPrint *buf = &wctx->section_pbuf[wctx->level];
121− const struct AVTextFormatSection *section = wctx->section[wctx->level];
122− const struct AVTextFormatSection *parent_section = wctx->level ?
123− wctx->section[wctx->level-1] : NULL;
106+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
107+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
108+
109+ if (!section)
110+ return;
124111
125112 /* build section header */
126113 av_bprint_clear(buf);
fftools/textformat/tf_ini.c+6−18
@@ -28,21 +28,7 @@ · 27 unmodified lines
2828
2929 #include "libavutil/bprint.h"
3030 #include "libavutil/opt.h"
31−
32−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
33−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
34−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
35−
36−#define DEFINE_FORMATTER_CLASS(name) \
37−static const char *name##_get_name(void *ctx) \
38−{ \
39− return #name ; \
40−} \
41−static const AVClass name##_class = { \
42− .class_name = #name, \
43− .item_name = name##_get_name, \
44− .option = name##_options \
45−}
31+#include "tf_internal.h"
4632
4733 /* Default output */
4834
@@ -104,9 +90,11 @@ static void ini_print_section_header(AVTextFormatContext *wctx, const void *data · 55 unmodified lines
10490 {
10591 INIContext *ini = wctx->priv;
10692 AVBPrint *buf = &wctx->section_pbuf[wctx->level];
107− const struct AVTextFormatSection *section = wctx->section[wctx->level];
108− const struct AVTextFormatSection *parent_section = wctx->level ?
109− wctx->section[wctx->level-1] : NULL;
93+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
94+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
95+
96+ if (!section)
97+ return;
11098
11199 av_bprint_clear(buf);
112100 if (!parent_section) {
fftools/textformat/tf_internal.h+85−0
@@ -0,0 +1,85 @@
1+/*
2+ * Copyright (c) The FFmpeg developers
3+ *
4+ * This file is part of FFmpeg.
5+ *
6+ * FFmpeg is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU Lesser General Public
8+ * License as published by the Free Software Foundation; either
9+ * version 2.1 of the License, or (at your option) any later version.
10+ *
11+ * FFmpeg is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+ * Lesser General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU Lesser General Public
17+ * License along with FFmpeg; if not, write to the Free Software
18+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+/**
22+ * @file
23+ * Internal utilities for text formatters.
24+ */
25+
26+#ifndef FFTOOLS_TEXTFORMAT_TF_INTERNAL_H
27+#define FFTOOLS_TEXTFORMAT_TF_INTERNAL_H
28+
29+#include "avtextformat.h"
30+
31+#define DEFINE_FORMATTER_CLASS(name) \
32+static const char *name##_get_name(void *ctx) \
33+{ \
34+ return #name ; \
35+} \
36+static const AVClass name##_class = { \
37+ .class_name = #name, \
38+ .item_name = name##_get_name, \
39+ .option = name##_options \
40+}
41+
42+
43+/**
44+ * Safely validate and access a section at a given level
45+ */
46+static inline const AVTextFormatSection *tf_get_section(AVTextFormatContext *tfc, int level)
47+{
48+ if (!tfc || level < 0 || level >= SECTION_MAX_NB_LEVELS || !tfc->section[level]) {
49+ if (tfc)
50+ av_log(tfc, AV_LOG_ERROR, "Invalid section access at level %d\n", level);
51+ return NULL;
52+ }
53+ return tfc->section[level];
54+}
55+
56+/**
57+ * Safely access the parent section
58+ */
59+static inline const AVTextFormatSection *tf_get_parent_section(AVTextFormatContext *tfc, int level)
60+{
61+ if (level <= 0)
62+ return NULL;
63+
64+ return tf_get_section(tfc, level - 1);
65+}
66+
67+static inline void writer_w8(AVTextFormatContext *wctx, int b)
68+{
69+ wctx->writer->writer->writer_w8(wctx->writer, b);
70+}
71+
72+static inline void writer_put_str(AVTextFormatContext *wctx, const char *str)
73+{
74+ wctx->writer->writer->writer_put_str(wctx->writer, str);
75+}
76+
77+static inline void writer_printf(AVTextFormatContext *wctx, const char *fmt, ...)
78+{
79+ va_list args;
80+ va_start(args, fmt);
81+ wctx->writer->writer->writer_vprintf(wctx->writer, fmt, args);
82+ va_end(args);
83+}
84+
85+#endif /* FFTOOLS_TEXTFORMAT_TF_INTERNAL_H */
fftools/textformat/tf_json.c+20−23
@@ -27,22 +27,7 @@ · 26 unmodified lines
2727 #include "avtextformat.h"
2828 #include "libavutil/bprint.h"
2929 #include "libavutil/opt.h"
30−
31−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
32−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
33−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
34−
35−#define DEFINE_FORMATTER_CLASS(name) \
36−static const char *name##_get_name(void *ctx) \
37−{ \
38− return #name ; \
39−} \
40−static const AVClass name##_class = { \
41− .class_name = #name, \
42− .item_name = name##_get_name, \
43− .option = name##_options \
44−}
45−
30+#include "tf_internal.h"
4631
4732 /* JSON output */
4833
@@ -103,10 +88,13 @@ static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx · 54 unmodified lines
10388
10489 static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
10590 {
91+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
92+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
10693 JSONContext *json = wctx->priv;
10794 AVBPrint buf;
108− const AVTextFormatSection *section = wctx->section[wctx->level];
109− const AVTextFormatSection *parent_section = wctx->level ? wctx->section[wctx->level - 1] : NULL;
95+
96+ if (!section)
97+ return;
11098
11199 if (wctx->level && wctx->nb_item[wctx->level - 1])
112100 writer_put_str(wctx, ",\n");
@@ -141,8 +129,11 @@ static void json_print_section_header(AVTextFormatContext *wctx, const void *dat · 28 unmodified lines
141129
142130 static void json_print_section_footer(AVTextFormatContext *wctx)
143131 {
132+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
144133 JSONContext *json = wctx->priv;
145− const struct AVTextFormatSection *section = wctx->section[wctx->level];
134+
135+ if (!section)
136+ return;
146137
147138 if (wctx->level == 0) {
148139 json->indent_level--;
@@ -175,9 +166,12 @@ static inline void json_print_item_str(AVTextFormatContext *wctx, · 26 unmodified lines
175166
176167 static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
177168 {
169+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
170+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
178171 JSONContext *json = wctx->priv;
179− const struct AVTextFormatSection *parent_section = wctx->level ?
180− wctx->section[wctx->level-1] : NULL;
172+
173+ if (!section)
174+ return;
181175
182176 if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
183177 writer_put_str(wctx, json->item_sep);
@@ -188,10 +182,14 @@ static void json_print_str(AVTextFormatContext *wctx, const char *key, const cha · 4 unmodified lines
188182
189183 static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
190184 {
185+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
186+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
191187 JSONContext *json = wctx->priv;
192− const AVTextFormatSection *parent_section = wctx->level ? wctx->section[wctx->level - 1] : NULL;
193188 AVBPrint buf;
194189
190+ if (!section)
191+ return;
192+
195193 if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
196194 writer_put_str(wctx, json->item_sep);
197195 if (!json->compact)
@@ -213,4 +211,3 @@ const AVTextFormatter avtextformatter_json = { · 15 unmodified lines
213211 .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
214212 .priv_class = &json_class,
215213 };
216−
fftools/textformat/tf_xml.c+14−21
@@ -25,21 +25,7 @@ · 24 unmodified lines
2525 #include "libavutil/bprint.h"
2626 #include "libavutil/error.h"
2727 #include "libavutil/opt.h"
28−
29−#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
30−#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
31−#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
32−
33−#define DEFINE_FORMATTER_CLASS(name) \
34−static const char *name##_get_name(void *ctx) \
35−{ \
36− return #name ; \
37−} \
38−static const AVClass name##_class = { \
39− .class_name = #name, \
40− .item_name = name##_get_name, \
41− .option = name##_options \
42−}
28+#include "tf_internal.h"
4329
4430 /* XML output */
4531
@@ -90,9 +76,11 @@ static av_cold int xml_init(AVTextFormatContext *wctx) · 44 unmodified lines
9076 static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
9177 {
9278 XMLContext *xml = wctx->priv;
93− const struct AVTextFormatSection *section = wctx->section[wctx->level];
94− const struct AVTextFormatSection *parent_section = wctx->level ?
95− wctx->section[wctx->level-1] : NULL;
79+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
80+ const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
81+
82+ if (!section)
83+ return;
9684
9785 if (wctx->level == 0) {
9886 const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
@@ -138,7 +126,10 @@ static void xml_print_section_header(AVTextFormatContext *wctx, const void *data · 39 unmodified lines
138126 static void xml_print_section_footer(AVTextFormatContext *wctx)
139127 {
140128 XMLContext *xml = wctx->priv;
141− const struct AVTextFormatSection *section = wctx->section[wctx->level];
129+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
130+
131+ if (!section)
132+ return;
142133
143134 if (wctx->level == 0) {
144135 writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
@@ -158,7 +149,10 @@ static void xml_print_value(AVTextFormatContext *wctx, const char *key, · 13 unmodified lines
158149 {
159150 AVBPrint buf;
160151 XMLContext *xml = wctx->priv;
161− const struct AVTextFormatSection *section = wctx->section[wctx->level];
152+ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
153+
154+ if (!section)
155+ return;
162156
163157 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
164158
@@ -216,4 +210,3 @@ const AVTextFormatter avtextformatter_xml = { · 51 unmodified lines
216210 .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
217211 .priv_class = &xml_class,
218212 };
219−
fftools/textformat/tw_avio.c+3−6
@@ -57,14 +57,11 @@ static void io_put_str(AVTextWriterContext *wctx, const char *str) · 56 unmodified lines
5757 avio_write(ctx->avio_context, (const unsigned char *)str, (int)strlen(str));
5858 }
5959
60−static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
60+static void io_vprintf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
6161 {
6262 IOWriterContext *ctx = wctx->priv;
63− va_list ap;
6463
65− va_start(ap, fmt);
66− avio_vprintf(ctx->avio_context, fmt, ap);
67− va_end(ap);
64+ avio_vprintf(ctx->avio_context, fmt, vl);
6865 }
6966
7067
@@ -73,7 +70,7 @@ const AVTextWriter avtextwriter_avio = { · 2 unmodified lines
7370 .priv_size = sizeof(IOWriterContext),
7471 .uninit = iowriter_uninit,
7572 .writer_put_str = io_put_str,
76− .writer_printf = io_printf,
73+ .writer_vprintf = io_vprintf,
7774 .writer_w8 = io_w8
7875 };
7976
fftools/textformat/tw_buffer.c+3−6
@@ -56,14 +56,11 @@ static void buffer_put_str(AVTextWriterContext *wctx, const char *str) · 55 unmodified lines
5656 av_bprintf(ctx->buffer, "%s", str);
5757 }
5858
59−static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
59+static void buffer_vprintf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
6060 {
6161 BufferWriterContext *ctx = wctx->priv;
6262
63− va_list vargs;
64− va_start(vargs, fmt);
65− av_vbprintf(ctx->buffer, fmt, vargs);
66− va_end(vargs);
63+ av_vbprintf(ctx->buffer, fmt, vl);
6764 }
6865
6966
@@ -72,7 +69,7 @@ const AVTextWriter avtextwriter_buffer = { · 2 unmodified lines
7269 .priv_size = sizeof(BufferWriterContext),
7370 .priv_class = &bufferwriter_class,
7471 .writer_put_str = buffer_put_str,
75− .writer_printf = buffer_printf,
72+ .writer_vprintf = buffer_vprintf,
7673 .writer_w8 = buffer_w8
7774 };
7875
fftools/textformat/tw_stdout.c+3−7
@@ -53,13 +53,9 @@ static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str) · 52 unmodified lines
5353 printf("%s", str);
5454 }
5555
56−static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
56+static inline void stdout_vprintf(AVTextWriterContext *wctx, const char *fmt, va_list vl)
5757 {
58− va_list ap;
59−
60− va_start(ap, fmt);
61− vprintf(fmt, ap);
62− va_end(ap);
58+ vprintf(fmt, vl);
6359 }
6460
6561
@@ -68,7 +64,7 @@ static const AVTextWriter avtextwriter_stdout = { · 2 unmodified lines
6864 .priv_size = sizeof(StdOutWriterContext),
6965 .priv_class = &stdoutwriter_class,
7066 .writer_put_str = stdout_put_str,
71− .writer_printf = stdout_printf,
67+ .writer_vprintf = stdout_vprintf,
7268 .writer_w8 = stdout_w8
7369 };
7470

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t