provide a default tree node layout, but do not make it mandatory

Sun, 29 Sep 2024 14:38:41 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 29 Sep 2024 14:38:41 +0200
changeset 895
ea1ac0e8225c
parent 894
89cd8dfdc3c2
child 896
7e09c76390c3

provide a default tree node layout, but do not make it mandatory

relates to #166

src/cx/tree.h file | annotate | diff | comparison | revisions
tests/test_tree.c file | annotate | diff | comparison | revisions
--- a/src/cx/tree.h	Sun Sep 29 13:49:33 2024 +0200
+++ b/src/cx/tree.h	Sun Sep 29 14:38:41 2024 +0200
@@ -674,6 +674,8 @@
 
     /**
      * A function to create new nodes.
+     *
+     * Nodes MAY use #cx_tree_node_base_s as base layout, but do not need to.
      */
     cx_tree_node_create_func node_create;
 
@@ -711,9 +713,82 @@
      * The number of currently stored elements.
      */
     size_t size;
+
+    /*
+     * Offset in the node struct for the parent pointer.
+     */
+    ptrdiff_t loc_parent;
+
+    /*
+     * Offset in the node struct for the children linked list.
+     */
+    ptrdiff_t loc_children;
+
+    /*
+     * Optional offset in the node struct for the pointer to the last child
+     * in the linked list (negative if there is no such pointer).
+     */
+    ptrdiff_t loc_last_child;
+
+    /*
+     * Offset in the node struct for the previous sibling pointer.
+     */
+    ptrdiff_t loc_prev;
+
+    /*
+     * Offset in the node struct for the next sibling pointer.
+     */
+    ptrdiff_t loc_next;
 };
 
 /**
+ * Base structure that can be used for tree nodes in a #CxTree.
+ */
+struct cx_tree_node_base_s {
+    /**
+     * Pointer to the parent.
+     */
+    struct cx_tree_node_base_s *parent;
+    /**
+     * Pointer to the first child.
+     */
+    struct cx_tree_node_base_s *children;
+    /**
+     * Pointer to the last child.
+     */
+    struct cx_tree_node_base_s *last_child;
+    /**
+     * Pointer to the previous sibling.
+     */
+    struct cx_tree_node_base_s *prev;
+    /**
+     * Pointer to the next sibling.
+     */
+    struct cx_tree_node_base_s *next;
+};
+
+/**
+ * Macro to roll out the #cx_tree_node_base_s structure with a custom
+ * node type.
+ */
+#define CX_TREE_NODE_BASE(type) \
+    type *parent; \
+    type *children;\
+    type *last_child;\
+    type *prev;\
+    type *next
+
+/**
+ * Macro for specifying the layout of a base node tree.
+ */
+#define cx_tree_node_base_layout \
+    offsetof(struct cx_tree_node_base_s, parent),\
+    offsetof(struct cx_tree_node_base_s, children),\
+    offsetof(struct cx_tree_node_base_s, last_child),\
+    offsetof(struct cx_tree_node_base_s, prev),  \
+    offsetof(struct cx_tree_node_base_s, next)
+
+/**
  * The class definition for arbitrary trees.
  */
 struct cx_tree_class_s {
--- a/tests/test_tree.c	Sun Sep 29 13:49:33 2024 +0200
+++ b/tests/test_tree.c	Sun Sep 29 14:38:41 2024 +0200
@@ -41,11 +41,7 @@
 } tree_node;
 
 typedef struct tree_node2 {
-    struct tree_node2 *parent;
-    struct tree_node2 *next;
-    struct tree_node2 *prev;
-    struct tree_node2 *children;
-    struct tree_node2 *last_child;
+    CX_TREE_NODE_BASE(struct tree_node2);
     int data;
 } tree_node2;
 
@@ -99,7 +95,7 @@
     offsetof(structname, parent), offsetof(structname, children),\
     offsetof(structname, last_child), \
     offsetof(structname, prev), offsetof(structname, next)
-#define tree_node2_layout tree_node_full_layout(tree_node2)
+#define tree_node2_layout cx_tree_node_base_layout
 #define tree_node_file_layout tree_node_full_layout(tree_node_file)
 
 #define tree_children(type) offsetof(type, children), offsetof(type, next)

mercurial