Coverage Report

Created: 2023-06-07 06:53

/src/libvhdi/libuna/libuna_utf8_string.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * UTF-8 string functions
3
 *
4
 * Copyright (C) 2008-2022, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <types.h>
24
25
#include "libuna_definitions.h"
26
#include "libuna_libcerror.h"
27
#include "libuna_scsu.h"
28
#include "libuna_types.h"
29
#include "libuna_unicode_character.h"
30
#include "libuna_utf8_string.h"
31
32
/* Determines the size of an UTF-8 string from a byte stream
33
 * Returns 1 if successful or -1 on error
34
 */
35
int libuna_utf8_string_size_from_byte_stream(
36
     const uint8_t *byte_stream,
37
     size_t byte_stream_size,
38
     int codepage,
39
     size_t *utf8_string_size,
40
     libcerror_error_t **error )
41
341
{
42
341
  static char *function                        = "libuna_utf8_string_size_from_byte_stream";
43
341
  size_t byte_stream_index                     = 0;
44
341
  libuna_unicode_character_t unicode_character = 0;
45
46
341
  if( byte_stream == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid byte stream.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
341
  if( byte_stream_size > (size_t) SSIZE_MAX )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
63
0
     "%s: invalid byte stream size value exceeds maximum.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
341
  if( utf8_string_size == NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74
0
     "%s: invalid UTF-8 string size.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
341
  *utf8_string_size = 0;
80
81
341
  if( byte_stream_size == 0 )
82
1
  {
83
1
    return( 1 );
84
1
  }
85
53.4k
  while( byte_stream_index < byte_stream_size )
86
53.1k
  {
87
    /* Convert the byte stream bytes into an Unicode character
88
     */
89
53.1k
    if( libuna_unicode_character_copy_from_byte_stream(
90
53.1k
         &unicode_character,
91
53.1k
         byte_stream,
92
53.1k
         byte_stream_size,
93
53.1k
         &byte_stream_index,
94
53.1k
         codepage,
95
53.1k
         error ) != 1 )
96
0
    {
97
0
      libcerror_error_set(
98
0
       error,
99
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
100
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
101
0
       "%s: unable to copy Unicode character from byte stream.",
102
0
       function );
103
104
0
      return( -1 );
105
0
    }
106
    /* Determine how many UTF-8 character bytes are required
107
     */
108
53.1k
    if( libuna_unicode_character_size_to_utf8(
109
53.1k
         unicode_character,
110
53.1k
         utf8_string_size,
111
53.1k
         error ) != 1 )
112
0
    {
113
0
      libcerror_error_set(
114
0
       error,
115
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
116
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
117
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
118
0
       function );
119
120
0
      return( -1 );
121
0
    }
122
53.1k
    if( unicode_character == 0 )
123
10
    {
124
10
      break;
125
10
    }
126
53.1k
  }
127
  /* Check if the string is terminated with an end-of-string character
128
   */
129
340
  if( unicode_character != 0 )
130
330
  {
131
330
    *utf8_string_size += 1;
132
330
  }
133
340
  return( 1 );
134
340
}
135
136
/* Copies an UTF-8 string from a byte stream
137
 * Returns 1 if successful or -1 on error
138
 */
139
int libuna_utf8_string_copy_from_byte_stream(
140
     libuna_utf8_character_t *utf8_string,
141
     size_t utf8_string_size,
142
     const uint8_t *byte_stream,
143
     size_t byte_stream_size,
144
     int codepage,
145
     libcerror_error_t **error )
146
340
{
147
340
  static char *function    = "libuna_utf8_string_copy_from_byte_stream";
148
340
  size_t utf8_string_index = 0;
149
150
340
  if( libuna_utf8_string_with_index_copy_from_byte_stream(
151
340
       utf8_string,
152
340
       utf8_string_size,
153
340
       &utf8_string_index,
154
340
       byte_stream,
155
340
       byte_stream_size,
156
340
       codepage,
157
340
       error ) != 1 )
158
0
  {
159
0
    libcerror_error_set(
160
0
     error,
161
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
162
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
163
0
     "%s: unable to copy byte stream to UTF-8 string.",
164
0
     function );
165
166
0
    return( -1 );
167
0
  }
168
340
  return( 1 );
169
340
}
170
171
/* Copies an UTF-8 string from a byte stream
172
 * Returns 1 if successful or -1 on error
173
 */
174
int libuna_utf8_string_with_index_copy_from_byte_stream(
175
     libuna_utf8_character_t *utf8_string,
176
     size_t utf8_string_size,
177
     size_t *utf8_string_index,
178
     const uint8_t *byte_stream,
179
     size_t byte_stream_size,
180
     int codepage,
181
     libcerror_error_t **error )
182
340
{
183
340
  static char *function                        = "libuna_utf8_string_with_index_copy_from_byte_stream";
184
340
  size_t byte_stream_index                     = 0;
185
340
  libuna_unicode_character_t unicode_character = 0;
186
187
340
  if( utf8_string == NULL )
188
0
  {
189
0
    libcerror_error_set(
190
0
     error,
191
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
192
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
193
0
     "%s: invalid UTF-8 string.",
194
0
     function );
195
196
0
    return( -1 );
197
0
  }
198
340
  if( utf8_string_size > (size_t) SSIZE_MAX )
199
0
  {
200
0
    libcerror_error_set(
201
0
     error,
202
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
203
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
204
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
205
0
     function );
206
207
0
    return( -1 );
208
0
  }
209
340
  if( utf8_string_index == NULL )
210
0
  {
211
0
    libcerror_error_set(
212
0
     error,
213
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
214
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
215
0
     "%s: invalid UTF-8 string index.",
216
0
     function );
217
218
0
    return( -1 );
219
0
  }
220
340
  if( byte_stream == NULL )
221
0
  {
222
0
    libcerror_error_set(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
225
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
226
0
     "%s: invalid byte stream.",
227
0
     function );
228
229
0
    return( -1 );
230
0
  }
231
340
  if( byte_stream_size > (size_t) SSIZE_MAX )
232
0
  {
233
0
    libcerror_error_set(
234
0
     error,
235
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
236
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
237
0
     "%s: invalid byte stream size value exceeds maximum.",
238
0
     function );
239
240
0
    return( -1 );
241
0
  }
242
340
  if( byte_stream_size == 0 )
243
0
  {
244
0
    libcerror_error_set(
245
0
     error,
246
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
247
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
248
0
     "%s: missing byte stream value.",
249
0
     function );
250
251
0
    return( -1 );
252
0
  }
253
53.4k
  while( byte_stream_index < byte_stream_size )
254
53.1k
  {
255
    /* Convert the byte stream bytes into an Unicode character
256
     */
257
53.1k
    if( libuna_unicode_character_copy_from_byte_stream(
258
53.1k
         &unicode_character,
259
53.1k
         byte_stream,
260
53.1k
         byte_stream_size,
261
53.1k
         &byte_stream_index,
262
53.1k
         codepage,
263
53.1k
         error ) != 1 )
264
0
    {
265
0
      libcerror_error_set(
266
0
       error,
267
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
268
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
269
0
       "%s: unable to copy Unicode character from byte stream.",
270
0
       function );
271
272
0
      return( -1 );
273
0
    }
274
    /* Convert the Unicode character into UTF-8 character bytes
275
     */
276
53.1k
    if( libuna_unicode_character_copy_to_utf8(
277
53.1k
         unicode_character,
278
53.1k
         utf8_string,
279
53.1k
         utf8_string_size,
280
53.1k
         utf8_string_index,
281
53.1k
         error ) != 1 )
282
0
    {
283
0
      libcerror_error_set(
284
0
       error,
285
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
286
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
287
0
       "%s: unable to copy Unicode character to UTF-8.",
288
0
       function );
289
290
0
      return( -1 );
291
0
    }
292
53.1k
    if( unicode_character == 0 )
293
10
    {
294
10
      break;
295
10
    }
296
53.1k
  }
297
  /* Check if the string is terminated with an end-of-string character
298
   */
299
340
  if( unicode_character != 0 )
300
330
  {
301
330
    if( *utf8_string_index >= utf8_string_size )
302
0
    {
303
0
      libcerror_error_set(
304
0
       error,
305
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
307
0
       "%s: UTF-8 string too small.",
308
0
       function );
309
310
0
      return( -1 );
311
0
    }
312
330
    utf8_string[ *utf8_string_index ] = 0;
313
314
330
    *utf8_string_index += 1;
315
330
  }
316
340
  return( 1 );
317
340
}
318
319
/* Compares an UTF-8 string with a byte stream
320
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
321
 */
322
int libuna_utf8_string_compare_with_byte_stream(
323
     const libuna_utf8_character_t *utf8_string,
324
     size_t utf8_string_size,
325
     const uint8_t *byte_stream,
326
     size_t byte_stream_size,
327
     int codepage,
328
     libcerror_error_t **error )
329
4.79k
{
330
4.79k
  static char *function                                    = "libuna_utf8_string_compare_with_byte_stream";
331
4.79k
  size_t byte_stream_index                                 = 0;
332
4.79k
  size_t utf8_string_index                                 = 0;
333
4.79k
  libuna_unicode_character_t utf8_unicode_character        = 0;
334
4.79k
  libuna_unicode_character_t byte_stream_unicode_character = 0;
335
336
4.79k
  if( utf8_string == NULL )
337
0
  {
338
0
    libcerror_error_set(
339
0
     error,
340
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
341
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
342
0
     "%s: invalid UTF-8 string.",
343
0
     function );
344
345
0
    return( -1 );
346
0
  }
347
4.79k
  if( utf8_string_size > (size_t) SSIZE_MAX )
348
0
  {
349
0
    libcerror_error_set(
350
0
     error,
351
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
352
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
353
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
354
0
     function );
355
356
0
    return( -1 );
357
0
  }
358
4.79k
  if( byte_stream == NULL )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
363
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
364
0
     "%s: invalid byte stream.",
365
0
     function );
366
367
0
    return( -1 );
368
0
  }
369
4.79k
  if( byte_stream_size > (size_t) SSIZE_MAX )
370
0
  {
371
0
    libcerror_error_set(
372
0
     error,
373
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
374
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
375
0
     "%s: invalid byte stream size value exceeds maximum.",
376
0
     function );
377
378
0
    return( -1 );
379
0
  }
380
4.79k
  if( byte_stream_size == 0 )
381
0
  {
382
0
    libcerror_error_set(
383
0
     error,
384
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
385
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
386
0
     "%s: missing byte stream value.",
387
0
     function );
388
389
0
    return( -1 );
390
0
  }
391
4.79k
  if( ( utf8_string_size >= 1 )
392
4.79k
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
393
2.47k
  {
394
2.47k
    utf8_string_size -= 1;
395
2.47k
  }
396
  /* Check if the byte stream is terminated with zero bytes
397
   */
398
4.79k
  if( ( byte_stream_size >= 1 )
399
4.79k
   && ( byte_stream[ byte_stream_size - 1 ] == 0 ) )
400
1.37k
  {
401
1.37k
    byte_stream_size -= 1;
402
1.37k
  }
403
8.28k
  while( ( utf8_string_index < utf8_string_size )
404
8.28k
      && ( byte_stream_index < byte_stream_size ) )
405
7.17k
  {
406
    /* Convert the UTF-8 character bytes into an Unicode character
407
     */
408
7.17k
    if( libuna_unicode_character_copy_from_utf8(
409
7.17k
         &utf8_unicode_character,
410
7.17k
         utf8_string,
411
7.17k
         utf8_string_size,
412
7.17k
         &utf8_string_index,
413
7.17k
         error ) != 1 )
414
143
    {
415
143
      libcerror_error_set(
416
143
       error,
417
143
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
418
143
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
419
143
       "%s: unable to copy Unicode character from UTF-8.",
420
143
       function );
421
422
143
      return( -1 );
423
143
    }
424
    /* Convert the byte stream bytes into an Unicode character
425
     */
426
7.03k
    if( libuna_unicode_character_copy_from_byte_stream(
427
7.03k
         &byte_stream_unicode_character,
428
7.03k
         byte_stream,
429
7.03k
         byte_stream_size,
430
7.03k
         &byte_stream_index,
431
7.03k
         codepage,
432
7.03k
         error ) != 1 )
433
0
    {
434
0
      libcerror_error_set(
435
0
       error,
436
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
437
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
438
0
       "%s: unable to copy Unicode character from byte stream.",
439
0
       function );
440
441
0
      return( -1 );
442
0
    }
443
7.03k
    if( utf8_unicode_character < byte_stream_unicode_character )
444
807
    {
445
807
      return( LIBUNA_COMPARE_LESS );
446
807
    }
447
6.22k
    else if( utf8_unicode_character > byte_stream_unicode_character )
448
2.73k
    {
449
2.73k
      return( LIBUNA_COMPARE_GREATER );
450
2.73k
    }
451
7.03k
  }
452
  /* Check if both strings were entirely processed
453
   */
454
1.11k
  if( utf8_string_index < utf8_string_size )
455
612
  {
456
612
    return( LIBUNA_COMPARE_GREATER );
457
612
  }
458
499
  else if( byte_stream_index < byte_stream_size )
459
497
  {
460
497
    return( LIBUNA_COMPARE_LESS );
461
497
  }
462
2
  return( LIBUNA_COMPARE_EQUAL );
463
1.11k
}
464
465
/* Determines the size of an UTF-8 string from an UTF-7 stream
466
 * Returns 1 if successful or -1 on error
467
 */
468
int libuna_utf8_string_size_from_utf7_stream(
469
     const uint8_t *utf7_stream,
470
     size_t utf7_stream_size,
471
     size_t *utf8_string_size,
472
     libcerror_error_t **error )
473
0
{
474
0
  static char *function                        = "libuna_utf8_string_size_from_utf7_stream";
475
0
  size_t utf7_stream_index                     = 0;
476
0
  libuna_unicode_character_t unicode_character = 0;
477
0
  uint32_t utf7_stream_base64_data             = 0;
478
479
0
  if( utf7_stream == NULL )
480
0
  {
481
0
    libcerror_error_set(
482
0
     error,
483
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
484
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
485
0
     "%s: invalid UTF-7 stream.",
486
0
     function );
487
488
0
    return( -1 );
489
0
  }
490
0
  if( utf7_stream_size > (size_t) SSIZE_MAX )
491
0
  {
492
0
    libcerror_error_set(
493
0
     error,
494
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
495
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
496
0
     "%s: invalid UTF-7 stream size value exceeds maximum.",
497
0
     function );
498
499
0
    return( -1 );
500
0
  }
501
0
  if( utf8_string_size == NULL )
502
0
  {
503
0
    libcerror_error_set(
504
0
     error,
505
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
506
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
507
0
     "%s: invalid UTF-8 string size.",
508
0
     function );
509
510
0
    return( -1 );
511
0
  }
512
0
  *utf8_string_size = 0;
513
514
0
  if( utf7_stream_size == 0 )
515
0
  {
516
0
    return( 1 );
517
0
  }
518
0
  while( utf7_stream_index < utf7_stream_size )
519
0
  {
520
    /* Convert the UTF-7 stream bytes into an Unicode character
521
     */
522
0
    if( libuna_unicode_character_copy_from_utf7_stream(
523
0
         &unicode_character,
524
0
         utf7_stream,
525
0
         utf7_stream_size,
526
0
         &utf7_stream_index,
527
0
         &utf7_stream_base64_data,
528
0
         error ) != 1 )
529
0
    {
530
0
      libcerror_error_set(
531
0
       error,
532
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
533
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
534
0
       "%s: unable to copy Unicode character from UTF-7 stream.",
535
0
       function );
536
537
0
      return( -1 );
538
0
    }
539
    /* Determine how many UTF-8 character bytes are required
540
     */
541
0
    if( libuna_unicode_character_size_to_utf8(
542
0
         unicode_character,
543
0
         utf8_string_size,
544
0
         error ) != 1 )
545
0
    {
546
0
      libcerror_error_set(
547
0
       error,
548
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
549
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
550
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
551
0
       function );
552
553
0
      return( -1 );
554
0
    }
555
0
    if( unicode_character == 0 )
556
0
    {
557
0
      break;
558
0
    }
559
0
  }
560
  /* Check if the string is terminated with an end-of-string character
561
   */
562
0
  if( unicode_character != 0 )
563
0
  {
564
0
    *utf8_string_size += 1;
565
0
  }
566
0
  return( 1 );
567
0
}
568
569
/* Copies an UTF-8 string from an UTF-7 stream
570
 * Returns 1 if successful or -1 on error
571
 */
572
int libuna_utf8_string_copy_from_utf7_stream(
573
     libuna_utf8_character_t *utf8_string,
574
     size_t utf8_string_size,
575
     const uint8_t *utf7_stream,
576
     size_t utf7_stream_size,
577
     libcerror_error_t **error )
578
0
{
579
0
  static char *function    = "libuna_utf8_string_copy_from_utf7_stream";
580
0
  size_t utf8_string_index = 0;
581
582
0
  if( libuna_utf8_string_with_index_copy_from_utf7_stream(
583
0
       utf8_string,
584
0
       utf8_string_size,
585
0
       &utf8_string_index,
586
0
       utf7_stream,
587
0
       utf7_stream_size,
588
0
       error ) != 1 )
589
0
  {
590
0
    libcerror_error_set(
591
0
     error,
592
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
593
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
594
0
     "%s: unable to UTF-7 stream to UTF-8 string.",
595
0
     function );
596
597
0
    return( -1 );
598
0
  }
599
0
  return( 1 );
600
0
}
601
602
/* Copies an UTF-8 string from an UTF-7 stream
603
 * Returns 1 if successful or -1 on error
604
 */
605
int libuna_utf8_string_with_index_copy_from_utf7_stream(
606
     libuna_utf8_character_t *utf8_string,
607
     size_t utf8_string_size,
608
     size_t *utf8_string_index,
609
     const uint8_t *utf7_stream,
610
     size_t utf7_stream_size,
611
     libcerror_error_t **error )
612
0
{
613
0
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf7_stream";
614
0
  size_t utf7_stream_index                     = 0;
615
0
  libuna_unicode_character_t unicode_character = 0;
616
0
  uint32_t utf7_stream_base64_data             = 0;
617
618
0
  if( utf8_string == NULL )
619
0
  {
620
0
    libcerror_error_set(
621
0
     error,
622
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
623
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
624
0
     "%s: invalid UTF-8 string.",
625
0
     function );
626
627
0
    return( -1 );
628
0
  }
629
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
630
0
  {
631
0
    libcerror_error_set(
632
0
     error,
633
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
634
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
635
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
636
0
     function );
637
638
0
    return( -1 );
639
0
  }
640
0
  if( utf8_string_index == NULL )
641
0
  {
642
0
    libcerror_error_set(
643
0
     error,
644
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
645
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
646
0
     "%s: invalid UTF-8 string index.",
647
0
     function );
648
649
0
    return( -1 );
650
0
  }
651
0
  if( utf7_stream == NULL )
652
0
  {
653
0
    libcerror_error_set(
654
0
     error,
655
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
656
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
657
0
     "%s: invalid UTF-7 stream.",
658
0
     function );
659
660
0
    return( -1 );
661
0
  }
662
0
  if( utf7_stream_size > (size_t) SSIZE_MAX )
663
0
  {
664
0
    libcerror_error_set(
665
0
     error,
666
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
667
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
668
0
     "%s: invalid UTF-7 stream size value exceeds maximum.",
669
0
     function );
670
671
0
    return( -1 );
672
0
  }
673
0
  if( utf7_stream_size == 0 )
674
0
  {
675
0
    libcerror_error_set(
676
0
     error,
677
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
678
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
679
0
     "%s: missing UTF-7 stream value.",
680
0
     function );
681
682
0
    return( -1 );
683
0
  }
684
0
  while( utf7_stream_index < utf7_stream_size )
685
0
  {
686
    /* Convert the UTF-7 stream bytes into an Unicode character
687
     */
688
0
    if( libuna_unicode_character_copy_from_utf7_stream(
689
0
         &unicode_character,
690
0
         utf7_stream,
691
0
         utf7_stream_size,
692
0
         &utf7_stream_index,
693
0
         &utf7_stream_base64_data,
694
0
         error ) != 1 )
695
0
    {
696
0
      libcerror_error_set(
697
0
       error,
698
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
699
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
700
0
       "%s: unable to copy Unicode character from UTF-7 stream.",
701
0
       function );
702
703
0
      return( -1 );
704
0
    }
705
    /* Convert the Unicode character into UTF-8 character bytes
706
     */
707
0
    if( libuna_unicode_character_copy_to_utf8(
708
0
         unicode_character,
709
0
         utf8_string,
710
0
         utf8_string_size,
711
0
         utf8_string_index,
712
0
         error ) != 1 )
713
0
    {
714
0
      libcerror_error_set(
715
0
       error,
716
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
717
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
718
0
       "%s: unable to copy Unicode character to UTF-8.",
719
0
       function );
720
721
0
      return( -1 );
722
0
    }
723
0
    if( unicode_character == 0 )
724
0
    {
725
0
      break;
726
0
    }
727
0
  }
728
  /* Check if the string is terminated with an end-of-string character
729
   */
730
0
  if( unicode_character != 0 )
731
0
  {
732
0
    if( *utf8_string_index >= utf8_string_size )
733
0
    {
734
0
      libcerror_error_set(
735
0
       error,
736
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
737
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
738
0
       "%s: UTF-8 string too small.",
739
0
       function );
740
741
0
      return( -1 );
742
0
    }
743
0
    utf8_string[ *utf8_string_index ] = 0;
744
745
0
    *utf8_string_index += 1;
746
0
  }
747
0
  return( 1 );
748
0
}
749
750
/* Compares an UTF-8 string with an UTF-7 stream
751
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
752
 */
753
int libuna_utf8_string_compare_with_utf7_stream(
754
     const libuna_utf8_character_t *utf8_string,
755
     size_t utf8_string_size,
756
     const uint8_t *utf7_stream,
757
     size_t utf7_stream_size,
758
     libcerror_error_t **error )
759
0
{
760
0
  static char *function                                    = "libuna_utf8_string_compare_with_utf7_stream";
761
0
  size_t utf7_stream_index                                 = 0;
762
0
  size_t utf8_string_index                                 = 0;
763
0
  libuna_unicode_character_t utf8_unicode_character        = 0;
764
0
  libuna_unicode_character_t utf7_stream_unicode_character = 0;
765
0
  uint32_t utf7_stream_base64_data                         = 0;
766
767
0
  if( utf8_string == NULL )
768
0
  {
769
0
    libcerror_error_set(
770
0
     error,
771
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
772
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
773
0
     "%s: invalid UTF-8 string.",
774
0
     function );
775
776
0
    return( -1 );
777
0
  }
778
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
779
0
  {
780
0
    libcerror_error_set(
781
0
     error,
782
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
783
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
784
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
785
0
     function );
786
787
0
    return( -1 );
788
0
  }
789
0
  if( utf7_stream == NULL )
790
0
  {
791
0
    libcerror_error_set(
792
0
     error,
793
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
794
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
795
0
     "%s: invalid UTF-7 stream.",
796
0
     function );
797
798
0
    return( -1 );
799
0
  }
800
0
  if( utf7_stream_size > (size_t) SSIZE_MAX )
801
0
  {
802
0
    libcerror_error_set(
803
0
     error,
804
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
805
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
806
0
     "%s: invalid UTF-7 stream size value exceeds maximum.",
807
0
     function );
808
809
0
    return( -1 );
810
0
  }
811
0
  if( utf7_stream_size == 0 )
812
0
  {
813
0
    libcerror_error_set(
814
0
     error,
815
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
816
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
817
0
     "%s: missing UTF-7 stream value.",
818
0
     function );
819
820
0
    return( -1 );
821
0
  }
822
0
  if( ( utf8_string_size >= 1 )
823
0
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
824
0
  {
825
0
    utf8_string_size -= 1;
826
0
  }
827
  /* Check if the UTF-7 stream is terminated with zero bytes
828
   */
829
0
  if( ( utf7_stream_size >= 1 )
830
0
   && ( utf7_stream[ utf7_stream_size - 1 ] == 0 ) )
831
0
  {
832
0
    utf7_stream_size -= 1;
833
0
  }
834
0
  while( ( utf8_string_index < utf8_string_size )
835
0
      && ( utf7_stream_index < utf7_stream_size ) )
836
0
  {
837
    /* Convert the UTF-8 character bytes into an Unicode character
838
     */
839
0
    if( libuna_unicode_character_copy_from_utf8(
840
0
         &utf8_unicode_character,
841
0
         utf8_string,
842
0
         utf8_string_size,
843
0
         &utf8_string_index,
844
0
         error ) != 1 )
845
0
    {
846
0
      libcerror_error_set(
847
0
       error,
848
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
849
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
850
0
       "%s: unable to copy Unicode character from UTF-8.",
851
0
       function );
852
853
0
      return( -1 );
854
0
    }
855
    /* Convert the UTF-7 character bytes into an Unicode character
856
     */
857
0
    if( libuna_unicode_character_copy_from_utf7_stream(
858
0
         &utf7_stream_unicode_character,
859
0
         utf7_stream,
860
0
         utf7_stream_size,
861
0
         &utf7_stream_index,
862
0
         &utf7_stream_base64_data,
863
0
                     error ) != 1 )
864
0
    {
865
0
      libcerror_error_set(
866
0
       error,
867
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
868
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
869
0
       "%s: unable to copy Unicode character from UTF-7 stream.",
870
0
       function );
871
872
0
      return( -1 );
873
0
    }
874
0
    if( utf8_unicode_character < utf7_stream_unicode_character )
875
0
    {
876
0
      return( LIBUNA_COMPARE_LESS );
877
0
    }
878
0
    else if( utf8_unicode_character > utf7_stream_unicode_character )
879
0
    {
880
0
      return( LIBUNA_COMPARE_GREATER );
881
0
    }
882
0
  }
883
  /* Check if both strings were entirely processed
884
   */
885
0
  if( utf8_string_index < utf8_string_size )
886
0
  {
887
0
    return( LIBUNA_COMPARE_GREATER );
888
0
  }
889
0
  else if( utf7_stream_index < utf7_stream_size )
890
0
  {
891
0
    return( LIBUNA_COMPARE_LESS );
892
0
  }
893
0
  return( LIBUNA_COMPARE_EQUAL );
894
0
}
895
896
/* Determines the size of an UTF-8 string from an UTF-8 stream
897
 * Returns 1 if successful or -1 on error
898
 */
899
int libuna_utf8_string_size_from_utf8_stream(
900
     const uint8_t *utf8_stream,
901
     size_t utf8_stream_size,
902
     size_t *utf8_string_size,
903
     libcerror_error_t **error )
904
2.79k
{
905
2.79k
  static char *function                        = "libuna_utf8_string_size_from_utf8_stream";
906
2.79k
  size_t utf8_stream_index                     = 0;
907
2.79k
  libuna_unicode_character_t unicode_character = 0;
908
909
2.79k
  if( utf8_stream == NULL )
910
0
  {
911
0
    libcerror_error_set(
912
0
     error,
913
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
914
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
915
0
     "%s: invalid UTF-8 stream.",
916
0
     function );
917
918
0
    return( -1 );
919
0
  }
920
2.79k
  if( utf8_stream_size > (size_t) SSIZE_MAX )
921
0
  {
922
0
    libcerror_error_set(
923
0
     error,
924
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
925
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
926
0
     "%s: invalid UTF-8 stream size value exceeds maximum.",
927
0
     function );
928
929
0
    return( -1 );
930
0
  }
931
2.79k
  if( utf8_string_size == NULL )
932
0
  {
933
0
    libcerror_error_set(
934
0
     error,
935
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
936
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
937
0
     "%s: invalid UTF-8 string size.",
938
0
     function );
939
940
0
    return( -1 );
941
0
  }
942
2.79k
  *utf8_string_size = 0;
943
944
2.79k
  if( utf8_stream_size == 0 )
945
16
  {
946
16
    return( 1 );
947
16
  }
948
  /* Check if UTF-8 stream starts with a byte order mark (BOM)
949
   */
950
2.77k
  if( utf8_stream_size >= 3 )
951
2.63k
  {
952
2.63k
    if( ( utf8_stream[ 0 ] == 0x0ef )
953
2.63k
     && ( utf8_stream[ 1 ] == 0x0bb )
954
2.63k
     && ( utf8_stream[ 2 ] == 0x0bf ) )
955
13
    {
956
13
      utf8_stream_index += 3;
957
13
    }
958
2.63k
  }
959
47.1k
  while( utf8_stream_index < utf8_stream_size )
960
46.8k
  {
961
    /* Convert the UTF-8 stream bytes into an Unicode character
962
     */
963
46.8k
    if( libuna_unicode_character_copy_from_utf8(
964
46.8k
         &unicode_character,
965
46.8k
         utf8_stream,
966
46.8k
         utf8_stream_size,
967
46.8k
         &utf8_stream_index,
968
46.8k
         error ) != 1 )
969
1.66k
    {
970
1.66k
      libcerror_error_set(
971
1.66k
       error,
972
1.66k
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
973
1.66k
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
974
1.66k
       "%s: unable to copy Unicode character from UTF-8 stream.",
975
1.66k
       function );
976
977
1.66k
      return( -1 );
978
1.66k
    }
979
    /* Determine how many UTF-8 character bytes are required
980
     */
981
45.2k
    if( libuna_unicode_character_size_to_utf8(
982
45.2k
         unicode_character,
983
45.2k
         utf8_string_size,
984
45.2k
         error ) != 1 )
985
0
    {
986
0
      libcerror_error_set(
987
0
       error,
988
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
989
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
990
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
991
0
       function );
992
993
0
      return( -1 );
994
0
    }
995
45.2k
    if( unicode_character == 0 )
996
824
    {
997
824
      break;
998
824
    }
999
45.2k
  }
1000
  /* Check if the string is terminated with an end-of-string character
1001
   */
1002
1.10k
  if( unicode_character != 0 )
1003
281
  {
1004
281
    *utf8_string_size += 1;
1005
281
  }
1006
1.10k
  return( 1 );
1007
2.77k
}
1008
1009
/* Copies an UTF-8 string from an UTF-8 stream
1010
 * Returns 1 if successful or -1 on error
1011
 */
1012
int libuna_utf8_string_copy_from_utf8_stream(
1013
     libuna_utf8_character_t *utf8_string,
1014
     size_t utf8_string_size,
1015
     const uint8_t *utf8_stream,
1016
     size_t utf8_stream_size,
1017
     libcerror_error_t **error )
1018
2.79k
{
1019
2.79k
  static char *function    = "libuna_utf8_string_copy_from_utf8_stream";
1020
2.79k
  size_t utf8_string_index = 0;
1021
1022
2.79k
  if( libuna_utf8_string_with_index_copy_from_utf8_stream(
1023
2.79k
       utf8_string,
1024
2.79k
       utf8_string_size,
1025
2.79k
       &utf8_string_index,
1026
2.79k
       utf8_stream,
1027
2.79k
       utf8_stream_size,
1028
2.79k
       error ) != 1 )
1029
1.72k
  {
1030
1.72k
    libcerror_error_set(
1031
1.72k
     error,
1032
1.72k
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1033
1.72k
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1034
1.72k
     "%s: unable to UTF-8 stream to UTF-8 string.",
1035
1.72k
     function );
1036
1037
1.72k
    return( -1 );
1038
1.72k
  }
1039
1.06k
  return( 1 );
1040
2.79k
}
1041
1042
/* Copies an UTF-8 string from an UTF-8 stream
1043
 * Returns 1 if successful or -1 on error
1044
 */
1045
int libuna_utf8_string_with_index_copy_from_utf8_stream(
1046
     libuna_utf8_character_t *utf8_string,
1047
     size_t utf8_string_size,
1048
     size_t *utf8_string_index,
1049
     const uint8_t *utf8_stream,
1050
     size_t utf8_stream_size,
1051
     libcerror_error_t **error )
1052
2.79k
{
1053
2.79k
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf8_stream";
1054
2.79k
  size_t utf8_stream_index                     = 0;
1055
2.79k
  libuna_unicode_character_t unicode_character = 0;
1056
1057
2.79k
  if( utf8_string == NULL )
1058
0
  {
1059
0
    libcerror_error_set(
1060
0
     error,
1061
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1062
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1063
0
     "%s: invalid UTF-8 string.",
1064
0
     function );
1065
1066
0
    return( -1 );
1067
0
  }
1068
2.79k
  if( utf8_string_size > (size_t) SSIZE_MAX )
1069
0
  {
1070
0
    libcerror_error_set(
1071
0
     error,
1072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1073
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1074
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
1075
0
     function );
1076
1077
0
    return( -1 );
1078
0
  }
1079
2.79k
  if( utf8_string_index == NULL )
1080
0
  {
1081
0
    libcerror_error_set(
1082
0
     error,
1083
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1084
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1085
0
     "%s: invalid UTF-8 string index.",
1086
0
     function );
1087
1088
0
    return( -1 );
1089
0
  }
1090
2.79k
  if( utf8_stream == NULL )
1091
0
  {
1092
0
    libcerror_error_set(
1093
0
     error,
1094
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1095
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1096
0
     "%s: invalid UTF-8 stream.",
1097
0
     function );
1098
1099
0
    return( -1 );
1100
0
  }
1101
2.79k
  if( utf8_stream_size > (size_t) SSIZE_MAX )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1106
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1107
0
     "%s: invalid UTF-8 stream size value exceeds maximum.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
2.79k
  if( utf8_stream_size == 0 )
1113
16
  {
1114
16
    libcerror_error_set(
1115
16
     error,
1116
16
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1117
16
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1118
16
     "%s: missing UTF-8 stream value.",
1119
16
     function );
1120
1121
16
    return( -1 );
1122
16
  }
1123
  /* Check if UTF-8 stream starts with a byte order mark (BOM)
1124
   */
1125
2.77k
  if( utf8_stream_size >= 3 )
1126
2.63k
  {
1127
2.63k
    if( ( utf8_stream[ 0 ] == 0x0ef )
1128
2.63k
     && ( utf8_stream[ 1 ] == 0x0bb )
1129
2.63k
     && ( utf8_stream[ 2 ] == 0x0bf ) )
1130
13
    {
1131
13
      utf8_stream_index += 3;
1132
13
    }
1133
2.63k
  }
1134
22.7k
  while( utf8_stream_index < utf8_stream_size )
1135
22.4k
  {
1136
    /* Convert the UTF-8 stream bytes into an Unicode character
1137
     */
1138
22.4k
    if( libuna_unicode_character_copy_from_utf8(
1139
22.4k
         &unicode_character,
1140
22.4k
         utf8_stream,
1141
22.4k
         utf8_stream_size,
1142
22.4k
         &utf8_stream_index,
1143
22.4k
         error ) != 1 )
1144
1.52k
    {
1145
1.52k
      libcerror_error_set(
1146
1.52k
       error,
1147
1.52k
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1148
1.52k
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1149
1.52k
       "%s: unable to copy Unicode character from UTF-8 stream.",
1150
1.52k
       function );
1151
1152
1.52k
      return( -1 );
1153
1.52k
    }
1154
    /* Convert the Unicode character into UTF-8 character bytes
1155
     */
1156
20.9k
    if( libuna_unicode_character_copy_to_utf8(
1157
20.9k
         unicode_character,
1158
20.9k
         utf8_string,
1159
20.9k
         utf8_string_size,
1160
20.9k
         utf8_string_index,
1161
20.9k
         error ) != 1 )
1162
168
    {
1163
168
      libcerror_error_set(
1164
168
       error,
1165
168
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1166
168
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1167
168
       "%s: unable to copy Unicode character to UTF-8.",
1168
168
       function );
1169
1170
168
      return( -1 );
1171
168
    }
1172
20.7k
    if( unicode_character == 0 )
1173
802
    {
1174
802
      break;
1175
802
    }
1176
20.7k
  }
1177
  /* Check if the string is terminated with an end-of-string character
1178
   */
1179
1.07k
  if( unicode_character != 0 )
1180
276
  {
1181
276
    if( *utf8_string_index >= utf8_string_size )
1182
16
    {
1183
16
      libcerror_error_set(
1184
16
       error,
1185
16
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1186
16
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1187
16
       "%s: UTF-8 string too small.",
1188
16
       function );
1189
1190
16
      return( -1 );
1191
16
    }
1192
260
    utf8_string[ *utf8_string_index ] = 0;
1193
1194
260
    *utf8_string_index += 1;
1195
260
  }
1196
1.06k
  return( 1 );
1197
1.07k
}
1198
1199
/* Compares an UTF-8 string with an UTF-8 stream
1200
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
1201
 */
1202
int libuna_utf8_string_compare_with_utf8_stream(
1203
     const libuna_utf8_character_t *utf8_string,
1204
     size_t utf8_string_size,
1205
     const uint8_t *utf8_stream,
1206
     size_t utf8_stream_size,
1207
     libcerror_error_t **error )
1208
21.0k
{
1209
21.0k
  static char *function                                    = "libuna_utf8_string_compare_with_utf8_stream";
1210
21.0k
  size_t utf8_stream_index                                 = 0;
1211
21.0k
  size_t utf8_string_index                                 = 0;
1212
21.0k
  libuna_unicode_character_t utf8_unicode_character        = 0;
1213
21.0k
  libuna_unicode_character_t utf8_stream_unicode_character = 0;
1214
1215
21.0k
  if( utf8_string == NULL )
1216
0
  {
1217
0
    libcerror_error_set(
1218
0
     error,
1219
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1220
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1221
0
     "%s: invalid UTF-8 string.",
1222
0
     function );
1223
1224
0
    return( -1 );
1225
0
  }
1226
21.0k
  if( utf8_string_size > (size_t) SSIZE_MAX )
1227
0
  {
1228
0
    libcerror_error_set(
1229
0
     error,
1230
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1231
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1232
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
1233
0
     function );
1234
1235
0
    return( -1 );
1236
0
  }
1237
21.0k
  if( utf8_stream == NULL )
1238
0
  {
1239
0
    libcerror_error_set(
1240
0
     error,
1241
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1242
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1243
0
     "%s: invalid UTF-8 stream.",
1244
0
     function );
1245
1246
0
    return( -1 );
1247
0
  }
1248
21.0k
  if( utf8_stream_size > (size_t) SSIZE_MAX )
1249
0
  {
1250
0
    libcerror_error_set(
1251
0
     error,
1252
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1253
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1254
0
     "%s: invalid UTF-8 stream size value exceeds maximum.",
1255
0
     function );
1256
1257
0
    return( -1 );
1258
0
  }
1259
21.0k
  if( utf8_stream_size == 0 )
1260
39
  {
1261
39
    libcerror_error_set(
1262
39
     error,
1263
39
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1264
39
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1265
39
     "%s: missing UTF-8 stream value.",
1266
39
     function );
1267
1268
39
    return( -1 );
1269
39
  }
1270
  /* Check if UTF-8 stream starts with a byte order mark (BOM)
1271
   */
1272
21.0k
  if( utf8_stream_size >= 3 )
1273
16.3k
  {
1274
16.3k
    if( ( utf8_stream[ 0 ] == 0x0ef )
1275
16.3k
     && ( utf8_stream[ 1 ] == 0x0bb )
1276
16.3k
     && ( utf8_stream[ 2 ] == 0x0bf ) )
1277
296
    {
1278
296
      utf8_stream_index += 3;
1279
296
    }
1280
16.3k
  }
1281
21.0k
  if( ( utf8_string_size >= 1 )
1282
21.0k
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
1283
3.97k
  {
1284
3.97k
    utf8_string_size -= 1;
1285
3.97k
  }
1286
  /* Check if the UTF-8 stream is terminated with zero bytes
1287
   */
1288
21.0k
  if( ( utf8_stream_size >= 1 )
1289
21.0k
   && ( utf8_stream[ utf8_stream_size - 1 ] == 0 ) )
1290
10.9k
  {
1291
10.9k
    utf8_stream_size -= 1;
1292
10.9k
  }
1293
49.8k
  while( ( utf8_string_index < utf8_string_size )
1294
49.8k
      && ( utf8_stream_index < utf8_stream_size ) )
1295
43.7k
  {
1296
    /* Convert the UTF-8 character bytes into an Unicode character
1297
     */
1298
43.7k
    if( libuna_unicode_character_copy_from_utf8(
1299
43.7k
         &utf8_unicode_character,
1300
43.7k
         utf8_string,
1301
43.7k
         utf8_string_size,
1302
43.7k
         &utf8_string_index,
1303
43.7k
         error ) != 1 )
1304
0
    {
1305
0
      libcerror_error_set(
1306
0
       error,
1307
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1308
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1309
0
       "%s: unable to copy Unicode character from UTF-8.",
1310
0
       function );
1311
1312
0
      return( -1 );
1313
0
    }
1314
    /* Convert the UTF-8 character bytes into an Unicode character
1315
     */
1316
43.7k
    if( libuna_unicode_character_copy_from_utf8(
1317
43.7k
         &utf8_stream_unicode_character,
1318
43.7k
         utf8_stream,
1319
43.7k
         utf8_stream_size,
1320
43.7k
         &utf8_stream_index,
1321
43.7k
                     error ) != 1 )
1322
294
    {
1323
294
      libcerror_error_set(
1324
294
       error,
1325
294
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1326
294
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1327
294
       "%s: unable to copy Unicode character from UTF-8 stream.",
1328
294
       function );
1329
1330
294
      return( -1 );
1331
294
    }
1332
43.4k
    if( utf8_unicode_character < utf8_stream_unicode_character )
1333
6.18k
    {
1334
6.18k
      return( LIBUNA_COMPARE_LESS );
1335
6.18k
    }
1336
37.3k
    else if( utf8_unicode_character > utf8_stream_unicode_character )
1337
8.49k
    {
1338
8.49k
      return( LIBUNA_COMPARE_GREATER );
1339
8.49k
    }
1340
43.4k
  }
1341
  /* Check if both strings were entirely processed
1342
   */
1343
6.07k
  if( utf8_string_index < utf8_string_size )
1344
2.32k
  {
1345
2.32k
    return( LIBUNA_COMPARE_GREATER );
1346
2.32k
  }
1347
3.75k
  else if( utf8_stream_index < utf8_stream_size )
1348
398
  {
1349
398
    return( LIBUNA_COMPARE_LESS );
1350
398
  }
1351
3.35k
  return( LIBUNA_COMPARE_EQUAL );
1352
6.07k
}
1353
1354
/* Determines the size of an UTF-8 string from an UTF-16 string
1355
 * Returns 1 if successful or -1 on error
1356
 */
1357
int libuna_utf8_string_size_from_utf16(
1358
     const libuna_utf16_character_t *utf16_string,
1359
     size_t utf16_string_size,
1360
     size_t *utf8_string_size,
1361
     libcerror_error_t **error )
1362
0
{
1363
0
  static char *function                        = "libuna_utf8_string_size_from_utf16";
1364
0
  size_t utf16_string_index                    = 0;
1365
0
  libuna_unicode_character_t unicode_character = 0;
1366
1367
0
  if( utf16_string == NULL )
1368
0
  {
1369
0
    libcerror_error_set(
1370
0
     error,
1371
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1372
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1373
0
     "%s: invalid UTF-16 string.",
1374
0
     function );
1375
1376
0
    return( -1 );
1377
0
  }
1378
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
1379
0
  {
1380
0
    libcerror_error_set(
1381
0
     error,
1382
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1383
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1384
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
1385
0
     function );
1386
1387
0
    return( -1 );
1388
0
  }
1389
0
  if( utf8_string_size == NULL )
1390
0
  {
1391
0
    libcerror_error_set(
1392
0
     error,
1393
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1394
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1395
0
     "%s: invalid UTF-8 string size.",
1396
0
     function );
1397
1398
0
    return( -1 );
1399
0
  }
1400
0
  *utf8_string_size = 0;
1401
1402
0
  if( utf16_string_size == 0 )
1403
0
  {
1404
0
    return( 1 );
1405
0
  }
1406
0
  while( utf16_string_index < utf16_string_size )
1407
0
  {
1408
    /* Convert the UTF-16 character bytes into an Unicode character
1409
     */
1410
0
    if( libuna_unicode_character_copy_from_utf16(
1411
0
         &unicode_character,
1412
0
         utf16_string,
1413
0
         utf16_string_size,
1414
0
         &utf16_string_index,
1415
0
         error ) != 1 )
1416
0
    {
1417
0
      libcerror_error_set(
1418
0
       error,
1419
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1420
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1421
0
       "%s: unable to copy Unicode character from UTF-16.",
1422
0
       function );
1423
1424
0
      return( -1 );
1425
0
    }
1426
    /* Determine how many UTF-8 character bytes are required
1427
     */
1428
0
    if( libuna_unicode_character_size_to_utf8(
1429
0
         unicode_character,
1430
0
         utf8_string_size,
1431
0
         error ) != 1 )
1432
0
    {
1433
0
      libcerror_error_set(
1434
0
       error,
1435
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1436
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1437
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
1438
0
       function );
1439
1440
0
      return( -1 );
1441
0
    }
1442
0
    if( unicode_character == 0 )
1443
0
    {
1444
0
      break;
1445
0
    }
1446
0
  }
1447
  /* Check if the string is terminated with an end-of-string character
1448
   */
1449
0
  if( unicode_character != 0 )
1450
0
  {
1451
0
    *utf8_string_size += 1;
1452
0
  }
1453
0
  return( 1 );
1454
0
}
1455
1456
/* Copies an UTF-8 string from an UTF-16 string
1457
 * Returns 1 if successful or -1 on error
1458
 */
1459
int libuna_utf8_string_copy_from_utf16(
1460
     libuna_utf8_character_t *utf8_string,
1461
     size_t utf8_string_size,
1462
     const libuna_utf16_character_t *utf16_string,
1463
     size_t utf16_string_size,
1464
     libcerror_error_t **error )
1465
0
{
1466
0
  static char *function    = "libuna_utf8_string_copy_from_utf16";
1467
0
  size_t utf8_string_index = 0;
1468
1469
0
  if( libuna_utf8_string_with_index_copy_from_utf16(
1470
0
       utf8_string,
1471
0
       utf8_string_size,
1472
0
       &utf8_string_index,
1473
0
       utf16_string,
1474
0
       utf16_string_size,
1475
0
       error ) != 1 )
1476
0
  {
1477
0
    libcerror_error_set(
1478
0
     error,
1479
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1481
0
     "%s: unable to copy UTF-16 string to UTF-8 string.",
1482
0
     function );
1483
1484
0
    return( -1 );
1485
0
  }
1486
0
  return( 1 );
1487
0
}
1488
1489
/* Copies an UTF-8 string from an UTF-16 string
1490
 * Returns 1 if successful or -1 on error
1491
 */
1492
int libuna_utf8_string_with_index_copy_from_utf16(
1493
     libuna_utf8_character_t *utf8_string,
1494
     size_t utf8_string_size,
1495
     size_t *utf8_string_index,
1496
     const libuna_utf16_character_t *utf16_string,
1497
     size_t utf16_string_size,
1498
     libcerror_error_t **error )
1499
0
{
1500
0
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf16";
1501
0
  size_t utf16_string_index                    = 0;
1502
0
  libuna_unicode_character_t unicode_character = 0;
1503
1504
0
  if( utf8_string == NULL )
1505
0
  {
1506
0
    libcerror_error_set(
1507
0
     error,
1508
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1509
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1510
0
     "%s: invalid UTF-8 string.",
1511
0
     function );
1512
1513
0
    return( -1 );
1514
0
  }
1515
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
1516
0
  {
1517
0
    libcerror_error_set(
1518
0
     error,
1519
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1520
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1521
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
1522
0
     function );
1523
1524
0
    return( -1 );
1525
0
  }
1526
0
  if( utf8_string_index == NULL )
1527
0
  {
1528
0
    libcerror_error_set(
1529
0
     error,
1530
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1531
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1532
0
     "%s: invalid UTF-8 string index.",
1533
0
     function );
1534
1535
0
    return( -1 );
1536
0
  }
1537
0
  if( utf16_string == NULL )
1538
0
  {
1539
0
    libcerror_error_set(
1540
0
     error,
1541
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1542
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1543
0
     "%s: invalid UTF-16 string.",
1544
0
     function );
1545
1546
0
    return( -1 );
1547
0
  }
1548
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
1549
0
  {
1550
0
    libcerror_error_set(
1551
0
     error,
1552
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1553
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1554
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
1555
0
     function );
1556
1557
0
    return( -1 );
1558
0
  }
1559
0
  if( utf16_string_size == 0 )
1560
0
  {
1561
0
    libcerror_error_set(
1562
0
     error,
1563
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1564
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1565
0
     "%s: missing UTF-16 string value.",
1566
0
     function );
1567
1568
0
    return( -1 );
1569
0
  }
1570
0
  while( utf16_string_index < utf16_string_size )
1571
0
  {
1572
    /* Convert the UTF-16 character bytes into an Unicode character
1573
     */
1574
0
    if( libuna_unicode_character_copy_from_utf16(
1575
0
         &unicode_character,
1576
0
         utf16_string,
1577
0
         utf16_string_size,
1578
0
         &utf16_string_index,
1579
0
         error ) != 1 )
1580
0
    {
1581
0
      libcerror_error_set(
1582
0
       error,
1583
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1584
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1585
0
       "%s: unable to copy Unicode character from UTF-16.",
1586
0
       function );
1587
1588
0
      return( -1 );
1589
0
    }
1590
    /* Convert the Unicode character into UTF-8 character bytes
1591
     */
1592
0
    if( libuna_unicode_character_copy_to_utf8(
1593
0
         unicode_character,
1594
0
         utf8_string,
1595
0
         utf8_string_size,
1596
0
         utf8_string_index,
1597
0
         error ) != 1 )
1598
0
    {
1599
0
      libcerror_error_set(
1600
0
       error,
1601
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1602
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1603
0
       "%s: unable to copy Unicode character to UTF-8.",
1604
0
       function );
1605
1606
0
      return( -1 );
1607
0
    }
1608
0
    if( unicode_character == 0 )
1609
0
    {
1610
0
      break;
1611
0
    }
1612
0
  }
1613
  /* Check if the string is terminated with an end-of-string character
1614
   */
1615
0
  if( unicode_character != 0 )
1616
0
  {
1617
0
    if( *utf8_string_index >= utf8_string_size )
1618
0
    {
1619
0
      libcerror_error_set(
1620
0
       error,
1621
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1622
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1623
0
       "%s: UTF-8 string too small.",
1624
0
       function );
1625
1626
0
      return( -1 );
1627
0
    }
1628
0
    utf8_string[ *utf8_string_index ] = 0;
1629
1630
0
    *utf8_string_index += 1;
1631
0
  }
1632
0
  return( 1 );
1633
0
}
1634
1635
/* Compares an UTF-8 string with an UTF-16 string
1636
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
1637
 */
1638
int libuna_utf8_string_compare_with_utf16(
1639
     const libuna_utf8_character_t *utf8_string,
1640
     size_t utf8_string_size,
1641
     const libuna_utf16_character_t *utf16_string,
1642
     size_t utf16_string_size,
1643
     libcerror_error_t **error )
1644
0
{
1645
0
  static char *function                              = "libuna_utf8_string_compare_with_utf16";
1646
0
  size_t utf16_string_index                          = 0;
1647
0
  size_t utf8_string_index                           = 0;
1648
0
  libuna_unicode_character_t utf8_unicode_character  = 0;
1649
0
  libuna_unicode_character_t utf16_unicode_character = 0;
1650
1651
0
  if( utf8_string == NULL )
1652
0
  {
1653
0
    libcerror_error_set(
1654
0
     error,
1655
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1656
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1657
0
     "%s: invalid UTF-8 string.",
1658
0
     function );
1659
1660
0
    return( -1 );
1661
0
  }
1662
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
1663
0
  {
1664
0
    libcerror_error_set(
1665
0
     error,
1666
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1667
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1668
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
1669
0
     function );
1670
1671
0
    return( -1 );
1672
0
  }
1673
0
  if( utf16_string == NULL )
1674
0
  {
1675
0
    libcerror_error_set(
1676
0
     error,
1677
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1678
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1679
0
     "%s: invalid UTF-16 string.",
1680
0
     function );
1681
1682
0
    return( -1 );
1683
0
  }
1684
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
1685
0
  {
1686
0
    libcerror_error_set(
1687
0
     error,
1688
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1689
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1690
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
1691
0
     function );
1692
1693
0
    return( -1 );
1694
0
  }
1695
0
  if( utf16_string_size == 0 )
1696
0
  {
1697
0
    libcerror_error_set(
1698
0
     error,
1699
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1700
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
1701
0
     "%s: missing UTF-16 string value.",
1702
0
     function );
1703
1704
0
    return( -1 );
1705
0
  }
1706
0
  if( ( utf8_string_size >= 1 )
1707
0
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
1708
0
  {
1709
0
    utf8_string_size -= 1;
1710
0
  }
1711
0
  if( ( utf16_string_size >= 1 )
1712
0
   && ( utf16_string[ utf16_string_size - 1 ] == 0 ) )
1713
0
  {
1714
0
    utf16_string_size -= 1;
1715
0
  }
1716
0
  while( ( utf8_string_index < utf8_string_size )
1717
0
      && ( utf16_string_index < utf16_string_size ) )
1718
0
  {
1719
    /* Convert the UTF-8 character bytes into an Unicode character
1720
     */
1721
0
    if( libuna_unicode_character_copy_from_utf8(
1722
0
         &utf8_unicode_character,
1723
0
         utf8_string,
1724
0
         utf8_string_size,
1725
0
         &utf8_string_index,
1726
0
         error ) != 1 )
1727
0
    {
1728
0
      libcerror_error_set(
1729
0
       error,
1730
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1731
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
1732
0
       "%s: unable to copy Unicode character from UTF-8.",
1733
0
       function );
1734
1735
0
      return( -1 );
1736
0
    }
1737
    /* Convert the UTF-16 character bytes into an Unicode character
1738
     */
1739
0
    if( libuna_unicode_character_copy_from_utf16(
1740
0
         &utf16_unicode_character,
1741
0
         utf16_string,
1742
0
         utf16_string_size,
1743
0
         &utf16_string_index,
1744
0
                     error ) != 1 )
1745
0
    {
1746
0
      libcerror_error_set(
1747
0
       error,
1748
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1749
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1750
0
       "%s: unable to copy Unicode character from UTF-16.",
1751
0
       function );
1752
1753
0
      return( -1 );
1754
0
    }
1755
0
    if( utf8_unicode_character < utf16_unicode_character )
1756
0
    {
1757
0
      return( LIBUNA_COMPARE_LESS );
1758
0
    }
1759
0
    else if( utf8_unicode_character > utf16_unicode_character )
1760
0
    {
1761
0
      return( LIBUNA_COMPARE_GREATER );
1762
0
    }
1763
0
  }
1764
  /* Check if both strings were entirely processed
1765
   */
1766
0
  if( utf8_string_index < utf8_string_size )
1767
0
  {
1768
0
    return( LIBUNA_COMPARE_GREATER );
1769
0
  }
1770
0
  else if( utf16_string_index < utf16_string_size )
1771
0
  {
1772
0
    return( LIBUNA_COMPARE_LESS );
1773
0
  }
1774
0
  return( LIBUNA_COMPARE_EQUAL );
1775
0
}
1776
1777
/* Determines the size of an UTF-8 string from an UTF-16 stream
1778
 * Returns 1 if successful or -1 on error
1779
 */
1780
int libuna_utf8_string_size_from_utf16_stream(
1781
     const uint8_t *utf16_stream,
1782
     size_t utf16_stream_size,
1783
     int byte_order,
1784
     size_t *utf8_string_size,
1785
     libcerror_error_t **error )
1786
105k
{
1787
105k
  static char *function                        = "libuna_utf8_string_size_from_utf16_stream";
1788
105k
  size_t utf16_stream_index                    = 0;
1789
105k
  libuna_unicode_character_t unicode_character = 0;
1790
105k
  int read_byte_order                          = 0;
1791
1792
105k
  if( utf16_stream == NULL )
1793
0
  {
1794
0
    libcerror_error_set(
1795
0
     error,
1796
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1797
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1798
0
     "%s: invalid UTF-16 stream.",
1799
0
     function );
1800
1801
0
    return( -1 );
1802
0
  }
1803
105k
  if( utf16_stream_size > (size_t) SSIZE_MAX )
1804
0
  {
1805
0
    libcerror_error_set(
1806
0
     error,
1807
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1808
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1809
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
1810
0
     function );
1811
1812
0
    return( -1 );
1813
0
  }
1814
105k
  if( ( utf16_stream_size % 2 ) != 0 )
1815
18
  {
1816
18
    libcerror_error_set(
1817
18
     error,
1818
18
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1819
18
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1820
18
     "%s: missing UTF-16 stream value.",
1821
18
     function );
1822
1823
18
    return( -1 );
1824
18
  }
1825
105k
  if( utf8_string_size == NULL )
1826
0
  {
1827
0
    libcerror_error_set(
1828
0
     error,
1829
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1830
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1831
0
     "%s: invalid UTF-8 string size.",
1832
0
     function );
1833
1834
0
    return( -1 );
1835
0
  }
1836
105k
  *utf8_string_size = 0;
1837
1838
105k
  if( utf16_stream_size == 0 )
1839
1
  {
1840
1
    return( 1 );
1841
1
  }
1842
  /* Check if UTF-16 stream is in big or little endian
1843
   */
1844
105k
  if( utf16_stream_size >= 2 )
1845
105k
  {
1846
105k
    if( ( utf16_stream[ 0 ] == 0xfe )
1847
105k
     && ( utf16_stream[ 1 ] == 0xff ) )
1848
755
    {
1849
755
      read_byte_order    = LIBUNA_ENDIAN_BIG;
1850
755
      utf16_stream_index = 2;
1851
755
    }
1852
105k
    else if( ( utf16_stream[ 0 ] == 0xff )
1853
105k
          && ( utf16_stream[ 1 ] == 0xfe ) )
1854
1.63k
    {
1855
1.63k
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
1856
1.63k
      utf16_stream_index = 2;
1857
1.63k
    }
1858
105k
    if( byte_order == 0 )
1859
0
    {
1860
0
      byte_order = read_byte_order;
1861
0
    }
1862
105k
  }
1863
105k
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
1864
105k
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
1865
0
  {
1866
0
    libcerror_error_set(
1867
0
     error,
1868
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1869
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1870
0
     "%s: unsupported byte order.",
1871
0
     function );
1872
1873
0
    return( -1 );
1874
0
  }
1875
3.98M
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
1876
3.89M
  {
1877
    /* Convert the UTF-16 stream bytes into an Unicode character
1878
     */
1879
3.89M
    if( libuna_unicode_character_copy_from_utf16_stream(
1880
3.89M
         &unicode_character,
1881
3.89M
         utf16_stream,
1882
3.89M
         utf16_stream_size,
1883
3.89M
         &utf16_stream_index,
1884
3.89M
         byte_order,
1885
3.89M
         error ) != 1 )
1886
236
    {
1887
236
      libcerror_error_set(
1888
236
       error,
1889
236
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1890
236
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1891
236
       "%s: unable to copy Unicode character from UTF-16 stream.",
1892
236
       function );
1893
1894
236
      return( -1 );
1895
236
    }
1896
    /* Determine how many UTF-8 character bytes are required
1897
     */
1898
3.89M
    if( libuna_unicode_character_size_to_utf8(
1899
3.89M
         unicode_character,
1900
3.89M
         utf8_string_size,
1901
3.89M
         error ) != 1 )
1902
0
    {
1903
0
      libcerror_error_set(
1904
0
       error,
1905
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
1906
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
1907
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
1908
0
       function );
1909
1910
0
      return( -1 );
1911
0
    }
1912
3.89M
    if( unicode_character == 0 )
1913
9.16k
    {
1914
9.16k
      break;
1915
9.16k
    }
1916
3.89M
  }
1917
  /* Check if the string is terminated with an end-of-string character
1918
   */
1919
105k
  if( unicode_character != 0 )
1920
96.2k
  {
1921
96.2k
    *utf8_string_size += 1;
1922
96.2k
  }
1923
105k
  return( 1 );
1924
105k
}
1925
1926
/* Copies an UTF-8 string from an UTF-16 stream
1927
 * Returns 1 if successful or -1 on error
1928
 */
1929
int libuna_utf8_string_copy_from_utf16_stream(
1930
     libuna_utf8_character_t *utf8_string,
1931
     size_t utf8_string_size,
1932
     const uint8_t *utf16_stream,
1933
     size_t utf16_stream_size,
1934
     int byte_order,
1935
     libcerror_error_t **error )
1936
11.4k
{
1937
11.4k
  static char *function    = "libuna_utf8_string_copy_from_utf16_stream";
1938
11.4k
  size_t utf8_string_index = 0;
1939
1940
11.4k
  if( libuna_utf8_string_with_index_copy_from_utf16_stream(
1941
11.4k
       utf8_string,
1942
11.4k
       utf8_string_size,
1943
11.4k
       &utf8_string_index,
1944
11.4k
       utf16_stream,
1945
11.4k
       utf16_stream_size,
1946
11.4k
       byte_order,
1947
11.4k
       error ) != 1 )
1948
0
  {
1949
0
    libcerror_error_set(
1950
0
     error,
1951
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1952
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1953
0
     "%s: unable to copy UTF-16 stream to UTF-8 string.",
1954
0
     function );
1955
1956
0
    return( -1 );
1957
0
  }
1958
11.4k
  return( 1 );
1959
11.4k
}
1960
1961
/* Copies an UTF-8 string from an UTF-16 stream
1962
 * Returns 1 if successful or -1 on error
1963
 */
1964
int libuna_utf8_string_with_index_copy_from_utf16_stream(
1965
     libuna_utf8_character_t *utf8_string,
1966
     size_t utf8_string_size,
1967
     size_t *utf8_string_index,
1968
     const uint8_t *utf16_stream,
1969
     size_t utf16_stream_size,
1970
     int byte_order,
1971
     libcerror_error_t **error )
1972
89.4k
{
1973
89.4k
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf16_stream";
1974
89.4k
  size_t utf16_stream_index                    = 0;
1975
89.4k
  libuna_unicode_character_t unicode_character = 0;
1976
89.4k
  int read_byte_order                          = 0;
1977
1978
89.4k
  if( utf8_string == NULL )
1979
0
  {
1980
0
    libcerror_error_set(
1981
0
     error,
1982
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1983
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1984
0
     "%s: invalid UTF-8 string.",
1985
0
     function );
1986
1987
0
    return( -1 );
1988
0
  }
1989
89.4k
  if( utf8_string_size > (size_t) SSIZE_MAX )
1990
0
  {
1991
0
    libcerror_error_set(
1992
0
     error,
1993
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1994
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1995
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
1996
0
     function );
1997
1998
0
    return( -1 );
1999
0
  }
2000
89.4k
  if( utf8_string_index == NULL )
2001
0
  {
2002
0
    libcerror_error_set(
2003
0
     error,
2004
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2005
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2006
0
     "%s: invalid UTF-8 string index.",
2007
0
     function );
2008
2009
0
    return( -1 );
2010
0
  }
2011
89.4k
  if( utf16_stream == NULL )
2012
0
  {
2013
0
    libcerror_error_set(
2014
0
     error,
2015
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2016
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2017
0
     "%s: invalid UTF-16 stream.",
2018
0
     function );
2019
2020
0
    return( -1 );
2021
0
  }
2022
89.4k
  if( utf16_stream_size > (size_t) SSIZE_MAX )
2023
0
  {
2024
0
    libcerror_error_set(
2025
0
     error,
2026
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2027
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2028
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
2029
0
     function );
2030
2031
0
    return( -1 );
2032
0
  }
2033
89.4k
  if( ( utf16_stream_size == 0 )
2034
89.4k
   || ( ( utf16_stream_size % 2 ) != 0 ) )
2035
0
  {
2036
0
    libcerror_error_set(
2037
0
     error,
2038
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2039
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2040
0
     "%s: missing UTF-16 stream value.",
2041
0
     function );
2042
2043
0
    return( -1 );
2044
0
  }
2045
  /* Check if UTF-16 stream is in big or little endian
2046
   */
2047
89.4k
  if( utf16_stream_size >= 2 )
2048
89.4k
  {
2049
89.4k
    if( ( utf16_stream[ 0 ] == 0xfe )
2050
89.4k
     && ( utf16_stream[ 1 ] == 0xff ) )
2051
377
    {
2052
377
      read_byte_order    = LIBUNA_ENDIAN_BIG;
2053
377
      utf16_stream_index = 2;
2054
377
    }
2055
89.0k
    else if( ( utf16_stream[ 0 ] == 0xff )
2056
89.0k
          && ( utf16_stream[ 1 ] == 0xfe ) )
2057
1.30k
    {
2058
1.30k
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
2059
1.30k
      utf16_stream_index = 2;
2060
1.30k
    }
2061
89.4k
    if( byte_order == 0 )
2062
0
    {
2063
0
      byte_order = read_byte_order;
2064
0
    }
2065
89.4k
  }
2066
89.4k
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
2067
89.4k
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2068
0
  {
2069
0
    libcerror_error_set(
2070
0
     error,
2071
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2072
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2073
0
     "%s: unsupported byte order.",
2074
0
     function );
2075
2076
0
    return( -1 );
2077
0
  }
2078
3.73M
  while( ( utf16_stream_index + 1 ) < utf16_stream_size )
2079
3.65M
  {
2080
    /* Convert the UTF-16 stream bytes into an Unicode character
2081
     */
2082
3.65M
    if( libuna_unicode_character_copy_from_utf16_stream(
2083
3.65M
         &unicode_character,
2084
3.65M
         utf16_stream,
2085
3.65M
         utf16_stream_size,
2086
3.65M
         &utf16_stream_index,
2087
3.65M
         byte_order,
2088
3.65M
         error ) != 1 )
2089
0
    {
2090
0
      libcerror_error_set(
2091
0
       error,
2092
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2093
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2094
0
       "%s: unable to copy Unicode character from UTF-16 stream.",
2095
0
       function );
2096
2097
0
      return( -1 );
2098
0
    }
2099
    /* Convert the Unicode character into UTF-8 character bytes
2100
     */
2101
3.65M
    if( libuna_unicode_character_copy_to_utf8(
2102
3.65M
         unicode_character,
2103
3.65M
         utf8_string,
2104
3.65M
         utf8_string_size,
2105
3.65M
         utf8_string_index,
2106
3.65M
         error ) != 1 )
2107
0
    {
2108
0
      libcerror_error_set(
2109
0
       error,
2110
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2111
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2112
0
       "%s: unable to copy Unicode character to UTF-8.",
2113
0
       function );
2114
2115
0
      return( -1 );
2116
0
    }
2117
3.65M
    if( unicode_character == 0 )
2118
3.73k
    {
2119
3.73k
      break;
2120
3.73k
    }
2121
3.65M
  }
2122
  /* Check if the string is terminated with an end-of-string character
2123
   */
2124
89.4k
  if( unicode_character != 0 )
2125
85.7k
  {
2126
85.7k
    if( *utf8_string_index >= utf8_string_size )
2127
0
    {
2128
0
      libcerror_error_set(
2129
0
       error,
2130
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2131
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2132
0
       "%s: UTF-8 string too small.",
2133
0
       function );
2134
2135
0
      return( -1 );
2136
0
    }
2137
85.7k
    utf8_string[ *utf8_string_index ] = 0;
2138
2139
85.7k
    *utf8_string_index += 1;
2140
85.7k
  }
2141
89.4k
  return( 1 );
2142
89.4k
}
2143
2144
/* Compares an UTF-8 string with an UTF-16 stream
2145
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
2146
 */
2147
int libuna_utf8_string_compare_with_utf16_stream(
2148
     const libuna_utf8_character_t *utf8_string,
2149
     size_t utf8_string_size,
2150
     const uint8_t *utf16_stream,
2151
     size_t utf16_stream_size,
2152
     int byte_order,
2153
     libcerror_error_t **error )
2154
2.53k
{
2155
2.53k
  static char *function                                     = "libuna_utf8_string_compare_with_utf16_stream";
2156
2.53k
  size_t utf16_stream_index                                 = 0;
2157
2.53k
  size_t utf8_string_index                                  = 0;
2158
2.53k
  libuna_unicode_character_t utf8_unicode_character         = 0;
2159
2.53k
  libuna_unicode_character_t utf16_stream_unicode_character = 0;
2160
2.53k
  int read_byte_order                                       = 0;
2161
2162
2.53k
  if( utf8_string == NULL )
2163
0
  {
2164
0
    libcerror_error_set(
2165
0
     error,
2166
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2167
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2168
0
     "%s: invalid UTF-8 string.",
2169
0
     function );
2170
2171
0
    return( -1 );
2172
0
  }
2173
2.53k
  if( utf8_string_size > (size_t) SSIZE_MAX )
2174
0
  {
2175
0
    libcerror_error_set(
2176
0
     error,
2177
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2178
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2179
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2180
0
     function );
2181
2182
0
    return( -1 );
2183
0
  }
2184
2.53k
  if( utf16_stream == NULL )
2185
0
  {
2186
0
    libcerror_error_set(
2187
0
     error,
2188
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2189
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2190
0
     "%s: invalid UTF-16 stream.",
2191
0
     function );
2192
2193
0
    return( -1 );
2194
0
  }
2195
2.53k
  if( utf16_stream_size > (size_t) SSIZE_MAX )
2196
0
  {
2197
0
    libcerror_error_set(
2198
0
     error,
2199
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2200
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2201
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
2202
0
     function );
2203
2204
0
    return( -1 );
2205
0
  }
2206
2.53k
  if( ( utf16_stream_size == 0 )
2207
2.53k
   || ( ( utf16_stream_size % 2 ) != 0 ) )
2208
4
  {
2209
4
    libcerror_error_set(
2210
4
     error,
2211
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2212
4
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2213
4
     "%s: missing UTF-16 stream value.",
2214
4
     function );
2215
2216
4
    return( -1 );
2217
4
  }
2218
  /* Check if UTF-16 stream is in big or little endian
2219
   */
2220
2.53k
  if( utf16_stream_size >= 2 )
2221
2.53k
  {
2222
2.53k
    if( ( utf16_stream[ 0 ] == 0xfe )
2223
2.53k
     && ( utf16_stream[ 1 ] == 0xff ) )
2224
131
    {
2225
131
      read_byte_order    = LIBUNA_ENDIAN_BIG;
2226
131
      utf16_stream_index = 2;
2227
131
    }
2228
2.40k
    else if( ( utf16_stream[ 0 ] == 0xff )
2229
2.40k
          && ( utf16_stream[ 1 ] == 0xfe ) )
2230
129
    {
2231
129
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
2232
129
      utf16_stream_index = 2;
2233
129
    }
2234
2.53k
    if( byte_order == 0 )
2235
0
    {
2236
0
      byte_order = read_byte_order;
2237
0
    }
2238
2.53k
  }
2239
2.53k
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
2240
2.53k
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2241
0
  {
2242
0
    libcerror_error_set(
2243
0
     error,
2244
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2245
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2246
0
     "%s: unsupported byte order.",
2247
0
     function );
2248
2249
0
    return( -1 );
2250
0
  }
2251
2.53k
  if( ( utf8_string_size >= 1 )
2252
2.53k
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
2253
667
  {
2254
667
    utf8_string_size -= 1;
2255
667
  }
2256
  /* Check if the UTF-16 stream is terminated with zero bytes
2257
   */
2258
2.53k
  if( ( utf16_stream_size >= 2 )
2259
2.53k
   && ( utf16_stream[ utf16_stream_size - 2 ] == 0 )
2260
2.53k
   && ( utf16_stream[ utf16_stream_size - 1 ] == 0 ) )
2261
923
  {
2262
923
    utf16_stream_size -= 2;
2263
923
  }
2264
3.26k
  while( ( utf8_string_index < utf8_string_size )
2265
3.26k
      && ( utf16_stream_index < utf16_stream_size ) )
2266
3.08k
  {
2267
    /* Convert the UTF-8 character bytes into an Unicode character
2268
     */
2269
3.08k
    if( libuna_unicode_character_copy_from_utf8(
2270
3.08k
         &utf8_unicode_character,
2271
3.08k
         utf8_string,
2272
3.08k
         utf8_string_size,
2273
3.08k
         &utf8_string_index,
2274
3.08k
         error ) != 1 )
2275
0
    {
2276
0
      libcerror_error_set(
2277
0
       error,
2278
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2279
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2280
0
       "%s: unable to copy Unicode character from UTF-8.",
2281
0
       function );
2282
2283
0
      return( -1 );
2284
0
    }
2285
    /* Convert the UTF-16 stream bytes into an Unicode character
2286
     */
2287
3.08k
    if( libuna_unicode_character_copy_from_utf16_stream(
2288
3.08k
         &utf16_stream_unicode_character,
2289
3.08k
         utf16_stream,
2290
3.08k
         utf16_stream_size,
2291
3.08k
         &utf16_stream_index,
2292
3.08k
         byte_order,
2293
3.08k
                     error ) != 1 )
2294
126
    {
2295
126
      libcerror_error_set(
2296
126
       error,
2297
126
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2298
126
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2299
126
       "%s: unable to copy Unicode character from UTF-16 stream.",
2300
126
       function );
2301
2302
126
      return( -1 );
2303
126
    }
2304
2.95k
    if( utf8_unicode_character < utf16_stream_unicode_character )
2305
1.58k
    {
2306
1.58k
      return( LIBUNA_COMPARE_LESS );
2307
1.58k
    }
2308
1.37k
    else if( utf8_unicode_character > utf16_stream_unicode_character )
2309
642
    {
2310
642
      return( LIBUNA_COMPARE_GREATER );
2311
642
    }
2312
2.95k
  }
2313
  /* Check if both strings were entirely processed
2314
   */
2315
178
  if( utf8_string_index < utf8_string_size )
2316
178
  {
2317
178
    return( LIBUNA_COMPARE_GREATER );
2318
178
  }
2319
0
  else if( utf16_stream_index < utf16_stream_size )
2320
0
  {
2321
0
    return( LIBUNA_COMPARE_LESS );
2322
0
  }
2323
0
  return( LIBUNA_COMPARE_EQUAL );
2324
178
}
2325
2326
/* Determines the size of an UTF-8 string from an UTF-32 string
2327
 * Returns 1 if successful or -1 on error
2328
 */
2329
int libuna_utf8_string_size_from_utf32(
2330
     const libuna_utf32_character_t *utf32_string,
2331
     size_t utf32_string_size,
2332
     size_t *utf8_string_size,
2333
     libcerror_error_t **error )
2334
0
{
2335
0
  static char *function                        = "libuna_utf8_string_size_from_utf32";
2336
0
  size_t utf32_string_index                    = 0;
2337
0
  libuna_unicode_character_t unicode_character = 0;
2338
2339
0
  if( utf32_string == NULL )
2340
0
  {
2341
0
    libcerror_error_set(
2342
0
     error,
2343
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2344
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2345
0
     "%s: invalid UTF-32 string.",
2346
0
     function );
2347
2348
0
    return( -1 );
2349
0
  }
2350
0
  if( utf32_string_size > (size_t) SSIZE_MAX )
2351
0
  {
2352
0
    libcerror_error_set(
2353
0
     error,
2354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2355
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2356
0
     "%s: invalid UTF-32 string size value exceeds maximum.",
2357
0
     function );
2358
2359
0
    return( -1 );
2360
0
  }
2361
0
  if( utf8_string_size == NULL )
2362
0
  {
2363
0
    libcerror_error_set(
2364
0
     error,
2365
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2366
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2367
0
     "%s: invalid UTF-8 string size.",
2368
0
     function );
2369
2370
0
    return( -1 );
2371
0
  }
2372
0
  *utf8_string_size = 0;
2373
2374
0
  if( utf32_string_size == 0 )
2375
0
  {
2376
0
    return( 1 );
2377
0
  }
2378
0
  while( utf32_string_index < utf32_string_size )
2379
0
  {
2380
    /* Convert the UTF-32 character bytes into an Unicode character
2381
     */
2382
0
    if( libuna_unicode_character_copy_from_utf32(
2383
0
         &unicode_character,
2384
0
         utf32_string,
2385
0
         utf32_string_size,
2386
0
         &utf32_string_index,
2387
0
         error ) != 1 )
2388
0
    {
2389
0
      libcerror_error_set(
2390
0
       error,
2391
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2392
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2393
0
       "%s: unable to copy Unicode character from UTF-32.",
2394
0
       function );
2395
2396
0
      return( -1 );
2397
0
    }
2398
    /* Determine how many UTF-8 character bytes are required
2399
     */
2400
0
    if( libuna_unicode_character_size_to_utf8(
2401
0
         unicode_character,
2402
0
         utf8_string_size,
2403
0
         error ) != 1 )
2404
0
    {
2405
0
      libcerror_error_set(
2406
0
       error,
2407
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2408
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2409
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
2410
0
       function );
2411
2412
0
      return( -1 );
2413
0
    }
2414
0
    if( unicode_character == 0 )
2415
0
    {
2416
0
      break;
2417
0
    }
2418
0
  }
2419
  /* Check if the string is terminated with an end-of-string character
2420
   */
2421
0
  if( unicode_character != 0 )
2422
0
  {
2423
0
    *utf8_string_size += 1;
2424
0
  }
2425
0
  return( 1 );
2426
0
}
2427
2428
/* Copies an UTF-8 string from an UTF-32 string
2429
 * Returns 1 if successful or -1 on error
2430
 */
2431
int libuna_utf8_string_copy_from_utf32(
2432
     libuna_utf8_character_t *utf8_string,
2433
     size_t utf8_string_size,
2434
     const libuna_utf32_character_t *utf32_string,
2435
     size_t utf32_string_size,
2436
     libcerror_error_t **error )
2437
0
{
2438
0
  static char *function    = "libuna_utf8_string_copy_from_utf32";
2439
0
  size_t utf8_string_index = 0;
2440
2441
0
  if( libuna_utf8_string_with_index_copy_from_utf32(
2442
0
       utf8_string,
2443
0
       utf8_string_size,
2444
0
       &utf8_string_index,
2445
0
       utf32_string,
2446
0
       utf32_string_size,
2447
0
       error ) != 1 )
2448
0
  {
2449
0
    libcerror_error_set(
2450
0
     error,
2451
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2452
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2453
0
     "%s: unable to copy UTF-32 string to UTF-8 string.",
2454
0
     function );
2455
2456
0
    return( -1 );
2457
0
  }
2458
0
  return( 1 );
2459
0
}
2460
2461
/* Copies an UTF-8 string from an UTF-32 string
2462
 * Returns 1 if successful or -1 on error
2463
 */
2464
int libuna_utf8_string_with_index_copy_from_utf32(
2465
     libuna_utf8_character_t *utf8_string,
2466
     size_t utf8_string_size,
2467
     size_t *utf8_string_index,
2468
     const libuna_utf32_character_t *utf32_string,
2469
     size_t utf32_string_size,
2470
     libcerror_error_t **error )
2471
0
{
2472
0
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf32";
2473
0
  size_t utf32_string_index                    = 0;
2474
0
  libuna_unicode_character_t unicode_character = 0;
2475
2476
0
  if( utf8_string == NULL )
2477
0
  {
2478
0
    libcerror_error_set(
2479
0
     error,
2480
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2481
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2482
0
     "%s: invalid UTF-8 string.",
2483
0
     function );
2484
2485
0
    return( -1 );
2486
0
  }
2487
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
2488
0
  {
2489
0
    libcerror_error_set(
2490
0
     error,
2491
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2492
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2493
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2494
0
     function );
2495
2496
0
    return( -1 );
2497
0
  }
2498
0
  if( utf8_string_index == NULL )
2499
0
  {
2500
0
    libcerror_error_set(
2501
0
     error,
2502
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2503
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2504
0
     "%s: invalid UTF-8 string index.",
2505
0
     function );
2506
2507
0
    return( -1 );
2508
0
  }
2509
0
  if( utf32_string == NULL )
2510
0
  {
2511
0
    libcerror_error_set(
2512
0
     error,
2513
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2514
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2515
0
     "%s: invalid UTF-32 string.",
2516
0
     function );
2517
2518
0
    return( -1 );
2519
0
  }
2520
0
  if( utf32_string_size > (size_t) SSIZE_MAX )
2521
0
  {
2522
0
    libcerror_error_set(
2523
0
     error,
2524
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2525
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2526
0
     "%s: invalid UTF-32 string size value exceeds maximum.",
2527
0
     function );
2528
2529
0
    return( -1 );
2530
0
  }
2531
0
  if( utf32_string_size == 0 )
2532
0
  {
2533
0
    libcerror_error_set(
2534
0
     error,
2535
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2536
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2537
0
     "%s: missing UTF-32 string value.",
2538
0
     function );
2539
2540
0
    return( -1 );
2541
0
  }
2542
0
  while( utf32_string_index < utf32_string_size )
2543
0
  {
2544
    /* Convert the UTF-32 character bytes into an Unicode character
2545
     */
2546
0
    if( libuna_unicode_character_copy_from_utf32(
2547
0
         &unicode_character,
2548
0
         utf32_string,
2549
0
         utf32_string_size,
2550
0
         &utf32_string_index,
2551
0
         error ) != 1 )
2552
0
    {
2553
0
      libcerror_error_set(
2554
0
       error,
2555
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2556
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2557
0
       "%s: unable to copy Unicode character from UTF-32.",
2558
0
       function );
2559
2560
0
      return( -1 );
2561
0
    }
2562
    /* Convert the Unicode character into UTF-8 character bytes
2563
     */
2564
0
    if( libuna_unicode_character_copy_to_utf8(
2565
0
         unicode_character,
2566
0
         utf8_string,
2567
0
         utf8_string_size,
2568
0
         utf8_string_index,
2569
0
         error ) != 1 )
2570
0
    {
2571
0
      libcerror_error_set(
2572
0
       error,
2573
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2574
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2575
0
       "%s: unable to copy Unicode character to UTF-8.",
2576
0
       function );
2577
2578
0
      return( -1 );
2579
0
    }
2580
0
    if( unicode_character == 0 )
2581
0
    {
2582
0
      break;
2583
0
    }
2584
0
  }
2585
  /* Check if the string is terminated with an end-of-string character
2586
   */
2587
0
  if( unicode_character != 0 )
2588
0
  {
2589
0
    if( *utf8_string_index >= utf8_string_size )
2590
0
    {
2591
0
      libcerror_error_set(
2592
0
       error,
2593
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2594
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2595
0
       "%s: UTF-8 string too small.",
2596
0
       function );
2597
2598
0
      return( -1 );
2599
0
    }
2600
0
    utf8_string[ *utf8_string_index ] = 0;
2601
2602
0
    *utf8_string_index += 1;
2603
0
  }
2604
0
  return( 1 );
2605
0
}
2606
2607
/* Compares an UTF-8 string with an UTF-32 string
2608
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
2609
 */
2610
int libuna_utf8_string_compare_with_utf32(
2611
     const libuna_utf8_character_t *utf8_string,
2612
     size_t utf8_string_size,
2613
     const libuna_utf32_character_t *utf32_string,
2614
     size_t utf32_string_size,
2615
     libcerror_error_t **error )
2616
0
{
2617
0
  static char *function                              = "libuna_utf8_string_compare_with_utf32";
2618
0
  size_t utf32_string_index                          = 0;
2619
0
  size_t utf8_string_index                           = 0;
2620
0
  libuna_unicode_character_t utf8_unicode_character  = 0;
2621
0
  libuna_unicode_character_t utf32_unicode_character = 0;
2622
2623
0
  if( utf8_string == NULL )
2624
0
  {
2625
0
    libcerror_error_set(
2626
0
     error,
2627
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2628
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2629
0
     "%s: invalid UTF-8 string.",
2630
0
     function );
2631
2632
0
    return( -1 );
2633
0
  }
2634
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
2635
0
  {
2636
0
    libcerror_error_set(
2637
0
     error,
2638
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2639
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2640
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2641
0
     function );
2642
2643
0
    return( -1 );
2644
0
  }
2645
0
  if( utf32_string == NULL )
2646
0
  {
2647
0
    libcerror_error_set(
2648
0
     error,
2649
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2650
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2651
0
     "%s: invalid UTF-32 string.",
2652
0
     function );
2653
2654
0
    return( -1 );
2655
0
  }
2656
0
  if( utf32_string_size > (size_t) SSIZE_MAX )
2657
0
  {
2658
0
    libcerror_error_set(
2659
0
     error,
2660
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2661
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2662
0
     "%s: invalid UTF-32 string size value exceeds maximum.",
2663
0
     function );
2664
2665
0
    return( -1 );
2666
0
  }
2667
0
  if( utf32_string_size == 0 )
2668
0
  {
2669
0
    libcerror_error_set(
2670
0
     error,
2671
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2672
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
2673
0
     "%s: missing UTF-32 string value.",
2674
0
     function );
2675
2676
0
    return( -1 );
2677
0
  }
2678
0
  if( ( utf8_string_size >= 1 )
2679
0
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
2680
0
  {
2681
0
    utf8_string_size -= 1;
2682
0
  }
2683
0
  if( ( utf32_string_size >= 1 )
2684
0
   && ( utf32_string[ utf32_string_size - 1 ] == 0 ) )
2685
0
  {
2686
0
    utf32_string_size -= 1;
2687
0
  }
2688
0
  while( ( utf8_string_index < utf8_string_size )
2689
0
      && ( utf32_string_index < utf32_string_size ) )
2690
0
  {
2691
    /* Convert the UTF-8 character bytes into an Unicode character
2692
     */
2693
0
    if( libuna_unicode_character_copy_from_utf8(
2694
0
         &utf8_unicode_character,
2695
0
         utf8_string,
2696
0
         utf8_string_size,
2697
0
         &utf8_string_index,
2698
0
         error ) != 1 )
2699
0
    {
2700
0
      libcerror_error_set(
2701
0
       error,
2702
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2703
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
2704
0
       "%s: unable to copy Unicode character from UTF-8.",
2705
0
       function );
2706
2707
0
      return( -1 );
2708
0
    }
2709
    /* Convert the UTF-32 character bytes into an Unicode character
2710
     */
2711
0
    if( libuna_unicode_character_copy_from_utf32(
2712
0
         &utf32_unicode_character,
2713
0
         utf32_string,
2714
0
         utf32_string_size,
2715
0
         &utf32_string_index,
2716
0
                     error ) != 1 )
2717
0
    {
2718
0
      libcerror_error_set(
2719
0
       error,
2720
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2721
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2722
0
       "%s: unable to copy Unicode character from UTF-32.",
2723
0
       function );
2724
2725
0
      return( -1 );
2726
0
    }
2727
0
    if( utf8_unicode_character < utf32_unicode_character )
2728
0
    {
2729
0
      return( LIBUNA_COMPARE_LESS );
2730
0
    }
2731
0
    else if( utf8_unicode_character > utf32_unicode_character )
2732
0
    {
2733
0
      return( LIBUNA_COMPARE_GREATER );
2734
0
    }
2735
0
  }
2736
  /* Check if both strings were entirely processed
2737
   */
2738
0
  if( utf8_string_index < utf8_string_size )
2739
0
  {
2740
0
    return( LIBUNA_COMPARE_GREATER );
2741
0
  }
2742
0
  else if( utf32_string_index < utf32_string_size )
2743
0
  {
2744
0
    return( LIBUNA_COMPARE_LESS );
2745
0
  }
2746
0
  return( LIBUNA_COMPARE_EQUAL );
2747
0
}
2748
2749
/* Determines the size of an UTF-8 string from an UTF-32 stream
2750
 * Returns 1 if successful or -1 on error
2751
 */
2752
int libuna_utf8_string_size_from_utf32_stream(
2753
     const uint8_t *utf32_stream,
2754
     size_t utf32_stream_size,
2755
     int byte_order,
2756
     size_t *utf8_string_size,
2757
     libcerror_error_t **error )
2758
0
{
2759
0
  static char *function                        = "libuna_utf8_string_size_from_utf32_stream";
2760
0
  size_t utf32_stream_index                    = 0;
2761
0
  libuna_unicode_character_t unicode_character = 0;
2762
0
  int read_byte_order                          = 0;
2763
2764
0
  if( utf32_stream == NULL )
2765
0
  {
2766
0
    libcerror_error_set(
2767
0
     error,
2768
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2769
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2770
0
     "%s: invalid UTF-32 stream.",
2771
0
     function );
2772
2773
0
    return( -1 );
2774
0
  }
2775
0
  if( utf32_stream_size > (size_t) SSIZE_MAX )
2776
0
  {
2777
0
    libcerror_error_set(
2778
0
     error,
2779
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2780
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2781
0
     "%s: invalid UTF-32 stream size value exceeds maximum.",
2782
0
     function );
2783
2784
0
    return( -1 );
2785
0
  }
2786
0
  if( ( utf32_stream_size % 4 ) != 0 )
2787
0
  {
2788
0
    libcerror_error_set(
2789
0
     error,
2790
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2791
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2792
0
     "%s: missing UTF-32 stream value.",
2793
0
     function );
2794
2795
0
    return( -1 );
2796
0
  }
2797
0
  if( utf8_string_size == NULL )
2798
0
  {
2799
0
    libcerror_error_set(
2800
0
     error,
2801
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2802
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2803
0
     "%s: invalid UTF-8 string size.",
2804
0
     function );
2805
2806
0
    return( -1 );
2807
0
  }
2808
0
  *utf8_string_size = 0;
2809
2810
0
  if( utf32_stream_size == 0 )
2811
0
  {
2812
0
    return( 1 );
2813
0
  }
2814
  /* Check if UTF-32 stream is in big or little endian
2815
   */
2816
0
  if( utf32_stream_size >= 4 )
2817
0
  {
2818
0
    if( ( utf32_stream[ 0 ] == 0x00 )
2819
0
     && ( utf32_stream[ 1 ] == 0x00 )
2820
0
     && ( utf32_stream[ 2 ] == 0xfe )
2821
0
     && ( utf32_stream[ 3 ] == 0xff ) )
2822
0
    {
2823
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
2824
0
      utf32_stream_index = 4;
2825
0
    }
2826
0
    else if( ( utf32_stream[ 0 ] == 0xff )
2827
0
          && ( utf32_stream[ 1 ] == 0xfe )
2828
0
          && ( utf32_stream[ 2 ] == 0x00 )
2829
0
          && ( utf32_stream[ 3 ] == 0x00 ) )
2830
0
    {
2831
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
2832
0
      utf32_stream_index = 4;
2833
0
    }
2834
0
    if( byte_order == 0 )
2835
0
    {
2836
0
      byte_order = read_byte_order;
2837
0
    }
2838
0
  }
2839
0
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
2840
0
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
2841
0
  {
2842
0
    libcerror_error_set(
2843
0
     error,
2844
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2845
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2846
0
     "%s: unsupported byte order.",
2847
0
     function );
2848
2849
0
    return( -1 );
2850
0
  }
2851
0
  while( ( utf32_stream_index + 3 ) < utf32_stream_size )
2852
0
  {
2853
    /* Convert the UTF-32 stream bytes into an Unicode character
2854
     */
2855
0
    if( libuna_unicode_character_copy_from_utf32_stream(
2856
0
         &unicode_character,
2857
0
         utf32_stream,
2858
0
         utf32_stream_size,
2859
0
         &utf32_stream_index,
2860
0
         byte_order,
2861
0
         error ) != 1 )
2862
0
    {
2863
0
      libcerror_error_set(
2864
0
       error,
2865
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2866
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2867
0
       "%s: unable to copy Unicode character from UTF-32 stream.",
2868
0
       function );
2869
2870
0
      return( -1 );
2871
0
    }
2872
    /* Determine how many UTF-8 character bytes are required
2873
     */
2874
0
    if( libuna_unicode_character_size_to_utf8(
2875
0
         unicode_character,
2876
0
         utf8_string_size,
2877
0
         error ) != 1 )
2878
0
    {
2879
0
      libcerror_error_set(
2880
0
       error,
2881
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
2882
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
2883
0
       "%s: unable to unable to determine size of Unicode character in UTF-8.",
2884
0
       function );
2885
2886
0
      return( -1 );
2887
0
    }
2888
0
    if( unicode_character == 0 )
2889
0
    {
2890
0
      break;
2891
0
    }
2892
0
  }
2893
  /* Check if the string is terminated with an end-of-string character
2894
   */
2895
0
  if( unicode_character != 0 )
2896
0
  {
2897
0
    *utf8_string_size += 1;
2898
0
  }
2899
0
  return( 1 );
2900
0
}
2901
2902
/* Copies an UTF-8 string from an UTF-32 stream
2903
 * Returns 1 if successful or -1 on error
2904
 */
2905
int libuna_utf8_string_copy_from_utf32_stream(
2906
     libuna_utf8_character_t *utf8_string,
2907
     size_t utf8_string_size,
2908
     const uint8_t *utf32_stream,
2909
     size_t utf32_stream_size,
2910
     int byte_order,
2911
     libcerror_error_t **error )
2912
0
{
2913
0
  static char *function    = "libuna_utf8_string_copy_from_utf32_stream";
2914
0
  size_t utf8_string_index = 0;
2915
2916
0
  if( libuna_utf8_string_with_index_copy_from_utf32_stream(
2917
0
       utf8_string,
2918
0
       utf8_string_size,
2919
0
       &utf8_string_index,
2920
0
       utf32_stream,
2921
0
       utf32_stream_size,
2922
0
       byte_order,
2923
0
       error ) != 1 )
2924
0
  {
2925
0
    libcerror_error_set(
2926
0
     error,
2927
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2928
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2929
0
     "%s: unable to copy UTF-32 stream to UTF-8 string.",
2930
0
     function );
2931
2932
0
    return( -1 );
2933
0
  }
2934
0
  return( 1 );
2935
0
}
2936
2937
/* Copies an UTF-8 string from an UTF-32 stream
2938
 * Returns 1 if successful or -1 on error
2939
 */
2940
int libuna_utf8_string_with_index_copy_from_utf32_stream(
2941
     libuna_utf8_character_t *utf8_string,
2942
     size_t utf8_string_size,
2943
     size_t *utf8_string_index,
2944
     const uint8_t *utf32_stream,
2945
     size_t utf32_stream_size,
2946
     int byte_order,
2947
     libcerror_error_t **error )
2948
0
{
2949
0
  static char *function                        = "libuna_utf8_string_with_index_copy_from_utf32_stream";
2950
0
  size_t utf32_stream_index                    = 0;
2951
0
  libuna_unicode_character_t unicode_character = 0;
2952
0
  int read_byte_order                          = 0;
2953
2954
0
  if( utf8_string == NULL )
2955
0
  {
2956
0
    libcerror_error_set(
2957
0
     error,
2958
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2959
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2960
0
     "%s: invalid UTF-8 string.",
2961
0
     function );
2962
2963
0
    return( -1 );
2964
0
  }
2965
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
2966
0
  {
2967
0
    libcerror_error_set(
2968
0
     error,
2969
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2970
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2971
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
2972
0
     function );
2973
2974
0
    return( -1 );
2975
0
  }
2976
0
  if( utf8_string_index == NULL )
2977
0
  {
2978
0
    libcerror_error_set(
2979
0
     error,
2980
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2981
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2982
0
     "%s: invalid UTF-8 string index.",
2983
0
     function );
2984
2985
0
    return( -1 );
2986
0
  }
2987
0
  if( utf32_stream == NULL )
2988
0
  {
2989
0
    libcerror_error_set(
2990
0
     error,
2991
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2992
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2993
0
     "%s: invalid UTF-32 stream.",
2994
0
     function );
2995
2996
0
    return( -1 );
2997
0
  }
2998
0
  if( utf32_stream_size > (size_t) SSIZE_MAX )
2999
0
  {
3000
0
    libcerror_error_set(
3001
0
     error,
3002
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3003
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3004
0
     "%s: invalid UTF-32 stream size value exceeds maximum.",
3005
0
     function );
3006
3007
0
    return( -1 );
3008
0
  }
3009
0
  if( ( utf32_stream_size == 0 )
3010
0
   || ( ( utf32_stream_size % 4 ) != 0 ) )
3011
0
  {
3012
0
    libcerror_error_set(
3013
0
     error,
3014
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3015
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3016
0
     "%s: missing UTF-32 stream value.",
3017
0
     function );
3018
3019
0
    return( -1 );
3020
0
  }
3021
  /* Check if UTF-32 stream is in big or little endian
3022
   */
3023
0
  if( utf32_stream_size >= 4 )
3024
0
  {
3025
0
    if( ( utf32_stream[ 0 ] == 0x00 )
3026
0
     && ( utf32_stream[ 1 ] == 0x00 )
3027
0
     && ( utf32_stream[ 2 ] == 0xfe )
3028
0
     && ( utf32_stream[ 3 ] == 0xff ) )
3029
0
    {
3030
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
3031
0
      utf32_stream_index = 4;
3032
0
    }
3033
0
    else if( ( utf32_stream[ 0 ] == 0xff )
3034
0
          && ( utf32_stream[ 1 ] == 0xfe )
3035
0
          && ( utf32_stream[ 2 ] == 0x00 )
3036
0
          && ( utf32_stream[ 3 ] == 0x00 ) )
3037
0
    {
3038
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
3039
0
      utf32_stream_index = 4;
3040
0
    }
3041
0
    if( byte_order == 0 )
3042
0
    {
3043
0
      byte_order = read_byte_order;
3044
0
    }
3045
0
  }
3046
0
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
3047
0
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
3048
0
  {
3049
0
    libcerror_error_set(
3050
0
     error,
3051
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3052
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3053
0
     "%s: unsupported byte order.",
3054
0
     function );
3055
3056
0
    return( -1 );
3057
0
  }
3058
0
  while( ( utf32_stream_index + 3 ) < utf32_stream_size )
3059
0
  {
3060
    /* Convert the UTF-32 stream bytes into an Unicode character
3061
     */
3062
0
    if( libuna_unicode_character_copy_from_utf32_stream(
3063
0
         &unicode_character,
3064
0
         utf32_stream,
3065
0
         utf32_stream_size,
3066
0
         &utf32_stream_index,
3067
0
         byte_order,
3068
0
         error ) != 1 )
3069
0
    {
3070
0
      libcerror_error_set(
3071
0
       error,
3072
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
3073
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
3074
0
       "%s: unable to copy Unicode character from UTF-32 stream.",
3075
0
       function );
3076
3077
0
      return( -1 );
3078
0
    }
3079
    /* Convert the Unicode character into UTF-8 character bytes
3080
     */
3081
0
    if( libuna_unicode_character_copy_to_utf8(
3082
0
         unicode_character,
3083
0
         utf8_string,
3084
0
         utf8_string_size,
3085
0
         utf8_string_index,
3086
0
         error ) != 1 )
3087
0
    {
3088
0
      libcerror_error_set(
3089
0
       error,
3090
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
3091
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3092
0
       "%s: unable to copy Unicode character to UTF-8.",
3093
0
       function );
3094
3095
0
      return( -1 );
3096
0
    }
3097
0
    if( unicode_character == 0 )
3098
0
    {
3099
0
      break;
3100
0
    }
3101
0
  }
3102
  /* Check if the string is terminated with an end-of-string character
3103
   */
3104
0
  if( unicode_character != 0 )
3105
0
  {
3106
0
    if( *utf8_string_index >= utf8_string_size )
3107
0
    {
3108
0
      libcerror_error_set(
3109
0
       error,
3110
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3111
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3112
0
       "%s: UTF-8 string too small.",
3113
0
       function );
3114
3115
0
      return( -1 );
3116
0
    }
3117
0
    utf8_string[ *utf8_string_index ] = 0;
3118
3119
0
    *utf8_string_index += 1;
3120
0
  }
3121
0
  return( 1 );
3122
0
}
3123
3124
/* Compares an UTF-8 string with an UTF-32 stream
3125
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
3126
 */
3127
int libuna_utf8_string_compare_with_utf32_stream(
3128
     const libuna_utf8_character_t *utf8_string,
3129
     size_t utf8_string_size,
3130
     const uint8_t *utf32_stream,
3131
     size_t utf32_stream_size,
3132
     int byte_order,
3133
     libcerror_error_t **error )
3134
0
{
3135
0
  static char *function                                     = "libuna_utf8_string_compare_with_utf32_stream";
3136
0
  size_t utf32_stream_index                                 = 0;
3137
0
  size_t utf8_string_index                                  = 0;
3138
0
  libuna_unicode_character_t utf8_unicode_character         = 0;
3139
0
  libuna_unicode_character_t utf32_stream_unicode_character = 0;
3140
0
  int read_byte_order                                       = 0;
3141
3142
0
  if( utf8_string == NULL )
3143
0
  {
3144
0
    libcerror_error_set(
3145
0
     error,
3146
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3147
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3148
0
     "%s: invalid UTF-8 string.",
3149
0
     function );
3150
3151
0
    return( -1 );
3152
0
  }
3153
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
3154
0
  {
3155
0
    libcerror_error_set(
3156
0
     error,
3157
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3158
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3159
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
3160
0
     function );
3161
3162
0
    return( -1 );
3163
0
  }
3164
0
  if( utf32_stream == NULL )
3165
0
  {
3166
0
    libcerror_error_set(
3167
0
     error,
3168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3170
0
     "%s: invalid UTF-32 stream.",
3171
0
     function );
3172
3173
0
    return( -1 );
3174
0
  }
3175
0
  if( utf32_stream_size > (size_t) SSIZE_MAX )
3176
0
  {
3177
0
    libcerror_error_set(
3178
0
     error,
3179
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3180
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3181
0
     "%s: invalid UTF-32 stream size value exceeds maximum.",
3182
0
     function );
3183
3184
0
    return( -1 );
3185
0
  }
3186
0
  if( ( utf32_stream_size == 0 )
3187
0
   || ( ( utf32_stream_size % 4 ) != 0 ) )
3188
0
  {
3189
0
    libcerror_error_set(
3190
0
     error,
3191
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3192
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3193
0
     "%s: missing UTF-32 stream value.",
3194
0
     function );
3195
3196
0
    return( -1 );
3197
0
  }
3198
  /* Check if UTF-32 stream is in big or little endian
3199
   */
3200
0
  if( utf32_stream_size >= 4 )
3201
0
  {
3202
0
    if( ( utf32_stream[ 0 ] == 0x00 )
3203
0
     && ( utf32_stream[ 1 ] == 0x00 )
3204
0
     && ( utf32_stream[ 2 ] == 0xfe )
3205
0
     && ( utf32_stream[ 3 ] == 0xff ) )
3206
0
    {
3207
0
      read_byte_order    = LIBUNA_ENDIAN_BIG;
3208
0
      utf32_stream_index = 4;
3209
0
    }
3210
0
    else if( ( utf32_stream[ 0 ] == 0xff )
3211
0
          && ( utf32_stream[ 1 ] == 0xfe )
3212
0
          && ( utf32_stream[ 2 ] == 0x00 )
3213
0
          && ( utf32_stream[ 3 ] == 0x00 ) )
3214
0
    {
3215
0
      read_byte_order    = LIBUNA_ENDIAN_LITTLE;
3216
0
      utf32_stream_index = 4;
3217
0
    }
3218
0
    if( byte_order == 0 )
3219
0
    {
3220
0
      byte_order = read_byte_order;
3221
0
    }
3222
0
  }
3223
0
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
3224
0
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
3225
0
  {
3226
0
    libcerror_error_set(
3227
0
     error,
3228
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3229
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3230
0
     "%s: unsupported byte order.",
3231
0
     function );
3232
3233
0
    return( -1 );
3234
0
  }
3235
0
  if( ( utf8_string_size >= 1 )
3236
0
   && ( utf8_string[ utf8_string_size - 1 ] == 0 ) )
3237
0
  {
3238
0
    utf8_string_size -= 1;
3239
0
  }
3240
  /* Check if the UTF-32 stream is terminated with zero bytes
3241
   */
3242
0
  if( ( utf32_stream_size >= 4 )
3243
0
   && ( utf32_stream[ utf32_stream_size - 4 ] == 0 )
3244
0
   && ( utf32_stream[ utf32_stream_size - 3 ] == 0 )
3245
0
   && ( utf32_stream[ utf32_stream_size - 2 ] == 0 )
3246
0
   && ( utf32_stream[ utf32_stream_size - 1 ] == 0 ) )
3247
0
  {
3248
0
    utf32_stream_size -= 1;
3249
0
  }
3250
0
  while( ( utf8_string_index < utf8_string_size )
3251
0
      && ( utf32_stream_index < utf32_stream_size ) )
3252
0
  {
3253
    /* Convert the UTF-8 character bytes into an Unicode character
3254
     */
3255
0
    if( libuna_unicode_character_copy_from_utf8(
3256
0
         &utf8_unicode_character,
3257
0
         utf8_string,
3258
0
         utf8_string_size,
3259
0
         &utf8_string_index,
3260
0
         error ) != 1 )
3261
0
    {
3262
0
      libcerror_error_set(
3263
0
       error,
3264
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
3265
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3266
0
       "%s: unable to copy Unicode character from UTF-8.",
3267
0
       function );
3268
3269
0
      return( -1 );
3270
0
    }
3271
    /* Convert the UTF-32 stream bytes into an Unicode character
3272
     */
3273
0
    if( libuna_unicode_character_copy_from_utf32_stream(
3274
0
         &utf32_stream_unicode_character,
3275
0
         utf32_stream,
3276
0
         utf32_stream_size,
3277
0
         &utf32_stream_index,
3278
0
         byte_order,
3279
0
                     error ) != 1 )
3280
0
    {
3281
0
      libcerror_error_set(
3282
0
       error,
3283
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
3284
0
       LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
3285
0
       "%s: unable to copy Unicode character from UTF-32 stream.",
3286
0
       function );
3287
3288
0
      return( -1 );
3289
0
    }
3290
0
    if( utf8_unicode_character < utf32_stream_unicode_character )
3291
0
    {
3292
0
      return( LIBUNA_COMPARE_LESS );
3293
0
    }
3294
0
    else if( utf8_unicode_character > utf32_stream_unicode_character )
3295
0
    {
3296
0
      return( LIBUNA_COMPARE_GREATER );
3297
0
    }
3298
0
  }
3299
  /* Check if both strings were entirely processed
3300
   */
3301
0
  if( utf8_string_index < utf8_string_size )
3302
0
  {
3303
0
    return( LIBUNA_COMPARE_GREATER );
3304
0
  }
3305
0
  else if( utf32_stream_index < utf32_stream_size )
3306
0
  {
3307
0
    return( LIBUNA_COMPARE_LESS );
3308
0
  }
3309
0
  return( LIBUNA_COMPARE_EQUAL );
3310
0
}
3311
3312
/* Determines the size of an UTF-8 string from a Standard Compression Scheme for Unicode (SCSU) stream
3313
 * Returns 1 if successful or -1 on error
3314
 */
3315
int libuna_utf8_string_size_from_scsu_stream(
3316
     const uint8_t *scsu_stream,
3317
     size_t scsu_stream_size,
3318
     size_t *utf8_string_size,
3319
     libcerror_error_t **error )
3320
0
{
3321
0
  uint32_t scsu_dynamic_window_positions[ 8 ] = {
3322
0
    0x0080, 0x00c0, 0x0400, 0x0600, 0x0900, 0x3040, 0x30a0, 0xff00 };
3323
3324
0
  static char *function                        = "libuna_utf8_string_size_from_scsu_stream";
3325
0
  libuna_unicode_character_t unicode_character = 0;
3326
0
  size_t scsu_stream_index                     = 0;
3327
0
  uint32_t scsu_window_position                = 0;
3328
0
  uint8_t byte_value1                          = 0;
3329
0
  uint8_t byte_value2                          = 0;
3330
0
  uint8_t byte_value3                          = 0;
3331
0
  uint8_t dynamic_window_position_index        = 0;
3332
0
  uint8_t in_unicode_mode                      = 0;
3333
0
  uint8_t unicode_character_set                = 0;
3334
3335
0
  if( scsu_stream == NULL )
3336
0
  {
3337
0
    libcerror_error_set(
3338
0
     error,
3339
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3340
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3341
0
     "%s: invalid SCSU stream.",
3342
0
     function );
3343
3344
0
    return( -1 );
3345
0
  }
3346
0
  if( scsu_stream_size > (size_t) SSIZE_MAX )
3347
0
  {
3348
0
    libcerror_error_set(
3349
0
     error,
3350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3351
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3352
0
     "%s: invalid SCSU stream size value exceeds maximum.",
3353
0
     function );
3354
3355
0
    return( -1 );
3356
0
  }
3357
0
  if( utf8_string_size == NULL )
3358
0
  {
3359
0
    libcerror_error_set(
3360
0
     error,
3361
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3362
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3363
0
     "%s: invalid UTF-8 string size.",
3364
0
     function );
3365
3366
0
    return( -1 );
3367
0
  }
3368
0
  *utf8_string_size = 0;
3369
3370
0
  if( scsu_stream_size == 0 )
3371
0
  {
3372
0
    return( 1 );
3373
0
  }
3374
0
  while( scsu_stream_index < scsu_stream_size )
3375
0
  {
3376
0
    unicode_character_set = 0;
3377
3378
0
    if( scsu_stream_index >= scsu_stream_size )
3379
0
    {
3380
0
      libcerror_error_set(
3381
0
       error,
3382
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3383
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3384
0
       "%s: SCSU stream too small.",
3385
0
       function );
3386
3387
0
      return( -1 );
3388
0
    }
3389
0
    byte_value1 = scsu_stream[ scsu_stream_index++ ];
3390
3391
0
    if( in_unicode_mode != 0 )
3392
0
    {
3393
0
      if( ( byte_value1 <= 0xdf )
3394
0
       || ( byte_value1 >= 0xf3 ) )
3395
0
      {
3396
0
        if( scsu_stream_index >= scsu_stream_size )
3397
0
        {
3398
0
          libcerror_error_set(
3399
0
           error,
3400
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3401
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3402
0
           "%s: SCSU stream too small.",
3403
0
           function );
3404
3405
0
          return( -1 );
3406
0
        }
3407
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3408
3409
0
        unicode_character   = byte_value1;
3410
0
        unicode_character <<= 8;
3411
0
        unicode_character  |= byte_value2;
3412
3413
0
        unicode_character_set = 1;
3414
0
      }
3415
      /* UCn tags
3416
       */
3417
0
      else if( ( byte_value1 >= 0xe0 )
3418
0
            && ( byte_value1 <= 0xe7 ) )
3419
0
      {
3420
0
        dynamic_window_position_index = byte_value1 - 0xe0;
3421
3422
0
        in_unicode_mode = 0;
3423
0
      }
3424
      /* UDn tags
3425
       */
3426
0
      else if( ( byte_value1 >= 0xe8 )
3427
0
            && ( byte_value1 <= 0xef ) )
3428
0
      {
3429
0
        if( scsu_stream_index >= scsu_stream_size )
3430
0
        {
3431
0
          libcerror_error_set(
3432
0
           error,
3433
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3434
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3435
0
           "%s: SCSU stream too small.",
3436
0
           function );
3437
3438
0
          return( -1 );
3439
0
        }
3440
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3441
3442
0
        dynamic_window_position_index = byte_value1 - 0xe8;
3443
0
        scsu_window_position          = libuna_scsu_window_offset_table[ byte_value2 ];
3444
3445
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3446
3447
0
        in_unicode_mode = 0;
3448
0
      }
3449
      /* UQU tag
3450
       */
3451
0
      else if( byte_value1 == 0xf0 )
3452
0
      {
3453
0
        if( ( scsu_stream_size < 2 )
3454
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3455
0
        {
3456
0
          libcerror_error_set(
3457
0
           error,
3458
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3459
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3460
0
           "%s: SCSU stream too small.",
3461
0
           function );
3462
3463
0
          return( -1 );
3464
0
        }
3465
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3466
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3467
3468
0
        unicode_character   = byte_value2;
3469
0
        unicode_character <<= 8;
3470
0
        unicode_character  |= byte_value3;
3471
3472
0
        unicode_character_set = 1;
3473
0
      }
3474
      /* UDX tag
3475
       */
3476
0
      else if( byte_value1 == 0xf1 )
3477
0
      {
3478
0
        if( ( scsu_stream_size < 2 )
3479
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3480
0
        {
3481
0
          libcerror_error_set(
3482
0
           error,
3483
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3484
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3485
0
           "%s: SCSU stream too small.",
3486
0
           function );
3487
3488
0
          return( -1 );
3489
0
        }
3490
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3491
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3492
3493
0
        dynamic_window_position_index = byte_value2 >> 5;
3494
0
        scsu_window_position          = byte_value2 & 0x1f;
3495
0
        scsu_window_position        <<= 8;
3496
0
        scsu_window_position         |= byte_value3;
3497
0
        scsu_window_position        <<= 7;
3498
0
        scsu_window_position         += 0x00010000UL;
3499
3500
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3501
3502
0
        in_unicode_mode = 0;
3503
0
      }
3504
0
    }
3505
0
    else
3506
0
    {
3507
0
      if( ( byte_value1 == 0x00 )
3508
0
       || ( byte_value1 == 0x09 )
3509
0
       || ( byte_value1 == 0x0a )
3510
0
       || ( byte_value1 == 0x0c )
3511
0
       || ( byte_value1 == 0x0d )
3512
0
       || ( ( byte_value1 >= 0x20 )
3513
0
        &&  ( byte_value1 <= 0x7f ) ) )
3514
0
      {
3515
0
        unicode_character = byte_value1;
3516
3517
0
        unicode_character_set = 1;
3518
0
      }
3519
      /* SQn tags
3520
       */
3521
0
      else if( ( byte_value1 >= 0x01 )
3522
0
            && ( byte_value1 <= 0x08 ) )
3523
0
      {
3524
0
        if( scsu_stream_index >= scsu_stream_size )
3525
0
        {
3526
0
          libcerror_error_set(
3527
0
           error,
3528
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3529
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3530
0
           "%s: SCSU stream too small.",
3531
0
           function );
3532
3533
0
          return( -1 );
3534
0
        }
3535
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3536
3537
0
        unicode_character = byte_value2;
3538
3539
0
        if( byte_value2 < 0x80 )
3540
0
        {
3541
0
          unicode_character += libuna_scsu_static_window_positions[ byte_value1 - 0x01 ];
3542
0
        }
3543
0
        else
3544
0
        {
3545
0
          unicode_character -= 0x80;
3546
0
          unicode_character += scsu_dynamic_window_positions[ byte_value1 - 0x01 ];
3547
0
        }
3548
0
        unicode_character_set = 1;
3549
0
      }
3550
      /* SDX tag
3551
       */
3552
0
      else if( byte_value1 == 0x0b )
3553
0
      {
3554
0
        if( ( scsu_stream_size < 2 )
3555
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3556
0
        {
3557
0
          libcerror_error_set(
3558
0
           error,
3559
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3560
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3561
0
           "%s: SCSU stream too small.",
3562
0
           function );
3563
3564
0
          return( -1 );
3565
0
        }
3566
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3567
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3568
3569
0
        dynamic_window_position_index = byte_value2 >> 5;
3570
0
        scsu_window_position          = byte_value2 & 0x1f;
3571
0
        scsu_window_position        <<= 8;
3572
0
        scsu_window_position         |= byte_value3;
3573
0
        scsu_window_position        <<= 7;
3574
0
        scsu_window_position         += 0x00010000UL;
3575
3576
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3577
0
      }
3578
      /* SQU tag
3579
       */
3580
0
      else if( byte_value1 == 0x0e )
3581
0
      {
3582
0
        if( ( scsu_stream_size < 2 )
3583
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3584
0
        {
3585
0
          libcerror_error_set(
3586
0
           error,
3587
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3588
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3589
0
           "%s: SCSU stream too small.",
3590
0
           function );
3591
3592
0
          return( -1 );
3593
0
        }
3594
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3595
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3596
3597
0
        unicode_character   = byte_value2;
3598
0
        unicode_character <<= 8;
3599
0
        unicode_character  |= byte_value3;
3600
3601
0
        unicode_character_set = 1;
3602
0
      }
3603
      /* SCU tag
3604
       */
3605
0
      else if( byte_value1 == 0x0f )
3606
0
      {
3607
0
        in_unicode_mode = 1;
3608
0
      }
3609
      /* SCn tags
3610
       */
3611
0
      else if( ( byte_value1 >= 0x10 )
3612
0
            && ( byte_value1 <= 0x17 ) )
3613
0
      {
3614
0
        dynamic_window_position_index = byte_value1 - 0x10;
3615
0
      }
3616
      /* SDn tags
3617
       */
3618
0
      else if( ( byte_value1 >= 0x18 )
3619
0
            && ( byte_value1 <= 0x1f ) )
3620
0
      {
3621
0
        if( scsu_stream_index >= scsu_stream_size )
3622
0
        {
3623
0
          libcerror_error_set(
3624
0
           error,
3625
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3626
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3627
0
           "%s: SCSU stream too small.",
3628
0
           function );
3629
3630
0
          return( -1 );
3631
0
        }
3632
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3633
3634
0
        dynamic_window_position_index = byte_value1 - 0x18;
3635
0
        scsu_window_position          = libuna_scsu_window_offset_table[ byte_value2 ];
3636
3637
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3638
0
      }
3639
0
      else if( byte_value1 >= 0x80 )
3640
0
      {
3641
0
        unicode_character  = byte_value1 - 0x80;
3642
0
        unicode_character += scsu_dynamic_window_positions[ dynamic_window_position_index ];
3643
3644
0
        unicode_character_set = 1;
3645
0
      }
3646
0
    }
3647
0
    if( unicode_character_set != 0 )
3648
0
    {
3649
      /* Determine how many UTF-8 character bytes are required
3650
       */
3651
0
      if( libuna_unicode_character_size_to_utf8(
3652
0
           unicode_character,
3653
0
           utf8_string_size,
3654
0
           error ) != 1 )
3655
0
      {
3656
0
        libcerror_error_set(
3657
0
         error,
3658
0
         LIBCERROR_ERROR_DOMAIN_CONVERSION,
3659
0
         LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
3660
0
         "%s: unable to unable to determine size of Unicode character in UTF-8.",
3661
0
         function );
3662
3663
0
        return( -1 );
3664
0
      }
3665
0
      if( unicode_character == 0 )
3666
0
      {
3667
0
        break;
3668
0
      }
3669
0
    }
3670
0
  }
3671
  /* Check if the string is terminated with an end-of-string character
3672
   */
3673
0
  if( unicode_character != 0 )
3674
0
  {
3675
0
    *utf8_string_size += 1;
3676
0
  }
3677
0
  return( 1 );
3678
0
}
3679
3680
/* Copies an UTF-8 string from a Standard Compression Scheme for Unicode (SCSU) stream
3681
 * Returns 1 if successful or -1 on error
3682
 */
3683
int libuna_utf8_string_copy_from_scsu_stream(
3684
     libuna_utf8_character_t *utf8_string,
3685
     size_t utf8_string_size,
3686
     const uint8_t *scsu_stream,
3687
     size_t scsu_stream_size,
3688
     libcerror_error_t **error )
3689
0
{
3690
0
  static char *function    = "libuna_utf8_string_copy_from_scsu_stream";
3691
0
  size_t utf8_string_index = 0;
3692
3693
0
  if( libuna_utf8_string_with_index_copy_from_scsu_stream(
3694
0
       utf8_string,
3695
0
       utf8_string_size,
3696
0
       &utf8_string_index,
3697
0
       scsu_stream,
3698
0
       scsu_stream_size,
3699
0
       error ) != 1 )
3700
0
  {
3701
0
    libcerror_error_set(
3702
0
     error,
3703
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3704
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
3705
0
     "%s: unable to SCSU stream to UTF-8 string.",
3706
0
     function );
3707
3708
0
    return( -1 );
3709
0
  }
3710
0
  return( 1 );
3711
0
}
3712
3713
/* Copies an UTF-8 string from a Standard Compression Scheme for Unicode (SCSU) stream
3714
 * Returns 1 if successful or -1 on error
3715
 */
3716
int libuna_utf8_string_with_index_copy_from_scsu_stream(
3717
     libuna_utf8_character_t *utf8_string,
3718
     size_t utf8_string_size,
3719
     size_t *utf8_string_index,
3720
     const uint8_t *scsu_stream,
3721
     size_t scsu_stream_size,
3722
     libcerror_error_t **error )
3723
0
{
3724
0
  uint32_t scsu_dynamic_window_positions[ 8 ] = {
3725
0
    0x0080, 0x00c0, 0x0400, 0x0600, 0x0900, 0x3040, 0x30a0, 0xff00 };
3726
3727
0
  static char *function                        = "libuna_utf8_string_with_index_copy_from_scsu_stream";
3728
0
  libuna_unicode_character_t unicode_character = 0;
3729
0
  size_t scsu_stream_index                     = 0;
3730
0
  uint32_t scsu_window_position                = 0;
3731
0
  uint8_t byte_value1                          = 0;
3732
0
  uint8_t byte_value2                          = 0;
3733
0
  uint8_t byte_value3                          = 0;
3734
0
  uint8_t dynamic_window_position_index        = 0;
3735
0
  uint8_t in_unicode_mode                      = 0;
3736
0
  uint8_t unicode_character_set                = 0;
3737
3738
0
  if( utf8_string == NULL )
3739
0
  {
3740
0
    libcerror_error_set(
3741
0
     error,
3742
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3743
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3744
0
     "%s: invalid UTF-8 string.",
3745
0
     function );
3746
3747
0
    return( -1 );
3748
0
  }
3749
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
3750
0
  {
3751
0
    libcerror_error_set(
3752
0
     error,
3753
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3754
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3755
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
3756
0
     function );
3757
3758
0
    return( -1 );
3759
0
  }
3760
0
  if( utf8_string_index == NULL )
3761
0
  {
3762
0
    libcerror_error_set(
3763
0
     error,
3764
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3765
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3766
0
     "%s: invalid UTF-8 string index.",
3767
0
     function );
3768
3769
0
    return( -1 );
3770
0
  }
3771
0
  if( scsu_stream == NULL )
3772
0
  {
3773
0
    libcerror_error_set(
3774
0
     error,
3775
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3776
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3777
0
     "%s: invalid SCSU stream.",
3778
0
     function );
3779
3780
0
    return( -1 );
3781
0
  }
3782
0
  if( scsu_stream_size > (size_t) SSIZE_MAX )
3783
0
  {
3784
0
    libcerror_error_set(
3785
0
     error,
3786
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3787
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3788
0
     "%s: invalid SCSU stream size value exceeds maximum.",
3789
0
     function );
3790
3791
0
    return( -1 );
3792
0
  }
3793
0
  if( scsu_stream_size == 0 )
3794
0
  {
3795
0
    libcerror_error_set(
3796
0
     error,
3797
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3798
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
3799
0
     "%s: missing SCSU stream value.",
3800
0
     function );
3801
3802
0
    return( -1 );
3803
0
  }
3804
0
  while( scsu_stream_index < scsu_stream_size )
3805
0
  {
3806
0
    unicode_character_set = 0;
3807
3808
0
    if( scsu_stream_index >= scsu_stream_size )
3809
0
    {
3810
0
      libcerror_error_set(
3811
0
       error,
3812
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3813
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3814
0
       "%s: SCSU stream too small.",
3815
0
       function );
3816
3817
0
      return( -1 );
3818
0
    }
3819
0
    byte_value1 = scsu_stream[ scsu_stream_index++ ];
3820
3821
0
    if( in_unicode_mode != 0 )
3822
0
    {
3823
0
      if( ( byte_value1 <= 0xdf )
3824
0
       || ( byte_value1 >= 0xf3 ) )
3825
0
      {
3826
0
        if( scsu_stream_index >= scsu_stream_size )
3827
0
        {
3828
0
          libcerror_error_set(
3829
0
           error,
3830
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3831
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3832
0
           "%s: SCSU stream too small.",
3833
0
           function );
3834
3835
0
          return( -1 );
3836
0
        }
3837
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3838
3839
0
        unicode_character   = byte_value1;
3840
0
        unicode_character <<= 8;
3841
0
        unicode_character  |= byte_value2;
3842
3843
0
        unicode_character_set = 1;
3844
0
      }
3845
      /* UCn tags
3846
       */
3847
0
      else if( ( byte_value1 >= 0xe0 )
3848
0
            && ( byte_value1 <= 0xe7 ) )
3849
0
      {
3850
0
        dynamic_window_position_index = byte_value1 - 0xe0;
3851
3852
0
        in_unicode_mode = 0;
3853
0
      }
3854
      /* UDn tags
3855
       */
3856
0
      else if( ( byte_value1 >= 0xe8 )
3857
0
            && ( byte_value1 <= 0xef ) )
3858
0
      {
3859
0
        if( scsu_stream_index >= scsu_stream_size )
3860
0
        {
3861
0
          libcerror_error_set(
3862
0
           error,
3863
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3864
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3865
0
           "%s: SCSU stream too small.",
3866
0
           function );
3867
3868
0
          return( -1 );
3869
0
        }
3870
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3871
3872
0
        dynamic_window_position_index = byte_value1 - 0xe8;
3873
0
        scsu_window_position          = libuna_scsu_window_offset_table[ byte_value2 ];
3874
3875
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3876
3877
0
        in_unicode_mode = 0;
3878
0
      }
3879
      /* UQU tag
3880
       */
3881
0
      else if( byte_value1 == 0xf0 )
3882
0
      {
3883
0
        if( ( scsu_stream_size < 2 )
3884
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3885
0
        {
3886
0
          libcerror_error_set(
3887
0
           error,
3888
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3889
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3890
0
           "%s: SCSU stream too small.",
3891
0
           function );
3892
3893
0
          return( -1 );
3894
0
        }
3895
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3896
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3897
3898
0
        unicode_character   = byte_value2;
3899
0
        unicode_character <<= 8;
3900
0
        unicode_character  |= byte_value3;
3901
3902
0
        unicode_character_set = 1;
3903
0
      }
3904
      /* UDX tag
3905
       */
3906
0
      else if( byte_value1 == 0xf1 )
3907
0
      {
3908
0
        if( ( scsu_stream_size < 2 )
3909
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3910
0
        {
3911
0
          libcerror_error_set(
3912
0
           error,
3913
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3914
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3915
0
           "%s: SCSU stream too small.",
3916
0
           function );
3917
3918
0
          return( -1 );
3919
0
        }
3920
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3921
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3922
3923
0
        dynamic_window_position_index = byte_value2 >> 5;
3924
0
        scsu_window_position          = byte_value2 & 0x1f;
3925
0
        scsu_window_position        <<= 8;
3926
0
        scsu_window_position         |= byte_value3;
3927
0
        scsu_window_position        <<= 7;
3928
0
        scsu_window_position         += 0x00010000UL;
3929
3930
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
3931
3932
0
        in_unicode_mode = 0;
3933
0
      }
3934
0
    }
3935
0
    else
3936
0
    {
3937
0
      if( ( byte_value1 == 0x00 )
3938
0
       || ( byte_value1 == 0x09 )
3939
0
       || ( byte_value1 == 0x0a )
3940
0
       || ( byte_value1 == 0x0c )
3941
0
       || ( byte_value1 == 0x0d )
3942
0
       || ( ( byte_value1 >= 0x20 )
3943
0
        &&  ( byte_value1 <= 0x7f ) ) )
3944
0
      {
3945
0
        unicode_character = byte_value1;
3946
3947
0
        unicode_character_set = 1;
3948
0
      }
3949
      /* SQn tags
3950
       */
3951
0
      else if( ( byte_value1 >= 0x01 )
3952
0
            && ( byte_value1 <= 0x08 ) )
3953
0
      {
3954
0
        if( scsu_stream_index >= scsu_stream_size )
3955
0
        {
3956
0
          libcerror_error_set(
3957
0
           error,
3958
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3959
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3960
0
           "%s: SCSU stream too small.",
3961
0
           function );
3962
3963
0
          return( -1 );
3964
0
        }
3965
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3966
3967
0
        unicode_character = byte_value2;
3968
3969
0
        if( byte_value2 < 0x80 )
3970
0
        {
3971
0
          unicode_character += libuna_scsu_static_window_positions[ byte_value1 - 0x01 ];
3972
0
        }
3973
0
        else
3974
0
        {
3975
0
          unicode_character -= 0x80;
3976
0
          unicode_character += scsu_dynamic_window_positions[ byte_value1 - 0x01 ];
3977
0
        }
3978
0
        unicode_character_set = 1;
3979
0
      }
3980
      /* SDX tag
3981
       */
3982
0
      else if( byte_value1 == 0x0b )
3983
0
      {
3984
0
        if( ( scsu_stream_size < 2 )
3985
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
3986
0
        {
3987
0
          libcerror_error_set(
3988
0
           error,
3989
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3990
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3991
0
           "%s: SCSU stream too small.",
3992
0
           function );
3993
3994
0
          return( -1 );
3995
0
        }
3996
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
3997
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
3998
3999
0
        dynamic_window_position_index = byte_value2 >> 5;
4000
0
        scsu_window_position          = byte_value2 & 0x1f;
4001
0
        scsu_window_position        <<= 8;
4002
0
        scsu_window_position         |= byte_value3;
4003
0
        scsu_window_position        <<= 7;
4004
0
        scsu_window_position         += 0x00010000UL;
4005
4006
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
4007
0
      }
4008
      /* SQU tag
4009
       */
4010
0
      else if( byte_value1 == 0x0e )
4011
0
      {
4012
0
        if( ( scsu_stream_size < 2 )
4013
0
         || ( scsu_stream_index > ( scsu_stream_size - 2 ) ) )
4014
0
        {
4015
0
          libcerror_error_set(
4016
0
           error,
4017
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4018
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4019
0
           "%s: SCSU stream too small.",
4020
0
           function );
4021
4022
0
          return( -1 );
4023
0
        }
4024
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
4025
0
        byte_value3 = scsu_stream[ scsu_stream_index++ ];
4026
4027
0
        unicode_character   = byte_value2;
4028
0
        unicode_character <<= 8;
4029
0
        unicode_character  |= byte_value3;
4030
4031
0
        unicode_character_set = 1;
4032
0
      }
4033
      /* SCU tag
4034
       */
4035
0
      else if( byte_value1 == 0x0f )
4036
0
      {
4037
0
        in_unicode_mode = 1;
4038
0
      }
4039
      /* SCn tags
4040
       */
4041
0
      else if( ( byte_value1 >= 0x10 )
4042
0
            && ( byte_value1 <= 0x17 ) )
4043
0
      {
4044
0
        dynamic_window_position_index = byte_value1 - 0x10;
4045
0
      }
4046
      /* SDn tags
4047
       */
4048
0
      else if( ( byte_value1 >= 0x18 )
4049
0
            && ( byte_value1 <= 0x1f ) )
4050
0
      {
4051
0
        if( scsu_stream_index >= scsu_stream_size )
4052
0
        {
4053
0
          libcerror_error_set(
4054
0
           error,
4055
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4056
0
           LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4057
0
           "%s: SCSU stream too small.",
4058
0
           function );
4059
4060
0
          return( -1 );
4061
0
        }
4062
0
        byte_value2 = scsu_stream[ scsu_stream_index++ ];
4063
4064
0
        dynamic_window_position_index = byte_value1 - 0x18;
4065
0
        scsu_window_position          = libuna_scsu_window_offset_table[ byte_value2 ];
4066
4067
0
        scsu_dynamic_window_positions[ dynamic_window_position_index ] = scsu_window_position;
4068
0
      }
4069
0
      else if( byte_value1 >= 0x80 )
4070
0
      {
4071
0
        unicode_character  = byte_value1 - 0x80;
4072
0
        unicode_character += scsu_dynamic_window_positions[ dynamic_window_position_index ];
4073
4074
0
        unicode_character_set = 1;
4075
0
      }
4076
0
    }
4077
0
    if( unicode_character_set != 0 )
4078
0
    {
4079
      /* Convert the Unicode character into UTF-8 character bytes
4080
       */
4081
0
      if( libuna_unicode_character_copy_to_utf8(
4082
0
           unicode_character,
4083
0
           utf8_string,
4084
0
           utf8_string_size,
4085
0
           utf8_string_index,
4086
0
           error ) != 1 )
4087
0
      {
4088
0
        libcerror_error_set(
4089
0
         error,
4090
0
         LIBCERROR_ERROR_DOMAIN_CONVERSION,
4091
0
         LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
4092
0
         "%s: unable to copy Unicode character to UTF-8.",
4093
0
         function );
4094
4095
0
        return( -1 );
4096
0
      }
4097
0
      if( unicode_character == 0 )
4098
0
      {
4099
0
        break;
4100
0
      }
4101
0
    }
4102
0
  }
4103
  /* Check if the string is terminated with an end-of-string character
4104
   */
4105
0
  if( unicode_character != 0 )
4106
0
  {
4107
0
    if( *utf8_string_index >= utf8_string_size )
4108
0
    {
4109
0
      libcerror_error_set(
4110
0
       error,
4111
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4112
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4113
0
       "%s: UTF-8 string too small.",
4114
0
       function );
4115
4116
0
      return( -1 );
4117
0
    }
4118
0
    utf8_string[ *utf8_string_index ] = 0;
4119
4120
0
    *utf8_string_index += 1;
4121
0
  }
4122
0
  return( 1 );
4123
0
}
4124