4 This file is part of PulseAudio.
6 Copyright 2007 Lennart Poettering
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.
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.
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
30 #include <pulse/xmalloc.h>
31 #include <pulse/utf8.h>
33 #include <pulsecore/hashmap.h>
34 #include <pulsecore/strbuf.h>
35 #include <pulsecore/core-util.h>
45 #define MAKE_HASHMAP(p) ((pa_hashmap*) (p))
46 #define MAKE_PROPLIST(p) ((pa_proplist*) (p))
48 static pa_bool_t
property_name_valid(const char *key
) {
50 if (!pa_utf8_valid(key
))
59 static void property_free(struct property
*prop
) {
63 pa_xfree(prop
->value
);
67 pa_proplist
* pa_proplist_new(void) {
68 return MAKE_PROPLIST(pa_hashmap_new(pa_idxset_string_hash_func
, pa_idxset_string_compare_func
));
71 void pa_proplist_free(pa_proplist
* p
) {
75 pa_hashmap_free(MAKE_HASHMAP(p
), NULL
, NULL
);
78 /** Will accept only valid UTF-8 */
79 int pa_proplist_sets(pa_proplist
*p
, const char *key
, const char *value
) {
80 struct property
*prop
;
81 pa_bool_t add
= FALSE
;
86 if (!property_name_valid(key
) || !pa_utf8_valid(value
))
89 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
))) {
90 prop
= pa_xnew(struct property
, 1);
91 prop
->key
= pa_xstrdup(key
);
94 pa_xfree(prop
->value
);
96 prop
->value
= pa_xstrdup(value
);
97 prop
->nbytes
= strlen(value
)+1;
100 pa_hashmap_put(MAKE_HASHMAP(p
), prop
->key
, prop
);
105 /** Will accept only valid UTF-8 */
106 int pa_proplist_setf(pa_proplist
*p
, const char *key
, const char *format
, ...) {
114 if (!property_name_valid(key
) || !pa_utf8_valid(format
))
117 va_start(ap
, format
);
118 t
= pa_vsprintf_malloc(format
, ap
);
121 r
= pa_proplist_sets(p
, key
, t
);
127 int pa_proplist_set(pa_proplist
*p
, const char *key
, const void *data
, size_t nbytes
) {
128 struct property
*prop
;
129 pa_bool_t add
= FALSE
;
134 if (!property_name_valid(key
))
137 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
))) {
138 prop
= pa_xnew(struct property
, 1);
139 prop
->key
= pa_xstrdup(key
);
142 pa_xfree(prop
->value
);
144 prop
->value
= pa_xmemdup(data
, nbytes
);
145 prop
->nbytes
= nbytes
;
148 pa_hashmap_put(MAKE_HASHMAP(p
), prop
->key
, prop
);
153 const char *pa_proplist_gets(pa_proplist
*p
, const char *key
) {
154 struct property
*prop
;
159 if (!property_name_valid(key
))
162 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
165 if (prop
->nbytes
<= 0)
168 if (((char*) prop
->value
)[prop
->nbytes
-1] != 0)
171 if (strlen((char*) prop
->value
) != prop
->nbytes
-1)
174 if (!pa_utf8_valid((char*) prop
->value
))
177 return (char*) prop
->value
;
180 int pa_proplist_get(pa_proplist
*p
, const char *key
, const void **data
, size_t *nbytes
) {
181 struct property
*prop
;
186 if (!property_name_valid(key
))
189 if (!(prop
= pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
193 *nbytes
= prop
->nbytes
;
198 void pa_proplist_update(pa_proplist
*p
, pa_update_mode_t mode
, pa_proplist
*other
) {
199 struct property
*prop
;
203 pa_assert(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
);
206 if (mode
== PA_UPDATE_SET
)
207 pa_proplist_clear(p
);
209 while ((prop
= pa_hashmap_iterate(MAKE_HASHMAP(other
), &state
, NULL
))) {
211 if (mode
== PA_UPDATE_MERGE
&& pa_proplist_contains(p
, prop
->key
))
214 pa_assert_se(pa_proplist_set(p
, prop
->key
, prop
->value
, prop
->nbytes
) == 0);
218 int pa_proplist_unset(pa_proplist
*p
, const char *key
) {
219 struct property
*prop
;
224 if (!property_name_valid(key
))
227 if (!(prop
= pa_hashmap_remove(MAKE_HASHMAP(p
), key
)))
234 int pa_proplist_unset_many(pa_proplist
*p
, const char * const keys
[]) {
235 const char * const * k
;
241 for (k
= keys
; *k
; k
++)
242 if (!property_name_valid(*k
))
245 for (k
= keys
; *k
; k
++)
246 if (pa_proplist_unset(p
, *k
) >= 0)
252 const char *pa_proplist_iterate(pa_proplist
*p
, void **state
) {
253 struct property
*prop
;
255 if (!(prop
= pa_hashmap_iterate(MAKE_HASHMAP(p
), state
, NULL
)))
261 char *pa_proplist_to_string(pa_proplist
*p
) {
268 buf
= pa_strbuf_new();
270 while ((key
= pa_proplist_iterate(p
, &state
))) {
274 if ((v
= pa_proplist_gets(p
, key
)))
275 pa_strbuf_printf(buf
, "%s = \"%s\"\n", key
, v
);
281 pa_assert_se(pa_proplist_get(p
, key
, &value
, &nbytes
) == 0);
282 c
= pa_xnew(char, nbytes
*2+1);
283 pa_hexstr((const uint8_t*) value
, nbytes
, c
, nbytes
*2+1);
285 pa_strbuf_printf(buf
, "%s = hex:%s\n", key
, c
);
290 return pa_strbuf_tostring_free(buf
);
293 int pa_proplist_contains(pa_proplist
*p
, const char *key
) {
297 if (!property_name_valid(key
))
300 if (!(pa_hashmap_get(MAKE_HASHMAP(p
), key
)))
306 void pa_proplist_clear(pa_proplist
*p
) {
307 struct property
*prop
;
310 while ((prop
= pa_hashmap_steal_first(MAKE_HASHMAP(p
))))
314 pa_proplist
* pa_proplist_copy(pa_proplist
*template) {
317 pa_assert_se(p
= pa_proplist_new());
320 pa_proplist_update(p
, PA_UPDATE_REPLACE
, template);