summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrimio <vasi.vilvoiu@gmail.com>2018-03-01 23:10:42 +0200
committerrimio <vasi.vilvoiu@gmail.com>2018-03-01 23:10:42 +0200
commit3621d55cd101fa5b23e645287393deefacf43e02 (patch)
tree8dc934e5ed5f2cdcd3f0f2fbae95f87fbab7ea8e
parent245bce0bd3b9af5ab026f4b8453424dbc4a1faea (diff)
Support for fp32 and fp64
-rw-r--r--include/ecbor.h28
-rw-r--r--src/ecbor.c41
-rw-r--r--src/ecbor_decoder.c65
-rw-r--r--src/ecbor_describe.c26
-rw-r--r--src/ecbor_internal.h6
-rwxr-xr-xtest/runtests.sh2
6 files changed, 162 insertions, 6 deletions
diff --git a/include/ecbor.h b/include/ecbor.h
index 039264f..730d786 100644
--- a/include/ecbor.h
+++ b/include/ecbor.h
@@ -61,7 +61,10 @@ typedef enum {
* CBOR major types
*/
typedef enum {
- ECBOR_MT_UNDEFINED = -1,
+ /* first type, used for bounds checking */
+ ECBOR_MT_FIRST = 0,
+
+ /* Major types as defined in the RFC */
ECBOR_MT_UINT = 0,
ECBOR_MT_NINT = 1,
ECBOR_MT_BSTR = 2,
@@ -69,20 +72,31 @@ typedef enum {
ECBOR_MT_ARRAY = 4,
ECBOR_MT_MAP = 5,
ECBOR_MT_TAG = 6,
- ECBOR_MT_SPECIAL = 7,
+ ECBOR_MT_SPECIAL = 7, /* this will be translated to a custom type */
+
+ /* Custom types */
+ ECBOR_MT_UNDEFINED = -1,
+ ECBOR_MT_FP16 = 8,
+ ECBOR_MT_FP32 = 9,
+ ECBOR_MT_FP64 = 10,
+
+ /* last code, used for bounds checking */
+ ECBOR_MT_LAST = 10
} ecbor_major_type_t;
/*
* CBOR Item
*/
typedef struct {
- /* major type of item */
+ /* major type and additional info of item */
ecbor_major_type_t major_type;
/* value */
union {
uint64_t uinteger;
int64_t integer;
+ float fp32;
+ double fp64;
struct {
uint64_t tag_value;
const uint8_t *child;
@@ -255,6 +269,14 @@ ecbor_get_tag_item (ecbor_item_t *tag, ecbor_item_t *arr_item);
((i).major_type == ECBOR_MT_MAP)
#define ECBOR_IS_TAG(i) \
((i).major_type == ECBOR_MT_TAG)
+#define ECBOR_IS_FP32(i) \
+ ((i).major_type == ECBOR_MT_FP32)
+#define ECBOR_IS_FLOAT(i) \
+ ECBOR_IS_FP32(i)
+#define ECBOR_IS_FP64(i) \
+ ((i).major_type == ECBOR_MT_FP64)
+#define ECBOR_IS_DOUBLE(i) \
+ ECBOR_IS_FP64(i)
#define ECBOR_GET_INT(i) \
((i).value.integer)
diff --git a/src/ecbor.c b/src/ecbor.c
index 2a9b5fb..0a5e3fb 100644
--- a/src/ecbor.c
+++ b/src/ecbor.c
@@ -58,14 +58,40 @@ ecbor_uint64_from_big_endian (uint64_t value)
#endif
}
+extern float
+ecbor_fp32_from_big_endian (float value)
+{
+#if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ return value;
+#elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ uint32_t r = ecbor_uint32_from_big_endian(*((uint32_t *) &value));
+ return *((float *) &r);
+#else
+ #error "Endianness not supported!"
+#endif
+}
+
+extern double
+ecbor_fp64_from_big_endian (double value)
+{
+#if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ return value;
+#elif __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ uint64_t r = ecbor_uint64_from_big_endian(*((uint64_t *) &value));
+ return *((double *) &r);
+#else
+ #error "Endianness not supported!"
+#endif
+}
+
extern ecbor_major_type_t
ecbor_get_type (ecbor_item_t *item)
{
if (!item) {
return ECBOR_MT_UNDEFINED;
}
- if (item->major_type < ECBOR_MT_UINT
- || item->major_type > ECBOR_MT_SPECIAL) {
+ if (item->major_type < ECBOR_MT_FIRST
+ || item->major_type > ECBOR_MT_LAST) {
return ECBOR_MT_UNDEFINED;
}
return item->major_type;
@@ -101,6 +127,17 @@ ecbor_get_value (ecbor_item_t *item, void *value)
case ECBOR_MT_TAG:
*((uint64_t *)value) = item->value.tag.tag_value;
break;
+
+ case ECBOR_MT_FP16:
+ return ECBOR_ERR_CURRENTLY_NOT_SUPPORTED;
+
+ case ECBOR_MT_FP32:
+ *((float *)value) = item->value.fp32;
+ break;
+
+ case ECBOR_MT_FP64:
+ *((double *)value) = item->value.fp64;
+ break;
default:
return ECBOR_ERR_INVALID_TYPE;
diff --git a/src/ecbor_decoder.c b/src/ecbor_decoder.c
index 66d4426..1c065d8 100644
--- a/src/ecbor_decoder.c
+++ b/src/ecbor_decoder.c
@@ -145,6 +145,56 @@ ecbor_decode_uint (ecbor_decode_context_t *context,
return ECBOR_OK;
}
+static inline ecbor_error_t
+ecbor_decode_fp32 (ecbor_decode_context_t *context,
+ float *value,
+ uint64_t *size)
+{
+ /* compute storage size */
+ (*size) = sizeof (float);
+ if (context->bytes_left < (*size)) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+
+ /* read actual value */
+ (*value) =
+ ecbor_fp32_from_big_endian (*((float *) context->in_position));
+
+ /* advance buffer */
+ context->in_position += (*size);
+ context->bytes_left -= (*size);
+
+ /* meter the first byte */
+ (*size) ++;
+
+ return ECBOR_OK;
+}
+
+static inline ecbor_error_t
+ecbor_decode_fp64 (ecbor_decode_context_t *context,
+ double *value,
+ uint64_t *size)
+{
+ /* compute storage size */
+ (*size) = sizeof (double);
+ if (context->bytes_left < (*size)) {
+ return ECBOR_ERR_INVALID_END_OF_BUFFER;
+ }
+
+ /* read actual value */
+ (*value) =
+ ecbor_fp64_from_big_endian (*((double *) context->in_position));
+
+ /* advance buffer */
+ context->in_position += (*size);
+ context->bytes_left -= (*size);
+
+ /* meter the first byte */
+ (*size) ++;
+
+ return ECBOR_OK;
+}
+
static ecbor_error_t
ecbor_decode_next_internal (ecbor_decode_context_t *context,
ecbor_item_t *item,
@@ -417,7 +467,22 @@ ecbor_decode_next_internal (ecbor_decode_context_t *context,
/* stop code */
item->size = 1;
return ECBOR_END_OF_INDEFINITE;
+ } else if (additional <= ECBOR_ADDITIONAL_1BYTE) {
+ return ecbor_decode_uint (context, &item->value.uinteger, &item->size,
+ additional);
+ } else if (additional == ECBOR_ADDITIONAL_2BYTE) {
+ /* currently we do not support half float */
+ return ECBOR_ERR_CURRENTLY_NOT_SUPPORTED;
+ } else if (additional == ECBOR_ADDITIONAL_4BYTE) {
+ /* floating point 32bit */
+ item->major_type = ECBOR_MT_FP32;
+ return ecbor_decode_fp32 (context, &item->value.fp32, &item->size);
+ } else if (additional == ECBOR_ADDITIONAL_8BYTE) {
+ /* floating point 64bit */
+ item->major_type = ECBOR_MT_FP64;
+ return ecbor_decode_fp64 (context, &item->value.fp64, &item->size);
} else {
+ /* currently unassigned according to RFC */
return ECBOR_ERR_CURRENTLY_NOT_SUPPORTED;
}
break;
diff --git a/src/ecbor_describe.c b/src/ecbor_describe.c
index bf1337b..1cd9917 100644
--- a/src/ecbor_describe.c
+++ b/src/ecbor_describe.c
@@ -221,6 +221,32 @@ print_ecbor_item (ecbor_item_t *item, unsigned int level, char *prefix)
}
break;
+ case ECBOR_MT_FP32:
+ {
+ float val;
+
+ rc = ecbor_get_value (item, (void *) &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[FP32] value %f\n", val);
+ }
+ break;
+
+ case ECBOR_MT_FP64:
+ {
+ double val;
+
+ rc = ecbor_get_value (item, (void *) &val);
+ if (rc != ECBOR_OK) {
+ return rc;
+ }
+
+ printf ("[FP64] value %f\n", val);
+ }
+ break;
+
default:
printf ("[UNKNOWN]\n");
break;
diff --git a/src/ecbor_internal.h b/src/ecbor_internal.h
index b783eb1..e5e4179 100644
--- a/src/ecbor_internal.h
+++ b/src/ecbor_internal.h
@@ -37,4 +37,10 @@ ecbor_uint32_from_big_endian (uint32_t value);
extern uint64_t
ecbor_uint64_from_big_endian (uint64_t value);
+extern float
+ecbor_fp32_from_big_endian (float value);
+
+extern double
+ecbor_fp64_from_big_endian (double value);
+
#endif \ No newline at end of file
diff --git a/test/runtests.sh b/test/runtests.sh
index ba49058..96de614 100755
--- a/test/runtests.sh
+++ b/test/runtests.sh
@@ -24,7 +24,7 @@ for f in files/appendix_a/*.bin; do
../bin/ecbor-describe $f > $result_file 2>/dev/null
rc=$?
- if [ ! -f $result_file ] || [ ! -f $answer_file ] || [ ! $rc -eq 0 ] || [ "$(diff $answer_file $result_file 2>/dev/null)" != "" ]; then
+ if [ ! -f $result_file ] || [ ! -f $answer_file ] || [ "$(diff $answer_file $result_file 2>/dev/null)" != "" ]; then
fail=$(($fail + 1))
status=$FAIL_MSG
else