]> code.delx.au - pulseaudio/blob - src/pulse/proplist.c
add new function pa_proplist_contains()
[pulseaudio] / src / pulse / proplist.c
1 /* $Id$ */
2
3 /***
4 This file is part of PulseAudio.
5
6 Copyright 2007 Lennart Poettering
7
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
12
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <string.h>
29
30 #include <pulse/xmalloc.h>
31 #include <pulse/utf8.h>
32
33 #include <pulsecore/hashmap.h>
34 #include <pulsecore/strbuf.h>
35 #include <pulsecore/core-util.h>
36
37 #include "proplist.h"
38
39 struct property {
40 char *key;
41 void *value;
42 size_t nbytes;
43 };
44
45 #define MAKE_HASHMAP(p) ((pa_hashmap*) (p))
46 #define MAKE_PROPLIST(p) ((pa_proplist*) (p))
47
48 static pa_bool_t property_name_valid(const char *key) {
49
50 if (!pa_utf8_valid(key))
51 return FALSE;
52
53 if (strlen(key) <= 0)
54 return FALSE;
55
56 return TRUE;
57 }
58
59 static void property_free(struct property *prop) {
60 pa_assert(prop);
61
62 pa_xfree(prop->key);
63 pa_xfree(prop->value);
64 pa_xfree(prop);
65 }
66
67 pa_proplist* pa_proplist_new(void) {
68 return MAKE_PROPLIST(pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func));
69 }
70
71 void pa_proplist_free(pa_proplist* p) {
72 struct property *prop;
73
74 while ((prop = pa_hashmap_steal_first(MAKE_HASHMAP(p))))
75 property_free(prop);
76
77 pa_hashmap_free(MAKE_HASHMAP(p), NULL, NULL);
78 }
79
80 /** Will accept only valid UTF-8 */
81 int pa_proplist_puts(pa_proplist *p, const char *key, const char *value) {
82 struct property *prop;
83 pa_bool_t add = FALSE;
84
85 pa_assert(p);
86 pa_assert(key);
87
88 if (!property_name_valid(key) || !pa_utf8_valid(value))
89 return -1;
90
91 if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
92 prop = pa_xnew(struct property, 1);
93 prop->key = pa_xstrdup(key);
94 add = TRUE;
95 } else
96 pa_xfree(prop->value);
97
98 prop->value = pa_xstrdup(value);
99 prop->nbytes = strlen(value)+1;
100
101 if (add)
102 pa_hashmap_put(MAKE_HASHMAP(p), prop->key, prop);
103
104 return 0;
105 }
106
107 int pa_proplist_put(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
108 struct property *prop;
109 pa_bool_t add = FALSE;
110
111 pa_assert(p);
112 pa_assert(key);
113
114 if (!property_name_valid(key))
115 return -1;
116
117 if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
118 prop = pa_xnew(struct property, 1);
119 prop->key = pa_xstrdup(key);
120 add = TRUE;
121 } else
122 pa_xfree(prop->value);
123
124 prop->value = pa_xmemdup(data, nbytes);
125 prop->nbytes = nbytes;
126
127 if (add)
128 pa_hashmap_put(MAKE_HASHMAP(p), prop->key, prop);
129
130 return 0;
131 }
132
133 const char *pa_proplist_gets(pa_proplist *p, const char *key) {
134 struct property *prop;
135
136 pa_assert(p);
137 pa_assert(key);
138
139 if (!property_name_valid(key))
140 return NULL;
141
142 if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key)))
143 return NULL;
144
145 if (prop->nbytes <= 0)
146 return NULL;
147
148 if (((char*) prop->value)[prop->nbytes-1] != 0)
149 return NULL;
150
151 if (strlen((char*) prop->value) != prop->nbytes-1)
152 return NULL;
153
154 if (!pa_utf8_valid((char*) prop->value))
155 return NULL;
156
157 return (char*) prop->value;
158 }
159
160 int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *nbytes) {
161 struct property *prop;
162
163 pa_assert(p);
164 pa_assert(key);
165
166 if (!property_name_valid(key))
167 return -1;
168
169 if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key)))
170 return -1;
171
172 *data = prop->value;
173 *nbytes = prop->nbytes;
174
175 return 0;
176 }
177
178 void pa_proplist_merge(pa_proplist *p, pa_proplist *other) {
179 struct property *prop;
180 void *state = NULL;
181
182 pa_assert(p);
183 pa_assert(other);
184
185 while ((prop = pa_hashmap_iterate(MAKE_HASHMAP(other), &state, NULL)))
186 pa_assert_se(pa_proplist_put(p, prop->key, prop->value, prop->nbytes) == 0);
187 }
188
189 int pa_proplist_remove(pa_proplist *p, const char *key) {
190 struct property *prop;
191
192 pa_assert(p);
193 pa_assert(key);
194
195 if (!property_name_valid(key))
196 return -1;
197
198 if (!(prop = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
199 return -1;
200
201 property_free(prop);
202 return 0;
203 }
204
205 const char *pa_proplist_iterate(pa_proplist *p, void **state) {
206 struct property *prop;
207
208 if (!(prop = pa_hashmap_iterate(MAKE_HASHMAP(p), state, NULL)))
209 return NULL;
210
211 return prop->key;
212 }
213
214 char *pa_proplist_to_string(pa_proplist *p) {
215 const char *key;
216 void *state = NULL;
217 pa_strbuf *buf;
218
219 pa_assert(p);
220
221 buf = pa_strbuf_new();
222
223 while ((key = pa_proplist_iterate(p, &state))) {
224
225 const char *v;
226
227 if ((v = pa_proplist_gets(p, key)))
228 pa_strbuf_printf(buf, "%s = \"%s\"\n", key, v);
229 else {
230 const void *value;
231 size_t nbytes;
232 char *c;
233
234 pa_assert_se(pa_proplist_get(p, key, &value, &nbytes) == 0);
235 c = pa_xnew(char, nbytes*2+1);
236 pa_hexstr((const uint8_t*) value, nbytes, c, nbytes*2+1);
237
238 pa_strbuf_printf(buf, "%s = hex:%s\n", key, c);
239 pa_xfree(c);
240 }
241 }
242
243 return pa_strbuf_tostring_free(buf);
244 }
245
246 int pa_proplist_contains(pa_proplist *p, const char *key) {
247 pa_assert(p);
248 pa_assert(key);
249
250 if (!property_name_valid(key))
251 return -1;
252
253 if (!(pa_hashmap_get(MAKE_HASHMAP(p), key)))
254 return 0;
255
256 return 1;
257 }