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