2 Copyright (c) 2012 Frank Lahm <franklahm@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
17 Typesafe, dynamic object store based on talloc
22 // Define some terminal types:
25 // A key/value store aka dictionary that supports retrieving elements by key
26 typedef dict_t DALLOC_CTX;
28 // An ordered set that can store different objects which can be retrieved by number
29 typedef set_t DALLOC_CTX;
32 // Create an dalloc object and add elementes of different type
35 // Allocate a new talloc context
36 TALLOC_CTX *mem_ctx = talloc_new(NULL);
37 // Create a new dalloc object
38 DALLOC_CTX *d = talloc_zero(mem_ctx, DALLOC_CTX);
40 // Store an int value in the object
42 dalloc_add_copy(d, &i, uint64_t);
45 char *str = dalloc_strdup(d, "hello world");
46 dalloc_add(d, str, char *);
48 // Add a nested object, you later can't fetch this directly
49 DALLOC_CTX *nested = talloc_zero(d, DALLOC_CTX);
50 dalloc_add(d, nested, DALLOC_CTX);
52 // Add an int value to the nested object, this can be fetched
54 dalloc_add_copy(nested, &i, uint64_t);
57 set_t *set = talloc_zero(nested, set_t);
58 dalloc_add(nested, set, set_t);
60 // Add an int value to the set
62 dalloc_add_copy(set, &i, uint64_t);
64 // Add a dictionary (key/value store)
65 dict_t *dict = talloc_zero(nested, dict_t);
66 dalloc_add(nested, dict, dict_t);
68 // Store a string as key in the dict
69 str = dalloc_strdup(d, "key");
70 dalloc_add(dict, str, char *);
72 // Add a value for the key
74 dalloc_add_copy(dict, &i, uint64_t);
77 // Fetching value references
78 // You can fetch anything that is not a DALLOC_CTXs, because passing
79 // "DALLOC_CTXs" as type to the functions dalloc_get() and dalloc_value_for_key()
80 // tells the function to step into that object and expect more arguments that specify
81 // which element to fetch.
84 // Get reference to an objects element by position
85 uint64_t *p = dalloc_get(d, "uint64_t", 0);
86 // p now points to the first int with a value of 1
88 // Get reference to the "hello world" string
89 str = dalloc_get(d, "char *", 1);
91 // You can't fetch a pure DALLOC_CTX
92 nested = dalloc_get(d, "DALLOC_CTX", 2);
93 // But you can do this
94 p = dalloc_get(d, "DALLOC_CTX", 2, "uint64_t", 0);
95 // p now points to the value 2
97 // You can fetch types that are typedefd DALLOC_CTXs
98 set = dalloc_get(d, "DALLOC_CTX", 2, "set_t", 1);
100 // Fetch int from set, note that you must use DALLOC_CTX as type for the set
101 p = dalloc_get(d, "DALLOC_CTX", 2, "DALLOC_CTX", 1, "uint64_t", 0);
104 // Fetch value by key from dictionary
105 p = dalloc_value_for_key(d, "DALLOC_CTX", 2, "DALLOC_CTX", 2, "key");
111 #endif /* HAVE_CONFIG_H */
119 #include <inttypes.h>
121 #include <atalk/errchk.h>
122 #include <atalk/util.h>
123 #include <atalk/logger.h>
124 #include <atalk/talloc.h>
125 #include <atalk/bstrlib.h>
126 #include <atalk/dalloc.h>
128 /* Use dalloc_add_copy() macro, not this function */
129 int dalloc_add_talloc_chunk(DALLOC_CTX *dd, void *talloc_chunk, void *obj, size_t size)
132 /* Called from dalloc_add_copy() macro */
133 dd->dd_talloc_array = talloc_realloc(dd,
136 talloc_array_length(dd->dd_talloc_array) + 1);
137 memcpy(talloc_chunk, obj, size);
138 dd->dd_talloc_array[talloc_array_length(dd->dd_talloc_array) - 1] = talloc_chunk;
140 /* Called from dalloc_add() macro */
141 dd->dd_talloc_array = talloc_realloc(dd,
144 talloc_array_length(dd->dd_talloc_array) + 1);
145 dd->dd_talloc_array[talloc_array_length(dd->dd_talloc_array) - 1] = obj;
151 /* Get number of elements, returns 0 if the structure is empty or not initialized */
152 int dalloc_size(DALLOC_CTX *d)
154 if (!d || !d->dd_talloc_array)
156 return talloc_array_length(d->dd_talloc_array);
160 * Get pointer to value from a DALLOC object
162 * Returns pointer to object from a DALLOC object. Nested object interation
163 * is supported by using the type string "DALLOC_CTX". Any other type string
164 * designates the requested objects type.
166 void *dalloc_get(const DALLOC_CTX *d, ...)
173 const char *elemtype;
176 type = va_arg(args, const char *);
178 while (STRCMP(type, ==, "DALLOC_CTX")) {
179 elem = va_arg(args, int);
180 if (elem >= talloc_array_length(d->dd_talloc_array)) {
181 LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d",
182 type, elem >= talloc_array_length(d->dd_talloc_array));
185 d = d->dd_talloc_array[elem];
186 type = va_arg(args, const char *);
189 elem = va_arg(args, int);
190 if (elem >= talloc_array_length(d->dd_talloc_array)) {
191 LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d",
192 type, elem, talloc_array_length(d->dd_talloc_array));
196 if (!(p = talloc_check_name(d->dd_talloc_array[elem], type))) {
197 LOG(log_error, logtype_sl, "dalloc_get(%d/%s): type mismatch: %s",
198 type, elem, talloc_get_name(d->dd_talloc_array[elem]));
209 void *dalloc_value_for_key(const DALLOC_CTX *d, ...)
216 const char *elemtype;
220 type = va_arg(args, const char *);
222 while (STRCMP(type, ==, "DALLOC_CTX")) {
223 elem = va_arg(args, int);
224 AFP_ASSERT(elem < talloc_array_length(d->dd_talloc_array));
225 d = d->dd_talloc_array[elem];
226 type = va_arg(args, const char *);
229 for (elem = 0; elem + 1 < talloc_array_length(d->dd_talloc_array); elem += 2) {
230 if (STRCMP(talloc_get_name(d->dd_talloc_array[elem]), !=, "char *")) {
231 LOG(log_error, logtype_default, "dalloc_value_for_key: key not a string: %s",
232 talloc_get_name(d->dd_talloc_array[elem]));
235 if (STRCMP((char *)d->dd_talloc_array[elem], ==, type)) {
236 p = d->dd_talloc_array[elem + 1];
248 char *dalloc_strdup(const void *ctx, const char *string)
253 EC_NULL( p = talloc_strdup(ctx, string) );
254 talloc_set_name(p, "char *");
265 char *dalloc_strndup(const void *ctx, const char *string, size_t n)
270 EC_NULL( p = talloc_strndup(ctx, string, n) );
271 talloc_set_name(p, "char *");