diff options
| author | rimio <vasi.vilvoiu@gmail.com> | 2018-03-01 23:10:42 +0200 |
|---|---|---|
| committer | rimio <vasi.vilvoiu@gmail.com> | 2018-03-01 23:10:42 +0200 |
| commit | 3621d55cd101fa5b23e645287393deefacf43e02 (patch) | |
| tree | 8dc934e5ed5f2cdcd3f0f2fbae95f87fbab7ea8e | |
| parent | 245bce0bd3b9af5ab026f4b8453424dbc4a1faea (diff) | |
Support for fp32 and fp64
| -rw-r--r-- | include/ecbor.h | 28 | ||||
| -rw-r--r-- | src/ecbor.c | 41 | ||||
| -rw-r--r-- | src/ecbor_decoder.c | 65 | ||||
| -rw-r--r-- | src/ecbor_describe.c | 26 | ||||
| -rw-r--r-- | src/ecbor_internal.h | 6 | ||||
| -rwxr-xr-x | test/runtests.sh | 2 |
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 |
