Coverage Report

Created: 2025-06-13 07:22

/src/libevtx/libfwevt/libfwevt_floating_point.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Floating point (IEEE 754) functions
3
 *
4
 * Copyright (C) 2011-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <types.h>
25
26
#include "libfwevt_floating_point.h"
27
#include "libfwevt_libcerror.h"
28
29
/* Deterimes the size of the string of a 32-bit floating point
30
 * The string size includes the end of string character
31
 * Returns 1 if successful or -1 on error
32
 */
33
int libfwevt_float32_get_string_size(
34
     uint32_t value_32bit,
35
     size_t *string_size,
36
     libcerror_error_t **error )
37
0
{
38
0
  static char *function        = "libfwevt_float32_get_string_size";
39
0
  uint8_t is_indeterminate     = 0;
40
0
  uint8_t is_infinite          = 0;
41
0
  uint8_t is_not_a_number      = 0;
42
0
  uint8_t is_negative          = 0;
43
0
  uint8_t number_of_characters = 0;
44
45
0
  if( string_size == NULL )
46
0
  {
47
0
    libcerror_error_set(
48
0
     error,
49
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51
0
     "%s: invalid string size.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
0
  is_negative = (uint8_t) ( value_32bit >> 31 );
57
58
0
  if( is_negative != 0 )
59
0
  {
60
0
    value_32bit &= ~( (uint32_t) 1 << 31 );
61
0
  }
62
0
  if( value_32bit == 0x7f800000UL )
63
0
  {
64
0
    is_infinite = 1;
65
0
  }
66
0
  else if( ( is_negative != 0 )
67
0
        && ( value_32bit == 0x7fc00000UL ) )
68
0
  {
69
0
    is_indeterminate = 1;
70
0
  }
71
0
  else if( ( value_32bit >= 0x7f800001UL )
72
0
        && ( value_32bit <= 0x7fffffffUL ) )
73
0
  {
74
0
    is_not_a_number = 1;
75
0
  }
76
0
  if( is_indeterminate != 0 )
77
0
  {
78
    /* "Ind" + end-of-string character */
79
0
    number_of_characters = 4;
80
0
  }
81
0
  else if( is_infinite != 0 )
82
0
  {
83
    /* "Inf" + end-of-string character */
84
0
    number_of_characters = 4;
85
0
  }
86
0
  else if( is_not_a_number != 0 )
87
0
  {
88
    /* "Nan" + end-of-string character */
89
0
    number_of_characters = 4;
90
0
  }
91
0
  else
92
0
  {
93
    /* "[-]0.000000e[+-]000" + end-of-string character */
94
0
    if( is_negative != 0 )
95
0
    {
96
0
      number_of_characters = 15;
97
0
    }
98
0
    else
99
0
    {
100
0
      number_of_characters = 14;
101
0
    }
102
0
  }
103
0
  *string_size = number_of_characters;
104
105
0
  return( 1 );
106
0
}
107
108
/* Copies a 32-bit floating point to an UTF-8 string
109
 * The string size should include the end of string character
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfwevt_float32_copy_to_utf8_string_with_index(
113
     uint32_t value_32bit,
114
     uint8_t *utf8_string,
115
     size_t utf8_string_size,
116
     size_t *utf8_string_index,
117
     libcerror_error_t **error )
118
0
{
119
0
  byte_stream_float32_t value_float32;
120
121
0
  static char *function         = "libfwevt_float32_copy_to_utf8_string_with_index";
122
0
  size_t safe_utf8_string_index = 0;
123
0
  uint32_t divider              = 0;
124
0
  uint32_t value_fraction       = 0;
125
0
  int16_t exponent10            = 0;
126
0
  int16_t exponent2             = 0;
127
0
  uint8_t digit_index           = 0;
128
0
  uint8_t exponent_sign         = 0;
129
0
  uint8_t is_indeterminate      = 0;
130
0
  uint8_t is_infinite           = 0;
131
0
  uint8_t is_not_a_number       = 0;
132
0
  uint8_t is_negative           = 0;
133
0
  uint8_t number_of_characters  = 0;
134
0
  double exponent_value         = 0.0;
135
0
  double value_float            = 0.0;
136
137
0
  if( utf8_string == NULL )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
142
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
143
0
     "%s: invalid UTF-8 string.",
144
0
     function );
145
146
0
    return( -1 );
147
0
  }
148
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
149
0
  {
150
0
    libcerror_error_set(
151
0
     error,
152
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
153
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
154
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
155
0
     function );
156
157
0
    return( -1 );
158
0
  }
159
0
  if( utf8_string_index == NULL )
160
0
  {
161
0
    libcerror_error_set(
162
0
     error,
163
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
164
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
165
0
     "%s: invalid UTF-8 string index.",
166
0
     function );
167
168
0
    return( -1 );
169
0
  }
170
0
  safe_utf8_string_index = *utf8_string_index;
171
172
0
  is_negative = (uint8_t) ( value_32bit >> 31 );
173
174
0
  if( is_negative != 0 )
175
0
  {
176
0
    value_32bit &= ~( (uint32_t) 1 << 31 );
177
0
  }
178
0
  if( value_32bit == 0x7f800000UL )
179
0
  {
180
0
    is_infinite = 1;
181
0
  }
182
0
  else if( ( is_negative != 0 )
183
0
        && ( value_32bit == 0x7fc00000UL ) )
184
0
  {
185
0
    is_indeterminate = 1;
186
0
  }
187
0
  else if( ( value_32bit >= 0x7f800001UL )
188
0
        && ( value_32bit <= 0x7fffffffUL ) )
189
0
  {
190
0
    is_not_a_number = 1;
191
0
  }
192
0
  else if( value_32bit != 0 )
193
0
  {
194
0
    value_float32.integer = value_32bit;
195
0
    value_float           = (double) value_float32.floating_point;
196
197
0
    exponent2 = (int16_t) ( value_32bit >> 23 );
198
199
0
    if( exponent2 == 0 )
200
0
    {
201
0
      exponent2 = -126;
202
0
    }
203
0
    else
204
0
    {
205
0
      exponent2 -= 127;
206
0
    }
207
0
  }
208
0
  if( is_indeterminate != 0 )
209
0
  {
210
    /* "Ind" + end-of-string character */
211
0
    number_of_characters = 4;
212
0
  }
213
0
  else if( is_infinite != 0 )
214
0
  {
215
    /* "Inf" + end-of-string character */
216
0
    number_of_characters = 4;
217
0
  }
218
0
  else if( is_not_a_number != 0 )
219
0
  {
220
    /* "Nan" + end-of-string character */
221
0
    number_of_characters = 4;
222
0
  }
223
0
  else
224
0
  {
225
    /* "[-]0.000000e[+-]000" + end-of-string character */
226
0
    if( is_negative != 0 )
227
0
    {
228
0
      number_of_characters = 15;
229
0
    }
230
0
    else
231
0
    {
232
0
      number_of_characters = 14;
233
0
    }
234
0
  }
235
0
  if( ( number_of_characters > utf8_string_size )
236
0
   || ( safe_utf8_string_index > ( utf8_string_size - number_of_characters ) ) )
237
0
  {
238
0
    libcerror_error_set(
239
0
     error,
240
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
241
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
242
0
     "%s: invalid UTF-8 string size value too small.",
243
0
     function );
244
245
0
    return( -1 );
246
0
  }
247
0
  if( is_indeterminate != 0 )
248
0
  {
249
    /* "Ind" + end-of-string character */
250
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'I';
251
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'n';
252
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'd';
253
0
  }
254
0
  else if( is_infinite != 0 )
255
0
  {
256
    /* "Inf" + end-of-string character */
257
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'I';
258
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'n';
259
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'f';
260
0
  }
261
0
  else if( is_not_a_number != 0 )
262
0
  {
263
    /* "Nan" + end-of-string character */
264
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'N';
265
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'a';
266
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'N';
267
0
  }
268
0
  else
269
0
  {
270
    /* "[-]0.000000e[+-]000" + end-of-string character */
271
0
    if( is_negative != 0 )
272
0
    {
273
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '-';
274
0
    }
275
0
    if( exponent2 < 0 )
276
0
    {
277
0
      exponent_sign = (uint8_t) '-';
278
0
      exponent2    *= -1;
279
0
    }
280
0
    else
281
0
    {
282
0
      exponent_sign = (uint8_t) '+';
283
0
    }
284
0
    exponent_value = 1.0;
285
0
    exponent10     = 0;
286
287
0
    while( exponent2 > 0 )
288
0
    {
289
0
      exponent_value *= 2;
290
0
      exponent2--;
291
292
0
      if( exponent_value >= 10.0 )
293
0
      {
294
0
        exponent_value /= 10.0;
295
0
        exponent10++;
296
297
0
        if( exponent_sign == (uint8_t) '-' )
298
0
        {
299
0
          value_float *= 10.0;
300
0
        }
301
0
        else
302
0
        {
303
0
          value_float /= 10.0;
304
0
        }
305
0
      }
306
0
    }
307
0
    if( value_float != 0.0 )
308
0
    {
309
0
      while( ( value_float < 1.0 )
310
0
          || ( value_float >= 10.0 ) )
311
0
      {
312
0
        exponent10++;
313
314
0
        if( exponent_sign == (uint8_t) '-' )
315
0
        {
316
0
          value_float *= 10;
317
0
        }
318
0
        else
319
0
        {
320
0
          value_float /= 10;
321
0
        }
322
0
      }
323
0
    }
324
0
    for( digit_index = 0;
325
0
         digit_index < 7;
326
0
         digit_index++ )
327
0
    {
328
0
      value_fraction *= 10;
329
0
      value_fraction += (uint8_t) value_float;
330
331
0
      value_float -= (uint8_t) value_float;
332
0
      value_float *= 10.0;
333
0
    }
334
0
    if( value_float >= 5.0 )
335
0
    {
336
0
      value_fraction += 1;
337
0
    }
338
0
    divider = 1000000;
339
340
0
    for( digit_index = 0;
341
0
         digit_index < 7;
342
0
         digit_index++ )
343
0
    {
344
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '0' + (uint8_t) ( value_fraction / divider );
345
346
0
      if( digit_index == 0 )
347
0
      {
348
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '.';
349
0
      }
350
0
      value_fraction %= divider;
351
0
      divider        /= 10;
352
0
    }
353
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'e';
354
0
    utf8_string[ safe_utf8_string_index++ ] = exponent_sign;
355
356
0
    divider = 100;
357
358
0
    for( digit_index = 0;
359
0
         digit_index < 3;
360
0
         digit_index++ )
361
0
    {
362
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '0' + (uint8_t) ( exponent10 / divider );
363
364
0
      exponent10 %= divider;
365
0
      divider    /= 10;
366
0
    }
367
0
  }
368
0
  utf8_string[ safe_utf8_string_index++ ] = 0;
369
370
0
  *utf8_string_index = safe_utf8_string_index;
371
372
0
  return( 1 );
373
0
}
374
375
/* Copies a 32-bit floating point to an UTF-16 string
376
 * The string size should include the end of string character
377
 * Returns 1 if successful or -1 on error
378
 */
379
int libfwevt_float32_copy_to_utf16_string_with_index(
380
     uint32_t value_32bit,
381
     uint16_t *utf16_string,
382
     size_t utf16_string_size,
383
     size_t *utf16_string_index,
384
     libcerror_error_t **error )
385
0
{
386
0
  byte_stream_float32_t value_float32;
387
388
0
  static char *function          = "libfwevt_float32_copy_to_utf16_string_with_index";
389
0
  size_t safe_utf16_string_index = 0;
390
0
  uint32_t divider               = 0;
391
0
  uint32_t value_fraction        = 0;
392
0
  uint16_t exponent_sign         = 0;
393
0
  int16_t exponent10             = 0;
394
0
  int16_t exponent2              = 0;
395
0
  uint8_t digit_index            = 0;
396
0
  uint8_t is_indeterminate       = 0;
397
0
  uint8_t is_infinite            = 0;
398
0
  uint8_t is_not_a_number        = 0;
399
0
  uint8_t is_negative            = 0;
400
0
  uint8_t number_of_characters   = 0;
401
0
  double exponent_value          = 0.0;
402
0
  double value_float             = 0.0;
403
404
0
  if( utf16_string == NULL )
405
0
  {
406
0
    libcerror_error_set(
407
0
     error,
408
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
409
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
410
0
     "%s: invalid UTF-16 string.",
411
0
     function );
412
413
0
    return( -1 );
414
0
  }
415
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
416
0
  {
417
0
    libcerror_error_set(
418
0
     error,
419
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
420
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
421
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
422
0
     function );
423
424
0
    return( -1 );
425
0
  }
426
0
  if( utf16_string_index == NULL )
427
0
  {
428
0
    libcerror_error_set(
429
0
     error,
430
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
431
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
432
0
     "%s: invalid UTF-16 string index.",
433
0
     function );
434
435
0
    return( -1 );
436
0
  }
437
0
  safe_utf16_string_index = *utf16_string_index;
438
439
0
  is_negative = (uint8_t) ( value_32bit >> 31 );
440
441
0
  if( is_negative != 0 )
442
0
  {
443
0
    value_32bit &= ~( (uint32_t) 1 << 31 );
444
0
  }
445
0
  if( value_32bit == 0x7f800000UL )
446
0
  {
447
0
    is_infinite = 1;
448
0
  }
449
0
  else if( ( is_negative != 0 )
450
0
        && ( value_32bit == 0x7fc00000UL ) )
451
0
  {
452
0
    is_indeterminate = 1;
453
0
  }
454
0
  else if( ( value_32bit >= 0x7f800001UL )
455
0
        && ( value_32bit <= 0x7fffffffUL ) )
456
0
  {
457
0
    is_not_a_number = 1;
458
0
  }
459
0
  else if( value_32bit != 0 )
460
0
  {
461
0
    value_float32.integer = value_32bit;
462
0
    value_float           = (double) value_float32.floating_point;
463
464
0
    exponent2 = (int16_t) ( value_32bit >> 23 );
465
466
0
    if( exponent2 == 0 )
467
0
    {
468
0
      exponent2 = -126;
469
0
    }
470
0
    else
471
0
    {
472
0
      exponent2 -= 127;
473
0
    }
474
0
  }
475
0
  if( is_indeterminate != 0 )
476
0
  {
477
    /* "Ind" + end-of-string character */
478
0
    number_of_characters = 4;
479
0
  }
480
0
  else if( is_infinite != 0 )
481
0
  {
482
    /* "Inf" + end-of-string character */
483
0
    number_of_characters = 4;
484
0
  }
485
0
  else if( is_not_a_number != 0 )
486
0
  {
487
    /* "Nan" + end-of-string character */
488
0
    number_of_characters = 4;
489
0
  }
490
0
  else
491
0
  {
492
    /* "[-]0.000000e[+-]000" + end-of-string character */
493
0
    if( is_negative != 0 )
494
0
    {
495
0
      number_of_characters = 15;
496
0
    }
497
0
    else
498
0
    {
499
0
      number_of_characters = 14;
500
0
    }
501
0
  }
502
0
  if( ( number_of_characters > utf16_string_size )
503
0
   || ( safe_utf16_string_index > ( utf16_string_size - number_of_characters ) ) )
504
0
  {
505
0
    libcerror_error_set(
506
0
     error,
507
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
508
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
509
0
     "%s: invalid UTF-16 string size value too small.",
510
0
     function );
511
512
0
    return( -1 );
513
0
  }
514
0
  if( is_indeterminate != 0 )
515
0
  {
516
    /* "Ind" + end-of-string character */
517
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'I';
518
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'n';
519
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'd';
520
0
  }
521
0
  else if( is_infinite != 0 )
522
0
  {
523
    /* "Inf" + end-of-string character */
524
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'I';
525
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'n';
526
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'f';
527
0
  }
528
0
  else if( is_not_a_number != 0 )
529
0
  {
530
    /* "Nan" + end-of-string character */
531
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'N';
532
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'a';
533
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'N';
534
0
  }
535
0
  else
536
0
  {
537
    /* "[-]0.000000e[+-]000" + end-of-string character */
538
0
    if( is_negative != 0 )
539
0
    {
540
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '-';
541
0
    }
542
0
    if( exponent2 < 0 )
543
0
    {
544
0
      exponent_sign = (uint16_t) '-';
545
0
      exponent2    *= -1;
546
0
    }
547
0
    else
548
0
    {
549
0
      exponent_sign = (uint16_t) '+';
550
0
    }
551
0
    exponent_value = 1.0;
552
0
    exponent10     = 0;
553
554
0
    while( exponent2 > 0 )
555
0
    {
556
0
      exponent_value *= 2;
557
0
      exponent2--;
558
559
0
      if( exponent_value >= 10.0 )
560
0
      {
561
0
        exponent_value /= 10.0;
562
0
        exponent10++;
563
564
0
        if( exponent_sign == (uint16_t) '-' )
565
0
        {
566
0
          value_float *= 10.0;
567
0
        }
568
0
        else
569
0
        {
570
0
          value_float /= 10.0;
571
0
        }
572
0
      }
573
0
    }
574
0
    if( value_float != 0.0 )
575
0
    {
576
0
      while( ( value_float < 1.0 )
577
0
          || ( value_float >= 10.0 ) )
578
0
      {
579
0
        exponent10++;
580
581
0
        if( exponent_sign == (uint16_t) '-' )
582
0
        {
583
0
          value_float *= 10;
584
0
        }
585
0
        else
586
0
        {
587
0
          value_float /= 10;
588
0
        }
589
0
      }
590
0
    }
591
0
    for( digit_index = 0;
592
0
         digit_index < 7;
593
0
         digit_index++ )
594
0
    {
595
0
      value_fraction *= 10;
596
0
      value_fraction += (uint8_t) value_float;
597
598
0
      value_float -= (uint8_t) value_float;
599
0
      value_float *= 10.0;
600
0
    }
601
0
    if( value_float >= 5.0 )
602
0
    {
603
0
      value_fraction += 1;
604
0
    }
605
0
    divider = 1000000;
606
607
0
    for( digit_index = 0;
608
0
         digit_index < 7;
609
0
         digit_index++ )
610
0
    {
611
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '0' + (uint16_t) ( value_fraction / divider );
612
613
0
      if( digit_index == 0 )
614
0
      {
615
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '.';
616
0
      }
617
0
      value_fraction %= divider;
618
0
      divider        /= 10;
619
0
    }
620
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'e';
621
0
    utf16_string[ safe_utf16_string_index++ ] = exponent_sign;
622
623
0
    divider = 100;
624
625
0
    for( digit_index = 0;
626
0
         digit_index < 3;
627
0
         digit_index++ )
628
0
    {
629
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '0' + (uint16_t) ( exponent10 / divider );
630
631
0
      exponent10 %= divider;
632
0
      divider    /= 10;
633
0
    }
634
0
  }
635
0
  utf16_string[ safe_utf16_string_index++ ] = 0;
636
637
0
  *utf16_string_index = safe_utf16_string_index;
638
639
0
  return( 1 );
640
0
}
641
642
/* Deterimes the size of the string of a 64-bit floating point
643
 * The string size includes the end of string character
644
 * Returns 1 if successful or -1 on error
645
 */
646
int libfwevt_float64_get_string_size(
647
     uint64_t value_64bit,
648
     size_t *string_size,
649
     libcerror_error_t **error )
650
0
{
651
0
  static char *function        = "libfwevt_float64_get_string_size";
652
0
  uint8_t is_indeterminate     = 0;
653
0
  uint8_t is_infinite          = 0;
654
0
  uint8_t is_not_a_number      = 0;
655
0
  uint8_t is_negative          = 0;
656
0
  uint8_t number_of_characters = 0;
657
658
0
  if( string_size == NULL )
659
0
  {
660
0
    libcerror_error_set(
661
0
     error,
662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
664
0
     "%s: invalid string size.",
665
0
     function );
666
667
0
    return( -1 );
668
0
  }
669
0
  is_negative = (uint8_t) ( value_64bit >> 63 );
670
671
0
  if( is_negative != 0 )
672
0
  {
673
0
    value_64bit &= ~( (uint64_t) 1 << 63 );
674
0
  }
675
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
676
  if( value_64bit == 0x7ff0000000000000UL )
677
#else
678
0
  if( value_64bit == 0x7ff0000000000000ULL )
679
0
#endif
680
0
  {
681
0
    is_infinite = 1;
682
0
  }
683
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
684
  else if( ( is_negative != 0 )
685
        && ( value_64bit == 0x7ff8000000000000UL ) )
686
#else
687
0
  else if( ( is_negative != 0 )
688
0
        && ( value_64bit == 0x7ff8000000000000ULL ) )
689
0
#endif
690
0
  {
691
0
    is_indeterminate = 1;
692
0
  }
693
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
694
  else if( ( value_64bit >= 0x7ff0000000000001UL )
695
        && ( value_64bit <= 0x7fffffffffffffffUL ) )
696
#else
697
0
  else if( ( value_64bit >= 0x7ff0000000000001ULL )
698
0
        && ( value_64bit <= 0x7fffffffffffffffULL ) )
699
0
#endif
700
0
  {
701
0
    is_not_a_number = 1;
702
0
  }
703
0
  if( is_indeterminate != 0 )
704
0
  {
705
    /* "Ind" + end-of-string character */
706
0
    number_of_characters = 4;
707
0
  }
708
0
  else if( is_infinite != 0 )
709
0
  {
710
    /* "Inf" + end-of-string character */
711
0
    number_of_characters = 4;
712
0
  }
713
0
  else if( is_not_a_number != 0 )
714
0
  {
715
    /* "Nan" + end-of-string character */
716
0
    number_of_characters = 4;
717
0
  }
718
0
  else
719
0
  {
720
    /* "[-]0.000000e[+-]000" + end-of-string character */
721
0
    if( is_negative != 0 )
722
0
    {
723
0
      number_of_characters = 15;
724
0
    }
725
0
    else
726
0
    {
727
0
      number_of_characters = 14;
728
0
    }
729
0
  }
730
0
  *string_size = number_of_characters;
731
732
0
  return( 1 );
733
0
}
734
735
/* Copies a 64-bit floating point to an UTF-8 string
736
 * The string size should include the end of string character
737
 * Returns 1 if successful or -1 on error
738
 */
739
int libfwevt_float64_copy_to_utf8_string_with_index(
740
     uint64_t value_64bit,
741
     uint8_t *utf8_string,
742
     size_t utf8_string_size,
743
     size_t *utf8_string_index,
744
     libcerror_error_t **error )
745
0
{
746
0
  byte_stream_float64_t value_float64;
747
748
0
  static char *function         = "libfwevt_float64_copy_to_utf8_string_with_index";
749
0
  size_t safe_utf8_string_index = 0;
750
0
  uint64_t divider              = 0;
751
0
  uint64_t value_fraction       = 0;
752
0
  int16_t exponent10            = 0;
753
0
  int16_t exponent2             = 0;
754
0
  uint8_t digit_index           = 0;
755
0
  uint8_t exponent_sign         = 0;
756
0
  uint8_t is_indeterminate      = 0;
757
0
  uint8_t is_infinite           = 0;
758
0
  uint8_t is_not_a_number       = 0;
759
0
  uint8_t is_negative           = 0;
760
0
  uint8_t number_of_characters  = 0;
761
0
  double exponent_value         = 0.0;
762
0
  double value_float            = 0.0;
763
764
0
  if( utf8_string == NULL )
765
0
  {
766
0
    libcerror_error_set(
767
0
     error,
768
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
769
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
770
0
     "%s: invalid UTF-8 string.",
771
0
     function );
772
773
0
    return( -1 );
774
0
  }
775
0
  if( utf8_string_size > (size_t) SSIZE_MAX )
776
0
  {
777
0
    libcerror_error_set(
778
0
     error,
779
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
780
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
781
0
     "%s: invalid UTF-8 string size value exceeds maximum.",
782
0
     function );
783
784
0
    return( -1 );
785
0
  }
786
0
  if( utf8_string_index == NULL )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
791
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
792
0
     "%s: invalid UTF-8 string index.",
793
0
     function );
794
795
0
    return( -1 );
796
0
  }
797
0
  safe_utf8_string_index = *utf8_string_index;
798
799
0
  is_negative = (uint8_t) ( value_64bit >> 63 );
800
801
0
  if( is_negative != 0 )
802
0
  {
803
0
    value_64bit &= ~( (uint64_t) 1 << 63 );
804
0
  }
805
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
806
  if( value_64bit == 0x7ff0000000000000UL )
807
#else
808
0
  if( value_64bit == 0x7ff0000000000000ULL )
809
0
#endif
810
0
  {
811
0
    is_infinite = 1;
812
0
  }
813
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
814
  else if( ( is_negative != 0 )
815
        && ( value_64bit == 0x7ff8000000000000UL ) )
816
#else
817
0
  else if( ( is_negative != 0 )
818
0
        && ( value_64bit == 0x7ff8000000000000ULL ) )
819
0
#endif
820
0
  {
821
0
    is_indeterminate = 1;
822
0
  }
823
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
824
  else if( ( value_64bit >= 0x7ff0000000000001UL )
825
        && ( value_64bit <= 0x7fffffffffffffffUL ) )
826
#else
827
0
  else if( ( value_64bit >= 0x7ff0000000000001ULL )
828
0
        && ( value_64bit <= 0x7fffffffffffffffULL ) )
829
0
#endif
830
0
  {
831
0
    is_not_a_number = 1;
832
0
  }
833
0
  else if( value_64bit != 0 )
834
0
  {
835
0
    value_float64.integer = value_64bit;
836
0
    value_float           = (double) value_float64.floating_point;
837
838
0
    exponent2 = (int16_t) ( value_64bit >> 52 );
839
840
0
    if( exponent2 == 0 )
841
0
    {
842
0
      exponent2 = -1023;
843
0
    }
844
0
    else
845
0
    {
846
0
      exponent2 -= 1023;
847
0
    }
848
0
  }
849
0
  if( is_indeterminate != 0 )
850
0
  {
851
    /* "Ind" + end-of-string character */
852
0
    number_of_characters = 4;
853
0
  }
854
0
  else if( is_infinite != 0 )
855
0
  {
856
    /* "Inf" + end-of-string character */
857
0
    number_of_characters = 4;
858
0
  }
859
0
  else if( is_not_a_number != 0 )
860
0
  {
861
    /* "Nan" + end-of-string character */
862
0
    number_of_characters = 4;
863
0
  }
864
0
  else
865
0
  {
866
    /* "[-]0.000000e[+-]000" + end-of-string character */
867
0
    if( is_negative != 0 )
868
0
    {
869
0
      number_of_characters = 15;
870
0
    }
871
0
    else
872
0
    {
873
0
      number_of_characters = 14;
874
0
    }
875
0
  }
876
0
  if( ( number_of_characters > utf8_string_size )
877
0
   || ( safe_utf8_string_index > ( utf8_string_size - number_of_characters ) ) )
878
0
  {
879
0
    libcerror_error_set(
880
0
     error,
881
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
882
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
883
0
     "%s: invalid UTF-8 string size value too small.",
884
0
     function );
885
886
0
    return( -1 );
887
0
  }
888
0
  if( is_indeterminate != 0 )
889
0
  {
890
    /* "Ind" + end-of-string character */
891
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'I';
892
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'n';
893
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'd';
894
0
  }
895
0
  else if( is_infinite != 0 )
896
0
  {
897
    /* "Inf" + end-of-string character */
898
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'I';
899
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'n';
900
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'f';
901
0
  }
902
0
  else if( is_not_a_number != 0 )
903
0
  {
904
    /* "Nan" + end-of-string character */
905
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'N';
906
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'a';
907
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'N';
908
0
  }
909
0
  else
910
0
  {
911
    /* "[-]0.000000e[+-]000" + end-of-string character */
912
0
    if( is_negative != 0 )
913
0
    {
914
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '-';
915
0
    }
916
0
    if( exponent2 < 0 )
917
0
    {
918
0
      exponent_sign = (uint8_t) '-';
919
0
      exponent2    *= -1;
920
0
    }
921
0
    else
922
0
    {
923
0
      exponent_sign = (uint8_t) '+';
924
0
    }
925
0
    exponent_value = 1.0;
926
0
    exponent10     = 0;
927
928
0
    while( exponent2 > 0 )
929
0
    {
930
0
      exponent_value *= 2;
931
0
      exponent2--;
932
933
0
      if( exponent_value >= 10.0 )
934
0
      {
935
0
        exponent_value /= 10.0;
936
0
        exponent10++;
937
938
0
        if( exponent_sign == (uint8_t) '-' )
939
0
        {
940
0
          value_float *= 10.0;
941
0
        }
942
0
        else
943
0
        {
944
0
          value_float /= 10.0;
945
0
        }
946
0
      }
947
0
    }
948
0
    if( value_float != 0.0 )
949
0
    {
950
0
      while( ( value_float < 1.0 )
951
0
          || ( value_float >= 10.0 ) )
952
0
      {
953
0
        exponent10++;
954
955
0
        if( exponent_sign == (uint8_t) '-' )
956
0
        {
957
0
          value_float *= 10;
958
0
        }
959
0
        else
960
0
        {
961
0
          value_float /= 10;
962
0
        }
963
0
      }
964
0
    }
965
0
    for( digit_index = 0;
966
0
         digit_index < 7;
967
0
         digit_index++ )
968
0
    {
969
0
      value_fraction *= 10;
970
0
      value_fraction += (uint8_t) value_float;
971
972
0
      value_float -= (uint8_t) value_float;
973
0
      value_float *= 10.0;
974
0
    }
975
0
    if( value_float >= 5.0 )
976
0
    {
977
0
      value_fraction += 1;
978
0
    }
979
0
    divider = 1000000;
980
981
0
    for( digit_index = 0;
982
0
         digit_index < 7;
983
0
         digit_index++ )
984
0
    {
985
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '0' + (uint8_t) ( value_fraction / divider );
986
987
0
      if( digit_index == 0 )
988
0
      {
989
0
        utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '.';
990
0
      }
991
0
      value_fraction %= divider;
992
0
      divider        /= 10;
993
0
    }
994
0
    utf8_string[ safe_utf8_string_index++ ] = (uint8_t) 'e';
995
0
    utf8_string[ safe_utf8_string_index++ ] = exponent_sign;
996
997
0
    divider = 100;
998
999
0
    for( digit_index = 0;
1000
0
         digit_index < 3;
1001
0
         digit_index++ )
1002
0
    {
1003
0
      utf8_string[ safe_utf8_string_index++ ] = (uint8_t) '0' + (uint8_t) ( exponent10 / divider );
1004
1005
0
      exponent10 %= divider;
1006
0
      divider    /= 10;
1007
0
    }
1008
0
  }
1009
0
  utf8_string[ safe_utf8_string_index++ ] = 0;
1010
1011
0
  *utf8_string_index = safe_utf8_string_index;
1012
1013
0
  return( 1 );
1014
0
}
1015
1016
/* Copies a 64-bit floating point to an UTF-16 string
1017
 * The string size should include the end of string character
1018
 * Returns 1 if successful or -1 on error
1019
 */
1020
int libfwevt_float64_copy_to_utf16_string_with_index(
1021
     uint64_t value_64bit,
1022
     uint16_t *utf16_string,
1023
     size_t utf16_string_size,
1024
     size_t *utf16_string_index,
1025
     libcerror_error_t **error )
1026
0
{
1027
0
  byte_stream_float64_t value_float64;
1028
1029
0
  static char *function          = "libfwevt_float64_copy_to_utf16_string_with_index";
1030
0
  size_t safe_utf16_string_index = 0;
1031
0
  uint64_t divider               = 0;
1032
0
  uint64_t value_fraction        = 0;
1033
0
  uint16_t exponent_sign         = 0;
1034
0
  int16_t exponent10             = 0;
1035
0
  int16_t exponent2              = 0;
1036
0
  uint8_t digit_index            = 0;
1037
0
  uint8_t is_indeterminate       = 0;
1038
0
  uint8_t is_infinite            = 0;
1039
0
  uint8_t is_not_a_number        = 0;
1040
0
  uint8_t is_negative            = 0;
1041
0
  uint8_t number_of_characters   = 0;
1042
0
  double exponent_value          = 0.0;
1043
0
  double value_float             = 0.0;
1044
1045
0
  if( utf16_string == NULL )
1046
0
  {
1047
0
    libcerror_error_set(
1048
0
     error,
1049
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1050
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1051
0
     "%s: invalid UTF-16 string.",
1052
0
     function );
1053
1054
0
    return( -1 );
1055
0
  }
1056
0
  if( utf16_string_size > (size_t) SSIZE_MAX )
1057
0
  {
1058
0
    libcerror_error_set(
1059
0
     error,
1060
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1061
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1062
0
     "%s: invalid UTF-16 string size value exceeds maximum.",
1063
0
     function );
1064
1065
0
    return( -1 );
1066
0
  }
1067
0
  if( utf16_string_index == NULL )
1068
0
  {
1069
0
    libcerror_error_set(
1070
0
     error,
1071
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1072
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1073
0
     "%s: invalid UTF-16 string index.",
1074
0
     function );
1075
1076
0
    return( -1 );
1077
0
  }
1078
0
  safe_utf16_string_index = *utf16_string_index;
1079
1080
0
  is_negative = (uint8_t) ( value_64bit >> 63 );
1081
1082
0
  if( is_negative != 0 )
1083
0
  {
1084
0
    value_64bit &= ~( (uint64_t) 1 << 63 );
1085
0
  }
1086
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
1087
  if( value_64bit == 0x7ff0000000000000UL )
1088
#else
1089
0
  if( value_64bit == 0x7ff0000000000000ULL )
1090
0
#endif
1091
0
  {
1092
0
    is_infinite = 1;
1093
0
  }
1094
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
1095
  else if( ( is_negative != 0 )
1096
        && ( value_64bit == 0x7ff8000000000000UL ) )
1097
#else
1098
0
  else if( ( is_negative != 0 )
1099
0
        && ( value_64bit == 0x7ff8000000000000ULL ) )
1100
0
#endif
1101
0
  {
1102
0
    is_indeterminate = 1;
1103
0
  }
1104
#if defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x0560 )
1105
  else if( ( value_64bit >= 0x7ff0000000000001UL )
1106
        && ( value_64bit <= 0x7fffffffffffffffUL ) )
1107
#else
1108
0
  else if( ( value_64bit >= 0x7ff0000000000001ULL )
1109
0
        && ( value_64bit <= 0x7fffffffffffffffULL ) )
1110
0
#endif
1111
0
  {
1112
0
    is_not_a_number = 1;
1113
0
  }
1114
0
  else if( value_64bit != 0 )
1115
0
  {
1116
0
    value_float64.integer = value_64bit;
1117
0
    value_float           = (double) value_float64.floating_point;
1118
1119
0
    exponent2 = (int16_t) ( value_64bit >> 52 );
1120
1121
0
    if( exponent2 == 0 )
1122
0
    {
1123
0
      exponent2 = -1023;
1124
0
    }
1125
0
    else
1126
0
    {
1127
0
      exponent2 -= 1023;
1128
0
    }
1129
0
  }
1130
0
  if( is_indeterminate != 0 )
1131
0
  {
1132
    /* "Ind" + end-of-string character */
1133
0
    number_of_characters = 4;
1134
0
  }
1135
0
  else if( is_infinite != 0 )
1136
0
  {
1137
    /* "Inf" + end-of-string character */
1138
0
    number_of_characters = 4;
1139
0
  }
1140
0
  else if( is_not_a_number != 0 )
1141
0
  {
1142
    /* "Nan" + end-of-string character */
1143
0
    number_of_characters = 4;
1144
0
  }
1145
0
  else
1146
0
  {
1147
    /* "[-]0.000000e[+-]000" + end-of-string character */
1148
0
    if( is_negative != 0 )
1149
0
    {
1150
0
      number_of_characters = 15;
1151
0
    }
1152
0
    else
1153
0
    {
1154
0
      number_of_characters = 14;
1155
0
    }
1156
0
  }
1157
0
  if( ( number_of_characters > utf16_string_size )
1158
0
   || ( safe_utf16_string_index > ( utf16_string_size - number_of_characters ) ) )
1159
0
  {
1160
0
    libcerror_error_set(
1161
0
     error,
1162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1163
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1164
0
     "%s: invalid UTF-16 string size value too small.",
1165
0
     function );
1166
1167
0
    return( -1 );
1168
0
  }
1169
0
  if( is_indeterminate != 0 )
1170
0
  {
1171
    /* "Ind" + end-of-string character */
1172
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'I';
1173
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'n';
1174
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'd';
1175
0
  }
1176
0
  else if( is_infinite != 0 )
1177
0
  {
1178
    /* "Inf" + end-of-string character */
1179
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'I';
1180
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'n';
1181
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'f';
1182
0
  }
1183
0
  else if( is_not_a_number != 0 )
1184
0
  {
1185
    /* "Nan" + end-of-string character */
1186
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'N';
1187
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'a';
1188
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'N';
1189
0
  }
1190
0
  else
1191
0
  {
1192
    /* "[-]0.000000e[+-]000" + end-of-string character */
1193
0
    if( is_negative != 0 )
1194
0
    {
1195
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '-';
1196
0
    }
1197
0
    if( exponent2 < 0 )
1198
0
    {
1199
0
      exponent_sign = (uint16_t) '-';
1200
0
      exponent2    *= -1;
1201
0
    }
1202
0
    else
1203
0
    {
1204
0
      exponent_sign = (uint16_t) '+';
1205
0
    }
1206
0
    exponent_value = 1.0;
1207
0
    exponent10     = 0;
1208
1209
0
    while( exponent2 > 0 )
1210
0
    {
1211
0
      exponent_value *= 2;
1212
0
      exponent2--;
1213
1214
0
      if( exponent_value >= 10.0 )
1215
0
      {
1216
0
        exponent_value /= 10.0;
1217
0
        exponent10++;
1218
1219
0
        if( exponent_sign == (uint16_t) '-' )
1220
0
        {
1221
0
          value_float *= 10.0;
1222
0
        }
1223
0
        else
1224
0
        {
1225
0
          value_float /= 10.0;
1226
0
        }
1227
0
      }
1228
0
    }
1229
0
    if( value_float != 0.0 )
1230
0
    {
1231
0
      while( ( value_float < 1.0 )
1232
0
          || ( value_float >= 10.0 ) )
1233
0
      {
1234
0
        exponent10++;
1235
1236
0
        if( exponent_sign == (uint16_t) '-' )
1237
0
        {
1238
0
          value_float *= 10;
1239
0
        }
1240
0
        else
1241
0
        {
1242
0
          value_float /= 10;
1243
0
        }
1244
0
      }
1245
0
    }
1246
0
    for( digit_index = 0;
1247
0
         digit_index < 7;
1248
0
         digit_index++ )
1249
0
    {
1250
0
      value_fraction *= 10;
1251
0
      value_fraction += (uint8_t) value_float;
1252
1253
0
      value_float -= (uint8_t) value_float;
1254
0
      value_float *= 10.0;
1255
0
    }
1256
0
    if( value_float >= 5.0 )
1257
0
    {
1258
0
      value_fraction += 1;
1259
0
    }
1260
0
    divider = 1000000;
1261
1262
0
    for( digit_index = 0;
1263
0
         digit_index < 7;
1264
0
         digit_index++ )
1265
0
    {
1266
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '0' + (uint16_t) ( value_fraction / divider );
1267
1268
0
      if( digit_index == 0 )
1269
0
      {
1270
0
        utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '.';
1271
0
      }
1272
0
      value_fraction %= divider;
1273
0
      divider        /= 10;
1274
0
    }
1275
0
    utf16_string[ safe_utf16_string_index++ ] = (uint16_t) 'e';
1276
0
    utf16_string[ safe_utf16_string_index++ ] = exponent_sign;
1277
1278
0
    divider = 100;
1279
1280
0
    for( digit_index = 0;
1281
0
         digit_index < 3;
1282
0
         digit_index++ )
1283
0
    {
1284
0
      utf16_string[ safe_utf16_string_index++ ] = (uint16_t) '0' + (uint16_t) ( exponent10 / divider );
1285
1286
0
      exponent10 %= divider;
1287
0
      divider    /= 10;
1288
0
    }
1289
0
  }
1290
0
  utf16_string[ safe_utf16_string_index++ ] = 0;
1291
1292
0
  *utf16_string_index = safe_utf16_string_index;
1293
1294
0
  return( 1 );
1295
0
}
1296