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 "mycore/mystring.h"
22 #include "mycore/utils/resources.h"
23
24 /////////////////////////////////////////////////////////
25 //// Init, Clean, Destroy
26 ////
27 /////////////////////////////////////////////////////////
mycore_string_init(mchar_async_t * mchar,size_t node_idx,mycore_string_t * str,size_t size)28 char * mycore_string_init(mchar_async_t *mchar, size_t node_idx, mycore_string_t* str, size_t size)
29 {
30 str->data = mchar_async_malloc(mchar, node_idx, size);
31 str->size = size;
32 str->node_idx = node_idx;
33 str->mchar = mchar;
34
35 mycore_string_clean(str);
36
37 return str->data;
38 }
39
mycore_string_clean(mycore_string_t * str)40 void mycore_string_clean(mycore_string_t* str)
41 {
42 str->length = 0;
43 }
44
mycore_string_clean_all(mycore_string_t * str)45 void mycore_string_clean_all(mycore_string_t* str)
46 {
47 memset(str, 0, sizeof(mycore_string_t));
48 }
49
mycore_string_destroy(mycore_string_t * str,bool destroy_obj)50 mycore_string_t * mycore_string_destroy(mycore_string_t* str, bool destroy_obj)
51 {
52 if(str == NULL)
53 return NULL;
54
55 if(str->data && str->mchar)
56 mchar_async_free(str->mchar, str->node_idx, str->data);
57
58 if(destroy_obj && str) {
59 mycore_free(str);
60 return NULL;
61 }
62
63 return str;
64 }
65
mycore_string_raw_clean(mycore_string_raw_t * str_raw)66 void mycore_string_raw_clean(mycore_string_raw_t* str_raw)
67 {
68 str_raw->length = 0;
69 }
70
mycore_string_raw_clean_all(mycore_string_raw_t * str_raw)71 void mycore_string_raw_clean_all(mycore_string_raw_t* str_raw)
72 {
73 memset(str_raw, 0, sizeof(mycore_string_raw_t));
74 }
75
mycore_string_raw_destroy(mycore_string_raw_t * str_raw,bool destroy_obj)76 mycore_string_raw_t * mycore_string_raw_destroy(mycore_string_raw_t* str_raw, bool destroy_obj)
77 {
78 if(str_raw == NULL)
79 return NULL;
80
81 if(str_raw->data) {
82 mycore_free(str_raw->data);
83 str_raw->data = NULL;
84 }
85
86 if(destroy_obj && str_raw) {
87 mycore_free(str_raw);
88 return NULL;
89 }
90
91 return str_raw;
92 }
93
mycore_string_realloc(mycore_string_t * str,size_t new_size)94 char * mycore_string_realloc(mycore_string_t *str, size_t new_size)
95 {
96 if(str == NULL)
97 return NULL;
98
99 char *tmp = mchar_async_realloc(str->mchar, str->node_idx, str->data, str->length, new_size);
100
101 if(tmp) {
102 str->size = new_size;
103 str->data = tmp;
104 }
105 else
106 return NULL;
107
108 return tmp;
109 }
110
111 /////////////////////////////////////////////////////////
112 //// Basic API
113 ////
114 /////////////////////////////////////////////////////////
mycore_string_data_alloc(mchar_async_t * mchar,size_t node_id,size_t size)115 char * mycore_string_data_alloc(mchar_async_t *mchar, size_t node_id, size_t size)
116 {
117 return mchar_async_malloc(mchar, node_id, size);
118 }
119
mycore_string_data_realloc(mchar_async_t * mchar,size_t node_id,char * data,size_t len_to_copy,size_t size)120 char * mycore_string_data_realloc(mchar_async_t *mchar, size_t node_id, char *data, size_t len_to_copy, size_t size)
121 {
122 return mchar_async_realloc(mchar, node_id, data, len_to_copy, size);
123 }
124
mycore_string_data_free(mchar_async_t * mchar,size_t node_id,char * data)125 void mycore_string_data_free(mchar_async_t *mchar, size_t node_id, char *data)
126 {
127 mchar_async_free(mchar, node_id, data);
128 }
129
mycore_string_data(mycore_string_t * str)130 char * mycore_string_data(mycore_string_t *str)
131 {
132 if(str == NULL)
133 return NULL;
134
135 return str->data;
136 }
137
mycore_string_length(mycore_string_t * str)138 size_t mycore_string_length(mycore_string_t *str)
139 {
140 if(str == NULL)
141 return 0;
142
143 return str->length;
144 }
145
mycore_string_size(mycore_string_t * str)146 size_t mycore_string_size(mycore_string_t *str)
147 {
148 if(str == NULL)
149 return 0;
150
151 return str->size;
152 }
153
mycore_string_data_set(mycore_string_t * str,char * data)154 char * mycore_string_data_set(mycore_string_t *str, char *data)
155 {
156 if(str == NULL)
157 return NULL;
158
159 str->data = data;
160 return str->data;
161 }
162
mycore_string_size_set(mycore_string_t * str,size_t size)163 size_t mycore_string_size_set(mycore_string_t *str, size_t size)
164 {
165 if(str == NULL)
166 return 0;
167
168 str->size = size;
169 return str->size;
170 }
171
mycore_string_length_set(mycore_string_t * str,size_t length)172 size_t mycore_string_length_set(mycore_string_t *str, size_t length)
173 {
174 if(str == NULL)
175 return 0;
176
177 str->length = length;
178 return str->length;
179 }
180
181 /////////////////////////////////////////////////////////
182 //// Append API
183 ////
184 /////////////////////////////////////////////////////////
mycore_string_append(mycore_string_t * str,const char * buff,size_t length)185 void mycore_string_append(mycore_string_t* str, const char* buff, size_t length)
186 {
187 MyCORE_STRING_REALLOC_IF_NEED(str, (length + 1), 0);
188
189 memcpy(&str->data[str->length], buff, (sizeof(char) * length));
190
191 str->length += length;
192 str->data[str->length] = '\0';
193 }
194
mycore_string_append_one(mycore_string_t * str,const char data)195 void mycore_string_append_one(mycore_string_t* str, const char data)
196 {
197 MyCORE_STRING_REALLOC_IF_NEED(str, 2, 1);
198 MyCORE_STRING_APPEND_BYTE_WITHOUT_REALLOC(data, str);
199 MyCORE_STRING_APPEND_BYTE_WITHOUT_INCREMENT_REALLOC('\0', str);
200 }
201
mycore_string_append_lowercase(mycore_string_t * str,const char * data,size_t length)202 void mycore_string_append_lowercase(mycore_string_t* str, const char* data, size_t length)
203 {
204 MyCORE_STRING_REALLOC_IF_NEED(str, (length + 1), 0);
205
206 unsigned char *ref = (unsigned char*)&str->data[str->length];
207 const unsigned char *buf = (const unsigned char*)data;
208
209 size_t i;
210 for(i = 0; i < length; i++) {
211 ref[i] = mycore_string_chars_lowercase_map[ buf[i] ];
212 }
213
214 ref[i] = '\0';
215 str->length += length;
216 }
217
mycore_string_copy(mycore_string_t * dest,mycore_string_t * target)218 void mycore_string_copy(mycore_string_t* dest, mycore_string_t* target)
219 {
220 mycore_string_append(dest, target->data, target->length);
221 }
222
mycore_string_raw_copy(char * str1,const char * str2,size_t size)223 size_t mycore_string_raw_copy(char* str1, const char* str2, size_t size)
224 {
225 str1[size] = '\0';
226
227 while(size) {
228 size--;
229 str1[size] = str2[size];
230 }
231
232 return size;
233 }
234
mycore_string_raw_set_replacement_character(mycore_string_t * target,size_t position)235 size_t mycore_string_raw_set_replacement_character(mycore_string_t* target, size_t position)
236 {
237 // Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD)
238 target->data[(position)] = (char)0xEF;
239 target->data[(position + 1)] = (char)0xBF;
240 target->data[(position + 2)] = (char)0xBD;
241
242 return 3;
243 }
244
mycore_string_append_with_replacement_null_characters(mycore_string_t * str,const char * buff,size_t length)245 void mycore_string_append_with_replacement_null_characters(mycore_string_t* str, const char* buff, size_t length)
246 {
247 MyCORE_STRING_REALLOC_IF_NEED(str, (length + 1), 0);
248
249 unsigned char *data = (unsigned char*)str->data;
250 const unsigned char *u_buff = (const unsigned char*)buff;
251
252 for (size_t i = 0; i < length; i++)
253 {
254 if(u_buff[i] == 0x00) {
255 mycore_string_realloc(str, (str->size + 5));
256 data = (unsigned char*)str->data;
257
258 // Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD)
259 data[str->length] = 0xEF; str->length++;
260 data[str->length] = 0xBF; str->length++;
261 data[str->length] = 0xBD;
262 }
263 else
264 data[str->length] = u_buff[i];
265
266 str->length++;
267 }
268
269 str->data[str->length] = '\0';
270 }
271
mycore_string_stay_only_whitespace(mycore_string_t * target)272 void mycore_string_stay_only_whitespace(mycore_string_t* target)
273 {
274 char *data = target->data;
275 size_t pos = 0;
276
277 for(size_t i = 0; i < target->length; i++)
278 {
279 if(mycore_utils_whithspace(data[i], ==, ||)) {
280 data[pos] = data[i];
281 pos++;
282 }
283 }
284
285 target->length = pos;
286 }
287
mycore_string_crop_whitespace_from_begin(mycore_string_t * target)288 size_t mycore_string_crop_whitespace_from_begin(mycore_string_t* target)
289 {
290 char *data = target->data;
291 size_t i;
292
293 for(i = 0; i < target->length; i++) {
294 if(mycore_utils_whithspace(data[i], !=, &&))
295 break;
296 }
297
298 if(i)
299 target->data = mchar_async_crop_first_chars_without_cache(target->data, i);
300
301 target->length -= i;
302
303 return i;
304 }
305
mycore_string_whitespace_from_begin(mycore_string_t * target)306 size_t mycore_string_whitespace_from_begin(mycore_string_t* target)
307 {
308 char *data = target->data;
309 size_t i;
310
311 for(i = 0; i < target->length; i++) {
312 if(mycore_utils_whithspace(data[i], !=, &&))
313 break;
314 }
315
316 return i;
317 }
318
319
320