Coverage Report

Created: 2024-02-25 07:20

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