Created
April 7, 2011 18:32
-
-
Save kulp/1876ecae7fd8886840bc to your computer and use it in GitHub Desktop.
provides macros for compactly representing tree-like structures at compile-time
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file | |
* Provides macros for compactly representing tree-like structures at compile- | |
* time. | |
* | |
* Must be compiled as C99 code to work correctly. With GCC, use -std=c99 or | |
* a superset thereof. | |
* | |
* Currently, traversal must be done manually. Soon, functions will exist to | |
* traverse the tree without understanding its internal structure. | |
* | |
* A tree node looks like this: @verbatim | |
struct _elt_SOME_USER_SPECIFIED_IDENTIFIER { | |
enum statictree_type { | |
STATICTREE_NULL, | |
STATICTREE_BRANCH, | |
STATICTREE_LEAF | |
} type; | |
struct { | |
struct { | |
int len; | |
struct _elt_SOME_USER_SPECIFIED_IDENTIFIER *elts; | |
} branch; | |
USER_SPECIFIED_TYPE leaf; | |
} val; | |
} | |
* @endverbatim | |
* | |
* Example usage: @verbatim | |
#define ST_CURR_ID some_opaque_identifier_linked_to_contained_type | |
ST_MAKE_TYPE(element, char*); | |
element forest[] = { | |
_LEAF("hi"), | |
_BRANCH( | |
_BRANCH( | |
_LEAF(","), | |
_LEAF("world"), | |
), | |
_LEAF("!"), | |
), | |
}; | |
element tree = _BRANCH( | |
_LEAF("where"), | |
_LEAF("is"), | |
_LEAF("Waldo"), | |
_LEAF("?"), | |
); | |
element leaf = _LEAF("alone"); | |
#undef ST_CURR_ID | |
#define ST_CURR_ID a_different_opaque_identifier | |
ST_MAKE_TYPE(my_type_name, struct pair { element a, b; }); | |
my_type_name top = _BRANCH( | |
_LEAF({ leaf, tree }), | |
_LEAF({ tree, forest[1] }), | |
); | |
* @endverbatim | |
*/ | |
#ifndef STATICTREE_H_ | |
#define STATICTREE_H_ | |
/// @todo differentiate internal nodes with and without values ? | |
enum statictree_type { STATICTREE_NULL, STATICTREE_BRANCH, STATICTREE_LEAF }; | |
// define this to save space on root and internal nodes | |
/// @todo make appropriate changes to _BRANCH() to support initialization | |
#if ST_BRANCH_LACKS_VALUE | |
# define _ST_BRANCH_CONTAINER union | |
#else | |
# define _ST_BRANCH_CONTAINER struct | |
#endif | |
/** | |
* Some of the following macros are not really variadic, but uses their apparent | |
* variadicity to permit the use of arguments containing commas (for example, | |
* structures or struct initializers). | |
*/ | |
//------------------------------------------------------------------------------ | |
// Public API | |
//------------------------------------------------------------------------------ | |
#define _LEAF(...) \ | |
ST_LEAF(ST_CURR_ID, __VA_ARGS__) | |
#define _HERE(...) \ | |
_LEAF(__VA_ARGS__) | |
#define _NOTHING \ | |
{ .type = STATICTREE_NULL } | |
#define _BRANCH(...) \ | |
ST_BRANCH(ST_CURR_ID, __VA_ARGS__) | |
#define _BRANCH_V(...) \ | |
ST_BRANCH_V(ST_CURR_ID, __VA_ARGS__) | |
#define ST_MAKE_TYPE(N,...) \ | |
typedef ST_TREE_TYPE(ST_CURR_ID, __VA_ARGS__) N | |
#ifndef countof | |
# define countof(X) (sizeof (X) / sizeof (X)[0]) | |
#endif | |
//------------------------------------------------------------------------------ | |
// Semi-public API | |
//------------------------------------------------------------------------------ | |
#define ST_LEAF(ID, ...) \ | |
{ .type = STATICTREE_LEAF, .val = { .leaf = __VA_ARGS__ } } | |
#define ST_BRANCH(ID, ...) \ | |
{ .type = STATICTREE_BRANCH, \ | |
.val = { .branch = { \ | |
.len = countof(((struct _ST_ELT_NAME(ID)[]) { __VA_ARGS__ })), \ | |
.elts = (struct _ST_ELT_NAME(ID)[]) { __VA_ARGS__ } } } } | |
#define ST_BRANCH_V(ID, ...) \ | |
{ .type = STATICTREE_BRANCH, \ | |
.val = { \ | |
.leaf = ((struct _ST_ELT_NAME(ID)[]) { __VA_ARGS__ })[0].val.leaf, \ | |
.branch = { \ | |
.len = countof(((struct _ST_ELT_NAME(ID)[]) { __VA_ARGS__ })) - 1, \ | |
.elts = &(struct _ST_ELT_NAME(ID)[]) { __VA_ARGS__ }[1] } } } | |
#define ST_TREE_TYPE_REF(ID) \ | |
struct _elt_##ID | |
#define ST_TREE_TYPE(ID,...) \ | |
ST_TREE_TYPE_REF(ID) { \ | |
enum statictree_type type; \ | |
_ST_BRANCH_CONTAINER { \ | |
struct { \ | |
int len; \ | |
struct _ST_ELT_NAME(ID) *elts; \ | |
/* int idx; */ \ | |
} branch; \ | |
__VA_ARGS__ leaf; \ | |
} val; \ | |
/* int visited; */ \ | |
} | |
//------------------------------------------------------------------------------ | |
// Private "API" | |
//------------------------------------------------------------------------------ | |
#define _ST_ELT_NAME(id) \ | |
_elt_##id | |
#endif /* STATICTREE_H_ */ | |
/* vim:set et ts=4 sw=4 syntax=c.doxygen: */ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment