1 /**
2  *
3  * /brief getdns list management functions
4  *
5  * This is the meat of the API
6  * Originally taken from the getdns API description pseudo implementation.
7  *
8  */
9 
10 /*
11  * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are met:
16  * * Redistributions of source code must retain the above copyright
17  *   notice, this list of conditions and the following disclaimer.
18  * * Redistributions in binary form must reproduce the above copyright
19  *   notice, this list of conditions and the following disclaimer in the
20  *   documentation and/or other materials provided with the distribution.
21  * * Neither the names of the copyright holders nor the
22  *   names of its contributors may be used to endorse or promote products
23  *   derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
29  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <string.h>
38 #include <ctype.h>
39 #include "types-internal.h"
40 #include "util-internal.h"
41 #include "list.h"
42 #include "dict.h"
43 
44 getdns_return_t
_getdns_list_find(const getdns_list * list,const char * key,getdns_item ** item)45 _getdns_list_find(const getdns_list *list, const char *key, getdns_item **item)
46 {
47 	const char *next;
48 	char *endptr;
49 	size_t index;
50 	getdns_item *i;
51 
52 	if (*key == '/') {
53 		if (!(next = strchr(++key, '/')))
54 			next = strchr(key, '\0');
55 	} else
56 		next = strchr(key, '\0');
57 
58 	if (key[0] == '-' && next == key + 1)
59 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
60 
61 	index = strtoul(key, &endptr, 10);
62 	if (!isdigit((int)*key) || endptr != next)
63 		/* Not a list index, so it was assumed */
64 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
65 
66 	if (index >= list->numinuse)
67 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
68 
69 	i = &list->items[index];
70 	if (!*next) {
71 		*item = i;
72 		return GETDNS_RETURN_GOOD;
73 
74 	} else switch (i->dtype) {
75 	case t_dict: return _getdns_dict_find(i->data.dict, next, item);
76 	case t_list: return _getdns_list_find(i->data.list, next, item);
77 	default    : /* Trying to dereference a non list or dict */
78 	             return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
79 	}
80 }
81 
82 
83 getdns_return_t
_getdns_list_remove_name(getdns_list * list,const char * name)84 _getdns_list_remove_name(getdns_list *list, const char *name)
85 {
86 	const char *next, *key = name;
87 	char *endptr;
88 	size_t index;
89 	getdns_item *i;
90 
91 	if (*key == '/') {
92 		if (!(next = strchr(++key, '/')))
93 			next = strchr(key, '\0');
94 	} else
95 		next = strchr(key, '\0');
96 
97 	if (key[0] == '-' && next == key + 1)
98 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
99 
100 	index = strtoul(key, &endptr, 10);
101 	if (!isdigit((int)*key) || endptr != next)
102 		/* Not a list index, so it was assumed */
103 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
104 
105 	if (index >= list->numinuse)
106 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
107 
108 	i = &list->items[index];
109 	if (!*next) {
110 		switch (i->dtype) {
111 		case t_dict   : getdns_dict_destroy(i->data.dict); break;
112 		case t_list   : getdns_list_destroy(i->data.list); break;
113 		case t_bindata: _getdns_bindata_destroy(
114 		                    &list->mf, i->data.bindata);
115 		default       : break;
116 		}
117 		if (index < list->numinuse - 1)
118 			(void) memmove( i, &i[1],
119 			    (list->numinuse - index) * sizeof(getdns_item));
120 		list->numinuse -= 1;
121 		return GETDNS_RETURN_GOOD;
122 
123 	} else switch (i->dtype) {
124 	case t_dict: return getdns_dict_remove_name(i->data.dict, next);
125 	case t_list: return _getdns_list_remove_name(i->data.list, next);
126 	default    : /* Trying to dereference a non list or dict */
127 	             return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
128 	}
129 }
130 
131 
132 getdns_return_t
_getdns_list_find_and_add(getdns_list * list,const char * key,getdns_item ** item)133 _getdns_list_find_and_add(
134     getdns_list *list, const char *key, getdns_item **item)
135 {
136 	const char *next;
137 	char *endptr;
138 	size_t index;
139 	getdns_item *newlist, *i;
140 
141 	if (*key == '/') {
142 		if (!(next = strchr(++key, '/')))
143 			next = strchr(key, '\0');
144 	} else
145 		next = strchr(key, '\0');
146 
147 	if (key[0] == '-' && next == key + 1)
148 		index = list->numinuse;
149 	else {
150 		index = strtoul(key, &endptr, 10);
151 		if (!isdigit((int)*key) || endptr != next)
152 			/* Not a list index, so it was assumed */
153 			return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
154 	}
155 	if (index > list->numinuse)
156 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
157 
158 	if (index == list->numinuse) {
159 		if (list->numalloc <= list->numinuse) {
160 			if (!(newlist = GETDNS_XREALLOC(list->mf, list->items,
161 			    getdns_item, list->numalloc+GETDNS_LIST_BLOCKSZ)))
162 				return GETDNS_RETURN_MEMORY_ERROR;
163 			list->items = newlist;
164 			list->numalloc += GETDNS_LIST_BLOCKSZ;
165 		}
166 		list->numinuse++;
167 		i = &list->items[index];
168 
169 		if (!*next) {
170 			i->dtype = t_int;
171 			i->data.n = 55555333;
172 			*item = i;
173 			return GETDNS_RETURN_GOOD;
174 		}
175 		if ((next[1] == '0' || next[1] == '-') &&
176 		    (next[2] == '/' || next[2] == '\0')) {
177 
178 			i->dtype = t_list;
179 			i->data.list = _getdns_list_create_with_mf(&list->mf);
180 			return _getdns_list_find_and_add(
181 			    i->data.list, next, item);
182 		}
183 		i->dtype = t_dict;
184 		i->data.dict = _getdns_dict_create_with_mf(&list->mf);
185 		return _getdns_dict_find_and_add(i->data.dict, next, item);
186 	}
187 	i = &list->items[index];
188 	if (!*next) {
189 		switch (i->dtype) {
190 		case t_dict   : getdns_dict_destroy(i->data.dict); break;
191 		case t_list   : getdns_list_destroy(i->data.list); break;
192 		case t_bindata: _getdns_bindata_destroy(
193 		                      &list->mf, i->data.bindata); break;
194 		default       : break;
195 		}
196 		i->dtype = t_int;
197 		i->data.n = 33355555;
198 		*item = i;
199 		return GETDNS_RETURN_GOOD;
200 
201 	} else switch (i->dtype) {
202 	case t_dict: return _getdns_dict_find_and_add(i->data.dict,next,item);
203 	case t_list: return _getdns_list_find_and_add(i->data.list,next,item);
204 	default    : /* Trying to dereference a non list or dict */
205 	             return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
206 	}
207 }
208 
209 
210 
211 /*---------------------------------------- getdns_list_get_length */
212 getdns_return_t
getdns_list_get_length(const struct getdns_list * list,size_t * answer)213 getdns_list_get_length(const struct getdns_list * list, size_t * answer)
214 {
215 	if (!list || !answer)
216 		return GETDNS_RETURN_INVALID_PARAMETER;
217 
218 	*answer = list->numinuse;
219 	return GETDNS_RETURN_GOOD;;
220 }				/* getdns_list_get_length */
221 
222 /*---------------------------------------- getdns_list_get_data_type */
223 getdns_return_t
getdns_list_get_data_type(const struct getdns_list * list,size_t index,getdns_data_type * answer)224 getdns_list_get_data_type(const struct getdns_list * list, size_t index,
225 	getdns_data_type * answer)
226 {
227 	if (!list || !answer)
228 		return GETDNS_RETURN_INVALID_PARAMETER;
229 
230 	if (index >= list->numinuse)
231 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
232 
233 	*answer = list->items[index].dtype;
234 	return GETDNS_RETURN_GOOD;
235 }				/* getdns_list_get_data_type */
236 
237 /*---------------------------------------- getdns_list_get_dict */
238 getdns_return_t
getdns_list_get_dict(const struct getdns_list * list,size_t index,struct getdns_dict ** answer)239 getdns_list_get_dict(const struct getdns_list * list, size_t index,
240 	struct getdns_dict ** answer)
241 {
242 	if (!list || !answer)
243 		return GETDNS_RETURN_INVALID_PARAMETER;
244 
245 	if (index >= list->numinuse)
246 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
247 
248 	if (list->items[index].dtype != t_dict)
249 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
250 
251 	*answer = list->items[index].data.dict;
252 	return GETDNS_RETURN_GOOD;
253 }				/* getdns_list_get_dict */
254 
255 /*---------------------------------------- getdns_list_get_list */
256 getdns_return_t
getdns_list_get_list(const struct getdns_list * list,size_t index,struct getdns_list ** answer)257 getdns_list_get_list(const struct getdns_list * list, size_t index,
258 	struct getdns_list ** answer)
259 {
260 	if (!list || !answer)
261 		return GETDNS_RETURN_INVALID_PARAMETER;
262 
263 	if (index >= list->numinuse)
264 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
265 
266 	if (list->items[index].dtype != t_list)
267 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
268 
269 	*answer = list->items[index].data.list;
270 	return GETDNS_RETURN_GOOD;
271 }				/* getdns_list_get_list */
272 
273 /*---------------------------------------- getdns_list_get_bindata */
274 getdns_return_t
getdns_list_get_bindata(const struct getdns_list * list,size_t index,struct getdns_bindata ** answer)275 getdns_list_get_bindata(const struct getdns_list * list, size_t index,
276 	struct getdns_bindata ** answer)
277 {
278 
279 	if (!list || !answer)
280 		return GETDNS_RETURN_INVALID_PARAMETER;
281 
282 	if (index >= list->numinuse)
283 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
284 
285 	if (list->items[index].dtype != t_bindata)
286 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
287 
288 	*answer = list->items[index].data.bindata;
289 	return GETDNS_RETURN_GOOD;
290 }				/* getdns_list_get_bindata */
291 
292 /*---------------------------------------- getdns_list_get_int */
293 getdns_return_t
getdns_list_get_int(const struct getdns_list * list,size_t index,uint32_t * answer)294 getdns_list_get_int(const struct getdns_list * list, size_t index,
295 	uint32_t * answer)
296 {
297 	if (!list || !answer)
298 		return GETDNS_RETURN_INVALID_PARAMETER;
299 
300 	if (index >= list->numinuse)
301 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
302 
303 	if (list->items[index].dtype != t_int)
304 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
305 
306 	*answer = list->items[index].data.n;
307 	return GETDNS_RETURN_GOOD;
308 }				/* getdns_list_get_int */
309 
310 /*---------------------------------------- _getdns_list_copy */
311 getdns_return_t
_getdns_list_copy(const struct getdns_list * srclist,struct getdns_list ** dstlist)312 _getdns_list_copy(const struct getdns_list * srclist,
313 	struct getdns_list ** dstlist)
314 {
315 	size_t i;
316 	getdns_return_t retval;
317 
318 	if (!dstlist)
319 		return GETDNS_RETURN_INVALID_PARAMETER;
320 
321 	if (!srclist) {
322 		*dstlist = NULL;
323 		return GETDNS_RETURN_GOOD;
324 	}
325 	*dstlist = getdns_list_create_with_extended_memory_functions(
326 		srclist->mf.mf_arg,
327 		srclist->mf.mf.ext.malloc,
328 		srclist->mf.mf.ext.realloc,
329 		srclist->mf.mf.ext.free
330 	);
331 	if (!*dstlist)
332 		return GETDNS_RETURN_MEMORY_ERROR;
333 
334 	for (i = 0; i < srclist->numinuse; i++) {
335 		switch (srclist->items[i].dtype) {
336 		case t_int:
337 			retval = _getdns_list_append_int(*dstlist,
338 			    srclist->items[i].data.n);
339 			break;
340 
341 		case t_list:
342 			retval = getdns_list_set_list(*dstlist,
343 			    (*dstlist)->numinuse, srclist->items[i].data.list);
344 			break;
345 
346 		case t_bindata:
347 			retval = _getdns_list_append_const_bindata(*dstlist,
348 			    srclist->items[i].data.bindata->size,
349 			    srclist->items[i].data.bindata->data);
350 			break;
351 
352 		case t_dict:
353 			retval = _getdns_list_append_dict(*dstlist,
354 			    srclist->items[i].data.dict);
355 			break;
356 		default:
357 			retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
358 			break;
359 		}
360 		if (retval != GETDNS_RETURN_GOOD) {
361 			getdns_list_destroy(*dstlist);
362 			*dstlist = NULL;
363 			return retval;
364 		}
365 	}
366 	return GETDNS_RETURN_GOOD;
367 }				/* _getdns_list_copy */
368 
369 struct getdns_list *
getdns_list_create_with_extended_memory_functions(void * userarg,void * (* malloc)(void * userarg,size_t),void * (* realloc)(void * userarg,void *,size_t),void (* free)(void * userarg,void *))370 getdns_list_create_with_extended_memory_functions(
371 	void *userarg,
372 	void *(*malloc)(void *userarg, size_t),
373 	void *(*realloc)(void *userarg, void *, size_t),
374 	void (*free)(void *userarg, void *))
375 {
376 	struct getdns_list *list;
377 	mf_union mf;
378 
379 	if (!malloc || !realloc || !free)
380 		return NULL;
381 
382 	mf.ext.malloc = malloc;
383 	list = userarg == MF_PLAIN
384 		 ? (struct getdns_list *)(*mf.pln.malloc)(
385 			   sizeof(struct getdns_list))
386 		 : (struct getdns_list *)(*mf.ext.malloc)(userarg,
387 			   sizeof(struct getdns_list));
388 	if (!list)
389 		return NULL;
390 
391 	list->mf.mf_arg         = userarg;
392 	list->mf.mf.ext.malloc  = malloc;
393 	list->mf.mf.ext.realloc = realloc;
394 	list->mf.mf.ext.free    = free;
395 
396 	list->numinuse = 0;
397 	if (!(list->items = GETDNS_XMALLOC(
398 	    list->mf, getdns_item, GETDNS_LIST_BLOCKSZ))) {
399 		GETDNS_FREE(list->mf, list);
400 		return NULL;
401 	}
402 	list->numalloc = GETDNS_LIST_BLOCKSZ;
403 	return list;
404 }
405 
406 struct getdns_list *
getdns_list_create_with_memory_functions(void * (* malloc)(size_t),void * (* realloc)(void *,size_t),void (* free)(void *))407 getdns_list_create_with_memory_functions(void *(*malloc)(size_t),
408 	void *(*realloc)(void *, size_t), void (*free)(void *))
409 {
410 	mf_union mf;
411 	mf.pln.malloc = malloc;
412 	mf.pln.realloc = realloc;
413 	mf.pln.free = free;
414 	return getdns_list_create_with_extended_memory_functions(
415 		MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free);
416 }
417 
418 
419 /*-------------------------- getdns_list_create_with_context */
420 struct getdns_list *
getdns_list_create_with_context(const getdns_context * context)421 getdns_list_create_with_context(const getdns_context *context)
422 {
423 	if (context)
424 		return getdns_list_create_with_extended_memory_functions(
425 			context->mf.mf_arg,
426 			context->mf.mf.ext.malloc,
427 			context->mf.mf.ext.realloc,
428 			context->mf.mf.ext.free
429 		);
430 	else
431 		return getdns_list_create_with_memory_functions(malloc,
432 			realloc, free);
433 }			/* getdns_list_create_with_context */
434 
435 /*---------------------------------------- getdns_list_create */
436 struct getdns_list *
getdns_list_create()437 getdns_list_create()
438 {
439 	return getdns_list_create_with_context(NULL);
440 }				/* getdns_list_create */
441 
442 static void
_getdns_list_destroy_item(struct getdns_list * list,size_t index)443 _getdns_list_destroy_item(struct getdns_list *list, size_t index)
444 {
445 	switch (list->items[index].dtype) {
446 	case t_dict:
447 		getdns_dict_destroy(list->items[index].data.dict);
448 		break;
449 
450 	case t_list:
451 		getdns_list_destroy(list->items[index].data.list);
452 		break;
453 
454 	case t_bindata:
455 		_getdns_bindata_destroy(&list->mf,
456 			list->items[index].data.bindata);
457 		break;
458 	default:
459 		break;
460 	}
461 }
462 
463 /*---------------------------------------- getdns_list_destroy */
464 void
getdns_list_destroy(struct getdns_list * list)465 getdns_list_destroy(struct getdns_list *list)
466 {
467 	size_t i;
468 
469 	if (!list)
470 		return;
471 
472 	for (i = 0; i < list->numinuse; i++)
473 		_getdns_list_destroy_item(list, i);
474 
475 	if (list->items)
476 		GETDNS_FREE(list->mf, list->items);
477 	GETDNS_FREE(list->mf, list);
478 }				/* getdns_list_destroy */
479 
480 
481 static getdns_return_t
_getdns_list_request_index(getdns_list * list,size_t index)482 _getdns_list_request_index(getdns_list *list, size_t index)
483 {
484 	getdns_item *newlist;
485 
486 	assert(list);
487 
488 	if (index > list->numinuse)
489 		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
490 
491 	if (index < list->numinuse) {
492 		_getdns_list_destroy_item(list, index);
493 		return GETDNS_RETURN_GOOD;
494 
495 	}
496 	if (list->numalloc > list->numinuse) {
497 		list->numinuse++;
498 		return GETDNS_RETURN_GOOD;
499 	}
500 	if (!(newlist = GETDNS_XREALLOC(list->mf, list->items,
501 	    getdns_item, list->numalloc + GETDNS_LIST_BLOCKSZ)))
502 
503 		return GETDNS_RETURN_MEMORY_ERROR;
504 
505 	list->numinuse++;
506 	list->items = newlist;
507 	list->numalloc += GETDNS_LIST_BLOCKSZ;
508 
509 	return GETDNS_RETURN_GOOD;
510 }
511 
512 /*---------------------------------------- getdns_list_set_dict */
513 static getdns_return_t
_getdns_list_set_this_dict(getdns_list * list,size_t index,getdns_dict * child_dict)514 _getdns_list_set_this_dict(
515     getdns_list *list, size_t index, getdns_dict *child_dict)
516 {
517 	getdns_return_t r;
518 
519 	if (!list || !child_dict)
520 		return GETDNS_RETURN_INVALID_PARAMETER;
521 
522 	if ((r = _getdns_list_request_index(list, index)))
523 		return r;
524 
525 	list->items[index].dtype = t_dict;
526 	list->items[index].data.dict = child_dict;
527 	return GETDNS_RETURN_GOOD;
528 }				/* getdns_list_set_dict */
529 
530 getdns_return_t
getdns_list_set_dict(getdns_list * list,size_t index,const getdns_dict * child_dict)531 getdns_list_set_dict(
532     getdns_list *list, size_t index, const getdns_dict *child_dict)
533 {
534 	getdns_dict *newdict;
535 	getdns_return_t r;
536 
537 	if (!list || !child_dict)
538 		return GETDNS_RETURN_INVALID_PARAMETER;
539 
540 	if ((r = _getdns_dict_copy(child_dict, &newdict)))
541 		return r;
542 
543 	if ((r = _getdns_list_set_this_dict(list, index, newdict)))
544 		getdns_dict_destroy(newdict);
545 
546 	return r;
547 }				/* getdns_list_set_dict */
548 
549 /*---------------------------------------- getdns_list_set_list */
550 getdns_return_t
getdns_list_set_list(getdns_list * list,size_t index,const getdns_list * child_list)551 getdns_list_set_list(
552     getdns_list *list, size_t index, const getdns_list *child_list)
553 {
554 	getdns_list *newlist;
555 	getdns_return_t r;
556 
557 	if (!list || !child_list)
558 		return GETDNS_RETURN_INVALID_PARAMETER;
559 
560 	if ((r = _getdns_list_copy(child_list, &newlist)))
561 		return r;
562 
563 	if ((r = _getdns_list_request_index(list, index))) {
564 		getdns_list_destroy(newlist);
565 		return r;
566 	}
567 	list->items[index].dtype = t_list;
568 	list->items[index].data.list = newlist;
569 	return GETDNS_RETURN_GOOD;
570 }				/* getdns_list_set_list */
571 
572 /*---------------------------------------- getdns_list_set_bindata */
573 static getdns_return_t
_getdns_list_set_const_bindata(getdns_list * list,size_t index,size_t size,const void * data)574 _getdns_list_set_const_bindata(
575     getdns_list *list, size_t index, size_t size, const void *data)
576 {
577 	getdns_bindata *newbindata;
578 	getdns_return_t r;
579 
580 	if (!list)
581 		return GETDNS_RETURN_INVALID_PARAMETER;
582 
583 	if (!(newbindata = _getdns_bindata_copy(&list->mf, size, data)))
584 		return GETDNS_RETURN_MEMORY_ERROR;
585 
586 	if ((r = _getdns_list_request_index(list, index))) {
587 		_getdns_bindata_destroy(&list->mf, newbindata);
588 		return r;
589 	}
590 	list->items[index].dtype = t_bindata;
591 	list->items[index].data.bindata = newbindata;
592 	return GETDNS_RETURN_GOOD;
593 }				/* getdns_list_set_bindata */
594 
595 getdns_return_t
getdns_list_set_bindata(getdns_list * list,size_t index,const getdns_bindata * child_bindata)596 getdns_list_set_bindata(
597     getdns_list *list, size_t index, const getdns_bindata *child_bindata)
598 {
599 	return !child_bindata ? GETDNS_RETURN_INVALID_PARAMETER
600 	    : _getdns_list_set_const_bindata(
601 	    list, index, child_bindata->size, child_bindata->data);
602 }
603 
604 /*----------------------------------------- getdns_list_set_string */
605 static getdns_return_t
getdns_list_set_string(getdns_list * list,size_t index,const char * value)606 getdns_list_set_string(getdns_list *list, size_t index, const char *value)
607 {
608 	getdns_bindata *newbindata;
609 	getdns_return_t r;
610 
611 	if (!list || !value)
612 		return GETDNS_RETURN_INVALID_PARAMETER;
613 
614 	if (!(newbindata = _getdns_bindata_copy(
615 	    &list->mf, strlen(value) + 1, (uint8_t *)value)))
616 		return GETDNS_RETURN_MEMORY_ERROR;
617 
618 	newbindata->size -= 1;
619 
620 	if ((r = _getdns_list_request_index(list, index))) {
621 		_getdns_bindata_destroy(&list->mf, newbindata);
622 		return r;
623 	}
624 	list->items[index].dtype = t_bindata;
625 	list->items[index].data.bindata = newbindata;
626 	return GETDNS_RETURN_GOOD;
627 }				/* getdns_list_set_string */
628 
629 /*---------------------------------------- getdns_list_set_int */
630 getdns_return_t
getdns_list_set_int(getdns_list * list,size_t index,uint32_t child_int)631 getdns_list_set_int(getdns_list * list, size_t index, uint32_t child_int)
632 {
633 	getdns_return_t r;
634 
635 	if (!list)
636 		return GETDNS_RETURN_INVALID_PARAMETER;
637 
638 	if ((r = _getdns_list_request_index(list, index)))
639 		return r;
640 
641 	list->items[index].dtype = t_int;
642 	list->items[index].data.n = child_int;
643 	return GETDNS_RETURN_GOOD;
644 }				/* getdns_list_set_int */
645 
646 getdns_return_t
_getdns_list_append_dict(getdns_list * list,const getdns_dict * child_dict)647 _getdns_list_append_dict(getdns_list *list, const getdns_dict *child_dict)
648 {
649 	if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
650 	return getdns_list_set_dict(list, list->numinuse, child_dict);
651 }
652 getdns_return_t
_getdns_list_append_this_dict(getdns_list * list,getdns_dict * child_dict)653 _getdns_list_append_this_dict(getdns_list *list, getdns_dict *child_dict)
654 {
655 	if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
656 	return _getdns_list_set_this_dict(list, list->numinuse, child_dict);
657 }
658 getdns_return_t
_getdns_list_append_const_bindata(getdns_list * list,size_t size,const void * data)659 _getdns_list_append_const_bindata(
660     getdns_list *list, size_t size, const void *data)
661 {
662 	if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
663 	return _getdns_list_set_const_bindata(list, list->numinuse, size, data);
664 }
665 getdns_return_t
_getdns_list_append_string(getdns_list * list,const char * value)666 _getdns_list_append_string(getdns_list *list, const char *value)
667 {
668 	if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
669 	return getdns_list_set_string(list, list->numinuse, value);
670 }
671 getdns_return_t
_getdns_list_append_int(getdns_list * list,uint32_t child_int)672 _getdns_list_append_int(getdns_list *list, uint32_t child_int)
673 {
674 	if (!list) return GETDNS_RETURN_INVALID_PARAMETER;
675 	return getdns_list_set_int(list, list->numinuse, child_int);
676 }
677 /* getdns_list.c */
678 
679