1 /*
2  * Byte 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_byte_stream.h"
26 #include "libuna_definitions.h"
27 #include "libuna_libcerror.h"
28 #include "libuna_types.h"
29 #include "libuna_unicode_character.h"
30 
31 /* Determines the size of a byte stream from an UTF-8 string
32  * Returns 1 if successful or -1 on error
33  */
libuna_byte_stream_size_from_utf8(const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,int codepage,size_t * byte_stream_size,libcerror_error_t ** error)34 int libuna_byte_stream_size_from_utf8(
35      const libuna_utf8_character_t *utf8_string,
36      size_t utf8_string_size,
37      int codepage,
38      size_t *byte_stream_size,
39      libcerror_error_t **error )
40 {
41 	static char *function                        = "libuna_byte_stream_size_from_utf8";
42 	size_t utf8_string_index                     = 0;
43 	libuna_unicode_character_t unicode_character = 0;
44 
45 	if( utf8_string == NULL )
46 	{
47 		libcerror_error_set(
48 		 error,
49 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51 		 "%s: invalid UTF-8 string.",
52 		 function );
53 
54 		return( -1 );
55 	}
56 	if( utf8_string_size > (size_t) SSIZE_MAX )
57 	{
58 		libcerror_error_set(
59 		 error,
60 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
62 		 "%s: invalid UTF-8 string size value exceeds maximum.",
63 		 function );
64 
65 		return( -1 );
66 	}
67 	if( byte_stream_size == NULL )
68 	{
69 		libcerror_error_set(
70 		 error,
71 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
72 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
73 		 "%s: invalid byte stream size.",
74 		 function );
75 
76 		return( -1 );
77 	}
78 	*byte_stream_size = 0;
79 
80 	while( utf8_string_index < utf8_string_size )
81 	{
82 		/* Convert the UTF-8 character bytes into an Unicode character
83 		 */
84 		if( libuna_unicode_character_copy_from_utf8(
85 		     &unicode_character,
86 		     utf8_string,
87 		     utf8_string_size,
88 		     &utf8_string_index,
89 		     error ) != 1 )
90 		{
91 			libcerror_error_set(
92 			 error,
93 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
94 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
95 			 "%s: unable to copy Unicode character from UTF-8.",
96 			 function );
97 
98 			return( -1 );
99 		}
100 		/* Determine how many byte stream character bytes are required
101 		 */
102 		if( libuna_unicode_character_size_to_byte_stream(
103 		     unicode_character,
104 		     codepage,
105 		     byte_stream_size,
106 		     error ) != 1 )
107 		{
108 			libcerror_error_set(
109 			 error,
110 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
111 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
112 			 "%s: unable to unable to determine size of Unicode character in byte stream.",
113 			 function );
114 
115 			return( -1 );
116 		}
117 		if( unicode_character == 0 )
118 		{
119 			break;
120 		}
121 	}
122 	return( 1 );
123 }
124 
125 /* Copies a byte stream from an UTF-8 string
126  * Returns 1 if successful or -1 on error
127  */
libuna_byte_stream_copy_from_utf8(uint8_t * byte_stream,size_t byte_stream_size,int codepage,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)128 int libuna_byte_stream_copy_from_utf8(
129      uint8_t *byte_stream,
130      size_t byte_stream_size,
131      int codepage,
132      const libuna_utf8_character_t *utf8_string,
133      size_t utf8_string_size,
134      libcerror_error_t **error )
135 {
136 	static char *function                        = "libuna_byte_stream_copy_from_utf8";
137 	size_t byte_stream_index                     = 0;
138 	size_t utf8_string_index                     = 0;
139 	libuna_unicode_character_t unicode_character = 0;
140 
141 	if( byte_stream == NULL )
142 	{
143 		libcerror_error_set(
144 		 error,
145 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
146 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
147 		 "%s: invalid byte stream.",
148 		 function );
149 
150 		return( -1 );
151 	}
152 	if( byte_stream_size > (size_t) SSIZE_MAX )
153 	{
154 		libcerror_error_set(
155 		 error,
156 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
157 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
158 		 "%s: invalid byte stream size value exceeds maximum.",
159 		 function );
160 
161 		return( -1 );
162 	}
163 	if( utf8_string == NULL )
164 	{
165 		libcerror_error_set(
166 		 error,
167 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169 		 "%s: invalid UTF-8 string.",
170 		 function );
171 
172 		return( -1 );
173 	}
174 	if( utf8_string_size > (size_t) SSIZE_MAX )
175 	{
176 		libcerror_error_set(
177 		 error,
178 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
179 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
180 		 "%s: invalid UTF-8 string size value exceeds maximum.",
181 		 function );
182 
183 		return( -1 );
184 	}
185 	while( utf8_string_index < utf8_string_size )
186 	{
187 		/* Convert the UTF-8 string bytes into an Unicode character
188 		 */
189 		if( libuna_unicode_character_copy_from_utf8(
190 		     &unicode_character,
191 		     utf8_string,
192 		     utf8_string_size,
193 		     &utf8_string_index,
194 		     error ) != 1 )
195 		{
196 			libcerror_error_set(
197 			 error,
198 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
199 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
200 			 "%s: unable to copy Unicode character from UTF-8 string.",
201 			 function );
202 
203 			return( -1 );
204 		}
205 		/* Convert the Unicode character into a byte stream
206 		 */
207 		if( libuna_unicode_character_copy_to_byte_stream(
208 		     unicode_character,
209 		     byte_stream,
210 		     byte_stream_size,
211 		     &byte_stream_index,
212 		     codepage,
213 		     error ) != 1 )
214 		{
215 			libcerror_error_set(
216 			 error,
217 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
218 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
219 			 "%s: unable to copy Unicode character to byte stream.",
220 			 function );
221 
222 			return( -1 );
223 		}
224 		if( unicode_character == 0 )
225 		{
226 			break;
227 		}
228 	}
229 	return( 1 );
230 }
231 
232 /* Determines the size of a byte stream from an UTF-16 string
233  * Returns 1 if successful or -1 on error
234  */
libuna_byte_stream_size_from_utf16(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,int codepage,size_t * byte_stream_size,libcerror_error_t ** error)235 int libuna_byte_stream_size_from_utf16(
236      const libuna_utf16_character_t *utf16_string,
237      size_t utf16_string_size,
238      int codepage,
239      size_t *byte_stream_size,
240      libcerror_error_t **error )
241 {
242 	static char *function                        = "libuna_byte_stream_size_from_utf16";
243 	size_t utf16_string_index                    = 0;
244 	libuna_unicode_character_t unicode_character = 0;
245 
246 	if( utf16_string == NULL )
247 	{
248 		libcerror_error_set(
249 		 error,
250 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252 		 "%s: invalid UTF-16 string.",
253 		 function );
254 
255 		return( -1 );
256 	}
257 	if( utf16_string_size > (size_t) SSIZE_MAX )
258 	{
259 		libcerror_error_set(
260 		 error,
261 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
263 		 "%s: invalid UTF-16 string size value exceeds maximum.",
264 		 function );
265 
266 		return( -1 );
267 	}
268 	if( byte_stream_size == NULL )
269 	{
270 		libcerror_error_set(
271 		 error,
272 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274 		 "%s: invalid byte stream size.",
275 		 function );
276 
277 		return( -1 );
278 	}
279 	*byte_stream_size = 0;
280 
281 	while( utf16_string_index < utf16_string_size )
282 	{
283 		/* Convert the UTF-16 character bytes into an Unicode character
284 		 */
285 		if( libuna_unicode_character_copy_from_utf16(
286 		     &unicode_character,
287 		     utf16_string,
288 		     utf16_string_size,
289 		     &utf16_string_index,
290 		     error ) != 1 )
291 		{
292 			libcerror_error_set(
293 			 error,
294 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
295 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
296 			 "%s: unable to copy Unicode character from UTF-16.",
297 			 function );
298 
299 			return( -1 );
300 		}
301 		/* Determine how many byte stream character bytes are required
302 		 */
303 		if( libuna_unicode_character_size_to_byte_stream(
304 		     unicode_character,
305 		     codepage,
306 		     byte_stream_size,
307 		     error ) != 1 )
308 		{
309 			libcerror_error_set(
310 			 error,
311 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
312 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
313 			 "%s: unable to unable to determine size of Unicode character in byte stream.",
314 			 function );
315 
316 			return( -1 );
317 		}
318 		if( unicode_character == 0 )
319 		{
320 			break;
321 		}
322 	}
323 	return( 1 );
324 }
325 
326 /* Copies a byte stream from an UTF-16 string
327  * Returns 1 if successful or -1 on error
328  */
libuna_byte_stream_copy_from_utf16(uint8_t * byte_stream,size_t byte_stream_size,int codepage,const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)329 int libuna_byte_stream_copy_from_utf16(
330      uint8_t *byte_stream,
331      size_t byte_stream_size,
332      int codepage,
333      const libuna_utf16_character_t *utf16_string,
334      size_t utf16_string_size,
335      libcerror_error_t **error )
336 {
337 	static char *function                        = "libuna_byte_stream_copy_from_utf16";
338 	size_t byte_stream_index                     = 0;
339 	size_t utf16_string_index                    = 0;
340 	libuna_unicode_character_t unicode_character = 0;
341 
342 	if( byte_stream == NULL )
343 	{
344 		libcerror_error_set(
345 		 error,
346 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
347 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
348 		 "%s: invalid byte stream.",
349 		 function );
350 
351 		return( -1 );
352 	}
353 	if( byte_stream_size > (size_t) SSIZE_MAX )
354 	{
355 		libcerror_error_set(
356 		 error,
357 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
358 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
359 		 "%s: invalid byte stream size value exceeds maximum.",
360 		 function );
361 
362 		return( -1 );
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 	while( utf16_string_index < utf16_string_size )
387 	{
388 		/* Convert the UTF-16 string bytes into an Unicode character
389 		 */
390 		if( libuna_unicode_character_copy_from_utf16(
391 		     &unicode_character,
392 		     utf16_string,
393 		     utf16_string_size,
394 		     &utf16_string_index,
395 		     error ) != 1 )
396 		{
397 			libcerror_error_set(
398 			 error,
399 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
400 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
401 			 "%s: unable to copy Unicode character from UTF-16 string.",
402 			 function );
403 
404 			return( -1 );
405 		}
406 		/* Convert the Unicode character into a byte stream
407 		 */
408 		if( libuna_unicode_character_copy_to_byte_stream(
409 		     unicode_character,
410 		     byte_stream,
411 		     byte_stream_size,
412 		     &byte_stream_index,
413 		     codepage,
414 		     error ) != 1 )
415 		{
416 			libcerror_error_set(
417 			 error,
418 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
419 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
420 			 "%s: unable to copy Unicode character to byte stream.",
421 			 function );
422 
423 			return( -1 );
424 		}
425 		if( unicode_character == 0 )
426 		{
427 			break;
428 		}
429 	}
430 	return( 1 );
431 }
432 
433 /* Determines the size of a byte stream from an UTF-32 string
434  * Returns 1 if successful or -1 on error
435  */
libuna_byte_stream_size_from_utf32(const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,int codepage,size_t * byte_stream_size,libcerror_error_t ** error)436 int libuna_byte_stream_size_from_utf32(
437      const libuna_utf32_character_t *utf32_string,
438      size_t utf32_string_size,
439      int codepage,
440      size_t *byte_stream_size,
441      libcerror_error_t **error )
442 {
443 	static char *function                        = "libuna_byte_stream_size_from_utf32";
444 	size_t utf32_string_index                    = 0;
445 	libuna_unicode_character_t unicode_character = 0;
446 
447 	if( utf32_string == NULL )
448 	{
449 		libcerror_error_set(
450 		 error,
451 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
452 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
453 		 "%s: invalid UTF-32 string.",
454 		 function );
455 
456 		return( -1 );
457 	}
458 	if( utf32_string_size > (size_t) SSIZE_MAX )
459 	{
460 		libcerror_error_set(
461 		 error,
462 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
463 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
464 		 "%s: invalid UTF-32 string size value exceeds maximum.",
465 		 function );
466 
467 		return( -1 );
468 	}
469 	if( byte_stream_size == NULL )
470 	{
471 		libcerror_error_set(
472 		 error,
473 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
474 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
475 		 "%s: invalid byte stream size.",
476 		 function );
477 
478 		return( -1 );
479 	}
480 	*byte_stream_size = 0;
481 
482 	while( utf32_string_index < utf32_string_size )
483 	{
484 		/* Convert the UTF-32 character bytes into an Unicode character
485 		 */
486 		if( libuna_unicode_character_copy_from_utf32(
487 		     &unicode_character,
488 		     utf32_string,
489 		     utf32_string_size,
490 		     &utf32_string_index,
491 		     error ) != 1 )
492 		{
493 			libcerror_error_set(
494 			 error,
495 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
496 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
497 			 "%s: unable to copy Unicode character from UTF-32.",
498 			 function );
499 
500 			return( -1 );
501 		}
502 		/* Determine how many byte stream character bytes are required
503 		 */
504 		if( libuna_unicode_character_size_to_byte_stream(
505 		     unicode_character,
506 		     codepage,
507 		     byte_stream_size,
508 		     error ) != 1 )
509 		{
510 			libcerror_error_set(
511 			 error,
512 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
513 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
514 			 "%s: unable to unable to determine size of Unicode character in byte stream.",
515 			 function );
516 
517 			return( -1 );
518 		}
519 		if( unicode_character == 0 )
520 		{
521 			break;
522 		}
523 	}
524 	return( 1 );
525 }
526 
527 /* Copies a byte stream from an UTF-32 string
528  * Returns 1 if successful or -1 on error
529  */
libuna_byte_stream_copy_from_utf32(uint8_t * byte_stream,size_t byte_stream_size,int codepage,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)530 int libuna_byte_stream_copy_from_utf32(
531      uint8_t *byte_stream,
532      size_t byte_stream_size,
533      int codepage,
534      const libuna_utf32_character_t *utf32_string,
535      size_t utf32_string_size,
536      libcerror_error_t **error )
537 {
538 	static char *function                        = "libuna_byte_stream_copy_from_utf32";
539 	size_t byte_stream_index                     = 0;
540 	size_t utf32_string_index                    = 0;
541 	libuna_unicode_character_t unicode_character = 0;
542 
543 	if( byte_stream == NULL )
544 	{
545 		libcerror_error_set(
546 		 error,
547 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
548 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
549 		 "%s: invalid byte stream.",
550 		 function );
551 
552 		return( -1 );
553 	}
554 	if( byte_stream_size > (size_t) SSIZE_MAX )
555 	{
556 		libcerror_error_set(
557 		 error,
558 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
559 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
560 		 "%s: invalid byte stream size value exceeds maximum.",
561 		 function );
562 
563 		return( -1 );
564 	}
565 	if( utf32_string == NULL )
566 	{
567 		libcerror_error_set(
568 		 error,
569 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
571 		 "%s: invalid UTF-32 string.",
572 		 function );
573 
574 		return( -1 );
575 	}
576 	if( utf32_string_size > (size_t) SSIZE_MAX )
577 	{
578 		libcerror_error_set(
579 		 error,
580 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
581 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
582 		 "%s: invalid UTF-32 string size value exceeds maximum.",
583 		 function );
584 
585 		return( -1 );
586 	}
587 	while( utf32_string_index < utf32_string_size )
588 	{
589 		/* Convert the UTF-32 string bytes into an Unicode character
590 		 */
591 		if( libuna_unicode_character_copy_from_utf32(
592 		     &unicode_character,
593 		     utf32_string,
594 		     utf32_string_size,
595 		     &utf32_string_index,
596 		     error ) != 1 )
597 		{
598 			libcerror_error_set(
599 			 error,
600 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
601 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
602 			 "%s: unable to copy Unicode character from UTF-32 string.",
603 			 function );
604 
605 			return( -1 );
606 		}
607 		/* Convert the Unicode character into a byte stream
608 		 */
609 		if( libuna_unicode_character_copy_to_byte_stream(
610 		     unicode_character,
611 		     byte_stream,
612 		     byte_stream_size,
613 		     &byte_stream_index,
614 		     codepage,
615 		     error ) != 1 )
616 		{
617 			libcerror_error_set(
618 			 error,
619 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
620 			 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
621 			 "%s: unable to copy Unicode character to byte stream.",
622 			 function );
623 
624 			return( -1 );
625 		}
626 		if( unicode_character == 0 )
627 		{
628 			break;
629 		}
630 	}
631 	return( 1 );
632 }
633 
634