Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include <inttypes.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6. #include <hubbub/hubbub.h>
  7. #include <hubbub/parser.h>
  8. #include <hubbub/tree.h>
  9.  
  10. #include "utils/utils.h"
  11.  
  12. #include "testutils.h"
  13.  
  14. #define NODE_REF_CHUNK 8192
  15. static uint16_t *node_ref;
  16. static uintptr_t node_ref_alloc;
  17. static uintptr_t node_counter;
  18.  
  19. #define GROW_REF                                                        \
  20.         if (node_counter >= node_ref_alloc) {                           \
  21.                 uint16_t *temp = realloc(node_ref,                      \
  22.                                 (node_ref_alloc + NODE_REF_CHUNK) *     \
  23.                                 sizeof(uint16_t));                      \
  24.                 if (temp == NULL) {                                     \
  25.                         printf("FAIL - no memory\n");                   \
  26.                         exit(1);                                        \
  27.                 }                                                       \
  28.                 node_ref = temp;                                        \
  29.                 node_ref_alloc += NODE_REF_CHUNK;                       \
  30.         }
  31.  
  32. static hubbub_error create_comment(void *ctx, const hubbub_string *data,
  33.                 void **result);
  34. static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype,
  35.                 void **result);
  36. static hubbub_error create_element(void *ctx, const hubbub_tag *tag,
  37.                 void **result);
  38. static hubbub_error create_text(void *ctx, const hubbub_string *data,
  39.                 void **result);
  40. static hubbub_error ref_node(void *ctx, void *node);
  41. static hubbub_error unref_node(void *ctx, void *node);
  42. static hubbub_error append_child(void *ctx, void *parent, void *child,
  43.                 void **result);
  44. static hubbub_error insert_before(void *ctx, void *parent, void *child,
  45.                 void *ref_child, void **result);
  46. static hubbub_error remove_child(void *ctx, void *parent, void *child,
  47.                 void **result);
  48. static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result);
  49. static hubbub_error reparent_children(void *ctx, void *node, void *new_parent);
  50. static hubbub_error get_parent(void *ctx, void *node, bool element_only,
  51.                 void **result);
  52. static hubbub_error has_children(void *ctx, void *node, bool *result);
  53. static hubbub_error form_associate(void *ctx, void *form, void *node);
  54. static hubbub_error add_attributes(void *ctx, void *node,
  55.                 const hubbub_attribute *attributes, uint32_t n_attributes);
  56. static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode);
  57. static hubbub_error complete_script(void *ctx, void *script);
  58.  
  59. static hubbub_tree_handler tree_handler = {
  60.         create_comment,
  61.         create_doctype,
  62.         create_element,
  63.         create_text,
  64.         ref_node,
  65.         unref_node,
  66.         append_child,
  67.         insert_before,
  68.         remove_child,
  69.         clone_node,
  70.         reparent_children,
  71.         get_parent,
  72.         has_children,
  73.         form_associate,
  74.         add_attributes,
  75.         set_quirks_mode,
  76.         NULL,
  77.         complete_script,
  78.         NULL
  79. };
  80.  
  81. static void *myrealloc(void *ptr, size_t len, void *pw)
  82. {
  83.         UNUSED(pw);
  84.  
  85.         return realloc(ptr, len);
  86. }
  87.  
  88. static int run_test(int argc, char **argv, unsigned int CHUNK_SIZE)
  89. {
  90.         hubbub_parser *parser;
  91.         hubbub_parser_optparams params;
  92.         FILE *fp;
  93.         size_t len, origlen;
  94.         uint8_t *buf = alloca(CHUNK_SIZE);
  95.         const char *charset;
  96.         hubbub_charset_source cssource;
  97.         bool passed = true;
  98.         uintptr_t n;
  99.  
  100.         UNUSED(argc);
  101.  
  102.         node_ref = calloc(NODE_REF_CHUNK, sizeof(uint16_t));
  103.         if (node_ref == NULL) {
  104.                 printf("Failed allocating node_ref\n");
  105.                 return 1;
  106.         }
  107.         node_ref_alloc = NODE_REF_CHUNK;
  108.  
  109.         assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) ==
  110.                         HUBBUB_OK);
  111.  
  112.         params.tree_handler = &tree_handler;
  113.         assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER,
  114.                         &params) == HUBBUB_OK);
  115.  
  116.         params.document_node = (void *) ++node_counter;
  117.         ref_node(NULL, (void *) node_counter);
  118.         assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE,
  119.                         &params) == HUBBUB_OK);
  120.  
  121.         fp = fopen(argv[1], "rb");
  122.         if (fp == NULL) {
  123.                 printf("Failed opening %s\n", argv[1]);
  124.                 return 1;
  125.         }
  126.  
  127.         fseek(fp, 0, SEEK_END);
  128.         origlen = len = ftell(fp);
  129.         fseek(fp, 0, SEEK_SET);
  130.  
  131.         while (len > 0) {
  132.                 ssize_t bytes_read = fread(buf, 1, CHUNK_SIZE, fp);
  133.                
  134.                 if (bytes_read < 1)
  135.                         break;
  136.                
  137.                 assert(hubbub_parser_parse_chunk(parser,
  138.                                 buf, bytes_read) == HUBBUB_OK);
  139.  
  140.                 len -= bytes_read;
  141.         }
  142.        
  143.         assert(len == 0);
  144.        
  145.         fclose(fp);
  146.  
  147.         charset = hubbub_parser_read_charset(parser, &cssource);
  148.  
  149.         printf("Charset: %s (from %d)\n", charset, cssource);
  150.  
  151.         hubbub_parser_destroy(parser);
  152.  
  153.         /* Ensure that all nodes have been released by the treebuilder */
  154.         for (n = 1; n <= node_counter; n++) {
  155.                 if (node_ref[n] != 0) {
  156.                         printf("%" PRIuPTR " still referenced (=%u)\n", n, node_ref[n]);
  157.                         passed = false;
  158.                 }
  159.         }
  160.  
  161.         free(node_ref);
  162.         node_counter = 0;
  163.  
  164.         printf("%s\n", passed ? "PASS" : "FAIL");
  165.  
  166.         return passed ? 0 : 1;
  167. }
  168.  
  169. int main(int argc, char **argv)
  170. {
  171.         int ret;
  172.         int shift;
  173.         int offset;
  174.         if (argc != 2) {
  175.                 printf("Usage: %s <filename>\n", argv[0]);
  176.                 return 1;
  177.         }
  178.  
  179. #define DO_TEST(n) if ((ret = run_test(argc, argv, (n))) != 0) return ret
  180.         for (shift = 0; (1 << shift) != 16384; shift++)
  181.                 for (offset = 0; offset < 10; offset += 3)
  182.                         DO_TEST((1 << shift) + offset);
  183.  
  184.         return 0;
  185. #undef DO_TEST
  186. }
  187.  
  188. hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result)
  189. {
  190.         printf("Creating (%" PRIuPTR ") [comment '%.*s']\n", ++node_counter,
  191.                         (int) data->len, data->ptr);
  192.  
  193.         assert(memchr(data->ptr, 0xff, data->len) == NULL);
  194.  
  195.         GROW_REF
  196.         node_ref[node_counter] = 0;
  197.  
  198.         ref_node(ctx, (void *) node_counter);
  199.  
  200.         *result = (void *) node_counter;
  201.  
  202.         return HUBBUB_OK;
  203. }
  204.  
  205. hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype,
  206.                 void **result)
  207. {
  208.         printf("Creating (%" PRIuPTR ") [doctype '%.*s']\n", ++node_counter,
  209.                         (int) doctype->name.len, doctype->name.ptr);
  210.  
  211.         assert(memchr(doctype->name.ptr, 0xff, doctype->name.len) == NULL);
  212.         if (doctype->public_missing == false) {
  213.                 assert(memchr(doctype->public_id.ptr, 0xff,
  214.                                 doctype->public_id.len) == NULL);
  215.         }
  216.         if (doctype->system_missing == false) {
  217.                 assert(memchr(doctype->system_id.ptr, 0xff,
  218.                                 doctype->system_id.len) == NULL);
  219.         }
  220.  
  221.         GROW_REF
  222.         node_ref[node_counter] = 0;
  223.  
  224.         ref_node(ctx, (void *) node_counter);
  225.  
  226.         *result = (void *) node_counter;
  227.  
  228.         return HUBBUB_OK;
  229. }
  230.  
  231. hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result)
  232. {
  233.         uint32_t i;
  234.  
  235.         printf("Creating (%" PRIuPTR ") [element '%.*s']\n", ++node_counter,
  236.                         (int) tag->name.len, tag->name.ptr);
  237.  
  238.         assert(memchr(tag->name.ptr, 0xff, tag->name.len) == NULL);
  239.         for (i = 0; i < tag->n_attributes; i++) {
  240.                 hubbub_attribute *attr = &tag->attributes[i];
  241.  
  242.                 assert(memchr(attr->name.ptr, 0xff, attr->name.len) == NULL);
  243.                 assert(memchr(attr->value.ptr, 0xff, attr->value.len) == NULL);
  244.         }
  245.  
  246.         GROW_REF
  247.         node_ref[node_counter] = 0;
  248.  
  249.         ref_node(ctx, (void *) node_counter);
  250.  
  251.         *result = (void *) node_counter;
  252.  
  253.         return HUBBUB_OK;
  254. }
  255.  
  256. hubbub_error create_text(void *ctx, const hubbub_string *data, void **result)
  257. {
  258.         printf("Creating (%" PRIuPTR ") [text '%.*s']\n", ++node_counter,
  259.                         (int) data->len, data->ptr);
  260.  
  261.         assert(memchr(data->ptr, 0xff, data->len) == NULL);
  262.  
  263.         GROW_REF
  264.         node_ref[node_counter] = 0;
  265.  
  266.         ref_node(ctx, (void *) node_counter);
  267.  
  268.         *result = (void *) node_counter;
  269.  
  270.         return HUBBUB_OK;
  271. }
  272.  
  273. hubbub_error ref_node(void *ctx, void *node)
  274. {
  275.         UNUSED(ctx);
  276.  
  277.         printf("Referencing %" PRIuPTR " (=%u)\n",
  278.                         (uintptr_t) node, ++node_ref[(uintptr_t) node]);
  279.  
  280.         return HUBBUB_OK;
  281. }
  282.  
  283. hubbub_error unref_node(void *ctx, void *node)
  284. {
  285.         UNUSED(ctx);
  286.  
  287.         printf("Unreferencing %" PRIuPTR " (=%u)\n",
  288.                         (uintptr_t) node, --node_ref[(uintptr_t) node]);
  289.  
  290.         return HUBBUB_OK;
  291. }
  292.  
  293. hubbub_error append_child(void *ctx, void *parent, void *child, void **result)
  294. {
  295.         printf("Appending %" PRIuPTR " to %" PRIuPTR "\n", (uintptr_t) child, (uintptr_t) parent);
  296.         ref_node(ctx, child);
  297.  
  298.         *result = (void *) child;
  299.  
  300.         return HUBBUB_OK;
  301. }
  302.  
  303. hubbub_error insert_before(void *ctx, void *parent, void *child,
  304.                 void *ref_child, void **result)
  305. {
  306.         printf("Inserting %" PRIuPTR " in %" PRIuPTR " before %" PRIuPTR "\n", (uintptr_t) child,
  307.                         (uintptr_t) parent, (uintptr_t) ref_child);
  308.         ref_node(ctx, child);
  309.  
  310.         *result = (void *) child;
  311.  
  312.         return HUBBUB_OK;
  313. }
  314.  
  315. hubbub_error remove_child(void *ctx, void *parent, void *child, void **result)
  316. {
  317.         printf("Removing %" PRIuPTR " from %" PRIuPTR "\n", (uintptr_t) child, (uintptr_t) parent);
  318.         ref_node(ctx, child);
  319.  
  320.         *result = (void *) child;
  321.  
  322.         return HUBBUB_OK;
  323. }
  324.  
  325. hubbub_error clone_node(void *ctx, void *node, bool deep, void **result)
  326. {
  327.         printf("%sCloning %" PRIuPTR " -> %" PRIuPTR "\n", deep ? "Deep-" : "",
  328.                         (uintptr_t) node, ++node_counter);
  329.  
  330.         GROW_REF
  331.         node_ref[node_counter] = 0;
  332.  
  333.         ref_node(ctx, (void *) node_counter);
  334.  
  335.         *result = (void *) node_counter;
  336.  
  337.         return HUBBUB_OK;
  338. }
  339.  
  340. hubbub_error reparent_children(void *ctx, void *node, void *new_parent)
  341. {
  342.         UNUSED(ctx);
  343.  
  344.         printf("Reparenting children of %" PRIuPTR " to %" PRIuPTR "\n",
  345.                                 (uintptr_t) node, (uintptr_t) new_parent);
  346.  
  347.         return HUBBUB_OK;
  348. }
  349.  
  350. hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result)
  351. {
  352.         printf("Retrieving parent of %" PRIuPTR " (%s)\n", (uintptr_t) node,
  353.                         element_only ? "element only" : "");
  354.  
  355.         ref_node(ctx, (void *) 1);
  356.         *result = (void *) 1;
  357.  
  358.         return HUBBUB_OK;
  359. }
  360.  
  361. hubbub_error has_children(void *ctx, void *node, bool *result)
  362. {
  363.         UNUSED(ctx);
  364.  
  365.         printf("Want children for %" PRIuPTR "\n", (uintptr_t) node);
  366.  
  367.         *result = false;
  368.  
  369.         return HUBBUB_OK;
  370. }
  371.  
  372. hubbub_error form_associate(void *ctx, void *form, void *node)
  373. {
  374.         UNUSED(ctx);
  375.  
  376.         printf("Associating %" PRIuPTR " with form %" PRIuPTR "\n",
  377.                         (uintptr_t) node, (uintptr_t) form);
  378.  
  379.         return HUBBUB_OK;
  380. }
  381.  
  382. hubbub_error add_attributes(void *ctx, void *node,
  383.                 const hubbub_attribute *attributes, uint32_t n_attributes)
  384. {
  385.         uint32_t i;
  386.  
  387.         UNUSED(ctx);
  388.         UNUSED(attributes);
  389.         UNUSED(n_attributes);
  390.  
  391.         printf("Adding attributes to %" PRIuPTR "\n", (uintptr_t) node);
  392.  
  393.         for (i = 0; i < n_attributes; i++) {
  394.                 const hubbub_attribute *attr = &attributes[i];
  395.  
  396.                 assert(memchr(attr->name.ptr, 0xff, attr->name.len) == NULL);
  397.                 assert(memchr(attr->value.ptr, 0xff, attr->value.len) == NULL);
  398.         }
  399.  
  400.         return HUBBUB_OK;
  401. }
  402.  
  403. hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode)
  404. {
  405.         UNUSED(ctx);
  406.  
  407.         printf("Quirks mode = %u\n", mode);
  408.  
  409.         return HUBBUB_OK;
  410. }
  411.  
  412. hubbub_error complete_script(void *ctx, void *script)
  413. {
  414.         UNUSED(ctx);
  415.         UNUSED(script);
  416.  
  417.         return HUBBUB_OK;
  418. }
  419.  
  420.