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