toys

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

relptr.h (1997B)


      1 #ifndef RELPTR_H
      2 #define RELPTR_H
      3 
      4 #include <stddef.h>
      5 #include <stdint.h>
      6 
      7 /* relative pointers allow pointers that can be copied around in memory whilst
      8  * still remaning valid. they allow this by forcing the user to specify a "base"
      9  * against which the pointer is calculated, as opposed to using the default
     10  * base of 0 (when using traditional, absolute pointers).
     11  */
     12 
     13 /* we would like our relative pointers to keep using 0 as a "null" value, for
     14  * ergonomics reasons. this makes initialisation of a data structure using
     15  * relative pointers identical to the same structure using absolute pointers.
     16  */
     17 #define RELPTR_NULL (0)
     18 
     19 /* in a naive implementation of relative pointers: `(uintptr_t) base + offset`,
     20  * using a RELPTR_NULL of 0 would result in a "null" pointer that points to
     21  * itself. this might be undesirable, as we might want to represent recursive
     22  * data structures that do indeed point to themselves. so, we "mask" our
     23  * relative pointer before and after conversion from an absolute pointer, to
     24  * set the "null value" to some unlikely to be used value.
     25  */
     26 #define _RELPTR_MASK(ty_relptr) ((ty_relptr) 1 << ((sizeof(ty_relptr) * 8) - 1))
     27 
     28 /* we need to convert between a pointer offset and a relative pointer.
     29  */
     30 #define _RELPTR_ENC(ty_relptr, ptroff) \
     31         ((ty_relptr) ((ptroff) ^ _RELPTR_MASK(ty_relptr)))
     32 
     33 #define _RELPTR_DEC(ty_relptr, relptr) \
     34         ((ty_relptr) ((relptr) ^ _RELPTR_MASK(ty_relptr)))
     35 
     36 /* these are our main helper macros, that convert between a base and an absolute
     37  * pointer to a relative pointer, and between a base and a relative pointer back
     38  * to an absolute pointer.
     39  */
     40 #define RELPTR_ABS2REL(ty_relptr, base, absptr) \
     41         ((absptr) \
     42          ? _RELPTR_ENC(ty_relptr, (char *) absptr - (char *) base) \
     43          : RELPTR_NULL)
     44 
     45 #define RELPTR_REL2ABS(ty_absptr, ty_relptr, base, relptr) \
     46         (((relptr)) \
     47          ? ((ty_absptr) ((char *) base + _RELPTR_DEC(ty_relptr, relptr))) \
     48          : NULL)
     49 
     50 #endif /* RELPTR_H */