From fd2d93f4a97ab5a3bc18764c353b971b4035ac6a Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Tue, 5 May 2026 16:05:19 +0800 Subject: Defined basic DOM operations. --- .gitignore | 3 +++ Makefile | 4 +-- wv_dom.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wv_dom.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ wv_mem.c | 10 +++---- wv_mem.h | 3 --- 6 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 wv_dom.c create mode 100644 wv_dom.h diff --git a/.gitignore b/.gitignore index c0b8288..083c749 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ **/*a.out **/*.swp **/*.core + +**/*.o +webview diff --git a/Makefile b/Makefile index 7c9c6c3..f10ad4c 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ CC = cc CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -g -O0 LDFLAGS = -HDRS = wv_mem.h wv_err.h -SRCS = wv_mem.c wv_main.c +HDRS = wv_mem.h wv_err.h wv_dom.h +SRCS = wv_mem.c wv_dom.c wv_main.c OBJS = $(SRCS:.c=.o) TARGET = webview diff --git a/wv_dom.c b/wv_dom.c new file mode 100644 index 0000000..ee24e98 --- /dev/null +++ b/wv_dom.c @@ -0,0 +1,88 @@ +#include +#include + +#include "wv_dom.h" + +wv_ref wv_node_new(struct wv_arena *arena, wv_node_type type) +{ + wv_ref ref; + struct wv_node *node; + + ref = wv_alloc(arena, sizeof(struct wv_node)); + node = (struct wv_node *)WV_ADDR(arena, ref); + memset(node, 0, sizeof(struct wv_node)); + node->type = type; + + return ref; +} + +void wv_node_append(struct wv_arena *arena, wv_ref parent_ref, + wv_ref child_ref) +{ + struct wv_node *p, *c, *last; + + if (!parent_ref || !child_ref) + return; + + p = (struct wv_node *)WV_ADDR(arena, parent_ref); + c = (struct wv_node *)WV_ADDR(arena, child_ref); + + c->parent = parent_ref; + + if (!p->first_child) { + /* This is the parent's only child */ + p->first_child = child_ref; + } else { + /* Link to the current tail of the child list */ + last = (struct wv_node *)WV_ADDR(arena, p->last_child); + last->next_sibling = child_ref; + c->prev_sibling = p->last_child; + } + + p->last_child = child_ref; +} + +void wv_attr_set(struct wv_arena *arena, wv_ref node_ref, + wv_ref key_str, wv_ref val_str) +{ + wv_ref attr_ref; + struct wv_node *n; + struct wv_attr *a; + + n = (struct wv_node *)WV_ADDR(arena, node_ref); + if (n->type != WV_NODE_ELEMENT) return; + + attr_ref = wv_alloc(arena, sizeof(struct wv_attr)); + a = (struct wv_attr *)WV_ADDR(arena, attr_ref); + + a->key = key_str; + a->val = val_str; + + // Link attribute to the head of the list (prepend) + a->next = n->u.element.attr_head; + n->u.element.attr_head = attr_ref; +} + +wv_ref wv_attr_get(struct wv_arena *arena, wv_ref node_ref, + const char *key_name) +{ + wv_ref curr; + struct wv_node *n; + struct wv_attr *a; + + n = (struct wv_node *)WV_ADDR(arena, node_ref); + if (n->type != WV_NODE_ELEMENT) + return 0; + + curr = n->u.element.attr_head; + while (curr != 0) { + a = (struct wv_attr *)WV_ADDR(arena, curr); + const char *attr_key = (const char *)WV_ADDR(arena, a->key); + if (strcmp(attr_key, key_name) == 0) + return a->val; + curr = a->next; + } + + return 0; +} + diff --git a/wv_dom.h b/wv_dom.h new file mode 100644 index 0000000..9a2c281 --- /dev/null +++ b/wv_dom.h @@ -0,0 +1,69 @@ +#ifndef WV_DOM_H +#define WV_DOM_H + +#include "wv_mem.h" + +typedef enum { + WV_TAG_UNKNOWN = 0, + WV_TAG_DOCUMENT, + WV_TAG_HTML, + WV_TAG_HEAD, + WV_TAG_META, + WV_TAG_TITLE, + WV_TAG_LINK, + WV_TAG_BODY, + WV_TAG_HEADER, + WV_TAG_H1, + WV_TAG_A, + WV_TAG_ARTICLE, + WV_TAG_UL, + WV_TAG_LI, + WV_TAG_TIME, + WV_TAG_FOOTER, + WV_TAG_P +} wv_tag_id; + +typedef enum { + WV_NODE_DOCUMENT, + WV_NODE_ELEMENT, + WV_NODE_TEXT +} wv_node_type; + +struct wv_attr { + wv_ref key; /* E.g., "href" */ + wv_ref val; /* E.g., "/log/vcs-1/" */ + wv_ref next; /* Next attribute in the list */ +}; + +struct wv_node { + wv_node_type type; + + wv_ref parent; + wv_ref first_child; + wv_ref last_child; + wv_ref prev_sibling; + wv_ref next_sibling; + + union { + struct { + wv_tag_id tag_id; + wv_ref attr_head; + } element; + + struct { + wv_ref str; + size_t len; + } text; + } u; +}; + +/* DOM operations */ +wv_ref wv_node_new(struct wv_arena *arena, wv_node_type type); +void wv_node_append(struct wv_arena *arena, wv_ref parent, wv_ref child); + +/* Attribute operations */ +wv_ref wv_attr_get(struct wv_arena *arena, wv_ref node_ref, const char *key_name); +void wv_attr_set(struct wv_arena *arena, wv_ref node_ref, wv_ref key_str, wv_ref val_str); + +#endif /* WV_DOM_H */ + diff --git a/wv_mem.c b/wv_mem.c index 1f6542b..7bf54d6 100644 --- a/wv_mem.c +++ b/wv_mem.c @@ -20,11 +20,11 @@ struct wv_arena *wv_arena_create(size_t n) n = WV_ARENA_MIN_SIZE; arena = malloc(sizeof(struct wv_arena)); - if (arena == NULL) + if (!arena) err(1, "malloc arena struct"); arena->buf = malloc(n); - if (arena->buf == NULL) + if (!arena->buf) err(1, "malloc arena buffer"); arena->size = n; @@ -59,7 +59,7 @@ wv_ref wv_alloc(struct wv_arena *arena, size_t n) } new_buf = realloc(arena->buf, new_size); - if (new_buf == NULL) + if (!new_buf) err(1, "realloc arena failed at %zu bytes", new_size); arena->buf = new_buf; @@ -73,7 +73,7 @@ wv_ref wv_alloc(struct wv_arena *arena, size_t n) void wv_arena_reset(struct wv_arena *arena) { - if (arena == NULL) + if (!arena) return; memset(arena->buf, 0, arena->offset); @@ -82,7 +82,7 @@ void wv_arena_reset(struct wv_arena *arena) void wv_arena_destroy(struct wv_arena *arena) { - if (arena == NULL) + if (!arena) return; free(arena->buf); diff --git a/wv_mem.h b/wv_mem.h index 9d23ae8..dc95c7c 100644 --- a/wv_mem.h +++ b/wv_mem.h @@ -7,9 +7,6 @@ /* Relative offset into the arena */ typedef uint32_t wv_ref; -/* 0 is our 'NULL' */ -#define WV_REF_NULL 0 - /* Resolve a ref into a memory address */ #define WV_ADDR(arena, ref) ((void *)((arena)->buf + (ref))) -- cgit v1.2.3