1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2008 Colin Guthrie
5 Copyright 2007 Lennart Poettering
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <string.h>
26
27 #include <pulse/xmalloc.h>
28
29 #include <pulsecore/hashmap.h>
30 #include <pulsecore/strbuf.h>
31 #include <pulsecore/core-util.h>
32
33 #include "headerlist.h"
34
35 struct header {
36 char *key;
37 void *value;
38 size_t nbytes;
39 };
40
41 #define MAKE_HASHMAP(p) ((pa_hashmap*) (p))
42 #define MAKE_HEADERLIST(p) ((pa_headerlist*) (p))
43
header_free(struct header * hdr)44 static void header_free(struct header *hdr) {
45 pa_assert(hdr);
46
47 pa_xfree(hdr->key);
48 pa_xfree(hdr->value);
49 pa_xfree(hdr);
50 }
51
pa_headerlist_new(void)52 pa_headerlist* pa_headerlist_new(void) {
53 return MAKE_HEADERLIST(pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) header_free));
54 }
55
pa_headerlist_free(pa_headerlist * p)56 void pa_headerlist_free(pa_headerlist* p) {
57 pa_hashmap_free(MAKE_HASHMAP(p));
58 }
59
pa_headerlist_puts(pa_headerlist * p,const char * key,const char * value)60 int pa_headerlist_puts(pa_headerlist *p, const char *key, const char *value) {
61 struct header *hdr;
62 bool add = false;
63
64 pa_assert(p);
65 pa_assert(key);
66
67 if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
68 hdr = pa_xnew(struct header, 1);
69 hdr->key = pa_xstrdup(key);
70 add = true;
71 } else
72 pa_xfree(hdr->value);
73
74 hdr->value = pa_xstrdup(value);
75 hdr->nbytes = strlen(value)+1;
76
77 if (add)
78 pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr);
79
80 return 0;
81 }
82
pa_headerlist_putsappend(pa_headerlist * p,const char * key,const char * value)83 int pa_headerlist_putsappend(pa_headerlist *p, const char *key, const char *value) {
84 struct header *hdr;
85 bool add = false;
86
87 pa_assert(p);
88 pa_assert(key);
89
90 if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
91 hdr = pa_xnew(struct header, 1);
92 hdr->key = pa_xstrdup(key);
93 hdr->value = pa_xstrdup(value);
94 add = true;
95 } else {
96 void *newval = pa_sprintf_malloc("%s%s", (char*)hdr->value, value);
97 pa_xfree(hdr->value);
98 hdr->value = newval;
99 }
100 hdr->nbytes = strlen(hdr->value)+1;
101
102 if (add)
103 pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr);
104
105 return 0;
106 }
107
pa_headerlist_gets(pa_headerlist * p,const char * key)108 const char *pa_headerlist_gets(pa_headerlist *p, const char *key) {
109 struct header *hdr;
110
111 pa_assert(p);
112 pa_assert(key);
113
114 if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key)))
115 return NULL;
116
117 if (hdr->nbytes <= 0)
118 return NULL;
119
120 if (((char*) hdr->value)[hdr->nbytes-1] != 0)
121 return NULL;
122
123 if (strlen((char*) hdr->value) != hdr->nbytes-1)
124 return NULL;
125
126 return (char*) hdr->value;
127 }
128
pa_headerlist_remove(pa_headerlist * p,const char * key)129 int pa_headerlist_remove(pa_headerlist *p, const char *key) {
130 pa_assert(p);
131 pa_assert(key);
132
133 return pa_hashmap_remove_and_free(MAKE_HASHMAP(p), key);
134 }
135
pa_headerlist_iterate(pa_headerlist * p,void ** state)136 const char *pa_headerlist_iterate(pa_headerlist *p, void **state) {
137 struct header *hdr;
138
139 if (!(hdr = pa_hashmap_iterate(MAKE_HASHMAP(p), state, NULL)))
140 return NULL;
141
142 return hdr->key;
143 }
144
pa_headerlist_to_string(pa_headerlist * p)145 char *pa_headerlist_to_string(pa_headerlist *p) {
146 const char *key;
147 void *state = NULL;
148 pa_strbuf *buf;
149
150 pa_assert(p);
151
152 buf = pa_strbuf_new();
153
154 while ((key = pa_headerlist_iterate(p, &state))) {
155
156 const char *v;
157
158 if ((v = pa_headerlist_gets(p, key)))
159 pa_strbuf_printf(buf, "%s: %s\r\n", key, v);
160 }
161
162 return pa_strbuf_to_string_free(buf);
163 }
164
pa_headerlist_contains(pa_headerlist * p,const char * key)165 int pa_headerlist_contains(pa_headerlist *p, const char *key) {
166 pa_assert(p);
167 pa_assert(key);
168
169 if (!(pa_hashmap_get(MAKE_HASHMAP(p), key)))
170 return 0;
171
172 return 1;
173 }
174