summaryrefslogtreecommitdiffstats
path: root/doc/wiki/Design.Arrays.txt
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/wiki/Design.Arrays.txt109
1 files changed, 109 insertions, 0 deletions
diff --git a/doc/wiki/Design.Arrays.txt b/doc/wiki/Design.Arrays.txt
new file mode 100644
index 0000000..2ecb787
--- /dev/null
+++ b/doc/wiki/Design.Arrays.txt
@@ -0,0 +1,109 @@
+Dynamic Arrays
+==============
+
+'lib/array.h' and 'lib/array-decl.h' describes Dovecot's type-safe dynamic
+arrays. Trying to add wrong typed elements gives a compiler warning.
+
+Declaring
+---------
+
+Arrays can be declared in two ways:
+
+ 1. Directly: 'ARRAY_DEFINE(array_name, array_type);'. For example:
+ 'ARRAY_DEFINE(numbers, int);' or 'ARRAY_DEFINE(foos, struct foo);'
+ 2. Via predefined type: 'ARRAY_DEFINE_TYPE(foo, struct foo); ...
+ ARRAY_TYPE(foo) foos;'
+
+The main reason to define a type for an array is to be able to pass the array
+as a function parameter, like:
+
+---%<-------------------------------------------------------------------------
+void func(ARRAY_TYPE(foo) *foos) { .. }
+---%<-------------------------------------------------------------------------
+
+Trying to do the same with 'ARRAY_DEFINE()' will generate a compiler warning.
+'lib/array-decl.h' defines several commonly used types.
+
+Initializing
+------------
+
+Arrays are typically initialized by calling 'i_array_init()', 'p_array_init()'
+or 't_array_init()' depending on where you want to allocate the memory from.
+Arrays are internally handled as <buffers> [Design.Buffers.txt], so the initial
+size is just multiplied by element size and passed to
+'buffer_create_dynamic()'.
+
+Example:
+
+---%<-------------------------------------------------------------------------
+ARRAY_DEFINE(foo, struct foo *);
+
+i_array_init(&foo, 32); /* initialize array with 32 elements until it needs to
+be grown */
+---%<-------------------------------------------------------------------------
+
+Arrays can be freed with 'array_free()', but this isn't necessary if the memory
+gets freed by other means (i.e. it was allocated from alloconly-pool or data
+stack).
+
+Writing
+-------
+
+ * 'array_append(array, data, count)' is the most common way to add data to
+ arrays
+ * 'array_append_array(dest, src)'
+ * 'array_insert(array, idx, data, count)'
+ * 'array_delete(array, idx, count)'
+ * 'array_idx_set(array, idx, data)' replaces (or adds) data to given index
+ * 'array_idx_clear(array, idx)' clears given index by writing NULs to it
+ * 'array_append_space(array, count)'
+
+Reading
+-------
+
+'array_idx(array, idx)' returns pointer to given index in array. The index must
+already exist, otherwise the call assert-crashes. This call adds extra overhead
+for accessing arrays though, so usually it's better to just get list of all
+elements and access them directly:
+
+---%<-------------------------------------------------------------------------
+data = array_get(&array, &count);
+---%<-------------------------------------------------------------------------
+
+You can also iterate through the whole array easily:
+
+---%<-------------------------------------------------------------------------
+const char *str;
+
+array_foreach(&string_array, str) {
+ /* str changes in each iteration */
+}
+---%<-------------------------------------------------------------------------
+
+There's also 'array_foreach_modifiable()' to get the data without const.
+
+Unsafe Read/Write
+-----------------
+
+Functions below have similar problems to [[Design/Buffer|buffer]'s '*_unsafe()'
+functions. Memory returned by them must not be accessed after calls to other
+'array_*()' modifying functions, because they may reallocate the array
+elsewhere in memory.
+
+ * 'array_append_space(array)'
+ * 'array_insert_space(array, idx)'
+ * 'array_get_modifiable(array, &count)'
+ * 'array_idx_modifiable(array, idx)'
+
+Others
+------
+
+ * 'array_cmp(array1, array2)' compares two arrays
+ * 'array_reverse(array)' reverses all elements in an array
+ * 'array_sort(array, cmp_func)' is a wrapper for 'qsort()' adding also type
+ safety. The parameters in cmp_func should be the same type as the array,
+ instead of 'const void *'.
+ * 'array_bsearch(array, key, cmp_func)' is a wrapper for 'bsearch()' also
+ adding type safety, just like 'array_sort()'.
+
+(This file was created from the wiki on 2019-06-19 12:42)