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