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 | } |