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