xref: /openbsd-src/lib/libcbor/src/cbor/internal/loaders.c (revision 4dcc46c4d04180142eda526ce521dfb137776d05)
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)129e5c2ddcSdjm uint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; }
13da0d961cSdjm 
_cbor_load_uint16(const unsigned char * source)149e5c2ddcSdjm uint16_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)249e5c2ddcSdjm uint32_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)369e5c2ddcSdjm uint64_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)539e5c2ddcSdjm float _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*4dcc46c4Sdjm float _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)729e5c2ddcSdjm float _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)779e5c2ddcSdjm double _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