toys

toys.git
git clone git://git.lenczewski.org/toys.git
Log | Files | Refs | README | LICENSE

relptr.c (2723B)


      1 #define HEADER_IMPL
      2 #include "relptr.h"
      3 
      4 #include <string.h>
      5 #include <stdio.h>
      6 
      7 /* defining a struct is guaranteed to introduce a new type, and allows us to
      8  * have a semblance of strong-ish typing for relptrs. this avoids nasty bugs
      9  * where you confuse two different relptr types with the same backing type.
     10  */
     11 typedef struct mylist_relptr {
     12 	int64_t v;
     13 } mylist_relptr_t;
     14 
     15 /* our example type, a singly linked list using relative pointers.
     16  */
     17 struct mylist {
     18 	int a;
     19 	mylist_relptr_t next;
     20 };
     21 
     22 static void
     23 mylist_append(struct mylist *restrict list, struct mylist *restrict node);
     24 
     25 static void
     26 mylist_print(struct mylist const *list);
     27 
     28 /* i like defining helper functions that give me a more compact way of using
     29  * the RELPTR_XXX() macros. this also makes debugging slightly easier as you
     30  * can step into the helper functions and inspect the relative pointer value
     31  * and the absolute pointer value.
     32  */
     33 static inline mylist_relptr_t
     34 mylist_abs2rel(void const *restrict base, struct mylist const *restrict absptr)
     35 {
     36 	mylist_relptr_t res = {
     37 		.v = RELPTR_ABS2REL(__typeof__ (res.v), base, absptr),
     38 	};
     39 
     40 	return res;
     41 }
     42 
     43 static inline struct mylist *
     44 mylist_rel2abs(void const *base, struct mylist_relptr relptr)
     45 {
     46 	void *res = RELPTR_REL2ABS(struct mylist *, __typeof__ (relptr.v), base, relptr.v);
     47 	return res;
     48 }
     49 
     50 /* a basic implementation to demonstrate usage of the relative pointer helpers.
     51  */
     52 static void
     53 mylist_append(struct mylist *restrict list, struct mylist *restrict node)
     54 {
     55 	if (list->next.v != RELPTR_NULL) { /* have next element in list */
     56 		mylist_append(mylist_rel2abs(list, list->next), node);
     57 	} else { /* at end of list */
     58 		list->next = mylist_abs2rel(list, node);
     59 	}
     60 }
     61 
     62 static void
     63 mylist_print(struct mylist const *list)
     64 {
     65 	printf("mylist:\n");
     66 
     67 	size_t i = 0;
     68 	while (list) {
     69 		printf("\t%zu = { %p, { a: %d, next: %p, } }\n",
     70 				i++, list, list->a, mylist_rel2abs(list, list->next));
     71 		list = mylist_rel2abs(list, list->next);
     72 	}
     73 }
     74 
     75 int
     76 main(void)
     77 {
     78 	struct mylist buf[4], buf2[4];
     79 	struct mylist *foo = buf, *bar = buf + 1, *baz = buf + 2;
     80 
     81 	foo->a = 1;
     82 	bar->a = 2;
     83 	baz->a = 3;
     84 
     85 	/* with custom types for the relptr, this step is a little opaque...
     86 	 */
     87 	foo->next.v = bar->next.v = baz->next.v = RELPTR_NULL;
     88 
     89 	printf("before appending to list...\n");
     90 	mylist_print(foo);
     91 
     92 	mylist_append(foo, bar);
     93 	mylist_append(foo, baz);
     94 
     95 	printf("after appending to list...\n");
     96 	mylist_print(foo);
     97 
     98 	/* with absolute pointers, copying the list to a different memory
     99 	 * location would cause the list to break (it would still point to the
    100 	 * old memory location).
    101 	 */
    102 	memcpy(buf2, buf, sizeof buf);
    103 
    104 	printf("after copying to different memory location...\n");
    105 	mylist_print(buf2);
    106 
    107 	return 0;
    108 }