File Coverage

third_party/modest/source/myhtml/token.c
Criterion Covered Total %
statement 198 407 48.6
branch 94 228 41.2
condition n/a
subroutine n/a
pod n/a
total 292 635 45.9


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2015-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 "myhtml/token.h"
22              
23             // all key size == value size
24             static const myhtml_token_replacement_entry_t myhtml_token_attr_svg_replacement[] = {
25             {"attributename", 13, "attributeName", 13},
26             {"attributetype", 13, "attributeType", 13},
27             {"basefrequency", 13, "baseFrequency", 13},
28             {"baseprofile", 11, "baseProfile", 11},
29             {"calcmode", 8, "calcMode", 8},
30             {"clippathunits", 13, "clipPathUnits", 13},
31             {"diffuseconstant", 15, "diffuseConstant", 15},
32             {"edgemode", 8, "edgeMode", 8},
33             {"filterunits", 11, "filterUnits", 11},
34             {"glyphref", 8, "glyphRef", 8},
35             {"gradienttransform", 17, "gradientTransform", 17},
36             {"gradientunits", 13, "gradientUnits", 13},
37             {"kernelmatrix", 12, "kernelMatrix", 12},
38             {"kernelunitlength", 16, "kernelUnitLength", 16},
39             {"keypoints", 9, "keyPoints", 9},
40             {"keysplines", 10, "keySplines", 10},
41             {"keytimes", 8, "keyTimes", 8},
42             {"lengthadjust", 12, "lengthAdjust", 12},
43             {"limitingconeangle", 17, "limitingConeAngle", 17},
44             {"markerheight", 12, "markerHeight", 12},
45             {"markerunits", 11, "markerUnits", 11},
46             {"markerwidth", 11, "markerWidth", 11},
47             {"maskcontentunits", 16, "maskContentUnits", 16},
48             {"maskunits", 9, "maskUnits", 9},
49             {"numoctaves", 10, "numOctaves", 10},
50             {"pathlength", 10, "pathLength", 10},
51             {"patterncontentunits", 19, "patternContentUnits", 19},
52             {"patterntransform", 16, "patternTransform", 16},
53             {"patternunits", 12, "patternUnits", 12},
54             {"pointsatx", 9, "pointsAtX", 9},
55             {"pointsaty", 9, "pointsAtY", 9},
56             {"pointsatz", 9, "pointsAtZ", 9},
57             {"preservealpha", 13, "preserveAlpha", 13},
58             {"preserveaspectratio", 19, "preserveAspectRatio", 19},
59             {"primitiveunits", 14, "primitiveUnits", 14},
60             {"refx", 4, "refX", 4},
61             {"refy", 4, "refY", 4},
62             {"repeatcount", 11, "repeatCount", 11},
63             {"repeatdur", 9, "repeatDur", 9},
64             {"requiredextensions", 18, "requiredExtensions", 18},
65             {"requiredfeatures", 16, "requiredFeatures", 16},
66             {"specularconstant", 16, "specularConstant", 16},
67             {"specularexponent", 16, "specularExponent", 16},
68             {"spreadmethod", 12, "spreadMethod", 12},
69             {"startoffset", 11, "startOffset", 11},
70             {"stddeviation", 12, "stdDeviation", 12},
71             {"stitchtiles", 11, "stitchTiles", 11},
72             {"surfacescale", 12, "surfaceScale", 12},
73             {"systemlanguage", 14, "systemLanguage", 14},
74             {"tablevalues", 11, "tableValues", 11},
75             {"targetx", 7, "targetX", 7},
76             {"targety", 7, "targetY", 7},
77             {"textlength", 10, "textLength", 10},
78             {"viewbox", 7, "viewBox", 7},
79             {"viewtarget", 10, "viewTarget", 10},
80             {"xchannelselector", 16, "xChannelSelector", 16},
81             {"ychannelselector", 16, "yChannelSelector", 16},
82             {"zoomandpan", 10, "zoomAndPan", 10}
83             };
84              
85             // all key size > value size
86             static const myhtml_token_namespace_replacement_t myhtml_token_attr_namespace_replacement[] = {
87             {"xlink:actuate", 13, "actuate", 7, MyHTML_NAMESPACE_XLINK},
88             {"xlink:arcrole", 13, "arcrole", 7, MyHTML_NAMESPACE_XLINK},
89             {"xlink:href", 10, "href", 4, MyHTML_NAMESPACE_XLINK},
90             {"xlink:role", 10, "role", 4, MyHTML_NAMESPACE_XLINK},
91             {"xlink:show", 10, "show", 4, MyHTML_NAMESPACE_XLINK},
92             {"xlink:title", 11, "title", 5, MyHTML_NAMESPACE_XLINK},
93             {"xlink:type", 10, "type", 4, MyHTML_NAMESPACE_XLINK},
94             {"xml:lang", 8, "lang", 4, MyHTML_NAMESPACE_XML},
95             {"xml:space", 9, "space", 5, MyHTML_NAMESPACE_XML},
96             {"xmlns", 5, "xmlns", 5, MyHTML_NAMESPACE_XMLNS},
97             {"xmlns:xlink", 11, "xlink", 5, MyHTML_NAMESPACE_XMLNS}
98             };
99              
100 145           myhtml_token_t * myhtml_token_create(myhtml_tree_t* tree, size_t size)
101             {
102 145 50         if(size == 0)
103 0           size = 4096;
104            
105 145           myhtml_token_t* token = (myhtml_token_t*)mycore_malloc(sizeof(myhtml_token_t));
106            
107 145 50         if(token == NULL)
108 0           return NULL;
109            
110 145           token->nodes_obj = mcobject_async_create();
111            
112 145 50         if(token->nodes_obj == NULL) {
113 0           mycore_free(token);
114 0           return NULL;
115             }
116            
117 145           token->attr_obj = mcobject_async_create();
118            
119 145 50         if(token->attr_obj == NULL) {
120 0           mycore_free(token->nodes_obj);
121 0           mycore_free(token);
122            
123 0           return NULL;
124             }
125            
126 145           mcobject_async_init(token->nodes_obj, 128, size, sizeof(myhtml_token_node_t));
127 145           mcobject_async_init(token->attr_obj, 128, size, sizeof(myhtml_token_attr_t));
128            
129 145           token->mcasync_token_id = mcobject_async_node_add(token->nodes_obj, NULL);
130 145           token->mcasync_attr_id = mcobject_async_node_add(token->attr_obj, NULL);
131            
132 145           token->tree = tree;
133            
134 145           return token;
135             }
136              
137 145           void myhtml_token_clean(myhtml_token_t* token)
138             {
139 145           mcobject_async_node_clean(token->nodes_obj, token->mcasync_token_id);
140 145           mcobject_async_node_clean(token->attr_obj, token->mcasync_attr_id);
141 145           }
142              
143 0           void myhtml_token_clean_all(myhtml_token_t* token)
144             {
145 0           mcobject_async_clean(token->nodes_obj);
146 0           mcobject_async_clean(token->attr_obj);
147 0           }
148              
149 144           myhtml_token_t * myhtml_token_destroy(myhtml_token_t* token)
150             {
151 144 50         if(token == NULL)
152 0           return NULL;
153            
154 144 50         if(token->nodes_obj)
155 144           token->nodes_obj = mcobject_async_destroy(token->nodes_obj, 1);
156            
157 144 50         if(token->attr_obj)
158 144           token->attr_obj = mcobject_async_destroy(token->attr_obj, 1);
159            
160 144           mycore_free(token);
161            
162 144           return NULL;
163             }
164              
165 2016           myhtml_token_node_t * myhtml_token_node_create(myhtml_token_t* token, size_t async_node_id)
166             {
167 2016           myhtml_token_node_t *token_node = (myhtml_token_node_t*)mcobject_async_malloc(token->nodes_obj, async_node_id, NULL);
168 2016 50         if(token_node == NULL)
169 0           return NULL;
170            
171 2016           myhtml_token_node_clean(token_node);
172 2016           return token_node;
173             }
174              
175 2016           void myhtml_token_node_clean(myhtml_token_node_t* node)
176             {
177 2016           memset(node, 0, sizeof(myhtml_token_node_t));
178 2016           node->type = MyHTML_TOKEN_TYPE_OPEN|MyHTML_TOKEN_TYPE_WHITESPACE;
179            
180 2016           mycore_string_clean_all(&node->str);
181 2016           }
182              
183 386           myhtml_token_attr_t * myhtml_token_attr_create(myhtml_token_t* token, size_t async_node_id)
184             {
185 386           myhtml_token_attr_t *attr_node = mcobject_async_malloc(token->attr_obj, async_node_id, NULL);
186 386 50         if(attr_node == NULL)
187 0           return NULL;
188            
189 386           myhtml_token_attr_clean(attr_node);
190 386           return attr_node;
191             }
192              
193 386           void myhtml_token_attr_clean(myhtml_token_attr_t* attr)
194             {
195 386           memset(attr, 0, sizeof(myhtml_token_attr_t));
196 386           attr->ns = MyHTML_NAMESPACE_HTML;
197            
198 386           mycore_string_clean_all(&attr->key);
199 386           mycore_string_clean_all(&attr->value);
200 386           }
201              
202 0           myhtml_tag_id_t myhtml_token_node_tag_id(myhtml_token_node_t *token_node)
203             {
204 0           return token_node->tag_id;
205             }
206              
207 0           myhtml_position_t myhtml_token_node_raw_position(myhtml_token_node_t *token_node)
208             {
209 0 0         if(token_node)
210 0           return (myhtml_position_t){token_node->raw_begin, token_node->raw_length};
211            
212 0           return (myhtml_position_t){0, 0};
213             }
214              
215 0           myhtml_position_t myhtml_token_node_element_position(myhtml_token_node_t *token_node)
216             {
217 0 0         if(token_node)
218 0           return (myhtml_position_t){token_node->element_begin, token_node->element_length};
219            
220 0           return (myhtml_position_t){0, 0};
221             }
222              
223 0           myhtml_tree_attr_t * myhtml_token_node_attribute_first(myhtml_token_node_t *token_node)
224             {
225 0           return token_node->attr_first;
226             }
227              
228 0           myhtml_tree_attr_t * myhtml_token_node_attribute_last(myhtml_token_node_t *token_node)
229             {
230 0           return token_node->attr_last;
231             }
232              
233 0           const char * myhtml_token_node_text(myhtml_token_node_t *token_node, size_t *length)
234             {
235 0 0         if(length)
236 0           *length = token_node->str.length;
237            
238 0           return token_node->str.data;
239             }
240              
241 0           mycore_string_t * myhtml_token_node_string(myhtml_token_node_t *token_node)
242             {
243 0           return &token_node->str;
244             }
245              
246 0           bool myhtml_token_node_is_close(myhtml_token_node_t *token_node)
247             {
248 0           return (token_node->type & MyHTML_TOKEN_TYPE_CLOSE);
249             }
250              
251 0           bool myhtml_token_node_is_close_self(myhtml_token_node_t *token_node)
252             {
253 0           return (token_node->type & MyHTML_TOKEN_TYPE_CLOSE_SELF);
254             }
255              
256 254           void myhtml_token_node_wait_for_done(myhtml_token_t* token, myhtml_token_node_t* node)
257             {
258             #ifndef MyCORE_BUILD_WITHOUT_THREADS
259 254 50         while((node->type & MyHTML_TOKEN_TYPE_DONE) == 0) {mythread_nanosleep_sleep(token->tree->myhtml->thread_stream->timespec);}
260             #endif
261 254           }
262              
263 17           void myhtml_token_set_done(myhtml_token_node_t* node)
264             {
265 17           node->type |= MyHTML_TOKEN_TYPE_DONE;
266 17           }
267              
268 0           myhtml_token_node_t * myhtml_token_node_clone(myhtml_token_t* token, myhtml_token_node_t* node, size_t token_thread_idx, size_t attr_thread_idx)
269             {
270 0 0         if(node == NULL)
271 0           return NULL;
272            
273 0           myhtml_tree_t* tree = token->tree;
274 0           myhtml_token_node_t* new_node = myhtml_token_node_create(token, token_thread_idx);
275            
276 0 0         if(new_node == NULL)
277 0           return NULL;
278            
279 0           new_node->tag_id = node->tag_id;
280 0           new_node->type = node->type;
281 0           new_node->attr_first = NULL;
282 0           new_node->attr_last = NULL;
283 0           new_node->raw_begin = node->raw_begin;
284 0           new_node->raw_length = node->raw_length;
285 0           new_node->element_begin = node->element_begin;
286 0           new_node->element_length = node->element_length;
287            
288 0 0         if(node->str.length) {
289 0           mycore_string_init(tree->mchar, tree->mchar_node_id, &new_node->str, node->str.length + 1);
290 0           mycore_string_append(&new_node->str, node->str.data, node->str.length);
291             } else {
292 0           mycore_string_clean_all(&new_node->str);
293             }
294            
295 0           myhtml_token_node_attr_copy(token, node, new_node, attr_thread_idx);
296            
297 0           return new_node;
298             }
299              
300 0           void myhtml_token_node_text_append(myhtml_token_t* token, myhtml_token_node_t* dest, const char* text, size_t text_len)
301             {
302 0           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &dest->str, (text_len + 2));
303            
304 0           mycore_string_t* string = &dest->str;
305 0           mycore_string_append(string, text, text_len);
306 0           }
307              
308 0           myhtml_token_attr_t * myhtml_token_node_attr_append(myhtml_token_t* token, myhtml_token_node_t* dest,
309             const char* key, size_t key_len,
310             const char* value, size_t value_len, size_t thread_idx)
311             {
312 0           myhtml_token_attr_t* new_attr = mcobject_async_malloc(token->attr_obj, thread_idx, NULL);
313 0           new_attr->next = 0;
314            
315 0 0         if(key_len) {
316 0           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->key, (key_len + 1));
317 0           mycore_string_append_lowercase(&new_attr->key, key, key_len);
318             }
319             else
320 0           mycore_string_clean_all(&new_attr->key);
321            
322 0 0         if(value_len) {
323 0           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->value, (value_len + 1));
324 0           mycore_string_append(&new_attr->value, value, value_len);
325             }
326             else
327 0           mycore_string_clean_all(&new_attr->value);
328            
329 0 0         if(dest->attr_first == NULL) {
330 0           new_attr->prev = 0;
331            
332 0           dest->attr_first = new_attr;
333 0           dest->attr_last = new_attr;
334             }
335             else {
336 0           dest->attr_last->next = new_attr;
337 0           new_attr->prev = dest->attr_last;
338            
339 0           dest->attr_last = new_attr;
340             }
341            
342 0           new_attr->ns = MyHTML_NAMESPACE_HTML;
343            
344 0           return new_attr;
345             }
346              
347 63           myhtml_token_attr_t * myhtml_token_node_attr_append_with_convert_encoding(myhtml_token_t* token, myhtml_token_node_t* dest,
348             const char* key, size_t key_len,
349             const char* value, size_t value_len,
350             size_t thread_idx, myencoding_t encoding)
351             {
352 63           myhtml_token_attr_t* new_attr = mcobject_async_malloc(token->attr_obj, thread_idx, NULL);
353 63           new_attr->next = 0;
354            
355 63 100         if(key_len) {
356 26           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->key, (key_len + 1));
357            
358 26 50         if(encoding == MyENCODING_UTF_8)
359 26           mycore_string_append_lowercase(&new_attr->key, key, key_len);
360             else
361 26           myencoding_string_append_lowercase_ascii(&new_attr->key, key, key_len, encoding);
362             }
363             else
364 37           mycore_string_clean_all(&new_attr->key);
365            
366 63 100         if(value_len) {
367 40           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->value, (value_len + 1));
368            
369 40 50         if(encoding == MyENCODING_UTF_8)
370 40           mycore_string_append(&new_attr->value, value, value_len);
371             else
372 40           myencoding_string_append(&new_attr->value, value, value_len, encoding);
373             }
374             else
375 23           mycore_string_clean_all(&new_attr->value);
376            
377 63 100         if(dest->attr_first == NULL) {
378 5           new_attr->prev = 0;
379            
380 5           dest->attr_first = new_attr;
381 5           dest->attr_last = new_attr;
382             }
383             else {
384 58           dest->attr_last->next = new_attr;
385 58           new_attr->prev = dest->attr_last;
386            
387 58           dest->attr_last = new_attr;
388             }
389            
390 63           new_attr->ns = MyHTML_NAMESPACE_HTML;
391            
392 63           return new_attr;
393             }
394              
395 0           void myhtml_token_node_attr_copy_with_check(myhtml_token_t* token, myhtml_token_node_t* target, myhtml_token_node_t* dest, size_t thread_idx)
396             {
397 0           myhtml_token_attr_t* attr = target->attr_first;
398            
399 0 0         while (attr)
400             {
401 0 0         if(attr->key.length && myhtml_token_attr_by_name(dest, attr->key.data, attr->key.length) == NULL) {
    0          
402 0           myhtml_token_attr_copy(token, attr, dest, thread_idx);
403             }
404            
405 0           attr = attr->next;
406             }
407 0           }
408              
409 0           void myhtml_token_node_attr_copy(myhtml_token_t* token, myhtml_token_node_t* target, myhtml_token_node_t* dest, size_t thread_idx)
410             {
411 0           myhtml_token_attr_t* attr = target->attr_first;
412            
413 0 0         while (attr)
414             {
415 0           myhtml_token_attr_copy(token, attr, dest, thread_idx);
416 0           attr = attr->next;
417             }
418 0           }
419              
420 15           bool myhtml_token_attr_copy(myhtml_token_t* token, myhtml_token_attr_t* attr, myhtml_token_node_t* dest, size_t thread_idx)
421             {
422 15           myhtml_token_attr_t* new_attr = mcobject_async_malloc(token->attr_obj, thread_idx, NULL);
423 15           new_attr->next = 0;
424            
425 15 50         if(attr->key.length) {
426 15           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->key, (attr->key.length + 1));
427 15           mycore_string_append_lowercase(&new_attr->key, attr->key.data, attr->key.length);
428             }
429             else
430 0           mycore_string_clean_all(&new_attr->key);
431            
432 15 50         if(attr->value.length) {
433 15           mycore_string_init(token->tree->mchar, token->tree->mchar_node_id, &new_attr->value, (attr->value.length + 1));
434 15           mycore_string_append(&new_attr->value, attr->value.data, attr->value.length);
435             }
436             else
437 0           mycore_string_clean_all(&new_attr->value);
438            
439 15 50         if(dest->attr_first == NULL) {
440 15           new_attr->prev = 0;
441            
442 15           dest->attr_first = new_attr;
443 15           dest->attr_last = new_attr;
444             }
445             else {
446 0           dest->attr_last->next = new_attr;
447 0           new_attr->prev = dest->attr_last;
448            
449 0           dest->attr_last = new_attr;
450             }
451            
452 15           new_attr->ns = attr->ns;
453            
454 15           return true;
455             }
456              
457 0           myhtml_token_attr_t * myhtml_token_attr_match(myhtml_token_t* token, myhtml_token_node_t* target,
458             const char* key, size_t key_size, const char* value, size_t value_size)
459             {
460 0           myhtml_token_attr_t* attr = target->attr_first;
461            
462 0 0         while (attr)
463             {
464 0 0         if(attr->key.length == key_size && attr->value.length == value_size)
    0          
465             {
466 0 0         if((mycore_strcmp(attr->key.data, key) == 0)) {
467 0 0         if((mycore_strcmp(attr->value.data, value) == 0))
468 0           return attr;
469             else
470 0           return NULL;
471             }
472             }
473            
474 0           attr = attr->next;
475             }
476            
477 0           return NULL;
478             }
479              
480 0           myhtml_token_attr_t * myhtml_token_attr_match_case(myhtml_token_t* token, myhtml_token_node_t* target,
481             const char* key, size_t key_size, const char* value, size_t value_size)
482             {
483 0           myhtml_token_attr_t* attr = target->attr_first;
484            
485 0 0         while (attr)
486             {
487 0 0         if(attr->key.length == key_size && attr->value.length == value_size)
    0          
488             {
489 0 0         if((mycore_strcmp(attr->key.data, key) == 0)) {
490 0 0         if((mycore_strcasecmp(attr->value.data, value) == 0))
491 0           return attr;
492             else
493 0           return NULL;
494             }
495             }
496            
497 0           attr = attr->next;
498             }
499            
500 0           return NULL;
501             }
502              
503 0           void myhtml_token_adjust_mathml_attributes(myhtml_token_node_t* target)
504             {
505 0           myhtml_token_attr_t* attr = myhtml_token_attr_by_name(target, "definitionurl", 13);
506            
507 0 0         if(attr) {
508 0           memcpy(attr->key.data, "definitionURL", 13);
509             }
510 0           }
511              
512 74           void _myhtml_token_create_copy_srt(myhtml_token_t* token, const char* from, size_t from_size, char** to)
513             {
514 74           *to = mchar_async_malloc(token->tree->mchar, token->tree->mchar_node_id, (from_size + 2));
515 74           mycore_string_raw_copy(*to, from, from_size);
516 74           }
517              
518 36           void myhtml_token_strict_doctype_by_token(myhtml_token_t* token, myhtml_token_node_t* target, myhtml_tree_doctype_t* return_doctype)
519             {
520 36           myhtml_token_attr_t* attr = target->attr_first;
521            
522 36 100         if(attr && attr->key.length) {
    50          
523 33           _myhtml_token_create_copy_srt(token, attr->key.data, attr->key.length, &return_doctype->attr_name);
524            
525 66 100         if(mycore_strcmp("html", return_doctype->attr_name))
526 2           return_doctype->is_html = false;
527             else
528 31           return_doctype->is_html = true;
529             }
530             else {
531 3           return_doctype->is_html = false;
532            
533 3           _myhtml_token_create_copy_srt(token, "\0", 1, &return_doctype->attr_name);
534            
535 3 50         if(return_doctype->attr_public)
536 0           mycore_free(return_doctype->attr_public);
537 3           return_doctype->attr_public = NULL;
538            
539 3 50         if(return_doctype->attr_system)
540 0           mycore_free(return_doctype->attr_system);
541 3           return_doctype->attr_system = NULL;
542            
543 3           return;
544             }
545            
546 33           attr = attr->next;
547            
548 33 100         if(attr && attr->value.length)
    50          
549             {
550 22 100         if(mycore_strcasecmp(attr->value.data, "PUBLIC") == 0)
551             {
552             // try see public
553 16           attr = attr->next;
554            
555 16 100         if(attr && attr->value.length) {
    100          
556 14           _myhtml_token_create_copy_srt(token, attr->value.data, attr->value.length, &return_doctype->attr_public);
557            
558             // try see system
559 14           attr = attr->next;
560            
561 28 100         if(attr && attr->value.length)
    50          
562 9           _myhtml_token_create_copy_srt(token, attr->value.data, attr->value.length, &return_doctype->attr_system);
563             else {
564 5 50         if(return_doctype->attr_system)
565 0           mycore_free(return_doctype->attr_system);
566            
567 5           _myhtml_token_create_copy_srt(token, "\0", 1, &return_doctype->attr_system);
568             }
569             }
570             else {
571 2 50         if(return_doctype->attr_public)
572 0           mycore_free(return_doctype->attr_public);
573 2           return_doctype->attr_public = NULL;
574            
575 2 50         if(return_doctype->attr_system)
576 0           mycore_free(return_doctype->attr_system);
577 16           return_doctype->attr_system = NULL;
578             }
579             }
580 6 50         else if(mycore_strncasecmp(attr->value.data, "SYSTEM", attr->value.length) == 0)
581             {
582 6           attr = attr->next;
583            
584 6 100         if(attr && attr->value.length) {
    50          
585 5           _myhtml_token_create_copy_srt(token, "\0", 1, &return_doctype->attr_public);
586 5           _myhtml_token_create_copy_srt(token, attr->value.data, attr->value.length, &return_doctype->attr_system);
587             }
588             else {
589 1 50         if(return_doctype->attr_public)
590 0           mycore_free(return_doctype->attr_public);
591 1           return_doctype->attr_public = NULL;
592            
593 1 50         if(return_doctype->attr_system)
594 0           mycore_free(return_doctype->attr_system);
595 6           return_doctype->attr_system = NULL;
596             }
597             }
598             else {
599 0 0         if(return_doctype->attr_public)
600 0           mycore_free(return_doctype->attr_public);
601 0           return_doctype->attr_public = NULL;
602            
603 0 0         if(return_doctype->attr_system)
604 0           mycore_free(return_doctype->attr_system);
605 0           return_doctype->attr_system = NULL;
606             }
607             }
608             }
609              
610 18           bool myhtml_token_doctype_check_html_4_0(myhtml_tree_doctype_t* return_doctype)
611             {
612 34 100         return mycore_strcmp(return_doctype->attr_public, "-//W3C//DTD HTML 4.0//EN") &&
    50          
613 16 50         (return_doctype->attr_system == NULL || mycore_strcmp(return_doctype->attr_system, "http://www.w3.org/TR/REC-html40/strict.dtd"));
614             }
615              
616 16           bool myhtml_token_doctype_check_html_4_01(myhtml_tree_doctype_t* return_doctype)
617             {
618 30 100         return mycore_strcmp(return_doctype->attr_public, "-//W3C//DTD HTML 4.01//EN") &&
    50          
619 14 50         (return_doctype->attr_system == NULL || mycore_strcmp(return_doctype->attr_system, "http://www.w3.org/TR/html4/strict.dtd"));
620             }
621              
622 14           bool myhtml_token_doctype_check_xhtml_1_0(myhtml_tree_doctype_t* return_doctype)
623             {
624 14 50         if(return_doctype->attr_system == NULL)
625 0           return true;
626            
627 26           return mycore_strcmp(return_doctype->attr_public, "-//W3C//DTD XHTML 1.0 Strict//EN") &&
628 12           mycore_strcmp(return_doctype->attr_system, "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
629             }
630              
631 12           bool myhtml_token_doctype_check_xhtml_1_1(myhtml_tree_doctype_t* return_doctype)
632             {
633 12 50         if(return_doctype->attr_system == NULL)
634 0           return true;
635            
636 23           return mycore_strcmp(return_doctype->attr_public, "-//W3C//DTD XHTML 1.1//EN") &&
637 11           mycore_strcmp(return_doctype->attr_system, "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd");
638             }
639              
640 36           bool myhtml_token_release_and_check_doctype_attributes(myhtml_token_t* token, myhtml_token_node_t* target, myhtml_tree_doctype_t* return_doctype)
641             {
642 36 50         if(return_doctype == NULL)
643 0           return false;
644            
645 36           myhtml_token_strict_doctype_by_token(token, target, return_doctype);
646            
647 36 50         if(return_doctype->attr_name == NULL)
648 0           return false;
649            
650 36 100         if((return_doctype->is_html ||
    100          
651 4 50         return_doctype->attr_public ||
652 0 0         (return_doctype->attr_system && mycore_strcmp(return_doctype->attr_system, "about:legacy-compat"))))
653             {
654 32 100         if(return_doctype->attr_public == NULL)
655 13           return false;
656            
657 37           if(return_doctype->is_html &&
658 34 100         myhtml_token_doctype_check_html_4_0(return_doctype) &&
659 30 100         myhtml_token_doctype_check_html_4_01(return_doctype) &&
660 26 100         myhtml_token_doctype_check_xhtml_1_0(return_doctype) &&
661 12           myhtml_token_doctype_check_xhtml_1_1(return_doctype))
662             {
663 11           return false;
664             }
665             }
666            
667 12           return true;
668             }
669              
670 0           void myhtml_token_adjust_svg_attributes(myhtml_token_node_t* target)
671             {
672 0           size_t count = sizeof(myhtml_token_attr_svg_replacement) / sizeof(myhtml_token_replacement_entry_t);
673            
674 0 0         for (size_t i = 0; i < count; i++)
675             {
676 0           myhtml_token_attr_t* attr = myhtml_token_attr_by_name(target, myhtml_token_attr_svg_replacement[i].from,
677             myhtml_token_attr_svg_replacement[i].from_size);
678            
679 0 0         if(attr) {
680 0           mycore_string_clean(&attr->key);
681 0           mycore_string_append(&attr->key, myhtml_token_attr_svg_replacement[i].to,
682             myhtml_token_attr_svg_replacement[i].to_size);
683             }
684             }
685 0           }
686              
687 0           void myhtml_token_adjust_foreign_attributes(myhtml_token_node_t* target)
688             {
689 0           size_t count = sizeof(myhtml_token_attr_namespace_replacement) / sizeof(myhtml_token_namespace_replacement_t);
690            
691 0 0         for (size_t i = 0; i < count; i++)
692             {
693 0           myhtml_token_attr_t* attr = myhtml_token_attr_by_name(target, myhtml_token_attr_namespace_replacement[i].from,
694             myhtml_token_attr_namespace_replacement[i].from_size);
695            
696 0 0         if(attr) {
697 0           mycore_string_clean(&attr->key);
698 0           mycore_string_append(&attr->key, myhtml_token_attr_namespace_replacement[i].to,
699             myhtml_token_attr_namespace_replacement[i].to_size);
700            
701 0           attr->ns = myhtml_token_attr_namespace_replacement[i].ns;
702             }
703             }
704 0           }
705              
706 0           bool myhtml_token_attr_compare(myhtml_token_node_t* target, myhtml_token_node_t* dest)
707             {
708 0 0         if(target == NULL || dest == NULL)
    0          
709 0           return false;
710            
711 0           myhtml_token_attr_t* target_attr = target->attr_first;
712 0           myhtml_token_attr_t* dest_attr = dest->attr_first;
713            
714 0 0         while (target_attr && dest_attr)
    0          
715             {
716 0 0         if(target_attr->key.length == dest_attr->key.length &&
    0          
717 0           target_attr->value.length == dest_attr->value.length)
718             {
719 0 0         if(mycore_strcmp(target_attr->key.data, dest_attr->key.data) != 0)
720 0           break;
721            
722 0 0         if(mycore_strcasecmp(target_attr->value.data, dest_attr->value.data) != 0)
723 0           break;
724             }
725             else
726             break;
727            
728 0           target_attr = target_attr->next;
729 0           dest_attr = dest_attr->next;
730             }
731            
732 0 0         if(target_attr == NULL && dest_attr == NULL)
    0          
733 0           return true;
734            
735 0           return false;
736             }
737              
738 140           myhtml_token_attr_t * myhtml_token_attr_by_name(myhtml_token_node_t* node, const char* name, size_t name_length)
739             {
740 140           myhtml_token_attr_t* attr = node->attr_first;
741            
742 353 100         while (attr)
743             {
744 315 100         if(name_length == attr->key.length) {
745 104 100         if(mycore_strcmp(attr->key.data, name) == 0)
746 102           break;
747             }
748            
749 213           attr = attr->next;
750             }
751            
752 140           return attr;
753             }
754              
755 138           void myhtml_token_delete(myhtml_token_t* token, myhtml_token_node_t* node)
756             {
757 138 100         if(node->str.data && node->str.mchar) {
    50          
758 87           mchar_async_free(node->str.mchar, node->str.node_idx, node->str.data);
759             }
760            
761 138           mcobject_async_free(token->nodes_obj, node);
762 138           }
763              
764 138           void myhtml_token_attr_delete_all(myhtml_token_t* token, myhtml_token_node_t* node)
765             {
766 138           myhtml_token_attr_t* attr = node->attr_first;
767            
768 169 100         while (attr)
769             {
770 31 50         if(attr->key.data && attr->key.mchar) {
    50          
771 31           mchar_async_free(attr->key.mchar, attr->key.node_idx, attr->key.data);
772             }
773            
774 31 50         if(attr->value.data && attr->value.mchar) {
    50          
775 31           mchar_async_free(attr->value.mchar, attr->value.node_idx, attr->value.data);
776             }
777            
778 31           attr = attr->next;
779             }
780 138           }
781              
782 53           myhtml_token_attr_t * myhtml_token_attr_remove(myhtml_token_node_t* node, myhtml_token_attr_t* attr)
783             {
784 53 50         if(attr)
785             {
786 53 100         if(attr->prev) {
787 13           attr->prev->next = attr->next;
788             }
789             else {
790 40           node->attr_first = attr->next;
791             }
792            
793 53 100         if(attr->next) {
794 41           attr->next->prev = attr->prev;
795             }
796             else {
797 12           node->attr_last = attr->prev;
798             }
799            
800 53           attr->next = NULL;
801 53           attr->prev = NULL;
802             }
803            
804 53           return attr;
805             }
806              
807 20           myhtml_token_attr_t * myhtml_token_attr_remove_by_name(myhtml_token_node_t* node, const char* name, size_t name_length)
808             {
809 20           return myhtml_token_attr_remove(node, myhtml_token_attr_by_name(node, name, name_length));
810             }
811              
812 0           myhtml_token_node_t * myhtml_token_merged_two_token_string(myhtml_tree_t* tree, myhtml_token_node_t* token_to, myhtml_token_node_t* token_from, bool cp_reverse)
813             {
814 0           myhtml_token_node_wait_for_done(tree->token, token_to);
815 0           myhtml_token_node_wait_for_done(tree->token, token_from);
816            
817 0           mycore_string_t *string1 = &token_to->str;
818 0           mycore_string_t *string2 = &token_from->str;
819            
820 0           token_to->raw_begin = 0;
821 0           token_to->raw_length = 0;
822            
823 0 0         if(token_to->str.node_idx == tree->mchar_node_id)
824             {
825 0 0         if(cp_reverse) {
826             //mycore_string_copy(string2, &string_base);
827             }
828             else {
829 0           mycore_string_copy(string1, string2);
830             }
831            
832 0           return token_to;
833             }
834 0 0         if(token_from->str.node_idx == tree->mchar_node_id)
835             {
836 0 0         if(cp_reverse) {
837 0           mycore_string_copy(string2, string1);
838             }
839             else {
840 0           mycore_string_copy(string1, string2);
841             }
842            
843 0           return token_from;
844             }
845             else {
846             mycore_string_t string_base;
847 0           mycore_string_init(tree->mchar, tree->mchar_node_id, &string_base, (string1->length + string2->length + 2));
848            
849 0 0         if(cp_reverse) {
850 0           mycore_string_copy(&string_base, string2);
851 0           mycore_string_copy(&string_base, string1);
852             }
853             else {
854 0           mycore_string_copy(&string_base, string1);
855 0           mycore_string_copy(&string_base, string2);
856             }
857            
858 0           token_to->str = string_base;
859             }
860            
861 0           return token_to;
862             }
863              
864 0           void myhtml_token_set_replacement_character_for_null_token(myhtml_tree_t* tree, myhtml_token_node_t* node)
865             {
866 0           myhtml_token_node_wait_for_done(tree->token, node);
867            
868             mycore_string_t new_str;
869 0           mycore_string_init(tree->mchar, tree->mchar_node_id, &new_str, (node->str.length + 2));
870            
871 0           mycore_string_append_with_replacement_null_characters(&new_str, node->str.data, node->str.length);
872            
873 0           node->str = new_str;
874 0           }
875