Coverage Report

Created: 2024-02-25 07:20

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