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