110ff414cSEd Maste /* 210ff414cSEd Maste * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> 310ff414cSEd Maste * 410ff414cSEd Maste * libcbor is free software; you can redistribute it and/or modify 510ff414cSEd Maste * it under the terms of the MIT license. See LICENSE for details. 610ff414cSEd Maste */ 710ff414cSEd Maste 810ff414cSEd Maste #include "loaders.h" 910ff414cSEd Maste #include <math.h> 1010ff414cSEd Maste #include <string.h> 1110ff414cSEd Maste _cbor_load_uint8(cbor_data source)1210ff414cSEd Masteuint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; } 1310ff414cSEd Maste _cbor_load_uint16(const unsigned char * source)1410ff414cSEd Masteuint16_t _cbor_load_uint16(const unsigned char *source) { 1510ff414cSEd Maste #ifdef IS_BIG_ENDIAN 1610ff414cSEd Maste uint16_t result; 1710ff414cSEd Maste memcpy(&result, source, 2); 1810ff414cSEd Maste return result; 1910ff414cSEd Maste #else 2010ff414cSEd Maste return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1); 2110ff414cSEd Maste #endif 2210ff414cSEd Maste } 2310ff414cSEd Maste _cbor_load_uint32(const unsigned char * source)2410ff414cSEd Masteuint32_t _cbor_load_uint32(const unsigned char *source) { 2510ff414cSEd Maste #ifdef IS_BIG_ENDIAN 2610ff414cSEd Maste uint32_t result; 2710ff414cSEd Maste memcpy(&result, source, 4); 2810ff414cSEd Maste return result; 2910ff414cSEd Maste #else 3010ff414cSEd Maste return ((uint32_t) * (source + 0) << 0x18) + 3110ff414cSEd Maste ((uint32_t) * (source + 1) << 0x10) + 3210ff414cSEd Maste ((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3); 3310ff414cSEd Maste #endif 3410ff414cSEd Maste } 3510ff414cSEd Maste _cbor_load_uint64(const unsigned char * source)3610ff414cSEd Masteuint64_t _cbor_load_uint64(const unsigned char *source) { 3710ff414cSEd Maste #ifdef IS_BIG_ENDIAN 3810ff414cSEd Maste uint64_t result; 3910ff414cSEd Maste memcpy(&result, source, 8); 4010ff414cSEd Maste return result; 4110ff414cSEd Maste #else 4210ff414cSEd Maste return ((uint64_t) * (source + 0) << 0x38) + 4310ff414cSEd Maste ((uint64_t) * (source + 1) << 0x30) + 4410ff414cSEd Maste ((uint64_t) * (source + 2) << 0x28) + 4510ff414cSEd Maste ((uint64_t) * (source + 3) << 0x20) + 4610ff414cSEd Maste ((uint32_t) * (source + 4) << 0x18) + 4710ff414cSEd Maste ((uint32_t) * (source + 5) << 0x10) + 4810ff414cSEd Maste ((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7); 4910ff414cSEd Maste #endif 5010ff414cSEd Maste } 5110ff414cSEd Maste 5210ff414cSEd Maste /* As per http://tools.ietf.org/html/rfc7049#appendix-D */ _cbor_decode_half(unsigned char * halfp)5310ff414cSEd Mastefloat _cbor_decode_half(unsigned char *halfp) { 5410ff414cSEd Maste int half = (halfp[0] << 8) + halfp[1]; 5510ff414cSEd Maste int exp = (half >> 10) & 0x1f; 5610ff414cSEd Maste int mant = half & 0x3ff; 5710ff414cSEd Maste double val; 5810ff414cSEd Maste if (exp == 0) 5910ff414cSEd Maste val = ldexp(mant, -24); 6010ff414cSEd Maste else if (exp != 31) 6110ff414cSEd Maste val = ldexp(mant + 1024, exp - 25); 6210ff414cSEd Maste else 6310ff414cSEd Maste val = mant == 0 ? INFINITY : NAN; 6410ff414cSEd Maste return (float)(half & 0x8000 ? -val : val); 6510ff414cSEd Maste } 6610ff414cSEd Maste _cbor_load_half(cbor_data source)67*5d3e7166SEd Mastefloat _cbor_load_half(cbor_data source) { 6810ff414cSEd Maste /* Discard const */ 6910ff414cSEd Maste return _cbor_decode_half((unsigned char *)source); 7010ff414cSEd Maste } 7110ff414cSEd Maste _cbor_load_float(cbor_data source)7210ff414cSEd Mastefloat _cbor_load_float(cbor_data source) { 7310ff414cSEd Maste union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)}; 7410ff414cSEd Maste return helper.as_float; 7510ff414cSEd Maste } 7610ff414cSEd Maste _cbor_load_double(cbor_data source)7710ff414cSEd Mastedouble _cbor_load_double(cbor_data source) { 7810ff414cSEd Maste union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)}; 7910ff414cSEd Maste return helper.as_double; 8010ff414cSEd Maste } 81