Coverage Report

Created: 2026-08-31 07:43

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
14.0k
{
131
14.0k
  static char *function                  = "libuna_unicode_character_size_to_byte_stream";
132
14.0k
  size_t safe_byte_stream_character_size = 0;
133
14.0k
  int result                             = 1;
134
135
14.0k
  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
14.0k
  safe_byte_stream_character_size = *byte_stream_character_size;
147
148
14.0k
  switch( codepage )
149
14.0k
  {
150
14.0k
    case LIBUNA_CODEPAGE_ASCII:
151
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_1:
152
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_2:
153
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_3:
154
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_4:
155
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_5:
156
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_6:
157
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_7:
158
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_8:
159
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_9:
160
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_10:
161
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_11:
162
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_13:
163
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_14:
164
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_15:
165
14.0k
    case LIBUNA_CODEPAGE_ISO_8859_16:
166
14.0k
    case LIBUNA_CODEPAGE_KOI8_R:
167
14.0k
    case LIBUNA_CODEPAGE_KOI8_U:
168
14.0k
    case LIBUNA_CODEPAGE_MAC_ARABIC:
169
14.0k
    case LIBUNA_CODEPAGE_MAC_CELTIC:
170
14.0k
    case LIBUNA_CODEPAGE_MAC_CENTRALEURROMAN:
171
14.0k
    case LIBUNA_CODEPAGE_MAC_CROATIAN:
172
14.0k
    case LIBUNA_CODEPAGE_MAC_CYRILLIC:
173
14.0k
    case LIBUNA_CODEPAGE_MAC_DINGBATS:
174
14.0k
    case LIBUNA_CODEPAGE_MAC_FARSI:
175
14.0k
    case LIBUNA_CODEPAGE_MAC_GAELIC:
176
14.0k
    case LIBUNA_CODEPAGE_MAC_GREEK:
177
14.0k
    case LIBUNA_CODEPAGE_MAC_ICELANDIC:
178
14.0k
    case LIBUNA_CODEPAGE_MAC_INUIT:
179
14.0k
    case LIBUNA_CODEPAGE_MAC_ROMAN:
180
14.0k
    case LIBUNA_CODEPAGE_MAC_ROMANIAN:
181
14.0k
    case LIBUNA_CODEPAGE_MAC_RUSSIAN:
182
14.0k
    case LIBUNA_CODEPAGE_MAC_TURKISH:
183
14.0k
    case LIBUNA_CODEPAGE_MAC_UKRAINIAN:
184
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_874:
185
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1250:
186
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1251:
187
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
188
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1253:
189
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1254:
190
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1255:
191
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1256:
192
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1257:
193
14.0k
    case LIBUNA_CODEPAGE_WINDOWS_1258:
194
14.0k
      safe_byte_stream_character_size += 1;
195
14.0k
      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
14.0k
  }
250
14.0k
  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
14.0k
  *byte_stream_character_size = safe_byte_stream_character_size;
262
263
14.0k
  return( result );
264
14.0k
}
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
203k
{
277
203k
  static char *function                             = "libuna_unicode_character_copy_from_byte_stream";
278
203k
  libuna_unicode_character_t safe_unicode_character = 0;
279
203k
  size_t safe_byte_stream_index                     = 0;
280
203k
  uint8_t byte_stream_character                     = 0;
281
203k
  int result                                        = 1;
282
283
203k
  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
203k
  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
203k
  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
203k
  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
203k
  safe_byte_stream_index = *byte_stream_index;
328
329
203k
  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
203k
  byte_stream_character = byte_stream[ safe_byte_stream_index ];
341
342
203k
  switch( codepage )
343
203k
  {
344
114k
    case LIBUNA_CODEPAGE_ASCII:
345
114k
      if( byte_stream_character < 0x80 )
346
112k
      {
347
112k
        safe_unicode_character = byte_stream_character;
348
112k
      }
349
2.66k
      else
350
2.66k
      {
351
2.66k
        safe_unicode_character = 0xfffd;
352
2.66k
      }
353
114k
      safe_byte_stream_index += 1;
354
355
114k
      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.0k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
829
89.0k
      result = libuna_codepage_windows_1252_copy_from_byte_stream(
830
89.0k
                &safe_unicode_character,
831
89.0k
                byte_stream,
832
89.0k
                byte_stream_size,
833
89.0k
                &safe_byte_stream_index,
834
89.0k
                error );
835
89.0k
      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
203k
  }
902
203k
  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
203k
  *unicode_character = safe_unicode_character;
914
203k
  *byte_stream_index = safe_byte_stream_index;
915
916
203k
  return( result );
917
203k
}
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
14.0k
{
930
14.0k
  static char *function         = "libuna_unicode_character_copy_to_byte_stream";
931
14.0k
  size_t safe_byte_stream_index = 0;
932
14.0k
  int result                    = 1;
933
934
14.0k
  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
14.0k
  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
14.0k
  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
14.0k
  safe_byte_stream_index = *byte_stream_index;
968
969
14.0k
  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
14.0k
  switch( codepage )
981
14.0k
  {
982
14.0k
    case LIBUNA_CODEPAGE_ASCII:
983
14.0k
      if( unicode_character < 0x0080 )
984
14.0k
      {
985
14.0k
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
986
14.0k
      }
987
0
      else
988
0
      {
989
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
990
0
      }
991
14.0k
      safe_byte_stream_index += 1;
992
993
14.0k
      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
14.0k
  }
2133
14.0k
  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
14.0k
  *byte_stream_index = safe_byte_stream_index;
2145
2146
14.0k
  return( result );
2147
14.0k
}
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.62k
{
2158
1.62k
  static char *function = "libuna_unicode_character_size_to_ucs2";
2159
2160
1.62k
  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.62k
  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.62k
  if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
2186
8
  {
2187
8
    *ucs2_character_size += 2;
2188
8
  }
2189
1.61k
  else
2190
1.61k
  {
2191
1.61k
    *ucs2_character_size += 1;
2192
1.61k
  }
2193
1.62k
  return( 1 );
2194
1.62k
}
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.60M
{
3711
7.60M
  static char *function           = "libuna_unicode_character_size_to_utf8";
3712
7.60M
  size_t safe_utf8_character_size = 0;
3713
3714
7.60M
  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.60M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
3728
232k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
3729
7.60M
   || ( 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.60M
  if( unicode_character < 0x00000080UL )
3744
4.75M
  {
3745
4.75M
    safe_utf8_character_size += 1;
3746
4.75M
  }
3747
2.85M
  else if( unicode_character < 0x00000800UL )
3748
211k
  {
3749
211k
    safe_utf8_character_size += 2;
3750
211k
  }
3751
2.64M
  else if( unicode_character < 0x00010000UL )
3752
2.61M
  {
3753
2.61M
    safe_utf8_character_size += 3;
3754
2.61M
  }
3755
23.3k
  else
3756
23.3k
  {
3757
23.3k
    safe_utf8_character_size += 4;
3758
23.3k
  }
3759
7.60M
  *utf8_character_size += safe_utf8_character_size;
3760
3761
7.60M
  return( 1 );
3762
7.60M
}
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
4.31M
{
3775
4.31M
  static char *function                             = "libuna_unicode_character_copy_from_utf8";
3776
4.31M
  libuna_unicode_character_t safe_unicode_character = 0;
3777
4.31M
  size_t safe_utf8_string_index                     = 0;
3778
4.31M
  uint8_t byte_value1                               = 0;
3779
4.31M
  uint8_t byte_value2                               = 0;
3780
4.31M
  uint8_t byte_value3                               = 0;
3781
4.31M
  uint8_t byte_value4                               = 0;
3782
4.31M
  uint8_t utf8_character_additional_bytes           = 0;
3783
4.31M
  int result                                        = 0;
3784
3785
4.31M
  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
4.31M
  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
4.31M
  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
4.31M
  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
4.31M
  safe_utf8_string_index = *utf8_string_index;
3830
3831
4.31M
  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
4.31M
  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
4.31M
  if( byte_value1 > 0xf4 )
3851
561
  {
3852
561
    libcerror_error_set(
3853
561
     error,
3854
561
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3855
561
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3856
561
     "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3857
561
     function,
3858
561
     byte_value1 );
3859
3860
561
    return( -1 );
3861
561
  }
3862
4.31M
  if( byte_value1 < 0xc0 )
3863
4.28M
  {
3864
4.28M
    utf8_character_additional_bytes = 0;
3865
4.28M
  }
3866
32.0k
  else if( byte_value1 < 0xe0 )
3867
6.57k
  {
3868
6.57k
    utf8_character_additional_bytes = 1;
3869
6.57k
  }
3870
25.4k
  else if( byte_value1 < 0xf0 )
3871
15.9k
  {
3872
15.9k
    utf8_character_additional_bytes = 2;
3873
15.9k
  }
3874
9.50k
  else
3875
9.50k
  {
3876
9.50k
    utf8_character_additional_bytes = 3;
3877
9.50k
  }
3878
4.31M
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
3879
4.31M
   || ( 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
4.31M
  safe_unicode_character = byte_value1;
3891
3892
4.31M
  if( utf8_character_additional_bytes == 0 )
3893
4.28M
  {
3894
4.28M
    if( byte_value1 >= 0x80 )
3895
544
    {
3896
544
      libcerror_error_set(
3897
544
       error,
3898
544
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3899
544
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3900
544
       "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3901
544
       function,
3902
544
       byte_value1 );
3903
3904
544
      return( -1 );
3905
544
    }
3906
4.28M
  }
3907
4.31M
  if( utf8_character_additional_bytes >= 1 )
3908
31.8k
  {
3909
31.8k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
3910
3911
31.8k
    if( ( byte_value2 < 0x80 )
3912
31.5k
     || ( byte_value2 > 0xbf ) )
3913
635
    {
3914
635
      libcerror_error_set(
3915
635
       error,
3916
635
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3917
635
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3918
635
       "%s: invalid 2nd UTF-8 character byte: 0x%02" PRIx8 ".",
3919
635
       function,
3920
635
       byte_value2 );
3921
3922
635
      return( -1 );
3923
635
    }
3924
31.2k
    result = 1;
3925
3926
31.2k
    switch( byte_value1 )
3927
31.2k
    {
3928
6.26k
      case 0xe0:
3929
6.26k
        if( ( byte_value2 < 0xa0 )
3930
6.14k
         || ( byte_value2 > 0xbf ) )
3931
115
        {
3932
115
          result = 0;
3933
115
        }
3934
6.26k
        break;
3935
3936
3.35k
      case 0xed:
3937
3.35k
        if( ( byte_value2 < 0x80 )
3938
3.35k
         || ( byte_value2 > 0x9f ) )
3939
68
        {
3940
68
          result = 0;
3941
68
        }
3942
3.35k
        break;
3943
3944
4.81k
      case 0xf0:
3945
4.81k
        if( ( byte_value2 < 0x90 )
3946
4.71k
         || ( byte_value2 > 0xbf ) )
3947
103
        {
3948
103
          result = 0;
3949
103
        }
3950
4.81k
        break;
3951
3952
1.19k
      case 0xf4:
3953
1.19k
        if( ( byte_value2 < 0x80 )
3954
1.19k
         || ( byte_value2 > 0xbf ) )
3955
0
        {
3956
0
          result = 0;
3957
0
        }
3958
1.19k
        break;
3959
3960
15.6k
      default:
3961
15.6k
        break;
3962
31.2k
    }
3963
31.2k
    if( result == 0 )
3964
286
    {
3965
286
      libcerror_error_set(
3966
286
       error,
3967
286
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3968
286
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3969
286
       "%s: invalid 1st and 2nd UTF-8 character byte pair: 0x%02" PRIx8 " 0x%02" PRIx8 ".",
3970
286
       function,
3971
286
       byte_value1,
3972
286
       byte_value2 );
3973
3974
286
      return( -1 );
3975
286
    }
3976
30.9k
    safe_unicode_character <<= 6;
3977
30.9k
    safe_unicode_character += byte_value2;
3978
3979
30.9k
    if( utf8_character_additional_bytes == 1 )
3980
6.32k
    {
3981
6.32k
      safe_unicode_character -= 0x03080;
3982
6.32k
    }
3983
30.9k
  }
3984
4.31M
  if( utf8_character_additional_bytes >= 2 )
3985
24.6k
  {
3986
24.6k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
3987
3988
24.6k
    if( ( byte_value3 < 0x80 )
3989
24.4k
     || ( byte_value3 > 0xbf ) )
3990
340
    {
3991
340
      libcerror_error_set(
3992
340
       error,
3993
340
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3994
340
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3995
340
       "%s: invalid 3rd UTF-8 character byte: 0x%02" PRIx8 ".",
3996
340
       function,
3997
340
       byte_value3 );
3998
3999
340
      return( -1 );
4000
340
    }
4001
24.2k
    result = 1;
4002
4003
24.2k
    switch( byte_value2 )
4004
24.2k
    {
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.2k
      default:
4022
24.2k
        break;
4023
24.2k
    }
4024
24.2k
    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.2k
    safe_unicode_character <<= 6;
4038
24.2k
    safe_unicode_character += byte_value3;
4039
4040
24.2k
    if( utf8_character_additional_bytes == 2 )
4041
15.1k
    {
4042
15.1k
      safe_unicode_character -= 0x0e2080;
4043
15.1k
    }
4044
24.2k
  }
4045
4.31M
  if( utf8_character_additional_bytes >= 3 )
4046
9.17k
  {
4047
9.17k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4048
4049
9.17k
    if( ( byte_value4 < 0x80 )
4050
9.12k
     || ( byte_value4 > 0xbf ) )
4051
205
    {
4052
205
      libcerror_error_set(
4053
205
       error,
4054
205
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4055
205
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4056
205
       "%s: invalid 4th UTF-8 character byte: 0x%02" PRIx8 ".",
4057
205
       function,
4058
205
       byte_value4 );
4059
4060
205
      return( -1 );
4061
205
    }
4062
8.97k
    safe_unicode_character <<= 6;
4063
8.97k
    safe_unicode_character += byte_value4;
4064
4065
8.97k
    if( utf8_character_additional_bytes == 3 )
4066
8.97k
    {
4067
8.97k
      safe_unicode_character -= 0x03c82080;
4068
8.97k
    }
4069
8.97k
  }
4070
  /* Determine if the Unicode character is valid
4071
   */
4072
4.31M
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4073
13.2k
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4074
4.31M
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4075
53
  {
4076
53
    libcerror_error_set(
4077
53
     error,
4078
53
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4079
53
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4080
53
     "%s: unsupported Unicode character.",
4081
53
     function );
4082
4083
53
    return( -1 );
4084
53
  }
4085
4.31M
  *unicode_character = safe_unicode_character;
4086
4.31M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4087
4088
4.31M
  return( 1 );
4089
4.31M
}
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
2.97M
{
4102
2.97M
  static char *function                   = "libuna_unicode_character_copy_to_utf8";
4103
2.97M
  size_t safe_utf8_string_index           = 0;
4104
2.97M
  size_t utf8_character_iterator          = 0;
4105
2.97M
  uint8_t utf8_character_additional_bytes = 0;
4106
2.97M
  uint8_t utf8_first_character_mark       = 0;
4107
4108
2.97M
  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
2.97M
  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
2.97M
  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
2.97M
  safe_utf8_string_index = *utf8_string_index;
4142
4143
2.97M
  if( safe_utf8_string_index >= utf8_string_size )
4144
490
  {
4145
490
    libcerror_error_set(
4146
490
     error,
4147
490
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4148
490
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4149
490
     "%s: UTF-8 string too small.",
4150
490
     function );
4151
4152
490
    return( -1 );
4153
490
  }
4154
  /* Determine if the Unicode character is valid
4155
   */
4156
2.97M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4157
91.3k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4158
2.97M
   || ( 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
2.97M
  if( unicode_character < 0x080 )
4172
736k
  {
4173
736k
    utf8_character_additional_bytes = 0;
4174
736k
    utf8_first_character_mark       = 0;
4175
736k
  }
4176
2.23M
  else if( unicode_character < 0x0800 )
4177
98.3k
  {
4178
98.3k
    utf8_character_additional_bytes = 1;
4179
98.3k
    utf8_first_character_mark       = 0x0c0;
4180
98.3k
  }
4181
2.13M
  else if( unicode_character < 0x010000 )
4182
2.13M
  {
4183
2.13M
    utf8_character_additional_bytes = 2;
4184
2.13M
    utf8_first_character_mark       = 0x0e0;
4185
2.13M
  }
4186
4.10k
  else
4187
4.10k
  {
4188
4.10k
    utf8_character_additional_bytes = 3;
4189
4.10k
    utf8_first_character_mark       = 0x0f0;
4190
4.10k
  }
4191
  /* Convert Unicode character into UTF-8 character bytes
4192
   */
4193
2.97M
  if( ( utf8_character_additional_bytes > utf8_string_size )
4194
2.97M
   || ( safe_utf8_string_index >= ( utf8_string_size - utf8_character_additional_bytes ) ) )
4195
517
  {
4196
517
    libcerror_error_set(
4197
517
     error,
4198
517
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4199
517
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4200
517
     "%s: UTF-8 string too small.",
4201
517
     function );
4202
4203
517
    return( -1 );
4204
517
  }
4205
2.96M
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4206
7.34M
       utf8_character_iterator > safe_utf8_string_index;
4207
4.37M
       utf8_character_iterator-- )
4208
4.37M
  {
4209
4.37M
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4210
4211
4.37M
    unicode_character >>= 6;
4212
4.37M
  }
4213
2.96M
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4214
4215
2.96M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4216
4217
2.96M
  return( 1 );
4218
2.97M
}
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
15.2k
{
4230
15.2k
  static char *function           = "libuna_unicode_character_size_to_utf8_rfc2279";
4231
15.2k
  size_t safe_utf8_character_size = 0;
4232
4233
15.2k
  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
15.2k
  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
15.2k
  if( unicode_character < 0x00000080UL )
4259
2.60k
  {
4260
2.60k
    safe_utf8_character_size += 1;
4261
2.60k
  }
4262
12.6k
  else if( unicode_character < 0x00000800UL )
4263
886
  {
4264
886
    safe_utf8_character_size += 2;
4265
886
  }
4266
11.7k
  else if( unicode_character < 0x00010000UL )
4267
11.6k
  {
4268
11.6k
    safe_utf8_character_size += 3;
4269
11.6k
  }
4270
135
  else if( unicode_character < 0x00200000UL )
4271
135
  {
4272
135
    safe_utf8_character_size += 4;
4273
135
  }
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
15.2k
  *utf8_character_size += safe_utf8_character_size;
4283
4284
15.2k
  return( 1 );
4285
15.2k
}
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
96.6k
{
4298
96.6k
  static char *function                             = "libuna_unicode_character_copy_from_utf8_rfc2279";
4299
96.6k
  libuna_unicode_character_t safe_unicode_character = 0;
4300
96.6k
  size_t safe_utf8_string_index                     = 0;
4301
96.6k
  uint8_t byte_value1                               = 0;
4302
96.6k
  uint8_t byte_value2                               = 0;
4303
96.6k
  uint8_t byte_value3                               = 0;
4304
96.6k
  uint8_t byte_value4                               = 0;
4305
96.6k
  uint8_t byte_value5                               = 0;
4306
96.6k
  uint8_t byte_value6                               = 0;
4307
96.6k
  uint8_t utf8_character_additional_bytes           = 0;
4308
4309
96.6k
  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
96.6k
  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
96.6k
  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
96.6k
  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
96.6k
  safe_utf8_string_index = *utf8_string_index;
4354
4355
96.6k
  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
96.6k
  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
96.6k
  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
96.6k
  if( byte_value1 < 0xc0 )
4387
51.4k
  {
4388
51.4k
    utf8_character_additional_bytes = 0;
4389
51.4k
  }
4390
45.1k
  else if( byte_value1 < 0xe0 )
4391
11.9k
  {
4392
11.9k
    utf8_character_additional_bytes = 1;
4393
11.9k
  }
4394
33.1k
  else if( byte_value1 < 0xf0 )
4395
28.3k
  {
4396
28.3k
    utf8_character_additional_bytes = 2;
4397
28.3k
  }
4398
4.84k
  else if( byte_value1 < 0xf8 )
4399
4.84k
  {
4400
4.84k
    utf8_character_additional_bytes = 3;
4401
4.84k
  }
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
96.6k
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
4411
96.6k
   || ( 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
96.6k
  safe_unicode_character = byte_value1;
4427
4428
96.6k
  if( utf8_character_additional_bytes == 0 )
4429
51.4k
  {
4430
51.4k
    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
51.4k
  }
4443
96.6k
  if( utf8_character_additional_bytes >= 1 )
4444
45.1k
  {
4445
45.1k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
4446
4447
45.1k
    if( ( byte_value2 < 0x80 )
4448
45.1k
     || ( 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
45.1k
    safe_unicode_character <<= 6;
4461
45.1k
    safe_unicode_character += byte_value2;
4462
4463
45.1k
    if( utf8_character_additional_bytes == 1 )
4464
11.9k
    {
4465
11.9k
      safe_unicode_character -= 0x03080;
4466
11.9k
    }
4467
45.1k
  }
4468
96.6k
  if( utf8_character_additional_bytes >= 2 )
4469
33.1k
  {
4470
33.1k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
4471
4472
33.1k
    if( ( byte_value3 < 0x80 )
4473
33.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
33.1k
    safe_unicode_character <<= 6;
4486
33.1k
    safe_unicode_character += byte_value3;
4487
4488
33.1k
    if( utf8_character_additional_bytes == 2 )
4489
28.3k
    {
4490
28.3k
      safe_unicode_character -= 0x0e2080;
4491
28.3k
    }
4492
33.1k
  }
4493
96.6k
  if( utf8_character_additional_bytes >= 3 )
4494
4.84k
  {
4495
4.84k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4496
4497
4.84k
    if( ( byte_value4 < 0x80 )
4498
4.84k
     || ( 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
4.84k
    safe_unicode_character <<= 6;
4511
4.84k
    safe_unicode_character += byte_value4;
4512
4513
4.84k
    if( utf8_character_additional_bytes == 3 )
4514
4.84k
    {
4515
4.84k
      safe_unicode_character -= 0x03c82080;
4516
4.84k
    }
4517
4.84k
  }
4518
96.6k
  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
96.6k
  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
96.6k
  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
96.6k
  *unicode_character = safe_unicode_character;
4578
96.6k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4579
4580
96.6k
  return( 1 );
4581
96.6k
}
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
15.2k
{
4594
15.2k
  static char *function                   = "libuna_unicode_character_copy_to_utf8_rfc2279";
4595
15.2k
  size_t safe_utf8_string_index           = 0;
4596
15.2k
  size_t utf8_character_iterator          = 0;
4597
15.2k
  uint8_t utf8_character_additional_bytes = 0;
4598
15.2k
  uint8_t utf8_first_character_mark       = 0;
4599
4600
15.2k
  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
15.2k
  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
15.2k
  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
15.2k
  safe_utf8_string_index = *utf8_string_index;
4634
4635
15.2k
  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
15.2k
  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
15.2k
  if( unicode_character < 0x080 )
4662
2.60k
  {
4663
2.60k
    utf8_character_additional_bytes = 0;
4664
2.60k
    utf8_first_character_mark       = 0;
4665
2.60k
  }
4666
12.6k
  else if( unicode_character < 0x0800 )
4667
886
  {
4668
886
    utf8_character_additional_bytes = 1;
4669
886
    utf8_first_character_mark       = 0x0c0;
4670
886
  }
4671
11.7k
  else if( unicode_character < 0x010000 )
4672
11.6k
  {
4673
11.6k
    utf8_character_additional_bytes = 2;
4674
11.6k
    utf8_first_character_mark       = 0x0e0;
4675
11.6k
  }
4676
135
  else if( unicode_character < 0x0200000 )
4677
135
  {
4678
135
    utf8_character_additional_bytes = 3;
4679
135
    utf8_first_character_mark       = 0x0f0;
4680
135
  }
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
15.2k
  if( ( utf8_character_additional_bytes > utf8_string_size )
4694
15.2k
   || ( 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
15.2k
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4706
39.8k
       utf8_character_iterator > safe_utf8_string_index;
4707
24.5k
       utf8_character_iterator-- )
4708
24.5k
  {
4709
24.5k
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4710
4711
24.5k
    unicode_character >>= 6;
4712
24.5k
  }
4713
15.2k
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4714
4715
15.2k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4716
4717
15.2k
  return( 1 );
4718
15.2k
}
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.8k
{
4729
26.8k
  static char *function = "libuna_unicode_character_size_to_utf16";
4730
4731
26.8k
  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.8k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4743
659
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4744
26.8k
   || ( 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.8k
  if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4756
257
  {
4757
257
    *utf16_character_size += 2;
4758
257
  }
4759
26.6k
  else
4760
26.6k
  {
4761
26.6k
    *utf16_character_size += 1;
4762
26.6k
  }
4763
26.8k
  return( 1 );
4764
26.8k
}
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
8.27k
{
4913
8.27k
  static char *function          = "libuna_unicode_character_copy_to_utf16";
4914
8.27k
  size_t safe_utf16_string_index = 0;
4915
4916
8.27k
  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
8.27k
  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
8.27k
  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
8.27k
  safe_utf16_string_index = *utf16_string_index;
4950
4951
8.27k
  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
8.27k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4965
1.42k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4966
8.27k
   || ( 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
8.27k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4978
7.95k
  {
4979
7.95k
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) unicode_character;
4980
7.95k
  }
4981
320
  else
4982
320
  {
4983
320
    if( ( utf16_string_size < 2 )
4984
320
     || ( 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
320
    unicode_character                        -= 0x010000;
4996
320
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
4997
320
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
4998
320
  }
4999
8.27k
  *utf16_string_index = safe_utf16_string_index;
5000
5001
8.27k
  return( 1 );
5002
8.27k
}
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
9.48M
{
5015
9.48M
  static char *function                             = "libuna_unicode_character_copy_from_utf16_stream";
5016
9.48M
  libuna_unicode_character_t safe_unicode_character = 0;
5017
9.48M
  libuna_utf16_character_t utf16_surrogate          = 0;
5018
9.48M
  size_t safe_utf16_stream_index                    = 0;
5019
9.48M
  int byte_order_without_flags                      = 0;
5020
5021
9.48M
  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
9.48M
  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
9.48M
  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
9.48M
  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
9.48M
  byte_order_without_flags = byte_order & 0xff;
5066
5067
9.48M
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5068
6.03M
   && ( 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
9.48M
  safe_utf16_stream_index = *utf16_stream_index;
5080
5081
9.48M
  if( ( utf16_stream_size < 2 )
5082
9.48M
   || ( safe_utf16_stream_index > ( utf16_stream_size - 2 ) ) )
5083
68
  {
5084
68
    libcerror_error_set(
5085
68
     error,
5086
68
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5087
68
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5088
68
     "%s: UTF-16 stream too small.",
5089
68
     function );
5090
5091
68
    return( -1 );
5092
68
  }
5093
9.48M
  if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5094
3.45M
  {
5095
3.45M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index ];
5096
3.45M
    safe_unicode_character <<= 8;
5097
3.45M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index + 1 ];
5098
3.45M
  }
5099
6.03M
  else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5100
6.03M
  {
5101
6.03M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index + 1 ];
5102
6.03M
    safe_unicode_character <<= 8;
5103
6.03M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index ];
5104
6.03M
  }
5105
9.48M
  safe_utf16_stream_index += 2;
5106
5107
  /* Determine if the Unicode character is valid
5108
   */
5109
9.48M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5110
730k
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5111
2.26k
  {
5112
2.26k
    if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5113
591
    {
5114
591
      libcerror_error_set(
5115
591
       error,
5116
591
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5117
591
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5118
591
       "%s: unsupported UTF-16 character.",
5119
591
       function );
5120
5121
591
      return( -1 );
5122
591
    }
5123
2.26k
  }
5124
  /* Determine if the UTF-16 character is within the high surrogate range
5125
   */
5126
9.48M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5127
826k
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
5128
96.2k
  {
5129
96.2k
    if( safe_utf16_stream_index > ( utf16_stream_size - 2 ) )
5130
96
    {
5131
96
      if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5132
44
      {
5133
44
        libcerror_error_set(
5134
44
         error,
5135
44
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5136
44
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5137
44
         "%s: missing surrogate UTF-16 character bytes.",
5138
44
         function );
5139
5140
44
        return( -1 );
5141
44
      }
5142
96
    }
5143
96.1k
    else
5144
96.1k
    {
5145
96.1k
      if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5146
79.3k
      {
5147
79.3k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index ];
5148
79.3k
        utf16_surrogate <<= 8;
5149
79.3k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index + 1 ];
5150
79.3k
      }
5151
16.8k
      else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5152
16.8k
      {
5153
16.8k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index + 1 ];
5154
16.8k
        utf16_surrogate <<= 8;
5155
16.8k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index ];
5156
16.8k
      }
5157
      /* Determine if the UTF-16 character is within the low surrogate range
5158
       */
5159
96.1k
      if( ( utf16_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5160
92.4k
       && ( utf16_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5161
91.8k
      {
5162
91.8k
        safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
5163
91.8k
        safe_unicode_character <<= 10;
5164
91.8k
        safe_unicode_character  += utf16_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
5165
91.8k
        safe_unicode_character  += 0x010000;
5166
5167
91.8k
        safe_utf16_stream_index += 2;
5168
91.8k
      }
5169
4.27k
      else if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5170
768
      {
5171
768
        libcerror_error_set(
5172
768
         error,
5173
768
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5174
768
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5175
768
         "%s: unsupported low surrogate UTF-16 character.",
5176
768
         function );
5177
5178
768
        return( -1 );
5179
768
      }
5180
96.1k
    }
5181
96.2k
  }
5182
9.48M
  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
9.48M
  *unicode_character  = safe_unicode_character;
5194
9.48M
  *utf16_stream_index = safe_utf16_stream_index;
5195
5196
9.48M
  return( 1 );
5197
9.48M
}
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.2k
{
5210
21.2k
  static char *function                    = "libuna_unicode_character_copy_to_utf16_stream";
5211
21.2k
  libuna_utf16_character_t utf16_surrogate = 0;
5212
21.2k
  size_t safe_utf16_stream_index           = 0;
5213
21.2k
  int byte_order_without_flags             = 0;
5214
5215
21.2k
  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.2k
  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.2k
  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.2k
  byte_order_without_flags = byte_order & 0xff;
5249
5250
21.2k
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5251
21.2k
   && ( 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.2k
  safe_utf16_stream_index = *utf16_stream_index;
5263
5264
  /* Determine if the Unicode character is valid
5265
   */
5266
21.2k
  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.2k
  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.2k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
5293
21.2k
  {
5294
21.2k
    if( ( utf16_stream_size < 2 )
5295
21.2k
     || ( 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.2k
    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.2k
    else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5313
21.2k
    {
5314
21.2k
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5315
21.2k
      unicode_character                         >>= 8;
5316
21.2k
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5317
21.2k
    }
5318
21.2k
    safe_utf16_stream_index += 2;
5319
21.2k
  }
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.2k
  *utf16_stream_index = safe_utf16_stream_index;
5369
5370
21.2k
  return( 1 );
5371
21.2k
}
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