1da0d961cSdjm /* 2d3425be1Sdjm * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> 3da0d961cSdjm * 4da0d961cSdjm * libcbor is free software; you can redistribute it and/or modify 5da0d961cSdjm * it under the terms of the MIT license. See LICENSE for details. 6da0d961cSdjm */ 7da0d961cSdjm 8da0d961cSdjm #include "loaders.h" 9da0d961cSdjm #include <math.h> 109e5c2ddcSdjm #include <string.h> 11da0d961cSdjm _cbor_load_uint8(cbor_data source)129e5c2ddcSdjmuint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; } 13da0d961cSdjm _cbor_load_uint16(const unsigned char * source)149e5c2ddcSdjmuint16_t _cbor_load_uint16(const unsigned char *source) { 15da0d961cSdjm #ifdef IS_BIG_ENDIAN 169e5c2ddcSdjm uint16_t result; 179e5c2ddcSdjm memcpy(&result, source, 2); 189e5c2ddcSdjm return result; 19da0d961cSdjm #else 209e5c2ddcSdjm return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1); 21da0d961cSdjm #endif 22da0d961cSdjm } 23da0d961cSdjm _cbor_load_uint32(const unsigned char * source)249e5c2ddcSdjmuint32_t _cbor_load_uint32(const unsigned char *source) { 25da0d961cSdjm #ifdef IS_BIG_ENDIAN 269e5c2ddcSdjm uint32_t result; 279e5c2ddcSdjm memcpy(&result, source, 4); 289e5c2ddcSdjm return result; 29da0d961cSdjm #else 30da0d961cSdjm return ((uint32_t) * (source + 0) << 0x18) + 31da0d961cSdjm ((uint32_t) * (source + 1) << 0x10) + 329e5c2ddcSdjm ((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3); 33da0d961cSdjm #endif 34da0d961cSdjm } 35da0d961cSdjm _cbor_load_uint64(const unsigned char * source)369e5c2ddcSdjmuint64_t _cbor_load_uint64(const unsigned char *source) { 37da0d961cSdjm #ifdef IS_BIG_ENDIAN 389e5c2ddcSdjm uint64_t result; 399e5c2ddcSdjm memcpy(&result, source, 8); 409e5c2ddcSdjm return result; 41da0d961cSdjm #else 42da0d961cSdjm return ((uint64_t) * (source + 0) << 0x38) + 43da0d961cSdjm ((uint64_t) * (source + 1) << 0x30) + 44da0d961cSdjm ((uint64_t) * (source + 2) << 0x28) + 45da0d961cSdjm ((uint64_t) * (source + 3) << 0x20) + 46da0d961cSdjm ((uint32_t) * (source + 4) << 0x18) + 47da0d961cSdjm ((uint32_t) * (source + 5) << 0x10) + 489e5c2ddcSdjm ((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7); 49da0d961cSdjm #endif 50da0d961cSdjm } 51da0d961cSdjm 52da0d961cSdjm /* As per http://tools.ietf.org/html/rfc7049#appendix-D */ _cbor_decode_half(unsigned char * halfp)539e5c2ddcSdjmfloat _cbor_decode_half(unsigned char *halfp) { 54da0d961cSdjm int half = (halfp[0] << 8) + halfp[1]; 55da0d961cSdjm int exp = (half >> 10) & 0x1f; 56da0d961cSdjm int mant = half & 0x3ff; 57da0d961cSdjm double val; 589e5c2ddcSdjm if (exp == 0) 599e5c2ddcSdjm val = ldexp(mant, -24); 609e5c2ddcSdjm else if (exp != 31) 619e5c2ddcSdjm val = ldexp(mant + 1024, exp - 25); 629e5c2ddcSdjm else 639e5c2ddcSdjm val = mant == 0 ? INFINITY : NAN; 64da0d961cSdjm return (float)(half & 0x8000 ? -val : val); 65da0d961cSdjm } 66da0d961cSdjm _cbor_load_half(cbor_data source)67*4dcc46c4Sdjmfloat _cbor_load_half(cbor_data source) { 68da0d961cSdjm /* Discard const */ 69da0d961cSdjm return _cbor_decode_half((unsigned char *)source); 70da0d961cSdjm } 71da0d961cSdjm _cbor_load_float(cbor_data source)729e5c2ddcSdjmfloat _cbor_load_float(cbor_data source) { 73da0d961cSdjm union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)}; 74da0d961cSdjm return helper.as_float; 75da0d961cSdjm } 76da0d961cSdjm _cbor_load_double(cbor_data source)779e5c2ddcSdjmdouble _cbor_load_double(cbor_data source) { 78da0d961cSdjm union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)}; 79da0d961cSdjm return helper.as_double; 80da0d961cSdjm } 81