Browse code

rtpengine: normalise `compat.h` handling towards bencode upstream

fixes #1885

Richard Fuchs authored on 11/03/2019 11:52:58
Showing 1 changed files
... ...
@@ -4,24 +4,7 @@
4 4
 #include <sys/uio.h>
5 5
 #include <string.h>
6 6
 
7
-#if defined(PKG_MALLOC) || defined(pkg_malloc)
8
-/* kamailio */
9
-# include "../../core/mem/mem.h"
10
-# include "../../core/str.h"
11
-# ifndef BENCODE_MALLOC
12
-# define BENCODE_MALLOC pkg_malloc
13
-# define BENCODE_FREE pkg_free
14
-# endif
15
-# define INLINE static inline
16
-#else
17
-/* rtpengine */
18
-# include "compat.h"
19
-# include "str.h"
20
-# ifndef BENCODE_MALLOC
21
-# define BENCODE_MALLOC malloc
22
-# define BENCODE_FREE free
23
-# endif
24
-#endif
7
+#include "compat.h"
25 8
 
26 9
 struct bencode_buffer;
27 10
 enum bencode_type;
Browse code

rtpengine: remove the SHM_MEM #define, after core change

Henning Westerholt authored on 26/12/2018 19:47:49
Showing 1 changed files
... ...
@@ -4,7 +4,7 @@
4 4
 #include <sys/uio.h>
5 5
 #include <string.h>
6 6
 
7
-#if defined(SHM_MEM) || defined(PKG_MALLOC) || defined(pkg_malloc)
7
+#if defined(PKG_MALLOC) || defined(pkg_malloc)
8 8
 /* kamailio */
9 9
 # include "../../core/mem/mem.h"
10 10
 # include "../../core/str.h"
Browse code

core, lib, modules: updated include paths for header files

Daniel-Constantin Mierla authored on 07/12/2016 11:07:22
Showing 1 changed files
... ...
@@ -6,8 +6,8 @@
6 6
 
7 7
 #if defined(SHM_MEM) || defined(PKG_MALLOC) || defined(pkg_malloc)
8 8
 /* kamailio */
9
-# include "../../mem/mem.h"
10
-# include "../../str.h"
9
+# include "../../core/mem/mem.h"
10
+# include "../../core/str.h"
11 11
 # ifndef BENCODE_MALLOC
12 12
 # define BENCODE_MALLOC pkg_malloc
13 13
 # define BENCODE_FREE pkg_free
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,561 @@
1
+#ifndef _BENCODE_H_
2
+#define _BENCODE_H_
3
+
4
+#include <sys/uio.h>
5
+#include <string.h>
6
+
7
+#if defined(SHM_MEM) || defined(PKG_MALLOC) || defined(pkg_malloc)
8
+/* kamailio */
9
+# include "../../mem/mem.h"
10
+# include "../../str.h"
11
+# ifndef BENCODE_MALLOC
12
+# define BENCODE_MALLOC pkg_malloc
13
+# define BENCODE_FREE pkg_free
14
+# endif
15
+# define INLINE static inline
16
+#else
17
+/* rtpengine */
18
+# include "compat.h"
19
+# include "str.h"
20
+# ifndef BENCODE_MALLOC
21
+# define BENCODE_MALLOC malloc
22
+# define BENCODE_FREE free
23
+# endif
24
+#endif
25
+
26
+struct bencode_buffer;
27
+enum bencode_type;
28
+struct bencode_item;
29
+struct __bencode_buffer_piece;
30
+struct __bencode_free_list;
31
+
32
+typedef enum bencode_type bencode_type_t;
33
+typedef struct bencode_buffer bencode_buffer_t;
34
+typedef struct bencode_item bencode_item_t;
35
+typedef void (*free_func_t)(void *);
36
+
37
+enum bencode_type {
38
+	BENCODE_INVALID = 0,
39
+	BENCODE_STRING,		/* byte string */
40
+	BENCODE_INTEGER,	/* long long int */
41
+	BENCODE_LIST,		/* flat list of other objects */
42
+	BENCODE_DICTIONARY,	/* dictionary of key/values pairs. keys are always strings */
43
+	BENCODE_IOVEC,		/* special case of a string, built through bencode_string_iovec() */
44
+	BENCODE_END_MARKER,	/* used internally only */
45
+};
46
+
47
+struct bencode_item {
48
+	bencode_type_t type;
49
+	struct iovec iov[2];	/* when decoding, iov[1] contains the contents of a string object */
50
+	unsigned int iov_cnt;
51
+	unsigned int str_len;	/* length of the whole ENCODED object. NOT the length of a byte string */
52
+	long long int value;	/* when decoding an integer, contains the value; otherwise used internally */
53
+	bencode_item_t *parent, *child, *last_child, *sibling;
54
+	bencode_buffer_t *buffer;
55
+	char __buf[0];
56
+};
57
+
58
+struct bencode_buffer {
59
+	struct __bencode_buffer_piece *pieces;
60
+	struct __bencode_free_list *free_list;
61
+	int error:1;		/* set to !0 if allocation failed at any point */
62
+};
63
+
64
+
65
+
66
+
67
+
68
+/* to embed BENCODE_STRING objects into printf-like functions */
69
+#define BENCODE_FORMAT "%.*s"
70
+#define BENCODE_FMT(b) (int) (b)->iov[1].iov_len, (char *) (b)->iov[1].iov_base
71
+
72
+
73
+
74
+
75
+/*** INIT & DESTROY ***/
76
+
77
+/* Initializes a bencode_buffer_t object. This object is used to group together all memory allocations
78
+ * made when encoding or decoding. Its memory usage is always growing, until it is freed, at which point
79
+ * all objects created through it become invalid. The actual object must be allocated separately, for
80
+ * example by being put on the stack.
81
+ * Returns 0 on success or -1 on failure (if no memory could be allocated). */
82
+int bencode_buffer_init(bencode_buffer_t *buf);
83
+
84
+/* Allocate a piece of memory from the given buffer object */
85
+void *bencode_buffer_alloc(bencode_buffer_t *, unsigned int);
86
+
87
+/* Destroys a previously initialized bencode_buffer_t object. All memory used by the object is freed
88
+ * and all objects created through it become invalid. */
89
+void bencode_buffer_free(bencode_buffer_t *buf);
90
+
91
+/* Creates a new empty dictionary object. Memory will be allocated from the bencode_buffer_t object.
92
+ * Returns NULL if no memory could be allocated. */
93
+bencode_item_t *bencode_dictionary(bencode_buffer_t *buf);
94
+
95
+/* Creates a new empty list object. Memory will be allocated from the bencode_buffer_t object.
96
+ * Returns NULL if no memory could be allocated. */
97
+bencode_item_t *bencode_list(bencode_buffer_t *buf);
98
+
99
+/* Adds a pointer to the bencode_buffer_t object's internal free list. When the bencode_buffer_t
100
+ * object is destroyed, the specified function will be called on this pointer. */
101
+void bencode_buffer_destroy_add(bencode_buffer_t *buf, free_func_t, void *);
102
+
103
+/* Returns the buffer associated with an item, or NULL if pointer given is NULL */
104
+INLINE bencode_buffer_t *bencode_item_buffer(bencode_item_t *);
105
+
106
+
107
+
108
+
109
+
110
+/*** DICTIONARY BUILDING ***/
111
+
112
+/* Adds a new key/value pair to a dictionary. Memory will be allocated from the same bencode_buffer_t
113
+ * object as the dictionary was allocated from. Returns NULL if no memory could be allocated, otherwise
114
+ * returns "val".
115
+ * The function does not check whether the key being added is already present in the dictionary.
116
+ * Also, the function does not reorder keys into lexicographical order; keys will be encoded in
117
+ * the same order as they've been added. The key must a null-terminated string.
118
+ * The value to be added must not have been previously linked into any other dictionary or list. */
119
+INLINE bencode_item_t *bencode_dictionary_add(bencode_item_t *dict, const char *key, bencode_item_t *val);
120
+INLINE bencode_item_t *bencode_dictionary_str_add(bencode_item_t *dict, const str *key, bencode_item_t *val);
121
+
122
+/* Identical to bencode_dictionary_add() but doesn't require the key string to be null-terminated */
123
+bencode_item_t *bencode_dictionary_add_len(bencode_item_t *dict, const char *key, int keylen, bencode_item_t *val);
124
+
125
+/* Convenience function to add a string value to a dictionary, possibly duplicated into the
126
+ * bencode_buffer_t object. */
127
+INLINE bencode_item_t *bencode_dictionary_add_string(bencode_item_t *dict, const char *key, const char *val);
128
+INLINE bencode_item_t *bencode_dictionary_add_string_dup(bencode_item_t *dict, const char *key, const char *val);
129
+
130
+/* Ditto, but for a "str" object */
131
+INLINE bencode_item_t *bencode_dictionary_add_str(bencode_item_t *dict, const char *key, const str *val);
132
+INLINE bencode_item_t *bencode_dictionary_str_add_str(bencode_item_t *dict, const str *key, const str *val);
133
+INLINE bencode_item_t *bencode_dictionary_add_str_dup(bencode_item_t *dict, const char *key, const str *val);
134
+
135
+/* Ditto, but adds a string created through an iovec array to the dictionary. See
136
+ * bencode_string_iovec(). */
137
+INLINE bencode_item_t *bencode_dictionary_add_iovec(bencode_item_t *dict, const char *key,
138
+	const struct iovec *iov, int iov_cnt, int str_len);
139
+
140
+/* Convenience functions to add the respective (newly created) objects to a dictionary */
141
+INLINE bencode_item_t *bencode_dictionary_add_integer(bencode_item_t *dict, const char *key, long long int val);
142
+INLINE bencode_item_t *bencode_dictionary_add_dictionary(bencode_item_t *dict, const char *key);
143
+INLINE bencode_item_t *bencode_dictionary_add_list(bencode_item_t *dict, const char *key);
144
+
145
+
146
+
147
+
148
+
149
+/*** LIST BUILDING ***/
150
+
151
+/* Adds a new item to a list. Returns "item".
152
+ * The item to be added must not have been previously linked into any other dictionary or list. */
153
+bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item);
154
+
155
+/* Convenience function to add the respective (newly created) objects to a list */
156
+INLINE bencode_item_t *bencode_list_add_string(bencode_item_t *list, const char *s);
157
+INLINE bencode_item_t *bencode_list_add_str(bencode_item_t *list, const str *s);
158
+INLINE bencode_item_t *bencode_list_add_list(bencode_item_t *list);
159
+INLINE bencode_item_t *bencode_list_add_dictionary(bencode_item_t *list);
160
+
161
+
162
+
163
+
164
+
165
+/*** STRING BUILDING & HANDLING ***/
166
+
167
+/* Creates a new byte-string object. The given string does not have to be null-terminated, instead
168
+ * the length of the string is specified by the "len" parameter. Returns NULL if no memory could
169
+ * be allocated.
170
+ * Strings are not copied or duplicated, so the string pointed to by "s" must remain valid until
171
+ * the complete document is finally encoded or sent out. */
172
+bencode_item_t *bencode_string_len(bencode_buffer_t *buf, const char *s, int len);
173
+
174
+/* Creates a new byte-string object. The given string must be null-terminated. Otherwise identical
175
+ * to bencode_string_len(). */
176
+INLINE bencode_item_t *bencode_string(bencode_buffer_t *buf, const char *s);
177
+
178
+/* Creates a new byte-string object from a "str" object. The string does not have to be null-
179
+ * terminated. */
180
+INLINE bencode_item_t *bencode_str(bencode_buffer_t *buf, const str *s);
181
+
182
+/* Identical to the above three functions, but copies the string into the bencode_buffer_t object.
183
+ * Thus, the given string doesn't have to remain valid and accessible afterwards. */
184
+bencode_item_t *bencode_string_len_dup(bencode_buffer_t *buf, const char *s, int len);
185
+INLINE bencode_item_t *bencode_string_dup(bencode_buffer_t *buf, const char *s);
186
+INLINE bencode_item_t *bencode_str_dup(bencode_buffer_t *buf, const str *s);
187
+
188
+/* Creates a new byte-string object from an iovec array. The created object has different internal
189
+ * semantics (not a BENCODE_STRING, but a BENCODE_IOVEC) and must not be treated like other string
190
+ * objects. The array pointer and contents must still be valid and accessible when the complete
191
+ * document is encoded. The full length of the string composed of the iovec array is given in the
192
+ * "str_len" parameter, which can be negative, in which case the array is iterated to calculate the
193
+ * length. */
194
+bencode_item_t *bencode_string_iovec(bencode_buffer_t *buf, const struct iovec *iov, int iov_cnt, int str_len);
195
+
196
+/* Convenience function to compare a string object to a regular C string. Returns 2 if object
197
+ * isn't a string object, otherwise returns according to strcmp(). */
198
+INLINE int bencode_strcmp(bencode_item_t *a, const char *b);
199
+
200
+/* Converts the string object "in" into a str object "out". Returns "out" on success, or NULL on
201
+ * error ("in" was NULL or not a string object). */
202
+INLINE str *bencode_get_str(bencode_item_t *in, str *out);
203
+
204
+
205
+
206
+
207
+
208
+/*** INTEGER BUILDING ***/
209
+
210
+/* Creates a new integer object. Returns NULL if no memory could be allocated. */
211
+bencode_item_t *bencode_integer(bencode_buffer_t *buf, long long int i);
212
+
213
+
214
+
215
+
216
+
217
+/*** COLLAPSING & ENCODING ***/
218
+
219
+/* Collapses and encodes the complete document structure under the "root" element (which normally
220
+ * is either a dictionary or a list) into an array of "iovec" structures. This array can then be
221
+ * passed to functions ala writev() or sendmsg() to output the encoded document as a whole. Memory
222
+ * is allocated from the same bencode_buffer_t object as the "root" object was allocated from.
223
+ * The "head" and "tail" parameters specify additional "iovec" structures that should be included
224
+ * in the allocated array before or after (respectively) the iovec structures used by the encoded
225
+ * document. Both parameters can be zero if no additional elements in the array are required.
226
+ * Returns a pointer to the allocated array or NULL if no memory could be allocated. The number of
227
+ * array elements is returned in "cnt" which must be a valid pointer to an int. This number does
228
+ * not include any additional elements allocated through the "head" or "tail" parameters.
229
+ *
230
+ * Therefore, the contents of the returned array are:
231
+ * [0 .. (head - 1)]                         = unused and uninitialized iovec structures
232
+ * [(head) .. (head + cnt - 1)]              = the encoded document
233
+ * [(head + cnt) .. (head + cnt + tail - 1)] = unused and uninitialized iovec structures
234
+ *
235
+ * The returned array will be freed when the corresponding bencode_buffer_t object is destroyed. */
236
+struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail);
237
+
238
+/* Similar to bencode_iovec(), but instead returns the encoded document as a null-terminated string.
239
+ * Memory for the string is allocated from the same bencode_buffer_t object as the "root" object
240
+ * was allocated from. If "len" is a non-NULL pointer, the length of the genrated string is returned
241
+ * in *len. This is important if the encoded document contains binary data, in which case null
242
+ * termination cannot be trusted. The returned string is freed when the corresponding
243
+ * bencode_buffer_t object is destroyed. */
244
+char *bencode_collapse(bencode_item_t *root, int *len);
245
+
246
+/* Identical to bencode_collapse() but fills in a "str" object. Returns "out". */
247
+static str *bencode_collapse_str(bencode_item_t *root, str *out);
248
+
249
+/* Identical to bencode_collapse(), but the memory for the returned string is not allocated from
250
+ * a bencode_buffer_t object, but instead using the function defined as BENCODE_MALLOC (normally
251
+ * malloc() or pkg_malloc()), similar to strdup(). Using this function, the bencode_buffer_t
252
+ * object can be destroyed, but the returned string remains valid and usable. */
253
+char *bencode_collapse_dup(bencode_item_t *root, int *len);
254
+
255
+
256
+
257
+
258
+
259
+/*** DECODING ***/
260
+
261
+/* Decodes an encoded document from a string into a tree of bencode_item_t objects. The string does
262
+ * not need to be null-terminated, instead the length of the string is given through the "len"
263
+ * parameter. Memory is allocated from the bencode_buffer_t object. Returns NULL if no memory could
264
+ * be allocated or if the document could not be successfully decoded.
265
+ *
266
+ * The returned element is the "root" of the document tree and normally is either a list object or
267
+ * a dictionary object, but can also be a single string or integer object with no other objects
268
+ * underneath or besides it (no childred and no siblings). The type of the object can be determined
269
+ * by its ->type property.
270
+ *
271
+ * The number of bytes that could successfully be decoded into an object tree can be accessed through
272
+ * the root element's ->str_len property. Normally, this number should be equal to the "len" parameter
273
+ * passed, in which case the full string could be decoded. If ->str_len is less than "len", then there
274
+ * was additional stray byte data after the end of the encoded document.
275
+ *
276
+ * The document tree can be traversed through the ->child and ->sibling pointers in each object. The
277
+ * ->child pointer will be NULL for string and integer objects, as they don't contain other objects.
278
+ * For lists and dictionaries, ->child will be a pointer to the first contained object. This first
279
+ * contained object's ->sibling pointer will point to the next (second) contained object of the list
280
+ * or the dictionary, and so on. The last contained element of a list of dictionary will have a
281
+ * NULL ->sibling pointer.
282
+ *
283
+ * Dictionaries are like lists with ordered key/value pairs. When traversing dictionaries like
284
+ * lists, the following applies: The first element in the list (where ->child points to) will be the
285
+ * key of the first key/value pair (guaranteed to be a string and guaranteed to be present). The
286
+ * next element (following one ->sibling) will be the value of the first key/value pair. Following
287
+ * another ->sibling will point to the key of the next (second) key/value pair, and so on.
288
+ *
289
+ * However, to access children objects of dictionaries, the special functions following the naming
290
+ * scheme bencode_dictionary_get_* below should be used. They perform key lookup through a simple
291
+ * hash built into the dictionary object and so perform the lookup much faster. Only dictionaries
292
+ * created through a decoding process (i.e. not ones created from bencode_dictionary()) have this
293
+ * property. The hash is efficient only up to a certain number of elements (BENCODE_HASH_BUCKETS
294
+ * in bencode.c) contained in the dictionary. If the number of children object exceeds this number,
295
+ * key lookup will be slower than simply linearily traversing the list.
296
+ *
297
+ * The decoding function for dictionary object does not check whether keys are unique within the
298
+ * dictionary. It also does not care about lexicographical order of the keys.
299
+ *
300
+ * Decoded string objects will contain the raw decoded byte string in ->iov[1] (including the correct
301
+ * length). Strings are NOT null-terminated. Decoded integer objects will contain the decoded value
302
+ * in ->value.
303
+ *
304
+ * All memory is freed when the bencode_buffer_t object is destroyed.
305
+ */
306
+bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len);
307
+
308
+/* Identical to bencode_decode(), but returns successfully only if the type of the decoded object match
309
+ * "expect". */
310
+INLINE bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const char *s, int len, bencode_type_t expect);
311
+
312
+/* Identical to bencode_decode_expect() but takes a "str" argument. */
313
+INLINE bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect);
314
+
315
+
316
+
317
+
318
+
319
+/*** DICTIONARY LOOKUP & EXTRACTION ***/
320
+
321
+/* Searches the given dictionary object for the given key and returns the respective value. Returns
322
+ * NULL if the given object isn't a dictionary or if the key doesn't exist. The key must be a
323
+ * null-terminated string. */
324
+INLINE bencode_item_t *bencode_dictionary_get(bencode_item_t *dict, const char *key);
325
+
326
+/* Identical to bencode_dictionary_get() but doesn't require the key to be null-terminated. */
327
+bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key, int key_len);
328
+
329
+/* Identical to bencode_dictionary_get() but returns the value only if its type is a string, and
330
+ * returns it as a pointer to the string itself. Returns NULL if the value is of some other type. The
331
+ * returned string is NOT null-terminated. Length of the string is returned in *len, which must be a
332
+ * valid pointer. The returned string will be valid until dict's bencode_buffer_t object is destroyed. */
333
+INLINE char *bencode_dictionary_get_string(bencode_item_t *dict, const char *key, int *len);
334
+
335
+/* Identical to bencode_dictionary_get_string() but fills in a "str" struct. Returns str->s, which
336
+ * may be NULL. */
337
+INLINE char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str);
338
+
339
+/* Looks up the given key in the dictionary and compares the corresponding value to the given
340
+ * null-terminated string. Returns 2 if the key isn't found or if the value isn't a string, otherwise
341
+ * returns according to strcmp(). */
342
+INLINE int bencode_dictionary_get_strcmp(bencode_item_t *dict, const char *key, const char *str);
343
+
344
+/* Identical to bencode_dictionary_get() but returns the string in a newly allocated buffer (using the
345
+ * BENCODE_MALLOC function), which remains valid even after bencode_buffer_t is destroyed. */
346
+INLINE char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len);
347
+
348
+/* Combines bencode_dictionary_get_str() and bencode_dictionary_get_string_dup(). Fills in a "str"
349
+ * struct, but copies the string into a newly allocated buffer. Returns str->s. */
350
+INLINE char *bencode_dictionary_get_str_dup(bencode_item_t *dict, const char *key, str *str);
351
+
352
+/* Identical to bencode_dictionary_get_string() but expects an integer object. The parameter "defval"
353
+ * specified which value should be returned if the key is not found or if the value is not an integer. */
354
+INLINE long long int bencode_dictionary_get_integer(bencode_item_t *dict, const char *key, long long int defval);
355
+
356
+/* Identical to bencode_dictionary_get(), but returns the object only if its type matches "expect". */
357
+INLINE bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const char *key, bencode_type_t expect);
358
+
359
+
360
+
361
+
362
+
363
+/**************************/
364
+
365
+INLINE bencode_buffer_t *bencode_item_buffer(bencode_item_t *i) {
366
+	if (!i)
367
+		return NULL;
368
+	return i->buffer;
369
+}
370
+
371
+INLINE bencode_item_t *bencode_string(bencode_buffer_t *buf, const char *s) {
372
+	return bencode_string_len(buf, s, strlen(s));
373
+}
374
+
375
+INLINE bencode_item_t *bencode_string_dup(bencode_buffer_t *buf, const char *s) {
376
+	return bencode_string_len_dup(buf, s, strlen(s));
377
+}
378
+
379
+INLINE bencode_item_t *bencode_str(bencode_buffer_t *buf, const str *s) {
380
+	return bencode_string_len(buf, s->s, s->len);
381
+}
382
+
383
+INLINE bencode_item_t *bencode_str_dup(bencode_buffer_t *buf, const str *s) {
384
+	return bencode_string_len_dup(buf, s->s, s->len);
385
+}
386
+
387
+INLINE bencode_item_t *bencode_dictionary_add(bencode_item_t *dict, const char *key, bencode_item_t *val) {
388
+	if (!key)
389
+		return NULL;
390
+	return bencode_dictionary_add_len(dict, key, strlen(key), val);
391
+}
392
+
393
+INLINE bencode_item_t *bencode_dictionary_str_add(bencode_item_t *dict, const str *key, bencode_item_t *val) {
394
+	if (!key)
395
+		return NULL;
396
+	return bencode_dictionary_add_len(dict, key->s, key->len, val);
397
+}
398
+
399
+INLINE bencode_item_t *bencode_dictionary_add_string(bencode_item_t *dict, const char *key, const char *val) {
400
+	if (!val)
401
+		return NULL;
402
+	return bencode_dictionary_add(dict, key, bencode_string(bencode_item_buffer(dict), val));
403
+}
404
+
405
+INLINE bencode_item_t *bencode_dictionary_add_string_dup(bencode_item_t *dict, const char *key, const char *val) {
406
+	if (!val)
407
+		return NULL;
408
+	return bencode_dictionary_add(dict, key, bencode_string_dup(bencode_item_buffer(dict), val));
409
+}
410
+
411
+INLINE bencode_item_t *bencode_dictionary_add_str(bencode_item_t *dict, const char *key, const str *val) {
412
+	if (!val)
413
+		return NULL;
414
+	return bencode_dictionary_add(dict, key, bencode_str(bencode_item_buffer(dict), val));
415
+}
416
+
417
+INLINE bencode_item_t *bencode_dictionary_str_add_str(bencode_item_t *dict, const str *key, const str *val) {
418
+	if (!val)
419
+		return NULL;
420
+	return bencode_dictionary_str_add(dict, key, bencode_str(bencode_item_buffer(dict), val));
421
+}
422
+
423
+INLINE bencode_item_t *bencode_dictionary_add_str_dup(bencode_item_t *dict, const char *key, const str *val) {
424
+	if (!val)
425
+		return NULL;
426
+	return bencode_dictionary_add(dict, key, bencode_str_dup(bencode_item_buffer(dict), val));
427
+}
428
+
429
+INLINE bencode_item_t *bencode_dictionary_add_integer(bencode_item_t *dict, const char *key, long long int val) {
430
+	return bencode_dictionary_add(dict, key, bencode_integer(bencode_item_buffer(dict), val));
431
+}
432
+
433
+INLINE bencode_item_t *bencode_dictionary_add_dictionary(bencode_item_t *dict, const char *key) {
434
+	return bencode_dictionary_add(dict, key, bencode_dictionary(bencode_item_buffer(dict)));
435
+}
436
+
437
+INLINE bencode_item_t *bencode_dictionary_add_list(bencode_item_t *dict, const char *key) {
438
+	return bencode_dictionary_add(dict, key, bencode_list(bencode_item_buffer(dict)));
439
+}
440
+
441
+INLINE bencode_item_t *bencode_list_add_string(bencode_item_t *list, const char *s) {
442
+	return bencode_list_add(list, bencode_string(bencode_item_buffer(list), s));
443
+}
444
+
445
+INLINE bencode_item_t *bencode_list_add_str(bencode_item_t *list, const str *s) {
446
+	return bencode_list_add(list, bencode_str(bencode_item_buffer(list), s));
447
+}
448
+
449
+INLINE bencode_item_t *bencode_list_add_list(bencode_item_t *list) {
450
+	return bencode_list_add(list, bencode_list(bencode_item_buffer(list)));
451
+}
452
+
453
+INLINE bencode_item_t *bencode_list_add_dictionary(bencode_item_t *list) {
454
+	return bencode_list_add(list, bencode_dictionary(bencode_item_buffer(list)));
455
+}
456
+
457
+INLINE bencode_item_t *bencode_dictionary_get(bencode_item_t *dict, const char *key) {
458
+	if (!key)
459
+		return NULL;
460
+	return bencode_dictionary_get_len(dict, key, strlen(key));
461
+}
462
+
463
+INLINE char *bencode_dictionary_get_string(bencode_item_t *dict, const char *key, int *len) {
464
+	bencode_item_t *val;
465
+	val = bencode_dictionary_get(dict, key);
466
+	if (!val || val->type != BENCODE_STRING)
467
+		return NULL;
468
+	*len = val->iov[1].iov_len;
469
+	return val->iov[1].iov_base;
470
+}
471
+
472
+INLINE char *bencode_dictionary_get_str(bencode_item_t *dict, const char *key, str *str) {
473
+	str->s = bencode_dictionary_get_string(dict, key, &str->len);
474
+	if (!str->s)
475
+		str->len = 0;
476
+	return str->s;
477
+}
478
+
479
+INLINE char *bencode_dictionary_get_string_dup(bencode_item_t *dict, const char *key, int *len) {
480
+	const char *s;
481
+	char *ret;
482
+	s = bencode_dictionary_get_string(dict, key, len);
483
+	if (!s)
484
+		return NULL;
485
+	ret = BENCODE_MALLOC(*len);
486
+	if (!ret)
487
+		return NULL;
488
+	memcpy(ret, s, *len);
489
+	return ret;
490
+}
491
+
492
+INLINE char *bencode_dictionary_get_str_dup(bencode_item_t *dict, const char *key, str *str) {
493
+	str->s = bencode_dictionary_get_string_dup(dict, key, &str->len);
494
+	return str->s;
495
+}
496
+
497
+INLINE long long int bencode_dictionary_get_integer(bencode_item_t *dict, const char *key, long long int defval) {
498
+	bencode_item_t *val;
499
+	val = bencode_dictionary_get(dict, key);
500
+	if (!val || val->type != BENCODE_INTEGER)
501
+		return defval;
502
+	return val->value;
503
+}
504
+
505
+INLINE bencode_item_t *bencode_decode_expect(bencode_buffer_t *buf, const char *s, int len, bencode_type_t expect) {
506
+	bencode_item_t *ret;
507
+	ret = bencode_decode(buf, s, len);
508
+	if (!ret || ret->type != expect)
509
+		return NULL;
510
+	return ret;
511
+}
512
+
513
+INLINE bencode_item_t *bencode_decode_expect_str(bencode_buffer_t *buf, const str *s, bencode_type_t expect) {
514
+	return bencode_decode_expect(buf, s->s, s->len, expect);
515
+}
516
+
517
+INLINE bencode_item_t *bencode_dictionary_get_expect(bencode_item_t *dict, const char *key, bencode_type_t expect) {
518
+	bencode_item_t *ret;
519
+	ret = bencode_dictionary_get(dict, key);
520
+	if (!ret || ret->type != expect)
521
+		return NULL;
522
+	return ret;
523
+}
524
+INLINE str *bencode_collapse_str(bencode_item_t *root, str *out) {
525
+	out->s = bencode_collapse(root, &out->len);
526
+	return out;
527
+}
528
+INLINE int bencode_strcmp(bencode_item_t *a, const char *b) {
529
+	int len;
530
+	if (a->type != BENCODE_STRING)
531
+		return 2;
532
+	len = strlen(b);
533
+	if (a->iov[1].iov_len < len)
534
+		return -1;
535
+	if (a->iov[1].iov_len > len)
536
+		return 1;
537
+	return memcmp(a->iov[1].iov_base, b, len);
538
+}
539
+INLINE int bencode_dictionary_get_strcmp(bencode_item_t *dict, const char *key, const char *str) {
540
+	bencode_item_t *i;
541
+	i = bencode_dictionary_get(dict, key);
542
+	if (!i)
543
+		return 2;
544
+	return bencode_strcmp(i, str);
545
+}
546
+
547
+INLINE str *bencode_get_str(bencode_item_t *in, str *out) {
548
+	if (!in || in->type != BENCODE_STRING)
549
+		return NULL;
550
+	out->s = in->iov[1].iov_base;
551
+	out->len = in->iov[1].iov_len;
552
+	return out;
553
+}
554
+
555
+INLINE bencode_item_t *bencode_dictionary_add_iovec(bencode_item_t *dict, const char *key,
556
+		const struct iovec *iov, int iov_cnt, int str_len)
557
+{
558
+	return bencode_dictionary_add(dict, key, bencode_string_iovec(bencode_item_buffer(dict), iov, iov_cnt, str_len));
559
+}
560
+
561
+#endif