1 /*
2  * UTF-16 stream 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_types.h"
28 #include "libuna_unicode_character.h"
29 #include "libuna_utf16_stream.h"
30 
31 /* Copies an UTF-16 stream byte order mark (BOM)
32  * Returns 1 if successful or -1 on error
33  */
libuna_utf16_stream_copy_byte_order_mark(uint8_t * utf16_stream,size_t utf16_stream_size,size_t * utf16_stream_index,int byte_order,libcerror_error_t ** error)34 int libuna_utf16_stream_copy_byte_order_mark(
35      uint8_t *utf16_stream,
36      size_t utf16_stream_size,
37      size_t *utf16_stream_index,
38      int byte_order,
39      libcerror_error_t **error )
40 {
41 	static char *function = "libuna_utf16_stream_copy_byte_order_mark";
42 
43 	if( utf16_stream == NULL )
44 	{
45 		libcerror_error_set(
46 		 error,
47 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49 		 "%s: invalid UTF-16 stream.",
50 		 function );
51 
52 		return( -1 );
53 	}
54 	if( utf16_stream_size > (size_t) SSIZE_MAX )
55 	{
56 		libcerror_error_set(
57 		 error,
58 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
60 		 "%s: invalid UTF-16 stream size value exceeds maximum.",
61 		 function );
62 
63 		return( -1 );
64 	}
65 	if( utf16_stream_index == NULL )
66 	{
67 		libcerror_error_set(
68 		 error,
69 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
70 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
71 		 "%s: invalid UTF-16 stream index.",
72 		 function );
73 
74 		return( -1 );
75 	}
76 	if( ( *utf16_stream_index + 2 ) > utf16_stream_size )
77 	{
78 		libcerror_error_set(
79 		 error,
80 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
82 		 "%s: UTF-16 stream too small.",
83 		 function );
84 
85 		return( -1 );
86 	}
87 	if( ( byte_order != LIBUNA_ENDIAN_BIG )
88 	 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
89 	{
90 		libcerror_error_set(
91 		 error,
92 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
93 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
94 		 "%s: unsupported byte order.",
95 		 function );
96 
97 		return( -1 );
98 	}
99 	if( byte_order == LIBUNA_ENDIAN_BIG )
100 	{
101 		utf16_stream[ *utf16_stream_index     ] = 0xfe;
102 		utf16_stream[ *utf16_stream_index + 1 ] = 0xff;
103 	}
104 	else if( byte_order == LIBUNA_ENDIAN_LITTLE )
105 	{
106 		utf16_stream[ *utf16_stream_index     ] = 0xff;
107 		utf16_stream[ *utf16_stream_index + 1 ] = 0xfe;
108 	}
109 	*utf16_stream_index += 2;
110 
111 	return( 1 );
112 }
113 
114 /* Determines the size of an UTF-16 stream from an UTF-8 string
115  * Returns 1 if successful or -1 on error
116  */
libuna_utf16_stream_size_from_utf8(const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,size_t * utf16_stream_size,libcerror_error_t ** error)117 int libuna_utf16_stream_size_from_utf8(
118      const libuna_utf8_character_t *utf8_string,
119      size_t utf8_string_size,
120      size_t *utf16_stream_size,
121      libcerror_error_t **error )
122 {
123 	static char *function                        = "libuna_utf16_stream_size_from_utf8";
124 	libuna_unicode_character_t unicode_character = 0;
125 	size_t utf8_string_index                     = 0;
126 
127 	if( utf8_string == NULL )
128 	{
129 		libcerror_error_set(
130 		 error,
131 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
132 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
133 		 "%s: invalid UTF-8 string.",
134 		 function );
135 
136 		return( -1 );
137 	}
138 	if( utf8_string_size > (size_t) SSIZE_MAX )
139 	{
140 		libcerror_error_set(
141 		 error,
142 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
143 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
144 		 "%s: invalid UTF-8 string size value exceeds maximum.",
145 		 function );
146 
147 		return( -1 );
148 	}
149 	if( utf16_stream_size == NULL )
150 	{
151 		libcerror_error_set(
152 		 error,
153 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155 		 "%s: invalid UTF-16 stream size.",
156 		 function );
157 
158 		return( -1 );
159 	}
160 	/* Add the byte order mark
161 	 */
162 	*utf16_stream_size = 1;
163 
164 	while( utf8_string_index < utf8_string_size )
165 	{
166 		/* Convert the UTF-8 character bytes into an Unicode character
167 		 */
168 		if( libuna_unicode_character_copy_from_utf8(
169 		     &unicode_character,
170 		     utf8_string,
171 		     utf8_string_size,
172 		     &utf8_string_index,
173 		     error ) != 1 )
174 		{
175 			libcerror_error_set(
176 			 error,
177 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
178 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
179 			 "%s: unable to copy Unicode character from UTF-8.",
180 			 function );
181 
182 			return( -1 );
183 		}
184 		/* Determine how many UTF-16 character bytes are required
185 		 */
186 		if( libuna_unicode_character_size_to_utf16(
187 		     unicode_character,
188 		     utf16_stream_size,
189 		     error ) != 1 )
190 		{
191 			libcerror_error_set(
192 			 error,
193 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
194 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
195 			 "%s: unable to determine size of Unicode character in UTF-16.",
196 			 function );
197 
198 			return( -1 );
199 		}
200 		if( unicode_character == 0 )
201 		{
202 			break;
203 		}
204 	}
205 	/* Convert the number of characters into bytes
206 	 */
207 	*utf16_stream_size *= 2;
208 
209 	return( 1 );
210 }
211 
212 /* Copies an UTF-16 stream from an UTF-8 string
213  * Returns 1 if successful or -1 on error
214  */
libuna_utf16_stream_copy_from_utf8(uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)215 int libuna_utf16_stream_copy_from_utf8(
216      uint8_t *utf16_stream,
217      size_t utf16_stream_size,
218      int byte_order,
219      const libuna_utf8_character_t *utf8_string,
220      size_t utf8_string_size,
221      libcerror_error_t **error )
222 {
223 	static char *function                        = "libuna_utf16_stream_copy_from_utf8";
224 	libuna_unicode_character_t unicode_character = 0;
225 	size_t utf16_stream_index                    = 0;
226 	size_t utf8_string_index                     = 0;
227 
228 	if( utf16_stream == NULL )
229 	{
230 		libcerror_error_set(
231 		 error,
232 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
233 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
234 		 "%s: invalid UTF-16 stream.",
235 		 function );
236 
237 		return( -1 );
238 	}
239 	if( utf16_stream_size > (size_t) SSIZE_MAX )
240 	{
241 		libcerror_error_set(
242 		 error,
243 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
244 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
245 		 "%s: invalid UTF-16 stream size value exceeds maximum.",
246 		 function );
247 
248 		return( -1 );
249 	}
250 	if( ( byte_order != LIBUNA_ENDIAN_BIG )
251 	 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
252 	{
253 		libcerror_error_set(
254 		 error,
255 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
256 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
257 		 "%s: unsupported byte order.",
258 		 function );
259 
260 		return( -1 );
261 	}
262 	if( utf8_string == NULL )
263 	{
264 		libcerror_error_set(
265 		 error,
266 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
267 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
268 		 "%s: invalid UTF-8 string.",
269 		 function );
270 
271 		return( -1 );
272 	}
273 	if( utf8_string_size > (size_t) SSIZE_MAX )
274 	{
275 		libcerror_error_set(
276 		 error,
277 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
278 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
279 		 "%s: invalid UTF-8 string size value exceeds maximum.",
280 		 function );
281 
282 		return( -1 );
283 	}
284 	if( libuna_utf16_stream_copy_byte_order_mark(
285 	     utf16_stream,
286 	     utf16_stream_size,
287 	     &utf16_stream_index,
288 	     byte_order,
289 	     error ) != 1 )
290 	{
291 		libcerror_error_set(
292 		 error,
293 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
294 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
295 		 "%s: unable to copy UTF-16 byte order mark.",
296 		 function );
297 
298 		return( -1 );
299 	}
300 	while( utf8_string_index < utf8_string_size )
301 	{
302 		/* Convert the UTF-8 string bytes into an Unicode character
303 		 */
304 		if( libuna_unicode_character_copy_from_utf8(
305 		     &unicode_character,
306 		     utf8_string,
307 		     utf8_string_size,
308 		     &utf8_string_index,
309 		     error ) != 1 )
310 		{
311 			libcerror_error_set(
312 			 error,
313 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
314 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
315 			 "%s: unable to copy Unicode character from UTF-8 string.",
316 			 function );
317 
318 			return( -1 );
319 		}
320 		/* Convert the Unicode character into UTF-16 stream bytes
321 		 */
322 		if( libuna_unicode_character_copy_to_utf16_stream(
323 		     unicode_character,
324 		     utf16_stream,
325 		     utf16_stream_size,
326 		     &utf16_stream_index,
327 		     byte_order,
328 		     error ) != 1 )
329 		{
330 			libcerror_error_set(
331 			 error,
332 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
333 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
334 			 "%s: unable to copy Unicode character to UTF-16 stream.",
335 			 function );
336 
337 			return( -1 );
338 		}
339 		if( unicode_character == 0 )
340 		{
341 			break;
342 		}
343 	}
344 	return( 1 );
345 }
346 
347 /* Determines the size of an UTF-16 stream from an UTF-16 string
348  * Returns 1 if successful or -1 on error
349  */
libuna_utf16_stream_size_from_utf16(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf16_stream_size,libcerror_error_t ** error)350 int libuna_utf16_stream_size_from_utf16(
351      const libuna_utf16_character_t *utf16_string,
352      size_t utf16_string_size,
353      size_t *utf16_stream_size,
354      libcerror_error_t **error )
355 {
356 	static char *function                        = "libuna_utf16_stream_size_from_utf16";
357 	libuna_unicode_character_t unicode_character = 0;
358 	size_t utf16_string_index                    = 0;
359 
360 	if( utf16_string == NULL )
361 	{
362 		libcerror_error_set(
363 		 error,
364 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
365 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
366 		 "%s: invalid UTF-16 string.",
367 		 function );
368 
369 		return( -1 );
370 	}
371 	if( utf16_string_size > (size_t) SSIZE_MAX )
372 	{
373 		libcerror_error_set(
374 		 error,
375 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
376 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
377 		 "%s: invalid UTF-16 string size value exceeds maximum.",
378 		 function );
379 
380 		return( -1 );
381 	}
382 	if( utf16_stream_size == NULL )
383 	{
384 		libcerror_error_set(
385 		 error,
386 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
387 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
388 		 "%s: invalid UTF-16 stream size.",
389 		 function );
390 
391 		return( -1 );
392 	}
393 	/* Add the byte order mark
394 	 */
395 	*utf16_stream_size = 1;
396 
397 	while( utf16_string_index < utf16_string_size )
398 	{
399 		/* Convert the UTF-16 character bytes into an Unicode character
400 		 */
401 		if( libuna_unicode_character_copy_from_utf16(
402 		     &unicode_character,
403 		     utf16_string,
404 		     utf16_string_size,
405 		     &utf16_string_index,
406 		     error ) != 1 )
407 		{
408 			libcerror_error_set(
409 			 error,
410 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
411 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
412 			 "%s: unable to copy Unicode character from UTF-16.",
413 			 function );
414 
415 			return( -1 );
416 		}
417 		/* Determine how many UTF-16 character bytes are required
418 		 */
419 		if( libuna_unicode_character_size_to_utf16(
420 		     unicode_character,
421 		     utf16_stream_size,
422 		     error ) != 1 )
423 		{
424 			libcerror_error_set(
425 			 error,
426 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
427 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
428 			 "%s: unable to determine size of Unicode character in UTF-16.",
429 			 function );
430 
431 			return( -1 );
432 		}
433 		if( unicode_character == 0 )
434 		{
435 			break;
436 		}
437 	}
438 	/* Convert the number of characters into bytes
439 	 */
440 	*utf16_stream_size *= 2;
441 
442 	return( 1 );
443 }
444 
445 /* Copies an UTF-16 stream from an UTF-16 string
446  * Returns 1 if successful or -1 on error
447  */
libuna_utf16_stream_copy_from_utf16(uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)448 int libuna_utf16_stream_copy_from_utf16(
449      uint8_t *utf16_stream,
450      size_t utf16_stream_size,
451      int byte_order,
452      const libuna_utf16_character_t *utf16_string,
453      size_t utf16_string_size,
454      libcerror_error_t **error )
455 {
456 	static char *function                        = "libuna_utf16_stream_copy_from_utf16";
457 	libuna_unicode_character_t unicode_character = 0;
458 	size_t utf16_stream_index                    = 0;
459 	size_t utf16_string_index                    = 0;
460 
461 	if( utf16_stream == NULL )
462 	{
463 		libcerror_error_set(
464 		 error,
465 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
466 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
467 		 "%s: invalid UTF-16 stream.",
468 		 function );
469 
470 		return( -1 );
471 	}
472 	if( utf16_stream_size > (size_t) SSIZE_MAX )
473 	{
474 		libcerror_error_set(
475 		 error,
476 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
477 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
478 		 "%s: invalid UTF-16 stream size value exceeds maximum.",
479 		 function );
480 
481 		return( -1 );
482 	}
483 	if( ( byte_order != LIBUNA_ENDIAN_BIG )
484 	 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
485 	{
486 		libcerror_error_set(
487 		 error,
488 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
489 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
490 		 "%s: unsupported byte order.",
491 		 function );
492 
493 		return( -1 );
494 	}
495 	if( utf16_string == NULL )
496 	{
497 		libcerror_error_set(
498 		 error,
499 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
500 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
501 		 "%s: invalid UTF-16 string.",
502 		 function );
503 
504 		return( -1 );
505 	}
506 	if( utf16_string_size > (size_t) SSIZE_MAX )
507 	{
508 		libcerror_error_set(
509 		 error,
510 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
511 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
512 		 "%s: invalid UTF-16 string size value exceeds maximum.",
513 		 function );
514 
515 		return( -1 );
516 	}
517 	if( libuna_utf16_stream_copy_byte_order_mark(
518 	     utf16_stream,
519 	     utf16_stream_size,
520 	     &utf16_stream_index,
521 	     byte_order,
522 	     error ) != 1 )
523 	{
524 		libcerror_error_set(
525 		 error,
526 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
527 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
528 		 "%s: unable to copy UTF-16 byte order mark.",
529 		 function );
530 
531 		return( -1 );
532 	}
533 	while( utf16_string_index < utf16_string_size )
534 	{
535 		/* Convert the UTF-16 string bytes into an Unicode character
536 		 */
537 		if( libuna_unicode_character_copy_from_utf16(
538 		     &unicode_character,
539 		     utf16_string,
540 		     utf16_string_size,
541 		     &utf16_string_index,
542 		     error ) != 1 )
543 		{
544 			libcerror_error_set(
545 			 error,
546 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
547 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
548 			 "%s: unable to copy Unicode character from UTF-16 string.",
549 			 function );
550 
551 			return( -1 );
552 		}
553 		/* Convert the Unicode character into UTF-16 stream bytes
554 		 */
555 		if( libuna_unicode_character_copy_to_utf16_stream(
556 		     unicode_character,
557 		     utf16_stream,
558 		     utf16_stream_size,
559 		     &utf16_stream_index,
560 		     byte_order,
561 		     error ) != 1 )
562 		{
563 			libcerror_error_set(
564 			 error,
565 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
566 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
567 			 "%s: unable to copy Unicode character to UTF-16 stream.",
568 			 function );
569 
570 			return( -1 );
571 		}
572 		if( unicode_character == 0 )
573 		{
574 			break;
575 		}
576 	}
577 	return( 1 );
578 }
579 
580 /* Determines the size of an UTF-16 stream from an UTF-32 string
581  * Returns 1 if successful or -1 on error
582  */
libuna_utf16_stream_size_from_utf32(const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,size_t * utf16_stream_size,libcerror_error_t ** error)583 int libuna_utf16_stream_size_from_utf32(
584      const libuna_utf32_character_t *utf32_string,
585      size_t utf32_string_size,
586      size_t *utf16_stream_size,
587      libcerror_error_t **error )
588 {
589 	static char *function                        = "libuna_utf16_stream_size_from_utf32";
590 	libuna_unicode_character_t unicode_character = 0;
591 	size_t utf32_string_index                    = 0;
592 
593 	if( utf32_string == NULL )
594 	{
595 		libcerror_error_set(
596 		 error,
597 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
598 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
599 		 "%s: invalid UTF-32 string.",
600 		 function );
601 
602 		return( -1 );
603 	}
604 	if( utf32_string_size > (size_t) SSIZE_MAX )
605 	{
606 		libcerror_error_set(
607 		 error,
608 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
609 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
610 		 "%s: invalid UTF-32 string size value exceeds maximum.",
611 		 function );
612 
613 		return( -1 );
614 	}
615 	if( utf16_stream_size == NULL )
616 	{
617 		libcerror_error_set(
618 		 error,
619 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
620 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
621 		 "%s: invalid UTF-16 stream size.",
622 		 function );
623 
624 		return( -1 );
625 	}
626 	/* Add the byte order mark
627 	 */
628 	*utf16_stream_size += 1;
629 
630 	while( utf32_string_index < utf32_string_size )
631 	{
632 		/* Convert the UTF-32 character bytes into an Unicode character
633 		 */
634 		if( libuna_unicode_character_copy_from_utf32(
635 		     &unicode_character,
636 		     utf32_string,
637 		     utf32_string_size,
638 		     &utf32_string_index,
639 		     error ) != 1 )
640 		{
641 			libcerror_error_set(
642 			 error,
643 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
644 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
645 			 "%s: unable to copy Unicode character from UTF-32.",
646 			 function );
647 
648 			return( -1 );
649 		}
650 		/* Determine how many UTF-16 character bytes are required
651 		 */
652 		if( libuna_unicode_character_size_to_utf16(
653 		     unicode_character,
654 		     utf16_stream_size,
655 		     error ) != 1 )
656 		{
657 			libcerror_error_set(
658 			 error,
659 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
660 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
661 			 "%s: unable to determine size of Unicode character in UTF-16.",
662 			 function );
663 
664 			return( -1 );
665 		}
666 		if( unicode_character == 0 )
667 		{
668 			break;
669 		}
670 	}
671 	/* Convert the number of characters into bytes
672 	 */
673 	*utf16_stream_size *= 2;
674 
675 	return( 1 );
676 }
677 
678 /* Copies an UTF-16 stream from an UTF-32 string
679  * Returns 1 if successful or -1 on error
680  */
libuna_utf16_stream_copy_from_utf32(uint8_t * utf16_stream,size_t utf16_stream_size,int byte_order,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)681 int libuna_utf16_stream_copy_from_utf32(
682      uint8_t *utf16_stream,
683      size_t utf16_stream_size,
684      int byte_order,
685      const libuna_utf32_character_t *utf32_string,
686      size_t utf32_string_size,
687      libcerror_error_t **error )
688 {
689 	static char *function                        = "libuna_utf16_stream_copy_from_utf32";
690 	libuna_unicode_character_t unicode_character = 0;
691 	size_t utf16_stream_index                    = 0;
692 	size_t utf32_string_index                    = 0;
693 
694 	if( utf16_stream == NULL )
695 	{
696 		libcerror_error_set(
697 		 error,
698 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
699 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
700 		 "%s: invalid UTF-16 stream.",
701 		 function );
702 
703 		return( -1 );
704 	}
705 	if( utf16_stream_size > (size_t) SSIZE_MAX )
706 	{
707 		libcerror_error_set(
708 		 error,
709 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
710 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
711 		 "%s: invalid UTF-16 stream size value exceeds maximum.",
712 		 function );
713 
714 		return( -1 );
715 	}
716 	if( ( byte_order != LIBUNA_ENDIAN_BIG )
717 	 && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
718 	{
719 		libcerror_error_set(
720 		 error,
721 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
722 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
723 		 "%s: unsupported byte order.",
724 		 function );
725 
726 		return( -1 );
727 	}
728 	if( utf32_string == NULL )
729 	{
730 		libcerror_error_set(
731 		 error,
732 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
733 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
734 		 "%s: invalid UTF-32 string.",
735 		 function );
736 
737 		return( -1 );
738 	}
739 	if( utf32_string_size > (size_t) SSIZE_MAX )
740 	{
741 		libcerror_error_set(
742 		 error,
743 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
744 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
745 		 "%s: invalid UTF-32 string size value exceeds maximum.",
746 		 function );
747 
748 		return( -1 );
749 	}
750 	if( libuna_utf16_stream_copy_byte_order_mark(
751 	     utf16_stream,
752 	     utf16_stream_size,
753 	     &utf16_stream_index,
754 	     byte_order,
755 	     error ) != 1 )
756 	{
757 		libcerror_error_set(
758 		 error,
759 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
760 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
761 		 "%s: unable to copy UTF-16 byte order mark.",
762 		 function );
763 
764 		return( -1 );
765 	}
766 	while( utf32_string_index < utf32_string_size )
767 	{
768 		/* Convert the UTF-32 string bytes into an Unicode character
769 		 */
770 		if( libuna_unicode_character_copy_from_utf32(
771 		     &unicode_character,
772 		     utf32_string,
773 		     utf32_string_size,
774 		     &utf32_string_index,
775 		     error ) != 1 )
776 		{
777 			libcerror_error_set(
778 			 error,
779 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
780 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
781 			 "%s: unable to copy Unicode character from UTF-32 string.",
782 			 function );
783 
784 			return( -1 );
785 		}
786 		/* Convert the Unicode character into UTF-16 stream bytes
787 		 */
788 		if( libuna_unicode_character_copy_to_utf16_stream(
789 		     unicode_character,
790 		     utf16_stream,
791 		     utf16_stream_size,
792 		     &utf16_stream_index,
793 		     byte_order,
794 		     error ) != 1 )
795 		{
796 			libcerror_error_set(
797 			 error,
798 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
799 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
800 			 "%s: unable to copy Unicode character to UTF-16 stream.",
801 			 function );
802 
803 			return( -1 );
804 		}
805 		if( unicode_character == 0 )
806 		{
807 			break;
808 		}
809 	}
810 	return( 1 );
811 }
812 
813