/src/libcbor/src/cbor/internal/loaders.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> |
3 | | * |
4 | | * libcbor is free software; you can redistribute it and/or modify |
5 | | * it under the terms of the MIT license. See LICENSE for details. |
6 | | */ |
7 | | |
8 | | #include "loaders.h" |
9 | | #include <math.h> |
10 | | #include <string.h> |
11 | | |
12 | 8.73M | uint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; } |
13 | | |
14 | 25.0k | uint16_t _cbor_load_uint16(const unsigned char *source) { |
15 | | #ifdef IS_BIG_ENDIAN |
16 | | uint16_t result; |
17 | | memcpy(&result, source, 2); |
18 | | return result; |
19 | | #else |
20 | 25.0k | return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1); |
21 | 25.0k | #endif |
22 | 25.0k | } |
23 | | |
24 | 10.4k | uint32_t _cbor_load_uint32(const unsigned char *source) { |
25 | | #ifdef IS_BIG_ENDIAN |
26 | | uint32_t result; |
27 | | memcpy(&result, source, 4); |
28 | | return result; |
29 | | #else |
30 | 10.4k | return ((uint32_t) * (source + 0) << 0x18) + |
31 | 10.4k | ((uint32_t) * (source + 1) << 0x10) + |
32 | 10.4k | ((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3); |
33 | 10.4k | #endif |
34 | 10.4k | } |
35 | | |
36 | 17.8k | uint64_t _cbor_load_uint64(const unsigned char *source) { |
37 | | #ifdef IS_BIG_ENDIAN |
38 | | uint64_t result; |
39 | | memcpy(&result, source, 8); |
40 | | return result; |
41 | | #else |
42 | 17.8k | return ((uint64_t) * (source + 0) << 0x38) + |
43 | 17.8k | ((uint64_t) * (source + 1) << 0x30) + |
44 | 17.8k | ((uint64_t) * (source + 2) << 0x28) + |
45 | 17.8k | ((uint64_t) * (source + 3) << 0x20) + |
46 | 17.8k | ((uint32_t) * (source + 4) << 0x18) + |
47 | 17.8k | ((uint32_t) * (source + 5) << 0x10) + |
48 | 17.8k | ((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7); |
49 | 17.8k | #endif |
50 | 17.8k | } |
51 | | |
52 | | /* As per https://www.rfc-editor.org/rfc/rfc8949.html#name-half-precision */ |
53 | 862 | float _cbor_decode_half(unsigned char *halfp) { |
54 | 862 | int half = (halfp[0] << 8) + halfp[1]; |
55 | 862 | int exp = (half >> 10) & 0x1f; |
56 | 862 | int mant = half & 0x3ff; |
57 | 862 | double val; |
58 | 862 | if (exp == 0) |
59 | 304 | val = ldexp(mant, -24); |
60 | 558 | else if (exp != 31) |
61 | 344 | val = ldexp(mant + 1024, exp - 25); |
62 | 214 | else |
63 | 214 | val = mant == 0 ? INFINITY : NAN; |
64 | 862 | return (float)(half & 0x8000 ? -val : val); |
65 | 862 | } |
66 | | |
67 | 862 | float _cbor_load_half(cbor_data source) { |
68 | | /* Discard const */ |
69 | 862 | return _cbor_decode_half((unsigned char *)source); |
70 | 862 | } |
71 | | |
72 | 1.13k | float _cbor_load_float(cbor_data source) { |
73 | 1.13k | union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)}; |
74 | 1.13k | return helper.as_float; |
75 | 1.13k | } |
76 | | |
77 | 375 | double _cbor_load_double(cbor_data source) { |
78 | 375 | union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)}; |
79 | 375 | return helper.as_double; |
80 | 375 | } |