xref: /freebsd/contrib/libcbor/src/cbor/internal/loaders.c (revision ccb59683b98360afaf5b5bb641a68fea22c68d0b)
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 http://tools.ietf.org/html/rfc7049#appendix-D */
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