1 /*
2 * UTF-16 string functions
3 *
4 * Copyright (C) 2008-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 <types.h>
24
25 #include "libuna_definitions.h"
26 #include "libuna_libcerror.h"
27 #include "libuna_scsu.h"
28 #include "libuna_types.h"
29 #include "libuna_unicode_character.h"
30 #include "libuna_utf16_string.h"
31
32 /* Determines the size of an UTF-16 string from a byte stream
33 * Returns 1 if successful or -1 on error
34 */
libuna_utf16_string_size_from_byte_stream(const uint8_t * byte_stream,size_t byte_stream_size,int codepage,size_t * utf16_string_size,libcerror_error_t ** error)35 int libuna_utf16_string_size_from_byte_stream(
36 const uint8_t *byte_stream,
37 size_t byte_stream_size,
38 int codepage,
39 size_t *utf16_string_size,
40 libcerror_error_t **error )
41 {
42 static char *function = "libuna_utf16_string_size_from_byte_stream";
43 size_t byte_stream_index = 0;
44 libuna_unicode_character_t unicode_character = 0;
45
46 if( byte_stream == NULL )
47 {
48 libcerror_error_set(
49 error,
50 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52 "%s: invalid byte stream.",
53 function );
54
55 return( -1 );
56 }
57 if( byte_stream_size > (size_t) SSIZE_MAX )
58 {
59 libcerror_error_set(
60 error,
61 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
63 "%s: invalid byte stream size value exceeds maximum.",
64 function );
65
66 return( -1 );
67 }
68 if( utf16_string_size == NULL )
69 {
70 libcerror_error_set(
71 error,
72 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74 "%s: invalid UTF-16 string size.",
75 function );
76
77 return( -1 );
78 }
79 *utf16_string_size = 0;
80
81 if( byte_stream_size == 0 )
82 {
83 return( 1 );
84 }
85 while( byte_stream_index < byte_stream_size )
86 {
87 /* Convert the byte stream bytes into an Unicode character
88 */
89 if( libuna_unicode_character_copy_from_byte_stream(
90 &unicode_character,
91 byte_stream,
92 byte_stream_size,
93 &byte_stream_index,
94 codepage,
95 error ) != 1 )
96 {
97 libcerror_error_set(
98 error,
99 LIBCERROR_ERROR_DOMAIN_CONVERSION,
100 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
101 "%s: unable to copy Unicode character from byte stream.",
102 function );
103
104 return( -1 );
105 }
106 /* Determine how many UTF-16 character byte words are required
107 */
108 if( libuna_unicode_character_size_to_utf16(
109 unicode_character,
110 utf16_string_size,
111 error ) != 1 )
112 {
113 libcerror_error_set(
114 error,
115 LIBCERROR_ERROR_DOMAIN_CONVERSION,
116 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
117 "%s: unable to unable to determine size of Unicode character in UTF-16.",
118 function );
119
120 return( -1 );
121 }
122 }
123 /* Check if the string is terminated with an end-of-string character
124 */
125 if( unicode_character != 0 )
126 {
127 *utf16_string_size += 1;
128 }
129 return( 1 );
130 }
131
132 /* Copies an UTF-16 string from a byte stream
133 * Returns 1 if successful or -1 on error
134 */
libuna_utf16_string_copy_from_byte_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * byte_stream,size_t byte_stream_size,int codepage,libcerror_error_t ** error)135 int libuna_utf16_string_copy_from_byte_stream(
136 libuna_utf16_character_t *utf16_string,
137 size_t utf16_string_size,
138 const uint8_t *byte_stream,
139 size_t byte_stream_size,
140 int codepage,
141 libcerror_error_t **error )
142 {
143 static char *function = "libuna_utf16_string_copy_from_byte_stream";
144 size_t utf16_string_index = 0;
145
146 if( libuna_utf16_string_with_index_copy_from_byte_stream(
147 utf16_string,
148 utf16_string_size,
149 &utf16_string_index,
150 byte_stream,
151 byte_stream_size,
152 codepage,
153 error ) != 1 )
154 {
155 libcerror_error_set(
156 error,
157 LIBCERROR_ERROR_DOMAIN_RUNTIME,
158 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
159 "%s: unable to copy byte stream to UTF-16 string.",
160 function );
161
162 return( -1 );
163 }
164 return( 1 );
165 }
166
167 /* Copies an UTF-16 string from a byte stream
168 * Returns 1 if successful or -1 on error
169 */
libuna_utf16_string_with_index_copy_from_byte_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * byte_stream,size_t byte_stream_size,int codepage,libcerror_error_t ** error)170 int libuna_utf16_string_with_index_copy_from_byte_stream(
171 libuna_utf16_character_t *utf16_string,
172 size_t utf16_string_size,
173 size_t *utf16_string_index,
174 const uint8_t *byte_stream,
175 size_t byte_stream_size,
176 int codepage,
177 libcerror_error_t **error )
178 {
179 static char *function = "libuna_utf16_string_with_index_copy_from_byte_stream";
180 size_t byte_stream_index = 0;
181 libuna_unicode_character_t unicode_character = 0;
182
183 if( utf16_string == NULL )
184 {
185 libcerror_error_set(
186 error,
187 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
189 "%s: invalid UTF-16 string.",
190 function );
191
192 return( -1 );
193 }
194 if( utf16_string_size > (size_t) SSIZE_MAX )
195 {
196 libcerror_error_set(
197 error,
198 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
199 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
200 "%s: invalid UTF-16 string size value exceeds maximum.",
201 function );
202
203 return( -1 );
204 }
205 if( utf16_string_index == NULL )
206 {
207 libcerror_error_set(
208 error,
209 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
210 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
211 "%s: invalid UTF-16 string index.",
212 function );
213
214 return( -1 );
215 }
216 if( byte_stream == NULL )
217 {
218 libcerror_error_set(
219 error,
220 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
221 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
222 "%s: invalid byte stream.",
223 function );
224
225 return( -1 );
226 }
227 if( byte_stream_size > (size_t) SSIZE_MAX )
228 {
229 libcerror_error_set(
230 error,
231 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
233 "%s: invalid byte stream size value exceeds maximum.",
234 function );
235
236 return( -1 );
237 }
238 if( byte_stream_size == 0 )
239 {
240 libcerror_error_set(
241 error,
242 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
243 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
244 "%s: missing byte stream value.",
245 function );
246
247 return( -1 );
248 }
249 while( byte_stream_index < byte_stream_size )
250 {
251 /* Convert the byte stream bytes into an Unicode character
252 */
253 if( libuna_unicode_character_copy_from_byte_stream(
254 &unicode_character,
255 byte_stream,
256 byte_stream_size,
257 &byte_stream_index,
258 codepage,
259 error ) != 1 )
260 {
261 libcerror_error_set(
262 error,
263 LIBCERROR_ERROR_DOMAIN_CONVERSION,
264 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
265 "%s: unable to copy Unicode character from byte stream.",
266 function );
267
268 return( -1 );
269 }
270 /* Convert the Unicode character into UTF-16 character byte words
271 */
272 if( libuna_unicode_character_copy_to_utf16(
273 unicode_character,
274 utf16_string,
275 utf16_string_size,
276 utf16_string_index,
277 error ) != 1 )
278 {
279 libcerror_error_set(
280 error,
281 LIBCERROR_ERROR_DOMAIN_CONVERSION,
282 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
283 "%s: unable to copy Unicode character to UTF-16.",
284 function );
285
286 return( -1 );
287 }
288 }
289 /* Check if the string is terminated with an end-of-string character
290 */
291 if( unicode_character != 0 )
292 {
293 if( *utf16_string_index >= utf16_string_size )
294 {
295 libcerror_error_set(
296 error,
297 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
298 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
299 "%s: UTF-16 string too small.",
300 function );
301
302 return( -1 );
303 }
304 utf16_string[ *utf16_string_index ] = 0;
305
306 *utf16_string_index += 1;
307 }
308 return( 1 );
309 }
310
311 /* Compares an UTF-16 string with a byte stream
312 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
313 */
libuna_utf16_string_compare_with_byte_stream(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * byte_stream,size_t byte_stream_size,int codepage,libcerror_error_t ** error)314 int libuna_utf16_string_compare_with_byte_stream(
315 const libuna_utf16_character_t *utf16_string,
316 size_t utf16_string_size,
317 const uint8_t *byte_stream,
318 size_t byte_stream_size,
319 int codepage,
320 libcerror_error_t **error )
321 {
322 static char *function = "libuna_utf16_string_compare_with_byte_stream";
323 size_t byte_stream_index = 0;
324 size_t utf16_string_index = 0;
325 libuna_unicode_character_t utf16_unicode_character = 0;
326 libuna_unicode_character_t byte_stream_unicode_character = 0;
327
328 if( utf16_string == NULL )
329 {
330 libcerror_error_set(
331 error,
332 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
333 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
334 "%s: invalid UTF-16 string.",
335 function );
336
337 return( -1 );
338 }
339 if( utf16_string_size > (size_t) SSIZE_MAX )
340 {
341 libcerror_error_set(
342 error,
343 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
344 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
345 "%s: invalid UTF-16 string size value exceeds maximum.",
346 function );
347
348 return( -1 );
349 }
350 if( byte_stream == NULL )
351 {
352 libcerror_error_set(
353 error,
354 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
356 "%s: invalid byte stream.",
357 function );
358
359 return( -1 );
360 }
361 if( byte_stream_size > (size_t) SSIZE_MAX )
362 {
363 libcerror_error_set(
364 error,
365 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
367 "%s: invalid byte stream size value exceeds maximum.",
368 function );
369
370 return( -1 );
371 }
372 if( byte_stream_size == 0 )
373 {
374 libcerror_error_set(
375 error,
376 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
378 "%s: missing byte stream value.",
379 function );
380
381 return( -1 );
382 }
383 if( ( utf16_string_size >= 1 )
384 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
385 {
386 utf16_string_size -= 1;
387 }
388 /* Check if the byte stream is terminated with zero bytes
389 */
390 if( ( byte_stream_size >= 1 )
391 && ( byte_stream[ byte_stream_size - 1 ] == 0 ) )
392 {
393 byte_stream_size -= 1;
394 }
395 while( ( utf16_string_index < utf16_string_size )
396 && ( byte_stream_index < byte_stream_size ) )
397 {
398 /* Convert the UTF-16 character bytes into an Unicode character
399 */
400 if( libuna_unicode_character_copy_from_utf16(
401 &utf16_unicode_character,
402 utf16_string,
403 utf16_string_size,
404 &utf16_string_index,
405 error ) != 1 )
406 {
407 libcerror_error_set(
408 error,
409 LIBCERROR_ERROR_DOMAIN_CONVERSION,
410 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
411 "%s: unable to copy Unicode character from UTF-16.",
412 function );
413
414 return( -1 );
415 }
416 /* Convert the byte stream bytes into an Unicode character
417 */
418 if( libuna_unicode_character_copy_from_byte_stream(
419 &byte_stream_unicode_character,
420 byte_stream,
421 byte_stream_size,
422 &byte_stream_index,
423 codepage,
424 error ) != 1 )
425 {
426 libcerror_error_set(
427 error,
428 LIBCERROR_ERROR_DOMAIN_CONVERSION,
429 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
430 "%s: unable to copy Unicode character from byte stream.",
431 function );
432
433 return( -1 );
434 }
435 if( utf16_unicode_character < byte_stream_unicode_character )
436 {
437 return( LIBUNA_COMPARE_LESS );
438 }
439 else if( utf16_unicode_character > byte_stream_unicode_character )
440 {
441 return( LIBUNA_COMPARE_GREATER );
442 }
443 }
444 /* Check if both strings were entirely processed
445 */
446 if( utf16_string_index < utf16_string_size )
447 {
448 return( LIBUNA_COMPARE_GREATER );
449 }
450 else if( byte_stream_index < byte_stream_size )
451 {
452 return( LIBUNA_COMPARE_LESS );
453 }
454 return( LIBUNA_COMPARE_EQUAL );
455 }
456
457 /* Determines the size of an UTF-16 string from an UTF-7 stream
458 * Returns 1 if successful or -1 on error
459 */
libuna_utf16_string_size_from_utf7_stream(const uint8_t * utf7_stream,size_t utf7_stream_size,size_t * utf16_string_size,libcerror_error_t ** error)460 int libuna_utf16_string_size_from_utf7_stream(
461 const uint8_t *utf7_stream,
462 size_t utf7_stream_size,
463 size_t *utf16_string_size,
464 libcerror_error_t **error )
465 {
466 static char *function = "libuna_utf16_string_size_from_utf7_stream";
467 size_t utf7_stream_index = 0;
468 libuna_unicode_character_t unicode_character = 0;
469 uint32_t utf7_stream_base64_data = 0;
470
471 if( utf7_stream == NULL )
472 {
473 libcerror_error_set(
474 error,
475 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
476 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
477 "%s: invalid UTF-7 stream.",
478 function );
479
480 return( -1 );
481 }
482 if( utf7_stream_size > (size_t) SSIZE_MAX )
483 {
484 libcerror_error_set(
485 error,
486 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
487 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
488 "%s: invalid UTF-7 stream size value exceeds maximum.",
489 function );
490
491 return( -1 );
492 }
493 if( utf16_string_size == NULL )
494 {
495 libcerror_error_set(
496 error,
497 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
498 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
499 "%s: invalid UTF-16 string size.",
500 function );
501
502 return( -1 );
503 }
504 *utf16_string_size = 0;
505
506 if( utf7_stream_size == 0 )
507 {
508 return( 1 );
509 }
510 while( utf7_stream_index < utf7_stream_size )
511 {
512 /* Convert the UTF-7 stream bytes into an Unicode character
513 */
514 if( libuna_unicode_character_copy_from_utf7_stream(
515 &unicode_character,
516 utf7_stream,
517 utf7_stream_size,
518 &utf7_stream_index,
519 &utf7_stream_base64_data,
520 error ) != 1 )
521 {
522 libcerror_error_set(
523 error,
524 LIBCERROR_ERROR_DOMAIN_CONVERSION,
525 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
526 "%s: unable to copy Unicode character from UTF-7 stream.",
527 function );
528
529 return( -1 );
530 }
531 /* Determine how many UTF-16 character bytes are required
532 */
533 if( libuna_unicode_character_size_to_utf16(
534 unicode_character,
535 utf16_string_size,
536 error ) != 1 )
537 {
538 libcerror_error_set(
539 error,
540 LIBCERROR_ERROR_DOMAIN_CONVERSION,
541 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
542 "%s: unable to unable to determine size of Unicode character in UTF-16.",
543 function );
544
545 return( -1 );
546 }
547 }
548 /* Check if the string is terminated with an end-of-string character
549 */
550 if( unicode_character != 0 )
551 {
552 *utf16_string_size += 1;
553 }
554 return( 1 );
555 }
556
557 /* Copies an UTF-16 string from an UTF-7 stream
558 * Returns 1 if successful or -1 on error
559 */
libuna_utf16_string_copy_from_utf7_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf7_stream,size_t utf7_stream_size,libcerror_error_t ** error)560 int libuna_utf16_string_copy_from_utf7_stream(
561 libuna_utf16_character_t *utf16_string,
562 size_t utf16_string_size,
563 const uint8_t *utf7_stream,
564 size_t utf7_stream_size,
565 libcerror_error_t **error )
566 {
567 static char *function = "libuna_utf16_string_copy_from_utf7_stream";
568 size_t utf16_string_index = 0;
569
570 if( libuna_utf16_string_with_index_copy_from_utf7_stream(
571 utf16_string,
572 utf16_string_size,
573 &utf16_string_index,
574 utf7_stream,
575 utf7_stream_size,
576 error ) != 1 )
577 {
578 libcerror_error_set(
579 error,
580 LIBCERROR_ERROR_DOMAIN_RUNTIME,
581 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
582 "%s: unable to UTF-7 stream to UTF-16 string.",
583 function );
584
585 return( -1 );
586 }
587 return( 1 );
588 }
589
590 /* Copies an UTF-16 string from an UTF-7 stream
591 * Returns 1 if successful or -1 on error
592 */
libuna_utf16_string_with_index_copy_from_utf7_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * utf7_stream,size_t utf7_stream_size,libcerror_error_t ** error)593 int libuna_utf16_string_with_index_copy_from_utf7_stream(
594 libuna_utf16_character_t *utf16_string,
595 size_t utf16_string_size,
596 size_t *utf16_string_index,
597 const uint8_t *utf7_stream,
598 size_t utf7_stream_size,
599 libcerror_error_t **error )
600 {
601 static char *function = "libuna_utf16_string_with_index_copy_from_utf7_stream";
602 size_t utf7_stream_index = 0;
603 libuna_unicode_character_t unicode_character = 0;
604 uint32_t utf7_stream_base64_data = 0;
605
606 if( utf16_string == NULL )
607 {
608 libcerror_error_set(
609 error,
610 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
611 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
612 "%s: invalid UTF-16 string.",
613 function );
614
615 return( -1 );
616 }
617 if( utf16_string_size > (size_t) SSIZE_MAX )
618 {
619 libcerror_error_set(
620 error,
621 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
622 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
623 "%s: invalid UTF-16 string size value exceeds maximum.",
624 function );
625
626 return( -1 );
627 }
628 if( utf16_string_index == NULL )
629 {
630 libcerror_error_set(
631 error,
632 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
633 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
634 "%s: invalid UTF-16 string index.",
635 function );
636
637 return( -1 );
638 }
639 if( utf7_stream == NULL )
640 {
641 libcerror_error_set(
642 error,
643 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
644 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
645 "%s: invalid UTF-7 stream.",
646 function );
647
648 return( -1 );
649 }
650 if( utf7_stream_size > (size_t) SSIZE_MAX )
651 {
652 libcerror_error_set(
653 error,
654 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
655 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
656 "%s: invalid UTF-7 stream size value exceeds maximum.",
657 function );
658
659 return( -1 );
660 }
661 if( utf7_stream_size == 0 )
662 {
663 libcerror_error_set(
664 error,
665 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
666 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
667 "%s: missing UTF-7 stream value.",
668 function );
669
670 return( -1 );
671 }
672 while( utf7_stream_index < utf7_stream_size )
673 {
674 /* Convert the UTF-7 stream bytes into an Unicode character
675 */
676 if( libuna_unicode_character_copy_from_utf7_stream(
677 &unicode_character,
678 utf7_stream,
679 utf7_stream_size,
680 &utf7_stream_index,
681 &utf7_stream_base64_data,
682 error ) != 1 )
683 {
684 libcerror_error_set(
685 error,
686 LIBCERROR_ERROR_DOMAIN_CONVERSION,
687 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
688 "%s: unable to copy Unicode character from UTF-7 stream.",
689 function );
690
691 return( -1 );
692 }
693 /* Convert the Unicode character into UTF-16 character bytes
694 */
695 if( libuna_unicode_character_copy_to_utf16(
696 unicode_character,
697 utf16_string,
698 utf16_string_size,
699 utf16_string_index,
700 error ) != 1 )
701 {
702 libcerror_error_set(
703 error,
704 LIBCERROR_ERROR_DOMAIN_CONVERSION,
705 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
706 "%s: unable to copy Unicode character to UTF-16.",
707 function );
708
709 return( -1 );
710 }
711 }
712 /* Check if the string is terminated with an end-of-string character
713 */
714 if( unicode_character != 0 )
715 {
716 if( *utf16_string_index >= utf16_string_size )
717 {
718 libcerror_error_set(
719 error,
720 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
721 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
722 "%s: UTF-16 string too small.",
723 function );
724
725 return( -1 );
726 }
727 utf16_string[ *utf16_string_index ] = 0;
728
729 *utf16_string_index += 1;
730 }
731 return( 1 );
732 }
733
734 /* Compares an UTF-16 string with an UTF-7 stream
735 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
736 */
libuna_utf16_string_compare_with_utf7_stream(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf7_stream,size_t utf7_stream_size,libcerror_error_t ** error)737 int libuna_utf16_string_compare_with_utf7_stream(
738 const libuna_utf16_character_t *utf16_string,
739 size_t utf16_string_size,
740 const uint8_t *utf7_stream,
741 size_t utf7_stream_size,
742 libcerror_error_t **error )
743 {
744 static char *function = "libuna_utf16_string_compare_with_utf7_stream";
745 size_t utf16_string_index = 0;
746 size_t utf7_stream_index = 0;
747 libuna_unicode_character_t utf16_unicode_character = 0;
748 libuna_unicode_character_t utf7_stream_unicode_character = 0;
749 uint32_t utf7_stream_base64_data = 0;
750
751 if( utf16_string == NULL )
752 {
753 libcerror_error_set(
754 error,
755 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
756 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
757 "%s: invalid UTF-16 string.",
758 function );
759
760 return( -1 );
761 }
762 if( utf16_string_size > (size_t) SSIZE_MAX )
763 {
764 libcerror_error_set(
765 error,
766 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
767 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
768 "%s: invalid UTF-16 string size value exceeds maximum.",
769 function );
770
771 return( -1 );
772 }
773 if( utf7_stream == NULL )
774 {
775 libcerror_error_set(
776 error,
777 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
778 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
779 "%s: invalid UTF-7 stream.",
780 function );
781
782 return( -1 );
783 }
784 if( utf7_stream_size > (size_t) SSIZE_MAX )
785 {
786 libcerror_error_set(
787 error,
788 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
789 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
790 "%s: invalid UTF-7 stream size value exceeds maximum.",
791 function );
792
793 return( -1 );
794 }
795 if( utf7_stream_size == 0 )
796 {
797 libcerror_error_set(
798 error,
799 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
800 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
801 "%s: missing UTF-7 stream value.",
802 function );
803
804 return( -1 );
805 }
806 if( ( utf16_string_size >= 1 )
807 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
808 {
809 utf16_string_size -= 1;
810 }
811 /* Check if the UTF-7 stream is terminated with zero bytes
812 */
813 if( ( utf7_stream_size >= 1 )
814 && ( utf7_stream[ utf7_stream_size - 1 ] == 0 ) )
815 {
816 utf7_stream_size -= 1;
817 }
818 while( ( utf16_string_index < utf16_string_size )
819 && ( utf7_stream_index < utf7_stream_size ) )
820 {
821 /* Convert the UTF-16 character bytes into an Unicode character
822 */
823 if( libuna_unicode_character_copy_from_utf16(
824 &utf16_unicode_character,
825 utf16_string,
826 utf16_string_size,
827 &utf16_string_index,
828 error ) != 1 )
829 {
830 libcerror_error_set(
831 error,
832 LIBCERROR_ERROR_DOMAIN_CONVERSION,
833 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
834 "%s: unable to copy Unicode character from UTF-16.",
835 function );
836
837 return( -1 );
838 }
839 /* Convert the UTF-7 character bytes into an Unicode character
840 */
841 if( libuna_unicode_character_copy_from_utf7_stream(
842 &utf7_stream_unicode_character,
843 utf7_stream,
844 utf7_stream_size,
845 &utf7_stream_index,
846 &utf7_stream_base64_data,
847 error ) != 1 )
848 {
849 libcerror_error_set(
850 error,
851 LIBCERROR_ERROR_DOMAIN_CONVERSION,
852 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
853 "%s: unable to copy Unicode character from UTF-7 stream.",
854 function );
855
856 return( -1 );
857 }
858 if( utf16_unicode_character < utf7_stream_unicode_character )
859 {
860 return( LIBUNA_COMPARE_LESS );
861 }
862 else if( utf16_unicode_character > utf7_stream_unicode_character )
863 {
864 return( LIBUNA_COMPARE_GREATER );
865 }
866 }
867 /* Check if both strings were entirely processed
868 */
869 if( utf16_string_index < utf16_string_size )
870 {
871 return( LIBUNA_COMPARE_GREATER );
872 }
873 else if( utf7_stream_index < utf7_stream_size )
874 {
875 return( LIBUNA_COMPARE_LESS );
876 }
877 return( LIBUNA_COMPARE_EQUAL );
878 }
879
880 /* Determines the size of an UTF-16 string from an UTF-8 string
881 * Returns 1 if successful or -1 on error
882 */
libuna_utf16_string_size_from_utf8(const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,size_t * utf16_string_size,libcerror_error_t ** error)883 int libuna_utf16_string_size_from_utf8(
884 const libuna_utf8_character_t *utf8_string,
885 size_t utf8_string_size,
886 size_t *utf16_string_size,
887 libcerror_error_t **error )
888 {
889 static char *function = "libuna_utf16_string_size_from_utf8";
890 size_t utf8_string_index = 0;
891 libuna_unicode_character_t unicode_character = 0;
892
893 if( utf8_string == NULL )
894 {
895 libcerror_error_set(
896 error,
897 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
898 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
899 "%s: invalid UTF-8 string.",
900 function );
901
902 return( -1 );
903 }
904 if( utf8_string_size > (size_t) SSIZE_MAX )
905 {
906 libcerror_error_set(
907 error,
908 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
909 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
910 "%s: invalid UTF-8 string size value exceeds maximum.",
911 function );
912
913 return( -1 );
914 }
915 if( utf16_string_size == NULL )
916 {
917 libcerror_error_set(
918 error,
919 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
920 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
921 "%s: invalid UTF-16 string size.",
922 function );
923
924 return( -1 );
925 }
926 *utf16_string_size = 0;
927
928 if( utf8_string_size == 0 )
929 {
930 return( 1 );
931 }
932 while( utf8_string_index < utf8_string_size )
933 {
934 /* Convert the UTF-8 character bytes into an Unicode character
935 */
936 if( libuna_unicode_character_copy_from_utf8(
937 &unicode_character,
938 utf8_string,
939 utf8_string_size,
940 &utf8_string_index,
941 error ) != 1 )
942 {
943 libcerror_error_set(
944 error,
945 LIBCERROR_ERROR_DOMAIN_CONVERSION,
946 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
947 "%s: unable to copy Unicode character from UTF-8.",
948 function );
949
950 return( -1 );
951 }
952 /* Determine how many UTF-16 character bytes are required
953 */
954 if( libuna_unicode_character_size_to_utf16(
955 unicode_character,
956 utf16_string_size,
957 error ) != 1 )
958 {
959 libcerror_error_set(
960 error,
961 LIBCERROR_ERROR_DOMAIN_CONVERSION,
962 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
963 "%s: unable to unable to determine size of Unicode character in UTF-16.",
964 function );
965
966 return( -1 );
967 }
968 }
969 /* Check if the string is terminated with an end-of-string character
970 */
971 if( unicode_character != 0 )
972 {
973 *utf16_string_size += 1;
974 }
975 return( 1 );
976 }
977
978 /* Copies an UTF-16 string from an UTF-8 string
979 * Returns 1 if successful or -1 on error
980 */
libuna_utf16_string_copy_from_utf8(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)981 int libuna_utf16_string_copy_from_utf8(
982 libuna_utf16_character_t *utf16_string,
983 size_t utf16_string_size,
984 const libuna_utf8_character_t *utf8_string,
985 size_t utf8_string_size,
986 libcerror_error_t **error )
987 {
988 static char *function = "libuna_utf16_string_copy_from_utf8";
989 size_t utf16_string_index = 0;
990
991 if( libuna_utf16_string_with_index_copy_from_utf8(
992 utf16_string,
993 utf16_string_size,
994 &utf16_string_index,
995 utf8_string,
996 utf8_string_size,
997 error ) != 1 )
998 {
999 libcerror_error_set(
1000 error,
1001 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1002 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1003 "%s: unable to copy UTF-8 string to UTF-16 string.",
1004 function );
1005
1006 return( -1 );
1007 }
1008 return( 1 );
1009 }
1010
1011 /* Copies an UTF-16 string from an UTF-8 string
1012 * Returns 1 if successful or -1 on error
1013 */
libuna_utf16_string_with_index_copy_from_utf8(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1014 int libuna_utf16_string_with_index_copy_from_utf8(
1015 libuna_utf16_character_t *utf16_string,
1016 size_t utf16_string_size,
1017 size_t *utf16_string_index,
1018 const libuna_utf8_character_t *utf8_string,
1019 size_t utf8_string_size,
1020 libcerror_error_t **error )
1021 {
1022 static char *function = "libuna_utf16_string_with_index_copy_from_utf8";
1023 size_t utf8_string_index = 0;
1024 libuna_unicode_character_t unicode_character = 0;
1025
1026 if( utf16_string == NULL )
1027 {
1028 libcerror_error_set(
1029 error,
1030 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1031 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1032 "%s: invalid UTF-16 string.",
1033 function );
1034
1035 return( -1 );
1036 }
1037 if( utf16_string_size > (size_t) SSIZE_MAX )
1038 {
1039 libcerror_error_set(
1040 error,
1041 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1042 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1043 "%s: invalid UTF-16 string size value exceeds maximum.",
1044 function );
1045
1046 return( -1 );
1047 }
1048 if( utf16_string_index == NULL )
1049 {
1050 libcerror_error_set(
1051 error,
1052 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1053 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1054 "%s: invalid UTF-16 string index.",
1055 function );
1056
1057 return( -1 );
1058 }
1059 if( utf8_string == NULL )
1060 {
1061 libcerror_error_set(
1062 error,
1063 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1064 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1065 "%s: invalid UTF-8 string.",
1066 function );
1067
1068 return( -1 );
1069 }
1070 if( utf8_string_size > (size_t) SSIZE_MAX )
1071 {
1072 libcerror_error_set(
1073 error,
1074 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1075 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1076 "%s: invalid UTF-8 string size value exceeds maximum.",
1077 function );
1078
1079 return( -1 );
1080 }
1081 if( utf8_string_size == 0 )
1082 {
1083 libcerror_error_set(
1084 error,
1085 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1086 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1087 "%s: missing UTF-8 string value.",
1088 function );
1089
1090 return( -1 );
1091 }
1092 while( utf8_string_index < utf8_string_size )
1093 {
1094 /* Convert the UTF-8 character bytes into an Unicode character
1095 */
1096 if( libuna_unicode_character_copy_from_utf8(
1097 &unicode_character,
1098 utf8_string,
1099 utf8_string_size,
1100 &utf8_string_index,
1101 error ) != 1 )
1102 {
1103 libcerror_error_set(
1104 error,
1105 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1106 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1107 "%s: unable to copy Unicode character from UTF-8.",
1108 function );
1109
1110 return( -1 );
1111 }
1112 /* Convert the Unicode character into UTF-16 character bytes
1113 */
1114 if( libuna_unicode_character_copy_to_utf16(
1115 unicode_character,
1116 utf16_string,
1117 utf16_string_size,
1118 utf16_string_index,
1119 error ) != 1 )
1120 {
1121 libcerror_error_set(
1122 error,
1123 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1124 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1125 "%s: unable to copy Unicode character to UTF-16.",
1126 function );
1127
1128 return( -1 );
1129 }
1130 }
1131 /* Check if the string is terminated with an end-of-string character
1132 */
1133 if( unicode_character != 0 )
1134 {
1135 if( *utf16_string_index >= utf16_string_size )
1136 {
1137 libcerror_error_set(
1138 error,
1139 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1140 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1141 "%s: UTF-16 string too small.",
1142 function );
1143
1144 return( -1 );
1145 }
1146 utf16_string[ *utf16_string_index ] = 0;
1147
1148 *utf16_string_index += 1;
1149 }
1150 return( 1 );
1151 }
1152
1153 /* Determines the size of an UTF-16 string from an UTF-8 stream
1154 * Returns 1 if successful or -1 on error
1155 */
libuna_utf16_string_size_from_utf8_stream(const uint8_t * utf8_stream,size_t utf8_stream_size,size_t * utf16_string_size,libcerror_error_t ** error)1156 int libuna_utf16_string_size_from_utf8_stream(
1157 const uint8_t *utf8_stream,
1158 size_t utf8_stream_size,
1159 size_t *utf16_string_size,
1160 libcerror_error_t **error )
1161 {
1162 static char *function = "libuna_utf16_string_size_from_utf8_stream";
1163 size_t utf8_stream_index = 0;
1164 libuna_unicode_character_t unicode_character = 0;
1165
1166 if( utf8_stream == NULL )
1167 {
1168 libcerror_error_set(
1169 error,
1170 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1171 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1172 "%s: invalid UTF-8 stream.",
1173 function );
1174
1175 return( -1 );
1176 }
1177 if( utf8_stream_size > (size_t) SSIZE_MAX )
1178 {
1179 libcerror_error_set(
1180 error,
1181 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1182 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1183 "%s: invalid UTF-8 stream size value exceeds maximum.",
1184 function );
1185
1186 return( -1 );
1187 }
1188 if( utf16_string_size == NULL )
1189 {
1190 libcerror_error_set(
1191 error,
1192 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1193 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1194 "%s: invalid UTF-16 string size.",
1195 function );
1196
1197 return( -1 );
1198 }
1199 *utf16_string_size = 0;
1200
1201 if( utf8_stream_size == 0 )
1202 {
1203 return( 1 );
1204 }
1205 /* Check if UTF-8 stream starts with a byte order mark (BOM)
1206 */
1207 if( utf8_stream_size >= 3 )
1208 {
1209 if( ( utf8_stream[ 0 ] == 0x0ef )
1210 && ( utf8_stream[ 1 ] == 0x0bb )
1211 && ( utf8_stream[ 2 ] == 0x0bf ) )
1212 {
1213 utf8_stream_index += 3;
1214 }
1215 }
1216 while( utf8_stream_index < utf8_stream_size )
1217 {
1218 /* Convert the UTF-8 stream bytes into an Unicode character
1219 */
1220 if( libuna_unicode_character_copy_from_utf8(
1221 &unicode_character,
1222 utf8_stream,
1223 utf8_stream_size,
1224 &utf8_stream_index,
1225 error ) != 1 )
1226 {
1227 libcerror_error_set(
1228 error,
1229 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1230 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1231 "%s: unable to copy Unicode character from UTF-8 stream.",
1232 function );
1233
1234 return( -1 );
1235 }
1236 /* Determine how many UTF-16 character bytes are required
1237 */
1238 if( libuna_unicode_character_size_to_utf16(
1239 unicode_character,
1240 utf16_string_size,
1241 error ) != 1 )
1242 {
1243 libcerror_error_set(
1244 error,
1245 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1246 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1247 "%s: unable to unable to determine size of Unicode character in UTF-16.",
1248 function );
1249
1250 return( -1 );
1251 }
1252 }
1253 /* Check if the string is terminated with an end-of-string character
1254 */
1255 if( unicode_character != 0 )
1256 {
1257 *utf16_string_size += 1;
1258 }
1259 return( 1 );
1260 }
1261
1262 /* Copies an UTF-16 string from an UTF-8 stream
1263 * Returns 1 if successful or -1 on error
1264 */
libuna_utf16_string_copy_from_utf8_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf8_stream,size_t utf8_stream_size,libcerror_error_t ** error)1265 int libuna_utf16_string_copy_from_utf8_stream(
1266 libuna_utf16_character_t *utf16_string,
1267 size_t utf16_string_size,
1268 const uint8_t *utf8_stream,
1269 size_t utf8_stream_size,
1270 libcerror_error_t **error )
1271 {
1272 static char *function = "libuna_utf16_string_copy_from_utf8_stream";
1273 size_t utf16_string_index = 0;
1274
1275 if( libuna_utf16_string_with_index_copy_from_utf8_stream(
1276 utf16_string,
1277 utf16_string_size,
1278 &utf16_string_index,
1279 utf8_stream,
1280 utf8_stream_size,
1281 error ) != 1 )
1282 {
1283 libcerror_error_set(
1284 error,
1285 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1286 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1287 "%s: unable to UTF-8 stream to UTF-16 string.",
1288 function );
1289
1290 return( -1 );
1291 }
1292 return( 1 );
1293 }
1294
1295 /* Copies an UTF-16 string from an UTF-8 stream
1296 * Returns 1 if successful or -1 on error
1297 */
libuna_utf16_string_with_index_copy_from_utf8_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * utf8_stream,size_t utf8_stream_size,libcerror_error_t ** error)1298 int libuna_utf16_string_with_index_copy_from_utf8_stream(
1299 libuna_utf16_character_t *utf16_string,
1300 size_t utf16_string_size,
1301 size_t *utf16_string_index,
1302 const uint8_t *utf8_stream,
1303 size_t utf8_stream_size,
1304 libcerror_error_t **error )
1305 {
1306 static char *function = "libuna_utf16_string_with_index_copy_from_utf8_stream";
1307 size_t utf8_stream_index = 0;
1308 libuna_unicode_character_t unicode_character = 0;
1309
1310 if( utf16_string == NULL )
1311 {
1312 libcerror_error_set(
1313 error,
1314 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1315 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1316 "%s: invalid UTF-16 string.",
1317 function );
1318
1319 return( -1 );
1320 }
1321 if( utf16_string_size > (size_t) SSIZE_MAX )
1322 {
1323 libcerror_error_set(
1324 error,
1325 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1326 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1327 "%s: invalid UTF-16 string size value exceeds maximum.",
1328 function );
1329
1330 return( -1 );
1331 }
1332 if( utf16_string_index == NULL )
1333 {
1334 libcerror_error_set(
1335 error,
1336 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1337 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1338 "%s: invalid UTF-16 string index.",
1339 function );
1340
1341 return( -1 );
1342 }
1343 if( utf8_stream == NULL )
1344 {
1345 libcerror_error_set(
1346 error,
1347 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1348 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1349 "%s: invalid UTF-8 stream.",
1350 function );
1351
1352 return( -1 );
1353 }
1354 if( utf8_stream_size > (size_t) SSIZE_MAX )
1355 {
1356 libcerror_error_set(
1357 error,
1358 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1359 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1360 "%s: invalid UTF-8 stream size value exceeds maximum.",
1361 function );
1362
1363 return( -1 );
1364 }
1365 if( utf8_stream_size == 0 )
1366 {
1367 libcerror_error_set(
1368 error,
1369 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1370 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1371 "%s: missing UTF-8 stream value.",
1372 function );
1373
1374 return( -1 );
1375 }
1376 /* Check if UTF-8 stream starts with a byte order mark (BOM)
1377 */
1378 if( utf8_stream_size >= 3 )
1379 {
1380 if( ( utf8_stream[ 0 ] == 0x0ef )
1381 && ( utf8_stream[ 1 ] == 0x0bb )
1382 && ( utf8_stream[ 2 ] == 0x0bf ) )
1383 {
1384 utf8_stream_index += 3;
1385 }
1386 }
1387 while( utf8_stream_index < utf8_stream_size )
1388 {
1389 /* Convert the UTF-8 stream bytes into an Unicode character
1390 */
1391 if( libuna_unicode_character_copy_from_utf8(
1392 &unicode_character,
1393 utf8_stream,
1394 utf8_stream_size,
1395 &utf8_stream_index,
1396 error ) != 1 )
1397 {
1398 libcerror_error_set(
1399 error,
1400 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1401 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1402 "%s: unable to copy Unicode character from UTF-8 stream.",
1403 function );
1404
1405 return( -1 );
1406 }
1407 /* Convert the Unicode character into UTF-16 character bytes
1408 */
1409 if( libuna_unicode_character_copy_to_utf16(
1410 unicode_character,
1411 utf16_string,
1412 utf16_string_size,
1413 utf16_string_index,
1414 error ) != 1 )
1415 {
1416 libcerror_error_set(
1417 error,
1418 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1419 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1420 "%s: unable to copy Unicode character to UTF-16.",
1421 function );
1422
1423 return( -1 );
1424 }
1425 }
1426 /* Check if the string is terminated with an end-of-string character
1427 */
1428 if( unicode_character != 0 )
1429 {
1430 if( *utf16_string_index >= utf16_string_size )
1431 {
1432 libcerror_error_set(
1433 error,
1434 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1435 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1436 "%s: UTF-16 string too small.",
1437 function );
1438
1439 return( -1 );
1440 }
1441 utf16_string[ *utf16_string_index ] = 0;
1442
1443 *utf16_string_index += 1;
1444 }
1445 return( 1 );
1446 }
1447
1448 /* Compares an UTF-16 string with an UTF-8 stream
1449 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
1450 */
libuna_utf16_string_compare_with_utf8_stream(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf8_stream,size_t utf8_stream_size,libcerror_error_t ** error)1451 int libuna_utf16_string_compare_with_utf8_stream(
1452 const libuna_utf16_character_t *utf16_string,
1453 size_t utf16_string_size,
1454 const uint8_t *utf8_stream,
1455 size_t utf8_stream_size,
1456 libcerror_error_t **error )
1457 {
1458 static char *function = "libuna_utf16_string_compare_with_utf8_stream";
1459 size_t utf16_string_index = 0;
1460 size_t utf8_stream_index = 0;
1461 libuna_unicode_character_t utf16_unicode_character = 0;
1462 libuna_unicode_character_t utf8_stream_unicode_character = 0;
1463
1464 if( utf16_string == NULL )
1465 {
1466 libcerror_error_set(
1467 error,
1468 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1469 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1470 "%s: invalid UTF-16 string.",
1471 function );
1472
1473 return( -1 );
1474 }
1475 if( utf16_string_size > (size_t) SSIZE_MAX )
1476 {
1477 libcerror_error_set(
1478 error,
1479 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1480 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1481 "%s: invalid UTF-16 string size value exceeds maximum.",
1482 function );
1483
1484 return( -1 );
1485 }
1486 if( utf8_stream == NULL )
1487 {
1488 libcerror_error_set(
1489 error,
1490 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1491 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1492 "%s: invalid UTF-8 stream.",
1493 function );
1494
1495 return( -1 );
1496 }
1497 if( utf8_stream_size > (size_t) SSIZE_MAX )
1498 {
1499 libcerror_error_set(
1500 error,
1501 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1502 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1503 "%s: invalid UTF-8 stream size value exceeds maximum.",
1504 function );
1505
1506 return( -1 );
1507 }
1508 if( utf8_stream_size == 0 )
1509 {
1510 libcerror_error_set(
1511 error,
1512 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1513 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1514 "%s: missing UTF-8 stream value.",
1515 function );
1516
1517 return( -1 );
1518 }
1519 /* Check if UTF-8 stream starts with a byte order mark (BOM)
1520 */
1521 if( utf8_stream_size >= 3 )
1522 {
1523 if( ( utf8_stream[ 0 ] == 0x0ef )
1524 && ( utf8_stream[ 1 ] == 0x0bb )
1525 && ( utf8_stream[ 2 ] == 0x0bf ) )
1526 {
1527 utf8_stream_index += 3;
1528 }
1529 }
1530 if( ( utf16_string_size >= 1 )
1531 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
1532 {
1533 utf16_string_size -= 1;
1534 }
1535 /* Check if the UTF-8 stream is terminated with zero bytes
1536 */
1537 if( ( utf8_stream_size >= 1 )
1538 && ( utf8_stream[ utf8_stream_size - 1 ] == 0 ) )
1539 {
1540 utf8_stream_size -= 1;
1541 }
1542 while( ( utf16_string_index < utf16_string_size )
1543 && ( utf8_stream_index < utf8_stream_size ) )
1544 {
1545 /* Convert the UTF-16 character bytes into an Unicode character
1546 */
1547 if( libuna_unicode_character_copy_from_utf16(
1548 &utf16_unicode_character,
1549 utf16_string,
1550 utf16_string_size,
1551 &utf16_string_index,
1552 error ) != 1 )
1553 {
1554 libcerror_error_set(
1555 error,
1556 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1557 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1558 "%s: unable to copy Unicode character from UTF-16.",
1559 function );
1560
1561 return( -1 );
1562 }
1563 /* Convert the UTF-8 character bytes into an Unicode character
1564 */
1565 if( libuna_unicode_character_copy_from_utf8(
1566 &utf8_stream_unicode_character,
1567 utf8_stream,
1568 utf8_stream_size,
1569 &utf8_stream_index,
1570 error ) != 1 )
1571 {
1572 libcerror_error_set(
1573 error,
1574 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1575 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1576 "%s: unable to copy Unicode character from UTF-8 stream.",
1577 function );
1578
1579 return( -1 );
1580 }
1581 if( utf16_unicode_character < utf8_stream_unicode_character )
1582 {
1583 return( LIBUNA_COMPARE_LESS );
1584 }
1585 else if( utf16_unicode_character > utf8_stream_unicode_character )
1586 {
1587 return( LIBUNA_COMPARE_GREATER );
1588 }
1589 }
1590 /* Check if both strings were entirely processed
1591 */
1592 if( utf16_string_index < utf16_string_size )
1593 {
1594 return( LIBUNA_COMPARE_GREATER );
1595 }
1596 else if( utf8_stream_index < utf8_stream_size )
1597 {
1598 return( LIBUNA_COMPARE_LESS );
1599 }
1600 return( LIBUNA_COMPARE_EQUAL );
1601 }
1602
1603 /* Determines the size of an UTF-16 string from an UTF-16 stream
1604 * Returns 1 if successful or -1 on error
1605 */
libuna_utf16_string_size_from_utf16_stream(const uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,size_t * utf16_string_size,libcerror_error_t ** error)1606 int libuna_utf16_string_size_from_utf16_stream(
1607 const uint8_t *utf16_stream,
1608 size_t utf16_stream_size,
1609 int byte_order,
1610 size_t *utf16_string_size,
1611 libcerror_error_t **error )
1612 {
1613 static char *function = "libuna_utf16_string_size_from_utf16_stream";
1614 size_t utf16_stream_index = 0;
1615 libuna_unicode_character_t unicode_character = 0;
1616 int read_byte_order = 0;
1617
1618 if( utf16_stream == NULL )
1619 {
1620 libcerror_error_set(
1621 error,
1622 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1623 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1624 "%s: invalid UTF-16 stream.",
1625 function );
1626
1627 return( -1 );
1628 }
1629 if( utf16_stream_size > (size_t) SSIZE_MAX )
1630 {
1631 libcerror_error_set(
1632 error,
1633 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1634 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1635 "%s: invalid UTF-16 stream size value exceeds maximum.",
1636 function );
1637
1638 return( -1 );
1639 }
1640 if( ( utf16_stream_size % 2 ) != 0 )
1641 {
1642 libcerror_error_set(
1643 error,
1644 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1645 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1646 "%s: missing UTF-16 stream value.",
1647 function );
1648
1649 return( -1 );
1650 }
1651 if( utf16_string_size == NULL )
1652 {
1653 libcerror_error_set(
1654 error,
1655 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1656 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1657 "%s: invalid UTF-16 string size.",
1658 function );
1659
1660 return( -1 );
1661 }
1662 *utf16_string_size = 0;
1663
1664 if( utf16_stream_size == 0 )
1665 {
1666 return( 1 );
1667 }
1668 /* Check if UTF-16 stream is in big or little endian
1669 */
1670 if( utf16_stream_size >= 2 )
1671 {
1672 if( ( utf16_stream[ 0 ] == 0x0ff )
1673 && ( utf16_stream[ 1 ] == 0x0fe ) )
1674 {
1675 read_byte_order = LIBUNA_ENDIAN_LITTLE;
1676 utf16_stream_index = 2;
1677 }
1678 else if( ( utf16_stream[ 0 ] == 0x0fe )
1679 && ( utf16_stream[ 1 ] == 0x0ff ) )
1680 {
1681 read_byte_order = LIBUNA_ENDIAN_BIG;
1682 utf16_stream_index = 2;
1683 }
1684 if( byte_order == 0 )
1685 {
1686 byte_order = read_byte_order;
1687 }
1688 }
1689 if( ( byte_order != LIBUNA_ENDIAN_BIG )
1690 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
1691 {
1692 libcerror_error_set(
1693 error,
1694 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1695 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1696 "%s: unsupported byte order.",
1697 function );
1698
1699 return( -1 );
1700 }
1701 while( ( utf16_stream_index + 1 ) < utf16_stream_size )
1702 {
1703 /* Convert the UTF-16 stream bytes into an Unicode character
1704 */
1705 if( libuna_unicode_character_copy_from_utf16_stream(
1706 &unicode_character,
1707 utf16_stream,
1708 utf16_stream_size,
1709 &utf16_stream_index,
1710 byte_order,
1711 error ) != 1 )
1712 {
1713 libcerror_error_set(
1714 error,
1715 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1716 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1717 "%s: unable to copy Unicode character from UTF-16 stream.",
1718 function );
1719
1720 return( -1 );
1721 }
1722 /* Determine how many UTF-16 character bytes are required
1723 */
1724 if( libuna_unicode_character_size_to_utf16(
1725 unicode_character,
1726 utf16_string_size,
1727 error ) != 1 )
1728 {
1729 libcerror_error_set(
1730 error,
1731 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1732 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1733 "%s: unable to unable to determine size of Unicode character in UTF-16.",
1734 function );
1735
1736 return( -1 );
1737 }
1738 }
1739 /* Check if the string is terminated with an end-of-string character
1740 */
1741 if( unicode_character != 0 )
1742 {
1743 *utf16_string_size += 1;
1744 }
1745 return( 1 );
1746 }
1747
1748 /* Copies an UTF-16 string from an UTF-16 stream
1749 * Returns 1 if successful or -1 on error
1750 */
libuna_utf16_string_copy_from_utf16_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,libcerror_error_t ** error)1751 int libuna_utf16_string_copy_from_utf16_stream(
1752 libuna_utf16_character_t *utf16_string,
1753 size_t utf16_string_size,
1754 const uint8_t *utf16_stream,
1755 size_t utf16_stream_size,
1756 int byte_order,
1757 libcerror_error_t **error )
1758 {
1759 static char *function = "libuna_utf16_string_copy_from_utf16_stream";
1760 size_t utf16_string_index = 0;
1761
1762 if( libuna_utf16_string_with_index_copy_from_utf16_stream(
1763 utf16_string,
1764 utf16_string_size,
1765 &utf16_string_index,
1766 utf16_stream,
1767 utf16_stream_size,
1768 byte_order,
1769 error ) != 1 )
1770 {
1771 libcerror_error_set(
1772 error,
1773 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1774 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1775 "%s: unable to copy UTF-16 stream to UTF-16 string.",
1776 function );
1777
1778 return( -1 );
1779 }
1780 return( 1 );
1781 }
1782
1783 /* Copies an UTF-16 string from an UTF-16 stream
1784 * Returns 1 if successful or -1 on error
1785 */
libuna_utf16_string_with_index_copy_from_utf16_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,libcerror_error_t ** error)1786 int libuna_utf16_string_with_index_copy_from_utf16_stream(
1787 libuna_utf16_character_t *utf16_string,
1788 size_t utf16_string_size,
1789 size_t *utf16_string_index,
1790 const uint8_t *utf16_stream,
1791 size_t utf16_stream_size,
1792 int byte_order,
1793 libcerror_error_t **error )
1794 {
1795 static char *function = "libuna_utf16_string_with_index_copy_from_utf16_stream";
1796 size_t utf16_stream_index = 0;
1797 libuna_unicode_character_t unicode_character = 0;
1798 int read_byte_order = 0;
1799
1800 if( utf16_string == NULL )
1801 {
1802 libcerror_error_set(
1803 error,
1804 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1805 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1806 "%s: invalid UTF-16 string.",
1807 function );
1808
1809 return( -1 );
1810 }
1811 if( utf16_string_size > (size_t) SSIZE_MAX )
1812 {
1813 libcerror_error_set(
1814 error,
1815 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1816 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1817 "%s: invalid UTF-16 string size value exceeds maximum.",
1818 function );
1819
1820 return( -1 );
1821 }
1822 if( utf16_string_index == NULL )
1823 {
1824 libcerror_error_set(
1825 error,
1826 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1827 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1828 "%s: invalid UTF-16 string index.",
1829 function );
1830
1831 return( -1 );
1832 }
1833 if( utf16_stream == NULL )
1834 {
1835 libcerror_error_set(
1836 error,
1837 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1838 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1839 "%s: invalid UTF-16 stream.",
1840 function );
1841
1842 return( -1 );
1843 }
1844 if( utf16_stream_size > (size_t) SSIZE_MAX )
1845 {
1846 libcerror_error_set(
1847 error,
1848 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1849 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1850 "%s: invalid UTF-16 stream size value exceeds maximum.",
1851 function );
1852
1853 return( -1 );
1854 }
1855 if( ( utf16_stream_size == 0 )
1856 || ( ( utf16_stream_size % 2 ) != 0 ) )
1857 {
1858 libcerror_error_set(
1859 error,
1860 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1861 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1862 "%s: missing UTF-16 stream value.",
1863 function );
1864
1865 return( -1 );
1866 }
1867 /* Check if UTF-16 stream is in big or little endian
1868 */
1869 if( utf16_stream_size >= 2 )
1870 {
1871 if( ( utf16_stream[ 0 ] == 0x0ff )
1872 && ( utf16_stream[ 1 ] == 0x0fe ) )
1873 {
1874 read_byte_order = LIBUNA_ENDIAN_LITTLE;
1875 utf16_stream_index = 2;
1876 }
1877 else if( ( utf16_stream[ 0 ] == 0x0fe )
1878 && ( utf16_stream[ 1 ] == 0x0ff ) )
1879 {
1880 read_byte_order = LIBUNA_ENDIAN_BIG;
1881 utf16_stream_index = 2;
1882 }
1883 if( byte_order == 0 )
1884 {
1885 byte_order = read_byte_order;
1886 }
1887 }
1888 if( ( byte_order != LIBUNA_ENDIAN_BIG )
1889 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
1890 {
1891 libcerror_error_set(
1892 error,
1893 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1894 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1895 "%s: unsupported byte order.",
1896 function );
1897
1898 return( -1 );
1899 }
1900 while( ( utf16_stream_index + 1 ) < utf16_stream_size )
1901 {
1902 /* Convert the UTF-16 stream bytes into an Unicode character
1903 */
1904 if( libuna_unicode_character_copy_from_utf16_stream(
1905 &unicode_character,
1906 utf16_stream,
1907 utf16_stream_size,
1908 &utf16_stream_index,
1909 byte_order,
1910 error ) != 1 )
1911 {
1912 libcerror_error_set(
1913 error,
1914 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1915 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1916 "%s: unable to copy Unicode character from UTF-16 stream.",
1917 function );
1918
1919 return( -1 );
1920 }
1921 /* Convert the Unicode character into UTF-16 character bytes
1922 */
1923 if( libuna_unicode_character_copy_to_utf16(
1924 unicode_character,
1925 utf16_string,
1926 utf16_string_size,
1927 utf16_string_index,
1928 error ) != 1 )
1929 {
1930 libcerror_error_set(
1931 error,
1932 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1933 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1934 "%s: unable to copy Unicode character to UTF-16.",
1935 function );
1936
1937 return( -1 );
1938 }
1939 }
1940 /* Check if the string is terminated with an end-of-string character
1941 */
1942 if( unicode_character != 0 )
1943 {
1944 if( *utf16_string_index >= utf16_string_size )
1945 {
1946 libcerror_error_set(
1947 error,
1948 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1949 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1950 "%s: UTF-16 string too small.",
1951 function );
1952
1953 return( -1 );
1954 }
1955 utf16_string[ *utf16_string_index ] = 0;
1956
1957 *utf16_string_index += 1;
1958 }
1959 return( 1 );
1960 }
1961
1962 /* Compares an UTF-16 string with an UTF-16 stream
1963 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
1964 */
libuna_utf16_string_compare_with_utf16_stream(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,libcerror_error_t ** error)1965 int libuna_utf16_string_compare_with_utf16_stream(
1966 const libuna_utf16_character_t *utf16_string,
1967 size_t utf16_string_size,
1968 const uint8_t *utf16_stream,
1969 size_t utf16_stream_size,
1970 int byte_order,
1971 libcerror_error_t **error )
1972 {
1973 static char *function = "libuna_utf16_string_compare_with_utf16_stream";
1974 size_t utf16_stream_index = 0;
1975 size_t utf16_string_index = 0;
1976 libuna_unicode_character_t utf16_unicode_character = 0;
1977 libuna_unicode_character_t utf16_stream_unicode_character = 0;
1978 int read_byte_order = 0;
1979
1980 if( utf16_string == NULL )
1981 {
1982 libcerror_error_set(
1983 error,
1984 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1985 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1986 "%s: invalid UTF-16 string.",
1987 function );
1988
1989 return( -1 );
1990 }
1991 if( utf16_string_size > (size_t) SSIZE_MAX )
1992 {
1993 libcerror_error_set(
1994 error,
1995 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1996 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1997 "%s: invalid UTF-16 string size value exceeds maximum.",
1998 function );
1999
2000 return( -1 );
2001 }
2002 if( utf16_stream == NULL )
2003 {
2004 libcerror_error_set(
2005 error,
2006 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2007 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2008 "%s: invalid UTF-16 stream.",
2009 function );
2010
2011 return( -1 );
2012 }
2013 if( utf16_stream_size > (size_t) SSIZE_MAX )
2014 {
2015 libcerror_error_set(
2016 error,
2017 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2018 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2019 "%s: invalid UTF-16 stream size value exceeds maximum.",
2020 function );
2021
2022 return( -1 );
2023 }
2024 if( ( utf16_stream_size == 0 )
2025 || ( ( utf16_stream_size % 2 ) != 0 ) )
2026 {
2027 libcerror_error_set(
2028 error,
2029 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2030 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2031 "%s: missing UTF-16 stream value.",
2032 function );
2033
2034 return( -1 );
2035 }
2036 /* Check if UTF-16 stream is in big or little endian
2037 */
2038 if( utf16_stream_size >= 2 )
2039 {
2040 if( ( utf16_stream[ 0 ] == 0xfe )
2041 && ( utf16_stream[ 1 ] == 0xff ) )
2042 {
2043 read_byte_order = LIBUNA_ENDIAN_BIG;
2044 utf16_stream_index = 2;
2045 }
2046 else if( ( utf16_stream[ 0 ] == 0xff )
2047 && ( utf16_stream[ 1 ] == 0xfe ) )
2048 {
2049 read_byte_order = LIBUNA_ENDIAN_LITTLE;
2050 utf16_stream_index = 2;
2051 }
2052 if( byte_order == 0 )
2053 {
2054 byte_order = read_byte_order;
2055 }
2056 }
2057 if( ( byte_order != LIBUNA_ENDIAN_BIG )
2058 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2059 {
2060 libcerror_error_set(
2061 error,
2062 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2063 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2064 "%s: unsupported byte order.",
2065 function );
2066
2067 return( -1 );
2068 }
2069 if( ( utf16_string_size >= 1 )
2070 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
2071 {
2072 utf16_string_size -= 1;
2073 }
2074 /* Check if the UTF-16 stream is terminated with zero bytes
2075 */
2076 if( ( utf16_stream_size >= 2 )
2077 && ( utf16_stream[ utf16_stream_size - 2 ] == 0 )
2078 && ( utf16_stream[ utf16_stream_size - 1 ] == 0 ) )
2079 {
2080 utf16_stream_size -= 2;
2081 }
2082 while( ( utf16_string_index < utf16_string_size )
2083 && ( utf16_stream_index < utf16_stream_size ) )
2084 {
2085 /* Convert the UTF-16 character bytes into an Unicode character
2086 */
2087 if( libuna_unicode_character_copy_from_utf16(
2088 &utf16_unicode_character,
2089 utf16_string,
2090 utf16_string_size,
2091 &utf16_string_index,
2092 error ) != 1 )
2093 {
2094 libcerror_error_set(
2095 error,
2096 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2097 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2098 "%s: unable to copy Unicode character from UTF-16.",
2099 function );
2100
2101 return( -1 );
2102 }
2103 /* Convert the UTF-16 stream bytes into an Unicode character
2104 */
2105 if( libuna_unicode_character_copy_from_utf16_stream(
2106 &utf16_stream_unicode_character,
2107 utf16_stream,
2108 utf16_stream_size,
2109 &utf16_stream_index,
2110 byte_order,
2111 error ) != 1 )
2112 {
2113 libcerror_error_set(
2114 error,
2115 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2116 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2117 "%s: unable to copy Unicode character from UTF-16 stream.",
2118 function );
2119
2120 return( -1 );
2121 }
2122 if( utf16_unicode_character < utf16_stream_unicode_character )
2123 {
2124 return( LIBUNA_COMPARE_LESS );
2125 }
2126 else if( utf16_unicode_character > utf16_stream_unicode_character )
2127 {
2128 return( LIBUNA_COMPARE_GREATER );
2129 }
2130 }
2131 /* Check if both strings were entirely processed
2132 */
2133 if( utf16_string_index < utf16_string_size )
2134 {
2135 return( LIBUNA_COMPARE_GREATER );
2136 }
2137 else if( utf16_stream_index < utf16_stream_size )
2138 {
2139 return( LIBUNA_COMPARE_LESS );
2140 }
2141 return( LIBUNA_COMPARE_EQUAL );
2142 }
2143
2144 /* Determines the size of an UTF-16 string from an UTF-32 string
2145 * Returns 1 if successful or -1 on error
2146 */
libuna_utf16_string_size_from_utf32(const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,size_t * utf16_string_size,libcerror_error_t ** error)2147 int libuna_utf16_string_size_from_utf32(
2148 const libuna_utf32_character_t *utf32_string,
2149 size_t utf32_string_size,
2150 size_t *utf16_string_size,
2151 libcerror_error_t **error )
2152 {
2153 static char *function = "libuna_utf16_string_size_from_utf32";
2154 size_t utf32_string_index = 0;
2155 libuna_unicode_character_t unicode_character = 0;
2156
2157 if( utf32_string == NULL )
2158 {
2159 libcerror_error_set(
2160 error,
2161 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2162 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2163 "%s: invalid UTF-32 string.",
2164 function );
2165
2166 return( -1 );
2167 }
2168 if( utf32_string_size > (size_t) SSIZE_MAX )
2169 {
2170 libcerror_error_set(
2171 error,
2172 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2173 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2174 "%s: invalid UTF-32 string size value exceeds maximum.",
2175 function );
2176
2177 return( -1 );
2178 }
2179 if( utf16_string_size == NULL )
2180 {
2181 libcerror_error_set(
2182 error,
2183 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2184 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2185 "%s: invalid UTF-16 string size.",
2186 function );
2187
2188 return( -1 );
2189 }
2190 *utf16_string_size = 0;
2191
2192 if( utf32_string_size == 0 )
2193 {
2194 return( 1 );
2195 }
2196 while( utf32_string_index < utf32_string_size )
2197 {
2198 /* Convert the UTF-32 character bytes into an Unicode character
2199 */
2200 if( libuna_unicode_character_copy_from_utf32(
2201 &unicode_character,
2202 utf32_string,
2203 utf32_string_size,
2204 &utf32_string_index,
2205 error ) != 1 )
2206 {
2207 libcerror_error_set(
2208 error,
2209 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2210 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2211 "%s: unable to copy Unicode character from UTF-32.",
2212 function );
2213
2214 return( -1 );
2215 }
2216 /* Determine how many UTF-16 character bytes are required
2217 */
2218 if( libuna_unicode_character_size_to_utf16(
2219 unicode_character,
2220 utf16_string_size,
2221 error ) != 1 )
2222 {
2223 libcerror_error_set(
2224 error,
2225 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2226 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2227 "%s: unable to unable to determine size of Unicode character in UTF-16.",
2228 function );
2229
2230 return( -1 );
2231 }
2232 }
2233 /* Check if the string is terminated with an end-of-string character
2234 */
2235 if( unicode_character != 0 )
2236 {
2237 *utf16_string_size += 1;
2238 }
2239 return( 1 );
2240 }
2241
2242 /* Copies an UTF-16 string from an UTF-32 string
2243 * Returns 1 if successful or -1 on error
2244 */
libuna_utf16_string_copy_from_utf32(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)2245 int libuna_utf16_string_copy_from_utf32(
2246 libuna_utf16_character_t *utf16_string,
2247 size_t utf16_string_size,
2248 const libuna_utf32_character_t *utf32_string,
2249 size_t utf32_string_size,
2250 libcerror_error_t **error )
2251 {
2252 static char *function = "libuna_utf16_string_copy_from_utf32";
2253 size_t utf16_string_index = 0;
2254
2255 if( libuna_utf16_string_with_index_copy_from_utf32(
2256 utf16_string,
2257 utf16_string_size,
2258 &utf16_string_index,
2259 utf32_string,
2260 utf32_string_size,
2261 error ) != 1 )
2262 {
2263 libcerror_error_set(
2264 error,
2265 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2266 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2267 "%s: unable to copy UTF-32 string to UTF-16 string.",
2268 function );
2269
2270 return( -1 );
2271 }
2272 return( 1 );
2273 }
2274
2275 /* Copies an UTF-16 string from an UTF-32 string
2276 * Returns 1 if successful or -1 on error
2277 */
libuna_utf16_string_with_index_copy_from_utf32(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)2278 int libuna_utf16_string_with_index_copy_from_utf32(
2279 libuna_utf16_character_t *utf16_string,
2280 size_t utf16_string_size,
2281 size_t *utf16_string_index,
2282 const libuna_utf32_character_t *utf32_string,
2283 size_t utf32_string_size,
2284 libcerror_error_t **error )
2285 {
2286 static char *function = "libuna_utf16_string_with_index_copy_from_utf32";
2287 size_t utf32_string_index = 0;
2288 libuna_unicode_character_t unicode_character = 0;
2289
2290 if( utf16_string == NULL )
2291 {
2292 libcerror_error_set(
2293 error,
2294 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2295 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2296 "%s: invalid UTF-16 string.",
2297 function );
2298
2299 return( -1 );
2300 }
2301 if( utf16_string_size > (size_t) SSIZE_MAX )
2302 {
2303 libcerror_error_set(
2304 error,
2305 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2306 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2307 "%s: invalid UTF-16 string size value exceeds maximum.",
2308 function );
2309
2310 return( -1 );
2311 }
2312 if( utf16_string_index == NULL )
2313 {
2314 libcerror_error_set(
2315 error,
2316 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2317 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2318 "%s: invalid UTF-16 string index.",
2319 function );
2320
2321 return( -1 );
2322 }
2323 if( utf32_string == NULL )
2324 {
2325 libcerror_error_set(
2326 error,
2327 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2328 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2329 "%s: invalid UTF-32 string.",
2330 function );
2331
2332 return( -1 );
2333 }
2334 if( utf32_string_size > (size_t) SSIZE_MAX )
2335 {
2336 libcerror_error_set(
2337 error,
2338 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2339 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2340 "%s: invalid UTF-32 string size value exceeds maximum.",
2341 function );
2342
2343 return( -1 );
2344 }
2345 if( utf32_string_size == 0 )
2346 {
2347 libcerror_error_set(
2348 error,
2349 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2350 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2351 "%s: missing UTF-32 string value.",
2352 function );
2353
2354 return( -1 );
2355 }
2356 while( utf32_string_index < utf32_string_size )
2357 {
2358 /* Convert the UTF-32 character bytes into an Unicode character
2359 */
2360 if( libuna_unicode_character_copy_from_utf32(
2361 &unicode_character,
2362 utf32_string,
2363 utf32_string_size,
2364 &utf32_string_index,
2365 error ) != 1 )
2366 {
2367 libcerror_error_set(
2368 error,
2369 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2370 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2371 "%s: unable to copy Unicode character from UTF-32.",
2372 function );
2373
2374 return( -1 );
2375 }
2376 /* Convert the Unicode character into UTF-16 character bytes
2377 */
2378 if( libuna_unicode_character_copy_to_utf16(
2379 unicode_character,
2380 utf16_string,
2381 utf16_string_size,
2382 utf16_string_index,
2383 error ) != 1 )
2384 {
2385 libcerror_error_set(
2386 error,
2387 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2388 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2389 "%s: unable to copy Unicode character to UTF-16.",
2390 function );
2391
2392 return( -1 );
2393 }
2394 }
2395 /* Check if the string is terminated with an end-of-string character
2396 */
2397 if( unicode_character != 0 )
2398 {
2399 if( *utf16_string_index >= utf16_string_size )
2400 {
2401 libcerror_error_set(
2402 error,
2403 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2404 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2405 "%s: UTF-16 string too small.",
2406 function );
2407
2408 return( -1 );
2409 }
2410 utf16_string[ *utf16_string_index ] = 0;
2411
2412 *utf16_string_index += 1;
2413 }
2414 return( 1 );
2415 }
2416
2417 /* Compares an UTF-16 string with an UTF-32 string
2418 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
2419 */
libuna_utf16_string_compare_with_utf32(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)2420 int libuna_utf16_string_compare_with_utf32(
2421 const libuna_utf16_character_t *utf16_string,
2422 size_t utf16_string_size,
2423 const libuna_utf32_character_t *utf32_string,
2424 size_t utf32_string_size,
2425 libcerror_error_t **error )
2426 {
2427 static char *function = "libuna_utf16_string_compare_with_utf32";
2428 size_t utf16_string_index = 0;
2429 size_t utf32_string_index = 0;
2430 libuna_unicode_character_t utf16_unicode_character = 0;
2431 libuna_unicode_character_t utf32_unicode_character = 0;
2432
2433 if( utf16_string == NULL )
2434 {
2435 libcerror_error_set(
2436 error,
2437 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2438 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2439 "%s: invalid UTF-16 string.",
2440 function );
2441
2442 return( -1 );
2443 }
2444 if( utf16_string_size > (size_t) SSIZE_MAX )
2445 {
2446 libcerror_error_set(
2447 error,
2448 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2449 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2450 "%s: invalid UTF-16 string size value exceeds maximum.",
2451 function );
2452
2453 return( -1 );
2454 }
2455 if( utf32_string == NULL )
2456 {
2457 libcerror_error_set(
2458 error,
2459 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2460 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2461 "%s: invalid UTF-32 string.",
2462 function );
2463
2464 return( -1 );
2465 }
2466 if( utf32_string_size > (size_t) SSIZE_MAX )
2467 {
2468 libcerror_error_set(
2469 error,
2470 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2471 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2472 "%s: invalid UTF-32 string size value exceeds maximum.",
2473 function );
2474
2475 return( -1 );
2476 }
2477 if( utf32_string_size == 0 )
2478 {
2479 libcerror_error_set(
2480 error,
2481 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2482 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2483 "%s: missing UTF-32 string value.",
2484 function );
2485
2486 return( -1 );
2487 }
2488 if( ( utf16_string_size >= 1 )
2489 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
2490 {
2491 utf16_string_size -= 1;
2492 }
2493 if( ( utf32_string_size >= 1 )
2494 && ( utf32_string[ utf32_string_size - 1 ] == 0 ) )
2495 {
2496 utf32_string_size -= 1;
2497 }
2498 while( ( utf16_string_index < utf16_string_size )
2499 && ( utf32_string_index < utf32_string_size ) )
2500 {
2501 /* Convert the UTF-16 character bytes into an Unicode character
2502 */
2503 if( libuna_unicode_character_copy_from_utf16(
2504 &utf16_unicode_character,
2505 utf16_string,
2506 utf16_string_size,
2507 &utf16_string_index,
2508 error ) != 1 )
2509 {
2510 libcerror_error_set(
2511 error,
2512 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2513 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2514 "%s: unable to copy Unicode character from UTF-16.",
2515 function );
2516
2517 return( -1 );
2518 }
2519 /* Convert the UTF-32 character bytes into an Unicode character
2520 */
2521 if( libuna_unicode_character_copy_from_utf32(
2522 &utf32_unicode_character,
2523 utf32_string,
2524 utf32_string_size,
2525 &utf32_string_index,
2526 error ) != 1 )
2527 {
2528 libcerror_error_set(
2529 error,
2530 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2531 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2532 "%s: unable to copy Unicode character from UTF-32.",
2533 function );
2534
2535 return( -1 );
2536 }
2537 if( utf16_unicode_character < utf32_unicode_character )
2538 {
2539 return( LIBUNA_COMPARE_LESS );
2540 }
2541 else if( utf16_unicode_character > utf32_unicode_character )
2542 {
2543 return( LIBUNA_COMPARE_GREATER );
2544 }
2545 }
2546 /* Check if both strings were entirely processed
2547 */
2548 if( utf16_string_index < utf16_string_size )
2549 {
2550 return( LIBUNA_COMPARE_GREATER );
2551 }
2552 else if( utf32_string_index < utf32_string_size )
2553 {
2554 return( LIBUNA_COMPARE_LESS );
2555 }
2556 return( LIBUNA_COMPARE_EQUAL );
2557 }
2558
2559 /* Determines the size of an UTF-16 string from an UTF-32 stream
2560 * Returns 1 if successful or -1 on error
2561 */
libuna_utf16_string_size_from_utf32_stream(const uint8_t * utf32_stream,size_t utf32_stream_size,int byte_order,size_t * utf16_string_size,libcerror_error_t ** error)2562 int libuna_utf16_string_size_from_utf32_stream(
2563 const uint8_t *utf32_stream,
2564 size_t utf32_stream_size,
2565 int byte_order,
2566 size_t *utf16_string_size,
2567 libcerror_error_t **error )
2568 {
2569 static char *function = "libuna_utf16_string_size_from_utf32_stream";
2570 size_t utf32_stream_index = 0;
2571 libuna_unicode_character_t unicode_character = 0;
2572 int read_byte_order = 0;
2573
2574 if( utf32_stream == NULL )
2575 {
2576 libcerror_error_set(
2577 error,
2578 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2579 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2580 "%s: invalid UTF-32 stream.",
2581 function );
2582
2583 return( -1 );
2584 }
2585 if( utf32_stream_size > (size_t) SSIZE_MAX )
2586 {
2587 libcerror_error_set(
2588 error,
2589 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2590 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2591 "%s: invalid UTF-32 stream size value exceeds maximum.",
2592 function );
2593
2594 return( -1 );
2595 }
2596 if( ( utf32_stream_size % 4 ) != 0 )
2597 {
2598 libcerror_error_set(
2599 error,
2600 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2601 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2602 "%s: missing UTF-32 stream value.",
2603 function );
2604
2605 return( -1 );
2606 }
2607 if( utf16_string_size == NULL )
2608 {
2609 libcerror_error_set(
2610 error,
2611 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2612 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2613 "%s: invalid UTF-16 string size.",
2614 function );
2615
2616 return( -1 );
2617 }
2618 *utf16_string_size = 0;
2619
2620 if( utf32_stream_size == 0 )
2621 {
2622 return( 1 );
2623 }
2624 /* Check if UTF-32 stream is in big or little endian
2625 */
2626 if( utf32_stream_size >= 4 )
2627 {
2628 if( ( utf32_stream[ 0 ] == 0x00 )
2629 && ( utf32_stream[ 1 ] == 0x00 )
2630 && ( utf32_stream[ 2 ] == 0xfe )
2631 && ( utf32_stream[ 3 ] == 0xff ) )
2632 {
2633 read_byte_order = LIBUNA_ENDIAN_BIG;
2634 utf32_stream_index = 4;
2635 }
2636 else if( ( utf32_stream[ 0 ] == 0xff )
2637 && ( utf32_stream[ 1 ] == 0xfe )
2638 && ( utf32_stream[ 2 ] == 0x00 )
2639 && ( utf32_stream[ 3 ] == 0x00 ) )
2640 {
2641 read_byte_order = LIBUNA_ENDIAN_LITTLE;
2642 utf32_stream_index = 4;
2643 }
2644 if( byte_order == 0 )
2645 {
2646 byte_order = read_byte_order;
2647 }
2648 }
2649 if( ( byte_order != LIBUNA_ENDIAN_BIG )
2650 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2651 {
2652 libcerror_error_set(
2653 error,
2654 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2655 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2656 "%s: unsupported byte order.",
2657 function );
2658
2659 return( -1 );
2660 }
2661 while( ( utf32_stream_index + 3 ) < utf32_stream_size )
2662 {
2663 /* Convert the UTF-32 stream bytes into an Unicode character
2664 */
2665 if( libuna_unicode_character_copy_from_utf32_stream(
2666 &unicode_character,
2667 utf32_stream,
2668 utf32_stream_size,
2669 &utf32_stream_index,
2670 byte_order,
2671 error ) != 1 )
2672 {
2673 libcerror_error_set(
2674 error,
2675 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2676 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2677 "%s: unable to copy Unicode character from UTF-32 stream.",
2678 function );
2679
2680 return( -1 );
2681 }
2682 /* Determine how many UTF-16 character bytes are required
2683 */
2684 if( libuna_unicode_character_size_to_utf16(
2685 unicode_character,
2686 utf16_string_size,
2687 error ) != 1 )
2688 {
2689 libcerror_error_set(
2690 error,
2691 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2692 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2693 "%s: unable to unable to determine size of Unicode character in UTF-16.",
2694 function );
2695
2696 return( -1 );
2697 }
2698 }
2699 /* Check if the string is terminated with an end-of-string character
2700 */
2701 if( unicode_character != 0 )
2702 {
2703 *utf16_string_size += 1;
2704 }
2705 return( 1 );
2706 }
2707
2708 /* Copies an UTF-16 string from an UTF-32 stream
2709 * Returns 1 if successful or -1 on error
2710 */
libuna_utf16_string_copy_from_utf32_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf32_stream,size_t utf32_stream_size,int byte_order,libcerror_error_t ** error)2711 int libuna_utf16_string_copy_from_utf32_stream(
2712 libuna_utf16_character_t *utf16_string,
2713 size_t utf16_string_size,
2714 const uint8_t *utf32_stream,
2715 size_t utf32_stream_size,
2716 int byte_order,
2717 libcerror_error_t **error )
2718 {
2719 static char *function = "libuna_utf16_string_copy_from_utf32_stream";
2720 size_t utf16_string_index = 0;
2721
2722 if( libuna_utf16_string_with_index_copy_from_utf32_stream(
2723 utf16_string,
2724 utf16_string_size,
2725 &utf16_string_index,
2726 utf32_stream,
2727 utf32_stream_size,
2728 byte_order,
2729 error ) != 1 )
2730 {
2731 libcerror_error_set(
2732 error,
2733 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2734 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2735 "%s: unable to copy UTF-32 stream to UTF-16 string.",
2736 function );
2737
2738 return( -1 );
2739 }
2740 return( 1 );
2741 }
2742
2743 /* Copies an UTF-16 string from an UTF-32 stream
2744 * Returns 1 if successful or -1 on error
2745 */
libuna_utf16_string_with_index_copy_from_utf32_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * utf32_stream,size_t utf32_stream_size,int byte_order,libcerror_error_t ** error)2746 int libuna_utf16_string_with_index_copy_from_utf32_stream(
2747 libuna_utf16_character_t *utf16_string,
2748 size_t utf16_string_size,
2749 size_t *utf16_string_index,
2750 const uint8_t *utf32_stream,
2751 size_t utf32_stream_size,
2752 int byte_order,
2753 libcerror_error_t **error )
2754 {
2755 static char *function = "libuna_utf16_string_with_index_copy_from_utf32_stream";
2756 size_t utf32_stream_index = 0;
2757 libuna_unicode_character_t unicode_character = 0;
2758 int read_byte_order = 0;
2759
2760 if( utf16_string == NULL )
2761 {
2762 libcerror_error_set(
2763 error,
2764 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2765 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2766 "%s: invalid UTF-16 string.",
2767 function );
2768
2769 return( -1 );
2770 }
2771 if( utf16_string_size > (size_t) SSIZE_MAX )
2772 {
2773 libcerror_error_set(
2774 error,
2775 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2776 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2777 "%s: invalid UTF-16 string size value exceeds maximum.",
2778 function );
2779
2780 return( -1 );
2781 }
2782 if( utf16_string_index == NULL )
2783 {
2784 libcerror_error_set(
2785 error,
2786 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2787 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2788 "%s: invalid UTF-16 string index.",
2789 function );
2790
2791 return( -1 );
2792 }
2793 if( utf32_stream == NULL )
2794 {
2795 libcerror_error_set(
2796 error,
2797 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2798 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2799 "%s: invalid UTF-32 stream.",
2800 function );
2801
2802 return( -1 );
2803 }
2804 if( utf32_stream_size > (size_t) SSIZE_MAX )
2805 {
2806 libcerror_error_set(
2807 error,
2808 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2809 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2810 "%s: invalid UTF-32 stream size value exceeds maximum.",
2811 function );
2812
2813 return( -1 );
2814 }
2815 if( ( utf32_stream_size == 0 )
2816 || ( ( utf32_stream_size % 4 ) != 0 ) )
2817 {
2818 libcerror_error_set(
2819 error,
2820 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2821 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2822 "%s: missing UTF-32 stream value.",
2823 function );
2824
2825 return( -1 );
2826 }
2827 /* Check if UTF-32 stream is in big or little endian
2828 */
2829 if( utf32_stream_size >=4 )
2830 {
2831 if( ( utf32_stream[ 0 ] == 0x00 )
2832 && ( utf32_stream[ 1 ] == 0x00 )
2833 && ( utf32_stream[ 2 ] == 0xfe )
2834 && ( utf32_stream[ 3 ] == 0xff ) )
2835 {
2836 read_byte_order = LIBUNA_ENDIAN_BIG;
2837 utf32_stream_index = 4;
2838 }
2839 else if( ( utf32_stream[ 0 ] == 0xff )
2840 && ( utf32_stream[ 1 ] == 0xfe )
2841 && ( utf32_stream[ 2 ] == 0x00 )
2842 && ( utf32_stream[ 3 ] == 0x00 ) )
2843 {
2844 read_byte_order = LIBUNA_ENDIAN_LITTLE;
2845 utf32_stream_index = 4;
2846 }
2847 if( byte_order == 0 )
2848 {
2849 byte_order = read_byte_order;
2850 }
2851 }
2852 if( ( byte_order != LIBUNA_ENDIAN_BIG )
2853 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2854 {
2855 libcerror_error_set(
2856 error,
2857 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2858 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2859 "%s: unsupported byte order.",
2860 function );
2861
2862 return( -1 );
2863 }
2864 while( ( utf32_stream_index + 3 ) < utf32_stream_size )
2865 {
2866 /* Convert the UTF-32 stream bytes into an Unicode character
2867 */
2868 if( libuna_unicode_character_copy_from_utf32_stream(
2869 &unicode_character,
2870 utf32_stream,
2871 utf32_stream_size,
2872 &utf32_stream_index,
2873 byte_order,
2874 error ) != 1 )
2875 {
2876 libcerror_error_set(
2877 error,
2878 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2879 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2880 "%s: unable to copy Unicode character from UTF-32 stream.",
2881 function );
2882
2883 return( -1 );
2884 }
2885 /* Convert the Unicode character into UTF-16 character bytes
2886 */
2887 if( libuna_unicode_character_copy_to_utf16(
2888 unicode_character,
2889 utf16_string,
2890 utf16_string_size,
2891 utf16_string_index,
2892 error ) != 1 )
2893 {
2894 libcerror_error_set(
2895 error,
2896 LIBCERROR_ERROR_DOMAIN_CONVERSION,
2897 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2898 "%s: unable to copy Unicode character to UTF-16.",
2899 function );
2900
2901 return( -1 );
2902 }
2903 }
2904 /* Check if the string is terminated with an end-of-string character
2905 */
2906 if( unicode_character != 0 )
2907 {
2908 if( *utf16_string_index >= utf16_string_size )
2909 {
2910 libcerror_error_set(
2911 error,
2912 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2913 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2914 "%s: UTF-16 string too small.",
2915 function );
2916
2917 return( -1 );
2918 }
2919 utf16_string[ *utf16_string_index ] = 0;
2920
2921 *utf16_string_index += 1;
2922 }
2923 return( 1 );
2924 }
2925
2926 /* Compares an UTF-16 string with an UTF-32 stream
2927 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
2928 */
libuna_utf16_string_compare_with_utf32_stream(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * utf32_stream,size_t utf32_stream_size,int byte_order,libcerror_error_t ** error)2929 int libuna_utf16_string_compare_with_utf32_stream(
2930 const libuna_utf16_character_t *utf16_string,
2931 size_t utf16_string_size,
2932 const uint8_t *utf32_stream,
2933 size_t utf32_stream_size,
2934 int byte_order,
2935 libcerror_error_t **error )
2936 {
2937 static char *function = "libuna_utf16_string_compare_with_utf32_stream";
2938 size_t utf16_string_index = 0;
2939 size_t utf32_stream_index = 0;
2940 libuna_unicode_character_t utf16_unicode_character = 0;
2941 libuna_unicode_character_t utf32_stream_unicode_character = 0;
2942 int read_byte_order = 0;
2943
2944 if( utf16_string == NULL )
2945 {
2946 libcerror_error_set(
2947 error,
2948 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2949 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2950 "%s: invalid UTF-16 string.",
2951 function );
2952
2953 return( -1 );
2954 }
2955 if( utf16_string_size > (size_t) SSIZE_MAX )
2956 {
2957 libcerror_error_set(
2958 error,
2959 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2960 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2961 "%s: invalid UTF-16 string size value exceeds maximum.",
2962 function );
2963
2964 return( -1 );
2965 }
2966 if( utf32_stream == NULL )
2967 {
2968 libcerror_error_set(
2969 error,
2970 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2971 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2972 "%s: invalid UTF-32 stream.",
2973 function );
2974
2975 return( -1 );
2976 }
2977 if( utf32_stream_size > (size_t) SSIZE_MAX )
2978 {
2979 libcerror_error_set(
2980 error,
2981 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2982 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2983 "%s: invalid UTF-32 stream size value exceeds maximum.",
2984 function );
2985
2986 return( -1 );
2987 }
2988 if( ( utf32_stream_size == 0 )
2989 || ( ( utf32_stream_size % 4 ) != 0 ) )
2990 {
2991 libcerror_error_set(
2992 error,
2993 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2994 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2995 "%s: missing UTF-32 stream value.",
2996 function );
2997
2998 return( -1 );
2999 }
3000 /* Check if UTF-32 stream is in big or little endian
3001 */
3002 if( utf32_stream_size >= 4 )
3003 {
3004 if( ( utf32_stream[ 0 ] == 0x00 )
3005 && ( utf32_stream[ 1 ] == 0x00 )
3006 && ( utf32_stream[ 2 ] == 0xfe )
3007 && ( utf32_stream[ 3 ] == 0xff ) )
3008 {
3009 read_byte_order = LIBUNA_ENDIAN_BIG;
3010 utf32_stream_index = 4;
3011 }
3012 else if( ( utf32_stream[ 0 ] == 0xff )
3013 && ( utf32_stream[ 1 ] == 0xfe )
3014 && ( utf32_stream[ 2 ] == 0x00 )
3015 && ( utf32_stream[ 3 ] == 0x00 ) )
3016 {
3017 read_byte_order = LIBUNA_ENDIAN_LITTLE;
3018 utf32_stream_index = 4;
3019 }
3020 if( byte_order == 0 )
3021 {
3022 byte_order = read_byte_order;
3023 }
3024 }
3025 if( ( byte_order != LIBUNA_ENDIAN_BIG )
3026 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
3027 {
3028 libcerror_error_set(
3029 error,
3030 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3031 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3032 "%s: unsupported byte order.",
3033 function );
3034
3035 return( -1 );
3036 }
3037 if( ( utf16_string_size >= 1 )
3038 && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
3039 {
3040 utf16_string_size -= 1;
3041 }
3042 /* Check if the UTF-32 stream is terminated with zero bytes
3043 */
3044 if( ( utf32_stream_size >= 4 )
3045 && ( utf32_stream[ utf32_stream_size - 4 ] == 0 )
3046 && ( utf32_stream[ utf32_stream_size - 3 ] == 0 )
3047 && ( utf32_stream[ utf32_stream_size - 2 ] == 0 )
3048 && ( utf32_stream[ utf32_stream_size - 1 ] == 0 ) )
3049 {
3050 utf32_stream_size -= 1;
3051 }
3052 while( ( utf16_string_index < utf16_string_size )
3053 && ( utf32_stream_index < utf32_stream_size ) )
3054 {
3055 /* Convert the UTF-16 character bytes into an Unicode character
3056 */
3057 if( libuna_unicode_character_copy_from_utf16(
3058 &utf16_unicode_character,
3059 utf16_string,
3060 utf16_string_size,
3061 &utf16_string_index,
3062 error ) != 1 )
3063 {
3064 libcerror_error_set(
3065 error,
3066 LIBCERROR_ERROR_DOMAIN_CONVERSION,
3067 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3068 "%s: unable to copy Unicode character from UTF-16.",
3069 function );
3070
3071 return( -1 );
3072 }
3073 /* Convert the UTF-32 stream bytes into an Unicode character
3074 */
3075 if( libuna_unicode_character_copy_from_utf32_stream(
3076 &utf32_stream_unicode_character,
3077 utf32_stream,
3078 utf32_stream_size,
3079 &utf32_stream_index,
3080 byte_order,
3081 error ) != 1 )
3082 {
3083 libcerror_error_set(
3084 error,
3085 LIBCERROR_ERROR_DOMAIN_CONVERSION,
3086 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
3087 "%s: unable to copy Unicode character from UTF-32 stream.",
3088 function );
3089
3090 return( -1 );
3091 }
3092 if( utf16_unicode_character < utf32_stream_unicode_character )
3093 {
3094 return( LIBUNA_COMPARE_LESS );
3095 }
3096 else if( utf16_unicode_character > utf32_stream_unicode_character )
3097 {
3098 return( LIBUNA_COMPARE_GREATER );
3099 }
3100 }
3101 /* Check if both strings were entirely processed
3102 */
3103 if( utf16_string_index < utf16_string_size )
3104 {
3105 return( LIBUNA_COMPARE_GREATER );
3106 }
3107 else if( utf32_stream_index < utf32_stream_size )
3108 {
3109 return( LIBUNA_COMPARE_LESS );
3110 }
3111 return( LIBUNA_COMPARE_EQUAL );
3112 }
3113
3114 /* Determines the size of an UTF-16 string from a Standard Compression Scheme for Unicode (SCSU) stream
3115 * Returns 1 if successful or -1 on error
3116 */
libuna_utf16_string_size_from_scsu_stream(const uint8_t * scsu_stream,size_t scsu_stream_size,size_t * utf16_string_size,libcerror_error_t ** error)3117 int libuna_utf16_string_size_from_scsu_stream(
3118 const uint8_t *scsu_stream,
3119 size_t scsu_stream_size,
3120 size_t *utf16_string_size,
3121 libcerror_error_t **error )
3122 {
3123 uint32_t scsu_dynamic_window_positions[ 8 ] = {
3124 0x0080, 0x00c0, 0x0400, 0x0600, 0x0900, 0x3040, 0x30a0, 0xff00 };
3125
3126 static char *function = "libuna_utf8_string_size_from_scsu_stream";
3127 libuna_unicode_character_t unicode_character = 0;
3128 size_t scsu_stream_index = 0;
3129 uint32_t scsu_window_position = 0;
3130 uint8_t byte_value1 = 0;
3131 uint8_t byte_value2 = 0;
3132 uint8_t byte_value3 = 0;
3133 uint8_t dynamic_window_position_index = 0;
3134 uint8_t in_unicode_mode = 0;
3135 uint8_t unicode_character_set = 0;
3136
3137 if( scsu_stream == NULL )
3138 {
3139 libcerror_error_set(
3140 error,
3141 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3142 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3143 "%s: invalid SCSU stream.",
3144 function );
3145
3146 return( -1 );
3147 }
3148 if( scsu_stream_size > (size_t) SSIZE_MAX )
3149 {
3150 libcerror_error_set(
3151 error,
3152 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3153 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3154 "%s: invalid SCSU stream size value exceeds maximum.",
3155 function );
3156
3157 return( -1 );
3158 }
3159 if( utf16_string_size == NULL )
3160 {
3161 libcerror_error_set(
3162 error,
3163 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3164 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3165 "%s: invalid UTF-16 string size.",
3166 function );
3167
3168 return( -1 );
3169 }
3170 *utf16_string_size = 0;
3171
3172 if( scsu_stream_size == 0 )
3173 {
3174 return( 1 );
3175 }
3176 while( scsu_stream_index < scsu_stream_size )
3177 {
3178 unicode_character_set = 0;
3179
3180 if( scsu_stream_index >= scsu_stream_size )
3181 {
3182 libcerror_error_set(
3183 error,
3184 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3185 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3186 "%s: SCSU stream too small.",
3187 function );
3188
3189 return( -1 );
3190 }
3191 byte_value1 = scsu_stream[ scsu_stream_index++ ];
3192
3193 if( in_unicode_mode != 0 )
3194 {
3195 if( ( byte_value1 <= 0xdf )
3196 || ( byte_value1 >= 0xf3 ) )
3197 {
3198 if( scsu_stream_index >= scsu_stream_size )
3199 {
3200 libcerror_error_set(
3201 error,
3202 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3203 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3204 "%s: SCSU stream too small.",
3205 function );
3206
3207 return( -1 );
3208 }
3209 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3210
3211 unicode_character = byte_value1;
3212 unicode_character <<= 8;
3213 unicode_character |= byte_value2;
3214
3215 unicode_character_set = 1;
3216 }
3217 /* UCn tags
3218 */
3219 else if( ( byte_value1 >= 0xe0 )
3220 && ( byte_value1 <= 0xe7 ) )
3221 {
3222 dynamic_window_position_index = byte_value1 - 0xe0;
3223
3224 in_unicode_mode = 0;
3225 }
3226 /* UDn tags
3227 */
3228 else if( ( byte_value1 >= 0xe8 )
3229 && ( byte_value1 <= 0xef ) )
3230 {
3231 if( scsu_stream_index >= scsu_stream_size )
3232 {
3233 libcerror_error_set(
3234 error,
3235 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3236 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3237 "%s: SCSU stream too small.",
3238 function );
3239
3240 return( -1 );
3241 }
3242 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3243
3244 dynamic_window_position_index = byte_value1 - 0xe8;
3245 scsu_window_position = libuna_scsu_window_offset_table[ byte_value2 ];
3246
3247 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3248
3249 in_unicode_mode = 0;
3250 }
3251 /* UQU tag
3252 */
3253 else if( byte_value1 == 0xf0 )
3254 {
3255 if( ( scsu_stream_size < 2 )
3256 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3257 {
3258 libcerror_error_set(
3259 error,
3260 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3261 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3262 "%s: SCSU stream too small.",
3263 function );
3264
3265 return( -1 );
3266 }
3267 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3268 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3269
3270 unicode_character = byte_value2;
3271 unicode_character <<= 8;
3272 unicode_character |= byte_value3;
3273
3274 unicode_character_set = 1;
3275 }
3276 /* UDX tag
3277 */
3278 else if( byte_value1 == 0xf1 )
3279 {
3280 if( ( scsu_stream_size < 2 )
3281 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3282 {
3283 libcerror_error_set(
3284 error,
3285 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3286 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3287 "%s: SCSU stream too small.",
3288 function );
3289
3290 return( -1 );
3291 }
3292 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3293 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3294
3295 dynamic_window_position_index = byte_value2 >> 5;
3296 scsu_window_position = byte_value2 & 0x1f;
3297 scsu_window_position <<= 8;
3298 scsu_window_position |= byte_value3;
3299 scsu_window_position <<= 7;
3300 scsu_window_position += 0x00010000UL;
3301
3302 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3303
3304 in_unicode_mode = 0;
3305 }
3306 }
3307 else
3308 {
3309 if( ( byte_value1 == 0x00 )
3310 || ( byte_value1 == 0x09 )
3311 || ( byte_value1 == 0x0a )
3312 || ( byte_value1 == 0x0c )
3313 || ( byte_value1 == 0x0d )
3314 || ( ( byte_value1 >= 0x20 )
3315 && ( byte_value1 <= 0x7f ) ) )
3316 {
3317 unicode_character = byte_value1;
3318
3319 unicode_character_set = 1;
3320 }
3321 /* SQn tags
3322 */
3323 else if( ( byte_value1 >= 0x01 )
3324 && ( byte_value1 <= 0x08 ) )
3325 {
3326 if( scsu_stream_index >= scsu_stream_size )
3327 {
3328 libcerror_error_set(
3329 error,
3330 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3331 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3332 "%s: SCSU stream too small.",
3333 function );
3334
3335 return( -1 );
3336 }
3337 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3338
3339 unicode_character = byte_value2;
3340
3341 if( byte_value2 < 0x80 )
3342 {
3343 unicode_character += libuna_scsu_static_window_positions[ byte_value1 - 0x01 ];
3344 }
3345 else
3346 {
3347 unicode_character -= 0x80;
3348 unicode_character += scsu_dynamic_window_positions[ byte_value1 - 0x01 ];
3349 }
3350 unicode_character_set = 1;
3351 }
3352 /* SDX tag
3353 */
3354 else if( byte_value1 == 0x0b )
3355 {
3356 if( ( scsu_stream_size < 2 )
3357 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3358 {
3359 libcerror_error_set(
3360 error,
3361 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3362 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3363 "%s: SCSU stream too small.",
3364 function );
3365
3366 return( -1 );
3367 }
3368 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3369 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3370
3371 dynamic_window_position_index = byte_value2 >> 5;
3372 scsu_window_position = byte_value2 & 0x1f;
3373 scsu_window_position <<= 8;
3374 scsu_window_position |= byte_value3;
3375 scsu_window_position <<= 7;
3376 scsu_window_position += 0x00010000UL;
3377
3378 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3379 }
3380 /* SQU tag
3381 */
3382 else if( byte_value1 == 0x0e )
3383 {
3384 if( ( scsu_stream_size < 2 )
3385 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3386 {
3387 libcerror_error_set(
3388 error,
3389 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3390 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3391 "%s: SCSU stream too small.",
3392 function );
3393
3394 return( -1 );
3395 }
3396 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3397 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3398
3399 unicode_character = byte_value2;
3400 unicode_character <<= 8;
3401 unicode_character |= byte_value3;
3402
3403 unicode_character_set = 1;
3404 }
3405 /* SCU tag
3406 */
3407 else if( byte_value1 == 0x0f )
3408 {
3409 in_unicode_mode = 1;
3410 }
3411 /* SCn tags
3412 */
3413 else if( ( byte_value1 >= 0x10 )
3414 && ( byte_value1 <= 0x17 ) )
3415 {
3416 dynamic_window_position_index = byte_value1 - 0x10;
3417 }
3418 /* SDn tags
3419 */
3420 else if( ( byte_value1 >= 0x18 )
3421 && ( byte_value1 <= 0x1f ) )
3422 {
3423 if( scsu_stream_index >= scsu_stream_size )
3424 {
3425 libcerror_error_set(
3426 error,
3427 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3428 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3429 "%s: SCSU stream too small.",
3430 function );
3431
3432 return( -1 );
3433 }
3434 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3435
3436 dynamic_window_position_index = byte_value1 - 0x18;
3437 scsu_window_position = libuna_scsu_window_offset_table[ byte_value2 ];
3438
3439 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3440 }
3441 else if( byte_value1 >= 0x80 )
3442 {
3443 unicode_character = byte_value1 - 0x80;
3444 unicode_character += scsu_dynamic_window_positions[ dynamic_window_position_index ];
3445
3446 unicode_character_set = 1;
3447 }
3448 }
3449 if( unicode_character_set != 0 )
3450 {
3451 /* Determine how many UTF-16 character bytes are required
3452 */
3453 if( libuna_unicode_character_size_to_utf16(
3454 unicode_character,
3455 utf16_string_size,
3456 error ) != 1 )
3457 {
3458 libcerror_error_set(
3459 error,
3460 LIBCERROR_ERROR_DOMAIN_CONVERSION,
3461 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
3462 "%s: unable to unable to determine size of Unicode character in UTF-16.",
3463 function );
3464
3465 return( -1 );
3466 }
3467 if( unicode_character == 0 )
3468 {
3469 break;
3470 }
3471 }
3472 }
3473 /* Check if the string is terminated with an end-of-string character
3474 */
3475 if( unicode_character != 0 )
3476 {
3477 *utf16_string_size += 1;
3478 }
3479 return( 1 );
3480 }
3481
3482 /* Copies an UTF-16 string from a Standard Compression Scheme for Unicode (SCSU) stream
3483 * Returns 1 if successful or -1 on error
3484 */
libuna_utf16_string_copy_from_scsu_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,const uint8_t * scsu_stream,size_t scsu_stream_size,libcerror_error_t ** error)3485 int libuna_utf16_string_copy_from_scsu_stream(
3486 libuna_utf16_character_t *utf16_string,
3487 size_t utf16_string_size,
3488 const uint8_t *scsu_stream,
3489 size_t scsu_stream_size,
3490 libcerror_error_t **error )
3491 {
3492 static char *function = "libuna_utf16_string_copy_from_scsu_stream";
3493 size_t utf16_string_index = 0;
3494
3495 if( libuna_utf16_string_with_index_copy_from_scsu_stream(
3496 utf16_string,
3497 utf16_string_size,
3498 &utf16_string_index,
3499 scsu_stream,
3500 scsu_stream_size,
3501 error ) != 1 )
3502 {
3503 libcerror_error_set(
3504 error,
3505 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3506 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
3507 "%s: unable to SCSU stream to UTF-16 string.",
3508 function );
3509
3510 return( -1 );
3511 }
3512 return( 1 );
3513 }
3514
3515 /* Copies an UTF-16 string from a Standard Compression Scheme for Unicode (SCSU) stream
3516 * Returns 1 if successful or -1 on error
3517 */
libuna_utf16_string_with_index_copy_from_scsu_stream(libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_string_index,const uint8_t * scsu_stream,size_t scsu_stream_size,libcerror_error_t ** error)3518 int libuna_utf16_string_with_index_copy_from_scsu_stream(
3519 libuna_utf16_character_t *utf16_string,
3520 size_t utf16_string_size,
3521 size_t *utf16_string_index,
3522 const uint8_t *scsu_stream,
3523 size_t scsu_stream_size,
3524 libcerror_error_t **error )
3525 {
3526 uint32_t scsu_dynamic_window_positions[ 8 ] = {
3527 0x0080, 0x00c0, 0x0400, 0x0600, 0x0900, 0x3040, 0x30a0, 0xff00 };
3528
3529 static char *function = "libuna_utf16_string_with_index_copy_from_scsu_stream";
3530 libuna_unicode_character_t unicode_character = 0;
3531 size_t scsu_stream_index = 0;
3532 uint32_t scsu_window_position = 0;
3533 uint8_t byte_value1 = 0;
3534 uint8_t byte_value2 = 0;
3535 uint8_t byte_value3 = 0;
3536 uint8_t dynamic_window_position_index = 0;
3537 uint8_t in_unicode_mode = 0;
3538 uint8_t unicode_character_set = 0;
3539
3540 if( utf16_string == NULL )
3541 {
3542 libcerror_error_set(
3543 error,
3544 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3545 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3546 "%s: invalid UTF-16 string.",
3547 function );
3548
3549 return( -1 );
3550 }
3551 if( utf16_string_size > (size_t) SSIZE_MAX )
3552 {
3553 libcerror_error_set(
3554 error,
3555 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3556 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3557 "%s: invalid UTF-16 string size value exceeds maximum.",
3558 function );
3559
3560 return( -1 );
3561 }
3562 if( utf16_string_index == NULL )
3563 {
3564 libcerror_error_set(
3565 error,
3566 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3567 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3568 "%s: invalid UTF-16 string index.",
3569 function );
3570
3571 return( -1 );
3572 }
3573 if( scsu_stream == NULL )
3574 {
3575 libcerror_error_set(
3576 error,
3577 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3578 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3579 "%s: invalid SCSU stream.",
3580 function );
3581
3582 return( -1 );
3583 }
3584 if( scsu_stream_size > (size_t) SSIZE_MAX )
3585 {
3586 libcerror_error_set(
3587 error,
3588 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3589 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3590 "%s: invalid SCSU stream size value exceeds maximum.",
3591 function );
3592
3593 return( -1 );
3594 }
3595 if( scsu_stream_size == 0 )
3596 {
3597 libcerror_error_set(
3598 error,
3599 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3600 LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
3601 "%s: missing SCSU stream value.",
3602 function );
3603
3604 return( -1 );
3605 }
3606 while( scsu_stream_index < scsu_stream_size )
3607 {
3608 unicode_character_set = 0;
3609
3610 if( scsu_stream_index >= scsu_stream_size )
3611 {
3612 libcerror_error_set(
3613 error,
3614 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3615 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3616 "%s: SCSU stream too small.",
3617 function );
3618
3619 return( -1 );
3620 }
3621 byte_value1 = scsu_stream[ scsu_stream_index++ ];
3622
3623 if( in_unicode_mode != 0 )
3624 {
3625 if( ( byte_value1 <= 0xdf )
3626 || ( byte_value1 >= 0xf3 ) )
3627 {
3628 if( scsu_stream_index >= scsu_stream_size )
3629 {
3630 libcerror_error_set(
3631 error,
3632 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3633 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3634 "%s: SCSU stream too small.",
3635 function );
3636
3637 return( -1 );
3638 }
3639 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3640
3641 unicode_character = byte_value1;
3642 unicode_character <<= 8;
3643 unicode_character |= byte_value2;
3644
3645 unicode_character_set = 1;
3646 }
3647 /* UCn tags
3648 */
3649 else if( ( byte_value1 >= 0xe0 )
3650 && ( byte_value1 <= 0xe7 ) )
3651 {
3652 dynamic_window_position_index = byte_value1 - 0xe0;
3653
3654 in_unicode_mode = 0;
3655 }
3656 /* UDn tags
3657 */
3658 else if( ( byte_value1 >= 0xe8 )
3659 && ( byte_value1 <= 0xef ) )
3660 {
3661 if( scsu_stream_index >= scsu_stream_size )
3662 {
3663 libcerror_error_set(
3664 error,
3665 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3666 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3667 "%s: SCSU stream too small.",
3668 function );
3669
3670 return( -1 );
3671 }
3672 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3673
3674 dynamic_window_position_index = byte_value1 - 0xe8;
3675 scsu_window_position = libuna_scsu_window_offset_table[ byte_value2 ];
3676
3677 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3678
3679 in_unicode_mode = 0;
3680 }
3681 /* UQU tag
3682 */
3683 else if( byte_value1 == 0xf0 )
3684 {
3685 if( ( scsu_stream_size < 2 )
3686 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3687 {
3688 libcerror_error_set(
3689 error,
3690 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3691 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3692 "%s: SCSU stream too small.",
3693 function );
3694
3695 return( -1 );
3696 }
3697 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3698 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3699
3700 unicode_character = byte_value2;
3701 unicode_character <<= 8;
3702 unicode_character |= byte_value3;
3703
3704 unicode_character_set = 1;
3705 }
3706 /* UDX tag
3707 */
3708 else if( byte_value1 == 0xf1 )
3709 {
3710 if( ( scsu_stream_size < 2 )
3711 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3712 {
3713 libcerror_error_set(
3714 error,
3715 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3716 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3717 "%s: SCSU stream too small.",
3718 function );
3719
3720 return( -1 );
3721 }
3722 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3723 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3724
3725 dynamic_window_position_index = byte_value2 >> 5;
3726 scsu_window_position = byte_value2 & 0x1f;
3727 scsu_window_position <<= 8;
3728 scsu_window_position |= byte_value3;
3729 scsu_window_position <<= 7;
3730 scsu_window_position += 0x00010000UL;
3731
3732 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3733
3734 in_unicode_mode = 0;
3735 }
3736 }
3737 else
3738 {
3739 if( ( byte_value1 == 0x00 )
3740 || ( byte_value1 == 0x09 )
3741 || ( byte_value1 == 0x0a )
3742 || ( byte_value1 == 0x0c )
3743 || ( byte_value1 == 0x0d )
3744 || ( ( byte_value1 >= 0x20 )
3745 && ( byte_value1 <= 0x7f ) ) )
3746 {
3747 unicode_character = byte_value1;
3748
3749 unicode_character_set = 1;
3750 }
3751 /* SQn tags
3752 */
3753 else if( ( byte_value1 >= 0x01 )
3754 && ( byte_value1 <= 0x08 ) )
3755 {
3756 if( scsu_stream_index >= scsu_stream_size )
3757 {
3758 libcerror_error_set(
3759 error,
3760 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3761 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3762 "%s: SCSU stream too small.",
3763 function );
3764
3765 return( -1 );
3766 }
3767 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3768
3769 unicode_character = byte_value2;
3770
3771 if( byte_value2 < 0x80 )
3772 {
3773 unicode_character += libuna_scsu_static_window_positions[ byte_value1 - 0x01 ];
3774 }
3775 else
3776 {
3777 unicode_character -= 0x80;
3778 unicode_character += scsu_dynamic_window_positions[ byte_value1 - 0x01 ];
3779 }
3780 unicode_character_set = 1;
3781 }
3782 /* SDX tag
3783 */
3784 else if( byte_value1 == 0x0b )
3785 {
3786 if( ( scsu_stream_size < 2 )
3787 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3788 {
3789 libcerror_error_set(
3790 error,
3791 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3792 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3793 "%s: SCSU stream too small.",
3794 function );
3795
3796 return( -1 );
3797 }
3798 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3799 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3800
3801 dynamic_window_position_index = byte_value2 >> 5;
3802 scsu_window_position = byte_value2 & 0x1f;
3803 scsu_window_position <<= 8;
3804 scsu_window_position |= byte_value3;
3805 scsu_window_position <<= 7;
3806 scsu_window_position += 0x00010000UL;
3807
3808 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3809 }
3810 /* SQU tag
3811 */
3812 else if( byte_value1 == 0x0e )
3813 {
3814 if( ( scsu_stream_size < 2 )
3815 || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3816 {
3817 libcerror_error_set(
3818 error,
3819 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3820 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3821 "%s: SCSU stream too small.",
3822 function );
3823
3824 return( -1 );
3825 }
3826 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3827 byte_value3 = scsu_stream[ scsu_stream_index++ ];
3828
3829 unicode_character = byte_value2;
3830 unicode_character <<= 8;
3831 unicode_character |= byte_value3;
3832
3833 unicode_character_set = 1;
3834 }
3835 /* SCU tag
3836 */
3837 else if( byte_value1 == 0x0f )
3838 {
3839 in_unicode_mode = 1;
3840 }
3841 /* SCn tags
3842 */
3843 else if( ( byte_value1 >= 0x10 )
3844 && ( byte_value1 <= 0x17 ) )
3845 {
3846 dynamic_window_position_index = byte_value1 - 0x10;
3847 }
3848 /* SDn tags
3849 */
3850 else if( ( byte_value1 >= 0x18 )
3851 && ( byte_value1 <= 0x1f ) )
3852 {
3853 if( scsu_stream_index >= scsu_stream_size )
3854 {
3855 libcerror_error_set(
3856 error,
3857 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3858 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3859 "%s: SCSU stream too small.",
3860 function );
3861
3862 return( -1 );
3863 }
3864 byte_value2 = scsu_stream[ scsu_stream_index++ ];
3865
3866 dynamic_window_position_index = byte_value1 - 0x18;
3867 scsu_window_position = libuna_scsu_window_offset_table[ byte_value2 ];
3868
3869 scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3870 }
3871 else if( byte_value1 >= 0x80 )
3872 {
3873 unicode_character = byte_value1 - 0x80;
3874 unicode_character += scsu_dynamic_window_positions[ dynamic_window_position_index ];
3875
3876 unicode_character_set = 1;
3877 }
3878 }
3879 if( unicode_character_set != 0 )
3880 {
3881 /* Convert the Unicode character into UTF-16 character bytes
3882 */
3883 if( libuna_unicode_character_copy_to_utf16(
3884 unicode_character,
3885 utf16_string,
3886 utf16_string_size,
3887 utf16_string_index,
3888 error ) != 1 )
3889 {
3890 libcerror_error_set(
3891 error,
3892 LIBCERROR_ERROR_DOMAIN_CONVERSION,
3893 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3894 "%s: unable to copy Unicode character to UTF-16.",
3895 function );
3896
3897 return( -1 );
3898 }
3899 if( unicode_character == 0 )
3900 {
3901 break;
3902 }
3903 }
3904 }
3905 /* Check if the string is terminated with an end-of-string character
3906 */
3907 if( unicode_character != 0 )
3908 {
3909 if( *utf16_string_index >= utf16_string_size )
3910 {
3911 libcerror_error_set(
3912 error,
3913 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3914 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3915 "%s: UTF-16 string too small.",
3916 function );
3917
3918 return( -1 );
3919 }
3920 utf16_string[ *utf16_string_index ] = 0;
3921
3922 *utf16_string_index += 1;
3923 }
3924 return( 1 );
3925 }
3926
3927