Sun, 03 Oct 2021 14:06:57 +0200
add some documentation and changes some signatures
src/cx/linked_list.h | file | annotate | diff | comparison | revisions | |
src/cx/list.h | file | annotate | diff | comparison | revisions | |
src/cx/tree.h | file | annotate | diff | comparison | revisions | |
src/linked_list.c | file | annotate | diff | comparison | revisions | |
src/tree.c | file | annotate | diff | comparison | revisions | |
test/test_list.c | file | annotate | diff | comparison | revisions | |
test/test_tree.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/cx/linked_list.h Sun Oct 03 13:07:48 2021 +0200 1.2 +++ b/src/cx/linked_list.h Sun Oct 03 14:06:57 2021 +0200 1.3 @@ -25,6 +25,15 @@ 1.4 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.5 * POSSIBILITY OF SUCH DAMAGE. 1.6 */ 1.7 +/** 1.8 + * \file linked_list.h 1.9 + * \brief Linked list implementation. 1.10 + * \details Also provides several low-level functions for custom linked list implementations. 1.11 + * \author Mike Becker 1.12 + * \author Olaf Wintermann 1.13 + * \version 3.0 1.14 + * \copyright 2-Clause BSD License 1.15 + */ 1.16 1.17 #ifndef UCX_LINKED_LIST_H 1.18 #define UCX_LINKED_LIST_H 1.19 @@ -36,6 +45,13 @@ 1.20 extern "C" { 1.21 #endif 1.22 1.23 +CxList cxLinkedListCreate(CxAllocator allocator, CxListComparator comparator, size_t item_size); 1.24 + 1.25 +void cxLinkedListDestroy(CxList list); 1.26 + 1.27 +size_t cxLinkedListRecalculateSize(CxList list); 1.28 + 1.29 + 1.30 /** 1.31 * Finds the node at a certain index. 1.32 * 1.33 @@ -55,17 +71,35 @@ 1.34 */ 1.35 void *cx_linked_list_at(void *start, size_t start_index, ptrdiff_t loc_advance, size_t index); 1.36 1.37 +/** 1.38 + * Finds the last node in a linked list. 1.39 + * 1.40 + * If a pointer to \p end is provided, the result is just \c *end. 1.41 + * Otherwise, this function starts with the pointer denoted by \c *begin and 1.42 + * traverses the list along a next pointer whose location within the node struct is 1.43 + * denoted by \p loc_next. 1.44 + * 1.45 + * If both \p begin and \p end are \c NULL, an empty list is assumed and this function returns \c NULL. 1.46 + * 1.47 + * @param begin a pointer to the begin node pointer (optional) 1.48 + * @param end a pointer to the end node pointer (optional) 1.49 + * @param loc_next the location of the \c next pointer (only required when \p end is \c NULL) 1.50 + * @return a pointer to the last node or \c NULL if the list is empty 1.51 + */ 1.52 void *cx_linked_list_last(void **begin, void **end, ptrdiff_t loc_next); 1.53 1.54 -int cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node); 1.55 - 1.56 -extern cx_list_class cx_linked_list_class; 1.57 - 1.58 -CxList cxLinkedListCreate(CxAllocator allocator, CxListComparator comparator, size_t item_size); 1.59 - 1.60 -void cxLinkedListDestroy(CxList list); 1.61 - 1.62 -size_t cxLinkedListRecalculateSize(CxList list); 1.63 +/** 1.64 + * Adds a new node to a linked list. 1.65 + * 1.66 + * \remark One of the pointers \p begin and \p end may be \c NULL, but not both. 1.67 + * 1.68 + * @param begin a pointer to the begin node pointer (if your list has one) 1.69 + * @param end a pointer to the end node pointer (if your list has one) 1.70 + * @param loc_prev the location of a \c prev pointer within your node struct (negative if your struct does not have one) 1.71 + * @param loc_next the location of a \c next pointer within your node struct (negative if your struct does not have one) 1.72 + * @param new_node a pointer to the node that shall be appended 1.73 + */ 1.74 +void cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node); 1.75 1.76 #ifdef __cplusplus 1.77 } /* extern "C" */
2.1 --- a/src/cx/list.h Sun Oct 03 13:07:48 2021 +0200 2.2 +++ b/src/cx/list.h Sun Oct 03 14:06:57 2021 +0200 2.3 @@ -25,6 +25,14 @@ 2.4 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2.5 * POSSIBILITY OF SUCH DAMAGE. 2.6 */ 2.7 +/** 2.8 + * \file list.h 2.9 + * \brief Interface for list implementations. 2.10 + * \author Mike Becker 2.11 + * \author Olaf Wintermann 2.12 + * \version 3.0 2.13 + * \copyright 2-Clause BSD License 2.14 + */ 2.15 2.16 #ifndef UCX_LIST_H 2.17 #define UCX_LIST_H
3.1 --- a/src/cx/tree.h Sun Oct 03 13:07:48 2021 +0200 3.2 +++ b/src/cx/tree.h Sun Oct 03 14:06:57 2021 +0200 3.3 @@ -25,6 +25,14 @@ 3.4 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3.5 * POSSIBILITY OF SUCH DAMAGE. 3.6 */ 3.7 +/** 3.8 + * \file tree.h 3.9 + * \brief Interface for tree implementations. 3.10 + * \author Olaf Wintermann 3.11 + * \author Mike Becker 3.12 + * \version 3.0 3.13 + * \copyright 2-Clause BSD License 3.14 + */ 3.15 3.16 #ifndef UCX_TREE_H 3.17 #define UCX_TREE_H 3.18 @@ -36,23 +44,93 @@ 3.19 #ifdef __cplusplus 3.20 extern "C" { 3.21 #endif 3.22 - 3.23 -void* cx_tree_last(void *node, ptrdiff_t loc_next); 3.24 - 3.25 -int cx_tree_add_node(void *node, ptrdiff_t loc_parent, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node); 3.26 3.27 -int cx_tree_add_child_node( 3.28 - void *parent, 3.29 - ptrdiff_t loc_parent, 3.30 - ptrdiff_t loc_prev, 3.31 - ptrdiff_t loc_next, 3.32 - void **children_begin, 3.33 - void **children_end, 3.34 - void *new_node); 3.35 +/** 3.36 + * Adds a sibling to the current tree node. 3.37 + * 3.38 + * In case your struct does not have a \p prev or a \p parent pointer, 3.39 + * specify a negative location. The location of the \p next pointer is 3.40 + * mandatory. 3.41 + * 3.42 + * \attention Do not use this function to add siblings in a tree where the 3.43 + * nodes store a pointer to the last sibling because that would not be modified by this function. 3.44 + * 3.45 + * \remark If yo do not provide a location to the parent pointer, a call to this function is 3.46 + * effectively the same as a call to cx_linked_list_add(). 3.47 + * 3.48 + * @param node a pointer to the node 3.49 + * @param loc_prev the location of a \c prev pointer within your node struct 3.50 + * @param loc_next the location of a \c next pointer within your node struct 3.51 + * @param loc_parent the location of a \c parent pointer within your node struct 3.52 + * @param new_node the new node that shall be added as a sibling 3.53 + */ 3.54 +void cx_tree_add_sibling(void *node, 3.55 + ptrdiff_t loc_prev, ptrdiff_t loc_next, 3.56 + ptrdiff_t loc_parent, 3.57 + void *new_node) 3.58 +__attribute__((__nonnull__)); 3.59 + 3.60 +/** 3.61 + * Adds a node to the list of children. 3.62 + * 3.63 + * \par Example with a full structure 3.64 + * A full tree node structure may look like this: 3.65 + * \code 3.66 + * typedef struct MyTreeNode MyTreeNode; 3.67 + * struct MyTreeNode { 3.68 + * MyTreeNode* parent; 3.69 + * MyTreeNode* first_child; 3.70 + * MyTreeNode* last_child; 3.71 + * MyTreeNode* prev_sibling; 3.72 + * MyTreeNode* next_sibling; 3.73 + * // ...contents... 3.74 + * } 3.75 + * \endcode 3.76 + * Adding a new child to a node with the above structure can be performed with the following call: 3.77 + * \code 3.78 + * MyTreeNode *node, *child; // given 3.79 + * cx_tree_add_child(&node->first_child, &node->last_child, 3.80 + * offsetof(MyTreeNode, prev_sibling), offsetof(MyTreeNode, next_sibling), 3.81 + * child, offsetof(MyTreeNode, parent), node); 3.82 + * \endcode 3.83 + * 3.84 + * \par Example with a reduced structure 3.85 + * The minimal reasonable structure with parent pointer looks like this: 3.86 + * \code 3.87 + * typedef struct MyTreeNode MyTreeNode; 3.88 + * struct MyTreeNode { 3.89 + * MyTreeNode* parent; 3.90 + * MyTreeNode* children; 3.91 + * MyTreeNode* next_sibling; 3.92 + * // ...contents... 3.93 + * } 3.94 + * \endcode 3.95 + * This simplifies the function call to: 3.96 + * \code 3.97 + * MyTreeNode *node, *child; // given 3.98 + * cx_tree_add_child(&node->children, NULL, -1, offsetof(MyTreeNode, next_sibling), 3.99 + * child, offsetof(MyTreeNode, parent), node); 3.100 + * \endcode 3.101 + * 3.102 + * \remark If your tree structure does not possess a parent pointer, a call to this function is 3.103 + * effectively the same as a call to cx_linked_list_add(). 3.104 + * 3.105 + * @param children_begin a pointer to the begin node pointer (if your list has one) 3.106 + * @param children_end a pointer to the end node pointer (if your list has one) 3.107 + * @param loc_prev the location of a \c prev pointer within your node struct 3.108 + * @param loc_next the location of a \c next pointer within your node struct 3.109 + * @param new_node a pointer to the node that shall be appended 3.110 + * @param loc_parent the location of a \c parent pointer within your node struct 3.111 + * @param parent the parent node 3.112 + */ 3.113 +void cx_tree_add_child(void **children_begin, void **children_end, 3.114 + ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node, 3.115 + ptrdiff_t loc_parent, void *parent) 3.116 +__attribute__((__nonnull__ (5))); 3.117 3.118 3.119 #ifdef __cplusplus 3.120 -} 3.121 +} /* extern "C" */ 3.122 #endif 3.123 3.124 #endif /* UCX_TREE_H */
4.1 --- a/src/linked_list.c Sun Oct 03 13:07:48 2021 +0200 4.2 +++ b/src/linked_list.c Sun Oct 03 14:06:57 2021 +0200 4.3 @@ -29,6 +29,7 @@ 4.4 #include "cx/linked_list.h" 4.5 #include <stdint.h> 4.6 #include <string.h> 4.7 +#include <assert.h> 4.8 4.9 /* LOW LEVEL LINKED LIST FUNCTIONS */ 4.10 4.11 @@ -61,16 +62,11 @@ 4.12 } 4.13 } 4.14 4.15 -int cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) { 4.16 +void cx_linked_list_add(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) { 4.17 void *last = cx_linked_list_last(begin, end, loc_next); 4.18 if (last == NULL) { 4.19 - if (begin == NULL) { 4.20 - // no current list and no begin ptr to write to - we don't find something to append to 4.21 - return 1; 4.22 - } else { 4.23 - // start fresh list 4.24 - *begin = new_node; 4.25 - } 4.26 + assert(begin != NULL); 4.27 + *begin = new_node; 4.28 } else { 4.29 // if there is a last node, update its next pointer 4.30 void **next = CX_LL_PTR(last, loc_next); 4.31 @@ -87,8 +83,6 @@ 4.32 void **prev = CX_LL_PTR(new_node, loc_prev); 4.33 *prev = last; 4.34 } 4.35 - 4.36 - return 0; 4.37 } 4.38 4.39 /* HIGH LEVEL LINKED LIST IMPLEMENTATION */
5.1 --- a/src/tree.c Sun Oct 03 13:07:48 2021 +0200 5.2 +++ b/src/tree.c Sun Oct 03 14:06:57 2021 +0200 5.3 @@ -31,7 +31,7 @@ 5.4 5.5 #define CX_TR_PTR(cur, off) ((void**)(((char*)cur)+off)) 5.6 5.7 -void* cx_tree_last(void *node, ptrdiff_t loc_next) { 5.8 +void *cx_tree_last(void *node, ptrdiff_t loc_next) { 5.9 void *last; 5.10 do { 5.11 last = node; 5.12 @@ -39,40 +39,22 @@ 5.13 return last; 5.14 } 5.15 5.16 -int cx_tree_add_node(void *node, ptrdiff_t loc_parent, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node) { 5.17 - void *last = cx_tree_last(node, loc_next); 5.18 - if(!last) 5.19 - return 1; 5.20 - 5.21 - // next pointer must be present 5.22 - *CX_TR_PTR(last, loc_next) = new_node; 5.23 - 5.24 - // optional fields 5.25 - if(loc_parent >= 0) { 5.26 +void cx_tree_add_sibling(void *node, ptrdiff_t loc_prev, ptrdiff_t loc_next, ptrdiff_t loc_parent, void *new_node) { 5.27 + cx_linked_list_add(&node, NULL, loc_prev, loc_next, new_node); 5.28 + 5.29 + // optional parent link 5.30 + if (loc_parent >= 0) { 5.31 *CX_TR_PTR(new_node, loc_parent) = *CX_TR_PTR(node, loc_parent); 5.32 } 5.33 - if(loc_prev >= 0) { 5.34 - *CX_TR_PTR(new_node, loc_prev) = last; 5.35 - } 5.36 - 5.37 - return 0; 5.38 } 5.39 5.40 -int cx_tree_add_child_node( 5.41 - void *parent, 5.42 - ptrdiff_t loc_parent, 5.43 - ptrdiff_t loc_prev, 5.44 - ptrdiff_t loc_next, 5.45 - void **children_begin, 5.46 - void **children_end, 5.47 - void *new_node) 5.48 -{ 5.49 - if(cx_linked_list_add(children_begin, children_end, loc_prev, loc_next, new_node)) { 5.50 - return 1; 5.51 - } 5.52 - // optional field 5.53 - if(loc_parent >= 0) { 5.54 +void cx_tree_add_child(void **children_begin, void **children_end, 5.55 + ptrdiff_t loc_prev, ptrdiff_t loc_next, void *new_node, 5.56 + ptrdiff_t loc_parent, void *parent) { 5.57 + cx_linked_list_add(children_begin, children_end, loc_prev, loc_next, new_node); 5.58 + 5.59 + // optional parent link 5.60 + if (loc_parent >= 0) { 5.61 *CX_TR_PTR(new_node, loc_parent) = parent; 5.62 } 5.63 - return 0; 5.64 }
6.1 --- a/test/test_list.c Sun Oct 03 13:07:48 2021 +0200 6.2 +++ b/test/test_list.c Sun Oct 03 14:06:57 2021 +0200 6.3 @@ -112,16 +112,13 @@ 6.4 ptrdiff_t loc_prev = offsetof(struct node, prev); 6.5 ptrdiff_t loc_next = offsetof(struct node, next); 6.6 6.7 - int ret; 6.8 - ret = cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 6.9 - CU_ASSERT_EQUAL(ret, 0) 6.10 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 6.11 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) 6.12 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) 6.13 CU_ASSERT_PTR_EQUAL(nodes[0].prev, NULL) 6.14 CU_ASSERT_PTR_EQUAL(nodes[0].next, NULL) 6.15 6.16 - ret = cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 6.17 - CU_ASSERT_EQUAL(ret, 0) 6.18 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 6.19 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) 6.20 CU_ASSERT_PTR_EQUAL(end, &nodes[1]) 6.21 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) 6.22 @@ -132,16 +129,14 @@ 6.23 begin = NULL; 6.24 end = NULL; 6.25 6.26 - ret = cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]); 6.27 - CU_ASSERT_EQUAL(ret, 0) 6.28 + cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]); 6.29 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) 6.30 - ret = cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]); 6.31 - CU_ASSERT_EQUAL(ret, 0) 6.32 + cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]); 6.33 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) 6.34 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) 6.35 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) 6.36 6.37 - ret = cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]); 6.38 + cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]); 6.39 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) 6.40 CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) 6.41 6.42 @@ -150,12 +145,10 @@ 6.43 begin = NULL; 6.44 end = NULL; 6.45 6.46 - ret = cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 6.47 - CU_ASSERT_EQUAL(ret, 0) 6.48 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 6.49 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) 6.50 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) 6.51 - ret = cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 6.52 - CU_ASSERT_EQUAL(ret, 0) 6.53 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 6.54 CU_ASSERT_PTR_EQUAL(end, &nodes[1]) 6.55 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) 6.56 CU_ASSERT_PTR_NULL(nodes[1].prev)
7.1 --- a/test/test_tree.c Sun Oct 03 13:07:48 2021 +0200 7.2 +++ b/test/test_tree.c Sun Oct 03 14:06:57 2021 +0200 7.3 @@ -60,15 +60,13 @@ 7.4 memset(&c, 0, sizeof(TestNode)); 7.5 7.6 // test 7.7 - int ret = cx_tree_add_node(&a, offsetof(TestNode, parent), offsetof(TestNode, prev), offsetof(TestNode, next), &b); 7.8 - CU_ASSERT_EQUAL(ret, 0) 7.9 + cx_tree_add_sibling(&a, offsetof(TestNode, prev), offsetof(TestNode, next), offsetof(TestNode, parent), &b); 7.10 CU_ASSERT_PTR_EQUAL(b.parent, &root) 7.11 CU_ASSERT_PTR_EQUAL(b.prev, &a) 7.12 CU_ASSERT_PTR_NULL(b.next) 7.13 CU_ASSERT_PTR_EQUAL(a.next, &b) 7.14 - 7.15 - ret = cx_tree_add_node(&a, -1, -1, offsetof(TestNode, next), &c); 7.16 - CU_ASSERT_EQUAL(ret, 0) 7.17 + 7.18 + cx_tree_add_sibling(&a, -1, offsetof(TestNode, next), -1, &c); 7.19 CU_ASSERT_PTR_NULL(c.parent) 7.20 CU_ASSERT_PTR_NULL(c.prev) 7.21 CU_ASSERT_PTR_NULL(c.next) 7.22 @@ -89,63 +87,57 @@ 7.23 TestNode a1; 7.24 memset(&a1, 0, sizeof(TestNode)); 7.25 7.26 - int ret; 7.27 - 7.28 // test 7.29 - ret = cx_tree_add_child_node( 7.30 - &root, 7.31 - offsetof(TestNode, parent), 7.32 + cx_tree_add_child( 7.33 + (void **) &root.children_begin, 7.34 + (void **) &root.children_end, 7.35 offsetof(TestNode, prev), 7.36 offsetof(TestNode, next), 7.37 - (void**)&root.children_begin, 7.38 - (void**)&root.children_end, 7.39 - &a); 7.40 - CU_ASSERT_EQUAL(ret, 0) 7.41 + &a, 7.42 + offsetof(TestNode, parent), 7.43 + &root); 7.44 CU_ASSERT_PTR_EQUAL(root.children_begin, &a) 7.45 CU_ASSERT_PTR_EQUAL(root.children_end, &a) 7.46 CU_ASSERT_PTR_EQUAL(a.parent, &root) 7.47 CU_ASSERT_PTR_NULL(a.prev) 7.48 CU_ASSERT_PTR_NULL(a.next) 7.49 7.50 - ret = cx_tree_add_child_node( 7.51 - &root, 7.52 - offsetof(TestNode, parent), 7.53 + cx_tree_add_child( 7.54 + (void **) &root.children_begin, 7.55 + (void **) &root.children_end, 7.56 offsetof(TestNode, prev), 7.57 offsetof(TestNode, next), 7.58 - (void**)&root.children_begin, 7.59 - (void**)&root.children_end, 7.60 - &b); 7.61 - CU_ASSERT_EQUAL(ret, 0) 7.62 + &b, 7.63 + offsetof(TestNode, parent), 7.64 + &root); 7.65 CU_ASSERT_PTR_NOT_NULL(root.children_begin) 7.66 CU_ASSERT_PTR_EQUAL(root.children_begin->next, &b) 7.67 CU_ASSERT_PTR_EQUAL(root.children_end, &b) 7.68 CU_ASSERT_PTR_EQUAL(b.parent, &root) 7.69 CU_ASSERT_PTR_EQUAL(b.prev, &a) 7.70 - 7.71 - ret = cx_tree_add_child_node( 7.72 - &root, 7.73 - -1, 7.74 + 7.75 + cx_tree_add_child( 7.76 + (void **) &root.children_begin, 7.77 + NULL, 7.78 -1, 7.79 offsetof(TestNode, next), 7.80 - (void**)&root.children_begin, 7.81 - NULL, 7.82 - &c); 7.83 - CU_ASSERT_EQUAL(ret, 0) 7.84 + &c, 7.85 + -1, 7.86 + &root); 7.87 CU_ASSERT_PTR_EQUAL(root.children_end, &b) // children_end unchanged 7.88 CU_ASSERT_PTR_EQUAL(b.next, &c) 7.89 CU_ASSERT_PTR_NULL(c.prev) 7.90 CU_ASSERT_PTR_NULL(c.next) 7.91 CU_ASSERT_PTR_NULL(c.parent) 7.92 - 7.93 - ret = cx_tree_add_child_node( 7.94 - &a, 7.95 - offsetof(TestNode, parent), 7.96 + 7.97 + cx_tree_add_child( 7.98 + (void **) &a.children_begin, 7.99 + (void **) &a.children_end, 7.100 offsetof(TestNode, prev), 7.101 offsetof(TestNode, next), 7.102 - (void**)&a.children_begin, 7.103 - (void**)&a.children_end, 7.104 - &a1); 7.105 - CU_ASSERT_EQUAL(ret, 0); 7.106 + &a1, 7.107 + offsetof(TestNode, parent), 7.108 + &a); 7.109 CU_ASSERT_PTR_EQUAL(a.children_begin, &a1); 7.110 CU_ASSERT_PTR_EQUAL(a1.parent, &a); 7.111 CU_ASSERT_PTR_NOT_NULL(root.children_begin)