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