1 /*
2  * Copyright (c) 2014-2019 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 "floats_ctrls.h"
9 #include <math.h>
10 #include "assert.h"
11 
cbor_float_get_width(const cbor_item_t * item)12 cbor_float_width cbor_float_get_width(const cbor_item_t *item) {
13   assert(cbor_isa_float_ctrl(item));
14   return item->metadata.float_ctrl_metadata.width;
15 }
16 
cbor_ctrl_value(const cbor_item_t * item)17 uint8_t cbor_ctrl_value(const cbor_item_t *item) {
18   assert(cbor_isa_float_ctrl(item));
19   assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
20   return item->metadata.float_ctrl_metadata.ctrl;
21 }
22 
cbor_float_ctrl_is_ctrl(const cbor_item_t * item)23 bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item) {
24   assert(cbor_isa_float_ctrl(item));
25   return cbor_float_get_width(item) == CBOR_FLOAT_0;
26 }
27 
cbor_float_get_float2(const cbor_item_t * item)28 float cbor_float_get_float2(const cbor_item_t *item) {
29   assert(cbor_is_float(item));
30   assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
31   return *(float *)item->data;
32 }
33 
cbor_float_get_float4(const cbor_item_t * item)34 float cbor_float_get_float4(const cbor_item_t *item) {
35   assert(cbor_is_float(item));
36   assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
37   return *(float *)item->data;
38 }
39 
cbor_float_get_float8(const cbor_item_t * item)40 double cbor_float_get_float8(const cbor_item_t *item) {
41   assert(cbor_is_float(item));
42   assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
43   return *(double *)item->data;
44 }
45 
cbor_float_get_float(const cbor_item_t * item)46 double cbor_float_get_float(const cbor_item_t *item) {
47   assert(cbor_is_float(item));
48   switch (cbor_float_get_width(item)) {
49     case CBOR_FLOAT_0:
50       return NAN;
51     case CBOR_FLOAT_16:
52       return cbor_float_get_float2(item);
53     case CBOR_FLOAT_32:
54       return cbor_float_get_float4(item);
55     case CBOR_FLOAT_64:
56       return cbor_float_get_float8(item);
57   }
58   return NAN; /* Compiler complaints */
59 }
60 
cbor_set_float2(cbor_item_t * item,float value)61 void cbor_set_float2(cbor_item_t *item, float value) {
62   assert(cbor_is_float(item));
63   assert(cbor_float_get_width(item) == CBOR_FLOAT_16);
64   *((float *)item->data) = value;
65 }
66 
cbor_set_float4(cbor_item_t * item,float value)67 void cbor_set_float4(cbor_item_t *item, float value) {
68   assert(cbor_is_float(item));
69   assert(cbor_float_get_width(item) == CBOR_FLOAT_32);
70   *((float *)item->data) = value;
71 }
72 
cbor_set_float8(cbor_item_t * item,double value)73 void cbor_set_float8(cbor_item_t *item, double value) {
74   assert(cbor_is_float(item));
75   assert(cbor_float_get_width(item) == CBOR_FLOAT_64);
76   *((double *)item->data) = value;
77 }
78 
cbor_set_ctrl(cbor_item_t * item,uint8_t value)79 void cbor_set_ctrl(cbor_item_t *item, uint8_t value) {
80   assert(cbor_isa_float_ctrl(item));
81   assert(cbor_float_get_width(item) == CBOR_FLOAT_0);
82   item->metadata.float_ctrl_metadata.ctrl = value;
83 }
84 
cbor_ctrl_is_bool(const cbor_item_t * item)85 bool cbor_ctrl_is_bool(const cbor_item_t *item) {
86   assert(cbor_is_bool(item));
87   return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE;
88 }
89 
cbor_new_ctrl()90 cbor_item_t *cbor_new_ctrl() {
91   cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
92   _CBOR_NOTNULL(item);
93 
94   *item = (cbor_item_t){
95       .type = CBOR_TYPE_FLOAT_CTRL,
96       .data = NULL,
97       .refcount = 1,
98       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_0,
99                                            .ctrl = CBOR_CTRL_NONE}}};
100   return item;
101 }
102 
cbor_new_float2()103 cbor_item_t *cbor_new_float2() {
104   cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
105   _CBOR_NOTNULL(item);
106 
107   *item = (cbor_item_t){
108       .type = CBOR_TYPE_FLOAT_CTRL,
109       .data = (unsigned char *)item + sizeof(cbor_item_t),
110       .refcount = 1,
111       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_16}}};
112   return item;
113 }
114 
cbor_new_float4()115 cbor_item_t *cbor_new_float4() {
116   cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 4);
117   _CBOR_NOTNULL(item);
118 
119   *item = (cbor_item_t){
120       .type = CBOR_TYPE_FLOAT_CTRL,
121       .data = (unsigned char *)item + sizeof(cbor_item_t),
122       .refcount = 1,
123       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_32}}};
124   return item;
125 }
126 
cbor_new_float8()127 cbor_item_t *cbor_new_float8() {
128   cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t) + 8);
129   _CBOR_NOTNULL(item);
130 
131   *item = (cbor_item_t){
132       .type = CBOR_TYPE_FLOAT_CTRL,
133       .data = (unsigned char *)item + sizeof(cbor_item_t),
134       .refcount = 1,
135       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_64}}};
136   return item;
137 }
138 
cbor_new_null()139 cbor_item_t *cbor_new_null() {
140   cbor_item_t *item = cbor_new_ctrl();
141   _CBOR_NOTNULL(item);
142   cbor_set_ctrl(item, CBOR_CTRL_NULL);
143   return item;
144 }
145 
cbor_new_undef()146 cbor_item_t *cbor_new_undef() {
147   cbor_item_t *item = cbor_new_ctrl();
148   _CBOR_NOTNULL(item);
149   cbor_set_ctrl(item, CBOR_CTRL_UNDEF);
150   return item;
151 }
152 
cbor_build_bool(bool value)153 cbor_item_t *cbor_build_bool(bool value) {
154   return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
155 }
156 
cbor_build_float2(float value)157 cbor_item_t *cbor_build_float2(float value) {
158   cbor_item_t *item = cbor_new_float2();
159   _CBOR_NOTNULL(item);
160   cbor_set_float2(item, value);
161   return item;
162 }
163 
cbor_build_float4(float value)164 cbor_item_t *cbor_build_float4(float value) {
165   cbor_item_t *item = cbor_new_float4();
166   _CBOR_NOTNULL(item);
167   cbor_set_float4(item, value);
168   return item;
169 }
170 
cbor_build_float8(double value)171 cbor_item_t *cbor_build_float8(double value) {
172   cbor_item_t *item = cbor_new_float8();
173   _CBOR_NOTNULL(item);
174   cbor_set_float8(item, value);
175   return item;
176 }
177 
cbor_build_ctrl(uint8_t value)178 cbor_item_t *cbor_build_ctrl(uint8_t value) {
179   cbor_item_t *item = cbor_new_ctrl();
180   _CBOR_NOTNULL(item);
181   cbor_set_ctrl(item, value);
182   return item;
183 }
184