Add a small lib to interpret and produce headers as used in http style requests.
[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     pa_strbuf *buf;
96
97     pa_assert(p);
98     pa_assert(key);
99
100     buf = pa_strbuf_new();
101     if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
102         hdr = pa_xnew(struct header, 1);
103         hdr->key = pa_xstrdup(key);
104         add = TRUE;
105     } else {
106         pa_strbuf_puts(buf, hdr->value);
107         pa_xfree(hdr->value);
108     }
109     pa_strbuf_puts(buf, value);
110     hdr->value = pa_strbuf_tostring_free(buf);
111     hdr->nbytes = strlen(hdr->value)+1;
112
113     if (add)
114         pa_hashmap_put(MAKE_HASHMAP(p), hdr->key, hdr);
115
116     return 0;
117 }
118
119 const char *pa_headerlist_gets(pa_headerlist *p, const char *key) {
120     struct header *hdr;
121
122     pa_assert(p);
123     pa_assert(key);
124
125     if (!(hdr = pa_hashmap_get(MAKE_HASHMAP(p), key)))
126         return NULL;
127
128     if (hdr->nbytes <= 0)
129         return NULL;
130
131     if (((char*) hdr->value)[hdr->nbytes-1] != 0)
132         return NULL;
133
134     if (strlen((char*) hdr->value) != hdr->nbytes-1)
135         return NULL;
136
137     return (char*) hdr->value;
138 }
139
140 int pa_headerlist_remove(pa_headerlist *p, const char *key) {
141     struct header *hdr;
142
143     pa_assert(p);
144     pa_assert(key);
145
146     if (!(hdr = pa_hashmap_remove(MAKE_HASHMAP(p), key)))
147         return -1;
148
149     header_free(hdr);
150     return 0;
151 }
152
153 const char *pa_headerlist_iterate(pa_headerlist *p, void **state) {
154     struct header *hdr;
155
156     if (!(hdr = pa_hashmap_iterate(MAKE_HASHMAP(p), state, NULL)))
157         return NULL;
158
159     return hdr->key;
160 }
161
162 char *pa_headerlist_to_string(pa_headerlist *p) {
163     const char *key;
164     void *state = NULL;
165     pa_strbuf *buf;
166
167     pa_assert(p);
168
169     buf = pa_strbuf_new();
170
171     while ((key = pa_headerlist_iterate(p, &state))) {
172
173         const char *v;
174
175         if ((v = pa_headerlist_gets(p, key)))
176             pa_strbuf_printf(buf, "%s: %s\r\n", key, v);
177     }
178
179     return pa_strbuf_tostring_free(buf);
180 }
181
182 int pa_headerlist_contains(pa_headerlist *p, const char *key) {
183     pa_assert(p);
184     pa_assert(key);
185
186     if (!(pa_hashmap_get(MAKE_HASHMAP(p), key)))
187         return 0;
188
189     return 1;
190 }