Coverage Report

Created: 2026-07-25 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libesedb/libuna/libuna_unicode_character.c
Line
Count
Source
1
/*
2
 * Unicode character functions
3
 *
4
 * Copyright (C) 2008-2026, 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_base64_stream.h"
26
#include "libuna_codepage_iso_8859_2.h"
27
#include "libuna_codepage_iso_8859_3.h"
28
#include "libuna_codepage_iso_8859_4.h"
29
#include "libuna_codepage_iso_8859_5.h"
30
#include "libuna_codepage_iso_8859_6.h"
31
#include "libuna_codepage_iso_8859_7.h"
32
#include "libuna_codepage_iso_8859_8.h"
33
#include "libuna_codepage_iso_8859_9.h"
34
#include "libuna_codepage_iso_8859_10.h"
35
#include "libuna_codepage_iso_8859_13.h"
36
#include "libuna_codepage_iso_8859_14.h"
37
#include "libuna_codepage_iso_8859_15.h"
38
#include "libuna_codepage_iso_8859_16.h"
39
#include "libuna_codepage_koi8_r.h"
40
#include "libuna_codepage_koi8_u.h"
41
#include "libuna_codepage_mac_arabic.h"
42
#include "libuna_codepage_mac_celtic.h"
43
#include "libuna_codepage_mac_centraleurroman.h"
44
#include "libuna_codepage_mac_croatian.h"
45
#include "libuna_codepage_mac_cyrillic.h"
46
#include "libuna_codepage_mac_dingbats.h"
47
#include "libuna_codepage_mac_farsi.h"
48
#include "libuna_codepage_mac_gaelic.h"
49
#include "libuna_codepage_mac_greek.h"
50
#include "libuna_codepage_mac_icelandic.h"
51
#include "libuna_codepage_mac_inuit.h"
52
#include "libuna_codepage_mac_roman.h"
53
#include "libuna_codepage_mac_romanian.h"
54
#include "libuna_codepage_mac_russian.h"
55
#include "libuna_codepage_mac_symbol.h"
56
#include "libuna_codepage_mac_thai.h"
57
#include "libuna_codepage_mac_turkish.h"
58
#include "libuna_codepage_mac_ukrainian.h"
59
#include "libuna_codepage_windows_874.h"
60
#include "libuna_codepage_windows_932.h"
61
#include "libuna_codepage_windows_936.h"
62
#include "libuna_codepage_windows_949.h"
63
#include "libuna_codepage_windows_950.h"
64
#include "libuna_codepage_windows_1250.h"
65
#include "libuna_codepage_windows_1251.h"
66
#include "libuna_codepage_windows_1252.h"
67
#include "libuna_codepage_windows_1253.h"
68
#include "libuna_codepage_windows_1254.h"
69
#include "libuna_codepage_windows_1255.h"
70
#include "libuna_codepage_windows_1256.h"
71
#include "libuna_codepage_windows_1257.h"
72
#include "libuna_codepage_windows_1258.h"
73
#include "libuna_definitions.h"
74
#include "libuna_libcerror.h"
75
#include "libuna_types.h"
76
#include "libuna_unicode_character.h"
77
#include "libuna_unused.h"
78
79
/* Valid directly encoded characters: A-Z, a-z, 0-9, '\', '(', ')', ',', '-', '.', '/', ':', '?'
80
 * Valid directly encoded whitespace: '\t', '\n', '\r', ' '
81
 * Valid optional directly encoded characters: '!', '"', '#', '$', '%', '&', '*', ';', '<', '=', '>', '@', '[', ']', '^', '_', '`', '{', '|', '}'
82
 */
83
static uint8_t libuna_unicode_character_utf7_valid_directly_encoded_character[ 256 ] = {
84
  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
85
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86
  1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
87
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
88
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
89
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
90
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
91
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
92
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
100
101
/* Valid UTF-7 base64 characters: A-Z, a-z, 0-9, '+' and '/'
102
 */
103
static uint8_t libuna_unicode_character_utf7_valid_base64_character[ 256 ] = {
104
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
107
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
108
  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
109
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
110
  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
111
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
112
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
120
121
/* Determines the size of a byte stream character from an Unicode character
122
 * Adds the size to the byte stream character size value
123
 * Returns 1 if successful, 0 if the byte stream character is valid but not supported since it requires special handling or -1 on error
124
 */
125
int libuna_unicode_character_size_to_byte_stream(
126
     libuna_unicode_character_t unicode_character,
127
     int codepage,
128
     size_t *byte_stream_character_size,
129
     libcerror_error_t **error )
130
12.2k
{
131
12.2k
  static char *function                  = "libuna_unicode_character_size_to_byte_stream";
132
12.2k
  size_t safe_byte_stream_character_size = 0;
133
12.2k
  int result                             = 1;
134
135
12.2k
  if( byte_stream_character_size == NULL )
136
0
  {
137
0
    libcerror_error_set(
138
0
     error,
139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
141
0
     "%s: invalid byte stream character size.",
142
0
     function );
143
144
0
    return( -1 );
145
0
  }
146
12.2k
  safe_byte_stream_character_size = *byte_stream_character_size;
147
148
12.2k
  switch( codepage )
149
12.2k
  {
150
12.2k
    case LIBUNA_CODEPAGE_ASCII:
151
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_1:
152
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_2:
153
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_3:
154
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_4:
155
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_5:
156
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_6:
157
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_7:
158
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_8:
159
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_9:
160
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_10:
161
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_11:
162
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_13:
163
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_14:
164
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_15:
165
12.2k
    case LIBUNA_CODEPAGE_ISO_8859_16:
166
12.2k
    case LIBUNA_CODEPAGE_KOI8_R:
167
12.2k
    case LIBUNA_CODEPAGE_KOI8_U:
168
12.2k
    case LIBUNA_CODEPAGE_MAC_ARABIC:
169
12.2k
    case LIBUNA_CODEPAGE_MAC_CELTIC:
170
12.2k
    case LIBUNA_CODEPAGE_MAC_CENTRALEURROMAN:
171
12.2k
    case LIBUNA_CODEPAGE_MAC_CROATIAN:
172
12.2k
    case LIBUNA_CODEPAGE_MAC_CYRILLIC:
173
12.2k
    case LIBUNA_CODEPAGE_MAC_DINGBATS:
174
12.2k
    case LIBUNA_CODEPAGE_MAC_FARSI:
175
12.2k
    case LIBUNA_CODEPAGE_MAC_GAELIC:
176
12.2k
    case LIBUNA_CODEPAGE_MAC_GREEK:
177
12.2k
    case LIBUNA_CODEPAGE_MAC_ICELANDIC:
178
12.2k
    case LIBUNA_CODEPAGE_MAC_INUIT:
179
12.2k
    case LIBUNA_CODEPAGE_MAC_ROMAN:
180
12.2k
    case LIBUNA_CODEPAGE_MAC_ROMANIAN:
181
12.2k
    case LIBUNA_CODEPAGE_MAC_RUSSIAN:
182
12.2k
    case LIBUNA_CODEPAGE_MAC_TURKISH:
183
12.2k
    case LIBUNA_CODEPAGE_MAC_UKRAINIAN:
184
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_874:
185
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1250:
186
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1251:
187
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
188
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1253:
189
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1254:
190
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1255:
191
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1256:
192
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1257:
193
12.2k
    case LIBUNA_CODEPAGE_WINDOWS_1258:
194
12.2k
      safe_byte_stream_character_size += 1;
195
12.2k
      break;
196
197
0
    case LIBUNA_CODEPAGE_MAC_SYMBOL:
198
0
      result = libuna_codepage_mac_symbol_unicode_character_size_to_byte_stream(
199
0
                unicode_character,
200
0
                &safe_byte_stream_character_size,
201
0
                error );
202
0
      break;
203
204
0
    case LIBUNA_CODEPAGE_MAC_THAI:
205
0
      result = libuna_codepage_mac_thai_unicode_character_size_to_byte_stream(
206
0
                unicode_character,
207
0
                &safe_byte_stream_character_size,
208
0
                error );
209
0
      break;
210
211
0
    case LIBUNA_CODEPAGE_WINDOWS_932:
212
0
      result = libuna_codepage_windows_932_unicode_character_size_to_byte_stream(
213
0
                unicode_character,
214
0
                &safe_byte_stream_character_size,
215
0
                error );
216
0
      break;
217
218
0
    case LIBUNA_CODEPAGE_WINDOWS_936:
219
0
      result = libuna_codepage_windows_936_unicode_character_size_to_byte_stream(
220
0
                unicode_character,
221
0
                &safe_byte_stream_character_size,
222
0
                error );
223
0
      break;
224
225
0
    case LIBUNA_CODEPAGE_WINDOWS_949:
226
0
      result = libuna_codepage_windows_949_unicode_character_size_to_byte_stream(
227
0
                unicode_character,
228
0
                &safe_byte_stream_character_size,
229
0
                error );
230
0
      break;
231
232
0
    case LIBUNA_CODEPAGE_WINDOWS_950:
233
0
      result = libuna_codepage_windows_950_unicode_character_size_to_byte_stream(
234
0
                unicode_character,
235
0
                &safe_byte_stream_character_size,
236
0
                error );
237
0
      break;
238
239
0
    default:
240
0
      libcerror_error_set(
241
0
       error,
242
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
243
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
244
0
       "%s: unsupported codepage: %d.",
245
0
       function,
246
0
       codepage );
247
248
0
      return( -1 );
249
12.2k
  }
250
12.2k
  if( result == -1 )
251
0
  {
252
0
    libcerror_error_set(
253
0
     error,
254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
255
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
256
0
     "%s: unable to determine byte stream character size.",
257
0
     function );
258
259
0
    return( -1 );
260
0
  }
261
12.2k
  *byte_stream_character_size = safe_byte_stream_character_size;
262
263
12.2k
  return( result );
264
12.2k
}
265
266
/* Copies an Unicode character from a byte stream
267
 * Returns 1 if successful, 0 if the byte stream character is valid but not supported since it requires special handling or -1 on error
268
 */
269
int libuna_unicode_character_copy_from_byte_stream(
270
     libuna_unicode_character_t *unicode_character,
271
     const uint8_t *byte_stream,
272
     size_t byte_stream_size,
273
     size_t *byte_stream_index,
274
     int codepage,
275
     libcerror_error_t **error )
276
202k
{
277
202k
  static char *function                             = "libuna_unicode_character_copy_from_byte_stream";
278
202k
  libuna_unicode_character_t safe_unicode_character = 0;
279
202k
  size_t safe_byte_stream_index                     = 0;
280
202k
  uint8_t byte_stream_character                     = 0;
281
202k
  int result                                        = 1;
282
283
202k
  if( unicode_character == NULL )
284
0
  {
285
0
    libcerror_error_set(
286
0
     error,
287
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
288
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
289
0
     "%s: invalid Unicode character.",
290
0
     function );
291
292
0
    return( -1 );
293
0
  }
294
202k
  if( byte_stream == NULL )
295
0
  {
296
0
    libcerror_error_set(
297
0
     error,
298
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
299
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
300
0
     "%s: invalid byte stream.",
301
0
     function );
302
303
0
    return( -1 );
304
0
  }
305
202k
  if( byte_stream_size > (size_t) SSIZE_MAX )
306
0
  {
307
0
    libcerror_error_set(
308
0
     error,
309
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
310
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
311
0
     "%s: invalid byte stream size value exceeds maximum.",
312
0
     function );
313
314
0
    return( -1 );
315
0
  }
316
202k
  if( byte_stream_index == NULL )
317
0
  {
318
0
    libcerror_error_set(
319
0
     error,
320
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
321
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
322
0
     "%s: invalid byte stream index.",
323
0
     function );
324
325
0
    return( -1 );
326
0
  }
327
202k
  safe_byte_stream_index = *byte_stream_index;
328
329
202k
  if( safe_byte_stream_index >= byte_stream_size )
330
0
  {
331
0
    libcerror_error_set(
332
0
     error,
333
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
334
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
335
0
     "%s: byte stream too small.",
336
0
     function );
337
338
0
    return( -1 );
339
0
  }
340
202k
  byte_stream_character = byte_stream[ safe_byte_stream_index ];
341
342
202k
  switch( codepage )
343
202k
  {
344
112k
    case LIBUNA_CODEPAGE_ASCII:
345
112k
      if( byte_stream_character < 0x80 )
346
110k
      {
347
110k
        safe_unicode_character = byte_stream_character;
348
110k
      }
349
2.76k
      else
350
2.76k
      {
351
2.76k
        safe_unicode_character = 0xfffd;
352
2.76k
      }
353
112k
      safe_byte_stream_index += 1;
354
355
112k
      break;
356
357
0
    case LIBUNA_CODEPAGE_ISO_8859_1:
358
0
      safe_unicode_character = byte_stream_character;
359
360
0
      safe_byte_stream_index += 1;
361
362
0
      break;
363
364
0
    case LIBUNA_CODEPAGE_ISO_8859_2:
365
0
      if( byte_stream_character < 0xa0 )
366
0
      {
367
0
        safe_unicode_character = byte_stream_character;
368
0
      }
369
0
      else
370
0
      {
371
0
        byte_stream_character -= 0xa0;
372
373
0
        safe_unicode_character = libuna_codepage_iso_8859_2_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
374
0
      }
375
0
      safe_byte_stream_index += 1;
376
377
0
      break;
378
379
0
    case LIBUNA_CODEPAGE_ISO_8859_3:
380
0
      if( byte_stream_character < 0xa0 )
381
0
      {
382
0
        safe_unicode_character = byte_stream_character;
383
0
      }
384
0
      else
385
0
      {
386
0
        byte_stream_character -= 0xa0;
387
388
0
        safe_unicode_character = libuna_codepage_iso_8859_3_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
389
0
      }
390
0
      safe_byte_stream_index += 1;
391
392
0
      break;
393
394
0
    case LIBUNA_CODEPAGE_ISO_8859_4:
395
0
      if( byte_stream_character < 0xa0 )
396
0
      {
397
0
        safe_unicode_character = byte_stream_character;
398
0
      }
399
0
      else
400
0
      {
401
0
        byte_stream_character -= 0xa0;
402
403
0
        safe_unicode_character = libuna_codepage_iso_8859_4_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
404
0
      }
405
0
      safe_byte_stream_index += 1;
406
407
0
      break;
408
409
0
    case LIBUNA_CODEPAGE_ISO_8859_5:
410
0
      if( byte_stream_character < 0xa0 )
411
0
      {
412
0
        safe_unicode_character = byte_stream_character;
413
0
      }
414
0
      else
415
0
      {
416
0
        byte_stream_character -= 0xa0;
417
418
0
        safe_unicode_character = libuna_codepage_iso_8859_5_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
419
0
      }
420
0
      safe_byte_stream_index += 1;
421
422
0
      break;
423
424
0
    case LIBUNA_CODEPAGE_ISO_8859_6:
425
0
      if( byte_stream_character < 0xa0 )
426
0
      {
427
0
        safe_unicode_character = byte_stream_character;
428
0
      }
429
0
      else
430
0
      {
431
0
        byte_stream_character -= 0xa0;
432
433
0
        safe_unicode_character = libuna_codepage_iso_8859_6_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
434
0
      }
435
0
      safe_byte_stream_index += 1;
436
437
0
      break;
438
439
0
    case LIBUNA_CODEPAGE_ISO_8859_7:
440
0
      if( byte_stream_character < 0xa0 )
441
0
      {
442
0
        safe_unicode_character = byte_stream_character;
443
0
      }
444
0
      else
445
0
      {
446
0
        byte_stream_character -= 0xa0;
447
448
0
        safe_unicode_character = libuna_codepage_iso_8859_7_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
449
0
      }
450
0
      safe_byte_stream_index += 1;
451
452
0
      break;
453
454
0
    case LIBUNA_CODEPAGE_ISO_8859_8:
455
0
      if( byte_stream_character < 0xa0 )
456
0
      {
457
0
        safe_unicode_character = byte_stream_character;
458
0
      }
459
0
      else
460
0
      {
461
0
        byte_stream_character -= 0xa0;
462
463
0
        safe_unicode_character = libuna_codepage_iso_8859_8_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
464
0
      }
465
0
      safe_byte_stream_index += 1;
466
467
0
      break;
468
469
0
    case LIBUNA_CODEPAGE_ISO_8859_9:
470
0
      if( byte_stream_character < 0xd0 )
471
0
      {
472
0
        safe_unicode_character = byte_stream_character;
473
0
      }
474
0
      else
475
0
      {
476
0
        byte_stream_character -= 0xd0;
477
478
0
        safe_unicode_character = libuna_codepage_iso_8859_9_byte_stream_to_unicode_base_0xd0[ byte_stream_character ];
479
0
      }
480
0
      safe_byte_stream_index += 1;
481
482
0
      break;
483
484
0
    case LIBUNA_CODEPAGE_ISO_8859_10:
485
0
      if( byte_stream_character < 0xa0 )
486
0
      {
487
0
        safe_unicode_character = byte_stream_character;
488
0
      }
489
0
      else
490
0
      {
491
0
        byte_stream_character -= 0xa0;
492
493
0
        safe_unicode_character = libuna_codepage_iso_8859_10_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
494
0
      }
495
0
      safe_byte_stream_index += 1;
496
497
0
      break;
498
499
0
    case LIBUNA_CODEPAGE_ISO_8859_11:
500
0
      if( byte_stream_character < 0xa1 )
501
0
      {
502
0
        safe_unicode_character = byte_stream_character;
503
0
      }
504
0
      else if( byte_stream_character < 0xdb )
505
0
      {
506
0
        safe_unicode_character = byte_stream_character + 0x0d60;
507
0
      }
508
0
      else if( byte_stream_character < 0xdf )
509
0
      {
510
0
        safe_unicode_character = 0xfffd;
511
0
      }
512
0
      else if( byte_stream_character < 0xfc )
513
0
      {
514
0
        safe_unicode_character = byte_stream_character + 0x0d60;
515
0
      }
516
0
      else
517
0
      {
518
0
        safe_unicode_character = 0xfffd;
519
0
      }
520
0
      safe_byte_stream_index += 1;
521
522
0
      break;
523
524
0
    case LIBUNA_CODEPAGE_ISO_8859_13:
525
0
      if( byte_stream_character < 0xa0 )
526
0
      {
527
0
        safe_unicode_character = byte_stream_character;
528
0
      }
529
0
      else
530
0
      {
531
0
        byte_stream_character -= 0xa0;
532
533
0
        safe_unicode_character = libuna_codepage_iso_8859_13_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
534
0
      }
535
0
      safe_byte_stream_index += 1;
536
537
0
      break;
538
539
0
    case LIBUNA_CODEPAGE_ISO_8859_14:
540
0
      if( byte_stream_character < 0xa0 )
541
0
      {
542
0
        safe_unicode_character = byte_stream_character;
543
0
      }
544
0
      else
545
0
      {
546
0
        byte_stream_character -= 0xa0;
547
548
0
        safe_unicode_character = libuna_codepage_iso_8859_14_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
549
0
      }
550
0
      safe_byte_stream_index += 1;
551
552
0
      break;
553
554
0
    case LIBUNA_CODEPAGE_ISO_8859_15:
555
0
      if( ( byte_stream_character >= 0xa0 )
556
0
       && ( byte_stream_character < 0xc0 ) )
557
0
      {
558
0
        byte_stream_character -= 0xa0;
559
560
0
        safe_unicode_character = libuna_codepage_iso_8859_15_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
561
0
      }
562
0
      else
563
0
      {
564
0
        safe_unicode_character = byte_stream_character;
565
0
      }
566
0
      safe_byte_stream_index += 1;
567
568
0
      break;
569
570
0
    case LIBUNA_CODEPAGE_ISO_8859_16:
571
0
      if( byte_stream_character < 0xa0 )
572
0
      {
573
0
        safe_unicode_character = byte_stream_character;
574
0
      }
575
0
      else
576
0
      {
577
0
        byte_stream_character -= 0xa0;
578
579
0
        safe_unicode_character = libuna_codepage_iso_8859_16_byte_stream_to_unicode_base_0xa0[ byte_stream_character ];
580
0
      }
581
0
      safe_byte_stream_index += 1;
582
583
0
      break;
584
585
0
    case LIBUNA_CODEPAGE_KOI8_R:
586
0
      result = libuna_codepage_koi8_r_copy_from_byte_stream(
587
0
                &safe_unicode_character,
588
0
                byte_stream,
589
0
                byte_stream_size,
590
0
                &safe_byte_stream_index,
591
0
                error );
592
0
      break;
593
594
0
    case LIBUNA_CODEPAGE_KOI8_U:
595
0
      result = libuna_codepage_koi8_u_copy_from_byte_stream(
596
0
                &safe_unicode_character,
597
0
                byte_stream,
598
0
                byte_stream_size,
599
0
                &safe_byte_stream_index,
600
0
                error );
601
0
      break;
602
603
0
    case LIBUNA_CODEPAGE_MAC_ARABIC:
604
0
      result = libuna_codepage_mac_arabic_copy_from_byte_stream(
605
0
                &safe_unicode_character,
606
0
                byte_stream,
607
0
                byte_stream_size,
608
0
                &safe_byte_stream_index,
609
0
                error );
610
0
      break;
611
612
0
    case LIBUNA_CODEPAGE_MAC_CELTIC:
613
0
      result = libuna_codepage_mac_celtic_copy_from_byte_stream(
614
0
                &safe_unicode_character,
615
0
                byte_stream,
616
0
                byte_stream_size,
617
0
                &safe_byte_stream_index,
618
0
                error );
619
0
      break;
620
621
0
    case LIBUNA_CODEPAGE_MAC_CENTRALEURROMAN:
622
0
      result = libuna_codepage_mac_centraleurroman_copy_from_byte_stream(
623
0
                &safe_unicode_character,
624
0
                byte_stream,
625
0
                byte_stream_size,
626
0
                &safe_byte_stream_index,
627
0
                error );
628
0
      break;
629
630
0
    case LIBUNA_CODEPAGE_MAC_CROATIAN:
631
0
      result = libuna_codepage_mac_croatian_copy_from_byte_stream(
632
0
                &safe_unicode_character,
633
0
                byte_stream,
634
0
                byte_stream_size,
635
0
                &safe_byte_stream_index,
636
0
                error );
637
0
      break;
638
639
0
    case LIBUNA_CODEPAGE_MAC_CYRILLIC:
640
0
      result = libuna_codepage_mac_cyrillic_copy_from_byte_stream(
641
0
                &safe_unicode_character,
642
0
                byte_stream,
643
0
                byte_stream_size,
644
0
                &safe_byte_stream_index,
645
0
                error );
646
0
      break;
647
648
0
    case LIBUNA_CODEPAGE_MAC_DINGBATS:
649
0
      result = libuna_codepage_mac_dingbats_copy_from_byte_stream(
650
0
                &safe_unicode_character,
651
0
                byte_stream,
652
0
                byte_stream_size,
653
0
                &safe_byte_stream_index,
654
0
                error );
655
0
      break;
656
657
0
    case LIBUNA_CODEPAGE_MAC_FARSI:
658
0
      result = libuna_codepage_mac_farsi_copy_from_byte_stream(
659
0
                &safe_unicode_character,
660
0
                byte_stream,
661
0
                byte_stream_size,
662
0
                &safe_byte_stream_index,
663
0
                error );
664
0
      break;
665
666
0
    case LIBUNA_CODEPAGE_MAC_GAELIC:
667
0
      result = libuna_codepage_mac_gaelic_copy_from_byte_stream(
668
0
                &safe_unicode_character,
669
0
                byte_stream,
670
0
                byte_stream_size,
671
0
                &safe_byte_stream_index,
672
0
                error );
673
0
      break;
674
675
0
    case LIBUNA_CODEPAGE_MAC_GREEK:
676
0
      result = libuna_codepage_mac_greek_copy_from_byte_stream(
677
0
                &safe_unicode_character,
678
0
                byte_stream,
679
0
                byte_stream_size,
680
0
                &safe_byte_stream_index,
681
0
                error );
682
0
      break;
683
684
0
    case LIBUNA_CODEPAGE_MAC_ICELANDIC:
685
0
      result = libuna_codepage_mac_icelandic_copy_from_byte_stream(
686
0
                &safe_unicode_character,
687
0
                byte_stream,
688
0
                byte_stream_size,
689
0
                &safe_byte_stream_index,
690
0
                error );
691
0
      break;
692
693
0
    case LIBUNA_CODEPAGE_MAC_INUIT:
694
0
      result = libuna_codepage_mac_inuit_copy_from_byte_stream(
695
0
                &safe_unicode_character,
696
0
                byte_stream,
697
0
                byte_stream_size,
698
0
                &safe_byte_stream_index,
699
0
                error );
700
0
      break;
701
702
0
    case LIBUNA_CODEPAGE_MAC_ROMAN:
703
0
      result = libuna_codepage_mac_roman_copy_from_byte_stream(
704
0
                &safe_unicode_character,
705
0
                byte_stream,
706
0
                byte_stream_size,
707
0
                &safe_byte_stream_index,
708
0
                error );
709
0
      break;
710
711
0
    case LIBUNA_CODEPAGE_MAC_ROMANIAN:
712
0
      result = libuna_codepage_mac_romanian_copy_from_byte_stream(
713
0
                &safe_unicode_character,
714
0
                byte_stream,
715
0
                byte_stream_size,
716
0
                &safe_byte_stream_index,
717
0
                error );
718
0
      break;
719
720
0
    case LIBUNA_CODEPAGE_MAC_RUSSIAN:
721
0
      result = libuna_codepage_mac_russian_copy_from_byte_stream(
722
0
                &safe_unicode_character,
723
0
                byte_stream,
724
0
                byte_stream_size,
725
0
                &safe_byte_stream_index,
726
0
                error );
727
0
      break;
728
729
0
    case LIBUNA_CODEPAGE_MAC_SYMBOL:
730
0
      result = libuna_codepage_mac_symbol_copy_from_byte_stream(
731
0
                &safe_unicode_character,
732
0
                byte_stream,
733
0
                byte_stream_size,
734
0
                &safe_byte_stream_index,
735
0
                error );
736
0
      break;
737
738
0
    case LIBUNA_CODEPAGE_MAC_THAI:
739
0
      result = libuna_codepage_mac_thai_copy_from_byte_stream(
740
0
                &safe_unicode_character,
741
0
                byte_stream,
742
0
                byte_stream_size,
743
0
                &safe_byte_stream_index,
744
0
                error );
745
0
      break;
746
747
0
    case LIBUNA_CODEPAGE_MAC_TURKISH:
748
0
      result = libuna_codepage_mac_turkish_copy_from_byte_stream(
749
0
                &safe_unicode_character,
750
0
                byte_stream,
751
0
                byte_stream_size,
752
0
                &safe_byte_stream_index,
753
0
                error );
754
0
      break;
755
756
0
    case LIBUNA_CODEPAGE_MAC_UKRAINIAN:
757
0
      result = libuna_codepage_mac_ukrainian_copy_from_byte_stream(
758
0
                &safe_unicode_character,
759
0
                byte_stream,
760
0
                byte_stream_size,
761
0
                &safe_byte_stream_index,
762
0
                error );
763
0
      break;
764
765
0
    case LIBUNA_CODEPAGE_WINDOWS_874:
766
0
      result = libuna_codepage_windows_874_copy_from_byte_stream(
767
0
                &safe_unicode_character,
768
0
                byte_stream,
769
0
                byte_stream_size,
770
0
                &safe_byte_stream_index,
771
0
                error );
772
0
      break;
773
774
0
    case LIBUNA_CODEPAGE_WINDOWS_932:
775
0
      result = libuna_codepage_windows_932_copy_from_byte_stream(
776
0
                &safe_unicode_character,
777
0
                byte_stream,
778
0
                byte_stream_size,
779
0
                &safe_byte_stream_index,
780
0
                error );
781
0
      break;
782
783
0
    case LIBUNA_CODEPAGE_WINDOWS_936:
784
0
      result = libuna_codepage_windows_936_copy_from_byte_stream(
785
0
                &safe_unicode_character,
786
0
                byte_stream,
787
0
                byte_stream_size,
788
0
                &safe_byte_stream_index,
789
0
                error );
790
0
      break;
791
792
0
    case LIBUNA_CODEPAGE_WINDOWS_949:
793
0
      result = libuna_codepage_windows_949_copy_from_byte_stream(
794
0
                &safe_unicode_character,
795
0
                byte_stream,
796
0
                byte_stream_size,
797
0
                &safe_byte_stream_index,
798
0
                error );
799
0
      break;
800
801
0
    case LIBUNA_CODEPAGE_WINDOWS_950:
802
0
      result = libuna_codepage_windows_950_copy_from_byte_stream(
803
0
                &safe_unicode_character,
804
0
                byte_stream,
805
0
                byte_stream_size,
806
0
                &safe_byte_stream_index,
807
0
                error );
808
0
      break;
809
810
0
    case LIBUNA_CODEPAGE_WINDOWS_1250:
811
0
      result = libuna_codepage_windows_1250_copy_from_byte_stream(
812
0
                &safe_unicode_character,
813
0
                byte_stream,
814
0
                byte_stream_size,
815
0
                &safe_byte_stream_index,
816
0
                error );
817
0
      break;
818
819
0
    case LIBUNA_CODEPAGE_WINDOWS_1251:
820
0
      result = libuna_codepage_windows_1251_copy_from_byte_stream(
821
0
                &safe_unicode_character,
822
0
                byte_stream,
823
0
                byte_stream_size,
824
0
                &safe_byte_stream_index,
825
0
                error );
826
0
      break;
827
828
89.6k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
829
89.6k
      result = libuna_codepage_windows_1252_copy_from_byte_stream(
830
89.6k
                &safe_unicode_character,
831
89.6k
                byte_stream,
832
89.6k
                byte_stream_size,
833
89.6k
                &safe_byte_stream_index,
834
89.6k
                error );
835
89.6k
      break;
836
837
0
    case LIBUNA_CODEPAGE_WINDOWS_1253:
838
0
      result = libuna_codepage_windows_1253_copy_from_byte_stream(
839
0
                &safe_unicode_character,
840
0
                byte_stream,
841
0
                byte_stream_size,
842
0
                &safe_byte_stream_index,
843
0
                error );
844
0
      break;
845
846
0
    case LIBUNA_CODEPAGE_WINDOWS_1254:
847
0
      result = libuna_codepage_windows_1254_copy_from_byte_stream(
848
0
                &safe_unicode_character,
849
0
                byte_stream,
850
0
                byte_stream_size,
851
0
                &safe_byte_stream_index,
852
0
                error );
853
0
      break;
854
855
0
    case LIBUNA_CODEPAGE_WINDOWS_1255:
856
0
      result = libuna_codepage_windows_1255_copy_from_byte_stream(
857
0
                &safe_unicode_character,
858
0
                byte_stream,
859
0
                byte_stream_size,
860
0
                &safe_byte_stream_index,
861
0
                error );
862
0
      break;
863
864
0
    case LIBUNA_CODEPAGE_WINDOWS_1256:
865
0
      result = libuna_codepage_windows_1256_copy_from_byte_stream(
866
0
                &safe_unicode_character,
867
0
                byte_stream,
868
0
                byte_stream_size,
869
0
                &safe_byte_stream_index,
870
0
                error );
871
0
      break;
872
873
0
    case LIBUNA_CODEPAGE_WINDOWS_1257:
874
0
      result = libuna_codepage_windows_1257_copy_from_byte_stream(
875
0
                &safe_unicode_character,
876
0
                byte_stream,
877
0
                byte_stream_size,
878
0
                &safe_byte_stream_index,
879
0
                error );
880
0
      break;
881
882
0
    case LIBUNA_CODEPAGE_WINDOWS_1258:
883
0
      result = libuna_codepage_windows_1258_copy_from_byte_stream(
884
0
                &safe_unicode_character,
885
0
                byte_stream,
886
0
                byte_stream_size,
887
0
                &safe_byte_stream_index,
888
0
                error );
889
0
      break;
890
891
0
    default:
892
0
      libcerror_error_set(
893
0
       error,
894
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
895
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
896
0
      "%s: unsupported codepage: %d.",
897
0
       function,
898
0
       codepage );
899
900
0
      return( -1 );
901
202k
  }
902
202k
  if( result == -1 )
903
0
  {
904
0
    libcerror_error_set(
905
0
     error,
906
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
907
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
908
0
     "%s: unable to copy Unicode character from byte stream.",
909
0
     function );
910
911
0
    return( -1 );
912
0
  }
913
202k
  *unicode_character = safe_unicode_character;
914
202k
  *byte_stream_index = safe_byte_stream_index;
915
916
202k
  return( result );
917
202k
}
918
919
/* Copies an Unicode character to a byte stream
920
 * Returns 1 if successful, 0 if the Unicode character is valid but not supported since it requires special handling or -1 on error
921
 */
922
int libuna_unicode_character_copy_to_byte_stream(
923
     libuna_unicode_character_t unicode_character,
924
     uint8_t *byte_stream,
925
     size_t byte_stream_size,
926
     size_t *byte_stream_index,
927
     int codepage,
928
     libcerror_error_t **error )
929
12.2k
{
930
12.2k
  static char *function         = "libuna_unicode_character_copy_to_byte_stream";
931
12.2k
  size_t safe_byte_stream_index = 0;
932
12.2k
  int result                    = 1;
933
934
12.2k
  if( byte_stream == NULL )
935
0
  {
936
0
    libcerror_error_set(
937
0
     error,
938
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
939
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
940
0
     "%s: invalid byte stream.",
941
0
     function );
942
943
0
    return( -1 );
944
0
  }
945
12.2k
  if( byte_stream_size > (size_t) SSIZE_MAX )
946
0
  {
947
0
    libcerror_error_set(
948
0
     error,
949
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
950
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
951
0
     "%s: invalid byte stream size value exceeds maximum.",
952
0
     function );
953
954
0
    return( -1 );
955
0
  }
956
12.2k
  if( byte_stream_index == NULL )
957
0
  {
958
0
    libcerror_error_set(
959
0
     error,
960
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
961
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
962
0
     "%s: invalid byte stream index.",
963
0
     function );
964
965
0
    return( -1 );
966
0
  }
967
12.2k
  safe_byte_stream_index = *byte_stream_index;
968
969
12.2k
  if( safe_byte_stream_index >= byte_stream_size )
970
0
  {
971
0
    libcerror_error_set(
972
0
     error,
973
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
974
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
975
0
     "%s: byte stream too small.",
976
0
     function );
977
978
0
    return( -1 );
979
0
  }
980
12.2k
  switch( codepage )
981
12.2k
  {
982
12.2k
    case LIBUNA_CODEPAGE_ASCII:
983
12.2k
      if( unicode_character < 0x0080 )
984
12.2k
      {
985
12.2k
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
986
12.2k
      }
987
0
      else
988
0
      {
989
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
990
0
      }
991
12.2k
      safe_byte_stream_index += 1;
992
993
12.2k
      break;
994
995
0
    case LIBUNA_CODEPAGE_ISO_8859_1:
996
0
      if( unicode_character < 0x0100 )
997
0
      {
998
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
999
0
      }
1000
0
      else
1001
0
      {
1002
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
1003
0
      }
1004
0
      safe_byte_stream_index += 1;
1005
1006
0
      break;
1007
1008
0
    case LIBUNA_CODEPAGE_ISO_8859_2:
1009
0
      if( unicode_character < 0x00a0 )
1010
0
      {
1011
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1012
0
      }
1013
0
      else if( ( unicode_character >= 0x00a0 )
1014
0
            && ( unicode_character < 0x0120 ) )
1015
0
      {
1016
0
        unicode_character -= 0x00a0;
1017
1018
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_2_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1019
0
      }
1020
0
      else if( ( unicode_character >= 0x0138 )
1021
0
            && ( unicode_character < 0x0180 ) )
1022
0
      {
1023
0
        unicode_character -= 0x0138;
1024
1025
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_2_unicode_to_byte_stream_base_0x0138[ unicode_character ];
1026
0
      }
1027
0
      else if( ( unicode_character >= 0x02d8 )
1028
0
            && ( unicode_character < 0x02e0 ) )
1029
0
      {
1030
0
        unicode_character -= 0x02d8;
1031
1032
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_2_unicode_to_byte_stream_base_0x02d8[ unicode_character ];
1033
0
      }
1034
0
      else if( unicode_character == 0x02c7 )
1035
0
      {
1036
0
        byte_stream[ safe_byte_stream_index ] = 0xb7;
1037
0
      }
1038
0
      else
1039
0
      {
1040
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
1041
0
      }
1042
0
      safe_byte_stream_index += 1;
1043
1044
0
      break;
1045
1046
0
    case LIBUNA_CODEPAGE_ISO_8859_3:
1047
0
      if( unicode_character < 0x00a0 )
1048
0
      {
1049
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1050
0
      }
1051
0
      else if( ( unicode_character >= 0x00a0 )
1052
0
            && ( unicode_character < 0x0100 ) )
1053
0
      {
1054
0
        unicode_character -= 0x00a0;
1055
1056
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_3_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1057
0
      }
1058
0
      else if( ( unicode_character >= 0x0108 )
1059
0
            && ( unicode_character < 0x0110 ) )
1060
0
      {
1061
0
        unicode_character -= 0x0108;
1062
1063
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_3_unicode_to_byte_stream_base_0x0108[ unicode_character ];
1064
0
      }
1065
0
      else if( ( unicode_character >= 0x0118 )
1066
0
            && ( unicode_character < 0x0128 ) )
1067
0
      {
1068
0
        unicode_character -= 0x0118;
1069
1070
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_3_unicode_to_byte_stream_base_0x0118[ unicode_character ];
1071
0
      }
1072
0
      else if( ( unicode_character >= 0x0130 )
1073
0
            && ( unicode_character < 0x0138 ) )
1074
0
      {
1075
0
        unicode_character -= 0x0130;
1076
1077
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_3_unicode_to_byte_stream_base_0x0130[ unicode_character ];
1078
0
      }
1079
0
      else if( ( unicode_character >= 0x0158 )
1080
0
            && ( unicode_character < 0x0160 ) )
1081
0
      {
1082
0
        unicode_character -= 0x0158;
1083
1084
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_3_unicode_to_byte_stream_base_0x0158[ unicode_character ];
1085
0
      }
1086
0
      else switch( unicode_character )
1087
0
      {
1088
0
        case 0x016c:
1089
0
          byte_stream[ safe_byte_stream_index ] = 0xdd;
1090
0
          break;
1091
1092
0
        case 0x016d:
1093
0
          byte_stream[ safe_byte_stream_index ] = 0xfd;
1094
0
          break;
1095
1096
0
        case 0x017b:
1097
0
          byte_stream[ safe_byte_stream_index ] = 0xaf;
1098
0
          break;
1099
1100
0
        case 0x017c:
1101
0
          byte_stream[ safe_byte_stream_index ] = 0xbf;
1102
0
          break;
1103
1104
0
        case 0x02d8:
1105
0
          byte_stream[ safe_byte_stream_index ] = 0xa2;
1106
0
          break;
1107
1108
0
        case 0x02d9:
1109
0
          byte_stream[ safe_byte_stream_index ] = 0xff;
1110
0
          break;
1111
1112
0
        default:
1113
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1114
0
          break;
1115
0
      }
1116
0
      safe_byte_stream_index += 1;
1117
1118
0
      break;
1119
1120
0
    case LIBUNA_CODEPAGE_ISO_8859_4:
1121
0
      if( unicode_character < 0x00a0 )
1122
0
      {
1123
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1124
0
      }
1125
0
      else if( ( unicode_character >= 0x00a0 )
1126
0
            && ( unicode_character < 0x0158 ) )
1127
0
      {
1128
0
        unicode_character -= 0x00a0;
1129
1130
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_4_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1131
0
      }
1132
0
      else if( ( unicode_character >= 0x0160 )
1133
0
            && ( unicode_character < 0x0180 ) )
1134
0
      {
1135
0
        unicode_character -= 0x0160;
1136
1137
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_4_unicode_to_byte_stream_base_0x0160[ unicode_character ];
1138
0
      }
1139
0
      else switch( unicode_character )
1140
0
      {
1141
0
        case 0x02c7:
1142
0
          byte_stream[ safe_byte_stream_index ] = 0xb7;
1143
0
          break;
1144
1145
0
        case 0x02d9:
1146
0
          byte_stream[ safe_byte_stream_index ] = 0xff;
1147
0
          break;
1148
1149
0
        case 0x02db:
1150
0
          byte_stream[ safe_byte_stream_index ] = 0xb2;
1151
0
          break;
1152
1153
0
        default:
1154
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1155
0
          break;
1156
0
      }
1157
0
      safe_byte_stream_index += 1;
1158
1159
0
      break;
1160
1161
0
    case LIBUNA_CODEPAGE_ISO_8859_5:
1162
0
      if( unicode_character < 0x00a1 )
1163
0
      {
1164
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1165
0
      }
1166
0
      else if( ( unicode_character >= 0x0400 )
1167
0
            && ( unicode_character < 0x0460 ) )
1168
0
      {
1169
0
        unicode_character -= 0x0400;
1170
1171
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_5_unicode_to_byte_stream_base_0x0400[ unicode_character ];
1172
0
      }
1173
0
      else switch( unicode_character )
1174
0
      {
1175
0
        case 0x00a7:
1176
0
          byte_stream[ safe_byte_stream_index ] = 0xfd;
1177
0
          break;
1178
1179
0
        case 0x00ad:
1180
0
          byte_stream[ safe_byte_stream_index ] = 0xad;
1181
0
          break;
1182
1183
0
        case 0x2116:
1184
0
          byte_stream[ safe_byte_stream_index ] = 0xf0;
1185
0
          break;
1186
1187
0
        default:
1188
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1189
0
          break;
1190
0
      }
1191
0
      safe_byte_stream_index += 1;
1192
1193
0
      break;
1194
1195
0
    case LIBUNA_CODEPAGE_ISO_8859_6:
1196
0
      if( unicode_character < 0x00a1 )
1197
0
      {
1198
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1199
0
      }
1200
0
      else if( ( unicode_character >= 0x0618 )
1201
0
            && ( unicode_character < 0x658 ) )
1202
0
      {
1203
0
        unicode_character -= 0x0618;
1204
1205
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_6_unicode_to_byte_stream_base_0x0618[ unicode_character ];
1206
0
      }
1207
0
      else switch( unicode_character )
1208
0
      {
1209
0
        case 0x00a4:
1210
0
          byte_stream[ safe_byte_stream_index ] = 0xa4;
1211
0
          break;
1212
1213
0
        case 0x00ad:
1214
0
          byte_stream[ safe_byte_stream_index ] = 0xad;
1215
0
          break;
1216
1217
0
        case 0x060c:
1218
0
          byte_stream[ safe_byte_stream_index ] = 0xac;
1219
0
          break;
1220
1221
0
        default:
1222
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1223
0
          break;
1224
0
      }
1225
0
      safe_byte_stream_index += 1;
1226
1227
0
      break;
1228
1229
0
    case LIBUNA_CODEPAGE_ISO_8859_7:
1230
0
      if( unicode_character < 0x00a0 )
1231
0
      {
1232
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1233
0
      }
1234
0
      else if( ( unicode_character >= 0x00a0 )
1235
0
            && ( unicode_character < 0x00b8 ) )
1236
0
      {
1237
0
        unicode_character -= 0x00a0;
1238
1239
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_7_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1240
0
      }
1241
0
      else if( ( unicode_character >= 0x0380 )
1242
0
            && ( unicode_character < 0x03d0 ) )
1243
0
      {
1244
0
        unicode_character -= 0x0380;
1245
1246
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_7_unicode_to_byte_stream_base_0x0380[ unicode_character ];
1247
0
      }
1248
0
      else switch( unicode_character )
1249
0
      {
1250
0
        case 0x00bb:
1251
0
          byte_stream[ safe_byte_stream_index ] = 0xbb;
1252
0
          break;
1253
1254
0
        case 0x00bd:
1255
0
          byte_stream[ safe_byte_stream_index ] = 0xbd;
1256
0
          break;
1257
1258
0
        case 0x037a:
1259
0
          byte_stream[ safe_byte_stream_index ] = 0xaa;
1260
0
          break;
1261
1262
0
        case 0x2015:
1263
0
          byte_stream[ safe_byte_stream_index ] = 0xaf;
1264
0
          break;
1265
1266
0
        case 0x2018:
1267
0
          byte_stream[ safe_byte_stream_index ] = 0xa1;
1268
0
          break;
1269
1270
0
        case 0x2019:
1271
0
          byte_stream[ safe_byte_stream_index ] = 0xa2;
1272
0
          break;
1273
1274
0
        case 0x20ac:
1275
0
          byte_stream[ safe_byte_stream_index ] = 0xa4;
1276
0
          break;
1277
1278
0
        case 0x20af:
1279
0
          byte_stream[ safe_byte_stream_index ] = 0xa5;
1280
0
          break;
1281
1282
0
        default:
1283
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1284
0
          break;
1285
0
      }
1286
0
      safe_byte_stream_index += 1;
1287
1288
0
      break;
1289
1290
0
    case LIBUNA_CODEPAGE_ISO_8859_8:
1291
0
      if( unicode_character < 0x00a0 )
1292
0
      {
1293
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1294
0
      }
1295
0
      else if( ( unicode_character >= 0x00a0 )
1296
0
            && ( unicode_character < 0x00c0 ) )
1297
0
      {
1298
0
        unicode_character -= 0x00a0;
1299
1300
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_8_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1301
0
      }
1302
0
      else if( ( unicode_character >= 0x05d0 )
1303
0
            && ( unicode_character < 0x05f0 ) )
1304
0
      {
1305
0
        unicode_character -= 0x05d0;
1306
1307
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_8_unicode_to_byte_stream_base_0x05d0[ unicode_character ];
1308
0
      }
1309
0
      else switch( unicode_character )
1310
0
      {
1311
0
        case 0x00d7:
1312
0
          byte_stream[ safe_byte_stream_index ] = 0xaa;
1313
0
          break;
1314
1315
0
        case 0x00f7:
1316
0
          byte_stream[ safe_byte_stream_index ] = 0xba;
1317
0
          break;
1318
1319
0
        case 0x200e:
1320
0
          byte_stream[ safe_byte_stream_index ] = 0xfd;
1321
0
          break;
1322
1323
0
        case 0x200f:
1324
0
          byte_stream[ safe_byte_stream_index ] = 0xfe;
1325
0
          break;
1326
1327
0
        case 0x2017:
1328
0
          byte_stream[ safe_byte_stream_index ] = 0xdf;
1329
0
          break;
1330
1331
0
        default:
1332
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1333
0
          break;
1334
0
      }
1335
0
      safe_byte_stream_index += 1;
1336
1337
0
      break;
1338
1339
0
    case LIBUNA_CODEPAGE_ISO_8859_9:
1340
0
      if( unicode_character < 0x00d0 )
1341
0
      {
1342
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1343
0
      }
1344
0
      else if( ( unicode_character >= 0x00d0 )
1345
0
            && ( unicode_character < 0x0100 ) )
1346
0
      {
1347
0
        unicode_character -= 0x00d0;
1348
1349
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_9_unicode_to_byte_stream_base_0x00d0[ unicode_character ];
1350
0
      }
1351
0
      else switch( unicode_character )
1352
0
      {
1353
0
        case 0x011e:
1354
0
          byte_stream[ safe_byte_stream_index ] = 0xd0;
1355
0
          break;
1356
1357
0
        case 0x011f:
1358
0
          byte_stream[ safe_byte_stream_index ] = 0xf0;
1359
0
          break;
1360
1361
0
        case 0x0130:
1362
0
          byte_stream[ safe_byte_stream_index ] = 0xdd;
1363
0
          break;
1364
1365
0
        case 0x0131:
1366
0
          byte_stream[ safe_byte_stream_index ] = 0xfd;
1367
0
          break;
1368
1369
0
        case 0x015e:
1370
0
          byte_stream[ safe_byte_stream_index ] = 0xde;
1371
0
          break;
1372
1373
0
        case 0x015f:
1374
0
          byte_stream[ safe_byte_stream_index ] = 0xfe;
1375
0
          break;
1376
1377
0
        default:
1378
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1379
0
          break;
1380
0
      }
1381
0
      safe_byte_stream_index += 1;
1382
1383
0
      break;
1384
1385
0
    case LIBUNA_CODEPAGE_ISO_8859_10:
1386
0
      if( unicode_character < 0x00a1 )
1387
0
      {
1388
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1389
0
      }
1390
0
      else if( ( unicode_character >= 0x00c0 )
1391
0
            && ( unicode_character < 0x0150 ) )
1392
0
      {
1393
0
        unicode_character -= 0x00c0;
1394
1395
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_10_unicode_to_byte_stream_base_0x00c0[ unicode_character ];
1396
0
      }
1397
0
      else if( ( unicode_character >= 0x0160 )
1398
0
            && ( unicode_character < 0x0170 ) )
1399
0
      {
1400
0
        unicode_character -= 0x0160;
1401
1402
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_10_unicode_to_byte_stream_base_0x0160[ unicode_character ];
1403
0
      }
1404
0
      else switch( unicode_character )
1405
0
      {
1406
0
        case 0x00a7:
1407
0
          byte_stream[ safe_byte_stream_index ] = 0xa7;
1408
0
          break;
1409
1410
0
        case 0x00ad:
1411
0
          byte_stream[ safe_byte_stream_index ] = 0xad;
1412
0
          break;
1413
1414
0
        case 0x00b0:
1415
0
          byte_stream[ safe_byte_stream_index ] = 0xb0;
1416
0
          break;
1417
1418
0
        case 0x00b7:
1419
0
          byte_stream[ safe_byte_stream_index ] = 0xb7;
1420
0
          break;
1421
1422
0
        case 0x0172:
1423
0
          byte_stream[ safe_byte_stream_index ] = 0xd9;
1424
0
          break;
1425
1426
0
        case 0x0173:
1427
0
          byte_stream[ safe_byte_stream_index ] = 0xf9;
1428
0
          break;
1429
1430
0
        case 0x017d:
1431
0
          byte_stream[ safe_byte_stream_index ] = 0xac;
1432
0
          break;
1433
1434
0
        case 0x017e:
1435
0
          byte_stream[ safe_byte_stream_index ] = 0xbc;
1436
0
          break;
1437
1438
0
        case 0x2015:
1439
0
          byte_stream[ safe_byte_stream_index ] = 0xbd;
1440
0
          break;
1441
1442
0
        default:
1443
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1444
0
          break;
1445
0
      }
1446
0
      safe_byte_stream_index += 1;
1447
1448
0
      break;
1449
1450
0
    case LIBUNA_CODEPAGE_ISO_8859_11:
1451
0
      if( unicode_character < 0x00a1 )
1452
0
      {
1453
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1454
0
      }
1455
0
      else if( ( unicode_character >= 0x0e01 )
1456
0
            && ( unicode_character < 0x0e3b ) )
1457
0
      {
1458
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) ( unicode_character - 0x0d60 );
1459
0
      }
1460
0
      else if( ( unicode_character >= 0x0e3f )
1461
0
            && ( unicode_character < 0x0e5c ) )
1462
0
      {
1463
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) ( unicode_character - 0x0d60 );
1464
0
      }
1465
0
      else
1466
0
      {
1467
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
1468
0
      }
1469
0
      safe_byte_stream_index += 1;
1470
1471
0
      break;
1472
1473
0
    case LIBUNA_CODEPAGE_ISO_8859_13:
1474
0
      if( unicode_character < 0x00a0 )
1475
0
      {
1476
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1477
0
      }
1478
0
      else if( ( unicode_character >= 0x00a0 )
1479
0
            && ( unicode_character < 0x0180 ) )
1480
0
      {
1481
0
        unicode_character -= 0x00a0;
1482
1483
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_13_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1484
0
      }
1485
0
      else if( ( unicode_character >= 0x2018 )
1486
0
             && ( unicode_character < 0x2020 ) )
1487
0
      {
1488
0
        unicode_character -= 0x2018;
1489
1490
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_13_unicode_to_byte_stream_base_0x2018[ unicode_character ];
1491
0
      }
1492
0
      else
1493
0
      {
1494
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
1495
0
      }
1496
0
      safe_byte_stream_index += 1;
1497
1498
0
      break;
1499
1500
0
    case LIBUNA_CODEPAGE_ISO_8859_14:
1501
0
      if( unicode_character < 0x00a1 )
1502
0
      {
1503
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1504
0
      }
1505
0
      else if( ( unicode_character >= 0x00c0 )
1506
0
            && ( unicode_character < 0x0100 ) )
1507
0
      {
1508
0
        unicode_character -= 0x00c0;
1509
1510
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_14_unicode_to_byte_stream_base_0x00c0[ unicode_character ];
1511
0
      }
1512
0
      else if( ( unicode_character >= 0x0170 )
1513
0
            && ( unicode_character < 0x0178 ) )
1514
0
      {
1515
0
        unicode_character -= 0x0170;
1516
1517
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_14_unicode_to_byte_stream_base_0x0170[ unicode_character ];
1518
0
      }
1519
0
      else if( ( unicode_character >= 0x1e80 )
1520
0
            && ( unicode_character < 0x1e88 ) )
1521
0
      {
1522
0
        unicode_character -= 0x1e80;
1523
1524
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_14_unicode_to_byte_stream_base_0x1e80[ unicode_character ];
1525
0
      }
1526
0
      else switch( unicode_character )
1527
0
      {
1528
0
        case 0x00a3:
1529
0
          byte_stream[ safe_byte_stream_index ] = 0xa3;
1530
0
          break;
1531
1532
0
        case 0x00a7:
1533
0
          byte_stream[ safe_byte_stream_index ] = 0xa7;
1534
0
          break;
1535
1536
0
        case 0x00a9:
1537
0
          byte_stream[ safe_byte_stream_index ] = 0xa9;
1538
0
          break;
1539
1540
0
        case 0x00ad:
1541
0
          byte_stream[ safe_byte_stream_index ] = 0xad;
1542
0
          break;
1543
1544
0
        case 0x00ae:
1545
0
          byte_stream[ safe_byte_stream_index ] = 0xae;
1546
0
          break;
1547
1548
0
        case 0x00b6:
1549
0
          byte_stream[ safe_byte_stream_index ] = 0xb6;
1550
0
          break;
1551
1552
0
        case 0x010a:
1553
0
          byte_stream[ safe_byte_stream_index ] = 0xa4;
1554
0
          break;
1555
1556
0
        case 0x010b:
1557
0
          byte_stream[ safe_byte_stream_index ] = 0xa5;
1558
0
          break;
1559
1560
0
        case 0x0120:
1561
0
          byte_stream[ safe_byte_stream_index ] = 0xb2;
1562
0
          break;
1563
1564
0
        case 0x0121:
1565
0
          byte_stream[ safe_byte_stream_index ] = 0xb3;
1566
0
          break;
1567
1568
0
        case 0x0178:
1569
0
          byte_stream[ safe_byte_stream_index ] = 0xaf;
1570
0
          break;
1571
1572
0
        case 0x1e02:
1573
0
          byte_stream[ safe_byte_stream_index ] = 0xa1;
1574
0
          break;
1575
1576
0
        case 0x1e03:
1577
0
          byte_stream[ safe_byte_stream_index ] = 0xa2;
1578
0
          break;
1579
1580
0
        case 0x1e0a:
1581
0
          byte_stream[ safe_byte_stream_index ] = 0xa6;
1582
0
          break;
1583
1584
0
        case 0x1e0b:
1585
0
          byte_stream[ safe_byte_stream_index ] = 0xab;
1586
0
          break;
1587
1588
0
        case 0x1e1e:
1589
0
          byte_stream[ safe_byte_stream_index ] = 0xb0;
1590
0
          break;
1591
1592
0
        case 0x1e1f:
1593
0
          byte_stream[ safe_byte_stream_index ] = 0xb1;
1594
0
          break;
1595
1596
0
        case 0x1e40:
1597
0
          byte_stream[ safe_byte_stream_index ] = 0xb4;
1598
0
          break;
1599
1600
0
        case 0x1e41:
1601
0
          byte_stream[ safe_byte_stream_index ] = 0xb5;
1602
0
          break;
1603
1604
0
        case 0x1e56:
1605
0
          byte_stream[ safe_byte_stream_index ] = 0xb7;
1606
0
          break;
1607
1608
0
        case 0x1e57:
1609
0
          byte_stream[ safe_byte_stream_index ] = 0xb9;
1610
0
          break;
1611
1612
0
        case 0x1e60:
1613
0
          byte_stream[ safe_byte_stream_index ] = 0xbb;
1614
0
          break;
1615
1616
0
        case 0x1e61:
1617
0
          byte_stream[ safe_byte_stream_index ] = 0xbf;
1618
0
          break;
1619
1620
0
        case 0x1e6a:
1621
0
          byte_stream[ safe_byte_stream_index ] = 0xd7;
1622
0
          break;
1623
1624
0
        case 0x1e6b:
1625
0
          byte_stream[ safe_byte_stream_index ] = 0xf7;
1626
0
          break;
1627
1628
0
        case 0x1ef2:
1629
0
          byte_stream[ safe_byte_stream_index ] = 0xac;
1630
0
          break;
1631
1632
0
        case 0x1ef3:
1633
0
          byte_stream[ safe_byte_stream_index ] = 0xbc;
1634
0
          break;
1635
1636
0
        default:
1637
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1638
0
          break;
1639
0
      }
1640
0
      safe_byte_stream_index += 1;
1641
1642
0
      break;
1643
1644
0
    case LIBUNA_CODEPAGE_ISO_8859_15:
1645
0
      if( unicode_character < 0x00a0 )
1646
0
      {
1647
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1648
0
      }
1649
0
      else if( ( unicode_character >= 0x00a0 )
1650
0
            && ( unicode_character < 0x00c0 ) )
1651
0
      {
1652
0
        unicode_character -= 0x00a0;
1653
1654
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_15_unicode_to_byte_stream_base_0x00a0[ unicode_character ];
1655
0
      }
1656
0
      else if( unicode_character < 0x0100 )
1657
0
      {
1658
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1659
0
      }
1660
0
      else switch( unicode_character )
1661
0
      {
1662
0
        case 0x0152:
1663
0
          byte_stream[ safe_byte_stream_index ] = 0xbc;
1664
0
          break;
1665
1666
0
        case 0x0153:
1667
0
          byte_stream[ safe_byte_stream_index ] = 0xbd;
1668
0
          break;
1669
1670
0
        case 0x0160:
1671
0
          byte_stream[ safe_byte_stream_index ] = 0xa6;
1672
0
          break;
1673
1674
0
        case 0x0161:
1675
0
          byte_stream[ safe_byte_stream_index ] = 0xa8;
1676
0
          break;
1677
1678
0
        case 0x0178:
1679
0
          byte_stream[ safe_byte_stream_index ] = 0xbe;
1680
0
          break;
1681
1682
0
        case 0x017d:
1683
0
          byte_stream[ safe_byte_stream_index ] = 0xb4;
1684
0
          break;
1685
1686
0
        case 0x017e:
1687
0
          byte_stream[ safe_byte_stream_index ] = 0xb8;
1688
0
          break;
1689
1690
0
        case 0x20ac:
1691
0
          byte_stream[ safe_byte_stream_index ] = 0xa4;
1692
0
          break;
1693
1694
0
        default:
1695
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1696
0
          break;
1697
0
      }
1698
0
      safe_byte_stream_index += 1;
1699
1700
0
      break;
1701
1702
0
    case LIBUNA_CODEPAGE_ISO_8859_16:
1703
0
      if( unicode_character < 0x00a1 )
1704
0
      {
1705
0
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
1706
0
      }
1707
0
      else if( ( unicode_character >= 0x00a8 )
1708
0
            && ( unicode_character < 0x0108 ) )
1709
0
      {
1710
0
        unicode_character -= 0x00a8;
1711
1712
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_16_unicode_to_byte_stream_base_0x00a8[ unicode_character ];
1713
0
      }
1714
0
      else if( ( unicode_character >= 0x0140 )
1715
0
            && ( unicode_character < 0x0148 ) )
1716
0
      {
1717
0
        unicode_character -= 0x0140;
1718
1719
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_16_unicode_to_byte_stream_base_0x0140[ unicode_character ];
1720
0
      }
1721
0
      else if( ( unicode_character >= 0x0150 )
1722
0
            && ( unicode_character < 0x0158 ) )
1723
0
      {
1724
0
        unicode_character -= 0x0150;
1725
1726
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_16_unicode_to_byte_stream_base_0x0150[ unicode_character ];
1727
0
      }
1728
0
      else if( ( unicode_character >= 0x0178 )
1729
0
            && ( unicode_character < 0x0180 ) )
1730
0
      {
1731
0
        unicode_character -= 0x0178;
1732
1733
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_16_unicode_to_byte_stream_base_0x0178[ unicode_character ];
1734
0
      }
1735
0
      else if( ( unicode_character >= 0x0218 )
1736
0
            && ( unicode_character < 0x0220 ) )
1737
0
      {
1738
0
        unicode_character -= 0x0218;
1739
1740
0
        byte_stream[ safe_byte_stream_index ] = libuna_codepage_iso_8859_16_unicode_to_byte_stream_base_0x0218[ unicode_character ];
1741
0
      }
1742
0
      else switch( unicode_character )
1743
0
      {
1744
0
        case 0x00a7:
1745
0
          byte_stream[ safe_byte_stream_index ] = 0xa7;
1746
0
          break;
1747
1748
0
        case 0x010c:
1749
0
          byte_stream[ safe_byte_stream_index ] = 0xb2;
1750
0
          break;
1751
1752
0
        case 0x010d:
1753
0
          byte_stream[ safe_byte_stream_index ] = 0xb9;
1754
0
          break;
1755
1756
0
        case 0x0110:
1757
0
          byte_stream[ safe_byte_stream_index ] = 0xd0;
1758
0
          break;
1759
1760
0
        case 0x0111:
1761
0
          byte_stream[ safe_byte_stream_index ] = 0xf0;
1762
0
          break;
1763
1764
0
        case 0x0118:
1765
0
          byte_stream[ safe_byte_stream_index ] = 0xdd;
1766
0
          break;
1767
1768
0
        case 0x0119:
1769
0
          byte_stream[ safe_byte_stream_index ] = 0xfd;
1770
0
          break;
1771
1772
0
        case 0x015a:
1773
0
          byte_stream[ safe_byte_stream_index ] = 0xd7;
1774
0
          break;
1775
1776
0
        case 0x015b:
1777
0
          byte_stream[ safe_byte_stream_index ] = 0xf7;
1778
0
          break;
1779
1780
0
        case 0x0160:
1781
0
          byte_stream[ safe_byte_stream_index ] = 0xa6;
1782
0
          break;
1783
1784
0
        case 0x0161:
1785
0
          byte_stream[ safe_byte_stream_index ] = 0xa8;
1786
0
          break;
1787
1788
0
        case 0x0170:
1789
0
          byte_stream[ safe_byte_stream_index ] = 0xd8;
1790
0
          break;
1791
1792
0
        case 0x0171:
1793
0
          byte_stream[ safe_byte_stream_index ] = 0xf8;
1794
0
          break;
1795
1796
0
        case 0x201d:
1797
0
          byte_stream[ safe_byte_stream_index ] = 0xb5;
1798
0
          break;
1799
1800
0
        case 0x201e:
1801
0
          byte_stream[ safe_byte_stream_index ] = 0xa5;
1802
0
          break;
1803
1804
0
        case 0x20ac:
1805
0
          byte_stream[ safe_byte_stream_index ] = 0xa4;
1806
0
          break;
1807
1808
0
        default:
1809
0
          byte_stream[ safe_byte_stream_index ] = 0x1a;
1810
0
          break;
1811
0
      }
1812
0
      safe_byte_stream_index += 1;
1813
1814
0
      break;
1815
1816
0
    case LIBUNA_CODEPAGE_KOI8_R:
1817
0
      result = libuna_codepage_koi8_r_copy_to_byte_stream(
1818
0
                unicode_character,
1819
0
                byte_stream,
1820
0
                byte_stream_size,
1821
0
                &safe_byte_stream_index,
1822
0
                error );
1823
0
      break;
1824
1825
0
    case LIBUNA_CODEPAGE_KOI8_U:
1826
0
      result = libuna_codepage_koi8_u_copy_to_byte_stream(
1827
0
                unicode_character,
1828
0
                byte_stream,
1829
0
                byte_stream_size,
1830
0
                &safe_byte_stream_index,
1831
0
                error );
1832
0
      break;
1833
1834
0
    case LIBUNA_CODEPAGE_MAC_ARABIC:
1835
0
      result = libuna_codepage_mac_arabic_copy_to_byte_stream(
1836
0
                unicode_character,
1837
0
                byte_stream,
1838
0
                byte_stream_size,
1839
0
                &safe_byte_stream_index,
1840
0
                error );
1841
0
      break;
1842
1843
0
    case LIBUNA_CODEPAGE_MAC_CELTIC:
1844
0
      result = libuna_codepage_mac_celtic_copy_to_byte_stream(
1845
0
                unicode_character,
1846
0
                byte_stream,
1847
0
                byte_stream_size,
1848
0
                &safe_byte_stream_index,
1849
0
                error );
1850
0
      break;
1851
1852
0
    case LIBUNA_CODEPAGE_MAC_CENTRALEURROMAN:
1853
0
      result = libuna_codepage_mac_centraleurroman_copy_to_byte_stream(
1854
0
                unicode_character,
1855
0
                byte_stream,
1856
0
                byte_stream_size,
1857
0
                &safe_byte_stream_index,
1858
0
                error );
1859
0
      break;
1860
1861
0
    case LIBUNA_CODEPAGE_MAC_CROATIAN:
1862
0
      result = libuna_codepage_mac_croatian_copy_to_byte_stream(
1863
0
                unicode_character,
1864
0
                byte_stream,
1865
0
                byte_stream_size,
1866
0
                &safe_byte_stream_index,
1867
0
                error );
1868
0
      break;
1869
1870
0
    case LIBUNA_CODEPAGE_MAC_CYRILLIC:
1871
0
      result = libuna_codepage_mac_cyrillic_copy_to_byte_stream(
1872
0
                unicode_character,
1873
0
                byte_stream,
1874
0
                byte_stream_size,
1875
0
                &safe_byte_stream_index,
1876
0
                error );
1877
0
      break;
1878
1879
0
    case LIBUNA_CODEPAGE_MAC_DINGBATS:
1880
0
      result = libuna_codepage_mac_dingbats_copy_to_byte_stream(
1881
0
                unicode_character,
1882
0
                byte_stream,
1883
0
                byte_stream_size,
1884
0
                &safe_byte_stream_index,
1885
0
                error );
1886
0
      break;
1887
1888
0
    case LIBUNA_CODEPAGE_MAC_FARSI:
1889
0
      result = libuna_codepage_mac_farsi_copy_to_byte_stream(
1890
0
                unicode_character,
1891
0
                byte_stream,
1892
0
                byte_stream_size,
1893
0
                &safe_byte_stream_index,
1894
0
                error );
1895
0
      break;
1896
1897
0
    case LIBUNA_CODEPAGE_MAC_GAELIC:
1898
0
      result = libuna_codepage_mac_gaelic_copy_to_byte_stream(
1899
0
                unicode_character,
1900
0
                byte_stream,
1901
0
                byte_stream_size,
1902
0
                &safe_byte_stream_index,
1903
0
                error );
1904
0
      break;
1905
1906
0
    case LIBUNA_CODEPAGE_MAC_GREEK:
1907
0
      result = libuna_codepage_mac_greek_copy_to_byte_stream(
1908
0
                unicode_character,
1909
0
                byte_stream,
1910
0
                byte_stream_size,
1911
0
                &safe_byte_stream_index,
1912
0
                error );
1913
0
      break;
1914
1915
0
    case LIBUNA_CODEPAGE_MAC_ICELANDIC:
1916
0
      result = libuna_codepage_mac_icelandic_copy_to_byte_stream(
1917
0
                unicode_character,
1918
0
                byte_stream,
1919
0
                byte_stream_size,
1920
0
                &safe_byte_stream_index,
1921
0
                error );
1922
0
      break;
1923
1924
0
    case LIBUNA_CODEPAGE_MAC_INUIT:
1925
0
      result = libuna_codepage_mac_inuit_copy_to_byte_stream(
1926
0
                unicode_character,
1927
0
                byte_stream,
1928
0
                byte_stream_size,
1929
0
                &safe_byte_stream_index,
1930
0
                error );
1931
0
      break;
1932
1933
0
    case LIBUNA_CODEPAGE_MAC_ROMAN:
1934
0
      result = libuna_codepage_mac_roman_copy_to_byte_stream(
1935
0
                unicode_character,
1936
0
                byte_stream,
1937
0
                byte_stream_size,
1938
0
                &safe_byte_stream_index,
1939
0
                error );
1940
0
      break;
1941
1942
0
    case LIBUNA_CODEPAGE_MAC_ROMANIAN:
1943
0
      result = libuna_codepage_mac_romanian_copy_to_byte_stream(
1944
0
                unicode_character,
1945
0
                byte_stream,
1946
0
                byte_stream_size,
1947
0
                &safe_byte_stream_index,
1948
0
                error );
1949
0
      break;
1950
1951
0
    case LIBUNA_CODEPAGE_MAC_RUSSIAN:
1952
0
      result = libuna_codepage_mac_russian_copy_to_byte_stream(
1953
0
                unicode_character,
1954
0
                byte_stream,
1955
0
                byte_stream_size,
1956
0
                &safe_byte_stream_index,
1957
0
                error );
1958
0
      break;
1959
1960
0
    case LIBUNA_CODEPAGE_MAC_SYMBOL:
1961
0
      result = libuna_codepage_mac_symbol_copy_to_byte_stream(
1962
0
                unicode_character,
1963
0
                byte_stream,
1964
0
                byte_stream_size,
1965
0
                &safe_byte_stream_index,
1966
0
                error );
1967
0
      break;
1968
1969
0
    case LIBUNA_CODEPAGE_MAC_THAI:
1970
0
      result = libuna_codepage_mac_thai_copy_to_byte_stream(
1971
0
                unicode_character,
1972
0
                byte_stream,
1973
0
                byte_stream_size,
1974
0
                &safe_byte_stream_index,
1975
0
                error );
1976
0
      break;
1977
1978
0
    case LIBUNA_CODEPAGE_MAC_TURKISH:
1979
0
      result = libuna_codepage_mac_turkish_copy_to_byte_stream(
1980
0
                unicode_character,
1981
0
                byte_stream,
1982
0
                byte_stream_size,
1983
0
                &safe_byte_stream_index,
1984
0
                error );
1985
0
      break;
1986
1987
0
    case LIBUNA_CODEPAGE_MAC_UKRAINIAN:
1988
0
      result = libuna_codepage_mac_ukrainian_copy_to_byte_stream(
1989
0
                unicode_character,
1990
0
                byte_stream,
1991
0
                byte_stream_size,
1992
0
                &safe_byte_stream_index,
1993
0
                error );
1994
0
      break;
1995
1996
0
    case LIBUNA_CODEPAGE_WINDOWS_874:
1997
0
      result = libuna_codepage_windows_874_copy_to_byte_stream(
1998
0
                unicode_character,
1999
0
                byte_stream,
2000
0
                byte_stream_size,
2001
0
                &safe_byte_stream_index,
2002
0
                error );
2003
0
      break;
2004
2005
0
    case LIBUNA_CODEPAGE_WINDOWS_932:
2006
0
      result = libuna_codepage_windows_932_copy_to_byte_stream(
2007
0
                unicode_character,
2008
0
                byte_stream,
2009
0
                byte_stream_size,
2010
0
                &safe_byte_stream_index,
2011
0
                error );
2012
0
      break;
2013
2014
0
    case LIBUNA_CODEPAGE_WINDOWS_936:
2015
0
      result = libuna_codepage_windows_936_copy_to_byte_stream(
2016
0
                unicode_character,
2017
0
                byte_stream,
2018
0
                byte_stream_size,
2019
0
                &safe_byte_stream_index,
2020
0
                error );
2021
0
      break;
2022
2023
0
    case LIBUNA_CODEPAGE_WINDOWS_949:
2024
0
      result = libuna_codepage_windows_949_copy_to_byte_stream(
2025
0
                unicode_character,
2026
0
                byte_stream,
2027
0
                byte_stream_size,
2028
0
                &safe_byte_stream_index,
2029
0
                error );
2030
0
      break;
2031
2032
0
    case LIBUNA_CODEPAGE_WINDOWS_950:
2033
0
      result = libuna_codepage_windows_950_copy_to_byte_stream(
2034
0
                unicode_character,
2035
0
                byte_stream,
2036
0
                byte_stream_size,
2037
0
                &safe_byte_stream_index,
2038
0
                error );
2039
0
      break;
2040
2041
0
    case LIBUNA_CODEPAGE_WINDOWS_1250:
2042
0
      result = libuna_codepage_windows_1250_copy_to_byte_stream(
2043
0
                unicode_character,
2044
0
                byte_stream,
2045
0
                byte_stream_size,
2046
0
                &safe_byte_stream_index,
2047
0
                error );
2048
0
      break;
2049
2050
0
    case LIBUNA_CODEPAGE_WINDOWS_1251:
2051
0
      result = libuna_codepage_windows_1251_copy_to_byte_stream(
2052
0
                unicode_character,
2053
0
                byte_stream,
2054
0
                byte_stream_size,
2055
0
                &safe_byte_stream_index,
2056
0
                error );
2057
0
      break;
2058
2059
0
    case LIBUNA_CODEPAGE_WINDOWS_1252:
2060
0
      result = libuna_codepage_windows_1252_copy_to_byte_stream(
2061
0
                unicode_character,
2062
0
                byte_stream,
2063
0
                byte_stream_size,
2064
0
                &safe_byte_stream_index,
2065
0
                error );
2066
0
      break;
2067
2068
0
    case LIBUNA_CODEPAGE_WINDOWS_1253:
2069
0
      result = libuna_codepage_windows_1253_copy_to_byte_stream(
2070
0
                unicode_character,
2071
0
                byte_stream,
2072
0
                byte_stream_size,
2073
0
                &safe_byte_stream_index,
2074
0
                error );
2075
0
      break;
2076
2077
0
    case LIBUNA_CODEPAGE_WINDOWS_1254:
2078
0
      result = libuna_codepage_windows_1254_copy_to_byte_stream(
2079
0
                unicode_character,
2080
0
                byte_stream,
2081
0
                byte_stream_size,
2082
0
                &safe_byte_stream_index,
2083
0
                error );
2084
0
      break;
2085
2086
0
    case LIBUNA_CODEPAGE_WINDOWS_1255:
2087
0
      result = libuna_codepage_windows_1255_copy_to_byte_stream(
2088
0
                unicode_character,
2089
0
                byte_stream,
2090
0
                byte_stream_size,
2091
0
                &safe_byte_stream_index,
2092
0
                error );
2093
0
      break;
2094
2095
0
    case LIBUNA_CODEPAGE_WINDOWS_1256:
2096
0
      result = libuna_codepage_windows_1256_copy_to_byte_stream(
2097
0
                unicode_character,
2098
0
                byte_stream,
2099
0
                byte_stream_size,
2100
0
                &safe_byte_stream_index,
2101
0
                error );
2102
0
      break;
2103
2104
0
    case LIBUNA_CODEPAGE_WINDOWS_1257:
2105
0
      result = libuna_codepage_windows_1257_copy_to_byte_stream(
2106
0
                unicode_character,
2107
0
                byte_stream,
2108
0
                byte_stream_size,
2109
0
                &safe_byte_stream_index,
2110
0
                error );
2111
0
      break;
2112
2113
0
    case LIBUNA_CODEPAGE_WINDOWS_1258:
2114
0
      result = libuna_codepage_windows_1258_copy_to_byte_stream(
2115
0
                unicode_character,
2116
0
                byte_stream,
2117
0
                byte_stream_size,
2118
0
                &safe_byte_stream_index,
2119
0
                error );
2120
0
      break;
2121
2122
0
    default:
2123
0
      libcerror_error_set(
2124
0
       error,
2125
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2126
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2127
0
      "%s: unsupported codepage: %d.",
2128
0
       function,
2129
0
             codepage );
2130
2131
0
      return( -1 );
2132
12.2k
  }
2133
12.2k
  if( result == -1 )
2134
0
  {
2135
0
    libcerror_error_set(
2136
0
     error,
2137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2138
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2139
0
     "%s: unable to copy Unicode character to byte stream.",
2140
0
     function );
2141
2142
0
    return( -1 );
2143
0
  }
2144
12.2k
  *byte_stream_index = safe_byte_stream_index;
2145
2146
12.2k
  return( result );
2147
12.2k
}
2148
2149
/* Determines the size of an UCS-2 character from an Unicode character
2150
 * Adds the size to the UCS-2 character size value
2151
 * Returns 1 if successful or -1 on error
2152
 */
2153
int libuna_unicode_character_size_to_ucs2(
2154
     libuna_unicode_character_t unicode_character,
2155
     size_t *ucs2_character_size,
2156
     libcerror_error_t **error )
2157
1.63k
{
2158
1.63k
  static char *function = "libuna_unicode_character_size_to_ucs2";
2159
2160
1.63k
  if( ucs2_character_size == NULL )
2161
0
  {
2162
0
    libcerror_error_set(
2163
0
     error,
2164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2166
0
     "%s: invalid UCS-2 character size.",
2167
0
     function );
2168
2169
0
    return( -1 );
2170
0
  }
2171
  /* Determine if the Unicode character is valid
2172
   * UCS-2 with surrogate pairs supports upto 0x10ffff characters
2173
   */
2174
1.63k
  if( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
2175
0
  {
2176
0
    libcerror_error_set(
2177
0
     error,
2178
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2179
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2180
0
     "%s: unsupported Unicode character.",
2181
0
     function );
2182
2183
0
    return( -1 );
2184
0
  }
2185
1.63k
  if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
2186
8
  {
2187
8
    *ucs2_character_size += 2;
2188
8
  }
2189
1.62k
  else
2190
1.62k
  {
2191
1.62k
    *ucs2_character_size += 1;
2192
1.62k
  }
2193
1.63k
  return( 1 );
2194
1.63k
}
2195
2196
/* Copies an Unicode character from an UCS-2 string
2197
 * Returns 1 if successful or -1 on error
2198
 */
2199
int libuna_unicode_character_copy_from_ucs2(
2200
     libuna_unicode_character_t *unicode_character,
2201
     const libuna_utf16_character_t *ucs2_string,
2202
     size_t ucs2_string_size,
2203
     size_t *ucs2_string_index,
2204
     libcerror_error_t **error )
2205
0
{
2206
0
  static char *function                             = "libuna_unicode_character_copy_from_ucs2";
2207
0
  libuna_utf16_character_t ucs2_surrogate           = 0;
2208
0
  libuna_unicode_character_t safe_unicode_character = 0;
2209
0
  size_t safe_ucs2_string_index                     = 0;
2210
2211
0
  if( unicode_character == NULL )
2212
0
  {
2213
0
    libcerror_error_set(
2214
0
     error,
2215
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2216
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2217
0
     "%s: invalid Unicode character.",
2218
0
     function );
2219
2220
0
    return( -1 );
2221
0
  }
2222
0
  if( ucs2_string == NULL )
2223
0
  {
2224
0
    libcerror_error_set(
2225
0
     error,
2226
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2227
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2228
0
     "%s: invalid UCS-2 string.",
2229
0
     function );
2230
2231
0
    return( -1 );
2232
0
  }
2233
0
  if( ucs2_string_size > (size_t) SSIZE_MAX )
2234
0
  {
2235
0
    libcerror_error_set(
2236
0
     error,
2237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2238
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2239
0
     "%s: invalid UCS-2 string size value exceeds maximum.",
2240
0
     function );
2241
2242
0
    return( -1 );
2243
0
  }
2244
0
  if( ucs2_string_index == NULL )
2245
0
  {
2246
0
    libcerror_error_set(
2247
0
     error,
2248
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2249
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2250
0
     "%s: invalid UCS-2 string index.",
2251
0
     function );
2252
2253
0
    return( -1 );
2254
0
  }
2255
0
  safe_ucs2_string_index = *ucs2_string_index;
2256
2257
0
  if( safe_ucs2_string_index >= ucs2_string_size )
2258
0
  {
2259
0
    libcerror_error_set(
2260
0
     error,
2261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2262
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2263
0
     "%s: UCS-2 string too small.",
2264
0
     function );
2265
2266
0
    return( -1 );
2267
0
  }
2268
0
  safe_unicode_character  = ucs2_string[ safe_ucs2_string_index ];
2269
0
  safe_ucs2_string_index += 1;
2270
2271
  /* Determine if the UCS-2 character is within the high surrogate range
2272
   */
2273
0
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
2274
0
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
2275
0
  {
2276
0
    if( safe_ucs2_string_index >= ucs2_string_size )
2277
0
    {
2278
0
      libcerror_error_set(
2279
0
       error,
2280
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2281
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2282
0
       "%s: missing surrogate UCS-2 character bytes.",
2283
0
       function );
2284
2285
0
      return( -1 );
2286
0
    }
2287
0
    ucs2_surrogate = ucs2_string[ safe_ucs2_string_index ];
2288
2289
    /* Determine if the UCS-2 character is within the low surrogate range
2290
     */
2291
0
    if( ( ucs2_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
2292
0
     && ( ucs2_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
2293
0
    {
2294
0
      safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
2295
0
      safe_unicode_character <<= 10;
2296
0
      safe_unicode_character  += ucs2_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
2297
0
      safe_unicode_character  += 0x010000;
2298
2299
0
      safe_ucs2_string_index += 1;
2300
0
    }
2301
0
  }
2302
  /* Determine if the Unicode character is valid
2303
   * UCS-2 with surrogate pairs supports upto 0x10ffff characters
2304
   */
2305
0
  if( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
2306
0
  {
2307
0
    libcerror_error_set(
2308
0
     error,
2309
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2310
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2311
0
     "%s: unsupported Unicode character.",
2312
0
     function );
2313
2314
0
    return( -1 );
2315
0
  }
2316
0
  *unicode_character = safe_unicode_character;
2317
0
  *ucs2_string_index = safe_ucs2_string_index;
2318
2319
0
  return( 1 );
2320
0
}
2321
2322
/* Copies an Unicode character into a UCS-2 string
2323
 * Returns 1 if successful or -1 on error
2324
 */
2325
int libuna_unicode_character_copy_to_ucs2(
2326
     libuna_unicode_character_t unicode_character,
2327
     libuna_utf16_character_t *ucs2_string,
2328
     size_t ucs2_string_size,
2329
     size_t *ucs2_string_index,
2330
     libcerror_error_t **error )
2331
0
{
2332
0
  static char *function         = "libuna_unicode_character_copy_to_ucs2";
2333
0
  size_t safe_ucs2_string_index = 0;
2334
2335
0
  if( ucs2_string == NULL )
2336
0
  {
2337
0
    libcerror_error_set(
2338
0
     error,
2339
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2340
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2341
0
     "%s: invalid UCS-2 string.",
2342
0
     function );
2343
2344
0
    return( -1 );
2345
0
  }
2346
0
  if( ucs2_string_size > (size_t) SSIZE_MAX )
2347
0
  {
2348
0
    libcerror_error_set(
2349
0
     error,
2350
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2351
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2352
0
     "%s: invalid UCS-2 string size value exceeds maximum.",
2353
0
     function );
2354
2355
0
    return( -1 );
2356
0
  }
2357
0
  if( ucs2_string_index == NULL )
2358
0
  {
2359
0
    libcerror_error_set(
2360
0
     error,
2361
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2362
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2363
0
     "%s: invalid UCS-2 string index.",
2364
0
     function );
2365
2366
0
    return( -1 );
2367
0
  }
2368
0
  safe_ucs2_string_index = *ucs2_string_index;
2369
2370
0
  if( safe_ucs2_string_index >= ucs2_string_size )
2371
0
  {
2372
0
    libcerror_error_set(
2373
0
     error,
2374
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2375
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2376
0
     "%s: UCS-2 string too small.",
2377
0
     function );
2378
2379
0
    return( -1 );
2380
0
  }
2381
  /* Determine if the Unicode character is valid
2382
   */
2383
0
  if( unicode_character > LIBUNA_UCS_CHARACTER_MAX )
2384
0
  {
2385
0
    libcerror_error_set(
2386
0
     error,
2387
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2388
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2389
0
     "%s: unsupported Unicode character.",
2390
0
     function );
2391
2392
0
    return( -1 );
2393
0
  }
2394
0
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
2395
0
  {
2396
0
    ucs2_string[ safe_ucs2_string_index++ ] = (libuna_utf16_character_t) unicode_character;
2397
0
  }
2398
0
  else
2399
0
  {
2400
0
    if( ( ucs2_string_size < 2 )
2401
0
     || ( safe_ucs2_string_index > ( ucs2_string_size - 2 ) ) )
2402
0
    {
2403
0
      libcerror_error_set(
2404
0
       error,
2405
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2406
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2407
0
       "%s: UCS-2 string too small.",
2408
0
       function );
2409
2410
0
      return( -1 );
2411
0
    }
2412
0
    unicode_character                      -= 0x010000;
2413
0
    ucs2_string[ safe_ucs2_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
2414
0
    ucs2_string[ safe_ucs2_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
2415
0
  }
2416
0
  *ucs2_string_index = safe_ucs2_string_index;
2417
2418
0
  return( 1 );
2419
0
}
2420
2421
/* Determines the size of an UCS-4 character from an Unicode character
2422
 * Adds the size to the UCS-4 character size value
2423
 * Returns 1 if successful or -1 on error
2424
 */
2425
int libuna_unicode_character_size_to_ucs4(
2426
     libuna_unicode_character_t unicode_character,
2427
     size_t *ucs4_character_size,
2428
     libcerror_error_t **error )
2429
0
{
2430
0
  static char *function = "libuna_unicode_character_size_to_ucs4";
2431
2432
0
  LIBUNA_UNREFERENCED_PARAMETER( unicode_character )
2433
2434
0
  if( ucs4_character_size == NULL )
2435
0
  {
2436
0
    libcerror_error_set(
2437
0
     error,
2438
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2439
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2440
0
     "%s: invalid UCS-4 character size.",
2441
0
     function );
2442
2443
0
    return( -1 );
2444
0
  }
2445
0
  if( unicode_character > LIBUNA_UCS_CHARACTER_MAX )
2446
0
  {
2447
0
    libcerror_error_set(
2448
0
     error,
2449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2450
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2451
0
     "%s: unsupported Unicode character.",
2452
0
     function );
2453
2454
0
    return( -1 );
2455
0
  }
2456
0
  *ucs4_character_size += 1;
2457
2458
0
  return( 1 );
2459
0
}
2460
2461
/* Copies an Unicode character from an UCS-4 string
2462
 * Returns 1 if successful or -1 on error
2463
 */
2464
int libuna_unicode_character_copy_from_ucs4(
2465
     libuna_unicode_character_t *unicode_character,
2466
     const libuna_utf32_character_t *ucs4_string,
2467
     size_t ucs4_string_size,
2468
     size_t *ucs4_string_index,
2469
     libcerror_error_t **error )
2470
0
{
2471
0
  static char *function                             = "libuna_unicode_character_copy_from_ucs4";
2472
0
  libuna_unicode_character_t safe_unicode_character = 0;
2473
0
  size_t safe_ucs4_string_index                     = 0;
2474
2475
0
  if( unicode_character == NULL )
2476
0
  {
2477
0
    libcerror_error_set(
2478
0
     error,
2479
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2480
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2481
0
     "%s: invalid Unicode character.",
2482
0
     function );
2483
2484
0
    return( -1 );
2485
0
  }
2486
0
  if( ucs4_string == NULL )
2487
0
  {
2488
0
    libcerror_error_set(
2489
0
     error,
2490
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2491
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2492
0
     "%s: invalid UCS-4 string.",
2493
0
     function );
2494
2495
0
    return( -1 );
2496
0
  }
2497
0
  if( ucs4_string_size > (size_t) SSIZE_MAX )
2498
0
  {
2499
0
    libcerror_error_set(
2500
0
     error,
2501
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2502
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2503
0
     "%s: invalid UCS-4 string size value exceeds maximum.",
2504
0
     function );
2505
2506
0
    return( -1 );
2507
0
  }
2508
0
  if( ucs4_string_index == NULL )
2509
0
  {
2510
0
    libcerror_error_set(
2511
0
     error,
2512
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2513
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2514
0
     "%s: invalid UCS-4 string index.",
2515
0
     function );
2516
2517
0
    return( -1 );
2518
0
  }
2519
0
  safe_ucs4_string_index = *ucs4_string_index;
2520
2521
0
  if( safe_ucs4_string_index >= ucs4_string_size )
2522
0
  {
2523
0
    libcerror_error_set(
2524
0
     error,
2525
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2526
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2527
0
     "%s: UCS-4 string too small.",
2528
0
     function );
2529
2530
0
    return( -1 );
2531
0
  }
2532
0
  safe_unicode_character = ucs4_string[ safe_ucs4_string_index ];
2533
2534
  /* Determine if the Unicode character is valid
2535
   */
2536
0
  if( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
2537
0
  {
2538
0
    libcerror_error_set(
2539
0
     error,
2540
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2541
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2542
0
     "%s: unsupported Unicode character.",
2543
0
     function );
2544
2545
0
    return( -1 );
2546
0
  }
2547
0
  *unicode_character = safe_unicode_character;
2548
0
  *ucs4_string_index = safe_ucs4_string_index + 1;
2549
2550
0
  return( 1 );
2551
0
}
2552
2553
/* Copies an Unicode character into a UCS-4 string
2554
 * Returns 1 if successful or -1 on error
2555
 */
2556
int libuna_unicode_character_copy_to_ucs4(
2557
     libuna_unicode_character_t unicode_character,
2558
     libuna_utf32_character_t *ucs4_string,
2559
     size_t ucs4_string_size,
2560
     size_t *ucs4_string_index,
2561
     libcerror_error_t **error )
2562
0
{
2563
0
  static char *function         = "libuna_unicode_character_copy_to_ucs4";
2564
0
  size_t safe_ucs4_string_index = 0;
2565
2566
0
  if( ucs4_string == NULL )
2567
0
  {
2568
0
    libcerror_error_set(
2569
0
     error,
2570
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2571
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2572
0
     "%s: invalid UCS-4 string.",
2573
0
     function );
2574
2575
0
    return( -1 );
2576
0
  }
2577
0
  if( ucs4_string_size > (size_t) SSIZE_MAX )
2578
0
  {
2579
0
    libcerror_error_set(
2580
0
     error,
2581
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2582
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2583
0
     "%s: invalid UCS-4 string size value exceeds maximum.",
2584
0
     function );
2585
2586
0
    return( -1 );
2587
0
  }
2588
0
  if( ucs4_string_index == NULL )
2589
0
  {
2590
0
    libcerror_error_set(
2591
0
     error,
2592
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2593
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2594
0
     "%s: invalid UCS-4 string index.",
2595
0
     function );
2596
2597
0
    return( -1 );
2598
0
  }
2599
0
  safe_ucs4_string_index = *ucs4_string_index;
2600
2601
0
  if( safe_ucs4_string_index >= ucs4_string_size )
2602
0
  {
2603
0
    libcerror_error_set(
2604
0
     error,
2605
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2606
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2607
0
     "%s: UCS-4 string too small.",
2608
0
     function );
2609
2610
0
    return( -1 );
2611
0
  }
2612
  /* Determine if the Unicode character is valid
2613
   */
2614
0
  if( unicode_character > LIBUNA_UCS_CHARACTER_MAX )
2615
0
  {
2616
0
    libcerror_error_set(
2617
0
     error,
2618
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2619
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2620
0
     "%s: unsupported Unicode character.",
2621
0
     function );
2622
2623
0
    return( -1 );
2624
0
  }
2625
0
  ucs4_string[ safe_ucs4_string_index ] = (libuna_utf32_character_t) unicode_character;
2626
2627
0
  *ucs4_string_index = safe_ucs4_string_index + 1;
2628
2629
0
  return( 1 );
2630
0
}
2631
2632
/* Determines the size of an UTF-7 stream character from an Unicode character
2633
 * Adds the size to the UTF-7 stream character size value
2634
 * Returns 1 if successful or -1 on error
2635
 */
2636
int libuna_unicode_character_size_to_utf7_stream(
2637
     libuna_unicode_character_t unicode_character,
2638
     size_t *utf7_stream_character_size,
2639
     uint32_t *utf7_stream_base64_data,
2640
     libcerror_error_t **error )
2641
0
{
2642
0
  static char *function                    = "libuna_unicode_character_size_to_utf7_stream";
2643
0
  libuna_utf16_character_t utf16_surrogate = 0;
2644
0
  size_t safe_utf7_stream_character_size   = 0;
2645
0
  uint32_t base64_triplet                  = 0;
2646
0
  uint32_t safe_utf7_stream_base64_data    = 0;
2647
0
  uint8_t base64_encode_character          = 0;
2648
0
  uint8_t byte_bit_shift                   = 0;
2649
0
  uint8_t current_byte                     = 0;
2650
0
  uint8_t number_of_bytes                  = 0;
2651
2652
0
  if( utf7_stream_character_size == NULL )
2653
0
  {
2654
0
    libcerror_error_set(
2655
0
     error,
2656
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2657
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2658
0
     "%s: invalid UTF-7 stream character size.",
2659
0
     function );
2660
2661
0
    return( -1 );
2662
0
  }
2663
0
  if( utf7_stream_base64_data == NULL )
2664
0
  {
2665
0
    libcerror_error_set(
2666
0
     error,
2667
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2668
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2669
0
     "%s: invalid UTF-7 stream base64 data.",
2670
0
     function );
2671
2672
0
    return( -1 );
2673
0
  }
2674
0
  safe_utf7_stream_character_size = *utf7_stream_character_size;
2675
0
  safe_utf7_stream_base64_data    = *utf7_stream_base64_data;
2676
2677
  /* Determine if the Unicode character is valid
2678
   */
2679
0
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
2680
0
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
2681
0
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
2682
0
  {
2683
0
    libcerror_error_set(
2684
0
     error,
2685
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2686
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2687
0
     "%s: unsupported Unicode character.",
2688
0
     function );
2689
2690
0
    return( -1 );
2691
0
  }
2692
  /* The + character must be escaped
2693
   */
2694
0
  if( unicode_character == (libuna_unicode_character_t) '+' )
2695
0
  {
2696
0
  }
2697
  /* Allow for the end of string character
2698
   */
2699
0
  else if( unicode_character == 0 )
2700
0
  {
2701
0
  }
2702
0
  else if( ( unicode_character >= 256 )
2703
0
        || ( libuna_unicode_character_utf7_valid_directly_encoded_character[ (uint8_t) unicode_character ] == 0 ) )
2704
0
  {
2705
0
    base64_encode_character = 1;
2706
0
  }
2707
0
  if( base64_encode_character == 0 )
2708
0
  {
2709
0
    if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
2710
0
    {
2711
0
      safe_utf7_stream_base64_data = 0;
2712
0
    }
2713
0
    safe_utf7_stream_character_size += 1;
2714
2715
    /* The + character must be escaped
2716
     */
2717
0
    if( unicode_character == (libuna_unicode_character_t) '+' )
2718
0
    {
2719
0
      safe_utf7_stream_character_size += 1;
2720
0
    }
2721
0
  }
2722
0
  else
2723
0
  {
2724
    /* Escape the base64 encoded characters with a +
2725
     */
2726
0
    if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) == 0 )
2727
0
    {
2728
0
      safe_utf7_stream_character_size += 1;
2729
0
    }
2730
    /* Otherwise continue the previously base64 encoded characters
2731
     */
2732
0
    else
2733
0
    {
2734
0
      base64_triplet  = safe_utf7_stream_base64_data & 0x00ffffff;
2735
0
      number_of_bytes = ( safe_utf7_stream_base64_data >> 24 ) & 0x03;
2736
0
      current_byte    = ( safe_utf7_stream_base64_data >> 28 ) & 0x03;
2737
2738
0
      if( number_of_bytes > 0 )
2739
0
      {
2740
0
        if( safe_utf7_stream_character_size < (size_t) ( number_of_bytes + 1 ) )
2741
0
        {
2742
0
          libcerror_error_set(
2743
0
           error,
2744
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2745
0
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2746
0
           "%s: invalid UTF-7 stream character size value out of bounds.",
2747
0
           function );
2748
2749
0
          return( -1 );
2750
0
        }
2751
        /* Correct the size for the last partial base64 stream
2752
         */
2753
0
        safe_utf7_stream_character_size -= number_of_bytes + 1;
2754
0
      }
2755
0
      if( safe_utf7_stream_character_size < 1 )
2756
0
      {
2757
0
        libcerror_error_set(
2758
0
         error,
2759
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2760
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2761
0
         "%s: invalid UTF-7 stream character size value out of bounds.",
2762
0
         function );
2763
2764
0
        return( -1 );
2765
0
      }
2766
      /* Correct the size for the base64 stream termination character
2767
       */
2768
0
      safe_utf7_stream_character_size -= 1;
2769
0
    }
2770
0
    safe_utf7_stream_base64_data = LIBUNA_UTF7_IS_BASE64_ENCODED;
2771
2772
0
    if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
2773
0
    {
2774
0
      unicode_character -= 0x010000;
2775
2776
0
      utf16_surrogate = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
2777
2778
0
      byte_bit_shift   = 16 - ( current_byte * 8 );
2779
0
      base64_triplet  += (uint32_t) ( ( utf16_surrogate >> 8 ) & 0xff ) << byte_bit_shift;
2780
0
      current_byte    += 1;
2781
0
      number_of_bytes += 1;
2782
2783
0
      if( number_of_bytes == 3 )
2784
0
      {
2785
0
        safe_utf7_stream_character_size += 4;
2786
0
        number_of_bytes                  = 0;
2787
0
        current_byte                     = 0;
2788
0
        base64_triplet                   = 0;
2789
0
      }
2790
0
      byte_bit_shift   = 16 - ( current_byte * 8 );
2791
0
      base64_triplet  += (uint32_t) ( utf16_surrogate & 0xff ) << byte_bit_shift;
2792
0
      current_byte    += 1;
2793
0
      number_of_bytes += 1;
2794
2795
0
      if( number_of_bytes == 3 )
2796
0
      {
2797
0
        safe_utf7_stream_character_size += 4;
2798
0
        number_of_bytes                  = 0;
2799
0
        current_byte                     = 0;
2800
0
        base64_triplet                   = 0;
2801
0
      }
2802
0
      unicode_character = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
2803
0
    }
2804
0
    byte_bit_shift   = 16 - ( current_byte * 8 );
2805
0
    base64_triplet  += (uint32_t) ( ( unicode_character >> 8 ) & 0xff ) << byte_bit_shift;
2806
0
    current_byte    += 1;
2807
0
    number_of_bytes += 1;
2808
2809
0
    if( number_of_bytes == 3 )
2810
0
    {
2811
0
      safe_utf7_stream_character_size += 4;
2812
0
      number_of_bytes                  = 0;
2813
0
      current_byte                     = 0;
2814
0
      base64_triplet                   = 0;
2815
0
    }
2816
0
    byte_bit_shift   = 16 - ( current_byte * 8 );
2817
0
    base64_triplet  += (uint32_t) ( unicode_character & 0xff ) << byte_bit_shift;
2818
0
    current_byte    += 1;
2819
0
    number_of_bytes += 1;
2820
2821
0
    if( number_of_bytes == 3 )
2822
0
    {
2823
0
      safe_utf7_stream_character_size += 4;
2824
0
      number_of_bytes                  = 0;
2825
0
      current_byte                     = 0;
2826
0
      base64_triplet                   = 0;
2827
0
    }
2828
    /* Terminate the base64 encoded characters
2829
     */
2830
0
    if( number_of_bytes > 0 )
2831
0
    {
2832
0
      safe_utf7_stream_character_size += number_of_bytes + 1;
2833
0
    }
2834
0
    safe_utf7_stream_character_size += 1;
2835
0
  }
2836
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
2837
0
  {
2838
0
    safe_utf7_stream_base64_data  = LIBUNA_UTF7_IS_BASE64_ENCODED;
2839
0
    safe_utf7_stream_base64_data |= (uint32_t) current_byte << 28;
2840
0
    safe_utf7_stream_base64_data |= (uint32_t) number_of_bytes << 24;
2841
0
    safe_utf7_stream_base64_data |= base64_triplet & 0x00ffffff;
2842
0
  }
2843
0
  *utf7_stream_character_size = safe_utf7_stream_character_size;
2844
0
  *utf7_stream_base64_data    = safe_utf7_stream_base64_data;
2845
2846
0
  return( 1 );
2847
0
}
2848
2849
/* Copies an Unicode character from an UTF-7 stream
2850
 * The bits of the base64 data contain:
2851
 *   0 - 23 the base64 triplet
2852
 *  24 - 25 the number of bytes in the triplet
2853
 *  26 - 27 unused
2854
 *  28 - 29 the current byte
2855
 *       30 unused
2856
 *       31 flag to indicate the current UTF-7 characters are (modified) base64 encoded
2857
 *
2858
 * Returns 1 if successful or -1 on error
2859
 */
2860
int libuna_unicode_character_copy_from_utf7_stream(
2861
     libuna_unicode_character_t *unicode_character,
2862
     const uint8_t *utf7_stream,
2863
     size_t utf7_stream_size,
2864
     size_t *utf7_stream_index,
2865
     uint32_t *utf7_stream_base64_data,
2866
     libcerror_error_t **error )
2867
0
{
2868
0
  static char *function                             = "libuna_unicode_character_copy_from_utf7_stream";
2869
0
  libuna_unicode_character_t safe_unicode_character = 0;
2870
0
  libuna_utf16_character_t utf16_surrogate          = 0;
2871
0
  size_t safe_utf7_stream_index                     = 0;
2872
0
  uint32_t base64_triplet                           = 0;
2873
0
  uint32_t safe_utf7_stream_base64_data             = 0;
2874
0
  uint8_t byte_bit_shift                            = 0;
2875
0
  uint8_t current_byte                              = 0;
2876
0
  uint8_t number_of_bytes                           = 0;
2877
0
  uint8_t padding_size                              = 0;
2878
0
  uint8_t utf7_character_value                      = 0;
2879
2880
0
  if( unicode_character == NULL )
2881
0
  {
2882
0
    libcerror_error_set(
2883
0
     error,
2884
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2885
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2886
0
     "%s: invalid Unicode character.",
2887
0
     function );
2888
2889
0
    return( -1 );
2890
0
  }
2891
0
  if( utf7_stream == NULL )
2892
0
  {
2893
0
    libcerror_error_set(
2894
0
     error,
2895
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2896
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2897
0
     "%s: invalid UTF-7 stream.",
2898
0
     function );
2899
2900
0
    return( -1 );
2901
0
  }
2902
0
  if( utf7_stream_size > (size_t) SSIZE_MAX )
2903
0
  {
2904
0
    libcerror_error_set(
2905
0
     error,
2906
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2907
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2908
0
     "%s: invalid UTF-7 stream size value exceeds maximum.",
2909
0
     function );
2910
2911
0
    return( -1 );
2912
0
  }
2913
0
  if( utf7_stream_index == NULL )
2914
0
  {
2915
0
    libcerror_error_set(
2916
0
     error,
2917
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2918
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2919
0
     "%s: invalid UTF-7 stream index.",
2920
0
     function );
2921
2922
0
    return( -1 );
2923
0
  }
2924
0
  if( utf7_stream_base64_data == NULL )
2925
0
  {
2926
0
    libcerror_error_set(
2927
0
     error,
2928
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2929
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2930
0
     "%s: invalid UTF-7 base64 data.",
2931
0
     function );
2932
2933
0
    return( -1 );
2934
0
  }
2935
0
  safe_utf7_stream_index       = *utf7_stream_index;
2936
0
  safe_utf7_stream_base64_data = *utf7_stream_base64_data;
2937
2938
0
  if( safe_utf7_stream_index >= utf7_stream_size )
2939
0
  {
2940
0
    libcerror_error_set(
2941
0
     error,
2942
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2943
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
2944
0
     "%s: UTF-7 stream too small.",
2945
0
     function );
2946
2947
0
    return( -1 );
2948
0
  }
2949
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
2950
0
  {
2951
0
    base64_triplet  = safe_utf7_stream_base64_data & 0x00ffffff;
2952
0
    number_of_bytes = ( safe_utf7_stream_base64_data >> 24 ) & 0x03;
2953
0
    current_byte    = ( safe_utf7_stream_base64_data >> 28 ) & 0x03;
2954
2955
0
    if( current_byte >= number_of_bytes )
2956
0
    {
2957
0
      if( safe_utf7_stream_index >= utf7_stream_size )
2958
0
      {
2959
0
        libcerror_error_set(
2960
0
         error,
2961
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2962
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2963
0
         "%s: invalid UTF-7 stream character size value out of bounds.",
2964
0
         function );
2965
2966
0
        return( -1 );
2967
0
      }
2968
0
      utf7_character_value = utf7_stream[ safe_utf7_stream_index ];
2969
2970
      /* Any character not in the modified base64 alphabet terminates the base64 encoded sequence
2971
       */
2972
0
      if( libuna_unicode_character_utf7_valid_base64_character[ utf7_character_value ] == 0 )
2973
0
      {
2974
0
        safe_utf7_stream_base64_data = 0;
2975
0
      }
2976
0
    }
2977
0
  }
2978
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) == 0 )
2979
0
  {
2980
0
    if( safe_utf7_stream_index >= utf7_stream_size )
2981
0
    {
2982
0
      libcerror_error_set(
2983
0
       error,
2984
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2985
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2986
0
       "%s: invalid UTF-7 stream character size value out of bounds.",
2987
0
       function );
2988
2989
0
      return( -1 );
2990
0
    }
2991
0
    utf7_character_value = utf7_stream[ safe_utf7_stream_index ];
2992
2993
    /* Determine if the character is modified base64 encoded
2994
     * or a + character
2995
     */
2996
0
    if( utf7_character_value == (uint8_t) '+' )
2997
0
    {
2998
0
      if( ( safe_utf7_stream_index + 1 ) >= utf7_stream_size )
2999
0
      {
3000
0
        libcerror_error_set(
3001
0
         error,
3002
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3003
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3004
0
         "%s: invalid UTF-7 stream character size value out of bounds.",
3005
0
         function );
3006
3007
0
        return( -1 );
3008
0
      }
3009
0
      if( utf7_stream[ safe_utf7_stream_index + 1 ] != (uint8_t) '-' )
3010
0
      {
3011
0
        safe_utf7_stream_base64_data = LIBUNA_UTF7_IS_BASE64_ENCODED;
3012
3013
0
        safe_utf7_stream_index++;
3014
0
      }
3015
0
    }
3016
    /* Allow for the end of string character
3017
     */
3018
0
    else if( utf7_character_value == 0 )
3019
0
    {
3020
0
    }
3021
0
    else if( libuna_unicode_character_utf7_valid_directly_encoded_character[ utf7_character_value ] == 0 )
3022
0
    {
3023
0
      libcerror_error_set(
3024
0
       error,
3025
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3026
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3027
0
       "%s: invalid directly encoded UTF-7 character byte: 0x%02" PRIx8 ".",
3028
0
       function,
3029
0
       utf7_character_value );
3030
3031
0
      return( -1 );
3032
0
    }
3033
0
  }
3034
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) == 0 )
3035
0
  {
3036
0
    safe_unicode_character = utf7_stream[ safe_utf7_stream_index++ ];
3037
3038
0
    if( ( safe_unicode_character == (libuna_unicode_character_t) '+' )
3039
0
     && ( utf7_stream[ safe_utf7_stream_index ] == (uint8_t) '-' ) )
3040
0
    {
3041
0
      safe_utf7_stream_index++;
3042
0
    }
3043
0
  }
3044
0
  else if( ( number_of_bytes == 0 )
3045
0
        || ( current_byte >= number_of_bytes ) )
3046
0
  {
3047
0
    if( libuna_base64_triplet_copy_from_base64_stream(
3048
0
         &base64_triplet,
3049
0
         utf7_stream,
3050
0
         utf7_stream_size - 1,
3051
0
         &safe_utf7_stream_index,
3052
0
         &padding_size,
3053
0
         LIBUNA_BASE64_VARIANT_UTF7,
3054
0
         error ) != 1 )
3055
0
    {
3056
0
      libcerror_error_set(
3057
0
       error,
3058
0
       LIBCERROR_ERROR_DOMAIN_CONVERSION,
3059
0
       LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3060
0
       "%s: unable to copy base64 encoded UTF-7 characters.",
3061
0
       function );
3062
3063
0
      return( -1 );
3064
0
    }
3065
0
    if( padding_size > 2 )
3066
0
    {
3067
0
      libcerror_error_set(
3068
0
       error,
3069
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3070
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3071
0
       "%s: unsupported padding in base64 encoded UTF-7 characters.",
3072
0
       function );
3073
3074
0
      return( -1 );
3075
0
    }
3076
0
    number_of_bytes = 3 - padding_size;
3077
0
    current_byte    = 0;
3078
0
  }
3079
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
3080
0
  {
3081
0
    if( current_byte > 2 )
3082
0
    {
3083
0
      libcerror_error_set(
3084
0
       error,
3085
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3086
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3087
0
       "%s: invalid current byte index value out of bounds.",
3088
0
       function );
3089
3090
0
      return( -1 );
3091
0
    }
3092
0
    byte_bit_shift         = 16 - ( current_byte * 8 );
3093
0
    safe_unicode_character = ( ( base64_triplet >> byte_bit_shift ) & 0x000000ffUL ) << 8;
3094
0
    current_byte          += 1;
3095
3096
0
    if( current_byte >= number_of_bytes )
3097
0
    {
3098
0
      if( libuna_base64_triplet_copy_from_base64_stream(
3099
0
           &base64_triplet,
3100
0
           utf7_stream,
3101
0
           utf7_stream_size - 1,
3102
0
           &safe_utf7_stream_index,
3103
0
           &padding_size,
3104
0
           LIBUNA_BASE64_VARIANT_UTF7,
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_OUTPUT_FAILED,
3111
0
         "%s: unable to copy base64 encoded UTF-7 characters.",
3112
0
         function );
3113
3114
0
        return( -1 );
3115
0
      }
3116
0
      if( padding_size > 2 )
3117
0
      {
3118
0
        libcerror_error_set(
3119
0
         error,
3120
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3121
0
         LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3122
0
         "%s: unsupported padding in base64 encoded UTF-7 characters.",
3123
0
         function );
3124
3125
0
        return( -1 );
3126
0
      }
3127
0
      number_of_bytes = 3 - padding_size;
3128
0
      current_byte    = 0;
3129
0
    }
3130
0
    if( current_byte > 2 )
3131
0
    {
3132
0
      libcerror_error_set(
3133
0
       error,
3134
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3135
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3136
0
       "%s: invalid current byte index value out of bounds.",
3137
0
       function );
3138
3139
0
      return( -1 );
3140
0
    }
3141
0
    byte_bit_shift          = 16 - ( current_byte * 8 );
3142
0
    safe_unicode_character += ( base64_triplet >> byte_bit_shift ) & 0x000000ffUL;
3143
0
    current_byte           += 1;
3144
3145
0
    if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
3146
0
     && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
3147
0
    {
3148
0
      if( current_byte >= number_of_bytes )
3149
0
      {
3150
0
        if( libuna_base64_triplet_copy_from_base64_stream(
3151
0
             &base64_triplet,
3152
0
             utf7_stream,
3153
0
             utf7_stream_size - 1,
3154
0
             &safe_utf7_stream_index,
3155
0
             &padding_size,
3156
0
             LIBUNA_BASE64_VARIANT_UTF7,
3157
0
             error ) != 1 )
3158
0
        {
3159
0
          libcerror_error_set(
3160
0
           error,
3161
0
           LIBCERROR_ERROR_DOMAIN_CONVERSION,
3162
0
           LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
3163
0
           "%s: unable to copy base64 encoded UTF-7 characters.",
3164
0
           function );
3165
3166
0
          return( -1 );
3167
0
        }
3168
0
        if( padding_size > 2 )
3169
0
        {
3170
0
          libcerror_error_set(
3171
0
           error,
3172
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3173
0
           LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3174
0
           "%s: unsupported padding in base64 encoded UTF-7 characters.",
3175
0
           function );
3176
3177
0
          return( -1 );
3178
0
        }
3179
0
        number_of_bytes = 3 - padding_size;
3180
0
        current_byte    = 0;
3181
0
      }
3182
0
      if( current_byte > 2 )
3183
0
      {
3184
0
        libcerror_error_set(
3185
0
         error,
3186
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3187
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3188
0
         "%s: invalid current byte index value out of bounds.",
3189
0
         function );
3190
3191
0
        return( -1 );
3192
0
      }
3193
0
      byte_bit_shift  = 16 - ( current_byte * 8 );
3194
0
      utf16_surrogate = ( ( base64_triplet >> byte_bit_shift ) & 0x000000ffUL ) << 8;
3195
0
      current_byte   += 1;
3196
3197
0
      if( current_byte >= number_of_bytes )
3198
0
      {
3199
0
        if( libuna_base64_triplet_copy_from_base64_stream(
3200
0
             &base64_triplet,
3201
0
             utf7_stream,
3202
0
             utf7_stream_size - 1,
3203
0
             &safe_utf7_stream_index,
3204
0
             &padding_size,
3205
0
             LIBUNA_BASE64_VARIANT_UTF7,
3206
0
             error ) != 1 )
3207
0
        {
3208
0
          libcerror_error_set(
3209
0
           error,
3210
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3211
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3212
0
           "%s: unable to retrieve base64 encoded UTF-7 characters.",
3213
0
           function );
3214
3215
0
          return( -1 );
3216
0
        }
3217
0
        if( padding_size > 2 )
3218
0
        {
3219
0
          libcerror_error_set(
3220
0
           error,
3221
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3222
0
           LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3223
0
           "%s: unsupported padding in base64 encoded UTF-7 characters.",
3224
0
           function );
3225
3226
0
          return( -1 );
3227
0
        }
3228
0
        number_of_bytes = 3 - padding_size;
3229
0
        current_byte    = 0;
3230
0
      }
3231
0
      if( current_byte > 2 )
3232
0
      {
3233
0
        libcerror_error_set(
3234
0
         error,
3235
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3236
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3237
0
         "%s: invalid current byte index value out of bounds.",
3238
0
         function );
3239
3240
0
        return( -1 );
3241
0
      }
3242
0
      byte_bit_shift   = 16 - ( current_byte * 8 );
3243
0
      utf16_surrogate += ( base64_triplet >> byte_bit_shift ) & 0x000000ffUL;
3244
0
      current_byte    += 1;
3245
3246
      /* Determine if the UTF-16 character is within the low surrogate range
3247
       */
3248
0
      if( ( utf16_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
3249
0
       && ( utf16_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
3250
0
      {
3251
0
        safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
3252
0
        safe_unicode_character <<= 10;
3253
0
        safe_unicode_character  += utf16_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
3254
0
        safe_unicode_character  += 0x010000;
3255
0
      }
3256
0
      else
3257
0
      {
3258
0
        libcerror_error_set(
3259
0
         error,
3260
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3261
0
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3262
0
         "%s: unsupported low surrogate UTF-16 character.",
3263
0
         function );
3264
3265
0
        return( -1 );
3266
0
      }
3267
0
    }
3268
0
    if( safe_utf7_stream_index >= utf7_stream_size )
3269
0
    {
3270
0
      libcerror_error_set(
3271
0
       error,
3272
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3273
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3274
0
       "%s: UTF-7 stream too small.",
3275
0
       function );
3276
3277
0
      return( -1 );
3278
0
    }
3279
0
    if( ( current_byte >= number_of_bytes )
3280
0
     && ( utf7_stream[ safe_utf7_stream_index ] == (uint8_t) '-' ) )
3281
0
    {
3282
0
      safe_utf7_stream_base64_data = 0;
3283
3284
0
      safe_utf7_stream_index++;
3285
0
    }
3286
0
  }
3287
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
3288
0
  {
3289
0
    safe_utf7_stream_base64_data  = LIBUNA_UTF7_IS_BASE64_ENCODED;
3290
0
    safe_utf7_stream_base64_data |= (uint32_t) current_byte << 28;
3291
0
    safe_utf7_stream_base64_data |= (uint32_t) number_of_bytes << 24;
3292
0
    safe_utf7_stream_base64_data |= base64_triplet & 0x00ffffff;
3293
0
  }
3294
0
  *unicode_character       = safe_unicode_character;
3295
0
  *utf7_stream_index       = safe_utf7_stream_index;
3296
0
  *utf7_stream_base64_data = safe_utf7_stream_base64_data;
3297
3298
0
  return( 1 );
3299
0
}
3300
3301
/* Copies an Unicode character into a UTF-7 stream
3302
 * The bits of the base64 data contain:
3303
 *   0 - 23 the base64 triplet
3304
 *  24 - 25 the number of bytes in the triplet
3305
 *  26 - 27 unused
3306
 *  28 - 29 the current byte
3307
 *       30 unused
3308
 *       31 flag to indicate the current UTF-7 characters are (modified) base64 encoded
3309
 *
3310
 * Returns 1 if successful or -1 on error
3311
 */
3312
int libuna_unicode_character_copy_to_utf7_stream(
3313
     libuna_unicode_character_t unicode_character,
3314
     uint8_t *utf7_stream,
3315
     size_t utf7_stream_size,
3316
     size_t *utf7_stream_index,
3317
     uint32_t *utf7_stream_base64_data,
3318
     libcerror_error_t **error )
3319
0
{
3320
0
  static char *function                    = "libuna_unicode_character_copy_to_utf7_stream";
3321
0
  libuna_utf16_character_t utf16_surrogate = 0;
3322
0
  size_t safe_utf7_stream_index            = 0;
3323
0
  uint32_t base64_triplet                  = 0;
3324
0
  uint32_t safe_utf7_stream_base64_data    = 0;
3325
0
  uint8_t base64_encode_character          = 0;
3326
0
  uint8_t byte_bit_shift                   = 0;
3327
0
  uint8_t current_byte                     = 0;
3328
0
  uint8_t number_of_bytes                  = 0;
3329
3330
0
  if( utf7_stream == NULL )
3331
0
  {
3332
0
    libcerror_error_set(
3333
0
     error,
3334
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3335
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3336
0
     "%s: invalid UTF-7 stream.",
3337
0
     function );
3338
3339
0
    return( -1 );
3340
0
  }
3341
0
  if( utf7_stream_size > (size_t) SSIZE_MAX )
3342
0
  {
3343
0
    libcerror_error_set(
3344
0
     error,
3345
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3346
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3347
0
     "%s: invalid UTF-7 stream size value exceeds maximum.",
3348
0
     function );
3349
3350
0
    return( -1 );
3351
0
  }
3352
0
  if( utf7_stream_index == NULL )
3353
0
  {
3354
0
    libcerror_error_set(
3355
0
     error,
3356
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3357
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3358
0
     "%s: invalid UTF-7 stream index.",
3359
0
     function );
3360
3361
0
    return( -1 );
3362
0
  }
3363
0
  if( utf7_stream_base64_data == NULL )
3364
0
  {
3365
0
    libcerror_error_set(
3366
0
     error,
3367
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3368
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3369
0
     "%s: invalid UTF-7 stream base64 data.",
3370
0
     function );
3371
3372
0
    return( -1 );
3373
0
  }
3374
0
  safe_utf7_stream_index       = *utf7_stream_index;
3375
0
  safe_utf7_stream_base64_data = *utf7_stream_base64_data;
3376
3377
  /* Determine if the Unicode character is valid
3378
   */
3379
0
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
3380
0
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
3381
0
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
3382
0
  {
3383
0
    libcerror_error_set(
3384
0
     error,
3385
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3386
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3387
0
     "%s: unsupported Unicode character.",
3388
0
     function );
3389
3390
0
    return( -1 );
3391
0
  }
3392
  /* A-Z is not a continous range on an EBCDIC based system
3393
   * it consists of the ranges: A-I, J-R, S-Z
3394
   */
3395
0
  if( ( unicode_character >= 0x41 )
3396
0
   && ( unicode_character <= 0x49 ) )
3397
0
  {
3398
0
    unicode_character = ( unicode_character - 0x41 ) + (libuna_unicode_character_t) 'A';
3399
0
  }
3400
0
  else if( ( unicode_character >= 0x4a )
3401
0
        && ( unicode_character <= 0x52 ) )
3402
0
  {
3403
0
    unicode_character = ( unicode_character - 0x4a ) + (libuna_unicode_character_t) 'J';
3404
0
  }
3405
0
  else if( ( unicode_character >= 0x53 )
3406
0
        && ( unicode_character <= 0x5a ) )
3407
0
  {
3408
0
    unicode_character = ( unicode_character - 0x53 ) + (libuna_unicode_character_t) 'S';
3409
0
  }
3410
  /* a-z is not a continous range on an EBCDIC based system
3411
   * it consists of the ranges: a-i, j-r, s-z
3412
   */
3413
0
  else if( ( unicode_character >= 0x61 )
3414
0
        && ( unicode_character <= 0x69 ) )
3415
0
  {
3416
0
    unicode_character = ( unicode_character - 0x61 ) + (libuna_unicode_character_t) 'a';
3417
0
  }
3418
0
  else if( ( unicode_character >= 0x6a )
3419
0
        && ( unicode_character <= 0x72 ) )
3420
0
  {
3421
0
    unicode_character = ( unicode_character - 0x6a ) + (libuna_unicode_character_t) 'j';
3422
0
  }
3423
0
  else if( ( unicode_character >= 0x73 )
3424
0
        && ( unicode_character <= 0x7a ) )
3425
0
  {
3426
0
    unicode_character = ( unicode_character - 0x73 ) + (libuna_unicode_character_t) 's';
3427
0
  }
3428
  /* 0-9
3429
   */
3430
0
  else if( ( unicode_character >= 0x30 )
3431
0
        && ( unicode_character <= 0x39 ) )
3432
0
  {
3433
0
    unicode_character = ( unicode_character - 0x30 ) + (libuna_unicode_character_t) '0';
3434
0
  }
3435
  /* The + character must be escaped
3436
   */
3437
0
  else if( unicode_character == (libuna_unicode_character_t) '+' )
3438
0
  {
3439
0
  }
3440
  /* Allow for the end of string character
3441
   */
3442
0
  else if( unicode_character == 0 )
3443
0
  {
3444
0
  }
3445
0
  else if( ( unicode_character >= 256 )
3446
0
        || ( libuna_unicode_character_utf7_valid_directly_encoded_character[ (uint8_t) unicode_character ] == 0 ) )
3447
0
  {
3448
0
    base64_encode_character = 1;
3449
0
  }
3450
0
  if( base64_encode_character == 0 )
3451
0
  {
3452
0
    if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
3453
0
    {
3454
0
      safe_utf7_stream_base64_data = 0;
3455
0
    }
3456
0
    if( safe_utf7_stream_index >= utf7_stream_size )
3457
0
    {
3458
0
      libcerror_error_set(
3459
0
       error,
3460
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3461
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3462
0
       "%s: UTF-7 stream too small.",
3463
0
       function );
3464
3465
0
      return( -1 );
3466
0
    }
3467
0
    utf7_stream[ safe_utf7_stream_index++ ] = (uint8_t) unicode_character;
3468
3469
    /* The + character must be escaped
3470
     */
3471
0
    if( unicode_character == (libuna_unicode_character_t) '+' )
3472
0
    {
3473
0
      if( safe_utf7_stream_index >= utf7_stream_size )
3474
0
      {
3475
0
        libcerror_error_set(
3476
0
         error,
3477
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3478
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3479
0
         "%s: UTF-7 stream too small.",
3480
0
         function );
3481
3482
0
        return( -1 );
3483
0
      }
3484
0
      utf7_stream[ safe_utf7_stream_index++ ] = (uint8_t) '-';
3485
0
    }
3486
0
  }
3487
0
  else
3488
0
  {
3489
    /* Escape the base64 encoded chracters with a +
3490
     */
3491
0
    if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) == 0 )
3492
0
    {
3493
0
      if( safe_utf7_stream_index >= utf7_stream_size )
3494
0
      {
3495
0
        libcerror_error_set(
3496
0
         error,
3497
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3498
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3499
0
         "%s: UTF-7 stream too small.",
3500
0
         function );
3501
3502
0
        return( -1 );
3503
0
      }
3504
0
      utf7_stream[ safe_utf7_stream_index++ ] = (uint8_t) '+';
3505
0
    }
3506
    /* Otherwise continue the previously base64 encoded characters
3507
     */
3508
0
    else
3509
0
    {
3510
0
      base64_triplet  = safe_utf7_stream_base64_data & 0x00ffffff;
3511
0
      number_of_bytes = ( safe_utf7_stream_base64_data >> 24 ) & 0x03;
3512
0
      current_byte    = ( safe_utf7_stream_base64_data >> 28 ) & 0x03;
3513
3514
0
      if( number_of_bytes > 0 )
3515
0
      {
3516
        /* Correct the index for the last partial base64 stream
3517
         */
3518
0
        safe_utf7_stream_index -= number_of_bytes + 1;
3519
0
      }
3520
      /* Correct the index for the base64 stream termination character
3521
       */
3522
0
      safe_utf7_stream_index -= 1;
3523
0
    }
3524
0
    safe_utf7_stream_base64_data = LIBUNA_UTF7_IS_BASE64_ENCODED;
3525
3526
0
    if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
3527
0
    {
3528
0
      unicode_character -= 0x010000;
3529
3530
0
      utf16_surrogate = (libuna_utf16_character_t) ( ( unicode_character >> 10 )
3531
0
                      + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
3532
3533
0
      byte_bit_shift   = 16 - ( current_byte * 8 );
3534
0
      base64_triplet  += (uint32_t) ( ( utf16_surrogate >> 8 ) & 0xff ) << byte_bit_shift;
3535
0
      current_byte    += 1;
3536
0
      number_of_bytes += 1;
3537
3538
0
      if( number_of_bytes == 3 )
3539
0
      {
3540
0
        if( libuna_base64_triplet_copy_to_base64_stream(
3541
0
             base64_triplet,
3542
0
             utf7_stream,
3543
0
             utf7_stream_size,
3544
0
             &safe_utf7_stream_index,
3545
0
             0,
3546
0
             LIBUNA_BASE64_VARIANT_UTF7,
3547
0
             error ) != 1 )
3548
0
        {
3549
0
          libcerror_error_set(
3550
0
           error,
3551
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3552
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3553
0
           "%s: unable to set base64 encoded UTF-7 characters.",
3554
0
           function );
3555
3556
0
          return( -1 );
3557
0
        }
3558
0
        number_of_bytes = 0;
3559
0
        current_byte    = 0;
3560
0
        base64_triplet  = 0;
3561
0
      }
3562
0
      byte_bit_shift   = 16 - ( current_byte * 8 );
3563
0
      base64_triplet  += (uint32_t) ( utf16_surrogate & 0xff ) << byte_bit_shift;
3564
0
      current_byte    += 1;
3565
0
      number_of_bytes += 1;
3566
3567
0
      if( number_of_bytes == 3 )
3568
0
      {
3569
0
        if( libuna_base64_triplet_copy_to_base64_stream(
3570
0
             base64_triplet,
3571
0
             utf7_stream,
3572
0
             utf7_stream_size,
3573
0
             &safe_utf7_stream_index,
3574
0
             0,
3575
0
             LIBUNA_BASE64_VARIANT_UTF7,
3576
0
             error ) != 1 )
3577
0
        {
3578
0
          libcerror_error_set(
3579
0
           error,
3580
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
3581
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3582
0
           "%s: unable to set base64 encoded UTF-7 characters.",
3583
0
           function );
3584
3585
0
          return( -1 );
3586
0
        }
3587
0
        number_of_bytes = 0;
3588
0
        current_byte    = 0;
3589
0
        base64_triplet  = 0;
3590
0
      }
3591
0
      unicode_character = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff )
3592
0
                        + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
3593
0
    }
3594
0
    byte_bit_shift   = 16 - ( current_byte * 8 );
3595
0
    base64_triplet  += (uint32_t) ( ( unicode_character >> 8 ) & 0xff ) << byte_bit_shift;
3596
0
    current_byte    += 1;
3597
0
    number_of_bytes += 1;
3598
3599
0
    if( number_of_bytes == 3 )
3600
0
    {
3601
0
      if( libuna_base64_triplet_copy_to_base64_stream(
3602
0
           base64_triplet,
3603
0
           utf7_stream,
3604
0
           utf7_stream_size,
3605
0
           &safe_utf7_stream_index,
3606
0
           0,
3607
0
           LIBUNA_BASE64_VARIANT_UTF7,
3608
0
           error ) != 1 )
3609
0
      {
3610
0
        libcerror_error_set(
3611
0
         error,
3612
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3613
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3614
0
         "%s: unable to set base64 encoded UTF-7 characters.",
3615
0
         function );
3616
3617
0
        return( -1 );
3618
0
      }
3619
0
      number_of_bytes = 0;
3620
0
      current_byte    = 0;
3621
0
      base64_triplet  = 0;
3622
0
    }
3623
0
    byte_bit_shift   = 16 - ( current_byte * 8 );
3624
0
    base64_triplet  += (uint32_t) ( unicode_character & 0xff ) << byte_bit_shift;
3625
0
    current_byte    += 1;
3626
0
    number_of_bytes += 1;
3627
3628
0
    if( number_of_bytes == 3 )
3629
0
    {
3630
0
      if( libuna_base64_triplet_copy_to_base64_stream(
3631
0
           base64_triplet,
3632
0
           utf7_stream,
3633
0
           utf7_stream_size,
3634
0
           &safe_utf7_stream_index,
3635
0
           0,
3636
0
           LIBUNA_BASE64_VARIANT_UTF7,
3637
0
           error ) != 1 )
3638
0
      {
3639
0
        libcerror_error_set(
3640
0
         error,
3641
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3642
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3643
0
         "%s: unable to set base64 encoded UTF-7 characters.",
3644
0
         function );
3645
3646
0
        return( -1 );
3647
0
      }
3648
0
      number_of_bytes = 0;
3649
0
      current_byte    = 0;
3650
0
      base64_triplet  = 0;
3651
0
    }
3652
    /* Terminate the base64 encoded characters
3653
     */
3654
0
    if( number_of_bytes > 0 )
3655
0
    {
3656
0
      if( libuna_base64_triplet_copy_to_base64_stream(
3657
0
           base64_triplet,
3658
0
           utf7_stream,
3659
0
           utf7_stream_size,
3660
0
           &safe_utf7_stream_index,
3661
0
           3 - number_of_bytes,
3662
0
           LIBUNA_BASE64_VARIANT_UTF7,
3663
0
           error ) != 1 )
3664
0
      {
3665
0
        libcerror_error_set(
3666
0
         error,
3667
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3668
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3669
0
         "%s: unable to set base64 encoded UTF-7 characters.",
3670
0
         function );
3671
3672
0
        return( -1 );
3673
0
      }
3674
0
    }
3675
0
    if( safe_utf7_stream_index >= utf7_stream_size )
3676
0
    {
3677
0
      libcerror_error_set(
3678
0
       error,
3679
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3680
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3681
0
       "%s: UTF-7 stream too small.",
3682
0
       function );
3683
3684
0
      return( -1 );
3685
0
    }
3686
0
    utf7_stream[ safe_utf7_stream_index++ ] = (uint8_t) '-';
3687
0
  }
3688
0
  if( ( safe_utf7_stream_base64_data & LIBUNA_UTF7_IS_BASE64_ENCODED ) != 0 )
3689
0
  {
3690
0
    safe_utf7_stream_base64_data  = LIBUNA_UTF7_IS_BASE64_ENCODED;
3691
0
    safe_utf7_stream_base64_data |= (uint32_t) current_byte << 28;
3692
0
    safe_utf7_stream_base64_data |= (uint32_t) number_of_bytes << 24;
3693
0
    safe_utf7_stream_base64_data |= base64_triplet & 0x00ffffff;
3694
0
  }
3695
0
  *utf7_stream_index       = safe_utf7_stream_index;
3696
0
  *utf7_stream_base64_data = safe_utf7_stream_base64_data;
3697
3698
0
  return( 1 );
3699
0
}
3700
3701
/* Determines the size of an UTF-8 character from an Unicode character
3702
 * This function supports upto U+10FFFF (4 byte UTF-8 characters)
3703
 * Adds the size to the UTF-8 character size value
3704
 * Returns 1 if successful or -1 on error
3705
 */
3706
int libuna_unicode_character_size_to_utf8(
3707
     libuna_unicode_character_t unicode_character,
3708
     size_t *utf8_character_size,
3709
     libcerror_error_t **error )
3710
7.56M
{
3711
7.56M
  static char *function           = "libuna_unicode_character_size_to_utf8";
3712
7.56M
  size_t safe_utf8_character_size = 0;
3713
3714
7.56M
  if( utf8_character_size == NULL )
3715
0
  {
3716
0
    libcerror_error_set(
3717
0
     error,
3718
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3719
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3720
0
     "%s: invalid UTF-8 character size.",
3721
0
     function );
3722
3723
0
    return( -1 );
3724
0
  }
3725
  /* Determine if the Unicode character is valid
3726
   */
3727
7.56M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
3728
261k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
3729
7.56M
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
3730
0
  {
3731
0
    libcerror_error_set(
3732
0
     error,
3733
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3734
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3735
0
     "%s: unsupported Unicode character.",
3736
0
     function );
3737
3738
0
    return( -1 );
3739
0
  }
3740
  /* RFC 3629 limits the UTF-8 character to consist of a maximum of 4 bytes
3741
   * while its predecessor RFC 2279 allowed up to 6 bytes
3742
   */
3743
7.56M
  if( unicode_character < 0x00000080UL )
3744
4.02M
  {
3745
4.02M
    safe_utf8_character_size += 1;
3746
4.02M
  }
3747
3.54M
  else if( unicode_character < 0x00000800UL )
3748
210k
  {
3749
210k
    safe_utf8_character_size += 2;
3750
210k
  }
3751
3.32M
  else if( unicode_character < 0x00010000UL )
3752
3.30M
  {
3753
3.30M
    safe_utf8_character_size += 3;
3754
3.30M
  }
3755
25.3k
  else
3756
25.3k
  {
3757
25.3k
    safe_utf8_character_size += 4;
3758
25.3k
  }
3759
7.56M
  *utf8_character_size += safe_utf8_character_size;
3760
3761
7.56M
  return( 1 );
3762
7.56M
}
3763
3764
/* Copies an Unicode character from an UTF-8 string
3765
 * This function supports upto U+10FFFF (4 byte UTF-8 characters)
3766
 * Returns 1 if successful or -1 on error
3767
 */
3768
int libuna_unicode_character_copy_from_utf8(
3769
     libuna_unicode_character_t *unicode_character,
3770
     const libuna_utf8_character_t *utf8_string,
3771
     size_t utf8_string_size,
3772
     size_t *utf8_string_index,
3773
     libcerror_error_t **error )
3774
3.50M
{
3775
3.50M
  static char *function                             = "libuna_unicode_character_copy_from_utf8";
3776
3.50M
  libuna_unicode_character_t safe_unicode_character = 0;
3777
3.50M
  size_t safe_utf8_string_index                     = 0;
3778
3.50M
  uint8_t byte_value1                               = 0;
3779
3.50M
  uint8_t byte_value2                               = 0;
3780
3.50M
  uint8_t byte_value3                               = 0;
3781
3.50M
  uint8_t byte_value4                               = 0;
3782
3.50M
  uint8_t utf8_character_additional_bytes           = 0;
3783
3.50M
  int result                                        = 0;
3784
3785
3.50M
  if( unicode_character == NULL )
3786
0
  {
3787
0
    libcerror_error_set(
3788
0
     error,
3789
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3790
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3791
0
     "%s: invalid Unicode character.",
3792
0
     function );
3793
3794
0
    return( -1 );
3795
0
  }
3796
3.50M
  if( utf8_string == NULL )
3797
0
  {
3798
0
    libcerror_error_set(
3799
0
     error,
3800
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3801
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3802
0
     "%s: invalid UTF-8 string.",
3803
0
     function );
3804
3805
0
    return( -1 );
3806
0
  }
3807
3.50M
  if( utf8_string_size > (size_t) SSIZE_MAX )
3808
0
  {
3809
0
    libcerror_error_set(
3810
0
     error,
3811
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3812
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3813
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
3814
0
     function );
3815
3816
0
    return( -1 );
3817
0
  }
3818
3.50M
  if( utf8_string_index == NULL )
3819
0
  {
3820
0
    libcerror_error_set(
3821
0
     error,
3822
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3823
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3824
0
     "%s: invalid UTF-8 string index.",
3825
0
     function );
3826
3827
0
    return( -1 );
3828
0
  }
3829
3.50M
  safe_utf8_string_index = *utf8_string_index;
3830
3831
3.50M
  if( safe_utf8_string_index >= utf8_string_size )
3832
0
  {
3833
0
    libcerror_error_set(
3834
0
     error,
3835
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3836
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3837
0
     "%s: UTF-8 string too small.",
3838
0
     function );
3839
3840
0
    return( -1 );
3841
0
  }
3842
  /* Determine the number of additional bytes of the UTF-8 character
3843
   */
3844
3.50M
  byte_value1 = utf8_string[ safe_utf8_string_index ];
3845
3846
  /* Determine the UTF-8 character and make sure it is valid
3847
   * RFC 3629 limits the UTF-8 character to consist of a maximum of 4 bytes
3848
   * while its predecessor RFC 2279 allowed up to 6 bytes
3849
   */
3850
3.50M
  if( byte_value1 > 0xf4 )
3851
658
  {
3852
658
    libcerror_error_set(
3853
658
     error,
3854
658
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3855
658
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3856
658
     "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3857
658
     function,
3858
658
     byte_value1 );
3859
3860
658
    return( -1 );
3861
658
  }
3862
3.50M
  if( byte_value1 < 0xc0 )
3863
3.47M
  {
3864
3.47M
    utf8_character_additional_bytes = 0;
3865
3.47M
  }
3866
32.2k
  else if( byte_value1 < 0xe0 )
3867
6.59k
  {
3868
6.59k
    utf8_character_additional_bytes = 1;
3869
6.59k
  }
3870
25.6k
  else if( byte_value1 < 0xf0 )
3871
16.3k
  {
3872
16.3k
    utf8_character_additional_bytes = 2;
3873
16.3k
  }
3874
9.37k
  else
3875
9.37k
  {
3876
9.37k
    utf8_character_additional_bytes = 3;
3877
9.37k
  }
3878
3.50M
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
3879
3.50M
   || ( safe_utf8_string_index > ( utf8_string_size - ( utf8_character_additional_bytes + 1 ) ) ) )
3880
142
  {
3881
142
    libcerror_error_set(
3882
142
     error,
3883
142
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3884
142
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3885
142
     "%s: missing UTF-8 character bytes.",
3886
142
     function );
3887
3888
142
    return( -1 );
3889
142
  }
3890
3.50M
  safe_unicode_character = byte_value1;
3891
3892
3.50M
  if( utf8_character_additional_bytes == 0 )
3893
3.47M
  {
3894
3.47M
    if( byte_value1 >= 0x80 )
3895
500
    {
3896
500
      libcerror_error_set(
3897
500
       error,
3898
500
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3899
500
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3900
500
       "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3901
500
       function,
3902
500
       byte_value1 );
3903
3904
500
      return( -1 );
3905
500
    }
3906
3.47M
  }
3907
3.50M
  if( utf8_character_additional_bytes >= 1 )
3908
32.1k
  {
3909
32.1k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
3910
3911
32.1k
    if( ( byte_value2 < 0x80 )
3912
31.7k
     || ( byte_value2 > 0xbf ) )
3913
703
    {
3914
703
      libcerror_error_set(
3915
703
       error,
3916
703
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3917
703
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3918
703
       "%s: invalid 2nd UTF-8 character byte: 0x%02" PRIx8 ".",
3919
703
       function,
3920
703
       byte_value2 );
3921
3922
703
      return( -1 );
3923
703
    }
3924
31.4k
    result = 1;
3925
3926
31.4k
    switch( byte_value1 )
3927
31.4k
    {
3928
6.02k
      case 0xe0:
3929
6.02k
        if( ( byte_value2 < 0xa0 )
3930
5.90k
         || ( byte_value2 > 0xbf ) )
3931
121
        {
3932
121
          result = 0;
3933
121
        }
3934
6.02k
        break;
3935
3936
4.00k
      case 0xed:
3937
4.00k
        if( ( byte_value2 < 0x80 )
3938
4.00k
         || ( byte_value2 > 0x9f ) )
3939
81
        {
3940
81
          result = 0;
3941
81
        }
3942
4.00k
        break;
3943
3944
4.29k
      case 0xf0:
3945
4.29k
        if( ( byte_value2 < 0x90 )
3946
4.19k
         || ( byte_value2 > 0xbf ) )
3947
100
        {
3948
100
          result = 0;
3949
100
        }
3950
4.29k
        break;
3951
3952
1.14k
      case 0xf4:
3953
1.14k
        if( ( byte_value2 < 0x80 )
3954
1.14k
         || ( byte_value2 > 0xbf ) )
3955
0
        {
3956
0
          result = 0;
3957
0
        }
3958
1.14k
        break;
3959
3960
15.9k
      default:
3961
15.9k
        break;
3962
31.4k
    }
3963
31.4k
    if( result == 0 )
3964
302
    {
3965
302
      libcerror_error_set(
3966
302
       error,
3967
302
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3968
302
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3969
302
       "%s: invalid 1st and 2nd UTF-8 character byte pair: 0x%02" PRIx8 " 0x%02" PRIx8 ".",
3970
302
       function,
3971
302
       byte_value1,
3972
302
       byte_value2 );
3973
3974
302
      return( -1 );
3975
302
    }
3976
31.1k
    safe_unicode_character <<= 6;
3977
31.1k
    safe_unicode_character += byte_value2;
3978
3979
31.1k
    if( utf8_character_additional_bytes == 1 )
3980
6.33k
    {
3981
6.33k
      safe_unicode_character -= 0x03080;
3982
6.33k
    }
3983
31.1k
  }
3984
3.50M
  if( utf8_character_additional_bytes >= 2 )
3985
24.7k
  {
3986
24.7k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
3987
3988
24.7k
    if( ( byte_value3 < 0x80 )
3989
24.6k
     || ( byte_value3 > 0xbf ) )
3990
335
    {
3991
335
      libcerror_error_set(
3992
335
       error,
3993
335
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3994
335
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3995
335
       "%s: invalid 3rd UTF-8 character byte: 0x%02" PRIx8 ".",
3996
335
       function,
3997
335
       byte_value3 );
3998
3999
335
      return( -1 );
4000
335
    }
4001
24.4k
    result = 1;
4002
4003
24.4k
    switch( byte_value2 )
4004
24.4k
    {
4005
0
      case 0xe0:
4006
0
        if( ( byte_value2 < 0xa0 )
4007
0
         || ( byte_value2 > 0xbf ) )
4008
0
        {
4009
0
          result = 0;
4010
0
        }
4011
0
        break;
4012
4013
0
      case 0xed:
4014
0
        if( ( byte_value2 < 0x80 )
4015
0
         || ( byte_value2 > 0x9f ) )
4016
0
        {
4017
0
          result = 0;
4018
0
        }
4019
0
        break;
4020
4021
24.4k
      default:
4022
24.4k
        break;
4023
24.4k
    }
4024
24.4k
    if( result == 0 )
4025
0
    {
4026
0
      libcerror_error_set(
4027
0
       error,
4028
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4029
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4030
0
       "%s: invalid 2nd and 3rd UTF-8 character byte pair: 0x%02" PRIx8 " 0x%02" PRIx8 ".",
4031
0
       function,
4032
0
       byte_value2,
4033
0
       byte_value3 );
4034
4035
0
      return( -1 );
4036
0
    }
4037
24.4k
    safe_unicode_character <<= 6;
4038
24.4k
    safe_unicode_character += byte_value3;
4039
4040
24.4k
    if( utf8_character_additional_bytes == 2 )
4041
15.4k
    {
4042
15.4k
      safe_unicode_character -= 0x0e2080;
4043
15.4k
    }
4044
24.4k
  }
4045
3.50M
  if( utf8_character_additional_bytes >= 3 )
4046
9.04k
  {
4047
9.04k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4048
4049
9.04k
    if( ( byte_value4 < 0x80 )
4050
8.97k
     || ( byte_value4 > 0xbf ) )
4051
204
    {
4052
204
      libcerror_error_set(
4053
204
       error,
4054
204
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4055
204
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4056
204
       "%s: invalid 4th UTF-8 character byte: 0x%02" PRIx8 ".",
4057
204
       function,
4058
204
       byte_value4 );
4059
4060
204
      return( -1 );
4061
204
    }
4062
8.84k
    safe_unicode_character <<= 6;
4063
8.84k
    safe_unicode_character += byte_value4;
4064
4065
8.84k
    if( utf8_character_additional_bytes == 3 )
4066
8.84k
    {
4067
8.84k
      safe_unicode_character -= 0x03c82080;
4068
8.84k
    }
4069
8.84k
  }
4070
  /* Determine if the Unicode character is valid
4071
   */
4072
3.50M
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4073
12.7k
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4074
3.50M
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4075
66
  {
4076
66
    libcerror_error_set(
4077
66
     error,
4078
66
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4079
66
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4080
66
     "%s: unsupported Unicode character.",
4081
66
     function );
4082
4083
66
    return( -1 );
4084
66
  }
4085
3.50M
  *unicode_character = safe_unicode_character;
4086
3.50M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4087
4088
3.50M
  return( 1 );
4089
3.50M
}
4090
4091
/* Copies an Unicode character into a UTF-8 string
4092
 * This function supports upto U+10FFFF (4 byte UTF-8 characters)
4093
 * Returns 1 if successful or -1 on error
4094
 */
4095
int libuna_unicode_character_copy_to_utf8(
4096
     libuna_unicode_character_t unicode_character,
4097
     libuna_utf8_character_t *utf8_string,
4098
     size_t utf8_string_size,
4099
     size_t *utf8_string_index,
4100
     libcerror_error_t **error )
4101
3.73M
{
4102
3.73M
  static char *function                   = "libuna_unicode_character_copy_to_utf8";
4103
3.73M
  size_t safe_utf8_string_index           = 0;
4104
3.73M
  size_t utf8_character_iterator          = 0;
4105
3.73M
  uint8_t utf8_character_additional_bytes = 0;
4106
3.73M
  uint8_t utf8_first_character_mark       = 0;
4107
4108
3.73M
  if( utf8_string == NULL )
4109
0
  {
4110
0
    libcerror_error_set(
4111
0
     error,
4112
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4113
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4114
0
     "%s: invalid UTF-8 string.",
4115
0
     function );
4116
4117
0
    return( -1 );
4118
0
  }
4119
3.73M
  if( utf8_string_size > (size_t) SSIZE_MAX )
4120
0
  {
4121
0
    libcerror_error_set(
4122
0
     error,
4123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4124
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4125
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
4126
0
     function );
4127
4128
0
    return( -1 );
4129
0
  }
4130
3.73M
  if( utf8_string_index == NULL )
4131
0
  {
4132
0
    libcerror_error_set(
4133
0
     error,
4134
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4135
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4136
0
     "%s: invalid UTF-8 string index.",
4137
0
     function );
4138
4139
0
    return( -1 );
4140
0
  }
4141
3.73M
  safe_utf8_string_index = *utf8_string_index;
4142
4143
3.73M
  if( safe_utf8_string_index >= utf8_string_size )
4144
471
  {
4145
471
    libcerror_error_set(
4146
471
     error,
4147
471
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4148
471
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4149
471
     "%s: UTF-8 string too small.",
4150
471
     function );
4151
4152
471
    return( -1 );
4153
471
  }
4154
  /* Determine if the Unicode character is valid
4155
   */
4156
3.73M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4157
113k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4158
3.73M
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4159
0
  {
4160
0
    libcerror_error_set(
4161
0
     error,
4162
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4163
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4164
0
     "%s: unsupported Unicode character.",
4165
0
     function );
4166
4167
0
    return( -1 );
4168
0
  }
4169
  /* Determine how many UTF-8 character bytes are required
4170
   */
4171
3.73M
  if( unicode_character < 0x080 )
4172
823k
  {
4173
823k
    utf8_character_additional_bytes = 0;
4174
823k
    utf8_first_character_mark       = 0;
4175
823k
  }
4176
2.90M
  else if( unicode_character < 0x0800 )
4177
95.3k
  {
4178
95.3k
    utf8_character_additional_bytes = 1;
4179
95.3k
    utf8_first_character_mark       = 0x0c0;
4180
95.3k
  }
4181
2.81M
  else if( unicode_character < 0x010000 )
4182
2.80M
  {
4183
2.80M
    utf8_character_additional_bytes = 2;
4184
2.80M
    utf8_first_character_mark       = 0x0e0;
4185
2.80M
  }
4186
4.37k
  else
4187
4.37k
  {
4188
4.37k
    utf8_character_additional_bytes = 3;
4189
4.37k
    utf8_first_character_mark       = 0x0f0;
4190
4.37k
  }
4191
  /* Convert Unicode character into UTF-8 character bytes
4192
   */
4193
3.73M
  if( ( utf8_character_additional_bytes > utf8_string_size )
4194
3.73M
   || ( safe_utf8_string_index >= ( utf8_string_size - utf8_character_additional_bytes ) ) )
4195
528
  {
4196
528
    libcerror_error_set(
4197
528
     error,
4198
528
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4199
528
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4200
528
     "%s: UTF-8 string too small.",
4201
528
     function );
4202
4203
528
    return( -1 );
4204
528
  }
4205
3.73M
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4206
9.45M
       utf8_character_iterator > safe_utf8_string_index;
4207
5.72M
       utf8_character_iterator-- )
4208
5.72M
  {
4209
5.72M
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4210
4211
5.72M
    unicode_character >>= 6;
4212
5.72M
  }
4213
3.73M
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4214
4215
3.73M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4216
4217
3.73M
  return( 1 );
4218
3.73M
}
4219
4220
/* Determines the size of an UTF-8 character from an Unicode character
4221
 * This function supports upto U+7FFFFFF (6 byte UTF-8 characters)
4222
 * Adds the size to the UTF-8 character size value
4223
 * Returns 1 if successful or -1 on error
4224
 */
4225
int libuna_unicode_character_size_to_utf8_rfc2279(
4226
     libuna_unicode_character_t unicode_character,
4227
     size_t *utf8_character_size,
4228
     libcerror_error_t **error )
4229
13.8k
{
4230
13.8k
  static char *function           = "libuna_unicode_character_size_to_utf8_rfc2279";
4231
13.8k
  size_t safe_utf8_character_size = 0;
4232
4233
13.8k
  if( utf8_character_size == NULL )
4234
0
  {
4235
0
    libcerror_error_set(
4236
0
     error,
4237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4238
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4239
0
     "%s: invalid UTF-8 character size.",
4240
0
     function );
4241
4242
0
    return( -1 );
4243
0
  }
4244
13.8k
  if( unicode_character > LIBUNA_UCS_CHARACTER_MAX )
4245
0
  {
4246
0
    libcerror_error_set(
4247
0
     error,
4248
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4249
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4250
0
     "%s: unsupported Unicode character.",
4251
0
     function );
4252
4253
0
    return( -1 );
4254
0
  }
4255
  /* RFC 3629 limits the UTF-8 character to consist of a maximum of 4 bytes
4256
   * while its predecessor RFC 2279 allowed up to 6 bytes
4257
   */
4258
13.8k
  if( unicode_character < 0x00000080UL )
4259
1.95k
  {
4260
1.95k
    safe_utf8_character_size += 1;
4261
1.95k
  }
4262
11.8k
  else if( unicode_character < 0x00000800UL )
4263
842
  {
4264
842
    safe_utf8_character_size += 2;
4265
842
  }
4266
11.0k
  else if( unicode_character < 0x00010000UL )
4267
10.9k
  {
4268
10.9k
    safe_utf8_character_size += 3;
4269
10.9k
  }
4270
117
  else if( unicode_character < 0x00200000UL )
4271
117
  {
4272
117
    safe_utf8_character_size += 4;
4273
117
  }
4274
0
  else if( unicode_character < 0x04000000UL )
4275
0
  {
4276
0
    safe_utf8_character_size += 5;
4277
0
  }
4278
0
  else
4279
0
  {
4280
0
    safe_utf8_character_size += 6;
4281
0
  }
4282
13.8k
  *utf8_character_size += safe_utf8_character_size;
4283
4284
13.8k
  return( 1 );
4285
13.8k
}
4286
4287
/* Copies an Unicode character from an UTF-8 string
4288
 * This function supports upto U+7FFFFFF (6 byte UTF-8 characters)
4289
 * Returns 1 if successful or -1 on error
4290
 */
4291
int libuna_unicode_character_copy_from_utf8_rfc2279(
4292
     libuna_unicode_character_t *unicode_character,
4293
     const libuna_utf8_character_t *utf8_string,
4294
     size_t utf8_string_size,
4295
     size_t *utf8_string_index,
4296
     libcerror_error_t **error )
4297
104k
{
4298
104k
  static char *function                             = "libuna_unicode_character_copy_from_utf8_rfc2279";
4299
104k
  libuna_unicode_character_t safe_unicode_character = 0;
4300
104k
  size_t safe_utf8_string_index                     = 0;
4301
104k
  uint8_t byte_value1                               = 0;
4302
104k
  uint8_t byte_value2                               = 0;
4303
104k
  uint8_t byte_value3                               = 0;
4304
104k
  uint8_t byte_value4                               = 0;
4305
104k
  uint8_t byte_value5                               = 0;
4306
104k
  uint8_t byte_value6                               = 0;
4307
104k
  uint8_t utf8_character_additional_bytes           = 0;
4308
4309
104k
  if( unicode_character == NULL )
4310
0
  {
4311
0
    libcerror_error_set(
4312
0
     error,
4313
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4314
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4315
0
     "%s: invalid Unicode character.",
4316
0
     function );
4317
4318
0
    return( -1 );
4319
0
  }
4320
104k
  if( utf8_string == NULL )
4321
0
  {
4322
0
    libcerror_error_set(
4323
0
     error,
4324
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4325
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4326
0
     "%s: invalid UTF-8 string.",
4327
0
     function );
4328
4329
0
    return( -1 );
4330
0
  }
4331
104k
  if( utf8_string_size > (size_t) SSIZE_MAX )
4332
0
  {
4333
0
    libcerror_error_set(
4334
0
     error,
4335
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4336
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4337
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
4338
0
     function );
4339
4340
0
    return( -1 );
4341
0
  }
4342
104k
  if( utf8_string_index == NULL )
4343
0
  {
4344
0
    libcerror_error_set(
4345
0
     error,
4346
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4347
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4348
0
     "%s: invalid UTF-8 string index.",
4349
0
     function );
4350
4351
0
    return( -1 );
4352
0
  }
4353
104k
  safe_utf8_string_index = *utf8_string_index;
4354
4355
104k
  if( safe_utf8_string_index >= utf8_string_size )
4356
0
  {
4357
0
    libcerror_error_set(
4358
0
     error,
4359
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4360
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4361
0
     "%s: UTF-8 string too small.",
4362
0
     function );
4363
4364
0
    return( -1 );
4365
0
  }
4366
  /* Determine the number of additional bytes of the UTF-8 character
4367
   */
4368
104k
  byte_value1 = utf8_string[ safe_utf8_string_index ];
4369
4370
  /* Determine the UTF-8 character and make sure it is valid
4371
   * RFC 3629 limits the UTF-8 character to consist of a maximum of 4 bytes
4372
   * while its predecessor RFC 2279 allowed up to 6 bytes
4373
   */
4374
104k
  if( byte_value1 > 0xfd )
4375
0
  {
4376
0
    libcerror_error_set(
4377
0
     error,
4378
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4379
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4380
0
     "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
4381
0
     function,
4382
0
     byte_value1 );
4383
4384
0
    return( -1 );
4385
0
  }
4386
104k
  if( byte_value1 < 0xc0 )
4387
56.2k
  {
4388
56.2k
    utf8_character_additional_bytes = 0;
4389
56.2k
  }
4390
48.3k
  else if( byte_value1 < 0xe0 )
4391
13.1k
  {
4392
13.1k
    utf8_character_additional_bytes = 1;
4393
13.1k
  }
4394
35.1k
  else if( byte_value1 < 0xf0 )
4395
29.8k
  {
4396
29.8k
    utf8_character_additional_bytes = 2;
4397
29.8k
  }
4398
5.28k
  else if( byte_value1 < 0xf8 )
4399
5.28k
  {
4400
5.28k
    utf8_character_additional_bytes = 3;
4401
5.28k
  }
4402
0
  else if( byte_value1 < 0xfc )
4403
0
  {
4404
0
    utf8_character_additional_bytes = 4;
4405
0
  }
4406
0
  else
4407
0
  {
4408
0
    utf8_character_additional_bytes = 5;
4409
0
  }
4410
104k
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
4411
104k
   || ( safe_utf8_string_index > ( utf8_string_size - ( utf8_character_additional_bytes + 1 ) ) ) )
4412
0
  {
4413
0
    libcerror_error_set(
4414
0
     error,
4415
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4416
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4417
0
     "%s: missing UTF-8 character bytes.",
4418
0
     function );
4419
4420
0
    return( -1 );
4421
0
  }
4422
  /* Determine the UTF-8 character and make sure it is valid
4423
   * RFC 3629 limits the UTF-8 character to consist of a maximum of 4 bytes
4424
   * while its predecessor RFC 2279 allowed up to 6 bytes
4425
   */
4426
104k
  safe_unicode_character = byte_value1;
4427
4428
104k
  if( utf8_character_additional_bytes == 0 )
4429
56.2k
  {
4430
56.2k
    if( byte_value1 >= 0x80 )
4431
0
    {
4432
0
      libcerror_error_set(
4433
0
       error,
4434
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4435
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4436
0
       "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
4437
0
       function,
4438
0
       byte_value1 );
4439
4440
0
      return( -1 );
4441
0
    }
4442
56.2k
  }
4443
104k
  if( utf8_character_additional_bytes >= 1 )
4444
48.3k
  {
4445
48.3k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
4446
4447
48.3k
    if( ( byte_value2 < 0x80 )
4448
48.3k
     || ( byte_value2 > 0xbf ) )
4449
0
    {
4450
0
      libcerror_error_set(
4451
0
       error,
4452
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4453
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4454
0
       "%s: invalid 2nd UTF-8 character byte: 0x%02" PRIx8 ".",
4455
0
       function,
4456
0
       byte_value2 );
4457
4458
0
      return( -1 );
4459
0
    }
4460
48.3k
    safe_unicode_character <<= 6;
4461
48.3k
    safe_unicode_character += byte_value2;
4462
4463
48.3k
    if( utf8_character_additional_bytes == 1 )
4464
13.1k
    {
4465
13.1k
      safe_unicode_character -= 0x03080;
4466
13.1k
    }
4467
48.3k
  }
4468
104k
  if( utf8_character_additional_bytes >= 2 )
4469
35.1k
  {
4470
35.1k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
4471
4472
35.1k
    if( ( byte_value3 < 0x80 )
4473
35.1k
     || ( byte_value3 > 0xbf ) )
4474
0
    {
4475
0
      libcerror_error_set(
4476
0
       error,
4477
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4478
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4479
0
       "%s: invalid 3rd UTF-8 character byte: 0x%02" PRIx8 ".",
4480
0
       function,
4481
0
       byte_value3 );
4482
4483
0
      return( -1 );
4484
0
    }
4485
35.1k
    safe_unicode_character <<= 6;
4486
35.1k
    safe_unicode_character += byte_value3;
4487
4488
35.1k
    if( utf8_character_additional_bytes == 2 )
4489
29.8k
    {
4490
29.8k
      safe_unicode_character -= 0x0e2080;
4491
29.8k
    }
4492
35.1k
  }
4493
104k
  if( utf8_character_additional_bytes >= 3 )
4494
5.28k
  {
4495
5.28k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4496
4497
5.28k
    if( ( byte_value4 < 0x80 )
4498
5.28k
     || ( byte_value4 > 0xbf ) )
4499
0
    {
4500
0
      libcerror_error_set(
4501
0
       error,
4502
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4503
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4504
0
       "%s: invalid 4th UTF-8 character byte: 0x%02" PRIx8 ".",
4505
0
       function,
4506
0
       byte_value4 );
4507
4508
0
      return( -1 );
4509
0
    }
4510
5.28k
    safe_unicode_character <<= 6;
4511
5.28k
    safe_unicode_character += byte_value4;
4512
4513
5.28k
    if( utf8_character_additional_bytes == 3 )
4514
5.28k
    {
4515
5.28k
      safe_unicode_character -= 0x03c82080;
4516
5.28k
    }
4517
5.28k
  }
4518
104k
  if( utf8_character_additional_bytes >= 4 )
4519
0
  {
4520
0
    byte_value5 = utf8_string[ safe_utf8_string_index + 4 ];
4521
4522
0
    if( ( byte_value5 < 0x80 )
4523
0
     || ( byte_value5 > 0xbf ) )
4524
0
    {
4525
0
      libcerror_error_set(
4526
0
       error,
4527
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4528
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4529
0
       "%s: invalid 5th UTF-8 character byte: 0x%02" PRIx8 ".",
4530
0
       function,
4531
0
       byte_value5 );
4532
4533
0
      return( -1 );
4534
0
    }
4535
0
    safe_unicode_character <<= 6;
4536
0
    safe_unicode_character += byte_value5;
4537
4538
0
    if( utf8_character_additional_bytes == 4 )
4539
0
    {
4540
0
      safe_unicode_character -= 0x0fa082080;
4541
0
    }
4542
0
  }
4543
104k
  if( utf8_character_additional_bytes == 5 )
4544
0
  {
4545
0
    byte_value6 = utf8_string[ safe_utf8_string_index + 5 ];
4546
4547
0
    if( ( byte_value6 < 0x80 )
4548
0
      || ( byte_value6 > 0xbf ) )
4549
0
    {
4550
0
      libcerror_error_set(
4551
0
       error,
4552
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4553
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4554
0
       "%s: invalid 6th UTF-8 character byte: 0x%02" PRIx8 ".",
4555
0
       function,
4556
0
       byte_value6 );
4557
4558
0
      return( -1 );
4559
0
    }
4560
0
    safe_unicode_character <<= 6;
4561
0
    safe_unicode_character += byte_value6;
4562
0
    safe_unicode_character -= 0x082082080;
4563
0
  }
4564
  /* Determine if the Unicode character is valid
4565
   */
4566
104k
  if( safe_unicode_character > LIBUNA_UCS_CHARACTER_MAX )
4567
0
  {
4568
0
    libcerror_error_set(
4569
0
     error,
4570
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4571
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4572
0
     "%s: unsupported Unicode character.",
4573
0
     function );
4574
4575
0
    return( -1 );
4576
0
  }
4577
104k
  *unicode_character = safe_unicode_character;
4578
104k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4579
4580
104k
  return( 1 );
4581
104k
}
4582
4583
/* Copies an Unicode character into a UTF-8 string
4584
 * This function supports upto U+7FFFFFF (6 byte UTF-8 characters)
4585
 * Returns 1 if successful or -1 on error
4586
 */
4587
int libuna_unicode_character_copy_to_utf8_rfc2279(
4588
     libuna_unicode_character_t unicode_character,
4589
     libuna_utf8_character_t *utf8_string,
4590
     size_t utf8_string_size,
4591
     size_t *utf8_string_index,
4592
     libcerror_error_t **error )
4593
13.8k
{
4594
13.8k
  static char *function                   = "libuna_unicode_character_copy_to_utf8_rfc2279";
4595
13.8k
  size_t safe_utf8_string_index           = 0;
4596
13.8k
  size_t utf8_character_iterator          = 0;
4597
13.8k
  uint8_t utf8_character_additional_bytes = 0;
4598
13.8k
  uint8_t utf8_first_character_mark       = 0;
4599
4600
13.8k
  if( utf8_string == NULL )
4601
0
  {
4602
0
    libcerror_error_set(
4603
0
     error,
4604
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4605
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4606
0
     "%s: invalid UTF-8 string.",
4607
0
     function );
4608
4609
0
    return( -1 );
4610
0
  }
4611
13.8k
  if( utf8_string_size > (size_t) SSIZE_MAX )
4612
0
  {
4613
0
    libcerror_error_set(
4614
0
     error,
4615
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4616
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4617
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
4618
0
     function );
4619
4620
0
    return( -1 );
4621
0
  }
4622
13.8k
  if( utf8_string_index == NULL )
4623
0
  {
4624
0
    libcerror_error_set(
4625
0
     error,
4626
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4627
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4628
0
     "%s: invalid UTF-8 string index.",
4629
0
     function );
4630
4631
0
    return( -1 );
4632
0
  }
4633
13.8k
  safe_utf8_string_index = *utf8_string_index;
4634
4635
13.8k
  if( safe_utf8_string_index >= utf8_string_size )
4636
0
  {
4637
0
    libcerror_error_set(
4638
0
     error,
4639
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4640
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4641
0
     "%s: UTF-8 string too small.",
4642
0
     function );
4643
4644
0
    return( -1 );
4645
0
  }
4646
  /* Determine if the Unicode character is valid
4647
   */
4648
13.8k
  if( unicode_character > LIBUNA_UCS_CHARACTER_MAX )
4649
0
  {
4650
0
    libcerror_error_set(
4651
0
     error,
4652
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4653
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4654
0
     "%s: unsupported Unicode character.",
4655
0
     function );
4656
4657
0
    return( -1 );
4658
0
  }
4659
  /* Determine how many UTF-8 character bytes are required
4660
   */
4661
13.8k
  if( unicode_character < 0x080 )
4662
1.95k
  {
4663
1.95k
    utf8_character_additional_bytes = 0;
4664
1.95k
    utf8_first_character_mark       = 0;
4665
1.95k
  }
4666
11.8k
  else if( unicode_character < 0x0800 )
4667
842
  {
4668
842
    utf8_character_additional_bytes = 1;
4669
842
    utf8_first_character_mark       = 0x0c0;
4670
842
  }
4671
11.0k
  else if( unicode_character < 0x010000 )
4672
10.9k
  {
4673
10.9k
    utf8_character_additional_bytes = 2;
4674
10.9k
    utf8_first_character_mark       = 0x0e0;
4675
10.9k
  }
4676
117
  else if( unicode_character < 0x0200000 )
4677
117
  {
4678
117
    utf8_character_additional_bytes = 3;
4679
117
    utf8_first_character_mark       = 0x0f0;
4680
117
  }
4681
0
  else if( unicode_character < 0x0400000 )
4682
0
  {
4683
0
    utf8_character_additional_bytes = 4;
4684
0
    utf8_first_character_mark       = 0x0f8;
4685
0
  }
4686
0
  else
4687
0
  {
4688
0
    utf8_character_additional_bytes = 5;
4689
0
    utf8_first_character_mark       = 0x0fc;
4690
0
  }
4691
  /* Convert Unicode character into UTF-8 character bytes
4692
   */
4693
13.8k
  if( ( utf8_character_additional_bytes > utf8_string_size )
4694
13.8k
   || ( safe_utf8_string_index >= ( utf8_string_size - utf8_character_additional_bytes ) ) )
4695
0
  {
4696
0
    libcerror_error_set(
4697
0
     error,
4698
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4699
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4700
0
     "%s: UTF-8 string too small.",
4701
0
     function );
4702
4703
0
    return( -1 );
4704
0
  }
4705
13.8k
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4706
36.8k
       utf8_character_iterator > safe_utf8_string_index;
4707
23.0k
       utf8_character_iterator-- )
4708
23.0k
  {
4709
23.0k
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4710
4711
23.0k
    unicode_character >>= 6;
4712
23.0k
  }
4713
13.8k
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4714
4715
13.8k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4716
4717
13.8k
  return( 1 );
4718
13.8k
}
4719
4720
/* Determines the size of an UTF-16 character from an Unicode character
4721
 * Adds the size to the UTF-16 character size value
4722
 * Returns 1 if successful or -1 on error
4723
 */
4724
int libuna_unicode_character_size_to_utf16(
4725
     libuna_unicode_character_t unicode_character,
4726
     size_t *utf16_character_size,
4727
     libcerror_error_t **error )
4728
26.0k
{
4729
26.0k
  static char *function = "libuna_unicode_character_size_to_utf16";
4730
4731
26.0k
  if( utf16_character_size == NULL )
4732
0
  {
4733
0
    libcerror_error_set(
4734
0
     error,
4735
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4736
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4737
0
     "%s: invalid UTF-16 character size.",
4738
0
     function );
4739
4740
0
    return( -1 );
4741
0
  }
4742
26.0k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4743
337
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4744
26.0k
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4745
0
  {
4746
0
    libcerror_error_set(
4747
0
     error,
4748
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4749
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4750
0
     "%s: unsupported Unicode character.",
4751
0
     function );
4752
4753
0
    return( -1 );
4754
0
  }
4755
26.0k
  if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4756
199
  {
4757
199
    *utf16_character_size += 2;
4758
199
  }
4759
25.8k
  else
4760
25.8k
  {
4761
25.8k
    *utf16_character_size += 1;
4762
25.8k
  }
4763
26.0k
  return( 1 );
4764
26.0k
}
4765
4766
/* Copies an Unicode character from an UTF-16 string
4767
 * Returns 1 if successful or -1 on error
4768
 */
4769
int libuna_unicode_character_copy_from_utf16(
4770
     libuna_unicode_character_t *unicode_character,
4771
     const libuna_utf16_character_t *utf16_string,
4772
     size_t utf16_string_size,
4773
     size_t *utf16_string_index,
4774
     libcerror_error_t **error )
4775
0
{
4776
0
  static char *function                             = "libuna_unicode_character_copy_from_utf16";
4777
0
  libuna_unicode_character_t safe_unicode_character = 0;
4778
0
  libuna_utf16_character_t utf16_surrogate          = 0;
4779
0
  size_t safe_utf16_string_index                    = 0;
4780
4781
0
  if( unicode_character == NULL )
4782
0
  {
4783
0
    libcerror_error_set(
4784
0
     error,
4785
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4786
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4787
0
     "%s: invalid Unicode character.",
4788
0
     function );
4789
4790
0
    return( -1 );
4791
0
  }
4792
0
  if( utf16_string == NULL )
4793
0
  {
4794
0
    libcerror_error_set(
4795
0
     error,
4796
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4797
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4798
0
     "%s: invalid UTF-16 string.",
4799
0
     function );
4800
4801
0
    return( -1 );
4802
0
  }
4803
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
4804
0
  {
4805
0
    libcerror_error_set(
4806
0
     error,
4807
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4808
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4809
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
4810
0
     function );
4811
4812
0
    return( -1 );
4813
0
  }
4814
0
  if( utf16_string_index == NULL )
4815
0
  {
4816
0
    libcerror_error_set(
4817
0
     error,
4818
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4819
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4820
0
     "%s: invalid UTF-16 string index.",
4821
0
     function );
4822
4823
0
    return( -1 );
4824
0
  }
4825
0
  safe_utf16_string_index = *utf16_string_index;
4826
4827
0
  if( safe_utf16_string_index >= utf16_string_size )
4828
0
  {
4829
0
    libcerror_error_set(
4830
0
     error,
4831
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4832
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4833
0
     "%s: UTF-16 string too small.",
4834
0
     function );
4835
4836
0
    return( -1 );
4837
0
  }
4838
0
  safe_unicode_character   = utf16_string[ safe_utf16_string_index ];
4839
0
  safe_utf16_string_index += 1;
4840
4841
  /* Determine if the UTF-16 character is within the high surrogate range
4842
   */
4843
0
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4844
0
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
4845
0
  {
4846
0
    if( safe_utf16_string_index >= utf16_string_size )
4847
0
    {
4848
0
      libcerror_error_set(
4849
0
       error,
4850
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4851
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4852
0
       "%s: missing surrogate UTF-16 character bytes.",
4853
0
       function );
4854
4855
0
      return( -1 );
4856
0
    }
4857
0
    utf16_surrogate          = utf16_string[ safe_utf16_string_index ];
4858
0
    safe_utf16_string_index += 1;
4859
4860
    /* Determine if the UTF-16 character is within the low surrogate range
4861
     */
4862
0
    if( ( utf16_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
4863
0
     && ( utf16_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4864
0
    {
4865
0
      safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
4866
0
      safe_unicode_character <<= 10;
4867
0
      safe_unicode_character  += utf16_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
4868
0
      safe_unicode_character  += 0x010000;
4869
0
    }
4870
0
    else
4871
0
    {
4872
0
      libcerror_error_set(
4873
0
       error,
4874
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4875
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4876
0
       "%s: unsupported low surrogate UTF-16 character.",
4877
0
       function );
4878
4879
0
      return( -1 );
4880
0
    }
4881
0
  }
4882
  /* Determine if the Unicode character is valid
4883
   */
4884
0
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4885
0
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4886
0
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4887
0
  {
4888
0
    libcerror_error_set(
4889
0
     error,
4890
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4891
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4892
0
     "%s: unsupported Unicode character.",
4893
0
     function );
4894
4895
0
    return( -1 );
4896
0
  }
4897
0
  *unicode_character  = safe_unicode_character;
4898
0
  *utf16_string_index = safe_utf16_string_index;
4899
4900
0
  return( 1 );
4901
0
}
4902
4903
/* Copies an Unicode character into a UTF-16 string
4904
 * Returns 1 if successful or -1 on error
4905
 */
4906
int libuna_unicode_character_copy_to_utf16(
4907
     libuna_unicode_character_t unicode_character,
4908
     libuna_utf16_character_t *utf16_string,
4909
     size_t utf16_string_size,
4910
     size_t *utf16_string_index,
4911
     libcerror_error_t **error )
4912
6.57k
{
4913
6.57k
  static char *function          = "libuna_unicode_character_copy_to_utf16";
4914
6.57k
  size_t safe_utf16_string_index = 0;
4915
4916
6.57k
  if( utf16_string == NULL )
4917
0
  {
4918
0
    libcerror_error_set(
4919
0
     error,
4920
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4921
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4922
0
     "%s: invalid UTF-16 string.",
4923
0
     function );
4924
4925
0
    return( -1 );
4926
0
  }
4927
6.57k
  if( utf16_string_size > (size_t) SSIZE_MAX )
4928
0
  {
4929
0
    libcerror_error_set(
4930
0
     error,
4931
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4932
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4933
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
4934
0
     function );
4935
4936
0
    return( -1 );
4937
0
  }
4938
6.57k
  if( utf16_string_index == NULL )
4939
0
  {
4940
0
    libcerror_error_set(
4941
0
     error,
4942
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4943
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4944
0
     "%s: invalid UTF-16 string index.",
4945
0
     function );
4946
4947
0
    return( -1 );
4948
0
  }
4949
6.57k
  safe_utf16_string_index = *utf16_string_index;
4950
4951
6.57k
  if( safe_utf16_string_index >= utf16_string_size )
4952
0
  {
4953
0
    libcerror_error_set(
4954
0
     error,
4955
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4956
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4957
0
     "%s: UTF-16 string too small.",
4958
0
     function );
4959
4960
0
    return( -1 );
4961
0
  }
4962
  /* Determine if the Unicode character is valid
4963
   */
4964
6.57k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4965
928
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4966
6.57k
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4967
0
  {
4968
0
    libcerror_error_set(
4969
0
     error,
4970
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4971
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4972
0
     "%s: unsupported Unicode character.",
4973
0
     function );
4974
4975
0
    return( -1 );
4976
0
  }
4977
6.57k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4978
6.33k
  {
4979
6.33k
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) unicode_character;
4980
6.33k
  }
4981
243
  else
4982
243
  {
4983
243
    if( ( utf16_string_size < 2 )
4984
243
     || ( safe_utf16_string_index > ( utf16_string_size - 2 ) ) )
4985
0
    {
4986
0
      libcerror_error_set(
4987
0
       error,
4988
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4989
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4990
0
       "%s: UTF-16 string too small.",
4991
0
       function );
4992
4993
0
      return( -1 );
4994
0
    }
4995
243
    unicode_character                        -= 0x010000;
4996
243
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
4997
243
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
4998
243
  }
4999
6.57k
  *utf16_string_index = safe_utf16_string_index;
5000
5001
6.57k
  return( 1 );
5002
6.57k
}
5003
5004
/* Copies an Unicode character from an UTF-16 stream
5005
 * Returns 1 if successful or -1 on error
5006
 */
5007
int libuna_unicode_character_copy_from_utf16_stream(
5008
     libuna_unicode_character_t *unicode_character,
5009
     const uint8_t *utf16_stream,
5010
     size_t utf16_stream_size,
5011
     size_t *utf16_stream_index,
5012
     int byte_order,
5013
     libcerror_error_t **error )
5014
11.2M
{
5015
11.2M
  static char *function                             = "libuna_unicode_character_copy_from_utf16_stream";
5016
11.2M
  libuna_unicode_character_t safe_unicode_character = 0;
5017
11.2M
  libuna_utf16_character_t utf16_surrogate          = 0;
5018
11.2M
  size_t safe_utf16_stream_index                    = 0;
5019
11.2M
  int byte_order_without_flags                      = 0;
5020
5021
11.2M
  if( unicode_character == NULL )
5022
0
  {
5023
0
    libcerror_error_set(
5024
0
     error,
5025
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5026
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5027
0
     "%s: invalid Unicode character.",
5028
0
     function );
5029
5030
0
    return( -1 );
5031
0
  }
5032
11.2M
  if( utf16_stream == NULL )
5033
0
  {
5034
0
    libcerror_error_set(
5035
0
     error,
5036
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5037
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5038
0
     "%s: invalid UTF-16 stream.",
5039
0
     function );
5040
5041
0
    return( -1 );
5042
0
  }
5043
11.2M
  if( utf16_stream_size > (size_t) SSIZE_MAX )
5044
0
  {
5045
0
    libcerror_error_set(
5046
0
     error,
5047
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5048
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5049
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
5050
0
     function );
5051
5052
0
    return( -1 );
5053
0
  }
5054
11.2M
  if( utf16_stream_index == NULL )
5055
0
  {
5056
0
    libcerror_error_set(
5057
0
     error,
5058
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5059
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5060
0
     "%s: invalid UTF-16 stream index.",
5061
0
     function );
5062
5063
0
    return( -1 );
5064
0
  }
5065
11.2M
  byte_order_without_flags = byte_order & 0xff;
5066
5067
11.2M
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5068
7.56M
   && ( byte_order_without_flags != LIBUNA_ENDIAN_LITTLE ) )
5069
0
  {
5070
0
    libcerror_error_set(
5071
0
     error,
5072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5073
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
5074
0
     "%s: unsupported byte order.",
5075
0
     function );
5076
5077
0
    return( -1 );
5078
0
  }
5079
11.2M
  safe_utf16_stream_index = *utf16_stream_index;
5080
5081
11.2M
  if( ( utf16_stream_size < 2 )
5082
11.2M
   || ( safe_utf16_stream_index > ( utf16_stream_size - 2 ) ) )
5083
91
  {
5084
91
    libcerror_error_set(
5085
91
     error,
5086
91
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5087
91
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5088
91
     "%s: UTF-16 stream too small.",
5089
91
     function );
5090
5091
91
    return( -1 );
5092
91
  }
5093
11.2M
  if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5094
3.67M
  {
5095
3.67M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index ];
5096
3.67M
    safe_unicode_character <<= 8;
5097
3.67M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index + 1 ];
5098
3.67M
  }
5099
7.56M
  else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5100
7.56M
  {
5101
7.56M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index + 1 ];
5102
7.56M
    safe_unicode_character <<= 8;
5103
7.56M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index ];
5104
7.56M
  }
5105
11.2M
  safe_utf16_stream_index += 2;
5106
5107
  /* Determine if the Unicode character is valid
5108
   */
5109
11.2M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5110
832k
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5111
2.09k
  {
5112
2.09k
    if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5113
692
    {
5114
692
      libcerror_error_set(
5115
692
       error,
5116
692
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5117
692
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5118
692
       "%s: unsupported UTF-16 character.",
5119
692
       function );
5120
5121
692
      return( -1 );
5122
692
    }
5123
2.09k
  }
5124
  /* Determine if the UTF-16 character is within the high surrogate range
5125
   */
5126
11.2M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5127
936k
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
5128
104k
  {
5129
104k
    if( safe_utf16_stream_index > ( utf16_stream_size - 2 ) )
5130
101
    {
5131
101
      if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5132
49
      {
5133
49
        libcerror_error_set(
5134
49
         error,
5135
49
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5136
49
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5137
49
         "%s: missing surrogate UTF-16 character bytes.",
5138
49
         function );
5139
5140
49
        return( -1 );
5141
49
      }
5142
101
    }
5143
104k
    else
5144
104k
    {
5145
104k
      if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5146
86.8k
      {
5147
86.8k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index ];
5148
86.8k
        utf16_surrogate <<= 8;
5149
86.8k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index + 1 ];
5150
86.8k
      }
5151
17.9k
      else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5152
17.9k
      {
5153
17.9k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index + 1 ];
5154
17.9k
        utf16_surrogate <<= 8;
5155
17.9k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index ];
5156
17.9k
      }
5157
      /* Determine if the UTF-16 character is within the low surrogate range
5158
       */
5159
104k
      if( ( utf16_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5160
101k
       && ( utf16_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5161
100k
      {
5162
100k
        safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
5163
100k
        safe_unicode_character <<= 10;
5164
100k
        safe_unicode_character  += utf16_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
5165
100k
        safe_unicode_character  += 0x010000;
5166
5167
100k
        safe_utf16_stream_index += 2;
5168
100k
      }
5169
3.95k
      else if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5170
744
      {
5171
744
        libcerror_error_set(
5172
744
         error,
5173
744
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5174
744
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5175
744
         "%s: unsupported low surrogate UTF-16 character.",
5176
744
         function );
5177
5178
744
        return( -1 );
5179
744
      }
5180
104k
    }
5181
104k
  }
5182
11.2M
  if( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
5183
0
  {
5184
0
    libcerror_error_set(
5185
0
     error,
5186
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5187
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5188
0
     "%s: unsupported Unicode character.",
5189
0
     function );
5190
5191
0
    return( -1 );
5192
0
  }
5193
11.2M
  *unicode_character  = safe_unicode_character;
5194
11.2M
  *utf16_stream_index = safe_utf16_stream_index;
5195
5196
11.2M
  return( 1 );
5197
11.2M
}
5198
5199
/* Copies an Unicode character to an UTF-16 stream
5200
 * Returns 1 if successful or -1 on error
5201
 */
5202
int libuna_unicode_character_copy_to_utf16_stream(
5203
     libuna_unicode_character_t unicode_character,
5204
     uint8_t *utf16_stream,
5205
     size_t utf16_stream_size,
5206
     size_t *utf16_stream_index,
5207
     int byte_order,
5208
     libcerror_error_t **error )
5209
21.6k
{
5210
21.6k
  static char *function                    = "libuna_unicode_character_copy_to_utf16_stream";
5211
21.6k
  libuna_utf16_character_t utf16_surrogate = 0;
5212
21.6k
  size_t safe_utf16_stream_index           = 0;
5213
21.6k
  int byte_order_without_flags             = 0;
5214
5215
21.6k
  if( utf16_stream == NULL )
5216
0
  {
5217
0
    libcerror_error_set(
5218
0
     error,
5219
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5220
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5221
0
     "%s: invalid UTF-16 stream.",
5222
0
     function );
5223
5224
0
    return( -1 );
5225
0
  }
5226
21.6k
  if( utf16_stream_size > (size_t) SSIZE_MAX )
5227
0
  {
5228
0
    libcerror_error_set(
5229
0
     error,
5230
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5231
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5232
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
5233
0
     function );
5234
5235
0
    return( -1 );
5236
0
  }
5237
21.6k
  if( utf16_stream_index == NULL )
5238
0
  {
5239
0
    libcerror_error_set(
5240
0
     error,
5241
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5242
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5243
0
     "%s: invalid UTF-16 stream index.",
5244
0
     function );
5245
5246
0
    return( -1 );
5247
0
  }
5248
21.6k
  byte_order_without_flags = byte_order & 0xff;
5249
5250
21.6k
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5251
21.6k
   && ( byte_order_without_flags != LIBUNA_ENDIAN_LITTLE ) )
5252
0
  {
5253
0
    libcerror_error_set(
5254
0
     error,
5255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5256
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
5257
0
     "%s: unsupported byte order.",
5258
0
     function );
5259
5260
0
    return( -1 );
5261
0
  }
5262
21.6k
  safe_utf16_stream_index = *utf16_stream_index;
5263
5264
  /* Determine if the Unicode character is valid
5265
   */
5266
21.6k
  if( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
5267
0
  {
5268
0
    libcerror_error_set(
5269
0
     error,
5270
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5271
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5272
0
     "%s: unsupported Unicode character.",
5273
0
     function );
5274
5275
0
    return( -1 );
5276
0
  }
5277
21.6k
  if( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5278
0
   && ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5279
0
  {
5280
0
    if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5281
0
    {
5282
0
      libcerror_error_set(
5283
0
       error,
5284
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5285
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5286
0
       "%s: unsupported Unicode character.",
5287
0
       function );
5288
5289
0
      return( -1 );
5290
0
    }
5291
0
  }
5292
21.6k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
5293
21.6k
  {
5294
21.6k
    if( ( utf16_stream_size < 2 )
5295
21.6k
     || ( safe_utf16_stream_index > ( utf16_stream_size - 2 ) ) )
5296
0
    {
5297
0
      libcerror_error_set(
5298
0
       error,
5299
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5300
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5301
0
       "%s: UTF-16 stream too small.",
5302
0
       function );
5303
5304
0
      return( -1 );
5305
0
    }
5306
21.6k
    if( byte_order == LIBUNA_ENDIAN_BIG )
5307
0
    {
5308
0
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5309
0
      unicode_character                         >>= 8;
5310
0
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5311
0
    }
5312
21.6k
    else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5313
21.6k
    {
5314
21.6k
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5315
21.6k
      unicode_character                         >>= 8;
5316
21.6k
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5317
21.6k
    }
5318
21.6k
    safe_utf16_stream_index += 2;
5319
21.6k
  }
5320
0
  else
5321
0
  {
5322
0
    if( ( utf16_stream_size < 4 )
5323
0
     || ( safe_utf16_stream_index > ( utf16_stream_size - 4 ) ) )
5324
0
    {
5325
0
      libcerror_error_set(
5326
0
       error,
5327
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5328
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5329
0
       "%s: UTF-16 stream too small.",
5330
0
       function );
5331
5332
0
      return( -1 );
5333
0
    }
5334
0
    unicode_character -= 0x010000;
5335
5336
0
    utf16_surrogate = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
5337
5338
0
    if( byte_order == LIBUNA_ENDIAN_BIG )
5339
0
    {
5340
0
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( utf16_surrogate & 0xff );
5341
0
      utf16_surrogate                           >>= 8;
5342
0
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( utf16_surrogate & 0xff );
5343
0
    }
5344
0
    else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5345
0
    {
5346
0
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( utf16_surrogate & 0xff );
5347
0
      utf16_surrogate                           >>= 8;
5348
0
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( utf16_surrogate & 0xff );
5349
0
    }
5350
0
    safe_utf16_stream_index += 2;
5351
5352
0
    utf16_surrogate = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
5353
5354
0
    if( byte_order == LIBUNA_ENDIAN_BIG )
5355
0
    {
5356
0
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( utf16_surrogate & 0xff );
5357
0
      utf16_surrogate                           >>= 8;
5358
0
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( utf16_surrogate & 0xff );
5359
0
    }
5360
0
    else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5361
0
    {
5362
0
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( utf16_surrogate & 0xff );
5363
0
      utf16_surrogate                           >>= 8;
5364
0
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( utf16_surrogate & 0xff );
5365
0
    }
5366
0
    safe_utf16_stream_index += 2;
5367
0
  }
5368
21.6k
  *utf16_stream_index = safe_utf16_stream_index;
5369
5370
21.6k
  return( 1 );
5371
21.6k
}
5372
5373
/* Determines the size of an UTF-32 character from an Unicode character
5374
 * Adds the size to the UTF-32 character size value
5375
 * Returns 1 if successful or -1 on error
5376
 */
5377
int libuna_unicode_character_size_to_utf32(
5378
     libuna_unicode_character_t unicode_character,
5379
     size_t *utf32_character_size,
5380
     libcerror_error_t **error )
5381
0
{
5382
0
  static char *function = "libuna_unicode_character_size_to_utf32";
5383
5384
0
  LIBUNA_UNREFERENCED_PARAMETER( unicode_character )
5385
5386
0
  if( utf32_character_size == NULL )
5387
0
  {
5388
0
    libcerror_error_set(
5389
0
     error,
5390
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5391
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5392
0
     "%s: invalid UTF-32 character size.",
5393
0
     function );
5394
5395
0
    return( -1 );
5396
0
  }
5397
0
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5398
0
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5399
0
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
5400
0
  {
5401
0
    libcerror_error_set(
5402
0
     error,
5403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5404
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5405
0
     "%s: unsupported Unicode character.",
5406
0
     function );
5407
5408
0
    return( -1 );
5409
0
  }
5410
0
  *utf32_character_size += 1;
5411
5412
0
  return( 1 );
5413
0
}
5414
5415
/* Copies an Unicode character from an UTF-32 string
5416
 * Returns 1 if successful or -1 on error
5417
 */
5418
int libuna_unicode_character_copy_from_utf32(
5419
     libuna_unicode_character_t *unicode_character,
5420
     const libuna_utf32_character_t *utf32_string,
5421
     size_t utf32_string_size,
5422
     size_t *utf32_string_index,
5423
     libcerror_error_t **error )
5424
0
{
5425
0
  static char *function                             = "libuna_unicode_character_copy_from_utf32";
5426
0
  libuna_unicode_character_t safe_unicode_character = 0;
5427
0
  size_t safe_utf32_string_index                    = 0;
5428
5429
0
  if( unicode_character == NULL )
5430
0
  {
5431
0
    libcerror_error_set(
5432
0
     error,
5433
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5434
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5435
0
     "%s: invalid Unicode character.",
5436
0
     function );
5437
5438
0
    return( -1 );
5439
0
  }
5440
0
  if( utf32_string == NULL )
5441
0
  {
5442
0
    libcerror_error_set(
5443
0
     error,
5444
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5445
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5446
0
     "%s: invalid UTF-32 string.",
5447
0
     function );
5448
5449
0
    return( -1 );
5450
0
  }
5451
0
  if( utf32_string_size > (size_t) SSIZE_MAX )
5452
0
  {
5453
0
    libcerror_error_set(
5454
0
     error,
5455
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5456
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5457
0
     "%s: invalid UTF-32 string size value exceeds maximum.",
5458
0
     function );
5459
5460
0
    return( -1 );
5461
0
  }
5462
0
  if( utf32_string_index == NULL )
5463
0
  {
5464
0
    libcerror_error_set(
5465
0
     error,
5466
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5467
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5468
0
     "%s: invalid UTF-32 string index.",
5469
0
     function );
5470
5471
0
    return( -1 );
5472
0
  }
5473
0
  safe_utf32_string_index = *utf32_string_index;
5474
5475
0
  if( safe_utf32_string_index >= utf32_string_size )
5476
0
  {
5477
0
    libcerror_error_set(
5478
0
     error,
5479
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5480
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5481
0
     "%s: UTF-32 string too small.",
5482
0
     function );
5483
5484
0
    return( -1 );
5485
0
  }
5486
0
  safe_unicode_character = utf32_string[ safe_utf32_string_index ];
5487
5488
  /* Determine if the Unicode character is valid
5489
   */
5490
0
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5491
0
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5492
0
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
5493
0
  {
5494
0
    libcerror_error_set(
5495
0
     error,
5496
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5497
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5498
0
     "%s: unsupported Unicode character.",
5499
0
     function );
5500
5501
0
    return( -1 );
5502
0
  }
5503
0
  *unicode_character  = safe_unicode_character;
5504
0
  *utf32_string_index = safe_utf32_string_index + 1;
5505
5506
0
  return( 1 );
5507
0
}
5508
5509
/* Copies an Unicode character into a UTF-32 string
5510
 * Returns 1 if successful or -1 on error
5511
 */
5512
int libuna_unicode_character_copy_to_utf32(
5513
     libuna_unicode_character_t unicode_character,
5514
     libuna_utf32_character_t *utf32_string,
5515
     size_t utf32_string_size,
5516
     size_t *utf32_string_index,
5517
     libcerror_error_t **error )
5518
0
{
5519
0
  static char *function          = "libuna_unicode_character_copy_to_utf32";
5520
0
  size_t safe_utf32_string_index = 0;
5521
5522
0
  if( utf32_string == NULL )
5523
0
  {
5524
0
    libcerror_error_set(
5525
0
     error,
5526
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5527
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5528
0
     "%s: invalid UTF-32 string.",
5529
0
     function );
5530
5531
0
    return( -1 );
5532
0
  }
5533
0
  if( utf32_string_size > (size_t) SSIZE_MAX )
5534
0
  {
5535
0
    libcerror_error_set(
5536
0
     error,
5537
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5538
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5539
0
     "%s: invalid UTF-32 string size value exceeds maximum.",
5540
0
     function );
5541
5542
0
    return( -1 );
5543
0
  }
5544
0
  if( utf32_string_index == NULL )
5545
0
  {
5546
0
    libcerror_error_set(
5547
0
     error,
5548
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5549
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5550
0
     "%s: invalid UTF-32 string index.",
5551
0
     function );
5552
5553
0
    return( -1 );
5554
0
  }
5555
0
  safe_utf32_string_index = *utf32_string_index;
5556
5557
0
  if( safe_utf32_string_index >= utf32_string_size )
5558
0
  {
5559
0
    libcerror_error_set(
5560
0
     error,
5561
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5562
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5563
0
     "%s: UTF-32 string too small.",
5564
0
     function );
5565
5566
0
    return( -1 );
5567
0
  }
5568
  /* Determine if the Unicode character is valid
5569
   */
5570
0
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5571
0
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5572
0
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
5573
0
  {
5574
0
    libcerror_error_set(
5575
0
     error,
5576
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5577
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5578
0
     "%s: unsupported Unicode character.",
5579
0
     function );
5580
5581
0
    return( -1 );
5582
0
  }
5583
0
  utf32_string[ safe_utf32_string_index ] = (libuna_utf32_character_t) unicode_character;
5584
5585
0
  *utf32_string_index = safe_utf32_string_index + 1;
5586
5587
0
  return( 1 );
5588
0
}
5589
5590
/* Copies an Unicode character from an UTF-32 stream
5591
 * Returns 1 if successful or -1 on error
5592
 */
5593
int libuna_unicode_character_copy_from_utf32_stream(
5594
     libuna_unicode_character_t *unicode_character,
5595
     const uint8_t *utf32_stream,
5596
     size_t utf32_stream_size,
5597
     size_t *utf32_stream_index,
5598
     int byte_order,
5599
     libcerror_error_t **error )
5600
0
{
5601
0
  static char *function                             = "libuna_unicode_character_copy_from_utf32_stream";
5602
0
  libuna_unicode_character_t safe_unicode_character = 0;
5603
0
  size_t safe_utf32_stream_index                    = 0;
5604
5605
0
  if( unicode_character == NULL )
5606
0
  {
5607
0
    libcerror_error_set(
5608
0
     error,
5609
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5610
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5611
0
     "%s: invalid Unicode character.",
5612
0
     function );
5613
5614
0
    return( -1 );
5615
0
  }
5616
0
  if( utf32_stream == NULL )
5617
0
  {
5618
0
    libcerror_error_set(
5619
0
     error,
5620
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5621
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5622
0
     "%s: invalid UTF-32 stream.",
5623
0
     function );
5624
5625
0
    return( -1 );
5626
0
  }
5627
0
  if( utf32_stream_size > (size_t) SSIZE_MAX )
5628
0
  {
5629
0
    libcerror_error_set(
5630
0
     error,
5631
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5632
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5633
0
     "%s: invalid UTF-32 stream size value exceeds maximum.",
5634
0
     function );
5635
5636
0
    return( -1 );
5637
0
  }
5638
0
  if( utf32_stream_index == NULL )
5639
0
  {
5640
0
    libcerror_error_set(
5641
0
     error,
5642
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5643
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5644
0
     "%s: invalid UTF-32 stream index.",
5645
0
     function );
5646
5647
0
    return( -1 );
5648
0
  }
5649
0
  safe_utf32_stream_index = *utf32_stream_index;
5650
5651
0
  if( ( utf32_stream_size < 4 )
5652
0
   || ( safe_utf32_stream_index > ( utf32_stream_size - 4 ) ) )
5653
0
  {
5654
0
    libcerror_error_set(
5655
0
     error,
5656
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5657
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5658
0
     "%s: UTF-32 stream too small.",
5659
0
     function );
5660
5661
0
    return( -1 );
5662
0
  }
5663
0
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
5664
0
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
5665
0
  {
5666
0
    libcerror_error_set(
5667
0
     error,
5668
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5669
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
5670
0
     "%s: unsupported byte order.",
5671
0
     function );
5672
5673
0
    return( -1 );
5674
0
  }
5675
0
  if( byte_order == LIBUNA_ENDIAN_BIG )
5676
0
  {
5677
0
    safe_unicode_character   = utf32_stream[ safe_utf32_stream_index ];
5678
0
    safe_unicode_character <<= 8;
5679
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index + 1 ];
5680
0
    safe_unicode_character <<= 8;
5681
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index + 2 ];
5682
0
    safe_unicode_character <<= 8;
5683
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index + 3 ];
5684
0
  }
5685
0
  else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5686
0
  {
5687
0
    safe_unicode_character   = utf32_stream[ safe_utf32_stream_index + 3 ];
5688
0
    safe_unicode_character <<= 8;
5689
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index + 2 ];
5690
0
    safe_unicode_character <<= 8;
5691
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index + 1 ];
5692
0
    safe_unicode_character <<= 8;
5693
0
    safe_unicode_character  += utf32_stream[ safe_utf32_stream_index ];
5694
0
  }
5695
  /* Determine if the Unicode character is valid
5696
   */
5697
0
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5698
0
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5699
0
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
5700
0
  {
5701
0
    libcerror_error_set(
5702
0
     error,
5703
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5704
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5705
0
     "%s: unsupported Unicode character.",
5706
0
     function );
5707
5708
0
    return( -1 );
5709
0
  }
5710
0
  *unicode_character  = safe_unicode_character;
5711
0
  *utf32_stream_index = safe_utf32_stream_index + 4;
5712
5713
0
  return( 1 );
5714
0
}
5715
5716
/* Copies an Unicode character to an UTF-32 stream
5717
 * Returns 1 if successful or -1 on error
5718
 */
5719
int libuna_unicode_character_copy_to_utf32_stream(
5720
     libuna_unicode_character_t unicode_character,
5721
     uint8_t *utf32_stream,
5722
     size_t utf32_stream_size,
5723
     size_t *utf32_stream_index,
5724
     int byte_order,
5725
     libcerror_error_t **error )
5726
0
{
5727
0
  static char *function          = "libuna_unicode_character_copy_to_utf32_stream";
5728
0
  size_t safe_utf32_stream_index = 0;
5729
5730
0
  if( utf32_stream == NULL )
5731
0
  {
5732
0
    libcerror_error_set(
5733
0
     error,
5734
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5735
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5736
0
     "%s: invalid UTF-32 stream.",
5737
0
     function );
5738
5739
0
    return( -1 );
5740
0
  }
5741
0
  if( utf32_stream_size > (size_t) SSIZE_MAX )
5742
0
  {
5743
0
    libcerror_error_set(
5744
0
     error,
5745
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5746
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5747
0
     "%s: invalid UTF-32 stream size value exceeds maximum.",
5748
0
     function );
5749
5750
0
    return( -1 );
5751
0
  }
5752
0
  if( utf32_stream_index == NULL )
5753
0
  {
5754
0
    libcerror_error_set(
5755
0
     error,
5756
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5757
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5758
0
     "%s: invalid UTF-32 stream index.",
5759
0
     function );
5760
5761
0
    return( -1 );
5762
0
  }
5763
0
  safe_utf32_stream_index = *utf32_stream_index;
5764
5765
0
  if( ( utf32_stream_size < 4 )
5766
0
   || ( safe_utf32_stream_index > ( utf32_stream_size - 4 ) ) )
5767
0
  {
5768
0
    libcerror_error_set(
5769
0
     error,
5770
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5771
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5772
0
     "%s: UTF-32 stream too small.",
5773
0
     function );
5774
5775
0
    return( -1 );
5776
0
  }
5777
0
  if( ( byte_order != LIBUNA_ENDIAN_BIG )
5778
0
   && ( byte_order != LIBUNA_ENDIAN_LITTLE ) )
5779
0
  {
5780
0
    libcerror_error_set(
5781
0
     error,
5782
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5783
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
5784
0
     "%s: unsupported byte order.",
5785
0
     function );
5786
5787
0
    return( -1 );
5788
0
  }
5789
  /* Determine if the Unicode character is valid
5790
   */
5791
0
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5792
0
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5793
0
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
5794
0
  {
5795
0
    libcerror_error_set(
5796
0
     error,
5797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5798
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5799
0
     "%s: unsupported Unicode character.",
5800
0
     function );
5801
5802
0
    return( -1 );
5803
0
  }
5804
0
  if( byte_order == LIBUNA_ENDIAN_BIG )
5805
0
  {
5806
0
    utf32_stream[ safe_utf32_stream_index + 3 ] = (uint8_t) ( unicode_character & 0xff );
5807
0
    unicode_character                         >>= 8;
5808
0
    utf32_stream[ safe_utf32_stream_index + 2 ] = (uint8_t) ( unicode_character & 0xff );
5809
0
    unicode_character                         >>= 8;
5810
0
    utf32_stream[ safe_utf32_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5811
0
    unicode_character                         >>= 8;
5812
0
    utf32_stream[ safe_utf32_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5813
0
  }
5814
0
  else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5815
0
  {
5816
0
    utf32_stream[ safe_utf32_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5817
0
    unicode_character                         >>= 8;
5818
0
    utf32_stream[ safe_utf32_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5819
0
    unicode_character                         >>= 8;
5820
0
    utf32_stream[ safe_utf32_stream_index + 2 ] = (uint8_t) ( unicode_character & 0xff );
5821
0
    unicode_character                        >>= 8;
5822
0
    utf32_stream[ safe_utf32_stream_index + 3 ] = (uint8_t) ( unicode_character & 0xff );
5823
0
  }
5824
0
  *utf32_stream_index = safe_utf32_stream_index + 4;
5825
5826
0
  return( 1 );
5827
0
}
5828