1 /*
2  * UTF-8 stream functions
3  *
4  * Copyright (C) 2008-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <memory.h>
24 #include <types.h>
25 
26 #include "libuna_definitions.h"
27 #include "libuna_libcerror.h"
28 #include "libuna_types.h"
29 #include "libuna_unicode_character.h"
30 #include "libuna_utf8_stream.h"
31 
32 /* Copies an UTF-8 stream byte order mark (BOM)
33  * Returns 1 if successful or -1 on error
34  */
libuna_utf8_stream_copy_byte_order_mark(uint8_t * utf8_stream,size_t utf8_stream_size,size_t * utf8_stream_index,libcerror_error_t ** error)35 int libuna_utf8_stream_copy_byte_order_mark(
36      uint8_t *utf8_stream,
37      size_t utf8_stream_size,
38      size_t *utf8_stream_index,
39      libcerror_error_t **error )
40 {
41 	static char *function = "libuna_utf8_stream_copy_byte_order_mark";
42 
43 	if( utf8_stream == NULL )
44 	{
45 		libcerror_error_set(
46 		 error,
47 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49 		 "%s: invalid UTF-8 stream.",
50 		 function );
51 
52 		return( -1 );
53 	}
54 	if( utf8_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-8 stream size value exceeds maximum.",
61 		 function );
62 
63 		return( -1 );
64 	}
65 	if( utf8_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-8 stream index.",
72 		 function );
73 
74 		return( -1 );
75 	}
76 	if( ( *utf8_stream_index + 3 ) > utf8_stream_size )
77 	{
78 		libcerror_error_set(
79 		 error,
80 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
82 		 "%s: UTF-8 stream too small.",
83 		 function );
84 
85 		return( -1 );
86 	}
87 	utf8_stream[ *utf8_stream_index     ] = 0xef;
88 	utf8_stream[ *utf8_stream_index + 1 ] = 0xbb;
89 	utf8_stream[ *utf8_stream_index + 2 ] = 0xbf;
90 
91 	*utf8_stream_index += 3;
92 
93 	return( 1 );
94 }
95 
96 /* Determines the size of an UTF-8 stream from an UTF-8 string
97  * Returns 1 if successful or -1 on error
98  */
libuna_utf8_stream_size_from_utf8(const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,size_t * utf8_stream_size,libcerror_error_t ** error)99 int libuna_utf8_stream_size_from_utf8(
100      const libuna_utf8_character_t *utf8_string,
101      size_t utf8_string_size,
102      size_t *utf8_stream_size,
103      libcerror_error_t **error )
104 {
105 	static char *function                        = "libuna_utf8_stream_size_from_utf8";
106 	libuna_unicode_character_t unicode_character = 0;
107 	size_t utf8_string_index                     = 0;
108 
109 	if( utf8_string == NULL )
110 	{
111 		libcerror_error_set(
112 		 error,
113 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
114 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
115 		 "%s: invalid UTF-8 string.",
116 		 function );
117 
118 		return( -1 );
119 	}
120 	if( utf8_string_size > (size_t) SSIZE_MAX )
121 	{
122 		libcerror_error_set(
123 		 error,
124 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
126 		 "%s: invalid UTF-8 string size value exceeds maximum.",
127 		 function );
128 
129 		return( -1 );
130 	}
131 	if( utf8_stream_size == NULL )
132 	{
133 		libcerror_error_set(
134 		 error,
135 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
136 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
137 		 "%s: invalid UTF-8 stream size.",
138 		 function );
139 
140 		return( -1 );
141 	}
142 	/* Add the byte order mark
143 	 */
144 	*utf8_stream_size = 3;
145 
146 	while( utf8_string_index < utf8_string_size )
147 	{
148 		/* Convert the UTF-8 character bytes into an Unicode character
149 		 */
150 		if( libuna_unicode_character_copy_from_utf8(
151 		     &unicode_character,
152 		     utf8_string,
153 		     utf8_string_size,
154 		     &utf8_string_index,
155 		     error ) != 1 )
156 		{
157 			libcerror_error_set(
158 			 error,
159 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
160 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
161 			 "%s: unable to copy Unicode character from UTF-8.",
162 			 function );
163 
164 			return( -1 );
165 		}
166 		/* Determine how many UTF-8 character bytes are required
167 		 */
168 		if( libuna_unicode_character_size_to_utf8(
169 		     unicode_character,
170 		     utf8_stream_size,
171 		     error ) != 1 )
172 		{
173 			libcerror_error_set(
174 			 error,
175 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
176 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
177 			 "%s: unable to determine size of Unicode character in UTF-8.",
178 			 function );
179 
180 			return( -1 );
181 		}
182 		if( unicode_character == 0 )
183 		{
184 			break;
185 		}
186 	}
187 	return( 1 );
188 }
189 
190 /* Copies an UTF-8 stream from an UTF-8 string
191  * Returns 1 if successful or -1 on error
192  */
libuna_utf8_stream_copy_from_utf8(uint8_t * utf8_stream,size_t utf8_stream_size,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)193 int libuna_utf8_stream_copy_from_utf8(
194      uint8_t *utf8_stream,
195      size_t utf8_stream_size,
196      const libuna_utf8_character_t *utf8_string,
197      size_t utf8_string_size,
198      libcerror_error_t **error )
199 {
200 	static char *function                        = "libuna_utf8_stream_copy_from_utf8";
201 	libuna_unicode_character_t unicode_character = 0;
202 	size_t utf8_stream_index                     = 0;
203 	size_t utf8_string_index                     = 0;
204 
205 	if( utf8_stream == NULL )
206 	{
207 		libcerror_error_set(
208 		 error,
209 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
210 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
211 		 "%s: invalid UTF-8 stream.",
212 		 function );
213 
214 		return( -1 );
215 	}
216 	if( utf8_stream_size > (size_t) SSIZE_MAX )
217 	{
218 		libcerror_error_set(
219 		 error,
220 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
221 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
222 		 "%s: invalid UTF-8 stream size value exceeds maximum.",
223 		 function );
224 
225 		return( -1 );
226 	}
227 	if( utf8_string == NULL )
228 	{
229 		libcerror_error_set(
230 		 error,
231 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
233 		 "%s: invalid UTF-8 string.",
234 		 function );
235 
236 		return( -1 );
237 	}
238 	if( utf8_string_size > (size_t) SSIZE_MAX )
239 	{
240 		libcerror_error_set(
241 		 error,
242 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
243 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
244 		 "%s: invalid UTF-8 string size value exceeds maximum.",
245 		 function );
246 
247 		return( -1 );
248 	}
249 	if( utf8_stream_size < utf8_string_size )
250 	{
251 		libcerror_error_set(
252 		 error,
253 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
254 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
255 		 "%s: UTF-8 stream is too small.",
256 		 function );
257 
258 		return( -1 );
259 	}
260 	if( libuna_utf8_stream_copy_byte_order_mark(
261 	     utf8_stream,
262 	     utf8_stream_size,
263 	     &utf8_stream_index,
264 	     error ) != 1 )
265 	{
266 		libcerror_error_set(
267 		 error,
268 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
269 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
270 		 "%s: unable to copy UTF-8 byte order mark.",
271 		 function );
272 
273 		return( -1 );
274 	}
275 	while( utf8_string_index < utf8_string_size )
276 	{
277 		/* Convert the UTF-8 string bytes into an Unicode character
278 		 */
279 		if( libuna_unicode_character_copy_from_utf8(
280 		     &unicode_character,
281 		     utf8_string,
282 		     utf8_string_size,
283 		     &utf8_string_index,
284 		     error ) != 1 )
285 		{
286 			libcerror_error_set(
287 			 error,
288 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
289 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
290 			 "%s: unable to copy Unicode character from UTF-8 string.",
291 			 function );
292 
293 			return( -1 );
294 		}
295 		/* Convert the Unicode character into UTF-8 stream bytes
296 		 */
297 		if( libuna_unicode_character_copy_to_utf8(
298 		     unicode_character,
299 		     utf8_stream,
300 		     utf8_stream_size,
301 		     &utf8_stream_index,
302 		     error ) != 1 )
303 		{
304 			libcerror_error_set(
305 			 error,
306 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
307 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
308 			 "%s: unable to copy Unicode character to UTF-8 stream.",
309 			 function );
310 
311 			return( -1 );
312 		}
313 		if( unicode_character == 0 )
314 		{
315 			break;
316 		}
317 	}
318 	return( 1 );
319 }
320 
321 /* Determines the size of an UTF-8 stream from an UTF-16 string
322  * Returns 1 if successful or -1 on error
323  */
libuna_utf8_stream_size_from_utf16(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf8_stream_size,libcerror_error_t ** error)324 int libuna_utf8_stream_size_from_utf16(
325      const libuna_utf16_character_t *utf16_string,
326      size_t utf16_string_size,
327      size_t *utf8_stream_size,
328      libcerror_error_t **error )
329 {
330 	static char *function                        = "libuna_utf8_stream_size_from_utf16";
331 	libuna_unicode_character_t unicode_character = 0;
332 	size_t utf16_string_index                    = 0;
333 
334 	if( utf16_string == NULL )
335 	{
336 		libcerror_error_set(
337 		 error,
338 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
339 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
340 		 "%s: invalid UTF-16 string.",
341 		 function );
342 
343 		return( -1 );
344 	}
345 	if( utf16_string_size > (size_t) SSIZE_MAX )
346 	{
347 		libcerror_error_set(
348 		 error,
349 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
350 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
351 		 "%s: invalid UTF-16 string size value exceeds maximum.",
352 		 function );
353 
354 		return( -1 );
355 	}
356 	if( utf8_stream_size == NULL )
357 	{
358 		libcerror_error_set(
359 		 error,
360 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
361 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
362 		 "%s: invalid UTF-8 stream size.",
363 		 function );
364 
365 		return( -1 );
366 	}
367 	/* Add the byte order mark
368 	 */
369 	*utf8_stream_size = 3;
370 
371 	while( utf16_string_index < utf16_string_size )
372 	{
373 		/* Convert the UTF-16 character bytes into an Unicode character
374 		 */
375 		if( libuna_unicode_character_copy_from_utf16(
376 		     &unicode_character,
377 		     utf16_string,
378 		     utf16_string_size,
379 		     &utf16_string_index,
380 		     error ) != 1 )
381 		{
382 			libcerror_error_set(
383 			 error,
384 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
385 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
386 			 "%s: unable to copy Unicode character from UTF-16.",
387 			 function );
388 
389 			return( -1 );
390 		}
391 		/* Determine how many UTF-8 character bytes are required
392 		 */
393 		if( libuna_unicode_character_size_to_utf8(
394 		     unicode_character,
395 		     utf8_stream_size,
396 		     error ) != 1 )
397 		{
398 			libcerror_error_set(
399 			 error,
400 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
401 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
402 			 "%s: unable to determine size of Unicode character in UTF-8.",
403 			 function );
404 
405 			return( -1 );
406 		}
407 		if( unicode_character == 0 )
408 		{
409 			break;
410 		}
411 	}
412 	return( 1 );
413 }
414 
415 /* Copies an UTF-8 stream from an UTF-16 string
416  * Returns 1 if successful or -1 on error
417  */
libuna_utf8_stream_copy_from_utf16(uint8_t * utf8_stream,size_t utf8_stream_size,const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)418 int libuna_utf8_stream_copy_from_utf16(
419      uint8_t *utf8_stream,
420      size_t utf8_stream_size,
421      const libuna_utf16_character_t *utf16_string,
422      size_t utf16_string_size,
423      libcerror_error_t **error )
424 {
425 	static char *function                        = "libuna_utf8_stream_copy_from_utf16";
426 	libuna_unicode_character_t unicode_character = 0;
427 	size_t utf16_string_index                    = 0;
428 	size_t utf8_stream_index                     = 0;
429 
430 	if( utf8_stream == NULL )
431 	{
432 		libcerror_error_set(
433 		 error,
434 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
435 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
436 		 "%s: invalid UTF-8 stream.",
437 		 function );
438 
439 		return( -1 );
440 	}
441 	if( utf8_stream_size > (size_t) SSIZE_MAX )
442 	{
443 		libcerror_error_set(
444 		 error,
445 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
446 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
447 		 "%s: invalid UTF-8 stream size value exceeds maximum.",
448 		 function );
449 
450 		return( -1 );
451 	}
452 	if( utf16_string == NULL )
453 	{
454 		libcerror_error_set(
455 		 error,
456 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458 		 "%s: invalid UTF-16 string.",
459 		 function );
460 
461 		return( -1 );
462 	}
463 	if( utf16_string_size > (size_t) SSIZE_MAX )
464 	{
465 		libcerror_error_set(
466 		 error,
467 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
469 		 "%s: invalid UTF-16 string size value exceeds maximum.",
470 		 function );
471 
472 		return( -1 );
473 	}
474 	if( libuna_utf8_stream_copy_byte_order_mark(
475 	     utf8_stream,
476 	     utf8_stream_size,
477 	     &utf8_stream_index,
478 	     error ) != 1 )
479 	{
480 		libcerror_error_set(
481 		 error,
482 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
483 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
484 		 "%s: unable to copy UTF-8 byte order mark.",
485 		 function );
486 
487 		return( -1 );
488 	}
489 	while( utf16_string_index < utf16_string_size )
490 	{
491 		/* Convert the UTF-16 string bytes into an Unicode character
492 		 */
493 		if( libuna_unicode_character_copy_from_utf16(
494 		     &unicode_character,
495 		     utf16_string,
496 		     utf16_string_size,
497 		     &utf16_string_index,
498 		     error ) != 1 )
499 		{
500 			libcerror_error_set(
501 			 error,
502 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
503 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
504 			 "%s: unable to copy Unicode character from UTF-16 string.",
505 			 function );
506 
507 			return( -1 );
508 		}
509 		/* Convert the Unicode character into UTF-8 stream bytes
510 		 */
511 		if( libuna_unicode_character_copy_to_utf8(
512 		     unicode_character,
513 		     utf8_stream,
514 		     utf8_stream_size,
515 		     &utf8_stream_index,
516 		     error ) != 1 )
517 		{
518 			libcerror_error_set(
519 			 error,
520 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
521 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
522 			 "%s: unable to copy Unicode character to UTF-8 stream.",
523 			 function );
524 
525 			return( -1 );
526 		}
527 		if( unicode_character == 0 )
528 		{
529 			break;
530 		}
531 	}
532 	return( 1 );
533 }
534 
535 /* Determines the size of an UTF-8 stream from an UTF-32 string
536  * Returns 1 if successful or -1 on error
537  */
libuna_utf8_stream_size_from_utf32(const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,size_t * utf8_stream_size,libcerror_error_t ** error)538 int libuna_utf8_stream_size_from_utf32(
539      const libuna_utf32_character_t *utf32_string,
540      size_t utf32_string_size,
541      size_t *utf8_stream_size,
542      libcerror_error_t **error )
543 {
544 	static char *function                        = "libuna_utf8_stream_size_from_utf32";
545 	libuna_unicode_character_t unicode_character = 0;
546 	size_t utf32_string_index                    = 0;
547 
548 	if( utf32_string == NULL )
549 	{
550 		libcerror_error_set(
551 		 error,
552 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
553 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
554 		 "%s: invalid UTF-32 string.",
555 		 function );
556 
557 		return( -1 );
558 	}
559 	if( utf32_string_size > (size_t) SSIZE_MAX )
560 	{
561 		libcerror_error_set(
562 		 error,
563 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
564 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
565 		 "%s: invalid UTF-32 string size value exceeds maximum.",
566 		 function );
567 
568 		return( -1 );
569 	}
570 	if( utf8_stream_size == NULL )
571 	{
572 		libcerror_error_set(
573 		 error,
574 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
575 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
576 		 "%s: invalid UTF-8 stream size.",
577 		 function );
578 
579 		return( -1 );
580 	}
581 	/* Add the byte order mark
582 	 */
583 	*utf8_stream_size = 3;
584 
585 	while( utf32_string_index < utf32_string_size )
586 	{
587 		/* Convert the UTF-32 character bytes into an Unicode character
588 		 */
589 		if( libuna_unicode_character_copy_from_utf32(
590 		     &unicode_character,
591 		     utf32_string,
592 		     utf32_string_size,
593 		     &utf32_string_index,
594 		     error ) != 1 )
595 		{
596 			libcerror_error_set(
597 			 error,
598 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
599 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
600 			 "%s: unable to copy Unicode character from UTF-32.",
601 			 function );
602 
603 			return( -1 );
604 		}
605 		/* Determine how many UTF-8 character bytes are required
606 		 */
607 		if( libuna_unicode_character_size_to_utf8(
608 		     unicode_character,
609 		     utf8_stream_size,
610 		     error ) != 1 )
611 		{
612 			libcerror_error_set(
613 			 error,
614 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
615 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
616 			 "%s: unable to determine size of Unicode character in UTF-8.",
617 			 function );
618 
619 			return( -1 );
620 		}
621 		if( unicode_character == 0 )
622 		{
623 			break;
624 		}
625 	}
626 	return( 1 );
627 }
628 
629 /* Copies an UTF-8 stream from an UTF-32 string
630  * Returns 1 if successful or -1 on error
631  */
libuna_utf8_stream_copy_from_utf32(uint8_t * utf8_stream,size_t utf8_stream_size,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)632 int libuna_utf8_stream_copy_from_utf32(
633      uint8_t *utf8_stream,
634      size_t utf8_stream_size,
635      const libuna_utf32_character_t *utf32_string,
636      size_t utf32_string_size,
637      libcerror_error_t **error )
638 {
639 	static char *function                        = "libuna_utf8_stream_copy_from_utf32";
640 	libuna_unicode_character_t unicode_character = 0;
641 	size_t utf32_string_index                    = 0;
642 	size_t utf8_stream_index                     = 0;
643 
644 	if( utf8_stream == NULL )
645 	{
646 		libcerror_error_set(
647 		 error,
648 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
649 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
650 		 "%s: invalid UTF-8 stream.",
651 		 function );
652 
653 		return( -1 );
654 	}
655 	if( utf8_stream_size > (size_t) SSIZE_MAX )
656 	{
657 		libcerror_error_set(
658 		 error,
659 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
660 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
661 		 "%s: invalid UTF-8 stream size value exceeds maximum.",
662 		 function );
663 
664 		return( -1 );
665 	}
666 	if( utf32_string == NULL )
667 	{
668 		libcerror_error_set(
669 		 error,
670 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
671 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
672 		 "%s: invalid UTF-32 string.",
673 		 function );
674 
675 		return( -1 );
676 	}
677 	if( utf32_string_size > (size_t) SSIZE_MAX )
678 	{
679 		libcerror_error_set(
680 		 error,
681 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
682 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
683 		 "%s: invalid UTF-32 string size value exceeds maximum.",
684 		 function );
685 
686 		return( -1 );
687 	}
688 	if( libuna_utf8_stream_copy_byte_order_mark(
689 	     utf8_stream,
690 	     utf8_stream_size,
691 	     &utf8_stream_index,
692 	     error ) != 1 )
693 	{
694 		libcerror_error_set(
695 		 error,
696 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
697 		 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
698 		 "%s: unable to copy UTF-8 byte order mark.",
699 		 function );
700 
701 		return( -1 );
702 	}
703 	while( utf32_string_index < utf32_string_size )
704 	{
705 		/* Convert the UTF-32 character bytes into an Unicode character
706 		 */
707 		if( libuna_unicode_character_copy_from_utf32(
708 		     &unicode_character,
709 		     utf32_string,
710 		     utf32_string_size,
711 		     &utf32_string_index,
712 		     error ) != 1 )
713 		{
714 			libcerror_error_set(
715 			 error,
716 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
717 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
718 			 "%s: unable to copy Unicode character from UTF-32.",
719 			 function );
720 
721 			return( -1 );
722 		}
723 		/* Convert the Unicode character into UTF-8 character bytes
724 		 */
725 		if( libuna_unicode_character_copy_to_utf8(
726 		     unicode_character,
727 		     utf8_stream,
728 		     utf8_stream_size,
729 		     &utf8_stream_index,
730 		     error ) != 1 )
731 		{
732 			libcerror_error_set(
733 			 error,
734 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
735 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
736 			 "%s: unable to copy Unicode character to UTF-8 stream.",
737 			 function );
738 
739 			return( -1 );
740 		}
741 		if( unicode_character == 0 )
742 		{
743 			break;
744 		}
745 	}
746 	return( 1 );
747 }
748 
749