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/mycss.h"
22 #include "mycss/tokenizer_resource.h"
23
mycss_create(void)24 mycss_t * mycss_create(void)
25 {
26 return (mycss_t*)mycore_calloc(1, sizeof(mycss_t));
27 }
28
mycss_init(mycss_t * mycss)29 mystatus_t mycss_init(mycss_t* mycss)
30 {
31 mystatus_t status = mycss_tokenizer_state_init(mycss);
32
33 if(status != MyCSS_STATUS_OK)
34 return status;
35
36 return MyCSS_STATUS_OK;
37 }
38
mycss_destroy(mycss_t * mycss,bool self_destroy)39 mycss_t * mycss_destroy(mycss_t* mycss, bool self_destroy)
40 {
41 if(mycss == NULL)
42 return NULL;
43
44 mycss_tokenizer_state_destroy(mycss);
45
46 if(self_destroy) {
47 mycore_free(mycss);
48 return NULL;
49 }
50
51 return mycss;
52 }
53
mycss_parse(mycss_entry_t * entry,myencoding_t encoding,const char * css,size_t css_size)54 mystatus_t mycss_parse(mycss_entry_t* entry, myencoding_t encoding, const char* css, size_t css_size)
55 {
56 mycss_entry_clean(entry);
57
58 /* set parser */
59 entry->parser = mycss_parser_token;
60
61 /* stylesheet */
62 entry->stylesheet = mycss_stylesheet_create();
63 mycss_stylesheet_init(entry->stylesheet, entry);
64
65 /* and parse css */
66 mycss_encoding_set(entry, encoding);
67
68 mystatus_t status = mycss_tokenizer_chunk(entry, css, css_size);
69 if(status != MyCSS_STATUS_OK)
70 return status;
71
72 status = mycss_tokenizer_end(entry);
73
74 return status;
75 }
76
mycss_parse_chunk(mycss_entry_t * entry,const char * css,size_t css_size)77 mystatus_t mycss_parse_chunk(mycss_entry_t* entry, const char* css, size_t css_size)
78 {
79 if(entry->type & MyCSS_ENTRY_TYPE_END) {
80 mycss_entry_clean_all(entry);
81 }
82
83 /* create and init new Result */
84 if(entry->stylesheet == NULL) {
85 entry->stylesheet = mycss_stylesheet_create();
86 mycss_stylesheet_init(entry->stylesheet, entry);
87 }
88
89 return mycss_tokenizer_chunk(entry, css, css_size);
90 }
91
mycss_parse_chunk_end(mycss_entry_t * entry)92 mystatus_t mycss_parse_chunk_end(mycss_entry_t* entry)
93 {
94 mystatus_t status = mycss_tokenizer_end(entry);
95 mycss_entry_end(entry);
96
97 return status;
98 }
99
100 // token
mycss_token_position(mycss_token_t * token,size_t * return_length)101 size_t mycss_token_position(mycss_token_t* token, size_t *return_length)
102 {
103 if(return_length)
104 *return_length = token->length;
105
106 return token->begin;
107 }
108
mycss_token_begin(mycss_token_t * token)109 size_t mycss_token_begin(mycss_token_t* token)
110 {
111 return token->begin;
112 }
113
mycss_token_length(mycss_token_t * token)114 size_t mycss_token_length(mycss_token_t* token)
115 {
116 return token->length;
117 }
118
mycss_token_type(mycss_token_t * token)119 mycss_token_type_t mycss_token_type(mycss_token_t* token)
120 {
121 return token->type;
122 }
123
mycss_token_name_by_type(mycss_token_type_t type)124 const char * mycss_token_name_by_type(mycss_token_type_t type)
125 {
126 if(type >= MyCSS_TOKEN_TYPE_LAST_ENTRY)
127 return mycss_token_type_description[MyCSS_TOKEN_TYPE_LAST_ENTRY];
128
129 return mycss_token_type_description[type];
130 }
131
mycss_token_data_to_string(mycss_entry_t * entry,mycss_token_t * token,mycore_string_t * str,bool init_string,bool case_insensitive)132 size_t mycss_token_data_to_string(mycss_entry_t* entry, mycss_token_t* token, mycore_string_t* str, bool init_string, bool case_insensitive)
133 {
134 if(init_string)
135 mycore_string_init(entry->mchar, entry->mchar_node_id, str, (token->length + 4));
136
137 mycss_string_res_t out_res;
138 mycss_string_res_clean(&out_res);
139
140 out_res.encoding = entry->encoding;
141 out_res.case_insensitive = case_insensitive;
142
143 mycore_incoming_buffer_t *buffer = mycore_incoming_buffer_find_by_position(entry->current_buffer, token->begin);
144 size_t relative_begin = token->begin - buffer->offset;
145
146 // if token data length in one buffer then print them all at once
147 if((relative_begin + token->length) <= buffer->size) {
148 mycss_string_data_process(str, &buffer->data[relative_begin], 0, token->length, &out_res);
149 mycss_string_data_process_end(str, &out_res);
150
151 return token->length;
152 }
153
154 // if the data are spread across multiple buffers that join them
155 size_t length = token->length;
156 while(buffer) {
157 if((relative_begin + length) > buffer->size)
158 {
159 size_t relative_end = (buffer->size - relative_begin);
160 length -= relative_end;
161
162 mycss_string_data_process(str, buffer->data, relative_begin, relative_end, &out_res);
163
164 relative_begin = 0;
165 buffer = buffer->next;
166 }
167 else {
168 mycss_string_data_process(str, &buffer->data[relative_begin], 0, length, &out_res);
169 break;
170 }
171 }
172
173 mycss_string_data_process_end(str, &out_res);
174
175 return token->length;
176 }
177
mycss_token_buffer_first(mycss_entry_t * entry,mycss_token_t * token)178 mycore_incoming_buffer_t * mycss_token_buffer_first(mycss_entry_t* entry, mycss_token_t* token)
179 {
180 return mycore_incoming_buffer_find_by_position(entry->current_buffer, token->begin);
181 }
182
183 // encoding
184
mycss_encoding_set(mycss_entry_t * entry,myencoding_t encoding)185 void mycss_encoding_set(mycss_entry_t* entry, myencoding_t encoding)
186 {
187 entry->encoding = encoding;
188 }
189
mycss_encoding_get(mycss_entry_t * entry)190 myencoding_t mycss_encoding_get(mycss_entry_t* entry)
191 {
192 return entry->encoding;
193 }
194
mycss_encoding_check_charset_rule(const char * css,size_t size)195 myencoding_t mycss_encoding_check_charset_rule(const char* css, size_t size)
196 {
197 if(size < 15)
198 return MyENCODING_UTF_8;
199
200 if(strncmp("@charset \"", css, 10))
201 return MyENCODING_UTF_8;
202
203 size_t begin = 10;
204 size_t length = begin;
205
206 while(length < size) {
207 if(css[length] == '"')
208 {
209 ++length;
210
211 if(length >= size || css[length] != ';')
212 return MyENCODING_UTF_8;
213
214 size_t name_len = (length - begin) - 1;
215
216 myencoding_t encoding;
217 if(myencoding_by_name(&css[begin], name_len, &encoding))
218 return encoding;
219
220 break;
221 }
222
223 ++length;
224 }
225
226 return MyENCODING_UTF_8;
227 }
228
229
230