1 /*
2 * Split UTF-8 string functions
3 *
4 * Copyright (C) 2010-2020, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <memory.h>
24 #include <types.h>
25
26 #include "libfvalue_libcerror.h"
27 #include "libfvalue_split_utf8_string.h"
28 #include "libfvalue_types.h"
29
30 /* Creates a split UTF-8 string
31 * Make sure the value split_string is referencing, is set to NULL
32 * Returns 1 if successful or -1 on error
33 */
libfvalue_split_utf8_string_initialize(libfvalue_split_utf8_string_t ** split_string,const uint8_t * utf8_string,size_t utf8_string_size,int number_of_segments,libcerror_error_t ** error)34 int libfvalue_split_utf8_string_initialize(
35 libfvalue_split_utf8_string_t **split_string,
36 const uint8_t *utf8_string,
37 size_t utf8_string_size,
38 int number_of_segments,
39 libcerror_error_t **error )
40 {
41 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
42 static char *function = "libfvalue_split_utf8_string_initialize";
43
44 if( split_string == NULL )
45 {
46 libcerror_error_set(
47 error,
48 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50 "%s: invalid split string.",
51 function );
52
53 return( -1 );
54 }
55 if( *split_string != NULL )
56 {
57 libcerror_error_set(
58 error,
59 LIBCERROR_ERROR_DOMAIN_RUNTIME,
60 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61 "%s: invalid split string value already set.",
62 function );
63
64 return( -1 );
65 }
66 if( number_of_segments < 0 )
67 {
68 libcerror_error_set(
69 error,
70 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
72 "%s: invalid number of segments less than zero.",
73 function );
74
75 return( -1 );
76 }
77 internal_split_string = memory_allocate_structure(
78 libfvalue_internal_split_utf8_string_t );
79
80 if( internal_split_string == NULL )
81 {
82 libcerror_error_set(
83 error,
84 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86 "%s: unable to create split string.",
87 function );
88
89 goto on_error;
90 }
91 if( memory_set(
92 internal_split_string,
93 0,
94 sizeof( libfvalue_internal_split_utf8_string_t ) ) == NULL )
95 {
96 libcerror_error_set(
97 error,
98 LIBCERROR_ERROR_DOMAIN_MEMORY,
99 LIBCERROR_MEMORY_ERROR_SET_FAILED,
100 "%s: unable to clear split string.",
101 function );
102
103 memory_free(
104 internal_split_string );
105
106 return( -1 );
107 }
108 if( ( utf8_string != NULL )
109 && ( utf8_string_size > 0 ) )
110 {
111 internal_split_string->string = (uint8_t *) memory_allocate(
112 sizeof( uint8_t ) * utf8_string_size );
113
114 if( internal_split_string->string == NULL )
115 {
116 libcerror_error_set(
117 error,
118 LIBCERROR_ERROR_DOMAIN_MEMORY,
119 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
120 "%s: unable to create string.",
121 function );
122
123 goto on_error;
124 }
125 if( memory_copy(
126 internal_split_string->string,
127 utf8_string,
128 sizeof( uint8_t ) * ( utf8_string_size - 1 ) ) == NULL )
129 {
130 libcerror_error_set(
131 error,
132 LIBCERROR_ERROR_DOMAIN_MEMORY,
133 LIBCERROR_MEMORY_ERROR_SET_FAILED,
134 "%s: unable to copy string.",
135 function );
136
137 goto on_error;
138 }
139 internal_split_string->string[ utf8_string_size - 1 ] = 0;
140 internal_split_string->string_size = utf8_string_size;
141 }
142 if( number_of_segments > 0 )
143 {
144 internal_split_string->segments = (uint8_t **) memory_allocate(
145 sizeof( uint8_t * ) * number_of_segments );
146
147 if( internal_split_string->segments == NULL )
148 {
149 libcerror_error_set(
150 error,
151 LIBCERROR_ERROR_DOMAIN_MEMORY,
152 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
153 "%s: unable to create segments.",
154 function );
155
156 goto on_error;
157 }
158 if( memory_set(
159 internal_split_string->segments,
160 0,
161 sizeof( uint8_t * ) * number_of_segments ) == NULL )
162 {
163 libcerror_error_set(
164 error,
165 LIBCERROR_ERROR_DOMAIN_MEMORY,
166 LIBCERROR_MEMORY_ERROR_SET_FAILED,
167 "%s: unable to clear segments.",
168 function );
169
170 goto on_error;
171 }
172 internal_split_string->segment_sizes = (size_t *) memory_allocate(
173 sizeof( size_t ) * number_of_segments );
174
175 if( internal_split_string->segment_sizes == NULL )
176 {
177 libcerror_error_set(
178 error,
179 LIBCERROR_ERROR_DOMAIN_MEMORY,
180 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
181 "%s: unable to create segment sizes.",
182 function );
183
184 goto on_error;
185 }
186 if( memory_set(
187 internal_split_string->segment_sizes,
188 0,
189 sizeof( size_t ) * number_of_segments ) == NULL )
190 {
191 libcerror_error_set(
192 error,
193 LIBCERROR_ERROR_DOMAIN_MEMORY,
194 LIBCERROR_MEMORY_ERROR_SET_FAILED,
195 "%s: unable to clear segment sizes.",
196 function );
197
198 goto on_error;
199 }
200 }
201 internal_split_string->number_of_segments = number_of_segments;
202
203 *split_string = (libfvalue_split_utf8_string_t *) internal_split_string;
204
205 return( 1 );
206
207 on_error:
208 if( internal_split_string != NULL )
209 {
210 if( internal_split_string->segment_sizes != NULL )
211 {
212 memory_free(
213 internal_split_string->segment_sizes );
214 }
215 if( internal_split_string->segments != NULL )
216 {
217 memory_free(
218 internal_split_string->segments );
219 }
220 if( internal_split_string->string != NULL )
221 {
222 memory_free(
223 internal_split_string->string );
224 }
225 memory_free(
226 internal_split_string );
227 }
228 return( -1 );
229 }
230
231 /* Frees a split UTF-8 string
232 * Returns 1 if successful or -1 on error
233 */
libfvalue_split_utf8_string_free(libfvalue_split_utf8_string_t ** split_string,libcerror_error_t ** error)234 int libfvalue_split_utf8_string_free(
235 libfvalue_split_utf8_string_t **split_string,
236 libcerror_error_t **error )
237 {
238 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
239 static char *function = "libfvalue_split_utf8_string_free";
240
241 if( split_string == NULL )
242 {
243 libcerror_error_set(
244 error,
245 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
246 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
247 "%s: invalid split string.",
248 function );
249
250 return( -1 );
251 }
252 if( *split_string != NULL )
253 {
254 internal_split_string = (libfvalue_internal_split_utf8_string_t *) *split_string;
255 *split_string = NULL;
256
257 if( internal_split_string->string != NULL )
258 {
259 memory_free(
260 internal_split_string->string );
261 }
262 if( internal_split_string->segments != NULL )
263 {
264 memory_free(
265 internal_split_string->segments );
266 }
267 if( internal_split_string->segment_sizes != NULL )
268 {
269 memory_free(
270 internal_split_string->segment_sizes );
271 }
272 memory_free(
273 internal_split_string );
274 }
275 return( 1 );
276 }
277
278 /* Retrieves the UTF-8 string
279 * Returns 1 if successful or -1 on error
280 */
libfvalue_split_utf8_string_get_string(libfvalue_split_utf8_string_t * split_string,uint8_t ** utf8_string,size_t * utf8_string_size,libcerror_error_t ** error)281 int libfvalue_split_utf8_string_get_string(
282 libfvalue_split_utf8_string_t *split_string,
283 uint8_t **utf8_string,
284 size_t *utf8_string_size,
285 libcerror_error_t **error )
286 {
287 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
288 static char *function = "libfvalue_split_utf8_string_get_string";
289
290 if( split_string == NULL )
291 {
292 libcerror_error_set(
293 error,
294 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
295 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
296 "%s: invalid split string.",
297 function );
298
299 return( -1 );
300 }
301 internal_split_string = (libfvalue_internal_split_utf8_string_t *) split_string;
302
303 if( utf8_string == NULL )
304 {
305 libcerror_error_set(
306 error,
307 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
308 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
309 "%s: invalid UTF-8 string.",
310 function );
311
312 return( -1 );
313 }
314 if( utf8_string_size == NULL )
315 {
316 libcerror_error_set(
317 error,
318 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
319 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
320 "%s: invalid UTF-8 string size.",
321 function );
322
323 return( -1 );
324 }
325 *utf8_string = internal_split_string->string;
326 *utf8_string_size = internal_split_string->string_size;
327
328 return( 1 );
329 }
330
331 /* Retrieves the number of segments
332 * Returns 1 if successful or -1 on error
333 */
libfvalue_split_utf8_string_get_number_of_segments(libfvalue_split_utf8_string_t * split_string,int * number_of_segments,libcerror_error_t ** error)334 int libfvalue_split_utf8_string_get_number_of_segments(
335 libfvalue_split_utf8_string_t *split_string,
336 int *number_of_segments,
337 libcerror_error_t **error )
338 {
339 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
340 static char *function = "libfvalue_split_utf8_string_get_number_of_segments";
341
342 if( split_string == NULL )
343 {
344 libcerror_error_set(
345 error,
346 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
347 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
348 "%s: invalid split string.",
349 function );
350
351 return( -1 );
352 }
353 internal_split_string = (libfvalue_internal_split_utf8_string_t *) split_string;
354
355 if( number_of_segments == NULL )
356 {
357 libcerror_error_set(
358 error,
359 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
360 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
361 "%s: invalid number of segments.",
362 function );
363
364 return( -1 );
365 }
366 *number_of_segments = internal_split_string->number_of_segments;
367
368 return( 1 );
369 }
370
371 /* Retrieves a specific segment
372 * Returns 1 if successful or -1 on error
373 */
libfvalue_split_utf8_string_get_segment_by_index(libfvalue_split_utf8_string_t * split_string,int segment_index,uint8_t ** utf8_string_segment,size_t * utf8_string_segment_size,libcerror_error_t ** error)374 int libfvalue_split_utf8_string_get_segment_by_index(
375 libfvalue_split_utf8_string_t *split_string,
376 int segment_index,
377 uint8_t **utf8_string_segment,
378 size_t *utf8_string_segment_size,
379 libcerror_error_t **error )
380 {
381 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
382 static char *function = "libfvalue_split_utf8_string_get_segment_by_index";
383
384 if( split_string == NULL )
385 {
386 libcerror_error_set(
387 error,
388 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
389 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
390 "%s: invalid split string.",
391 function );
392
393 return( -1 );
394 }
395 internal_split_string = (libfvalue_internal_split_utf8_string_t *) split_string;
396
397 if( ( segment_index < 0 )
398 || ( segment_index >= internal_split_string->number_of_segments ) )
399 {
400 libcerror_error_set(
401 error,
402 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
403 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
404 "%s: invalid segment index value out of bounds.",
405 function );
406
407 return( -1 );
408 }
409 if( utf8_string_segment == NULL )
410 {
411 libcerror_error_set(
412 error,
413 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
414 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
415 "%s: invalid UTF-8 string segment.",
416 function );
417
418 return( -1 );
419 }
420 if( utf8_string_segment_size == NULL )
421 {
422 libcerror_error_set(
423 error,
424 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
425 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
426 "%s: invalid UTF-8 string segment size.",
427 function );
428
429 return( -1 );
430 }
431 *utf8_string_segment = internal_split_string->segments[ segment_index ];
432 *utf8_string_segment_size = internal_split_string->segment_sizes[ segment_index ];
433
434 return( 1 );
435 }
436
437 /* Sets a specific segment
438 * Returns 1 if successful or -1 on error
439 */
libfvalue_split_utf8_string_set_segment_by_index(libfvalue_split_utf8_string_t * split_string,int segment_index,uint8_t * utf8_string_segment,size_t utf8_string_segment_size,libcerror_error_t ** error)440 int libfvalue_split_utf8_string_set_segment_by_index(
441 libfvalue_split_utf8_string_t *split_string,
442 int segment_index,
443 uint8_t *utf8_string_segment,
444 size_t utf8_string_segment_size,
445 libcerror_error_t **error )
446 {
447 libfvalue_internal_split_utf8_string_t *internal_split_string = NULL;
448 static char *function = "libfvalue_split_utf8_string_set_segment_by_index";
449 size_t utf8_string_segment_offset = 0;
450
451 if( split_string == NULL )
452 {
453 libcerror_error_set(
454 error,
455 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
456 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
457 "%s: invalid split string.",
458 function );
459
460 return( -1 );
461 }
462 internal_split_string = (libfvalue_internal_split_utf8_string_t *) split_string;
463
464 if( ( segment_index < 0 )
465 || ( segment_index >= internal_split_string->number_of_segments ) )
466 {
467 libcerror_error_set(
468 error,
469 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
470 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
471 "%s: invalid segment index value out of bounds.",
472 function );
473
474 return( -1 );
475 }
476 if( utf8_string_segment == NULL )
477 {
478 if( utf8_string_segment_size != 0 )
479 {
480 libcerror_error_set(
481 error,
482 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
483 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
484 "%s: invalid UTF-8 string segment size value out of bounds.",
485 function );
486
487 return( -1 );
488 }
489 }
490 else
491 {
492 if( utf8_string_segment < internal_split_string->string )
493 {
494 libcerror_error_set(
495 error,
496 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
497 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
498 "%s: invalid UTF-8 string segment value out of bounds.",
499 function );
500
501 return( -1 );
502 }
503 utf8_string_segment_offset = (size_t) ( utf8_string_segment - internal_split_string->string );
504
505 if( utf8_string_segment_offset > internal_split_string->string_size )
506 {
507 libcerror_error_set(
508 error,
509 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
511 "%s: invalid UTF-8 string segment value out of bounds.",
512 function );
513
514 return( -1 );
515 }
516 utf8_string_segment_offset += utf8_string_segment_size;
517
518 if( utf8_string_segment_offset > internal_split_string->string_size )
519 {
520 libcerror_error_set(
521 error,
522 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
523 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
524 "%s: invalid UTF-8 string segment value out of bounds.",
525 function );
526
527 return( -1 );
528 }
529 }
530 internal_split_string->segments[ segment_index ] = utf8_string_segment;
531 internal_split_string->segment_sizes[ segment_index ] = utf8_string_segment_size;
532
533 return( 1 );
534 }
535
536