diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-05-24 18:00:38 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-05-28 15:34:29 +0800 |
| commit | 95428c41f0ee3ac108cf1a4acfaa67157ad954dc (patch) | |
| tree | 8565027758cd931f49ebe78738fb41126254b253 /dom.c | |
| parent | 7aea09077aad335ac32bfd9858ded60ffd4d8a5b (diff) | |
| download | glacier-95428c41f0ee3ac108cf1a4acfaa67157ad954dc.tar.gz | |
Build DOM.
Diffstat (limited to 'dom.c')
| -rw-r--r-- | dom.c | 132 |
1 files changed, 121 insertions, 11 deletions
@@ -1,37 +1,147 @@ #include <stdio.h> +#include <err.h> +#include "mem.h" #include "dom.h" +#include "vec.h" #include "parse.h" -void init_dom(const char *html) +static struct node **nodes; +static size_t count; +static size_t capacity; + +static struct vec stack; +static struct node *root; + +static inline struct node *node_alloc(void) +{ + struct node *v; + + if (count == capacity) { + capacity = capacity ? capacity * 2 : 64; + nodes = REALLOC(nodes, capacity * sizeof(struct node *)); + } + + v = CALLOC(1, sizeof(struct node)); + nodes[count++] = v; + return v; +} + +struct node *dom_init(const char *html) { + vec_init(&stack, sizeof(struct node *)); parse(html); + return root; +} + +void dom_free(void) +{ + size_t i; + + for (i = 0; i < count; i++) + free(nodes[i]); + free(nodes); + nodes = NULL; + count = 0; + capacity = 0; + + vec_free(&stack); +} + +static inline int is_self_closing(tag_type tag) +{ + switch (tag) { + case TAG_META: + case TAG_LINK: + return 1; + default: + return 0; + } +} + +static inline void close_tag(struct node *v) +{ + void *top; + struct node *parent; + + top = vec_top(&stack); + if (!top) { + root = v; + return; + } + + parent = *(struct node **)top; + v->parent = parent; + + if (!parent->first_child) { + parent->first_child = v; + parent->last_child = v; + } else { + parent->last_child->next_sibling = v; + parent->last_child = v; + } } -/* Parser event handlers */ extern void on_open(const char *tag, size_t n) { - printf("Tag opened: %.*s\n", (int)n, tag); + struct node *v; + + v = node_alloc(); + v->tag = str_to_tag(tag, n); + vec_push(&stack, &v); +} + +extern void on_open_end(void) +{ + struct node *v; + + v = *(struct node **)vec_top(&stack); + if (is_self_closing(v->tag)) { + v = *(struct node **)vec_pop(&stack); + close_tag(v); + } } extern void on_close(const char *tag, size_t n) { - printf("Tag closed: %.*s\n", (int)n, tag); + tag_type type; + struct node *top; + + type = str_to_tag(tag, n); + top = *(struct node **)vec_top(&stack); + if (top->tag != type) + errx(1, "Unmatched closing tag: %.*s", (int)n, tag); + + top = *(struct node **)vec_pop(&stack); + close_tag(top); } extern void on_text(const char *text, size_t n) { - printf("Text: %.*s\n", (int)n, text); + struct node *v; + + v = node_alloc(); + v->tag = TAG_TEXT; + v->text = text; + v->textlen = n; + close_tag(v); } -extern void on_attr(const char *name, size_t nname, const char *val, - size_t nval) +extern void on_attr(const char *name, size_t nname, + const char *val, size_t nval) { - printf("Attribute: name=%.*s", (int)nname, name); + struct attr *a; + struct node *v; - if (val && nval > 0) - printf(", value=%.*s", (int)nval, val); + a = MALLOC(sizeof(struct attr)); + a->key = name; + a->keylen = nname; + a->val = val; + a->vallen = nval; + a->next = NULL; - printf("\n"); + v = *(struct node **)vec_top(&stack); + a->next = v->attrs; + v->attrs = a; } |
