blob: af00f135527f7155f1147ff7faacc6b8a6a8dd69 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/*
* Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
*
* libcbor is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "loaders.h"
#include <math.h>
#include <string.h>
uint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; }
uint16_t _cbor_load_uint16(const unsigned char *source) {
#ifdef IS_BIG_ENDIAN
uint16_t result;
memcpy(&result, source, 2);
return result;
#else
return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1);
#endif
}
uint32_t _cbor_load_uint32(const unsigned char *source) {
#ifdef IS_BIG_ENDIAN
uint32_t result;
memcpy(&result, source, 4);
return result;
#else
return ((uint32_t) * (source + 0) << 0x18) +
((uint32_t) * (source + 1) << 0x10) +
((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3);
#endif
}
uint64_t _cbor_load_uint64(const unsigned char *source) {
#ifdef IS_BIG_ENDIAN
uint64_t result;
memcpy(&result, source, 8);
return result;
#else
return ((uint64_t) * (source + 0) << 0x38) +
((uint64_t) * (source + 1) << 0x30) +
((uint64_t) * (source + 2) << 0x28) +
((uint64_t) * (source + 3) << 0x20) +
((uint32_t) * (source + 4) << 0x18) +
((uint32_t) * (source + 5) << 0x10) +
((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7);
#endif
}
/* As per http://tools.ietf.org/html/rfc7049#appendix-D */
float _cbor_decode_half(unsigned char *halfp) {
int half = (halfp[0] << 8) + halfp[1];
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0)
val = ldexp(mant, -24);
else if (exp != 31)
val = ldexp(mant + 1024, exp - 25);
else
val = mant == 0 ? INFINITY : NAN;
return (float)(half & 0x8000 ? -val : val);
}
double _cbor_load_half(cbor_data source) {
/* Discard const */
return _cbor_decode_half((unsigned char *)source);
}
float _cbor_load_float(cbor_data source) {
union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)};
return helper.as_float;
}
double _cbor_load_double(cbor_data source) {
union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)};
return helper.as_double;
}
|