Coverage Report

Created: 2026-11-11 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpv/misc/node.c
Line
Count
Source
1
#include "node.h"
2
3
#include <mpv/client.h>
4
5
#include "common/common.h"
6
#include "bstr.h"
7
8
// Init a node with the given format. If parent is not NULL, it is set as
9
// parent allocation according to m_option_type_node rules (which means
10
// the mpv_node_list allocs are used for chaining the TA allocations).
11
// format == MPV_FORMAT_NONE will simply initialize it with all-0.
12
void node_init(struct mpv_node *dst, int format, struct mpv_node *parent)
13
2.03M
{
14
    // Other formats need to be initialized manually.
15
2.03M
    mp_assert(format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY ||
16
2.03M
           format == MPV_FORMAT_FLAG || format == MPV_FORMAT_INT64 ||
17
2.03M
           format == MPV_FORMAT_DOUBLE || format == MPV_FORMAT_BYTE_ARRAY ||
18
2.03M
           format == MPV_FORMAT_NONE);
19
20
2.03M
    void *ta_parent = NULL;
21
2.03M
    if (parent) {
22
1.40M
        mp_assert(parent->format == MPV_FORMAT_NODE_MAP ||
23
1.40M
               parent->format == MPV_FORMAT_NODE_ARRAY);
24
1.40M
        ta_parent = parent->u.list;
25
1.40M
    }
26
27
2.03M
    *dst = (struct mpv_node){ .format = format };
28
2.03M
    if (format == MPV_FORMAT_NODE_MAP || format == MPV_FORMAT_NODE_ARRAY)
29
1.03M
        dst->u.list = talloc_zero(ta_parent, struct mpv_node_list);
30
2.03M
    if (format == MPV_FORMAT_BYTE_ARRAY)
31
0
        dst->u.ba = talloc_zero(ta_parent, struct mpv_byte_array);
32
2.03M
}
33
34
// Add an entry to a MPV_FORMAT_NODE_ARRAY.
35
// m_option_type_node memory management rules apply.
36
struct mpv_node *node_array_add(struct mpv_node *dst, int format)
37
399k
{
38
399k
    struct mpv_node_list *list = dst->u.list;
39
399k
    mp_assert(dst->format == MPV_FORMAT_NODE_ARRAY && dst->u.list);
40
399k
    MP_TARRAY_GROW(list, list->values, list->num);
41
399k
    node_init(&list->values[list->num], format, dst);
42
399k
    return &list->values[list->num++];
43
399k
}
44
45
// Add an entry to a MPV_FORMAT_NODE_MAP. Keep in mind that this does
46
// not check for already existing entries under the same key.
47
// m_option_type_node memory management rules apply.
48
struct mpv_node *node_map_add(struct mpv_node *dst, const char *key, int format)
49
972k
{
50
972k
    mp_assert(key);
51
972k
    return node_map_badd(dst, bstr0(key), format);
52
972k
}
53
54
struct mpv_node *node_map_badd(struct mpv_node *dst, struct bstr key, int format)
55
1.00M
{
56
1.00M
    mp_assert(key.start);
57
58
1.00M
    struct mpv_node_list *list = dst->u.list;
59
1.00M
    mp_assert(dst->format == MPV_FORMAT_NODE_MAP && dst->u.list);
60
1.00M
    MP_TARRAY_GROW(list, list->values, list->num);
61
1.00M
    MP_TARRAY_GROW(list, list->keys, list->num);
62
1.00M
    list->keys[list->num] = bstrdup0(list, key);
63
1.00M
    node_init(&list->values[list->num], format, dst);
64
1.00M
    return &list->values[list->num++];
65
1.00M
}
66
67
// Add a string entry to a MPV_FORMAT_NODE_MAP. Keep in mind that this does
68
// not check for already existing entries under the same key.
69
// m_option_type_node memory management rules apply.
70
void node_map_add_string(struct mpv_node *dst, const char *key, const char *val)
71
527k
{
72
527k
    mp_assert(val);
73
74
527k
    struct mpv_node *entry = node_map_add(dst, key, MPV_FORMAT_NONE);
75
527k
    entry->format = MPV_FORMAT_STRING;
76
527k
    entry->u.string = talloc_strdup(dst->u.list, val);
77
527k
}
78
79
void node_map_add_bstr(struct mpv_node *dst, const char *key, bstr val)
80
0
{
81
0
    mp_assert(val.start);
82
83
0
    struct mpv_node *entry = node_map_add(dst, key, MPV_FORMAT_NONE);
84
0
    entry->format = MPV_FORMAT_STRING;
85
0
    entry->u.string = bstrto0(dst->u.list, val);
86
0
}
87
88
void node_map_add_int64(struct mpv_node *dst, const char *key, int64_t v)
89
172k
{
90
172k
    node_map_add(dst, key, MPV_FORMAT_INT64)->u.int64 = v;
91
172k
}
92
93
void node_map_add_double(struct mpv_node *dst, const char *key, double v)
94
6.05k
{
95
6.05k
    node_map_add(dst, key, MPV_FORMAT_DOUBLE)->u.double_ = v;
96
6.05k
}
97
98
void node_map_add_flag(struct mpv_node *dst, const char *key, bool v)
99
159k
{
100
159k
    node_map_add(dst, key, MPV_FORMAT_FLAG)->u.flag = v;
101
159k
}
102
103
mpv_node *node_map_get(mpv_node *src, const char *key)
104
0
{
105
0
    return node_map_bget(src, bstr0(key));
106
0
}
107
108
mpv_node *node_map_bget(mpv_node *src, struct bstr key)
109
23.4k
{
110
23.4k
    if (src->format != MPV_FORMAT_NODE_MAP)
111
0
        return NULL;
112
113
23.4k
    for (int i = 0; i < src->u.list->num; i++) {
114
0
        if (bstr_equals0(key, src->u.list->keys[i]))
115
0
            return &src->u.list->values[i];
116
0
    }
117
118
23.4k
    return NULL;
119
23.4k
}
120
121
// Note: for MPV_FORMAT_NODE_MAP, this (incorrectly) takes the order into
122
//       account, instead of treating it as set.
123
bool equal_mpv_value(const void *a, const void *b, int format)
124
0
{
125
0
    switch (format) {
126
0
    case MPV_FORMAT_NONE:
127
0
        return true;
128
0
    case MPV_FORMAT_STRING:
129
0
    case MPV_FORMAT_OSD_STRING:
130
0
        return strcmp(*(char **)a, *(char **)b) == 0;
131
0
    case MPV_FORMAT_FLAG:
132
0
        return *(int *)a == *(int *)b;
133
0
    case MPV_FORMAT_INT64:
134
0
        return *(int64_t *)a == *(int64_t *)b;
135
0
    case MPV_FORMAT_DOUBLE:
136
0
        return *(double *)a == *(double *)b;
137
0
    case MPV_FORMAT_NODE:
138
0
        return equal_mpv_node(a, b);
139
0
    case MPV_FORMAT_BYTE_ARRAY: {
140
0
        const struct mpv_byte_array *a_r = a, *b_r = b;
141
0
        if (a_r->size != b_r->size)
142
0
            return false;
143
0
        return memcmp(a_r->data, b_r->data, a_r->size) == 0;
144
0
    }
145
0
    case MPV_FORMAT_NODE_ARRAY:
146
0
    case MPV_FORMAT_NODE_MAP:
147
0
    {
148
0
        mpv_node_list *l_a = *(mpv_node_list **)a, *l_b = *(mpv_node_list **)b;
149
0
        if (l_a->num != l_b->num)
150
0
            return false;
151
0
        for (int n = 0; n < l_a->num; n++) {
152
0
            if (format == MPV_FORMAT_NODE_MAP) {
153
0
                if (strcmp(l_a->keys[n], l_b->keys[n]) != 0)
154
0
                    return false;
155
0
            }
156
0
            if (!equal_mpv_node(&l_a->values[n], &l_b->values[n]))
157
0
                return false;
158
0
        }
159
0
        return true;
160
0
    }
161
0
    }
162
0
    MP_ASSERT_UNREACHABLE(); // supposed to be able to handle all defined types
163
0
}
164
165
// Remarks see equal_mpv_value().
166
bool equal_mpv_node(const struct mpv_node *a, const struct mpv_node *b)
167
0
{
168
0
    if (a->format != b->format)
169
0
        return false;
170
0
    return equal_mpv_value(&a->u, &b->u, a->format);
171
0
}