FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/textformat/tf_ini.c
Date: 2026-05-02 03:33:10
Exec Total Coverage
Lines: 43 51 84.3%
Functions: 4 4 100.0%
Branches: 19 29 65.5%

Line Branch Exec Source
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 #include <limits.h>
22 #include <stdarg.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "avtextformat.h"
28
29 #include "libavutil/attributes.h"
30 #include "libavutil/bprint.h"
31 #include "libavutil/opt.h"
32 #include "tf_internal.h"
33
34 /* Default output */
35
36 typedef struct DefaultContext {
37 const AVClass *class;
38 int nokey;
39 int noprint_wrappers;
40 int nested_section[SECTION_MAX_NB_LEVELS];
41 } DefaultContext;
42
43 /* INI format output */
44
45 typedef struct INIContext {
46 const AVClass *class;
47 int hierarchical;
48 } INIContext;
49
50 #undef OFFSET
51 #define OFFSET(x) offsetof(INIContext, x)
52
53 static const AVOption ini_options[] = {
54 { "hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1 },
55 { "h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1 },
56 { NULL },
57 };
58
59 DEFINE_FORMATTER_CLASS(ini);
60
61 740 static char *ini_escape_str(AVBPrint *dst, const char *src)
62 {
63 740 int i = 0;
64 char c;
65
66
2/2
✓ Branch 0 taken 6309 times.
✓ Branch 1 taken 740 times.
7049 while ((c = src[i++])) {
67
2/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 6295 times.
6309 switch (c) {
68 case '\b': av_bprintf(dst, "%s", "\\b"); break;
69 case '\f': av_bprintf(dst, "%s", "\\f"); break;
70 case '\n': av_bprintf(dst, "%s", "\\n"); break;
71 case '\r': av_bprintf(dst, "%s", "\\r"); break;
72 case '\t': av_bprintf(dst, "%s", "\\t"); break;
73 14 case '\\':
74 case '#':
75 case '=':
76 case ':':
77 14 av_bprint_chars(dst, '\\', 1);
78 av_fallthrough;
79 6309 default:
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6309 times.
6309 if ((unsigned char)c < 32)
81 av_bprintf(dst, "\\x00%02x", (unsigned char)c);
82 else
83 6309 av_bprint_chars(dst, c, 1);
84 6309 break;
85 }
86 }
87 740 return dst->str;
88 }
89
90 42 static void ini_print_section_header(AVTextFormatContext *wctx, const void *data)
91 {
92 42 INIContext *ini = wctx->priv;
93 42 AVBPrint *buf = &wctx->section_pbuf[wctx->level];
94 42 const AVTextFormatSection *section = tf_get_section(wctx, wctx->level);
95 42 const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level);
96
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!section)
98 return;
99
100 42 av_bprint_clear(buf);
101
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 if (!parent_section) {
102 1 writer_put_str(wctx, "# ffprobe output\n\n");
103 1 return;
104 }
105
106
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 3 times.
41 if (wctx->nb_item[wctx->level - 1])
107 38 writer_w8(wctx, '\n');
108
109 41 av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level - 1].str);
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ini->hierarchical ||
111 !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
112
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 3 times.
41 av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
113
114
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 10 times.
41 if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
115 62 unsigned n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE
116 28 ? wctx->nb_item_type[wctx->level - 1][section->id]
117
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
31 : wctx->nb_item[wctx->level - 1];
118 31 av_bprintf(buf, ".%u", n);
119 }
120 }
121
122
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
41 if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER)))
123 39 writer_printf(wctx, "[%s]\n", buf->str);
124 }
125
126 370 static void ini_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
127 {
128 AVBPrint buf;
129
130 370 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
131 370 writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
132 370 av_bprint_clear(&buf);
133 370 writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
134 370 av_bprint_finalize(&buf, NULL);
135 370 }
136
137 316 static void ini_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
138 {
139 316 writer_printf(wctx, "%s=%"PRId64"\n", key, value);
140 316 }
141
142 const AVTextFormatter avtextformatter_ini = {
143 .name = "ini",
144 .priv_size = sizeof(INIContext),
145 .print_section_header = ini_print_section_header,
146 .print_integer = ini_print_int,
147 .print_string = ini_print_str,
148 .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS | AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
149 .priv_class = &ini_class,
150 };
151