Coverage Report

Created: 2026-07-10 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpff/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
15.7k
{
131
15.7k
  static char *function                  = "libuna_unicode_character_size_to_byte_stream";
132
15.7k
  size_t safe_byte_stream_character_size = 0;
133
15.7k
  int result                             = 1;
134
135
15.7k
  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
15.7k
  safe_byte_stream_character_size = *byte_stream_character_size;
147
148
15.7k
  switch( codepage )
149
15.7k
  {
150
15.7k
    case LIBUNA_CODEPAGE_ASCII:
151
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_1:
152
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_2:
153
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_3:
154
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_4:
155
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_5:
156
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_6:
157
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_7:
158
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_8:
159
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_9:
160
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_10:
161
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_11:
162
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_13:
163
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_14:
164
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_15:
165
15.7k
    case LIBUNA_CODEPAGE_ISO_8859_16:
166
15.7k
    case LIBUNA_CODEPAGE_KOI8_R:
167
15.7k
    case LIBUNA_CODEPAGE_KOI8_U:
168
15.7k
    case LIBUNA_CODEPAGE_MAC_ARABIC:
169
15.7k
    case LIBUNA_CODEPAGE_MAC_CELTIC:
170
15.7k
    case LIBUNA_CODEPAGE_MAC_CENTRALEURROMAN:
171
15.7k
    case LIBUNA_CODEPAGE_MAC_CROATIAN:
172
15.7k
    case LIBUNA_CODEPAGE_MAC_CYRILLIC:
173
15.7k
    case LIBUNA_CODEPAGE_MAC_DINGBATS:
174
15.7k
    case LIBUNA_CODEPAGE_MAC_FARSI:
175
15.7k
    case LIBUNA_CODEPAGE_MAC_GAELIC:
176
15.7k
    case LIBUNA_CODEPAGE_MAC_GREEK:
177
15.7k
    case LIBUNA_CODEPAGE_MAC_ICELANDIC:
178
15.7k
    case LIBUNA_CODEPAGE_MAC_INUIT:
179
15.7k
    case LIBUNA_CODEPAGE_MAC_ROMAN:
180
15.7k
    case LIBUNA_CODEPAGE_MAC_ROMANIAN:
181
15.7k
    case LIBUNA_CODEPAGE_MAC_RUSSIAN:
182
15.7k
    case LIBUNA_CODEPAGE_MAC_TURKISH:
183
15.7k
    case LIBUNA_CODEPAGE_MAC_UKRAINIAN:
184
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_874:
185
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1250:
186
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1251:
187
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
188
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1253:
189
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1254:
190
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1255:
191
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1256:
192
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1257:
193
15.7k
    case LIBUNA_CODEPAGE_WINDOWS_1258:
194
15.7k
      safe_byte_stream_character_size += 1;
195
15.7k
      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
15.7k
  }
250
15.7k
  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
15.7k
  *byte_stream_character_size = safe_byte_stream_character_size;
262
263
15.7k
  return( result );
264
15.7k
}
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
207k
{
277
207k
  static char *function                             = "libuna_unicode_character_copy_from_byte_stream";
278
207k
  libuna_unicode_character_t safe_unicode_character = 0;
279
207k
  size_t safe_byte_stream_index                     = 0;
280
207k
  uint8_t byte_stream_character                     = 0;
281
207k
  int result                                        = 1;
282
283
207k
  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
207k
  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
207k
  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
207k
  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
207k
  safe_byte_stream_index = *byte_stream_index;
328
329
207k
  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
207k
  byte_stream_character = byte_stream[ safe_byte_stream_index ];
341
342
207k
  switch( codepage )
343
207k
  {
344
116k
    case LIBUNA_CODEPAGE_ASCII:
345
116k
      if( byte_stream_character < 0x80 )
346
113k
      {
347
113k
        safe_unicode_character = byte_stream_character;
348
113k
      }
349
2.72k
      else
350
2.72k
      {
351
2.72k
        safe_unicode_character = 0xfffd;
352
2.72k
      }
353
116k
      safe_byte_stream_index += 1;
354
355
116k
      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
91.8k
    case LIBUNA_CODEPAGE_WINDOWS_1252:
829
91.8k
      result = libuna_codepage_windows_1252_copy_from_byte_stream(
830
91.8k
                &safe_unicode_character,
831
91.8k
                byte_stream,
832
91.8k
                byte_stream_size,
833
91.8k
                &safe_byte_stream_index,
834
91.8k
                error );
835
91.8k
      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
207k
  }
902
207k
  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
207k
  *unicode_character = safe_unicode_character;
914
207k
  *byte_stream_index = safe_byte_stream_index;
915
916
207k
  return( result );
917
207k
}
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
15.7k
{
930
15.7k
  static char *function         = "libuna_unicode_character_copy_to_byte_stream";
931
15.7k
  size_t safe_byte_stream_index = 0;
932
15.7k
  int result                    = 1;
933
934
15.7k
  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
15.7k
  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
15.7k
  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
15.7k
  safe_byte_stream_index = *byte_stream_index;
968
969
15.7k
  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
15.7k
  switch( codepage )
981
15.7k
  {
982
15.7k
    case LIBUNA_CODEPAGE_ASCII:
983
15.7k
      if( unicode_character < 0x0080 )
984
15.7k
      {
985
15.7k
        byte_stream[ safe_byte_stream_index ] = (uint8_t) unicode_character;
986
15.7k
      }
987
0
      else
988
0
      {
989
0
        byte_stream[ safe_byte_stream_index ] = 0x1a;
990
0
      }
991
15.7k
      safe_byte_stream_index += 1;
992
993
15.7k
      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
15.7k
  }
2133
15.7k
  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
15.7k
  *byte_stream_index = safe_byte_stream_index;
2145
2146
15.7k
  return( result );
2147
15.7k
}
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
9.47M
{
3711
9.47M
  static char *function           = "libuna_unicode_character_size_to_utf8";
3712
9.47M
  size_t safe_utf8_character_size = 0;
3713
3714
9.47M
  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
9.47M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
3728
285k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
3729
9.47M
   || ( 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
9.47M
  if( unicode_character < 0x00000080UL )
3744
5.84M
  {
3745
5.84M
    safe_utf8_character_size += 1;
3746
5.84M
  }
3747
3.63M
  else if( unicode_character < 0x00000800UL )
3748
232k
  {
3749
232k
    safe_utf8_character_size += 2;
3750
232k
  }
3751
3.40M
  else if( unicode_character < 0x00010000UL )
3752
3.37M
  {
3753
3.37M
    safe_utf8_character_size += 3;
3754
3.37M
  }
3755
26.5k
  else
3756
26.5k
  {
3757
26.5k
    safe_utf8_character_size += 4;
3758
26.5k
  }
3759
9.47M
  *utf8_character_size += safe_utf8_character_size;
3760
3761
9.47M
  return( 1 );
3762
9.47M
}
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
5.32M
{
3775
5.32M
  static char *function                             = "libuna_unicode_character_copy_from_utf8";
3776
5.32M
  libuna_unicode_character_t safe_unicode_character = 0;
3777
5.32M
  size_t safe_utf8_string_index                     = 0;
3778
5.32M
  uint8_t byte_value1                               = 0;
3779
5.32M
  uint8_t byte_value2                               = 0;
3780
5.32M
  uint8_t byte_value3                               = 0;
3781
5.32M
  uint8_t byte_value4                               = 0;
3782
5.32M
  uint8_t utf8_character_additional_bytes           = 0;
3783
5.32M
  int result                                        = 0;
3784
3785
5.32M
  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
5.32M
  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
5.32M
  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
5.32M
  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
5.32M
  safe_utf8_string_index = *utf8_string_index;
3830
3831
5.32M
  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
5.32M
  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
5.32M
  if( byte_value1 > 0xf4 )
3851
648
  {
3852
648
    libcerror_error_set(
3853
648
     error,
3854
648
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3855
648
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3856
648
     "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3857
648
     function,
3858
648
     byte_value1 );
3859
3860
648
    return( -1 );
3861
648
  }
3862
5.32M
  if( byte_value1 < 0xc0 )
3863
5.29M
  {
3864
5.29M
    utf8_character_additional_bytes = 0;
3865
5.29M
  }
3866
33.6k
  else if( byte_value1 < 0xe0 )
3867
6.59k
  {
3868
6.59k
    utf8_character_additional_bytes = 1;
3869
6.59k
  }
3870
27.0k
  else if( byte_value1 < 0xf0 )
3871
17.6k
  {
3872
17.6k
    utf8_character_additional_bytes = 2;
3873
17.6k
  }
3874
9.46k
  else
3875
9.46k
  {
3876
9.46k
    utf8_character_additional_bytes = 3;
3877
9.46k
  }
3878
5.32M
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
3879
5.32M
   || ( safe_utf8_string_index > ( utf8_string_size - ( utf8_character_additional_bytes + 1 ) ) ) )
3880
161
  {
3881
161
    libcerror_error_set(
3882
161
     error,
3883
161
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3884
161
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
3885
161
     "%s: missing UTF-8 character bytes.",
3886
161
     function );
3887
3888
161
    return( -1 );
3889
161
  }
3890
5.32M
  safe_unicode_character = byte_value1;
3891
3892
5.32M
  if( utf8_character_additional_bytes == 0 )
3893
5.29M
  {
3894
5.29M
    if( byte_value1 >= 0x80 )
3895
545
    {
3896
545
      libcerror_error_set(
3897
545
       error,
3898
545
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3899
545
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3900
545
       "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
3901
545
       function,
3902
545
       byte_value1 );
3903
3904
545
      return( -1 );
3905
545
    }
3906
5.29M
  }
3907
5.32M
  if( utf8_character_additional_bytes >= 1 )
3908
33.5k
  {
3909
33.5k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
3910
3911
33.5k
    if( ( byte_value2 < 0x80 )
3912
33.0k
     || ( byte_value2 > 0xbf ) )
3913
728
    {
3914
728
      libcerror_error_set(
3915
728
       error,
3916
728
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3917
728
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3918
728
       "%s: invalid 2nd UTF-8 character byte: 0x%02" PRIx8 ".",
3919
728
       function,
3920
728
       byte_value2 );
3921
3922
728
      return( -1 );
3923
728
    }
3924
32.8k
    result = 1;
3925
3926
32.8k
    switch( byte_value1 )
3927
32.8k
    {
3928
6.53k
      case 0xe0:
3929
6.53k
        if( ( byte_value2 < 0xa0 )
3930
6.40k
         || ( byte_value2 > 0xbf ) )
3931
129
        {
3932
129
          result = 0;
3933
129
        }
3934
6.53k
        break;
3935
3936
3.57k
      case 0xed:
3937
3.57k
        if( ( byte_value2 < 0x80 )
3938
3.57k
         || ( byte_value2 > 0x9f ) )
3939
81
        {
3940
81
          result = 0;
3941
81
        }
3942
3.57k
        break;
3943
3944
4.98k
      case 0xf0:
3945
4.98k
        if( ( byte_value2 < 0x90 )
3946
4.87k
         || ( byte_value2 > 0xbf ) )
3947
106
        {
3948
106
          result = 0;
3949
106
        }
3950
4.98k
        break;
3951
3952
1.24k
      case 0xf4:
3953
1.24k
        if( ( byte_value2 < 0x80 )
3954
1.24k
         || ( byte_value2 > 0xbf ) )
3955
0
        {
3956
0
          result = 0;
3957
0
        }
3958
1.24k
        break;
3959
3960
16.4k
      default:
3961
16.4k
        break;
3962
32.8k
    }
3963
32.8k
    if( result == 0 )
3964
316
    {
3965
316
      libcerror_error_set(
3966
316
       error,
3967
316
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3968
316
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3969
316
       "%s: invalid 1st and 2nd UTF-8 character byte pair: 0x%02" PRIx8 " 0x%02" PRIx8 ".",
3970
316
       function,
3971
316
       byte_value1,
3972
316
       byte_value2 );
3973
3974
316
      return( -1 );
3975
316
    }
3976
32.4k
    safe_unicode_character <<= 6;
3977
32.4k
    safe_unicode_character += byte_value2;
3978
3979
32.4k
    if( utf8_character_additional_bytes == 1 )
3980
6.34k
    {
3981
6.34k
      safe_unicode_character -= 0x03080;
3982
6.34k
    }
3983
32.4k
  }
3984
5.32M
  if( utf8_character_additional_bytes >= 2 )
3985
26.1k
  {
3986
26.1k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
3987
3988
26.1k
    if( ( byte_value3 < 0x80 )
3989
25.9k
     || ( byte_value3 > 0xbf ) )
3990
363
    {
3991
363
      libcerror_error_set(
3992
363
       error,
3993
363
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3994
363
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
3995
363
       "%s: invalid 3rd UTF-8 character byte: 0x%02" PRIx8 ".",
3996
363
       function,
3997
363
       byte_value3 );
3998
3999
363
      return( -1 );
4000
363
    }
4001
25.7k
    result = 1;
4002
4003
25.7k
    switch( byte_value2 )
4004
25.7k
    {
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
25.7k
      default:
4022
25.7k
        break;
4023
25.7k
    }
4024
25.7k
    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
25.7k
    safe_unicode_character <<= 6;
4038
25.7k
    safe_unicode_character += byte_value3;
4039
4040
25.7k
    if( utf8_character_additional_bytes == 2 )
4041
16.6k
    {
4042
16.6k
      safe_unicode_character -= 0x0e2080;
4043
16.6k
    }
4044
25.7k
  }
4045
5.32M
  if( utf8_character_additional_bytes >= 3 )
4046
9.11k
  {
4047
9.11k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4048
4049
9.11k
    if( ( byte_value4 < 0x80 )
4050
9.03k
     || ( byte_value4 > 0xbf ) )
4051
225
    {
4052
225
      libcerror_error_set(
4053
225
       error,
4054
225
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4055
225
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4056
225
       "%s: invalid 4th UTF-8 character byte: 0x%02" PRIx8 ".",
4057
225
       function,
4058
225
       byte_value4 );
4059
4060
225
      return( -1 );
4061
225
    }
4062
8.89k
    safe_unicode_character <<= 6;
4063
8.89k
    safe_unicode_character += byte_value4;
4064
4065
8.89k
    if( utf8_character_additional_bytes == 3 )
4066
8.89k
    {
4067
8.89k
      safe_unicode_character -= 0x03c82080;
4068
8.89k
    }
4069
8.89k
  }
4070
  /* Determine if the Unicode character is valid
4071
   */
4072
5.32M
  if( ( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4073
13.8k
    &&  ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4074
5.32M
   || ( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4075
59
  {
4076
59
    libcerror_error_set(
4077
59
     error,
4078
59
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4079
59
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4080
59
     "%s: unsupported Unicode character.",
4081
59
     function );
4082
4083
59
    return( -1 );
4084
59
  }
4085
5.32M
  *unicode_character = safe_unicode_character;
4086
5.32M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4087
4088
5.32M
  return( 1 );
4089
5.32M
}
4090
4091
/* Copies an Unicode character into a UTF-8 string
4092
 * This function supports upto U+10FFFF (4 byte UTF-8 characters)
4093
 * Returns 1 if successful or -1 on error
4094
 */
4095
int libuna_unicode_character_copy_to_utf8(
4096
     libuna_unicode_character_t unicode_character,
4097
     libuna_utf8_character_t *utf8_string,
4098
     size_t utf8_string_size,
4099
     size_t *utf8_string_index,
4100
     libcerror_error_t **error )
4101
3.76M
{
4102
3.76M
  static char *function                   = "libuna_unicode_character_copy_to_utf8";
4103
3.76M
  size_t safe_utf8_string_index           = 0;
4104
3.76M
  size_t utf8_character_iterator          = 0;
4105
3.76M
  uint8_t utf8_character_additional_bytes = 0;
4106
3.76M
  uint8_t utf8_first_character_mark       = 0;
4107
4108
3.76M
  if( utf8_string == NULL )
4109
0
  {
4110
0
    libcerror_error_set(
4111
0
     error,
4112
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4113
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4114
0
     "%s: invalid UTF-8 string.",
4115
0
     function );
4116
4117
0
    return( -1 );
4118
0
  }
4119
3.76M
  if( utf8_string_size > (size_t) SSIZE_MAX )
4120
0
  {
4121
0
    libcerror_error_set(
4122
0
     error,
4123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4124
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4125
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
4126
0
     function );
4127
4128
0
    return( -1 );
4129
0
  }
4130
3.76M
  if( utf8_string_index == NULL )
4131
0
  {
4132
0
    libcerror_error_set(
4133
0
     error,
4134
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4135
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4136
0
     "%s: invalid UTF-8 string index.",
4137
0
     function );
4138
4139
0
    return( -1 );
4140
0
  }
4141
3.76M
  safe_utf8_string_index = *utf8_string_index;
4142
4143
3.76M
  if( safe_utf8_string_index >= utf8_string_size )
4144
587
  {
4145
587
    libcerror_error_set(
4146
587
     error,
4147
587
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4148
587
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4149
587
     "%s: UTF-8 string too small.",
4150
587
     function );
4151
4152
587
    return( -1 );
4153
587
  }
4154
  /* Determine if the Unicode character is valid
4155
   */
4156
3.76M
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4157
121k
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4158
3.76M
   || ( unicode_character > LIBUNA_UNICODE_CHARACTER_MAX ) )
4159
0
  {
4160
0
    libcerror_error_set(
4161
0
     error,
4162
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4163
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4164
0
     "%s: unsupported Unicode character.",
4165
0
     function );
4166
4167
0
    return( -1 );
4168
0
  }
4169
  /* Determine how many UTF-8 character bytes are required
4170
   */
4171
3.76M
  if( unicode_character < 0x080 )
4172
829k
  {
4173
829k
    utf8_character_additional_bytes = 0;
4174
829k
    utf8_first_character_mark       = 0;
4175
829k
  }
4176
2.93M
  else if( unicode_character < 0x0800 )
4177
105k
  {
4178
105k
    utf8_character_additional_bytes = 1;
4179
105k
    utf8_first_character_mark       = 0x0c0;
4180
105k
  }
4181
2.83M
  else if( unicode_character < 0x010000 )
4182
2.82M
  {
4183
2.82M
    utf8_character_additional_bytes = 2;
4184
2.82M
    utf8_first_character_mark       = 0x0e0;
4185
2.82M
  }
4186
4.98k
  else
4187
4.98k
  {
4188
4.98k
    utf8_character_additional_bytes = 3;
4189
4.98k
    utf8_first_character_mark       = 0x0f0;
4190
4.98k
  }
4191
  /* Convert Unicode character into UTF-8 character bytes
4192
   */
4193
3.76M
  if( ( utf8_character_additional_bytes > utf8_string_size )
4194
3.76M
   || ( safe_utf8_string_index >= ( utf8_string_size - utf8_character_additional_bytes ) ) )
4195
626
  {
4196
626
    libcerror_error_set(
4197
626
     error,
4198
626
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4199
626
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
4200
626
     "%s: UTF-8 string too small.",
4201
626
     function );
4202
4203
626
    return( -1 );
4204
626
  }
4205
3.76M
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4206
9.54M
       utf8_character_iterator > safe_utf8_string_index;
4207
5.77M
       utf8_character_iterator-- )
4208
5.77M
  {
4209
5.77M
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4210
4211
5.77M
    unicode_character >>= 6;
4212
5.77M
  }
4213
3.76M
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4214
4215
3.76M
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4216
4217
3.76M
  return( 1 );
4218
3.76M
}
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
11.0k
{
4230
11.0k
  static char *function           = "libuna_unicode_character_size_to_utf8_rfc2279";
4231
11.0k
  size_t safe_utf8_character_size = 0;
4232
4233
11.0k
  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
11.0k
  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
11.0k
  if( unicode_character < 0x00000080UL )
4259
1.91k
  {
4260
1.91k
    safe_utf8_character_size += 1;
4261
1.91k
  }
4262
9.16k
  else if( unicode_character < 0x00000800UL )
4263
756
  {
4264
756
    safe_utf8_character_size += 2;
4265
756
  }
4266
8.41k
  else if( unicode_character < 0x00010000UL )
4267
8.29k
  {
4268
8.29k
    safe_utf8_character_size += 3;
4269
8.29k
  }
4270
113
  else if( unicode_character < 0x00200000UL )
4271
113
  {
4272
113
    safe_utf8_character_size += 4;
4273
113
  }
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
11.0k
  *utf8_character_size += safe_utf8_character_size;
4283
4284
11.0k
  return( 1 );
4285
11.0k
}
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
109k
{
4298
109k
  static char *function                             = "libuna_unicode_character_copy_from_utf8_rfc2279";
4299
109k
  libuna_unicode_character_t safe_unicode_character = 0;
4300
109k
  size_t safe_utf8_string_index                     = 0;
4301
109k
  uint8_t byte_value1                               = 0;
4302
109k
  uint8_t byte_value2                               = 0;
4303
109k
  uint8_t byte_value3                               = 0;
4304
109k
  uint8_t byte_value4                               = 0;
4305
109k
  uint8_t byte_value5                               = 0;
4306
109k
  uint8_t byte_value6                               = 0;
4307
109k
  uint8_t utf8_character_additional_bytes           = 0;
4308
4309
109k
  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
109k
  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
109k
  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
109k
  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
109k
  safe_utf8_string_index = *utf8_string_index;
4354
4355
109k
  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
109k
  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
109k
  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
109k
  if( byte_value1 < 0xc0 )
4387
57.2k
  {
4388
57.2k
    utf8_character_additional_bytes = 0;
4389
57.2k
  }
4390
52.0k
  else if( byte_value1 < 0xe0 )
4391
14.0k
  {
4392
14.0k
    utf8_character_additional_bytes = 1;
4393
14.0k
  }
4394
37.9k
  else if( byte_value1 < 0xf0 )
4395
32.1k
  {
4396
32.1k
    utf8_character_additional_bytes = 2;
4397
32.1k
  }
4398
5.81k
  else if( byte_value1 < 0xf8 )
4399
5.81k
  {
4400
5.81k
    utf8_character_additional_bytes = 3;
4401
5.81k
  }
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
109k
  if( ( ( (size_t) utf8_character_additional_bytes + 1 ) > utf8_string_size )
4411
109k
   || ( 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
109k
  safe_unicode_character = byte_value1;
4427
4428
109k
  if( utf8_character_additional_bytes == 0 )
4429
57.2k
  {
4430
57.2k
    if( byte_value1 >= 0x80 )
4431
0
    {
4432
0
      libcerror_error_set(
4433
0
       error,
4434
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4435
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4436
0
       "%s: invalid 1st UTF-8 character byte: 0x%02" PRIx8 ".",
4437
0
       function,
4438
0
       byte_value1 );
4439
4440
0
      return( -1 );
4441
0
    }
4442
57.2k
  }
4443
109k
  if( utf8_character_additional_bytes >= 1 )
4444
52.0k
  {
4445
52.0k
    byte_value2 = utf8_string[ safe_utf8_string_index + 1 ];
4446
4447
52.0k
    if( ( byte_value2 < 0x80 )
4448
52.0k
     || ( 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
52.0k
    safe_unicode_character <<= 6;
4461
52.0k
    safe_unicode_character += byte_value2;
4462
4463
52.0k
    if( utf8_character_additional_bytes == 1 )
4464
14.0k
    {
4465
14.0k
      safe_unicode_character -= 0x03080;
4466
14.0k
    }
4467
52.0k
  }
4468
109k
  if( utf8_character_additional_bytes >= 2 )
4469
37.9k
  {
4470
37.9k
    byte_value3 = utf8_string[ safe_utf8_string_index + 2 ];
4471
4472
37.9k
    if( ( byte_value3 < 0x80 )
4473
37.9k
     || ( 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
37.9k
    safe_unicode_character <<= 6;
4486
37.9k
    safe_unicode_character += byte_value3;
4487
4488
37.9k
    if( utf8_character_additional_bytes == 2 )
4489
32.1k
    {
4490
32.1k
      safe_unicode_character -= 0x0e2080;
4491
32.1k
    }
4492
37.9k
  }
4493
109k
  if( utf8_character_additional_bytes >= 3 )
4494
5.81k
  {
4495
5.81k
    byte_value4 = utf8_string[ safe_utf8_string_index + 3 ];
4496
4497
5.81k
    if( ( byte_value4 < 0x80 )
4498
5.81k
     || ( byte_value4 > 0xbf ) )
4499
0
    {
4500
0
      libcerror_error_set(
4501
0
       error,
4502
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4503
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4504
0
       "%s: invalid 4th UTF-8 character byte: 0x%02" PRIx8 ".",
4505
0
       function,
4506
0
       byte_value4 );
4507
4508
0
      return( -1 );
4509
0
    }
4510
5.81k
    safe_unicode_character <<= 6;
4511
5.81k
    safe_unicode_character += byte_value4;
4512
4513
5.81k
    if( utf8_character_additional_bytes == 3 )
4514
5.81k
    {
4515
5.81k
      safe_unicode_character -= 0x03c82080;
4516
5.81k
    }
4517
5.81k
  }
4518
109k
  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
109k
  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
109k
  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
109k
  *unicode_character = safe_unicode_character;
4578
109k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4579
4580
109k
  return( 1 );
4581
109k
}
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
11.0k
{
4594
11.0k
  static char *function                   = "libuna_unicode_character_copy_to_utf8_rfc2279";
4595
11.0k
  size_t safe_utf8_string_index           = 0;
4596
11.0k
  size_t utf8_character_iterator          = 0;
4597
11.0k
  uint8_t utf8_character_additional_bytes = 0;
4598
11.0k
  uint8_t utf8_first_character_mark       = 0;
4599
4600
11.0k
  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
11.0k
  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
11.0k
  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
11.0k
  safe_utf8_string_index = *utf8_string_index;
4634
4635
11.0k
  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
11.0k
  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
11.0k
  if( unicode_character < 0x080 )
4662
1.91k
  {
4663
1.91k
    utf8_character_additional_bytes = 0;
4664
1.91k
    utf8_first_character_mark       = 0;
4665
1.91k
  }
4666
9.16k
  else if( unicode_character < 0x0800 )
4667
756
  {
4668
756
    utf8_character_additional_bytes = 1;
4669
756
    utf8_first_character_mark       = 0x0c0;
4670
756
  }
4671
8.41k
  else if( unicode_character < 0x010000 )
4672
8.29k
  {
4673
8.29k
    utf8_character_additional_bytes = 2;
4674
8.29k
    utf8_first_character_mark       = 0x0e0;
4675
8.29k
  }
4676
113
  else if( unicode_character < 0x0200000 )
4677
113
  {
4678
113
    utf8_character_additional_bytes = 3;
4679
113
    utf8_first_character_mark       = 0x0f0;
4680
113
  }
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
11.0k
  if( ( utf8_character_additional_bytes > utf8_string_size )
4694
11.0k
   || ( 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
11.0k
  for( utf8_character_iterator = safe_utf8_string_index + utf8_character_additional_bytes;
4706
28.7k
       utf8_character_iterator > safe_utf8_string_index;
4707
17.6k
       utf8_character_iterator-- )
4708
17.6k
  {
4709
17.6k
    utf8_string[ utf8_character_iterator ] = (libuna_utf8_character_t) ( ( unicode_character & 0x0bf ) | 0x080 );
4710
4711
17.6k
    unicode_character >>= 6;
4712
17.6k
  }
4713
11.0k
  utf8_string[ safe_utf8_string_index ] = (libuna_utf8_character_t) ( unicode_character | utf8_first_character_mark );
4714
4715
11.0k
  *utf8_string_index = safe_utf8_string_index + 1 + utf8_character_additional_bytes;
4716
4717
11.0k
  return( 1 );
4718
11.0k
}
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
25.8k
{
4729
25.8k
  static char *function = "libuna_unicode_character_size_to_utf16";
4730
4731
25.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
25.8k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4743
296
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4744
25.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
25.8k
  if( unicode_character > LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4756
168
  {
4757
168
    *utf16_character_size += 2;
4758
168
  }
4759
25.6k
  else
4760
25.6k
  {
4761
25.6k
    *utf16_character_size += 1;
4762
25.6k
  }
4763
25.8k
  return( 1 );
4764
25.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
5.82k
{
4913
5.82k
  static char *function          = "libuna_unicode_character_copy_to_utf16";
4914
5.82k
  size_t safe_utf16_string_index = 0;
4915
4916
5.82k
  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
5.82k
  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
5.82k
  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
5.82k
  safe_utf16_string_index = *utf16_string_index;
4950
4951
5.82k
  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
5.82k
  if( ( ( unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
4965
913
    &&  ( unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
4966
5.82k
   || ( 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
5.82k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
4978
5.59k
  {
4979
5.59k
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) unicode_character;
4980
5.59k
  }
4981
225
  else
4982
225
  {
4983
225
    if( ( utf16_string_size < 2 )
4984
225
     || ( 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
225
    unicode_character                        -= 0x010000;
4996
225
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character >> 10 ) + LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START );
4997
225
    utf16_string[ safe_utf16_string_index++ ] = (libuna_utf16_character_t) ( ( unicode_character & 0x03ff ) + LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START );
4998
225
  }
4999
5.82k
  *utf16_string_index = safe_utf16_string_index;
5000
5001
5.82k
  return( 1 );
5002
5.82k
}
5003
5004
/* Copies an Unicode character from an UTF-16 stream
5005
 * Returns 1 if successful or -1 on error
5006
 */
5007
int libuna_unicode_character_copy_from_utf16_stream(
5008
     libuna_unicode_character_t *unicode_character,
5009
     const uint8_t *utf16_stream,
5010
     size_t utf16_stream_size,
5011
     size_t *utf16_stream_index,
5012
     int byte_order,
5013
     libcerror_error_t **error )
5014
11.9M
{
5015
11.9M
  static char *function                             = "libuna_unicode_character_copy_from_utf16_stream";
5016
11.9M
  libuna_unicode_character_t safe_unicode_character = 0;
5017
11.9M
  libuna_utf16_character_t utf16_surrogate          = 0;
5018
11.9M
  size_t safe_utf16_stream_index                    = 0;
5019
11.9M
  int byte_order_without_flags                      = 0;
5020
5021
11.9M
  if( unicode_character == NULL )
5022
0
  {
5023
0
    libcerror_error_set(
5024
0
     error,
5025
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5026
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5027
0
     "%s: invalid Unicode character.",
5028
0
     function );
5029
5030
0
    return( -1 );
5031
0
  }
5032
11.9M
  if( utf16_stream == NULL )
5033
0
  {
5034
0
    libcerror_error_set(
5035
0
     error,
5036
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5037
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5038
0
     "%s: invalid UTF-16 stream.",
5039
0
     function );
5040
5041
0
    return( -1 );
5042
0
  }
5043
11.9M
  if( utf16_stream_size > (size_t) SSIZE_MAX )
5044
0
  {
5045
0
    libcerror_error_set(
5046
0
     error,
5047
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5048
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
5049
0
     "%s: invalid UTF-16 stream size value exceeds maximum.",
5050
0
     function );
5051
5052
0
    return( -1 );
5053
0
  }
5054
11.9M
  if( utf16_stream_index == NULL )
5055
0
  {
5056
0
    libcerror_error_set(
5057
0
     error,
5058
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5059
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
5060
0
     "%s: invalid UTF-16 stream index.",
5061
0
     function );
5062
5063
0
    return( -1 );
5064
0
  }
5065
11.9M
  byte_order_without_flags = byte_order & 0xff;
5066
5067
11.9M
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5068
7.62M
   && ( byte_order_without_flags != LIBUNA_ENDIAN_LITTLE ) )
5069
0
  {
5070
0
    libcerror_error_set(
5071
0
     error,
5072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5073
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
5074
0
     "%s: unsupported byte order.",
5075
0
     function );
5076
5077
0
    return( -1 );
5078
0
  }
5079
11.9M
  safe_utf16_stream_index = *utf16_stream_index;
5080
5081
11.9M
  if( ( utf16_stream_size < 2 )
5082
11.9M
   || ( safe_utf16_stream_index > ( utf16_stream_size - 2 ) ) )
5083
73
  {
5084
73
    libcerror_error_set(
5085
73
     error,
5086
73
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
5087
73
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
5088
73
     "%s: UTF-16 stream too small.",
5089
73
     function );
5090
5091
73
    return( -1 );
5092
73
  }
5093
11.9M
  if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5094
4.37M
  {
5095
4.37M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index ];
5096
4.37M
    safe_unicode_character <<= 8;
5097
4.37M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index + 1 ];
5098
4.37M
  }
5099
7.62M
  else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5100
7.62M
  {
5101
7.62M
    safe_unicode_character   = utf16_stream[ safe_utf16_stream_index + 1 ];
5102
7.62M
    safe_unicode_character <<= 8;
5103
7.62M
    safe_unicode_character  += utf16_stream[ safe_utf16_stream_index ];
5104
7.62M
  }
5105
11.9M
  safe_utf16_stream_index += 2;
5106
5107
  /* Determine if the Unicode character is valid
5108
   */
5109
11.9M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5110
967k
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5111
1.88k
  {
5112
1.88k
    if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5113
817
    {
5114
817
      libcerror_error_set(
5115
817
       error,
5116
817
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
5117
817
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5118
817
       "%s: unsupported UTF-16 character.",
5119
817
       function );
5120
5121
817
      return( -1 );
5122
817
    }
5123
1.88k
  }
5124
  /* Determine if the UTF-16 character is within the high surrogate range
5125
   */
5126
11.9M
  if( ( safe_unicode_character >= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START )
5127
1.08M
   && ( safe_unicode_character <= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_END ) )
5128
120k
  {
5129
120k
    if( safe_utf16_stream_index > ( utf16_stream_size - 2 ) )
5130
113
    {
5131
113
      if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5132
67
      {
5133
67
        libcerror_error_set(
5134
67
         error,
5135
67
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5136
67
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5137
67
         "%s: missing surrogate UTF-16 character bytes.",
5138
67
         function );
5139
5140
67
        return( -1 );
5141
67
      }
5142
113
    }
5143
120k
    else
5144
120k
    {
5145
120k
      if( byte_order_without_flags == LIBUNA_ENDIAN_BIG )
5146
101k
      {
5147
101k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index ];
5148
101k
        utf16_surrogate <<= 8;
5149
101k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index + 1 ];
5150
101k
      }
5151
19.0k
      else if( byte_order_without_flags == LIBUNA_ENDIAN_LITTLE )
5152
19.0k
      {
5153
19.0k
        utf16_surrogate   = utf16_stream[ safe_utf16_stream_index + 1 ];
5154
19.0k
        utf16_surrogate <<= 8;
5155
19.0k
        utf16_surrogate  += utf16_stream[ safe_utf16_stream_index ];
5156
19.0k
      }
5157
      /* Determine if the UTF-16 character is within the low surrogate range
5158
       */
5159
120k
      if( ( utf16_surrogate >= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START )
5160
117k
       && ( utf16_surrogate <= LIBUNA_UNICODE_SURROGATE_LOW_RANGE_END ) )
5161
116k
      {
5162
116k
        safe_unicode_character  -= LIBUNA_UNICODE_SURROGATE_HIGH_RANGE_START;
5163
116k
        safe_unicode_character <<= 10;
5164
116k
        safe_unicode_character  += utf16_surrogate - LIBUNA_UNICODE_SURROGATE_LOW_RANGE_START;
5165
116k
        safe_unicode_character  += 0x010000;
5166
5167
116k
        safe_utf16_stream_index += 2;
5168
116k
      }
5169
3.64k
      else if( ( byte_order & LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE ) == 0 )
5170
933
      {
5171
933
        libcerror_error_set(
5172
933
         error,
5173
933
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
5174
933
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5175
933
         "%s: unsupported low surrogate UTF-16 character.",
5176
933
         function );
5177
5178
933
        return( -1 );
5179
933
      }
5180
120k
    }
5181
120k
  }
5182
11.9M
  if( safe_unicode_character > LIBUNA_UNICODE_CHARACTER_MAX )
5183
0
  {
5184
0
    libcerror_error_set(
5185
0
     error,
5186
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
5187
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
5188
0
     "%s: unsupported Unicode character.",
5189
0
     function );
5190
5191
0
    return( -1 );
5192
0
  }
5193
11.9M
  *unicode_character  = safe_unicode_character;
5194
11.9M
  *utf16_stream_index = safe_utf16_stream_index;
5195
5196
11.9M
  return( 1 );
5197
11.9M
}
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
22.2k
{
5210
22.2k
  static char *function                    = "libuna_unicode_character_copy_to_utf16_stream";
5211
22.2k
  libuna_utf16_character_t utf16_surrogate = 0;
5212
22.2k
  size_t safe_utf16_stream_index           = 0;
5213
22.2k
  int byte_order_without_flags             = 0;
5214
5215
22.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
22.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
22.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
22.2k
  byte_order_without_flags = byte_order & 0xff;
5249
5250
22.2k
  if( ( byte_order_without_flags != LIBUNA_ENDIAN_BIG )
5251
22.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
22.2k
  safe_utf16_stream_index = *utf16_stream_index;
5263
5264
  /* Determine if the Unicode character is valid
5265
   */
5266
22.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
22.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
22.2k
  if( unicode_character <= LIBUNA_UNICODE_BASIC_MULTILINGUAL_PLANE_MAX )
5293
22.2k
  {
5294
22.2k
    if( ( utf16_stream_size < 2 )
5295
22.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
22.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
22.2k
    else if( byte_order == LIBUNA_ENDIAN_LITTLE )
5313
22.2k
    {
5314
22.2k
      utf16_stream[ safe_utf16_stream_index     ] = (uint8_t) ( unicode_character & 0xff );
5315
22.2k
      unicode_character                         >>= 8;
5316
22.2k
      utf16_stream[ safe_utf16_stream_index + 1 ] = (uint8_t) ( unicode_character & 0xff );
5317
22.2k
    }
5318
22.2k
    safe_utf16_stream_index += 2;
5319
22.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
22.2k
  *utf16_stream_index = safe_utf16_stream_index;
5369
5370
22.2k
  return( 1 );
5371
22.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