1 /*
2 * Functions for manipulating HTS messages
3 * Copyright (C) 2007 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #pragma once
20 #include <stdlib.h>
21 #include <inttypes.h>
22 #include "queue.h"
23 #include "build.h"
24
25 #define HTSMSG_ERR_FIELD_NOT_FOUND -1
26 #define HTSMSG_ERR_CONVERSION_IMPOSSIBLE -2
27
28 TAILQ_HEAD(htsmsg_field_queue, htsmsg_field);
29
30 typedef struct htsmsg {
31 /**
32 * fields
33 */
34 struct htsmsg_field_queue hm_fields;
35
36 /**
37 * Set if this message is a list, otherwise it is a map.
38 */
39 int hm_islist;
40
41 /**
42 * Data to be free'd when the message is destroyed
43 */
44 const void *hm_data;
45 size_t hm_data_size;
46 } htsmsg_t;
47
48
49 #define HMF_MAP 1
50 #define HMF_S64 2
51 #define HMF_STR 3
52 #define HMF_BIN 4
53 #define HMF_LIST 5
54 #define HMF_DBL 6
55 #define HMF_BOOL 7
56
57 typedef struct htsmsg_field {
58 TAILQ_ENTRY(htsmsg_field) hmf_link;
59 const char *hmf_name;
60 uint8_t hmf_type;
61 uint8_t hmf_flags;
62
63 #define HMF_ALLOCED 0x1
64 #define HMF_INALLOCED 0x2
65 #define HMF_NAME_INALLOCED 0x4
66 #define HMF_NAME_ALLOCED 0x8
67
68 union {
69 int64_t s64;
70 const char *str;
71 struct {
72 const char *data;
73 size_t len;
74 } bin;
75 htsmsg_t msg;
76 double dbl;
77 int bool;
78 } u;
79
80 #if ENABLE_SLOW_MEMORYINFO
81 size_t hmf_edata_size;
82 #endif
83 char hmf_edata[0];
84 } htsmsg_field_t;
85
86 #define hmf_s64 u.s64
87 #define hmf_msg u.msg
88 #define hmf_str u.str
89 #define hmf_bin u.bin.data
90 #define hmf_binsize u.bin.len
91 #define hmf_dbl u.dbl
92 #define hmf_bool u.bool
93
94 // backwards compat
95 #define htsmsg_get_map_by_field(f) htsmsg_field_get_map(f)
96 #define htsmsg_get_list_by_field(f) htsmsg_field_get_list(f)
97
98 #define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link)
99 #define HTSMSG_FIRST(msg) TAILQ_FIRST(&(msg)->hm_fields)
100 #define HTSMSG_NEXT(f) TAILQ_NEXT(f, hmf_link)
101
102 /**
103 * Create a new map
104 */
105 htsmsg_t *htsmsg_create_map(void);
106
107 /**
108 * Create a new list
109 */
110 htsmsg_t *htsmsg_create_list(void);
111
112 /**
113 * Remove a given field from a msg
114 */
115 void htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f);
116
117 /**
118 * Destroys a message (map or list)
119 */
120 void htsmsg_destroy(htsmsg_t *msg);
121
122 /**
123 * Add an boolean field.
124 */
125 void htsmsg_add_bool(htsmsg_t *msg, const char *name, int b);
126
127 /**
128 * Add/update an boolean field.
129 */
130 void htsmsg_set_bool(htsmsg_t *msg, const char *name, int b);
131
132 /**
133 * Add an integer field where source is signed 64 bit.
134 */
135 void htsmsg_add_s64(htsmsg_t *msg, const char *name, int64_t s64);
136
137 /**
138 * Add/update an integer field where source is signed 64 bit.
139 */
140 int htsmsg_set_s64(htsmsg_t *msg, const char *name, int64_t s64);
141
142 /**
143 * Add an integer field where source is unsigned 32 bit.
144 */
145 static inline void
htsmsg_add_u32(htsmsg_t * msg,const char * name,uint32_t u32)146 htsmsg_add_u32(htsmsg_t *msg, const char *name, uint32_t u32)
147 { htsmsg_add_s64(msg, name, u32); }
148
149 /**
150 * Add/update an integer field
151 */
152 static inline int
htsmsg_set_u32(htsmsg_t * msg,const char * name,uint32_t u32)153 htsmsg_set_u32(htsmsg_t *msg, const char *name, uint32_t u32)
154 { return htsmsg_set_s64(msg, name, u32); }
155
156 /**
157 * Add an integer field where source is signed 32 bit.
158 */
159 static inline void
htsmsg_add_s32(htsmsg_t * msg,const char * name,int32_t s32)160 htsmsg_add_s32(htsmsg_t *msg, const char *name, int32_t s32)
161 { htsmsg_add_s64(msg, name, s32); }
162
163 /**
164 * Add/update an integer field
165 */
166 static inline int
htsmsg_set_s32(htsmsg_t * msg,const char * name,int32_t s32)167 htsmsg_set_s32(htsmsg_t *msg, const char *name, int32_t s32)
168 { return htsmsg_set_s64(msg, name, s32); }
169
170 /**
171 * Add a string field.
172 */
173 void htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str);
174
175 /**
176 * Add a string field (NULL check).
177 */
178 void htsmsg_add_str2(htsmsg_t *msg, const char *name, const char *str);
179
180 /**
181 * Add a string field to a list only once.
182 */
183 void htsmsg_add_str_exclusive(htsmsg_t *msg, const char *str);
184
185 /**
186 * Add/update a string field
187 */
188 int htsmsg_set_str(htsmsg_t *msg, const char *name, const char *str);
189
190 /**
191 * Update a string field
192 */
193 int htsmsg_field_set_str(htsmsg_field_t *f, const char *str);
194 int htsmsg_field_set_str_force(htsmsg_field_t *f, const char *str);
195
196 /**
197 * Add an field where source is a list or map message.
198 */
199 htsmsg_t *htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub);
200
201 /**
202 * Add/update an field where source is a list or map message.
203 */
204 htsmsg_t *htsmsg_set_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub);
205
206 /**
207 * Add an field where source is a double
208 */
209 void htsmsg_add_dbl(htsmsg_t *msg, const char *name, double dbl);
210
211 /**
212 * Add an field where source is a list or map message.
213 *
214 * This function will not strdup() \p name but relies on the caller
215 * to keep the string allocated for as long as the message is valid.
216 */
217 void htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub);
218
219 /**
220 * Add an binary field. The data is copied to a malloced storage
221 */
222 void htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin,
223 size_t len);
224
225 /**
226 * Add an binary field. The data is not copied, instead the caller
227 * is responsible for keeping the data valid for as long as the message
228 * is around.
229 */
230 void htsmsg_add_binptr(htsmsg_t *msg, const char *name, const void *bin,
231 size_t len);
232
233 /**
234 * Get an integer as an unsigned 32 bit integer.
235 *
236 * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
237 * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
238 * out of range for the requested storage.
239 */
240 int htsmsg_get_u32(htsmsg_t *msg, const char *name, uint32_t *u32p);
241
242 int htsmsg_field_get_u32(htsmsg_field_t *f, uint32_t *u32p);
243
244 /**
245 * Get an integer as an signed 32 bit integer.
246 *
247 * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
248 * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
249 * out of range for the requested storage.
250 */
251 int htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p);
252
253 /**
254 * Get an integer as an signed 64 bit integer.
255 *
256 * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
257 * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
258 * out of range for the requested storage.
259 */
260 int htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p);
261
262 int htsmsg_field_get_s64(htsmsg_field_t *f, int64_t *s64p);
263
264 /*
265 * Return the field \p name as an s64.
266 */
267 int64_t htsmsg_get_s64_or_default(htsmsg_t *msg, const char *name, int64_t def);
268
269 int bool_check(const char *str);
270
271 int htsmsg_field_get_bool(htsmsg_field_t *f, int *boolp);
272
273 int htsmsg_get_bool(htsmsg_t *msg, const char *name, int *boolp);
274
275 int htsmsg_get_bool_or_default(htsmsg_t *msg, const char *name, int def);
276
277
278 /**
279 * Get pointer to a binary field. No copying of data is performed.
280 *
281 * @param binp Pointer to a void * that will be filled in with a pointer
282 * to the data
283 * @param lenp Pointer to a size_t that will be filled with the size of
284 * the data
285 *
286 * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
287 * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not a binary blob.
288 */
289 int htsmsg_get_bin(htsmsg_t *msg, const char *name, const void **binp,
290 size_t *lenp);
291
292 /**
293 * Get a field of type 'list'. No copying is done.
294 *
295 * @return NULL if the field can not be found or not of list type.
296 * Otherwise a htsmsg is returned.
297 */
298 htsmsg_t *htsmsg_get_list(htsmsg_t *msg, const char *name);
299
300 htsmsg_t *htsmsg_field_get_list(htsmsg_field_t *f);
301
302 /**
303 * Get a field of type 'string'. No copying is done.
304 *
305 * @return NULL if the field can not be found or not of string type.
306 * Otherwise a pointer to the data is returned.
307 */
308 const char *htsmsg_get_str(htsmsg_t *msg, const char *name);
309
310 /**
311 * Get a field of type 'map'. No copying is done.
312 *
313 * @return NULL if the field can not be found or not of map type.
314 * Otherwise a htsmsg is returned.
315 */
316 htsmsg_t *htsmsg_get_map(htsmsg_t *msg, const char *name);
317
318 htsmsg_t *htsmsg_field_get_map(htsmsg_field_t *f);
319
320 /**
321 * Traverse a hierarchy of htsmsg's to find a specific child.
322 */
323 htsmsg_t *htsmsg_get_map_multi(htsmsg_t *msg, ...)
324 __attribute__((__sentinel__(0)));
325
326 /**
327 * Traverse a hierarchy of htsmsg's to find a specific child.
328 */
329 const char *htsmsg_get_str_multi(htsmsg_t *msg, ...)
330 __attribute__((__sentinel__(0)));
331
332 /**
333 * Get a field of type 'double'.
334 *
335 * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist
336 * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or
337 * out of range for the requested storage.
338 */
339 int htsmsg_get_dbl(htsmsg_t *msg, const char *name, double *dblp);
340
341 int htsmsg_field_get_dbl(htsmsg_field_t *f, double *dblp);
342
343 /**
344 * Given the field \p f, return a string if it is of type string, otherwise
345 * return NULL
346 */
347 const char *htsmsg_field_get_string(htsmsg_field_t *f);
348 #define htsmsg_field_get_str(f) htsmsg_field_get_string(f)
349
350 /**
351 * Get s64 from field
352 */
353
354
355 /**
356 * Return the field \p name as an u32.
357 *
358 * @return An unsigned 32 bit integer or NULL if the field can not be found
359 * or if conversion is not possible.
360 */
361 int htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def);
362
363 /**
364 * Return the field \p name as an s32.
365 *
366 * @return A signed 32 bit integer or NULL if the field can not be found
367 * or if conversion is not possible.
368 */
369 int32_t htsmsg_get_s32_or_default(htsmsg_t *msg, const char *name,
370 int32_t def);
371
372 /**
373 * Remove the given field called \p name from the message \p msg.
374 */
375 int htsmsg_delete_field(htsmsg_t *msg, const char *name);
376
377 /**
378 * Is list/map empty
379 */
380 int htsmsg_is_empty(htsmsg_t *msg);
381
382 /**
383 * Detach will remove the given field (and only if it is a list or map)
384 * from the message and make it a 'standalone message'. This means
385 * the the contents of the sub message will stay valid if the parent is
386 * destroyed. The caller is responsible for freeing this new message.
387 */
388 htsmsg_t *htsmsg_detach_submsg(htsmsg_field_t *f);
389
390 /**
391 * Print a message to stdout.
392 */
393 void htsmsg_print(htsmsg_t *msg);
394
395 /**
396 * Create a new field. Primarily intended for htsmsg internal functions.
397 */
398 htsmsg_field_t *htsmsg_field_add(htsmsg_t *msg, const char *name,
399 int type, int flags, size_t esize);
400
401 /**
402 * Get a field, return NULL if it does not exist
403 */
404 htsmsg_field_t *htsmsg_field_find(htsmsg_t *msg, const char *name);
405
406 /**
407 * Get a last field, return NULL if it does not exist
408 */
409 htsmsg_field_t *htsmsg_field_last(htsmsg_t *msg);
410
411
412 /**
413 * Clone a message.
414 */
415 htsmsg_t *htsmsg_copy(htsmsg_t *src);
416
417 /**
418 * Compare a message.
419 */
420 int htsmsg_cmp(htsmsg_t *m1, htsmsg_t *m2);
421
422 #define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link)
423
424
425 /**
426 * Misc
427 */
428 htsmsg_t *htsmsg_get_map_in_list(htsmsg_t *m, int num);
429
430 htsmsg_t *htsmsg_get_map_by_field_if_name(htsmsg_field_t *f, const char *name);
431
432 const char *htsmsg_get_cdata(htsmsg_t *m, const char *field);
433
434 char *htsmsg_list_2_csv(htsmsg_t *m, char delim, int human);
435
436 htsmsg_t *htsmsg_csv_2_list(const char *str, char delim);
437
438 htsmsg_t *htsmsg_create_key_val(const char *key, const char *val);
439
440 /**
441 *
442 */
443 struct memoryinfo;
444 extern struct memoryinfo htsmsg_memoryinfo;
445 extern struct memoryinfo htsmsg_field_memoryinfo;
446