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
12cbor_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
17uint8_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
23bool 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
28float 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
34float 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
40double 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
46double 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
61void 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
67void 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
73void 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
79void 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
85bool 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
90cbor_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
103cbor_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
115cbor_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
127cbor_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
139cbor_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
146cbor_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
153cbor_item_t *cbor_build_bool(bool value) {
154  return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
155}
156
157cbor_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
164cbor_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
171cbor_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
178cbor_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