aboutsummaryrefslogtreecommitdiff
path: root/src/iterator.c
blob: 6ebc9af79ba7895742f1fc2a09d0b9d28379c230 (plain)
  1. #include <stdlib.h>
  2. #include "config.h"
  3. #include "node.h"
  4. #include "cmark.h"
  5. #include "iterator.h"
  6. cmark_iter*
  7. cmark_iter_new(cmark_node *root)
  8. {
  9. cmark_iter *iter = (cmark_iter*)malloc(sizeof(cmark_iter));
  10. if (iter == NULL) {
  11. return NULL;
  12. } else {
  13. iter->root = root;
  14. iter->current = root;
  15. iter->event_type = CMARK_EVENT_ENTER;
  16. return iter;
  17. }
  18. }
  19. void
  20. cmark_iter_free(cmark_iter *iter)
  21. {
  22. free(iter);
  23. }
  24. cmark_event_type
  25. cmark_iter_next(cmark_iter *iter)
  26. {
  27. return iter->event_type;
  28. }
  29. int S_is_leaf(cmark_node *node)
  30. {
  31. switch (cmark_node_get_type(node)) {
  32. case CMARK_NODE_HTML:
  33. case CMARK_NODE_HRULE:
  34. case CMARK_NODE_CODE_BLOCK:
  35. case CMARK_NODE_TEXT:
  36. case CMARK_NODE_SOFTBREAK:
  37. case CMARK_NODE_LINEBREAK:
  38. case CMARK_NODE_CODE:
  39. case CMARK_NODE_INLINE_HTML:
  40. return 1;
  41. default:
  42. return 0;
  43. }
  44. }
  45. cmark_node*
  46. cmark_iter_get_node(cmark_iter *iter)
  47. {
  48. /* we'll return current */
  49. cmark_node *cur = iter->current;
  50. if (cur == NULL || iter->event_type == CMARK_EVENT_DONE) {
  51. return NULL;
  52. }
  53. /* roll forward to next item, setting both fields */
  54. if (iter->event_type == CMARK_EVENT_ENTER && !S_is_leaf(cur)) {
  55. if (cur->first_child == NULL) {
  56. /* stay on this node but exit */
  57. iter->event_type = CMARK_EVENT_EXIT;
  58. } else {
  59. iter->current = cur->first_child;
  60. iter->event_type = CMARK_EVENT_ENTER;
  61. }
  62. } else if (cur == iter->root) {
  63. /* don't move past root */
  64. iter->event_type = CMARK_EVENT_DONE;
  65. iter->current = NULL;
  66. } else if (cur->next) {
  67. iter->event_type = CMARK_EVENT_ENTER;
  68. iter->current = cur->next;
  69. } else if (cur->parent) {
  70. iter->event_type = CMARK_EVENT_EXIT;
  71. iter->current = cur->parent;
  72. } else {
  73. iter->event_type = CMARK_EVENT_DONE;
  74. iter->current = NULL;
  75. }
  76. return cur;
  77. }