]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/talloc/dalloc.c
dalloc documentation and small fixes
[netatalk.git] / libatalk / talloc / dalloc.c
index 4c06f0656e501275e40d241a976580436f2d9139..99dd7ec08238f98a7163e88d7929b33593268c32 100644 (file)
   GNU General Public License for more details.
 */
 
+/*!
+  @file
+  Typesafe, dynamic object store based on talloc
+  Usage:
+
+  //
+  // Define some terminal types:
+  //
+
+  // A key/value store aka dictionary that supports retrieving elements by key
+  typedef dict_t DALLOC_CTX;
+
+  // An ordered set that can store different objects which can be retrieved by number
+  typedef set_t DALLOC_CTX;
+
+  //
+  // Create an dalloc object and add elementes of different type
+  //
+
+  // Allocate a new talloc context
+  TALLOC_CTX *mem_ctx = talloc_new(NULL);
+  // Create a new dalloc object
+  DALLOC_CTX *d = talloc_zero(mem_ctx, DALLOC_CTX);
+  // Store an int value in the object
+  uint64_t i = 1;
+  dalloc_add_copy(d, &i, uint64_t);
+  // Store a string
+  char *str = dalloc_strdup(d, "hello world");
+  dalloc_add(d, str, char *);
+  // Add a nested object, you later can't fetch this directly
+  DALLOC_CTX *nested = talloc_zero(d, DALLOC_CTX);
+  dalloc_add(d, nested, DALLOC_CTX);
+
+  // Add an int value to the nested object, this can be fetched
+  i = 2;
+  dalloc_add_copy(nested, &i, uint64_t);
+
+  // Add a nested set
+  set_t *set = talloc_zero(nested, set_t);
+  dalloc_add(nested, set, set_t);
+  // Add an int value to the set
+  i = 3;
+  dalloc_add_copy(set, &i, uint64_t);
+
+  // Add a dictionary (key/value store)
+  dict_t *dict = talloc_zero(nested, dict_t);
+  dalloc_add(nested, dict, dict_t);
+
+  // Store a string as key in the dict
+  str = dalloc_strdup(d, "key");
+  dalloc_add(dict, str, char *);
+
+  // Add a value for the key
+  i = 4;
+  dalloc_add_copy(dict, &i, uint64_t);
+
+  //
+  // Fetching value references
+  // You can fetch anything that is not a DALLOC_CTXs, because passing
+  // "DALLOC_CTXs" as type to the functions dalloc_get() and dalloc_value_for_key()
+  // tells the function to step into that object and expect more arguments that specify
+  // which element to fetch.
+  //
+
+  // Get reference to an objects element by position
+  uint64_t *p = dalloc_get(d, "uint64_t", 0);
+  // p now points to the first int with a value of 1
+
+  // Get reference to the "hello world" string
+  str = dalloc_get(d, "char *", 1);
+
+  // You can't fetch a pure DALLOC_CTX
+  nested = dalloc_get(d, "DALLOC_CTX", 2);
+  // But you can do this
+  p = dalloc_get(d, "DALLOC_CTX", 2, "uint64_t", 0);
+  // p now points to the value 2
+
+  // You can fetch types that are typedefd DALLOC_CTXs
+  set = dalloc_get(d, "DALLOC_CTX", 2, "set_t", 1);
+
+  // Fetch int from set, note that you must use DALLOC_CTX as type for the set
+  p = dalloc_get(d, "DALLOC_CTX", 2, "DALLOC_CTX", 1, "uint64_t", 0);
+  // p points to 3
+
+  // Fetch value by key from dictionary
+  p = dalloc_value_for_key(d, "DALLOC_CTX", 2, "DALLOC_CTX", 2, "key");
+  // p now point to 4
+*/
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
@@ -62,6 +156,13 @@ int dalloc_size(DALLOC_CTX *d)
     return talloc_array_length(d->dd_talloc_array);
 }
 
+/*
+ * Get pointer to value from a DALLOC object
+ *
+ * Returns pointer to object from a DALLOC object. Nested object interation
+ * is supported by using the type string "DALLOC_CTX". Any other type string
+ * designates the requested objects type.
+ */
 void *dalloc_get(const DALLOC_CTX *d, ...)
 {
     EC_INIT;
@@ -74,20 +175,28 @@ void *dalloc_get(const DALLOC_CTX *d, ...)
     va_start(args, d);
     type = va_arg(args, const char *);
 
-    if (STRCMP(type, !=, "DALLOC_CTX"))
-        EC_FAIL;
-
     while (STRCMP(type, ==, "DALLOC_CTX")) {
         elem = va_arg(args, int);
-        AFP_ASSERT(elem < talloc_array_length(d->dd_talloc_array));
+        if (elem >= talloc_array_length(d->dd_talloc_array)) {
+            LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d",
+                type, elem >= talloc_array_length(d->dd_talloc_array));
+            EC_FAIL;
+        }
         d = d->dd_talloc_array[elem];
         type = va_arg(args, const char *);
     }
 
     elem = va_arg(args, int);
-    AFP_ASSERT(elem < talloc_array_length(d->dd_talloc_array));
+    if (elem >= talloc_array_length(d->dd_talloc_array)) {
+        LOG(log_error, logtype_sl, "dalloc_get(%s): bound check error: %d >= %d",
+            type, elem,  talloc_array_length(d->dd_talloc_array));
+        EC_FAIL;
+    }
 
-    p = talloc_check_name(d->dd_talloc_array[elem], type);
+    if (!(p = talloc_check_name(d->dd_talloc_array[elem], type))) {
+        LOG(log_error, logtype_sl, "dalloc_get(%d/%s): type mismatch: %s",
+            type, elem, talloc_get_name(d->dd_talloc_array[elem]));
+    }
 
     va_end(args);
 
@@ -110,9 +219,6 @@ void *dalloc_value_for_key(const DALLOC_CTX *d, ...)
     va_start(args, d);
     type = va_arg(args, const char *);
 
-    if (STRCMP(type, !=, "DALLOC_CTX"))
-        EC_FAIL;
-
     while (STRCMP(type, ==, "DALLOC_CTX")) {
         elem = va_arg(args, int);
         AFP_ASSERT(elem < talloc_array_length(d->dd_talloc_array));