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 uint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; } 13 14 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 return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1); 21 #endif 22 } 23 24 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 return ((uint32_t) * (source + 0) << 0x18) + 31 ((uint32_t) * (source + 1) << 0x10) + 32 ((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3); 33 #endif 34 } 35 36 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 return ((uint64_t) * (source + 0) << 0x38) + 43 ((uint64_t) * (source + 1) << 0x30) + 44 ((uint64_t) * (source + 2) << 0x28) + 45 ((uint64_t) * (source + 3) << 0x20) + 46 ((uint32_t) * (source + 4) << 0x18) + 47 ((uint32_t) * (source + 5) << 0x10) + 48 ((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7); 49 #endif 50 } 51 52 /* As per https://www.rfc-editor.org/rfc/rfc8949.html#name-half-precision */ 53 float _cbor_decode_half(unsigned char *halfp) { 54 int half = (halfp[0] << 8) + halfp[1]; 55 int exp = (half >> 10) & 0x1f; 56 int mant = half & 0x3ff; 57 double val; 58 if (exp == 0) 59 val = ldexp(mant, -24); 60 else if (exp != 31) 61 val = ldexp(mant + 1024, exp - 25); 62 else 63 val = mant == 0 ? INFINITY : NAN; 64 return (float)(half & 0x8000 ? -val : val); 65 } 66 67 float _cbor_load_half(cbor_data source) { 68 /* Discard const */ 69 return _cbor_decode_half((unsigned char *)source); 70 } 71 72 float _cbor_load_float(cbor_data source) { 73 union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)}; 74 return helper.as_float; 75 } 76 77 double _cbor_load_double(cbor_data source) { 78 union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)}; 79 return helper.as_double; 80 } 81