Use separate data variables for storing DOM stack data
[elinks.git] / src / document / dom / stack.h
blob4833521b3c10ee9025014a3ae87d254b9b20e04f
2 #ifndef EL__DOCUMENT_DOM_STACK_H
3 #define EL__DOCUMENT_DOM_STACK_H
5 #include "document/document.h"
6 #include "document/dom/node.h"
7 #include "util/error.h"
8 #include "util/hash.h"
10 struct dom_stack;
12 typedef struct dom_node *
13 (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
15 #define DOM_STACK_MAX_DEPTH 4096
17 struct dom_stack_state {
18 struct dom_node *node;
20 /* Used for recording which node list are currently being 'decended'
21 * into. E.g. whether we are iterating all child elements or attributes
22 * of an element. */
23 struct dom_node_list *list;
24 /* The index (in the list above) which are currently being handled. */
25 size_t index;
27 /* A callback registered to be called when the node is popped. Used for
28 * correctly highlighting ending elements (e.g. </a>). */
29 dom_stack_callback_T callback;
31 /* The depth of the state in the stack. This is amongst other things
32 * used to get the state object data. */
33 unsigned int depth;
36 /* The DOM stack is a convenient way to traverse DOM trees. Also it
37 * maintains needed state info and is therefore also a holder of the current
38 * context since the stack is used to when the DOM tree is manipulated. */
39 struct dom_stack {
40 /* The stack of nodes */
41 struct dom_stack_state *states;
42 size_t depth;
44 /* This is one big array of parser specific objects. */
45 /* The objects hold parser specific data. For the SGML parser this
46 * holds DTD-oriented info about the node (recorded in struct
47 * sgml_node_info). E.g. whether an element node is optional. */
48 unsigned char *state_objects;
49 size_t object_size;
51 /* Parser and document specific stuff */
52 dom_stack_callback_T callbacks[DOM_NODES];
53 void *renderer;
55 void *parser;
58 #define dom_stack_has_parents(nav) \
59 ((nav)->states && (nav)->depth > 0)
61 static inline struct dom_stack_state *
62 get_dom_stack_state(struct dom_stack *stack, int top_offset)
64 assertm(stack->depth - 1 - top_offset >= 0,
65 "Attempting to access invalid state");
66 return &stack->states[stack->depth - 1 - top_offset];
69 #define get_dom_stack_parent(nav) get_dom_stack_state(nav, 1)
70 #define get_dom_stack_top(nav) get_dom_stack_state(nav, 0)
72 #define get_dom_stack_state_data(stack, state) \
73 ((void *) &(stack)->state_objects[(state)->depth * (stack)->object_size])
75 /* The state iterators do not include the bottom state */
77 #define foreach_dom_state(nav, item, pos) \
78 for ((pos) = 1; (pos) < (nav)->depth; (pos)++) \
79 if (((item) = &(nav)->states[(pos)]))
81 #define foreachback_dom_state(nav, item, pos) \
82 for ((pos) = (nav)->depth - 1; (pos) > 0; (pos)--) \
83 if (((item) = &(nav)->states[(pos)]))
85 /* Dive through the stack states in search for the specified match. */
86 static inline struct dom_stack_state *
87 search_dom_stack(struct dom_stack *stack, enum dom_node_type type,
88 unsigned char *string, uint16_t length)
90 struct dom_stack_state *state;
91 int pos;
93 /* FIXME: Take node subtype and compare if non-zero or something. */
94 foreachback_dom_state (stack, state, pos) {
95 struct dom_node *parent = state->node;
97 if (parent->type == type
98 && parent->length == length
99 && !strncasecmp(parent->string, string, length))
100 return state;
103 return NULL;
107 /* Life cycle functions. */
109 /* The @object_size arg tells whether the stack should allocate objects for each
110 * state to be assigned to the state's @data member. Zero means no state data should
111 * be allocated. */
112 void init_dom_stack(struct dom_stack *stack, void *parser, void *renderer,
113 dom_stack_callback_T callbacks[DOM_NODES],
114 size_t object_size);
115 void done_dom_stack(struct dom_stack *stack);
117 /* Decends down to the given node making it the current parent */
118 /* If an error occurs the node is free()d and NULL is returned */
119 struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
121 /* Ascends the stack to the current parent */
122 void pop_dom_node(struct dom_stack *stack);
124 /* Ascends the stack looking for specific parent */
125 void pop_dom_nodes(struct dom_stack *stack, enum dom_node_type type,
126 unsigned char *string, uint16_t length);
128 /* Visit each node in the tree rooted at @root pre-order */
129 void walk_dom_nodes(struct dom_stack *stack, struct dom_node *root);
131 #endif