summaryrefslogtreecommitdiff
path: root/src/util/util.h
blob: db957c68c4af6905317dce386f7537954e1c674f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef KALMIA_UTIL_H
#define KALMIA_UTIL_H

#include <kalmia.h>
#include "xml/xml.h"


/** @brief add a new element to an array
 *
 * @param array  Pointer to the array to expand
 * @param len    Pointer to the current length of the array
 * @param element_size  Size of each element in the array
 *
 * @returns  A pointer to the newly added element of the array, or NULL on failure.
 */
void * kai_expand_array(void **array, size_t *len, size_t element_size);


/** @brief Convert a string to an array of reals
 *
 * This function will always fill the array with `count` elements. If there are not
 * `count` elements to be converted in the string, it will fill the rest of the array
 * with zeroes.
 *
 * @param dest  Array of reals in which to store the results
 * @param str   The string to convert
 * @param count The number of elements to convert
 *
 * @returns  The number of conversions performed. If there were at least `count` elements
 * in the string to convert, this is the same as `count`. If not, it is the number of
 * actual elements present in the string.
 */
size_t kai_text_to_reals(ka_real_t *dest, const char *str, size_t count);


size_t kai_text_to_longs(long *dest, const char *str, size_t count);

size_t kai_text_to_uints(unsigned int *dest, const char *str, size_t count);


void *kai_alloc(size_t size, const char *purpose);


#define KAI_FOR_CHILD_OF_TYPE(parent, child, type) \
for ( \
	child = kai_tag_get_first_child_with_type(parent, type); \
	child != NULL; \
	child = kai_tag_get_next_sibling_with_type(child, type) \
)


#define KAI_FILL_ARRAY_FROM_TAGS(result, dest, count, type, parent, tag_type, read, release) \
do { \
	unsigned int count_internal = 0; \
	bool error = false; \
	struct kai_tag_t *tag_internal; \
	KAI_FOR_CHILD_OF_TYPE(parent, tag_internal, tag_type) { \
		count_internal += 1; \
	} \
	 \
	if (count_internal == 0) { \
		dest = NULL; \
	} \
	else { \
		dest = malloc(count_internal * sizeof(type)); \
		int i = 0; \
		KAI_FOR_CHILD_OF_TYPE(parent, tag_internal, tag_type) { \
			if (error) break; \
			int result_internal = read(dest + i, tag_internal); \
			if (result_internal != 0) { \
				int j; \
				for (j=0; j<i; j++) { \
					release(dest[i]); \
				} \
				free(dest); \
				dest = NULL; \
				result = -1; \
				count = 0; \
				error = true; \
			} \
			i += 1; \
		} \
	} \
 \
 	if (!error) { \
		result = 0; \
		count = count_internal; \
	} \
} while (0)


/* macro to ensure tag type matches what we expect */
#define KAI_CHECK_TAG_TYPE(expected) \
if (strcmp(src->type, expected) != 0) { \
	return -1; \
}

#endif