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/tokenizer_global.h"
22 #include "mycss/tokenizer_resource.h"
23 #include "mycore/utils/resources.h"
24 
25 /////////////////////////////////////////////////////////
26 //// Global back
27 ////
28 /////////////////////////////////////////////////////////
mycss_tokenizer_global_back(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)29 size_t mycss_tokenizer_global_back(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
30 {
31     MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
32 
33     entry->state = MyCSS_TOKENIZER_STATE_DATA;
34     return css_offset;
35 }
36 
37 /////////////////////////////////////////////////////////
38 //// Consume a numeric
39 ////
40 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_numeric(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)41 size_t mycss_tokenizer_global_state_numeric(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
42 {
43     if(css[css_offset] == '%')
44     {
45         css_offset++;
46 
47         token->length = (entry->current_buffer->offset + css_offset) - token->begin;
48         token->type   = MyCSS_TOKEN_TYPE_PERCENTAGE;
49 
50         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
51 
52         entry->state = MyCSS_TOKENIZER_STATE_DATA;
53         return css_offset;
54     }
55     else if(css[css_offset] == '-') {
56         css_offset++;
57 
58         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMERIC_MINUS;
59     }
60     else if(css[css_offset] == '\\') {
61         css_offset++;
62 
63         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMERIC_RSOLIDUS;
64     }
65     else if(mycss_begin_chars_state_map[ (const unsigned char)(css[css_offset]) ] == MyCSS_TOKENIZER_STATE_NAME_START_CODE_POINT) {
66         css_offset++;
67 
68         token->type = MyCSS_TOKEN_TYPE_DIMENSION;
69 
70         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME;
71         entry->state_back = MyCSS_TOKENIZER_GLOBAL_BACK;
72     }
73     else
74     {
75         token->length = (entry->current_buffer->offset + css_offset) - token->begin;
76         token->type   = MyCSS_TOKEN_TYPE_NUMBER;
77 
78         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
79 
80         entry->state = MyCSS_TOKENIZER_STATE_DATA;
81     }
82 
83     return css_offset;
84 }
85 
mycss_tokenizer_global_state_numeric_minus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)86 size_t mycss_tokenizer_global_state_numeric_minus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
87 {
88     if(mycss_begin_chars_state_map[ (const unsigned char)(css[css_offset]) ] == MyCSS_TOKENIZER_STATE_NAME_START_CODE_POINT) {
89         css_offset++;
90 
91         token->type = MyCSS_TOKEN_TYPE_DIMENSION;
92 
93         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME;
94         entry->state_back = MyCSS_TOKENIZER_GLOBAL_BACK;
95     }
96     else if(css[css_offset] == '\\') {
97         css_offset++;
98 
99         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMERIC_MINUS_RSOLIDUS;
100     }
101     else {
102         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
103         token->type   = MyCSS_TOKEN_TYPE_NUMBER;
104 
105         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
106 
107         entry->state = MyCSS_TOKENIZER_STATE_DATA;
108         css_offset = mycss_tokenizer_state_set_current_buffer_for_continue(entry, css_offset, 1);
109     }
110 
111     return css_offset;
112 }
113 
mycss_tokenizer_global_state_numeric_minus_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)114 size_t mycss_tokenizer_global_state_numeric_minus_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
115 {
116     if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
117         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 2;
118         token->type   = MyCSS_TOKEN_TYPE_NUMBER;
119 
120         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
121 
122         entry->state = MyCSS_TOKENIZER_STATE_DATA;
123         css_offset = mycss_tokenizer_state_set_current_buffer_for_continue(entry, css_offset, 2);
124     }
125     else {
126         css_offset++;
127 
128         token->type = MyCSS_TOKEN_TYPE_DIMENSION;
129 
130         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME;
131         entry->state_back = MyCSS_TOKENIZER_GLOBAL_BACK;
132     }
133 
134     return css_offset;
135 }
136 
mycss_tokenizer_global_state_numeric_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)137 size_t mycss_tokenizer_global_state_numeric_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
138 {
139     if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
140         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
141         token->type   = MyCSS_TOKEN_TYPE_NUMBER;
142 
143         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
144 
145         entry->state = MyCSS_TOKENIZER_STATE_DATA;
146         css_offset = mycss_tokenizer_state_set_current_buffer_for_continue(entry, css_offset, 1);
147     }
148     else {
149         css_offset++;
150 
151         token->type = MyCSS_TOKEN_TYPE_DIMENSION;
152 
153         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME;
154         entry->state_back = MyCSS_TOKENIZER_GLOBAL_BACK;
155     }
156 
157     return css_offset;
158 }
159 
160 /////////////////////////////////////////////////////////
161 //// Consume a number
162 ////
163 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_number_digit(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)164 size_t mycss_tokenizer_global_state_number_digit(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
165 {
166     while(css_offset < css_size)
167     {
168         if(css[css_offset] < '0' || css[css_offset] > '9')
169         {
170             if(css[css_offset] == '.') {
171                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_DOT;
172 
173                 css_offset++;
174                 break;
175             }
176             else if(css[css_offset] == 'E' || css[css_offset] == 'e') {
177                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_E;
178 
179                 css_offset++;
180                 break;
181             }
182             else {
183                 token->length = (entry->current_buffer->offset + css_offset) - token->begin;
184 
185                 entry->state = entry->state_back;
186                 break;
187             }
188         }
189 
190         css_offset++;
191     }
192 
193     return css_offset;
194 }
195 
mycss_tokenizer_global_state_number_dot(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)196 size_t mycss_tokenizer_global_state_number_dot(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
197 {
198     if(css[css_offset] >= '0' && css[css_offset] <= '9') {
199         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_DECIMAL;
200         css_offset++;
201     }
202     else {
203         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
204         entry->state = entry->state_back;
205     }
206 
207     return css_offset;
208 }
209 
mycss_tokenizer_global_state_number_decimal(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)210 size_t mycss_tokenizer_global_state_number_decimal(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
211 {
212     while(css_offset < css_size)
213     {
214         if(css[css_offset] < '0' || css[css_offset] > '9')
215         {
216             if(css[css_offset] == 'E' || css[css_offset] == 'e') {
217                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_E;
218 
219                 css_offset++;
220                 break;
221             }
222             else {
223                 token->length = (entry->current_buffer->offset + css_offset) - token->begin;
224                 entry->state = entry->state_back;
225                 break;
226             }
227         }
228 
229         css_offset++;
230     }
231 
232     return css_offset;
233 }
234 
mycss_tokenizer_global_state_number_e(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)235 size_t mycss_tokenizer_global_state_number_e(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
236 {
237     if(css[css_offset] == '+' || css[css_offset] == '-') {
238         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_E_PLUS_MINUS;
239         css_offset++;
240     }
241     else if(css[css_offset] >= '0' && css[css_offset] <= '9') {
242         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_E_DECIMAL;
243         css_offset++;
244     }
245     else {
246         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
247         entry->state = entry->state_back;
248     }
249 
250     return css_offset;
251 }
252 
mycss_tokenizer_global_state_number_e_plus_minus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)253 size_t mycss_tokenizer_global_state_number_e_plus_minus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
254 {
255     if(css[css_offset] >= '0' && css[css_offset] <= '9') {
256         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NUMBER_E_DECIMAL;
257         css_offset++;
258     }
259     else {
260         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 2;
261         entry->state = entry->state_back;
262     }
263 
264     return css_offset;
265 }
266 
mycss_tokenizer_global_state_number_e_decimal(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)267 size_t mycss_tokenizer_global_state_number_e_decimal(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
268 {
269     while(css_offset < css_size)
270     {
271         if(css[css_offset] < '0' || css[css_offset] > '9')
272         {
273             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
274             entry->state = entry->state_back;
275             break;
276         }
277 
278         css_offset++;
279     }
280 
281     return css_offset;
282 }
283 
284 /////////////////////////////////////////////////////////
285 //// Consume a url token
286 ////
287 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_url(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)288 size_t mycss_tokenizer_global_state_url(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
289 {
290     while(css_offset < css_size)
291     {
292         if(css[css_offset] != '\r' && css[css_offset] != 0x0C &&
293            css[css_offset] != '\n' && css[css_offset] != '\t' && css[css_offset] != ' ')
294         {
295             if(css[css_offset] == '"') {
296                 css_offset++;
297 
298                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_DOUBLE_QUOTED;
299                 entry->state_back = MyCSS_TOKENIZER_GLOBAL_STATE_URL_STRING_BACK;
300 
301                 token->begin = entry->current_buffer->offset + css_offset;
302                 break;
303             }
304             else if(css[css_offset] == '\'') {
305                 css_offset++;
306 
307                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_SINGLE_QUOTED;
308                 entry->state_back = MyCSS_TOKENIZER_GLOBAL_STATE_URL_STRING_BACK;
309 
310                 token->begin = entry->current_buffer->offset + css_offset;
311                 break;
312             }
313 
314             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_URL_AFTER;
315 
316             token->begin = entry->current_buffer->offset + css_offset;
317             break;
318         }
319 
320         ++css_offset;
321     }
322 
323     return css_offset;
324 }
325 
mycss_tokenizer_global_state_url_string_back(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)326 size_t mycss_tokenizer_global_state_url_string_back(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
327 {
328     if(token->type == MyCSS_TOKEN_TYPE_BAD_STRING)
329         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_BAD_URL;
330     else
331         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_URL_AFTER_WHITESPACE;
332 
333     return css_offset;
334 }
335 
mycss_tokenizer_global_state_url_after(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)336 size_t mycss_tokenizer_global_state_url_after(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
337 {
338     const unsigned char *u_css = (const unsigned char*)css;
339 
340     while(css_offset < css_size)
341     {
342         if(css[css_offset] == ')') {
343             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
344             token->type   = MyCSS_TOKEN_TYPE_URL;
345 
346             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
347 
348             entry->state = MyCSS_TOKENIZER_STATE_DATA;
349 
350             css_offset++;
351             break;
352         }
353         else if(css[css_offset] == '\r' || css[css_offset] == 0x0C ||
354                 css[css_offset] == '\n' || css[css_offset] == '\t' || css[css_offset] == ' ')
355         {
356             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_URL_AFTER_WHITESPACE;
357 
358             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
359 
360             css_offset++;
361             break;
362         }
363         else if(css[css_offset] == '"' || css[css_offset] == '\'' || css[css_offset] == '(' ||
364                 // non-printable code point
365                 u_css[css_offset] == 0x00 || u_css[css_offset] == 0x08 || u_css[css_offset] == 0x0B ||
366                 u_css[css_offset] == 0x7F || (u_css[css_offset] >= 0x0E && u_css[css_offset] <= 0x1F))
367         {
368             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_BAD_URL;
369 
370             css_offset++;
371             break;
372         }
373         else if(css[css_offset] == '\\') {
374             css_offset++;
375 
376             break;
377         }
378 
379         ++css_offset;
380     }
381 
382     return css_offset;
383 }
384 
mycss_tokenizer_global_state_url_after_whitespace(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)385 size_t mycss_tokenizer_global_state_url_after_whitespace(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
386 {
387     while(css_offset < css_size)
388     {
389         if(css[css_offset] != '\r' && css[css_offset] != 0x0C &&
390            css[css_offset] != '\n' && css[css_offset] != '\t' && css[css_offset] != ' ')
391         {
392             if(css[css_offset] == ')') {
393                 token->type = MyCSS_TOKEN_TYPE_URL;
394 
395                 MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
396 
397                 entry->state = MyCSS_TOKENIZER_STATE_DATA;
398 
399                 css_offset++;
400                 break;
401             }
402 
403             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_BAD_URL;
404             break;
405         }
406 
407         ++css_offset;
408     }
409 
410     return css_offset;
411 }
412 
mycss_tokenizer_global_state_url_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)413 size_t mycss_tokenizer_global_state_url_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
414 {
415     if(css[css_offset] != '\n' && css[css_offset] != '\r' && css[css_offset] != 0x0C) {
416         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_URL_AFTER;
417         return (css_offset + 1);
418     }
419 
420     entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_BAD_URL;
421 
422     return css_offset;
423 }
424 
mycss_tokenizer_global_state_bad_url(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)425 size_t mycss_tokenizer_global_state_bad_url(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
426 {
427     while(css_offset < css_size)
428     {
429         if(css[css_offset] == ')') {
430             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
431             token->type   = MyCSS_TOKEN_TYPE_BAD_URL;
432 
433             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
434 
435             entry->state = MyCSS_TOKENIZER_STATE_DATA;
436 
437             css_offset++;
438             break;
439         }
440 //        else if(css[css_offset] == '\\') {
441 //            css_offset++;
442 //            break;
443 //        }
444 
445         ++css_offset;
446     }
447 
448     return css_offset;
449 }
450 
451 /////////////////////////////////////////////////////////
452 //// Consume a string token
453 ////
454 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_string_double_quoted(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)455 size_t mycss_tokenizer_global_state_string_double_quoted(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
456 {
457     while(css_offset < css_size)
458     {
459         if(css[css_offset] == '"')
460         {
461             token->type   = MyCSS_TOKEN_TYPE_STRING;
462             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
463 
464             // skip QUOTATION MARK (")
465             ++css_offset;
466             entry->state = entry->state_back;
467             break;
468         }
469         else if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
470             token->type   = MyCSS_TOKEN_TYPE_BAD_STRING;
471             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
472 
473             entry->state = entry->state_back;
474             break;
475         }
476         else if(css[css_offset] == '\\') {
477             css_offset++;
478 
479             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_DOUBLE_QUOTED_RSOLIDUS;
480             break;
481         }
482 
483         ++css_offset;
484     }
485 
486     return css_offset;
487 }
488 
mycss_tokenizer_global_state_string_double_quoted_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)489 size_t mycss_tokenizer_global_state_string_double_quoted_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
490 {
491     if(css[css_offset] == '\r')
492         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_DOUBLE_QUOTED_RSOLIDUS_R;
493     else
494         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_DOUBLE_QUOTED;
495 
496     css_offset++;
497     return css_offset;
498 }
499 
mycss_tokenizer_global_state_string_double_quoted_rsolidus_r(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)500 size_t mycss_tokenizer_global_state_string_double_quoted_rsolidus_r(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
501 {
502     if(css[css_offset] == '\n')
503         css_offset++;
504 
505     entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_DOUBLE_QUOTED;
506 
507     return css_offset;
508 }
509 
mycss_tokenizer_global_state_string_single_quoted(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)510 size_t mycss_tokenizer_global_state_string_single_quoted(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
511 {
512     while(css_offset < css_size)
513     {
514         if(css[css_offset] == '\'')
515         {
516             token->type   = MyCSS_TOKEN_TYPE_STRING;
517             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
518 
519             // skip APOSTROPHE (')
520             ++css_offset;
521 
522             entry->state = entry->state_back;
523             break;
524         }
525         else if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
526             token->type   = MyCSS_TOKEN_TYPE_BAD_STRING;
527             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
528 
529             entry->state = entry->state_back;
530             break;
531         }
532         else if(css[css_offset] == '\\') {
533             css_offset++;
534 
535             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_SINGLE_QUOTED_RSOLIDUS;
536             break;
537         }
538 
539         ++css_offset;
540     }
541 
542     return css_offset;
543 }
544 
mycss_tokenizer_global_state_string_single_quoted_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)545 size_t mycss_tokenizer_global_state_string_single_quoted_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
546 {
547     if(css[css_offset] == '\r')
548         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_SINGLE_QUOTED_RSOLIDUS_R;
549     else
550         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_SINGLE_QUOTED;
551 
552     css_offset++;
553     return css_offset;
554 }
555 
mycss_tokenizer_global_state_string_single_quoted_rsolidus_r(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)556 size_t mycss_tokenizer_global_state_string_single_quoted_rsolidus_r(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
557 {
558     if(css[css_offset] == '\n')
559         css_offset++;
560 
561     entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_STRING_SINGLE_QUOTED;
562 
563     return css_offset;
564 }
565 
566 /////////////////////////////////////////////////////////
567 //// Consume an ident-like token
568 ////
569 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_ident(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)570 size_t mycss_tokenizer_global_state_ident(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
571 {
572     if(css[css_offset] == '(')
573     {
574         if(mycss_tokenizer_token_strcasecmp(entry, token, "url", 3) == 0) {
575             css_offset++;
576 
577             token->begin = css_offset;
578             token->type  = MyCSS_TOKEN_TYPE_URL;
579             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_URL;
580         }
581         else {
582             css_offset++;
583 
584             token->type = MyCSS_TOKEN_TYPE_FUNCTION;
585 
586             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
587 
588             entry->state = MyCSS_TOKENIZER_STATE_DATA;
589         }
590     }
591     else {
592         token->type = MyCSS_TOKEN_TYPE_IDENT;
593 
594         MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
595 
596         entry->state = MyCSS_TOKENIZER_STATE_DATA;
597     }
598 
599     return css_offset;
600 }
601 
602 /////////////////////////////////////////////////////////
603 //// Consume a name
604 ////
605 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_name(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)606 size_t mycss_tokenizer_global_state_name(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
607 {
608     const unsigned char *u_css = (const unsigned char*)css;
609 
610     while(css_offset < css_size)
611     {
612         if(mycss_chars_name_code_point_map[ u_css[css_offset] ] == 0xff)
613         {
614             if(css[css_offset] == '\\') {
615                 ++css_offset;
616 
617                 if(css_offset >= css_size) {
618                     entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME_RSOLIDUS;
619                     break;
620                 }
621 
622                 if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
623                     --css_offset;
624 
625                     token->length = (entry->current_buffer->offset + css_offset) - token->begin;
626                     entry->state = entry->state_back;
627 
628                     break;
629                 }
630             }
631             else {
632                 token->length = (entry->current_buffer->offset + css_offset) - token->begin;
633                 entry->state = entry->state_back;
634 
635                 break;
636             }
637         }
638 
639         css_offset++;
640     }
641 
642     return css_offset;
643 }
644 
mycss_tokenizer_global_state_name_rsolidus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)645 size_t mycss_tokenizer_global_state_name_rsolidus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
646 {
647     if(css[css_offset] == '\n' || css[css_offset] == '\r' || css[css_offset] == 0x0C) {
648         token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
649         entry->state = entry->state_back;
650 
651         return mycss_tokenizer_state_set_current_buffer_for_continue(entry, css_offset, 1);
652     }
653     else {
654         entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_NAME;
655         css_offset++;
656     }
657 
658     return css_offset;
659 }
660 
661 /////////////////////////////////////////////////////////
662 //// Consume a unicode-range token
663 ////
664 /////////////////////////////////////////////////////////
mycss_tokenizer_global_state_unicode_range_before(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)665 size_t mycss_tokenizer_global_state_unicode_range_before(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
666 {
667     entry->help_counter = 0;
668     entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_UNICODE_RANGE;
669 
670     return css_offset;
671 }
672 
mycss_tokenizer_global_state_unicode_range(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)673 size_t mycss_tokenizer_global_state_unicode_range(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
674 {
675     const unsigned char *u_css = (const unsigned char*)css;
676 
677     while(css_offset < css_size)
678     {
679         if(mycore_string_chars_hex_map[ u_css[css_offset] ] != 0xff)
680         {
681             entry->help_counter++;
682 
683             if(entry->help_counter == 6) {
684                 css_offset++;
685 
686                 entry->help_counter = 0;
687                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_UNICODE_RANGE_MINUS;
688 
689                 break;
690             }
691         }
692         else if(css[css_offset] == '?') {
693             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_UNICODE_RANGE_QUESTION;
694             break;
695         }
696         else if(css[css_offset] == '-') {
697             css_offset++;
698 
699             entry->help_counter = 0;
700             entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_UNICODE_RANGE_MINUS;
701             break;
702         }
703         else {
704             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
705             token->type   = MyCSS_TOKEN_TYPE_UNICODE_RANGE;
706 
707             // TODO
708             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
709 
710             entry->state = MyCSS_TOKENIZER_STATE_DATA;
711             break;
712         }
713 
714         css_offset++;
715     }
716 
717     return css_offset;
718 }
719 
mycss_tokenizer_global_state_unicode_range_question(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)720 size_t mycss_tokenizer_global_state_unicode_range_question(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
721 {
722     while(css_offset < css_size)
723     {
724         if(css[css_offset] == '?') {
725             entry->help_counter++;
726 
727             if(entry->help_counter == 6) {
728                 css_offset++;
729 
730                 token->length = (entry->current_buffer->offset + css_offset) - token->begin;
731                 token->type   = MyCSS_TOKEN_TYPE_UNICODE_RANGE;
732 
733                 MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
734 
735                 entry->state = MyCSS_TOKENIZER_STATE_DATA;
736                 break;
737             }
738         }
739         else {
740             token->length = (entry->current_buffer->offset + css_offset) - token->begin;
741             token->type   = MyCSS_TOKEN_TYPE_UNICODE_RANGE;
742 
743             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
744 
745             entry->state = MyCSS_TOKENIZER_STATE_DATA;
746             break;
747         }
748 
749         css_offset++;
750     }
751 
752     return css_offset;
753 }
754 
mycss_tokenizer_global_state_unicode_range_minus(mycss_entry_t * entry,mycss_token_t * token,const char * css,size_t css_offset,size_t css_size)755 size_t mycss_tokenizer_global_state_unicode_range_minus(mycss_entry_t* entry, mycss_token_t* token, const char* css, size_t css_offset, size_t css_size)
756 {
757     const unsigned char *u_css = (const unsigned char*)css;
758 
759     while(css_offset < css_size)
760     {
761         if(mycore_string_chars_hex_map[ u_css[css_offset] ] != 0xff)
762         {
763             entry->help_counter++;
764 
765             if(entry->help_counter == 6) {
766                 css_offset++;
767 
768                 entry->state = MyCSS_TOKENIZER_GLOBAL_STATE_UNICODE_RANGE_MINUS;
769                 break;
770             }
771         }
772         else {
773             if(entry->help_counter == 0) {
774                 token->length = ((entry->current_buffer->offset + css_offset) - token->begin) - 1;
775                 css_offset = mycss_tokenizer_state_set_current_buffer_for_continue(entry, css_offset, 1);
776             }
777             else {
778                 token->length = (entry->current_buffer->offset + css_offset) - token->begin;
779             }
780 
781             token->type = MyCSS_TOKEN_TYPE_UNICODE_RANGE;
782 
783             MyCSS_TOKEN_READY_CALLBACK_FUNCTION(entry, token);
784 
785             entry->state = MyCSS_TOKENIZER_STATE_DATA;
786             break;
787         }
788 
789         css_offset++;
790     }
791 
792     return css_offset;
793 }
794 
795 
796 
797