1 /*
2 * This file is part of libdom.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2009 Bo Yang <struggleyb.nku@gmail.com>
6 */
7
8 #include <assert.h>
9 #include <stdlib.h>
10
11 #include <libwapcaplet/libwapcaplet.h>
12
13 #include "html/html_options_collection.h"
14
15 #include "core/node.h"
16 #include "core/element.h"
17 #include "core/string.h"
18 #include "utils/utils.h"
19
20 /*-----------------------------------------------------------------------*/
21 /* Constructor and destructor */
22
23 /**
24 * Create a dom_html_options_collection
25 *
26 * \param doc The document
27 * \param root The root element of the collection
28 * \param ic The callback function used to determin whether certain node
29 * beint32_ts to the collection
30 * \param col The result collection object
31 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
32 */
_dom_html_options_collection_create(struct dom_html_document * doc,struct dom_node_internal * root,dom_callback_is_in_collection ic,void * ctx,struct dom_html_options_collection ** col)33 dom_exception _dom_html_options_collection_create(struct dom_html_document *doc,
34 struct dom_node_internal *root,
35 dom_callback_is_in_collection ic,
36 void *ctx,
37 struct dom_html_options_collection **col)
38 {
39 *col = malloc(sizeof(dom_html_options_collection));
40 if (*col == NULL)
41 return DOM_NO_MEM_ERR;
42
43 return _dom_html_options_collection_initialise(doc, *col, root,
44 ic, ctx);
45 }
46
47 /**
48 * Intialiase a dom_html_options_collection
49 *
50 * \param doc The document
51 * \param col The collection object to be initialised
52 * \param root The root element of the collection
53 * \param ic The callback function used to determin whether certain node
54 * beint32_ts to the collection
55 * \return DOM_NO_ERR on success.
56 */
_dom_html_options_collection_initialise(struct dom_html_document * doc,struct dom_html_options_collection * col,struct dom_node_internal * root,dom_callback_is_in_collection ic,void * ctx)57 dom_exception _dom_html_options_collection_initialise(struct dom_html_document *doc,
58 struct dom_html_options_collection *col,
59 struct dom_node_internal *root,
60 dom_callback_is_in_collection ic, void *ctx)
61 {
62 return _dom_html_collection_initialise(doc, &col->base, root, ic, ctx);
63 }
64
65 /**
66 * Finalise a dom_html_options_collection object
67 *
68 * \param col The dom_html_options_collection object
69 */
_dom_html_options_collection_finalise(struct dom_html_options_collection * col)70 void _dom_html_options_collection_finalise(struct dom_html_options_collection *col)
71 {
72 _dom_html_collection_finalise(&col->base);
73 }
74
75 /**
76 * Destroy a dom_html_options_collection object
77 * \param col The dom_html_options_collection object
78 */
_dom_html_options_collection_destroy(struct dom_html_options_collection * col)79 void _dom_html_options_collection_destroy(struct dom_html_options_collection *col)
80 {
81 _dom_html_options_collection_finalise(col);
82
83 free(col);
84 }
85
86
87 /*-----------------------------------------------------------------------*/
88 /* Public API */
89
90 /**
91 * Get the length of this dom_html_options_collection
92 *
93 * \param col The dom_html_options_collection object
94 * \param len The returned length of this collection
95 * \return DOM_NO_ERR on success.
96 */
dom_html_options_collection_get_length(dom_html_options_collection * col,uint32_t * len)97 dom_exception dom_html_options_collection_get_length(dom_html_options_collection *col,
98 uint32_t *len)
99 {
100 return dom_html_collection_get_length(&col->base, len);
101 }
102
103 /**
104 * Set the length of this dom_html_options_collection
105 *
106 * \param col The dom_html_options_collection object
107 * \param len The length of this collection to be set
108 * \return DOM_NO_ERR on success.
109 */
dom_html_options_collection_set_length(dom_html_options_collection * col,uint32_t len)110 dom_exception dom_html_options_collection_set_length(
111 dom_html_options_collection *col, uint32_t len)
112 {
113 UNUSED(col);
114 UNUSED(len);
115
116 /* TODO: how to deal with this */
117 return DOM_NOT_SUPPORTED_ERR;
118 }
119
120 /**
121 * Get the node with certain index
122 *
123 * \param col The dom_html_options_collection object
124 * \param index The index number based on zero
125 * \param node The returned node object
126 * \return DOM_NO_ERR on success.
127 */
dom_html_options_collection_item(dom_html_options_collection * col,uint32_t index,struct dom_node ** node)128 dom_exception dom_html_options_collection_item(dom_html_options_collection *col,
129 uint32_t index, struct dom_node **node)
130 {
131 return dom_html_collection_item(&col->base, index, node);
132 }
133
134 /**
135 * Get the node in the collection according name
136 *
137 * \param col The collection
138 * \param name The name of target node
139 * \param node The returned node object
140 * \return DOM_NO_ERR on success.
141 */
dom_html_options_collection_named_item(dom_html_options_collection * col,dom_string * name,struct dom_node ** node)142 dom_exception dom_html_options_collection_named_item(dom_html_options_collection *col,
143 dom_string *name, struct dom_node **node)
144 {
145 struct dom_node_internal *n = col->base.root;
146 dom_string *kname;
147 dom_exception err;
148
149 /* Search for an element with an appropriate ID */
150 err = dom_html_collection_named_item(&col->base, name, node);
151 if (err == DOM_NO_ERR && *node != NULL)
152 return err;
153
154 /* Didn't find one, so consider name attribute */
155 err = dom_string_create_interned((const uint8_t *) "name", SLEN("name"),
156 &kname);
157 if (err != DOM_NO_ERR)
158 return err;
159
160 while (n != NULL) {
161 if (n->type == DOM_ELEMENT_NODE &&
162 col->base.ic(n, col->base.ctx) == true) {
163 dom_string *nval = NULL;
164
165 err = dom_element_get_attribute(n, kname, &nval);
166 if (err != DOM_NO_ERR) {
167 dom_string_unref(kname);
168 return err;
169 }
170
171 if (nval != NULL && dom_string_isequal(name, nval)) {
172 *node = (struct dom_node *) n;
173 dom_node_ref(n);
174 dom_string_unref(nval);
175 dom_string_unref(kname);
176
177 return DOM_NO_ERR;
178 }
179
180 if (nval != NULL)
181 dom_string_unref(nval);
182 }
183
184 /* Depth first iterating */
185 if (n->first_child != NULL) {
186 n = n->first_child;
187 } else if (n->next != NULL) {
188 n = n->next;
189 } else {
190 /* No children and siblings */
191 struct dom_node_internal *parent = n->parent;
192
193 while (n != col->base.root &&
194 n == parent->last_child) {
195 n = parent;
196 parent = parent->parent;
197 }
198
199 if (n == col->base.root)
200 n = NULL;
201 else
202 n = n->next;
203 }
204 }
205
206 dom_string_unref(kname);
207
208 /* Not found the target node */
209 *node = NULL;
210
211 return DOM_NO_ERR;
212 }
213
214 /**
215 * Claim a reference on this collection
216 *
217 * \pram col The collection object
218 */
dom_html_options_collection_ref(dom_html_options_collection * col)219 void dom_html_options_collection_ref(dom_html_options_collection *col)
220 {
221 if (col == NULL)
222 return;
223
224 col->base.refcnt ++;
225 }
226
227 /**
228 * Relese a reference on this collection
229 *
230 * \pram col The collection object
231 */
dom_html_options_collection_unref(dom_html_options_collection * col)232 void dom_html_options_collection_unref(dom_html_options_collection *col)
233 {
234 if (col == NULL)
235 return;
236
237 if (col->base.refcnt > 0)
238 col->base.refcnt --;
239
240 if (col->base.refcnt == 0)
241 _dom_html_options_collection_destroy(col);
242 }
243
244