aboutsummaryrefslogtreecommitdiff
path: root/src/node.c
blob: 199dd388218709ccf6274606e4b4dff373d500f2 (plain)
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "config.h"
  4. #include "node.h"
  5. static void
  6. S_node_unlink(cmark_node *node);
  7. cmark_node*
  8. cmark_node_new(cmark_node_type type) {
  9. cmark_node *node = (cmark_node *)calloc(1, sizeof(*node));
  10. node->type = type;
  11. switch (node->type) {
  12. case CMARK_NODE_HEADER:
  13. node->as.header.level = 1;
  14. break;
  15. case CMARK_NODE_LIST: {
  16. cmark_list *list = &node->as.list;
  17. list->list_type = CMARK_BULLET_LIST;
  18. list->start = 1;
  19. list->tight = false;
  20. break;
  21. }
  22. default:
  23. break;
  24. }
  25. return node;
  26. }
  27. // Free a cmark_node list and any children.
  28. static
  29. void S_free_nodes(cmark_node *e)
  30. {
  31. cmark_node *next;
  32. while (e != NULL) {
  33. cmark_strbuf_free(&e->string_content);
  34. switch (e->type){
  35. case NODE_CODE_BLOCK:
  36. cmark_chunk_free(&e->as.code.info);
  37. cmark_chunk_free(&e->as.code.literal);
  38. break;
  39. case NODE_TEXT:
  40. case NODE_INLINE_HTML:
  41. case NODE_CODE:
  42. case NODE_HTML:
  43. cmark_chunk_free(&e->as.literal);
  44. break;
  45. case NODE_LINK:
  46. case NODE_IMAGE:
  47. free(e->as.link.url);
  48. free(e->as.link.title);
  49. break;
  50. default:
  51. break;
  52. }
  53. if (e->last_child) {
  54. // Splice children into list
  55. e->last_child->next = e->next;
  56. e->next = e->first_child;
  57. }
  58. next = e->next;
  59. free(e);
  60. e = next;
  61. }
  62. }
  63. void
  64. cmark_node_free(cmark_node *node) {
  65. S_node_unlink(node);
  66. node->next = NULL;
  67. S_free_nodes(node);
  68. }
  69. cmark_node_type
  70. cmark_node_get_type(cmark_node *node)
  71. {
  72. if (node == NULL) {
  73. return CMARK_NODE_NONE;
  74. } else {
  75. return node->type;
  76. }
  77. }
  78. const char*
  79. cmark_node_get_type_string(cmark_node *node)
  80. {
  81. if (node == NULL) {
  82. return "NONE";
  83. }
  84. switch (node->type) {
  85. case CMARK_NODE_NONE: return "none";
  86. case CMARK_NODE_DOCUMENT: return "document";
  87. case CMARK_NODE_BLOCK_QUOTE: return "block_quote";
  88. case CMARK_NODE_LIST: return "list";
  89. case CMARK_NODE_ITEM: return "item";
  90. case CMARK_NODE_CODE_BLOCK: return "code_block";
  91. case CMARK_NODE_HTML: return "html";
  92. case CMARK_NODE_PARAGRAPH: return "paragraph";
  93. case CMARK_NODE_HEADER: return "header";
  94. case CMARK_NODE_HRULE: return "hrule";
  95. case CMARK_NODE_TEXT: return "text";
  96. case CMARK_NODE_SOFTBREAK: return "softbreak";
  97. case CMARK_NODE_LINEBREAK: return "linebreak";
  98. case CMARK_NODE_CODE: return "code";
  99. case CMARK_NODE_INLINE_HTML: return "inline_html";
  100. case CMARK_NODE_EMPH: return "emph";
  101. case CMARK_NODE_STRONG: return "strong";
  102. case CMARK_NODE_LINK: return "link";
  103. case CMARK_NODE_IMAGE: return "image";
  104. }
  105. return "<unknown>";
  106. }
  107. cmark_node*
  108. cmark_node_next(cmark_node *node)
  109. {
  110. if (node == NULL) {
  111. return NULL;
  112. } else {
  113. return node->next;
  114. }
  115. }
  116. cmark_node*
  117. cmark_node_previous(cmark_node *node)
  118. {
  119. if (node == NULL) {
  120. return NULL;
  121. } else {
  122. return node->prev;
  123. }
  124. }
  125. cmark_node*
  126. cmark_node_parent(cmark_node *node)
  127. {
  128. if (node == NULL) {
  129. return NULL;
  130. } else {
  131. return node->parent;
  132. }
  133. }
  134. cmark_node*
  135. cmark_node_first_child(cmark_node *node)
  136. {
  137. if (node == NULL) {
  138. return NULL;
  139. } else {
  140. return node->first_child;
  141. }
  142. }
  143. cmark_node*
  144. cmark_node_last_child(cmark_node *node)
  145. {
  146. if (node == NULL) {
  147. return NULL;
  148. } else {
  149. return node->last_child;
  150. }
  151. }
  152. static char*
  153. S_strdup(const char *str) {
  154. size_t size = strlen(str) + 1;
  155. char *dup = (char *)malloc(size);
  156. memcpy(dup, str, size);
  157. return dup;
  158. }
  159. const char*
  160. cmark_node_get_literal(cmark_node *node) {
  161. if (node == NULL) {
  162. return NULL;
  163. }
  164. switch (node->type) {
  165. case NODE_HTML:
  166. case NODE_TEXT:
  167. case NODE_INLINE_HTML:
  168. case NODE_CODE:
  169. return cmark_chunk_to_cstr(&node->as.literal);
  170. case NODE_CODE_BLOCK:
  171. return cmark_chunk_to_cstr(&node->as.code.literal);
  172. default:
  173. break;
  174. }
  175. return NULL;
  176. }
  177. int
  178. cmark_node_set_literal(cmark_node *node, const char *content) {
  179. if (node == NULL) {
  180. return 0;
  181. }
  182. switch (node->type) {
  183. case NODE_HTML:
  184. case NODE_TEXT:
  185. case NODE_INLINE_HTML:
  186. case NODE_CODE:
  187. cmark_chunk_set_cstr(&node->as.literal, content);
  188. return 1;
  189. case NODE_CODE_BLOCK:
  190. cmark_chunk_set_cstr(&node->as.code.literal, content);
  191. return 1;
  192. default:
  193. break;
  194. }
  195. return 0;
  196. }
  197. int
  198. cmark_node_get_header_level(cmark_node *node) {
  199. if (node == NULL) {
  200. return 0;
  201. }
  202. switch (node->type) {
  203. case CMARK_NODE_HEADER:
  204. return node->as.header.level;
  205. default:
  206. break;
  207. }
  208. return 0;
  209. }
  210. int
  211. cmark_node_set_header_level(cmark_node *node, int level) {
  212. if (node == NULL || level < 1 || level > 6) {
  213. return 0;
  214. }
  215. switch (node->type) {
  216. case CMARK_NODE_HEADER:
  217. node->as.header.level = level;
  218. return 1;
  219. default:
  220. break;
  221. }
  222. return 0;
  223. }
  224. cmark_list_type
  225. cmark_node_get_list_type(cmark_node *node) {
  226. if (node == NULL) {
  227. return CMARK_NO_LIST;
  228. }
  229. if (node->type == CMARK_NODE_LIST) {
  230. return node->as.list.list_type;
  231. }
  232. else {
  233. return CMARK_NO_LIST;
  234. }
  235. }
  236. int
  237. cmark_node_set_list_type(cmark_node *node, cmark_list_type type) {
  238. if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
  239. return 0;
  240. }
  241. if (node == NULL) {
  242. return 0;
  243. }
  244. if (node->type == CMARK_NODE_LIST) {
  245. node->as.list.list_type = type;
  246. return 1;
  247. }
  248. else {
  249. return 0;
  250. }
  251. }
  252. cmark_delim_type
  253. cmark_node_get_list_delim(cmark_node *node) {
  254. if (node == NULL) {
  255. return CMARK_NO_DELIM;
  256. }
  257. if (node->type == CMARK_NODE_LIST) {
  258. return node->as.list.delimiter;
  259. }
  260. else {
  261. return CMARK_NO_DELIM;
  262. }
  263. }
  264. int
  265. cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) {
  266. if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
  267. return 0;
  268. }
  269. if (node == NULL) {
  270. return 0;
  271. }
  272. if (node->type == CMARK_NODE_LIST) {
  273. node->as.list.delimiter = delim;
  274. return 1;
  275. }
  276. else {
  277. return 0;
  278. }
  279. }
  280. int
  281. cmark_node_get_list_start(cmark_node *node) {
  282. if (node == NULL) {
  283. return 0;
  284. }
  285. if (node->type == CMARK_NODE_LIST) {
  286. return node->as.list.start;
  287. }
  288. else {
  289. return 0;
  290. }
  291. }
  292. int
  293. cmark_node_set_list_start(cmark_node *node, int start) {
  294. if (node == NULL || start < 0) {
  295. return 0;
  296. }
  297. if (node->type == CMARK_NODE_LIST) {
  298. node->as.list.start = start;
  299. return 1;
  300. }
  301. else {
  302. return 0;
  303. }
  304. }
  305. int
  306. cmark_node_get_list_tight(cmark_node *node) {
  307. if (node == NULL) {
  308. return 0;
  309. }
  310. if (node->type == CMARK_NODE_LIST) {
  311. return node->as.list.tight;
  312. }
  313. else {
  314. return 0;
  315. }
  316. }
  317. int
  318. cmark_node_set_list_tight(cmark_node *node, int tight) {
  319. if (node == NULL) {
  320. return 0;
  321. }
  322. if (node->type == CMARK_NODE_LIST) {
  323. node->as.list.tight = tight;
  324. return 1;
  325. }
  326. else {
  327. return 0;
  328. }
  329. }
  330. const char*
  331. cmark_node_get_fence_info(cmark_node *node) {
  332. if (node == NULL) {
  333. return NULL;
  334. }
  335. if (node->type == NODE_CODE_BLOCK) {
  336. return cmark_chunk_to_cstr(&node->as.code.info);
  337. }
  338. else {
  339. return NULL;
  340. }
  341. }
  342. int
  343. cmark_node_set_fence_info(cmark_node *node, const char *info) {
  344. if (node == NULL) {
  345. return 0;
  346. }
  347. if (node->type == NODE_CODE_BLOCK) {
  348. cmark_chunk_set_cstr(&node->as.code.info, info);
  349. return 1;
  350. }
  351. else {
  352. return 0;
  353. }
  354. }
  355. const char*
  356. cmark_node_get_url(cmark_node *node) {
  357. if (node == NULL) {
  358. return NULL;
  359. }
  360. switch (node->type) {
  361. case NODE_LINK:
  362. case NODE_IMAGE:
  363. return (char *)node->as.link.url;
  364. default:
  365. break;
  366. }
  367. return NULL;
  368. }
  369. int
  370. cmark_node_set_url(cmark_node *node, const char *url) {
  371. if (node == NULL) {
  372. return 0;
  373. }
  374. switch (node->type) {
  375. case NODE_LINK:
  376. case NODE_IMAGE:
  377. free(node->as.link.url);
  378. node->as.link.url = (unsigned char *)S_strdup(url);
  379. return 1;
  380. default:
  381. break;
  382. }
  383. return 0;
  384. }
  385. const char*
  386. cmark_node_get_title(cmark_node *node) {
  387. if (node == NULL) {
  388. return NULL;
  389. }
  390. switch (node->type) {
  391. case NODE_LINK:
  392. case NODE_IMAGE:
  393. return (char *)node->as.link.title;
  394. default:
  395. break;
  396. }
  397. return NULL;
  398. }
  399. int
  400. cmark_node_set_title(cmark_node *node, const char *title) {
  401. if (node == NULL) {
  402. return 0;
  403. }
  404. switch (node->type) {
  405. case NODE_LINK:
  406. case NODE_IMAGE:
  407. free(node->as.link.title);
  408. node->as.link.title = (unsigned char *)S_strdup(title);
  409. return 1;
  410. default:
  411. break;
  412. }
  413. return 0;
  414. }
  415. int
  416. cmark_node_get_start_line(cmark_node *node) {
  417. if (node == NULL) {
  418. return 0;
  419. }
  420. return node->start_line;
  421. }
  422. int
  423. cmark_node_get_start_column(cmark_node *node) {
  424. if (node == NULL) {
  425. return 0;
  426. }
  427. return node->start_column;
  428. }
  429. int
  430. cmark_node_get_end_line(cmark_node *node) {
  431. if (node == NULL) {
  432. return 0;
  433. }
  434. return node->end_line;
  435. }
  436. int
  437. cmark_node_get_end_column(cmark_node *node) {
  438. if (node == NULL) {
  439. return 0;
  440. }
  441. return node->end_column;
  442. }
  443. static inline bool
  444. S_is_block(cmark_node *node) {
  445. if (node == NULL) {
  446. return false;
  447. }
  448. return node->type >= CMARK_NODE_FIRST_BLOCK
  449. && node->type <= CMARK_NODE_LAST_BLOCK;
  450. }
  451. static inline bool
  452. S_is_inline(cmark_node *node) {
  453. if (node == NULL) {
  454. return false;
  455. }
  456. return node->type >= CMARK_NODE_FIRST_INLINE
  457. && node->type <= CMARK_NODE_LAST_INLINE;
  458. }
  459. static bool
  460. S_can_contain(cmark_node *node, cmark_node *child)
  461. {
  462. cmark_node *cur;
  463. if (node == NULL || child == NULL) {
  464. return false;
  465. }
  466. // Verify that child is not an ancestor of node or equal to node.
  467. cur = node;
  468. do {
  469. if (cur == child) {
  470. return false;
  471. }
  472. cur = cur->parent;
  473. } while (cur != NULL);
  474. if (child->type == CMARK_NODE_DOCUMENT) {
  475. return false;
  476. }
  477. switch (node->type) {
  478. case CMARK_NODE_DOCUMENT:
  479. case CMARK_NODE_BLOCK_QUOTE:
  480. case CMARK_NODE_ITEM:
  481. return S_is_block(child)
  482. && child->type != CMARK_NODE_ITEM;
  483. case CMARK_NODE_LIST:
  484. return child->type == CMARK_NODE_ITEM;
  485. case CMARK_NODE_PARAGRAPH:
  486. case CMARK_NODE_HEADER:
  487. case CMARK_NODE_EMPH:
  488. case CMARK_NODE_STRONG:
  489. case CMARK_NODE_LINK:
  490. case CMARK_NODE_IMAGE:
  491. return S_is_inline(child);
  492. default:
  493. break;
  494. }
  495. return false;
  496. }
  497. // Unlink a node without adjusting its next, prev, and parent pointers.
  498. static void
  499. S_node_unlink(cmark_node *node)
  500. {
  501. if (node == NULL) {
  502. return;
  503. }
  504. if (node->prev) {
  505. node->prev->next = node->next;
  506. }
  507. if (node->next) {
  508. node->next->prev = node->prev;
  509. }
  510. // Adjust first_child and last_child of parent.
  511. cmark_node *parent = node->parent;
  512. if (parent) {
  513. if (parent->first_child == node) {
  514. parent->first_child = node->next;
  515. }
  516. if (parent->last_child == node) {
  517. parent->last_child = node->prev;
  518. }
  519. }
  520. }
  521. void
  522. cmark_node_unlink(cmark_node *node) {
  523. S_node_unlink(node);
  524. node->next = NULL;
  525. node->prev = NULL;
  526. node->parent = NULL;
  527. }
  528. int
  529. cmark_node_insert_before(cmark_node *node, cmark_node *sibling)
  530. {
  531. if (node == NULL || sibling == NULL) {
  532. return 0;
  533. }
  534. if (!node->parent || !S_can_contain(node->parent, sibling)) {
  535. return 0;
  536. }
  537. S_node_unlink(sibling);
  538. cmark_node *old_prev = node->prev;
  539. // Insert 'sibling' between 'old_prev' and 'node'.
  540. if (old_prev) {
  541. old_prev->next = sibling;
  542. }
  543. sibling->prev = old_prev;
  544. sibling->next = node;
  545. node->prev = sibling;
  546. // Set new parent.
  547. cmark_node *parent = node->parent;
  548. sibling->parent = parent;
  549. // Adjust first_child of parent if inserted as first child.
  550. if (parent && !old_prev) {
  551. parent->first_child = sibling;
  552. }
  553. return 1;
  554. }
  555. int
  556. cmark_node_insert_after(cmark_node *node, cmark_node *sibling)
  557. {
  558. if (node == NULL || sibling == NULL) {
  559. return 0;
  560. }
  561. if (!node->parent || !S_can_contain(node->parent, sibling)) {
  562. return 0;
  563. }
  564. S_node_unlink(sibling);
  565. cmark_node *old_next = node->next;
  566. // Insert 'sibling' between 'node' and 'old_next'.
  567. if (old_next) {
  568. old_next->prev = sibling;
  569. }
  570. sibling->next = old_next;
  571. sibling->prev = node;
  572. node->next = sibling;
  573. // Set new parent.
  574. cmark_node *parent = node->parent;
  575. sibling->parent = parent;
  576. // Adjust last_child of parent if inserted as last child.
  577. if (parent && !old_next) {
  578. parent->last_child = sibling;
  579. }
  580. return 1;
  581. }
  582. int
  583. cmark_node_prepend_child(cmark_node *node, cmark_node *child)
  584. {
  585. if (!S_can_contain(node, child)) {
  586. return 0;
  587. }
  588. S_node_unlink(child);
  589. cmark_node *old_first_child = node->first_child;
  590. child->next = old_first_child;
  591. child->prev = NULL;
  592. child->parent = node;
  593. node->first_child = child;
  594. if (old_first_child) {
  595. old_first_child->prev = child;
  596. }
  597. else {
  598. // Also set last_child if node previously had no children.
  599. node->last_child = child;
  600. }
  601. return 1;
  602. }
  603. int
  604. cmark_node_append_child(cmark_node *node, cmark_node *child)
  605. {
  606. if (!S_can_contain(node, child)) {
  607. return 0;
  608. }
  609. S_node_unlink(child);
  610. cmark_node *old_last_child = node->last_child;
  611. child->next = NULL;
  612. child->prev = old_last_child;
  613. child->parent = node;
  614. node->last_child = child;
  615. if (old_last_child) {
  616. old_last_child->next = child;
  617. }
  618. else {
  619. // Also set first_child if node previously had no children.
  620. node->first_child = child;
  621. }
  622. return 1;
  623. }
  624. static void
  625. S_print_error(FILE *out, cmark_node *node, const char *elem)
  626. {
  627. if (out == NULL) {
  628. return;
  629. }
  630. fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
  631. cmark_node_get_type_string(node), node->start_line,
  632. node->start_column);
  633. }
  634. int
  635. cmark_node_check(cmark_node *node, FILE *out)
  636. {
  637. cmark_node *cur;
  638. int errors = 0;
  639. if (!node) {
  640. return 0;
  641. }
  642. cur = node;
  643. while (true) {
  644. if (cur->first_child) {
  645. if (cur->first_child->prev != NULL) {
  646. S_print_error(out, cur->first_child, "prev");
  647. cur->first_child->prev = NULL;
  648. ++errors;
  649. }
  650. if (cur->first_child->parent != cur) {
  651. S_print_error(out, cur->first_child, "parent");
  652. cur->first_child->parent = cur;
  653. ++errors;
  654. }
  655. cur = cur->first_child;
  656. continue;
  657. }
  658. next_sibling:
  659. if (cur == node) {
  660. break;
  661. }
  662. if (cur->next) {
  663. if (cur->next->prev != cur) {
  664. S_print_error(out, cur->next, "prev");
  665. cur->next->prev = cur;
  666. ++errors;
  667. }
  668. if (cur->next->parent != cur->parent) {
  669. S_print_error(out, cur->next, "parent");
  670. cur->next->parent = cur->parent;
  671. ++errors;
  672. }
  673. cur = cur->next;
  674. continue;
  675. }
  676. if (cur->parent->last_child != cur) {
  677. S_print_error(out, cur->parent, "last_child");
  678. cur->parent->last_child = cur;
  679. ++errors;
  680. }
  681. cur = cur->parent;
  682. goto next_sibling;
  683. }
  684. return errors;
  685. }