1 /*
2 * Base16 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 <byte_stream.h>
24 #include <types.h>
25
26 #include "libuna_base16_stream.h"
27 #include "libuna_definitions.h"
28 #include "libuna_libcerror.h"
29 #include "libuna_types.h"
30
31 /* Copies a base16 character from a base16 stream
32 * Returns 1 if successful or -1 on error
33 */
libuna_base16_character_copy_from_base16_stream(uint32_t * base16_character,const uint8_t * base16_stream,uint32_t base16_variant,libcerror_error_t ** error)34 int libuna_base16_character_copy_from_base16_stream(
35 uint32_t *base16_character,
36 const uint8_t *base16_stream,
37 uint32_t base16_variant,
38 libcerror_error_t **error )
39 {
40 static char *function = "libuna_base16_character_copy_from_base16_stream";
41 uint32_t safe_base16_character = 0;
42
43 if( base16_character == NULL )
44 {
45 libcerror_error_set(
46 error,
47 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
48 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
49 "%s: invalid base16 character.",
50 function );
51
52 return( -1 );
53 }
54 if( base16_stream == NULL )
55 {
56 libcerror_error_set(
57 error,
58 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60 "%s: invalid base16 stream.",
61 function );
62
63 return( -1 );
64 }
65 switch( base16_variant & 0xf0000000UL )
66 {
67 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
68 safe_base16_character = *base16_stream;
69 break;
70
71 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
72 byte_stream_copy_to_uint16_big_endian(
73 base16_stream,
74 safe_base16_character );
75 break;
76
77 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
78 byte_stream_copy_to_uint16_little_endian(
79 base16_stream,
80 safe_base16_character );
81 break;
82
83 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
84 byte_stream_copy_to_uint32_big_endian(
85 base16_stream,
86 safe_base16_character );
87 break;
88
89 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
90 byte_stream_copy_to_uint32_little_endian(
91 base16_stream,
92 safe_base16_character );
93 break;
94
95 default:
96 libcerror_error_set(
97 error,
98 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
99 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
100 "%s: unsupported base16 variant.",
101 function );
102
103 return( -1 );
104 }
105 if( ( safe_base16_character & 0xffffff00UL ) != 0 )
106 {
107 libcerror_error_set(
108 error,
109 LIBCERROR_ERROR_DOMAIN_RUNTIME,
110 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
111 "%s: invalid base16 character.",
112 function );
113
114 return( -1 );
115 }
116 *base16_character = safe_base16_character;
117
118 return( 1 );
119 }
120
121 /* Determines the size of a byte stream from a base16 stream
122 *
123 * LIBUNA_BASE16_FLAG_STRIP_WHITESPACE removes leading space and tab characters,
124 * and trailing space, tab and end of line characters
125 *
126 * Returns 1 if successful or -1 on error
127 */
libuna_base16_stream_size_to_byte_stream(const uint8_t * base16_stream,size_t base16_stream_size,size_t * byte_stream_size,uint32_t base16_variant,uint8_t flags,libcerror_error_t ** error)128 int libuna_base16_stream_size_to_byte_stream(
129 const uint8_t *base16_stream,
130 size_t base16_stream_size,
131 size_t *byte_stream_size,
132 uint32_t base16_variant,
133 uint8_t flags,
134 libcerror_error_t **error )
135 {
136 static char *function = "libuna_base16_stream_size_to_byte_stream";
137 size_t base16_character_size = 0;
138 size_t base16_stream_index = 0;
139 size_t number_of_characters = 0;
140 size_t whitespace_size = 0;
141 uint32_t base16_character1 = 0;
142 uint32_t base16_character2 = 0;
143 uint8_t character_case = 0;
144 uint8_t character_limit = 0;
145 uint8_t strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
146
147 if( base16_stream == NULL )
148 {
149 libcerror_error_set(
150 error,
151 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
152 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
153 "%s: invalid base16 stream.",
154 function );
155
156 return( -1 );
157 }
158 if( base16_stream_size > (size_t) SSIZE_MAX )
159 {
160 libcerror_error_set(
161 error,
162 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
164 "%s: invalid base16 stream size value exceeds maximum.",
165 function );
166
167 return( -1 );
168 }
169 if( byte_stream_size == NULL )
170 {
171 libcerror_error_set(
172 error,
173 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175 "%s: invalid byte stream size.",
176 function );
177
178 return( -1 );
179 }
180 switch( base16_variant & 0x000000ffUL )
181 {
182 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_NONE:
183 character_limit = 0;
184 break;
185
186 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_64:
187 character_limit = 64;
188 break;
189
190 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_76:
191 character_limit = 76;
192 break;
193
194 default:
195 libcerror_error_set(
196 error,
197 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
198 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
199 "%s: unsupported base16 variant.",
200 function );
201
202 return( -1 );
203 }
204 switch( base16_variant & 0x000f0000UL )
205 {
206 case LIBUNA_BASE16_VARIANT_CASE_LOWER:
207 character_case = LIBUNA_CASE_LOWER;
208 break;
209
210 case LIBUNA_BASE16_VARIANT_CASE_MIXED:
211 character_case = LIBUNA_CASE_MIXED;
212 break;
213
214 case LIBUNA_BASE16_VARIANT_CASE_UPPER:
215 character_case = LIBUNA_CASE_UPPER;
216 break;
217
218 default:
219 libcerror_error_set(
220 error,
221 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
222 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
223 "%s: unsupported base16 variant.",
224 function );
225
226 return( -1 );
227 }
228 switch( base16_variant & 0xf0000000UL )
229 {
230 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
231 base16_character_size = 1;
232 break;
233
234 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
235 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
236 base16_character_size = 2;
237 break;
238
239 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
240 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
241 base16_character_size = 4;
242 break;
243
244 default:
245 libcerror_error_set(
246 error,
247 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
248 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
249 "%s: unsupported base16 variant.",
250 function );
251
252 return( -1 );
253 }
254 if( ( flags & ~( LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) ) != 0 )
255 {
256 libcerror_error_set(
257 error,
258 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
259 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
260 "%s: unsupported flags.",
261 function );
262
263 return( -1 );
264 }
265 /* Ignore trailing whitespace
266 */
267 if( base16_stream_size > base16_character_size )
268 {
269 base16_stream_index = base16_stream_size - base16_character_size;
270 whitespace_size = 0;
271
272 while( base16_stream_index > base16_character_size )
273 {
274 if( libuna_base16_character_copy_from_base16_stream(
275 &base16_character1,
276 &( base16_stream[ base16_stream_index ] ),
277 base16_variant,
278 error ) != 1 )
279 {
280 libcerror_error_set(
281 error,
282 LIBCERROR_ERROR_DOMAIN_CONVERSION,
283 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
284 "%s: unable to copy base16 character at index: %" PRIzd ".",
285 function,
286 base16_stream_index );
287
288 return( -1 );
289 }
290 base16_stream_index -= base16_character_size;
291
292 if( ( base16_character1 == (uint32_t) '\n' )
293 || ( base16_character1 == (uint32_t) '\r' ) )
294 {
295 whitespace_size += base16_character_size;
296 }
297 else if( ( flags & LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) == 0 )
298 {
299 break;
300 }
301 else if( ( base16_character1 == (uint32_t) ' ' )
302 || ( base16_character1 == (uint32_t) '\t' )
303 || ( base16_character1 == (uint32_t) '\v' ) )
304 {
305 whitespace_size += base16_character_size;
306 }
307 else
308 {
309 break;
310 }
311 }
312 base16_stream_size -= whitespace_size;
313 }
314 base16_stream_index = 0;
315 whitespace_size = 0;
316
317 while( base16_stream_index < base16_stream_size )
318 {
319 if( libuna_base16_character_copy_from_base16_stream(
320 &base16_character1,
321 &( base16_stream[ base16_stream_index ] ),
322 base16_variant,
323 error ) != 1 )
324 {
325 libcerror_error_set(
326 error,
327 LIBCERROR_ERROR_DOMAIN_CONVERSION,
328 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
329 "%s: unable to copy base16 character at index: %" PRIzd ".",
330 function,
331 base16_stream_index );
332
333 return( -1 );
334 }
335 base16_stream_index += base16_character_size;
336
337 if( ( base16_character1 == (uint32_t) '\n' )
338 || ( base16_character1 == (uint32_t) '\r' ) )
339 {
340 if( ( strip_mode != LIBUNA_STRIP_MODE_NON_WHITESPACE )
341 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
342 {
343 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
344 }
345 else
346 {
347 /* Handle multi-character end-of-line
348 */
349 if( ( base16_stream_index + base16_character_size ) < base16_stream_size )
350 {
351 if( libuna_base16_character_copy_from_base16_stream(
352 &base16_character2,
353 &( base16_stream[ base16_stream_index + base16_character_size ] ),
354 base16_variant,
355 error ) != 1 )
356 {
357 libcerror_error_set(
358 error,
359 LIBCERROR_ERROR_DOMAIN_CONVERSION,
360 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
361 "%s: unable to copy base16 character at index: %" PRIzd ".",
362 function,
363 base16_stream_index );
364
365 return( -1 );
366 }
367 if( ( base16_character2 == (uint32_t) '\n' )
368 || ( base16_character2 == (uint32_t) '\r' ) )
369 {
370 base16_stream_index += base16_character_size;
371 whitespace_size += base16_character_size;
372 }
373 }
374 strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
375 }
376 if( character_limit != 0 )
377 {
378 if( number_of_characters != (size_t) character_limit )
379 {
380 libcerror_error_set(
381 error,
382 LIBCERROR_ERROR_DOMAIN_CONVERSION,
383 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
384 "%s: number of characters in line does not match character limit.",
385 function );
386
387 return( -1 );
388 }
389 number_of_characters = 0;
390 }
391 whitespace_size += base16_character_size;
392 }
393 else if( ( base16_character1 == (uint32_t) ' ' )
394 || ( base16_character1 == (uint32_t) '\t' )
395 || ( base16_character1 == (uint32_t) '\v' ) )
396 {
397 if( ( flags & LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) != 0 )
398 {
399 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
400 {
401 strip_mode = LIBUNA_STRIP_MODE_TRAILING_WHITESPACE;
402 }
403 if( ( strip_mode != LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
404 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
405 {
406 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
407 }
408 else
409 {
410 whitespace_size += base16_character_size;
411 }
412 }
413 else
414 {
415 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
416 }
417 }
418 else if( strip_mode == LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
419 {
420 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
421 }
422 else if( strip_mode == LIBUNA_STRIP_MODE_TRAILING_WHITESPACE )
423 {
424 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
425 }
426 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
427 {
428 if( ( base16_character1 >= (uint32_t) 'A' )
429 && ( base16_character1 <= (uint32_t) 'F' ) )
430 {
431 if( ( character_case != LIBUNA_CASE_MIXED )
432 && ( character_case != LIBUNA_CASE_UPPER ) )
433 {
434 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
435 }
436 number_of_characters++;
437 }
438 else if( ( base16_character1 >= (uint32_t) 'a' )
439 && ( base16_character1 <= (uint32_t) 'f' ) )
440 {
441 if( ( character_case != LIBUNA_CASE_MIXED )
442 && ( character_case != LIBUNA_CASE_LOWER ) )
443 {
444 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
445 }
446 number_of_characters++;
447 }
448 else if( ( base16_character1 >= (uint32_t) '0' )
449 && ( base16_character1 <= (uint32_t) '9' ) )
450 {
451 number_of_characters++;
452 }
453 else
454 {
455 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
456 }
457 }
458 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
459 {
460 libcerror_error_set(
461 error,
462 LIBCERROR_ERROR_DOMAIN_CONVERSION,
463 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
464 "%s: invalid character in base16 stream at index: %" PRIzd ".",
465 function,
466 base16_stream_index - base16_character_size );
467
468 return( -1 );
469 }
470 }
471 if( character_limit != 0 )
472 {
473 if( number_of_characters > (size_t) character_limit )
474 {
475 libcerror_error_set(
476 error,
477 LIBCERROR_ERROR_DOMAIN_CONVERSION,
478 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
479 "%s: number of characters in last line exceed maximum.",
480 function );
481
482 return( -1 );
483 }
484 }
485 base16_stream_size -= whitespace_size;
486
487 /* Make sure the byte stream is able to hold
488 * at least 1 byte for each 2 base16 characters
489 */
490 base16_character_size *= 2;
491
492 if( ( base16_stream_size % base16_character_size ) != 0 )
493 {
494 libcerror_error_set(
495 error,
496 LIBCERROR_ERROR_DOMAIN_CONVERSION,
497 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
498 "%s: invalid base16 stream size.",
499 function );
500
501 return( -1 );
502 }
503 base16_stream_size /= base16_character_size;
504
505 *byte_stream_size = base16_stream_size;
506
507 return( 1 );
508 }
509
510 /* Copies a byte stream from a base16 stream
511 *
512 * LIBUNA_BASE16_FLAG_STRIP_WHITESPACE removes leading space and tab characters,
513 * and trailing space, tab and end of line characters
514 *
515 * Returns 1 if successful or -1 on error
516 */
libuna_base16_stream_copy_to_byte_stream(const uint8_t * base16_stream,size_t base16_stream_size,uint8_t * byte_stream,size_t byte_stream_size,uint32_t base16_variant,uint8_t flags,libcerror_error_t ** error)517 int libuna_base16_stream_copy_to_byte_stream(
518 const uint8_t *base16_stream,
519 size_t base16_stream_size,
520 uint8_t *byte_stream,
521 size_t byte_stream_size,
522 uint32_t base16_variant,
523 uint8_t flags,
524 libcerror_error_t **error )
525 {
526 static char *function = "libuna_base16_stream_copy_to_byte_stream";
527 size_t base16_character_size = 0;
528 size_t base16_stream_index = 0;
529 size_t byte_stream_index = 0;
530 size_t number_of_characters = 0;
531 size_t whitespace_size = 0;
532 uint32_t base16_character1 = 0;
533 uint32_t base16_character2 = 0;
534 uint8_t byte_value = 0;
535 uint8_t character_case = 0;
536 uint8_t character_limit = 0;
537 uint8_t strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
538
539 if( base16_stream == NULL )
540 {
541 libcerror_error_set(
542 error,
543 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
544 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
545 "%s: invalid base16 stream.",
546 function );
547
548 return( -1 );
549 }
550 if( base16_stream_size > (size_t) SSIZE_MAX )
551 {
552 libcerror_error_set(
553 error,
554 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
555 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
556 "%s: invalid base16 stream size value exceeds maximum.",
557 function );
558
559 return( -1 );
560 }
561 if( byte_stream == NULL )
562 {
563 libcerror_error_set(
564 error,
565 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
566 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
567 "%s: invalid byte stream.",
568 function );
569
570 return( -1 );
571 }
572 if( byte_stream_size > (size_t) SSIZE_MAX )
573 {
574 libcerror_error_set(
575 error,
576 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
577 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
578 "%s: invalid byte stream size value exceeds maximum.",
579 function );
580
581 return( -1 );
582 }
583 switch( base16_variant & 0x000000ffUL )
584 {
585 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_NONE:
586 character_limit = 0;
587 break;
588
589 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_64:
590 character_limit = 64;
591 break;
592
593 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_76:
594 character_limit = 76;
595 break;
596
597 default:
598 libcerror_error_set(
599 error,
600 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
601 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
602 "%s: unsupported base16 variant.",
603 function );
604
605 return( -1 );
606 }
607 switch( base16_variant & 0x000f0000UL )
608 {
609 case LIBUNA_BASE16_VARIANT_CASE_LOWER:
610 character_case = LIBUNA_CASE_LOWER;
611 break;
612
613 case LIBUNA_BASE16_VARIANT_CASE_MIXED:
614 character_case = LIBUNA_CASE_MIXED;
615 break;
616
617 case LIBUNA_BASE16_VARIANT_CASE_UPPER:
618 character_case = LIBUNA_CASE_UPPER;
619 break;
620
621 default:
622 libcerror_error_set(
623 error,
624 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
625 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
626 "%s: unsupported base16 variant.",
627 function );
628
629 return( -1 );
630 }
631 switch( base16_variant & 0xf0000000UL )
632 {
633 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
634 base16_character_size = 1;
635 break;
636
637 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
638 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
639 base16_character_size = 2;
640 break;
641
642 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
643 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
644 base16_character_size = 4;
645 break;
646
647 default:
648 libcerror_error_set(
649 error,
650 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
651 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
652 "%s: unsupported base16 variant.",
653 function );
654
655 return( -1 );
656 }
657 if( ( flags & ~( LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) ) != 0 )
658 {
659 libcerror_error_set(
660 error,
661 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
662 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
663 "%s: unsupported flags.",
664 function );
665
666 return( -1 );
667 }
668 /* Ignore trailing whitespace
669 */
670 if( base16_stream_size > base16_character_size )
671 {
672 base16_stream_index = base16_stream_size - base16_character_size;
673 whitespace_size = 0;
674
675 while( base16_stream_index > base16_character_size )
676 {
677 if( libuna_base16_character_copy_from_base16_stream(
678 &base16_character1,
679 &( base16_stream[ base16_stream_index ] ),
680 base16_variant,
681 error ) != 1 )
682 {
683 libcerror_error_set(
684 error,
685 LIBCERROR_ERROR_DOMAIN_CONVERSION,
686 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
687 "%s: unable to copy base16 character at index: %" PRIzd ".",
688 function,
689 base16_stream_index );
690
691 return( -1 );
692 }
693 base16_stream_index -= base16_character_size;
694
695 if( ( base16_character1 == (uint32_t) '\n' )
696 || ( base16_character1 == (uint32_t) '\r' ) )
697 {
698 whitespace_size += base16_character_size;
699 }
700 else if( ( flags & LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) == 0 )
701 {
702 break;
703 }
704 else if( ( base16_character1 == (uint32_t) ' ' )
705 || ( base16_character1 == (uint32_t) '\t' )
706 || ( base16_character1 == (uint32_t) '\v' ) )
707 {
708 whitespace_size += base16_character_size;
709 }
710 else
711 {
712 break;
713 }
714 }
715 base16_stream_size -= whitespace_size;
716 }
717 if( ( flags & LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) == 0 )
718 {
719 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
720 }
721 base16_stream_index = 0;
722
723 while( base16_stream_index < base16_stream_size )
724 {
725 if( libuna_base16_character_copy_from_base16_stream(
726 &base16_character1,
727 &( base16_stream[ base16_stream_index ] ),
728 base16_variant,
729 error ) != 1 )
730 {
731 libcerror_error_set(
732 error,
733 LIBCERROR_ERROR_DOMAIN_CONVERSION,
734 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
735 "%s: unable to copy base16 character at index: %" PRIzd ".",
736 function,
737 base16_stream_index );
738
739 return( -1 );
740 }
741 base16_stream_index += base16_character_size;
742
743 if( ( base16_character1 == (uint32_t) '\n' )
744 || ( base16_character1 == (uint32_t) '\r' ) )
745 {
746 if( ( strip_mode != LIBUNA_STRIP_MODE_NON_WHITESPACE )
747 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
748 {
749 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
750 }
751 else
752 {
753 /* Handle multi-character end-of-line
754 */
755 if( ( base16_stream_index + base16_character_size ) < base16_stream_size )
756 {
757 if( libuna_base16_character_copy_from_base16_stream(
758 &base16_character2,
759 &( base16_stream[ base16_stream_index + base16_character_size ] ),
760 base16_variant,
761 error ) != 1 )
762 {
763 libcerror_error_set(
764 error,
765 LIBCERROR_ERROR_DOMAIN_CONVERSION,
766 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
767 "%s: unable to copy base16 character at index: %" PRIzd ".",
768 function,
769 base16_stream_index );
770
771 return( -1 );
772 }
773 if( ( base16_character2 == (uint32_t) '\n' )
774 || ( base16_character2 == (uint32_t) '\r' ) )
775 {
776 base16_stream_index += base16_character_size;
777 }
778 }
779 strip_mode = LIBUNA_STRIP_MODE_LEADING_WHITESPACE;
780 }
781 if( character_limit != 0 )
782 {
783 if( number_of_characters != (size_t) character_limit )
784 {
785 libcerror_error_set(
786 error,
787 LIBCERROR_ERROR_DOMAIN_CONVERSION,
788 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
789 "%s: number of characters in line does not match character limit.",
790 function );
791
792 return( -1 );
793 }
794 number_of_characters = 0;
795 }
796 }
797 else if( ( base16_character1 == (uint32_t) ' ' )
798 || ( base16_character1 == (uint32_t) '\t' )
799 || ( base16_character1 == (uint32_t) '\v' ) )
800 {
801 if( ( flags & LIBUNA_BASE16_FLAG_STRIP_WHITESPACE ) != 0 )
802 {
803 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
804 {
805 strip_mode = LIBUNA_STRIP_MODE_TRAILING_WHITESPACE;
806 }
807 if( ( strip_mode != LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
808 && ( strip_mode != LIBUNA_STRIP_MODE_TRAILING_WHITESPACE ) )
809 {
810 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
811 }
812 }
813 else
814 {
815 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
816 }
817 }
818 else if( strip_mode == LIBUNA_STRIP_MODE_LEADING_WHITESPACE )
819 {
820 strip_mode = LIBUNA_STRIP_MODE_NON_WHITESPACE;
821 }
822 else if( strip_mode == LIBUNA_STRIP_MODE_TRAILING_WHITESPACE )
823 {
824 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
825 }
826 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
827 {
828 libcerror_error_set(
829 error,
830 LIBCERROR_ERROR_DOMAIN_CONVERSION,
831 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
832 "%s: invalid character in base16 stream at index: %" PRIzd ".",
833 function,
834 base16_stream_index - base16_character_size );
835
836 return( -1 );
837 }
838 if( strip_mode == LIBUNA_STRIP_MODE_NON_WHITESPACE )
839 {
840 byte_value = 0;
841
842 if( ( base16_character1 >= (uint32_t) 'A' )
843 && ( base16_character1 <= (uint32_t) 'F' ) )
844 {
845 if( ( character_case != LIBUNA_CASE_MIXED )
846 && ( character_case != LIBUNA_CASE_UPPER ) )
847 {
848 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
849 }
850 byte_value = (uint8_t) ( base16_character1 - (uint32_t) 'A' + 10 );
851 }
852 else if( ( base16_character1 >= (uint32_t) 'a' )
853 && ( base16_character1 <= (uint32_t) 'f' ) )
854 {
855 if( ( character_case != LIBUNA_CASE_MIXED )
856 && ( character_case != LIBUNA_CASE_LOWER ) )
857 {
858 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
859 }
860 byte_value = (uint8_t) ( base16_character1 - (uint32_t) 'a' + 10 );
861 }
862 else if( ( base16_character1 >= (uint32_t) '0' )
863 && ( base16_character1 <= (uint32_t) '9' ) )
864 {
865 byte_value = (uint8_t) ( base16_character1 - (uint32_t) '0' );
866 }
867 else
868 {
869 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
870 }
871 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
872 {
873 libcerror_error_set(
874 error,
875 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
876 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
877 "%s: invalid base16 character stream at index: %" PRIzd ".",
878 function,
879 base16_stream_index - base16_character_size );
880
881 return( -1 );
882 }
883 byte_value <<= 4;
884
885 if( libuna_base16_character_copy_from_base16_stream(
886 &base16_character1,
887 &( base16_stream[ base16_stream_index ] ),
888 base16_variant,
889 error ) != 1 )
890 {
891 libcerror_error_set(
892 error,
893 LIBCERROR_ERROR_DOMAIN_CONVERSION,
894 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
895 "%s: unable to copy base16 character at index: %" PRIzd ".",
896 function,
897 base16_stream_index );
898
899 return( -1 );
900 }
901 base16_stream_index += base16_character_size;
902
903 if( ( base16_character1 >= (uint32_t) 'A' )
904 && ( base16_character1 <= (uint32_t) 'F' ) )
905 {
906 if( ( character_case != LIBUNA_CASE_MIXED )
907 && ( character_case != LIBUNA_CASE_UPPER ) )
908 {
909 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
910 }
911 byte_value |= (uint8_t) ( base16_character1 - (uint32_t) 'A' + 10 );
912 }
913 else if( ( base16_character1 >= (uint32_t) 'a' )
914 && ( base16_character1 <= (uint32_t) 'f' ) )
915 {
916 if( ( character_case != LIBUNA_CASE_MIXED )
917 && ( character_case != LIBUNA_CASE_LOWER ) )
918 {
919 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
920 }
921 byte_value |= (uint8_t) ( base16_character1 - (uint32_t) 'a' + 10 );
922 }
923 else if( ( base16_character1 >= (uint32_t) '0' )
924 && ( base16_character1 <= (uint32_t) '9' ) )
925 {
926 byte_value |= (uint8_t) ( base16_character1 - (uint32_t) '0' );
927 }
928 else
929 {
930 strip_mode = LIBUNA_STRIP_MODE_INVALID_CHARACTER;
931 }
932 if( strip_mode == LIBUNA_STRIP_MODE_INVALID_CHARACTER )
933 {
934 libcerror_error_set(
935 error,
936 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
937 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
938 "%s: invalid base16 character stream at index: %" PRIzd ".",
939 function,
940 base16_stream_index - base16_character_size );
941
942 return( -1 );
943 }
944 if( byte_stream_index >= byte_stream_size )
945 {
946 libcerror_error_set(
947 error,
948 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
949 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
950 "%s: byte stream is too small.",
951 function );
952
953 return( -1 );
954 }
955 byte_stream[ byte_stream_index++ ] = byte_value;
956
957 number_of_characters += 2;
958 }
959 }
960 if( character_limit != 0 )
961 {
962 if( number_of_characters > (size_t) character_limit )
963 {
964 libcerror_error_set(
965 error,
966 LIBCERROR_ERROR_DOMAIN_CONVERSION,
967 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
968 "%s: number of characters in last line exceed maximum.",
969 function );
970
971 return( -1 );
972 }
973 }
974 return( 1 );
975 }
976
977 /* Determines the size of a base16 stream from a byte stream
978 * Returns 1 if successful or -1 on error
979 */
libuna_base16_stream_size_from_byte_stream(const uint8_t * byte_stream,size_t byte_stream_size,size_t * base16_stream_size,uint32_t base16_variant,libcerror_error_t ** error)980 int libuna_base16_stream_size_from_byte_stream(
981 const uint8_t *byte_stream,
982 size_t byte_stream_size,
983 size_t *base16_stream_size,
984 uint32_t base16_variant,
985 libcerror_error_t **error )
986 {
987 static char *function = "libuna_base16_stream_size_from_byte_stream";
988 size_t base16_character_size = 0;
989 size_t safe_base16_stream_size = 0;
990 size_t whitespace_size = 0;
991 uint8_t character_limit = 0;
992
993 if( byte_stream == NULL )
994 {
995 libcerror_error_set(
996 error,
997 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
998 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
999 "%s: invalid byte stream.",
1000 function );
1001
1002 return( -1 );
1003 }
1004 if( byte_stream_size > (size_t) SSIZE_MAX )
1005 {
1006 libcerror_error_set(
1007 error,
1008 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1009 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1010 "%s: invalid byte stream size value exceeds maximum.",
1011 function );
1012
1013 return( -1 );
1014 }
1015 if( base16_stream_size == NULL )
1016 {
1017 libcerror_error_set(
1018 error,
1019 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1020 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1021 "%s: invalid base16 stream size.",
1022 function );
1023
1024 return( -1 );
1025 }
1026 switch( base16_variant & 0x000000ffUL )
1027 {
1028 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_NONE:
1029 character_limit = 0;
1030 break;
1031
1032 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_64:
1033 character_limit = 64;
1034 break;
1035
1036 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_76:
1037 character_limit = 76;
1038 break;
1039
1040 default:
1041 libcerror_error_set(
1042 error,
1043 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1044 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1045 "%s: unsupported base16 variant.",
1046 function );
1047
1048 return( -1 );
1049 }
1050 switch( base16_variant & 0x000f0000UL )
1051 {
1052 case LIBUNA_BASE16_VARIANT_CASE_LOWER:
1053 case LIBUNA_BASE16_VARIANT_CASE_MIXED:
1054 case LIBUNA_BASE16_VARIANT_CASE_UPPER:
1055 break;
1056
1057 default:
1058 libcerror_error_set(
1059 error,
1060 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1061 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1062 "%s: unsupported base16 variant.",
1063 function );
1064
1065 return( -1 );
1066 }
1067 switch( base16_variant & 0xf0000000UL )
1068 {
1069 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1070 base16_character_size = 1;
1071 break;
1072
1073 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1074 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1075 base16_character_size = 2;
1076 break;
1077
1078 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1079 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1080 base16_character_size = 4;
1081 break;
1082
1083 default:
1084 libcerror_error_set(
1085 error,
1086 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1087 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1088 "%s: unsupported base16 variant.",
1089 function );
1090
1091 return( -1 );
1092 }
1093 /* The base16 stream contains 2 characters for every byte
1094 */
1095 safe_base16_stream_size = byte_stream_size * 2;
1096
1097 if( character_limit != 0 )
1098 {
1099 whitespace_size = safe_base16_stream_size / character_limit;
1100
1101 if( ( safe_base16_stream_size % character_limit ) != 0 )
1102 {
1103 whitespace_size += 1;
1104 }
1105 safe_base16_stream_size += whitespace_size;
1106 }
1107 *base16_stream_size = safe_base16_stream_size * base16_character_size;
1108
1109 return( 1 );
1110 }
1111
1112 /* Copies a base16 stream from a byte stream
1113 * Returns 1 if successful or -1 on error
1114 */
libuna_base16_stream_copy_from_byte_stream(uint8_t * base16_stream,size_t base16_stream_size,const uint8_t * byte_stream,size_t byte_stream_size,uint32_t base16_variant,libcerror_error_t ** error)1115 int libuna_base16_stream_copy_from_byte_stream(
1116 uint8_t *base16_stream,
1117 size_t base16_stream_size,
1118 const uint8_t *byte_stream,
1119 size_t byte_stream_size,
1120 uint32_t base16_variant,
1121 libcerror_error_t **error )
1122 {
1123 static char *function = "libuna_base16_stream_copy_from_byte_stream";
1124 size_t base16_stream_index = 0;
1125
1126 if( libuna_base16_stream_with_index_copy_from_byte_stream(
1127 base16_stream,
1128 base16_stream_size,
1129 &base16_stream_index,
1130 byte_stream,
1131 byte_stream_size,
1132 base16_variant,
1133 error ) != 1 )
1134 {
1135 libcerror_error_set(
1136 error,
1137 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1138 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1139 "%s: unable to copy base16 stream from byte stream.",
1140 function );
1141
1142 return( -1 );
1143 }
1144 return( 1 );
1145 }
1146
1147 /* Copies a base16 stream from a byte stream
1148 * Returns 1 if successful or -1 on error
1149 */
libuna_base16_stream_with_index_copy_from_byte_stream(uint8_t * base16_stream,size_t base16_stream_size,size_t * base16_stream_index,const uint8_t * byte_stream,size_t byte_stream_size,uint32_t base16_variant,libcerror_error_t ** error)1150 int libuna_base16_stream_with_index_copy_from_byte_stream(
1151 uint8_t *base16_stream,
1152 size_t base16_stream_size,
1153 size_t *base16_stream_index,
1154 const uint8_t *byte_stream,
1155 size_t byte_stream_size,
1156 uint32_t base16_variant,
1157 libcerror_error_t **error )
1158 {
1159 static char *function = "libuna_base16_stream_with_index_copy_from_byte_stream";
1160 size_t base16_character_size = 0;
1161 size_t byte_stream_index = 0;
1162 size_t calculated_base16_stream_size = 0;
1163 size_t number_of_characters = 0;
1164 size_t safe_base16_stream_index = 0;
1165 size_t whitespace_size = 0;
1166 uint32_t a_character_value = 0;
1167 uint32_t base16_character = 0;
1168 uint8_t character_limit = 0;
1169
1170 if( base16_stream == NULL )
1171 {
1172 libcerror_error_set(
1173 error,
1174 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1175 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1176 "%s: invalid base16 stream.",
1177 function );
1178
1179 return( -1 );
1180 }
1181 if( base16_stream_size > (size_t) SSIZE_MAX )
1182 {
1183 libcerror_error_set(
1184 error,
1185 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1186 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1187 "%s: invalid base16 stream size value exceeds maximum.",
1188 function );
1189
1190 return( -1 );
1191 }
1192 if( base16_stream_index == NULL )
1193 {
1194 libcerror_error_set(
1195 error,
1196 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1197 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1198 "%s: invalid base16 stream index.",
1199 function );
1200
1201 return( -1 );
1202 }
1203 if( *base16_stream_index >= base16_stream_size )
1204 {
1205 libcerror_error_set(
1206 error,
1207 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1208 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1209 "%s: base16 stream string too small.",
1210 function );
1211
1212 return( -1 );
1213 }
1214 if( byte_stream == NULL )
1215 {
1216 libcerror_error_set(
1217 error,
1218 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1219 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1220 "%s: invalid byte stream.",
1221 function );
1222
1223 return( -1 );
1224 }
1225 if( byte_stream_size > (size_t) SSIZE_MAX )
1226 {
1227 libcerror_error_set(
1228 error,
1229 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1230 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1231 "%s: invalid byte stream size value exceeds maximum.",
1232 function );
1233
1234 return( -1 );
1235 }
1236 switch( base16_variant & 0x000000ffUL )
1237 {
1238 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_NONE:
1239 character_limit = 0;
1240 break;
1241
1242 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_64:
1243 character_limit = 64;
1244 break;
1245
1246 case LIBUNA_BASE16_VARIANT_CHARACTER_LIMIT_76:
1247 character_limit = 76;
1248 break;
1249
1250 default:
1251 libcerror_error_set(
1252 error,
1253 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1254 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1255 "%s: unsupported base16 variant.",
1256 function );
1257
1258 return( -1 );
1259 }
1260 switch( base16_variant & 0x000f0000UL )
1261 {
1262 case LIBUNA_BASE16_VARIANT_CASE_LOWER:
1263 a_character_value = (uint32_t) 'a' - 10;
1264 break;
1265
1266 case LIBUNA_BASE16_VARIANT_CASE_MIXED:
1267 case LIBUNA_BASE16_VARIANT_CASE_UPPER:
1268 a_character_value = (uint32_t) 'A' - 10;
1269 break;
1270
1271 default:
1272 libcerror_error_set(
1273 error,
1274 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1275 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1276 "%s: unsupported base16 variant.",
1277 function );
1278
1279 return( -1 );
1280 }
1281 switch( base16_variant & 0xf0000000UL )
1282 {
1283 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1284 base16_character_size = 1;
1285 break;
1286
1287 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1288 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1289 base16_character_size = 2;
1290 break;
1291
1292 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1293 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1294 base16_character_size = 4;
1295 break;
1296
1297 default:
1298 libcerror_error_set(
1299 error,
1300 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1301 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1302 "%s: unsupported base16 variant.",
1303 function );
1304
1305 return( -1 );
1306 }
1307 safe_base16_stream_index = *base16_stream_index;
1308
1309 /* Make sure the base16 stream is able to hold
1310 * at least 2 bytes for each byte
1311 */
1312 calculated_base16_stream_size = byte_stream_size * 2;
1313
1314 if( character_limit != 0 )
1315 {
1316 whitespace_size = calculated_base16_stream_size / character_limit;
1317
1318 if( ( calculated_base16_stream_size % character_limit ) != 0 )
1319 {
1320 whitespace_size += 1;
1321 }
1322 calculated_base16_stream_size += whitespace_size;
1323 }
1324 calculated_base16_stream_size *= base16_character_size;
1325
1326 if( base16_stream_size < calculated_base16_stream_size )
1327 {
1328 libcerror_error_set(
1329 error,
1330 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1331 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1332 "%s: base16 stream is too small.",
1333 function );
1334
1335 return( -1 );
1336 }
1337 while( byte_stream_index < byte_stream_size )
1338 {
1339 base16_character = byte_stream[ byte_stream_index ] >> 4;
1340
1341 if( base16_character <= 9 )
1342 {
1343 base16_character += (uint32_t) '0';
1344 }
1345 else
1346 {
1347 base16_character += a_character_value;
1348 }
1349 switch( base16_variant & 0xf0000000UL )
1350 {
1351 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1352 base16_stream[ safe_base16_stream_index ] = (uint8_t) base16_character;
1353 break;
1354
1355 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1356 byte_stream_copy_from_uint16_big_endian(
1357 &( base16_stream[ safe_base16_stream_index ] ),
1358 base16_character );
1359 break;
1360
1361 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1362 byte_stream_copy_from_uint16_little_endian(
1363 &( base16_stream[ safe_base16_stream_index ] ),
1364 base16_character );
1365 break;
1366
1367 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1368 byte_stream_copy_from_uint32_big_endian(
1369 &( base16_stream[ safe_base16_stream_index ] ),
1370 base16_character );
1371 break;
1372
1373 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1374 byte_stream_copy_from_uint32_little_endian(
1375 &( base16_stream[ safe_base16_stream_index ] ),
1376 base16_character );
1377 break;
1378 }
1379 safe_base16_stream_index += base16_character_size;
1380
1381 base16_character = byte_stream[ byte_stream_index ] & 0x0f;
1382
1383 if( base16_character <= 9 )
1384 {
1385 base16_character += (uint32_t) '0';
1386 }
1387 else
1388 {
1389 base16_character += a_character_value;
1390 }
1391 switch( base16_variant & 0xf0000000UL )
1392 {
1393 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1394 base16_stream[ safe_base16_stream_index ] = (uint8_t) base16_character;
1395 break;
1396
1397 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1398 byte_stream_copy_from_uint16_big_endian(
1399 &( base16_stream[ safe_base16_stream_index ] ),
1400 base16_character );
1401 break;
1402
1403 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1404 byte_stream_copy_from_uint16_little_endian(
1405 &( base16_stream[ safe_base16_stream_index ] ),
1406 base16_character );
1407 break;
1408
1409 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1410 byte_stream_copy_from_uint32_big_endian(
1411 &( base16_stream[ safe_base16_stream_index ] ),
1412 base16_character );
1413 break;
1414
1415 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1416 byte_stream_copy_from_uint32_little_endian(
1417 &( base16_stream[ safe_base16_stream_index ] ),
1418 base16_character );
1419 break;
1420 }
1421 safe_base16_stream_index += base16_character_size;
1422
1423 if( character_limit != 0 )
1424 {
1425 number_of_characters += 2;
1426
1427 if( number_of_characters >= (size_t) character_limit )
1428 {
1429 base16_character = (uint32_t) '\n';
1430
1431 switch( base16_variant & 0xf0000000UL )
1432 {
1433 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1434 base16_stream[ safe_base16_stream_index ] = (uint8_t) base16_character;
1435 break;
1436
1437 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1438 byte_stream_copy_from_uint16_big_endian(
1439 &( base16_stream[ safe_base16_stream_index ] ),
1440 base16_character );
1441 break;
1442
1443 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1444 byte_stream_copy_from_uint16_little_endian(
1445 &( base16_stream[ safe_base16_stream_index ] ),
1446 base16_character );
1447 break;
1448
1449 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1450 byte_stream_copy_from_uint32_big_endian(
1451 &( base16_stream[ safe_base16_stream_index ] ),
1452 base16_character );
1453 break;
1454
1455 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1456 byte_stream_copy_from_uint32_little_endian(
1457 &( base16_stream[ safe_base16_stream_index ] ),
1458 base16_character );
1459 break;
1460 }
1461 safe_base16_stream_index += base16_character_size;
1462
1463 number_of_characters = 0;
1464 }
1465 }
1466 byte_stream_index++;
1467 }
1468 if( character_limit != 0 )
1469 {
1470 if( number_of_characters != 0 )
1471 {
1472 base16_character = (uint32_t) '\n';
1473
1474 switch( base16_variant & 0xf0000000UL )
1475 {
1476 case LIBUNA_BASE16_VARIANT_ENCODING_BYTE_STREAM:
1477 base16_stream[ safe_base16_stream_index ] = (uint8_t) base16_character;
1478 break;
1479
1480 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_BIG_ENDIAN:
1481 byte_stream_copy_from_uint16_big_endian(
1482 &( base16_stream[ safe_base16_stream_index ] ),
1483 base16_character );
1484 break;
1485
1486 case LIBUNA_BASE16_VARIANT_ENCODING_UTF16_LITTLE_ENDIAN:
1487 byte_stream_copy_from_uint16_little_endian(
1488 &( base16_stream[ safe_base16_stream_index ] ),
1489 base16_character );
1490 break;
1491
1492 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_BIG_ENDIAN:
1493 byte_stream_copy_from_uint32_big_endian(
1494 &( base16_stream[ safe_base16_stream_index ] ),
1495 base16_character );
1496 break;
1497
1498 case LIBUNA_BASE16_VARIANT_ENCODING_UTF32_LITTLE_ENDIAN:
1499 byte_stream_copy_from_uint32_little_endian(
1500 &( base16_stream[ safe_base16_stream_index ] ),
1501 base16_character );
1502 break;
1503 }
1504 safe_base16_stream_index += base16_character_size;
1505 }
1506 }
1507 *base16_stream_index = safe_base16_stream_index;
1508
1509 return( 1 );
1510 }
1511
1512