110ff414cSEd Maste /*
210ff414cSEd Maste  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
310ff414cSEd Maste  *
410ff414cSEd Maste  * libcbor is free software; you can redistribute it and/or modify
510ff414cSEd Maste  * it under the terms of the MIT license. See LICENSE for details.
610ff414cSEd Maste  */
710ff414cSEd Maste 
810ff414cSEd Maste #include "floats_ctrls.h"
910ff414cSEd Maste #include <math.h>
1010ff414cSEd Maste #include "assert.h"
1110ff414cSEd Maste 
cbor_float_get_width(const cbor_item_t * item)1210ff414cSEd Maste cbor_float_width cbor_float_get_width(const cbor_item_t *item) {
13*5d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_float_ctrl(item));
1410ff414cSEd Maste   return item->metadata.float_ctrl_metadata.width;
1510ff414cSEd Maste }
1610ff414cSEd Maste 
cbor_ctrl_value(const cbor_item_t * item)1710ff414cSEd Maste uint8_t cbor_ctrl_value(const cbor_item_t *item) {
18*5d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_float_ctrl(item));
19*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0);
2010ff414cSEd Maste   return item->metadata.float_ctrl_metadata.ctrl;
2110ff414cSEd Maste }
2210ff414cSEd Maste 
cbor_float_ctrl_is_ctrl(const cbor_item_t * item)2310ff414cSEd Maste bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item) {
24*5d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_float_ctrl(item));
2510ff414cSEd Maste   return cbor_float_get_width(item) == CBOR_FLOAT_0;
2610ff414cSEd Maste }
2710ff414cSEd Maste 
cbor_float_get_float2(const cbor_item_t * item)2810ff414cSEd Maste float cbor_float_get_float2(const cbor_item_t *item) {
29*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
30*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16);
3110ff414cSEd Maste   return *(float *)item->data;
3210ff414cSEd Maste }
3310ff414cSEd Maste 
cbor_float_get_float4(const cbor_item_t * item)3410ff414cSEd Maste float cbor_float_get_float4(const cbor_item_t *item) {
35*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
36*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32);
3710ff414cSEd Maste   return *(float *)item->data;
3810ff414cSEd Maste }
3910ff414cSEd Maste 
cbor_float_get_float8(const cbor_item_t * item)4010ff414cSEd Maste double cbor_float_get_float8(const cbor_item_t *item) {
41*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
42*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64);
4310ff414cSEd Maste   return *(double *)item->data;
4410ff414cSEd Maste }
4510ff414cSEd Maste 
cbor_float_get_float(const cbor_item_t * item)4610ff414cSEd Maste double cbor_float_get_float(const cbor_item_t *item) {
47*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
48*5d3e7166SEd Maste   // cppcheck-suppress missingReturn
4910ff414cSEd Maste   switch (cbor_float_get_width(item)) {
5010ff414cSEd Maste     case CBOR_FLOAT_0:
5110ff414cSEd Maste       return NAN;
5210ff414cSEd Maste     case CBOR_FLOAT_16:
5310ff414cSEd Maste       return cbor_float_get_float2(item);
5410ff414cSEd Maste     case CBOR_FLOAT_32:
5510ff414cSEd Maste       return cbor_float_get_float4(item);
5610ff414cSEd Maste     case CBOR_FLOAT_64:
5710ff414cSEd Maste       return cbor_float_get_float8(item);
5810ff414cSEd Maste   }
5910ff414cSEd Maste }
6010ff414cSEd Maste 
cbor_get_bool(const cbor_item_t * item)6110ff414cSEd Maste bool cbor_get_bool(const cbor_item_t *item) {
62*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_bool(item));
6310ff414cSEd Maste   return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE;
6410ff414cSEd Maste }
6510ff414cSEd Maste 
cbor_set_float2(cbor_item_t * item,float value)6610ff414cSEd Maste void cbor_set_float2(cbor_item_t *item, float value) {
67*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
68*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16);
6910ff414cSEd Maste   *((float *)item->data) = value;
7010ff414cSEd Maste }
7110ff414cSEd Maste 
cbor_set_float4(cbor_item_t * item,float value)7210ff414cSEd Maste void cbor_set_float4(cbor_item_t *item, float value) {
73*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
74*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32);
7510ff414cSEd Maste   *((float *)item->data) = value;
7610ff414cSEd Maste }
7710ff414cSEd Maste 
cbor_set_float8(cbor_item_t * item,double value)7810ff414cSEd Maste void cbor_set_float8(cbor_item_t *item, double value) {
79*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_float(item));
80*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64);
8110ff414cSEd Maste   *((double *)item->data) = value;
8210ff414cSEd Maste }
8310ff414cSEd Maste 
cbor_set_ctrl(cbor_item_t * item,uint8_t value)8410ff414cSEd Maste void cbor_set_ctrl(cbor_item_t *item, uint8_t value) {
85*5d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_float_ctrl(item));
86*5d3e7166SEd Maste   CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0);
8710ff414cSEd Maste   item->metadata.float_ctrl_metadata.ctrl = value;
8810ff414cSEd Maste }
8910ff414cSEd Maste 
cbor_set_bool(cbor_item_t * item,bool value)9010ff414cSEd Maste void cbor_set_bool(cbor_item_t *item, bool value) {
91*5d3e7166SEd Maste   CBOR_ASSERT(cbor_is_bool(item));
9210ff414cSEd Maste   item->metadata.float_ctrl_metadata.ctrl =
9310ff414cSEd Maste       value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE;
9410ff414cSEd Maste }
9510ff414cSEd Maste 
cbor_new_ctrl(void)96*5d3e7166SEd Maste cbor_item_t *cbor_new_ctrl(void) {
97*5d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
9810ff414cSEd Maste   _CBOR_NOTNULL(item);
9910ff414cSEd Maste 
10010ff414cSEd Maste   *item = (cbor_item_t){
10110ff414cSEd Maste       .type = CBOR_TYPE_FLOAT_CTRL,
10210ff414cSEd Maste       .data = NULL,
10310ff414cSEd Maste       .refcount = 1,
10410ff414cSEd Maste       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_0,
10510ff414cSEd Maste                                            .ctrl = CBOR_CTRL_NONE}}};
10610ff414cSEd Maste   return item;
10710ff414cSEd Maste }
10810ff414cSEd Maste 
cbor_new_float2(void)109*5d3e7166SEd Maste cbor_item_t *cbor_new_float2(void) {
110*5d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4);
11110ff414cSEd Maste   _CBOR_NOTNULL(item);
11210ff414cSEd Maste 
11310ff414cSEd Maste   *item = (cbor_item_t){
11410ff414cSEd Maste       .type = CBOR_TYPE_FLOAT_CTRL,
11510ff414cSEd Maste       .data = (unsigned char *)item + sizeof(cbor_item_t),
11610ff414cSEd Maste       .refcount = 1,
11710ff414cSEd Maste       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_16}}};
11810ff414cSEd Maste   return item;
11910ff414cSEd Maste }
12010ff414cSEd Maste 
cbor_new_float4(void)121*5d3e7166SEd Maste cbor_item_t *cbor_new_float4(void) {
122*5d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4);
12310ff414cSEd Maste   _CBOR_NOTNULL(item);
12410ff414cSEd Maste 
12510ff414cSEd Maste   *item = (cbor_item_t){
12610ff414cSEd Maste       .type = CBOR_TYPE_FLOAT_CTRL,
12710ff414cSEd Maste       .data = (unsigned char *)item + sizeof(cbor_item_t),
12810ff414cSEd Maste       .refcount = 1,
12910ff414cSEd Maste       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_32}}};
13010ff414cSEd Maste   return item;
13110ff414cSEd Maste }
13210ff414cSEd Maste 
cbor_new_float8(void)133*5d3e7166SEd Maste cbor_item_t *cbor_new_float8(void) {
134*5d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 8);
13510ff414cSEd Maste   _CBOR_NOTNULL(item);
13610ff414cSEd Maste 
13710ff414cSEd Maste   *item = (cbor_item_t){
13810ff414cSEd Maste       .type = CBOR_TYPE_FLOAT_CTRL,
13910ff414cSEd Maste       .data = (unsigned char *)item + sizeof(cbor_item_t),
14010ff414cSEd Maste       .refcount = 1,
14110ff414cSEd Maste       .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_64}}};
14210ff414cSEd Maste   return item;
14310ff414cSEd Maste }
14410ff414cSEd Maste 
cbor_new_null(void)145*5d3e7166SEd Maste cbor_item_t *cbor_new_null(void) {
14610ff414cSEd Maste   cbor_item_t *item = cbor_new_ctrl();
14710ff414cSEd Maste   _CBOR_NOTNULL(item);
14810ff414cSEd Maste   cbor_set_ctrl(item, CBOR_CTRL_NULL);
14910ff414cSEd Maste   return item;
15010ff414cSEd Maste }
15110ff414cSEd Maste 
cbor_new_undef(void)152*5d3e7166SEd Maste cbor_item_t *cbor_new_undef(void) {
15310ff414cSEd Maste   cbor_item_t *item = cbor_new_ctrl();
15410ff414cSEd Maste   _CBOR_NOTNULL(item);
15510ff414cSEd Maste   cbor_set_ctrl(item, CBOR_CTRL_UNDEF);
15610ff414cSEd Maste   return item;
15710ff414cSEd Maste }
15810ff414cSEd Maste 
cbor_build_bool(bool value)15910ff414cSEd Maste cbor_item_t *cbor_build_bool(bool value) {
16010ff414cSEd Maste   return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
16110ff414cSEd Maste }
16210ff414cSEd Maste 
cbor_build_float2(float value)16310ff414cSEd Maste cbor_item_t *cbor_build_float2(float value) {
16410ff414cSEd Maste   cbor_item_t *item = cbor_new_float2();
16510ff414cSEd Maste   _CBOR_NOTNULL(item);
16610ff414cSEd Maste   cbor_set_float2(item, value);
16710ff414cSEd Maste   return item;
16810ff414cSEd Maste }
16910ff414cSEd Maste 
cbor_build_float4(float value)17010ff414cSEd Maste cbor_item_t *cbor_build_float4(float value) {
17110ff414cSEd Maste   cbor_item_t *item = cbor_new_float4();
17210ff414cSEd Maste   _CBOR_NOTNULL(item);
17310ff414cSEd Maste   cbor_set_float4(item, value);
17410ff414cSEd Maste   return item;
17510ff414cSEd Maste }
17610ff414cSEd Maste 
cbor_build_float8(double value)17710ff414cSEd Maste cbor_item_t *cbor_build_float8(double value) {
17810ff414cSEd Maste   cbor_item_t *item = cbor_new_float8();
17910ff414cSEd Maste   _CBOR_NOTNULL(item);
18010ff414cSEd Maste   cbor_set_float8(item, value);
18110ff414cSEd Maste   return item;
18210ff414cSEd Maste }
18310ff414cSEd Maste 
cbor_build_ctrl(uint8_t value)18410ff414cSEd Maste cbor_item_t *cbor_build_ctrl(uint8_t value) {
18510ff414cSEd Maste   cbor_item_t *item = cbor_new_ctrl();
18610ff414cSEd Maste   _CBOR_NOTNULL(item);
18710ff414cSEd Maste   cbor_set_ctrl(item, value);
18810ff414cSEd Maste   return item;
18910ff414cSEd Maste }
190