linked_list.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #ifndef LINKED_LIST_H
  2. #define LINKED_LIST_H 1
  3. #include <metalang99.h>
  4. /* translate variable name to variable in "`ll` namespace" */
  5. #define _LL_NAME(NAME) _ll_##NAME##__
  6. /*
  7. * // define linked list
  8. * LL_DEF(node, int x, float y);
  9. *
  10. * // will be
  11. * typedef struct ... {
  12. * int x;
  13. * float y;
  14. *
  15. * ...
  16. * } node;
  17. *
  18. * // to see actual code use preprocessor `${CC} -P -E | clang-format`
  19. */
  20. #define LL_DEF(NAME, ...) \
  21. ML99_EVAL(ML99_typedef( \
  22. v(NAME), \
  23. ML99_struct(v(_LL_NAME(NAME)), \
  24. ML99_variadicsForEach( \
  25. v(ML99_semicoloned), \
  26. v(__VA_ARGS__, \
  27. struct _LL_NAME(NAME) * _LL_NAME(next)))))) \
  28. ML99_TRAILING_SEMICOLON()
  29. /* get next element */
  30. #define LL_NEXT(HEAD) ((HEAD)->_LL_NAME(next))
  31. /* get last element */
  32. #define LL_LAST(HEAD, LAST) \
  33. do { \
  34. (LAST) = (HEAD); \
  35. while (!!LL_NEXT(LAST)) \
  36. (LAST) = LL_NEXT(LAST); \
  37. } while (0)
  38. #define LL_APPEND(HEAD, NEW) \
  39. do { \
  40. if (!!(HEAD)) { \
  41. __typeof__((HEAD)) _LL_NAME(tmp); \
  42. LL_LAST(HEAD, _LL_NAME(tmp)); \
  43. LL_NEXT(_LL_NAME(tmp)) = (NEW); \
  44. } else { \
  45. (HEAD) = (NEW); \
  46. } \
  47. } while (0)
  48. #define LL_PREPEND(HEAD, NEW) \
  49. do { \
  50. if (!!(HEAD)) LL_NEXT(NEW) = (HEAD); \
  51. (HEAD) = (NEW); \
  52. } while (0)
  53. #define LL_FOREACH(HEAD, ITEM) \
  54. (ITEM) = (HEAD); \
  55. for (__typeof__((HEAD)) _LL_NAME(tmp) = LL_NEXT(ITEM); (ITEM); \
  56. (ITEM) = _LL_NAME(tmp), \
  57. _LL_NAME(tmp) = (ITEM) ? LL_NEXT(ITEM) \
  58. : NULL)
  59. /* get length */
  60. #define LL_LENGTH(HEAD, LEN) \
  61. do { \
  62. (LEN) = 0; \
  63. __typeof__((HEAD)) _LL_NAME(i); \
  64. LL_FOREACH(HEAD, _LL_NAME(i)) { (LEN)++; } \
  65. } while (0)
  66. #define LL_REVERSE(HEAD) \
  67. do { \
  68. __typeof__((HEAD)) _LL_NAME(item) = (HEAD), \
  69. _LL_NAME(prev) = NULL; \
  70. while (!!_LL_NAME(item)) { \
  71. __typeof__((HEAD)) _LL_NAME(next) = \
  72. LL_NEXT(_LL_NAME(item)); \
  73. LL_NEXT(_LL_NAME(item)) = _LL_NAME(prev); \
  74. _LL_NAME(prev) = _LL_NAME(item); \
  75. _LL_NAME(item) = _LL_NAME(next); \
  76. } \
  77. (HEAD) = _LL_NAME(prev); \
  78. } while (0)
  79. #define LL_CONCAT(A, B) \
  80. do { \
  81. if (!!(A)) { \
  82. __typeof__((A)) _LL_NAME(last) = (A); \
  83. LL_LAST((A), _LL_NAME(last)); \
  84. LL_NEXT(_LL_NAME(last)) = (B); \
  85. } else { \
  86. (A) = (B); \
  87. } \
  88. } while (0)
  89. #define LL_SEARCH(HEAD, CMP, QUERY, FOUND) \
  90. do { \
  91. __typeof__((HEAD)) _LL_NAME(i); \
  92. LL_FOREACH((HEAD), _LL_NAME(i)) \
  93. { \
  94. if (!((CMP)(_LL_NAME(i), (QUERY)))) break; \
  95. } \
  96. (FOUND) = _LL_NAME(i); \
  97. } while (0)
  98. #define LL_DELETE(HEAD, ITEM) \
  99. do { \
  100. if ((ITEM) == (HEAD)) { \
  101. (HEAD) = LL_NEXT(HEAD); \
  102. } else { \
  103. __typeof__((HEAD)) _LL_NAME(cur) = (HEAD); \
  104. while (LL_NEXT(_LL_NAME(cur)) \
  105. && LL_NEXT(_LL_NAME(cur)) != (ITEM)) \
  106. _LL_NAME(cur) = LL_NEXT(_LL_NAME(cur)); \
  107. LL_NEXT(_LL_NAME(cur)) = LL_NEXT(ITEM); \
  108. } \
  109. } while (0)
  110. #endif /* LINKED_LIST_H */