1 /*
2  Copyright (C) 2016-2017 Alexander Borisov
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 
18  Author: lex.borisov@gmail.com (Alexander Borisov)
19 */
20 
21 #include "mycss/namespace/init.h"
22 
mycss_namespace_create(void)23 mycss_namespace_t * mycss_namespace_create(void)
24 {
25     return (mycss_namespace_t*)mycore_calloc(1, sizeof(mycss_namespace_t));
26 }
27 
mycss_namespace_init(mycss_entry_t * entry,mycss_namespace_t * ns)28 mystatus_t mycss_namespace_init(mycss_entry_t* entry, mycss_namespace_t* ns)
29 {
30     /* Objects Namespace */
31     ns->mcobject_entries = mcobject_create();
32     if(ns->mcobject_entries == NULL)
33         return MyCSS_STATUS_ERROR_NAMESPACE_ENTRIES_CREATE;
34 
35     mystatus_t myhtml_status = mcobject_init(ns->mcobject_entries, 256, sizeof(mycss_namespace_entry_t));
36     if(myhtml_status)
37         return MyCSS_STATUS_ERROR_NAMESPACE_ENTRIES_INIT;
38 
39     return MyCSS_STATUS_OK;
40 }
41 
mycss_namespace_clean(mycss_namespace_t * ns)42 void mycss_namespace_clean(mycss_namespace_t* ns)
43 {
44     ns->entry = NULL;
45 }
46 
mycss_namespace_clean_all(mycss_namespace_t * ns)47 mystatus_t mycss_namespace_clean_all(mycss_namespace_t* ns)
48 {
49     mcobject_clean(ns->mcobject_entries);
50     ns->entry = NULL;
51 
52     return MyCSS_STATUS_OK;
53 }
54 
mycss_namespace_destroy(mycss_namespace_t * ns,bool self_destroy)55 mycss_namespace_t * mycss_namespace_destroy(mycss_namespace_t* ns, bool self_destroy)
56 {
57     if(ns == NULL)
58         return NULL;
59 
60     ns->mcobject_entries = mcobject_destroy(ns->mcobject_entries, true);
61 
62     if(self_destroy) {
63         mycore_free(ns);
64         return NULL;
65     }
66 
67     return ns;
68 }
69 
mycss_namespace_entry_create(mycss_namespace_t * ns)70 mycss_namespace_entry_t * mycss_namespace_entry_create(mycss_namespace_t* ns)
71 {
72     return mcobject_malloc(ns->mcobject_entries, NULL);
73 }
74 
mycss_namespace_entry_clean(mycss_namespace_entry_t * ns_entry)75 void mycss_namespace_entry_clean(mycss_namespace_entry_t* ns_entry)
76 {
77     memset(ns_entry, 0, sizeof(mycss_namespace_entry_t));
78 }
79 
mycss_namespace_entry_destroy(mycss_namespace_entry_t * ns_entry,mycss_entry_t * entry,bool self_destroy)80 mycss_namespace_entry_t * mycss_namespace_entry_destroy(mycss_namespace_entry_t* ns_entry, mycss_entry_t* entry, bool self_destroy)
81 {
82     if(ns_entry->name) {
83         mycore_string_destroy(ns_entry->name, false);
84         mcobject_free(entry->mcobject_string_entries, ns_entry->name);
85     }
86 
87     if(ns_entry->url) {
88         mycore_string_destroy(ns_entry->url, false);
89         mcobject_free(entry->mcobject_string_entries, ns_entry->url);
90     }
91 
92     if(self_destroy) {
93         mycore_free(ns_entry);
94         return NULL;
95     }
96 
97     return ns_entry;
98 }
99 
mycss_namespace_entry_append_to_current(mycss_namespace_t * ns,mycss_namespace_entry_t * ns_entry)100 void mycss_namespace_entry_append_to_current(mycss_namespace_t* ns, mycss_namespace_entry_t* ns_entry)
101 {
102     if(ns->entry_last) {
103         ns->entry_last->next = ns_entry;
104         ns_entry->prev = ns->entry_last;
105     }
106     else {
107         (*ns->entry) = ns_entry;
108     }
109 
110     ns->entry_last = ns_entry;
111 }
112 
mycss_namespace_stylesheet_init(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_entry_t * entry)113 mystatus_t mycss_namespace_stylesheet_init(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_entry_t* entry)
114 {
115     ns_stylesheet->name_tree = mctree_create(14);
116     if(ns_stylesheet->name_tree == NULL)
117         return MyCSS_STATUS_ERROR_NAMESPACE_CREATE;
118 
119     ns_stylesheet->ns_id_counter = 0;
120 
121     ns_stylesheet->entry_default = mycss_namespace_entry_create(entry->ns);
122     if(ns_stylesheet->entry_default == NULL)
123         return MyCSS_STATUS_ERROR_NAMESPACE_ENTRIES_CREATE;
124 
125     mycss_namespace_entry_clean(ns_stylesheet->entry_default);
126     mycss_namespace_entry_clean(&ns_stylesheet->entry_undef);
127     mycss_namespace_entry_clean(&ns_stylesheet->entry_any);
128 
129     /* init name for basic namespace entry; for default namespace entry name = NULL */
130     ns_stylesheet->entry_undef.name = mycss_entry_string_create_and_init(entry, 2);
131     if(ns_stylesheet->entry_undef.name == NULL)
132         return MyCSS_STATUS_ERROR_STRING_CREATE;
133 
134     ns_stylesheet->entry_any.name = mycss_entry_string_create_and_init(entry, 2);
135     if(ns_stylesheet->entry_any.name == NULL)
136         return MyCSS_STATUS_ERROR_STRING_CREATE;
137 
138     mycore_string_append(ns_stylesheet->entry_any.name, "*", 1);
139     ns_stylesheet->entry_any.ns_id = MyHTML_NAMESPACE_ANY;
140 
141     mycss_namespace_stylesheet_init_default(ns_stylesheet, entry, NULL, 0, MyHTML_NAMESPACE_ANY);
142 
143     return MyCSS_STATUS_OK;
144 }
145 
mycss_namespace_stylesheet_clean(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_entry_t * entry)146 mystatus_t mycss_namespace_stylesheet_clean(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_entry_t* entry)
147 {
148     mctree_clean(ns_stylesheet->name_tree);
149     ns_stylesheet->ns_id_counter = 0;
150 
151     mycss_namespace_stylesheet_init_default(ns_stylesheet, entry, NULL, 0, MyHTML_NAMESPACE_ANY);
152 
153     return MyCSS_STATUS_OK;
154 }
155 
mycss_namespace_stylesheet_destroy(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_entry_t * entry,bool self_destroy)156 mycss_namespace_stylesheet_t * mycss_namespace_stylesheet_destroy(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_entry_t* entry, bool self_destroy)
157 {
158     mycss_namespace_entry_t* ns_entry = ns_stylesheet->entry_default;
159 
160     while(ns_entry) {
161         mycss_namespace_entry_t* ns_entry_next = ns_entry->next;
162 
163         mycss_namespace_entry_destroy(ns_entry, entry, false);
164         mcobject_free(entry->ns->mcobject_entries, ns_entry);
165 
166         ns_entry = ns_entry_next;
167     }
168 
169     ns_stylesheet->name_tree = mctree_destroy(ns_stylesheet->name_tree);
170     ns_stylesheet->entry_undef.name = mycore_string_destroy(ns_stylesheet->entry_undef.name, false);
171     ns_stylesheet->entry_any.name = mycore_string_destroy(ns_stylesheet->entry_any.name, false);
172 
173     if(self_destroy) {
174         mycore_free(ns_stylesheet);
175         return NULL;
176     }
177 
178     return ns_stylesheet;
179 }
180 
mycss_namespace_stylesheet_init_default(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_entry_t * entry,const char * url,size_t url_length,myhtml_namespace_t def_ns)181 mystatus_t mycss_namespace_stylesheet_init_default(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_entry_t* entry, const char* url, size_t url_length, myhtml_namespace_t def_ns)
182 {
183     mycore_string_t *str = ns_stylesheet->entry_default->url;
184 
185     if(str == NULL) {
186         str = mcobject_malloc(entry->mcobject_string_entries, NULL);
187         mycore_string_init(entry->mchar, entry->mchar_node_id, str, (url_length + 1));
188 
189         ns_stylesheet->entry_default->url = str;
190     }
191     else
192         mycore_string_clean(str);
193 
194     if(url && url_length) {
195         mycore_string_append(str, url, url_length);
196         ns_stylesheet->entry_default->ns_id = myhtml_namespace_id_by_url(url, url_length);
197     }
198     else
199         ns_stylesheet->entry_default->ns_id = def_ns;
200 
201     ns_stylesheet->entry_default->mctree_id = 0;
202     ns_stylesheet->entry_default->name      = NULL;
203     ns_stylesheet->entry_default->next      = NULL;
204     ns_stylesheet->entry_default->prev      = NULL;
205 
206     return MyCSS_STATUS_OK;
207 }
208 
mycss_namespace_stylesheet_append_default(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_namespace_entry_t * ns_entry)209 void mycss_namespace_stylesheet_append_default(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_namespace_entry_t* ns_entry)
210 {
211     if(ns_stylesheet->entry_default == NULL) {
212         ns_stylesheet->entry_default = ns_entry;
213         return;
214     }
215 
216     mycss_namespace_entry_t* ns_entry_cur = ns_stylesheet->entry_default;
217 
218     while(ns_entry_cur->next)
219         ns_entry_cur = ns_entry_cur->next;
220 
221     ns_entry_cur->next = ns_entry;
222     ns_entry->prev = ns_entry_cur;
223 
224     ns_stylesheet->entry_default = ns_entry;
225 }
226 
mycss_namespace_stylesheet_destroy_default(mycss_namespace_stylesheet_t * ns_stylesheet,mycss_entry_t * entry)227 void mycss_namespace_stylesheet_destroy_default(mycss_namespace_stylesheet_t* ns_stylesheet, mycss_entry_t* entry)
228 {
229     mycore_string_t *str = ns_stylesheet->entry_default->url;
230 
231     if(str) {
232         mycore_string_destroy(str, false);
233         mcobject_free(entry->mcobject_string_entries, str);
234 
235         ns_stylesheet->entry_default->url = NULL;
236     }
237 }
238 
mycss_namespace_name_by_id(mycss_namespace_t * ns,mctree_t * name_tree,size_t ns_id,size_t * length)239 const char * mycss_namespace_name_by_id(mycss_namespace_t* ns, mctree_t* name_tree, size_t ns_id, size_t* length)
240 {
241     if(ns_id < MyHTML_NAMESPACE_LAST_ENTRY)
242         return myhtml_namespace_name_by_id((myhtml_namespace_t)ns_id, length);
243 
244     ns_id -= MyHTML_NAMESPACE_LAST_ENTRY;
245 
246     mycss_namespace_entry_t *entry = (mycss_namespace_entry_t*)(name_tree->nodes[ ns_id ].value);
247 
248     if(length)
249         *length = entry->name->length;
250 
251     return entry->name->data;
252 }
253 
mycss_namespace_name_by_entry(mycss_namespace_entry_t * ns_entry,mctree_t * name_tree,size_t * length,bool * is_default)254 const char * mycss_namespace_name_by_entry(mycss_namespace_entry_t* ns_entry, mctree_t* name_tree, size_t* length, bool* is_default)
255 {
256     if(ns_entry->name == NULL) {
257         if(is_default)
258             *is_default = true;
259 
260         if(length)
261             *length = 0;
262 
263         if(ns_entry->ns_id <= MyHTML_NAMESPACE_LAST_ENTRY)
264             return myhtml_namespace_name_by_id(ns_entry->ns_id, length);
265 
266         return NULL;
267     }
268 
269     if(is_default)
270         *is_default = false;
271 
272     if(length)
273         *length = ns_entry->name->length;
274 
275     return ns_entry->name->data;
276 }
277 
mycss_namespace_entry_by_name(mycss_namespace_t * ns,mctree_t * name_tree,const char * ns_name,size_t length,bool case_insensitive)278 mycss_namespace_entry_t * mycss_namespace_entry_by_name(mycss_namespace_t *ns, mctree_t* name_tree, const char* ns_name, size_t length, bool case_insensitive)
279 {
280     if(ns == NULL)
281         return NULL;
282 
283     mctree_index_t idx;
284     if(case_insensitive)
285         idx = mctree_search_lowercase(name_tree, ns_name, length);
286     else
287         idx = mctree_search(name_tree, ns_name, length);
288 
289     if(idx == 0)
290         return 0;
291 
292     return (mycss_namespace_entry_t*)(name_tree->nodes[ idx ].value);
293 }
294 
295 
296