Skip to content
This repository has been archived by the owner on Apr 9, 2020. It is now read-only.

Commit

Permalink
Merge pull request #20 from obgm/no-floats
Browse files Browse the repository at this point in the history
Make floats optional (fixes #8, also fixes #21, #22)
  • Loading branch information
cabo committed May 8, 2015
2 parents b444590 + b32b58b commit 241bc28
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ option ( fatal_warnings "Treat build warnings as errors" ON )
option ( coveralls "Generate coveralls data" ON )
option ( coveralls_send "Send data to coveralls site" OFF )
option ( build_docs "Create docs using Doxygen" ${DOXYGEN_FOUND} )
option ( no_floats "Build without floating point support" OFF )

set ( dist_dir ${CMAKE_BINARY_DIR}/dist )
set ( prefix ${CMAKE_INSTALL_PREFIX} )
Expand Down Expand Up @@ -70,6 +71,10 @@ else ()
message ( FATAL_ERROR "unhandled compiler id: ${CMAKE_C_COMPILER_ID}" )
endif ()

if ( no_floats )
add_definitions(-DCBOR_NO_FLOAT)
endif()

if ( verbose )
set ( CMAKE_VERBOSE_MAKEFILE ON )
endif ()
Expand Down
5 changes: 4 additions & 1 deletion include/cn-cbor/cn-cbor.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ typedef enum cn_cbor_error {
/** An invalid parameter was passed to a function */
CN_CBOR_ERR_INVALID_PARAMETER,
/** Allocation failed */
CN_CBOR_ERR_OUT_OF_MEMORY
CN_CBOR_ERR_OUT_OF_MEMORY,
/** A float was encountered during parse but the library was built without
support for float types. */
CN_CBOR_ERR_FLOAT_NOT_SUPPORTED
} cn_cbor_error;

/**
Expand Down
21 changes: 20 additions & 1 deletion src/cn-cbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void cn_cbor_free(const cn_cbor* cb CBOR_CONTEXT) {
}
}

#ifndef CBOR_NO_FLOAT
static double decode_half(int half) {
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
Expand All @@ -45,6 +46,7 @@ static double decode_half(int half) {
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
}
#endif /* CBOR_NO_FLOAT */

/* Fix these if you can't do non-aligned reads */
#define ntoh8p(p) (*(unsigned char*)(p))
Expand Down Expand Up @@ -85,6 +87,7 @@ static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_par
int ai;
uint64_t val;
cn_cbor* cb = NULL;
#ifndef CBOR_NO_FLOAT
union {
float f;
uint32_t u;
Expand All @@ -93,6 +96,7 @@ static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_par
double d;
uint64_t u;
} u64;
#endif /* CBOR_NO_FLOAT */

again:
TAKE(pos, ebuf, 1, ib = ntoh8p(pos) );
Expand Down Expand Up @@ -174,16 +178,31 @@ static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_par
case VAL_TRUE: cb->type = CN_CBOR_TRUE; break;
case VAL_NIL: cb->type = CN_CBOR_NULL; break;
case VAL_UNDEF: cb->type = CN_CBOR_UNDEF; break;
case AI_2: cb->type = CN_CBOR_DOUBLE; cb->v.dbl = decode_half(val); break;
case AI_2:
#ifndef CBOR_NO_FLOAT
cb->type = CN_CBOR_DOUBLE;
cb->v.dbl = decode_half(val);
#else /* CBOR_NO_FLOAT */
CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
#endif /* CBOR_NO_FLOAT */
break;
case AI_4:
#ifndef CBOR_NO_FLOAT
cb->type = CN_CBOR_DOUBLE;
u32.u = val;
cb->v.dbl = u32.f;
#else /* CBOR_NO_FLOAT */
CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
#endif /* CBOR_NO_FLOAT */
break;
case AI_8:
#ifndef CBOR_NO_FLOAT
cb->type = CN_CBOR_DOUBLE;
u64.u = val;
cb->v.dbl = u64.d;
#else /* CBOR_NO_FLOAT */
CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
#endif /* CBOR_NO_FLOAT */
break;
default: cb->v.uint = val;
}
Expand Down
4 changes: 4 additions & 0 deletions src/cn-encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static void _write_positive(cn_write_state *ws, cn_cbor_type typ, uint64_t val)
}
}

#ifndef CBOR_NO_FLOAT
static void _write_double(cn_write_state *ws, double val)
{
float float_val = val;
Expand Down Expand Up @@ -173,6 +174,7 @@ static void _write_double(cn_write_state *ws, double val)

}
}
#endif /* CBOR_NO_FLOAT */

// TODO: make public?
typedef void (*cn_visit_func)(const cn_cbor *cb, int depth, void *context);
Expand Down Expand Up @@ -270,7 +272,9 @@ void _encoder_visitor(const cn_cbor *cb, int depth, void *context)
break;

case CN_CBOR_DOUBLE:
#ifndef CBOR_NO_FLOAT
CHECK(_write_double(ws, cb->v.dbl));
#endif /* CBOR_NO_FLOAT */
break;

case CN_CBOR_INVALID:
Expand Down
3 changes: 2 additions & 1 deletion src/cn-error.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ const char *cn_cbor_error_str[] = {
"CN_CBOR_ERR_RESERVED_AI",
"CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING",
"CN_CBOR_ERR_INVALID_PARAMETER",
"CN_CBOR_ERR_OUT_OF_MEMORY"
"CN_CBOR_ERR_OUT_OF_MEMORY",
"CN_CBOR_ERR_FLOAT_NOT_SUPPORTED"
};
38 changes: 33 additions & 5 deletions test/cbor_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CTEST(cbor, error)
ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING], "CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING");
ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_INVALID_PARAMETER], "CN_CBOR_ERR_INVALID_PARAMETER");
ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_OUT_OF_MEMORY], "CN_CBOR_ERR_OUT_OF_MEMORY");
ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_FLOAT_NOT_SUPPORTED], "CN_CBOR_ERR_FLOAT_NOT_SUPPORTED");
}

CTEST(cbor, parse)
Expand Down Expand Up @@ -92,6 +93,7 @@ CTEST(cbor, parse)
"f6", // null
"f7", // undefined
"f8ff", // simple(255)
#ifndef CBOR_NO_FLOAT
"f93c00", // 1.0
"f9bc00", // -1.0
"f903ff", // 6.097555160522461e-05
Expand All @@ -101,6 +103,7 @@ CTEST(cbor, parse)
"fa47800000", // 65536.0
"fb3ff199999999999a", // 1.1
"f97e00", // NaN
#endif /* CBOR_NO_FLOAT */
"5f42010243030405ff", // (_ h'0102', h'030405')
"7f61616161ff", // (_ "a", "a")
"9fff", // [_ ]
Expand Down Expand Up @@ -133,7 +136,7 @@ CTEST(cbor, parse)
CTEST(cbor, parse_normalize)
{
cn_cbor_errback err;
char *tests[] = {
char *basic_tests[] = {
"00", "00", // 0
"1800", "00",
"1818", "1818",
Expand All @@ -146,6 +149,8 @@ CTEST(cbor, parse_normalize)
"c600", "c600", // 6(0) (undefined tag)
"d80600", "c600",
"d9000600", "c600",
};
char *float_tests[] = {
"fb3ff0000000000000", "f93c00", // 1.0
"fbbff0000000000000", "f9bc00", // -1.0
"fb40f86a0000000000", "fa47c35000", // 100000.0
Expand All @@ -160,12 +165,12 @@ CTEST(cbor, parse_normalize)
unsigned char encoded[1024];
ssize_t enc_sz;

for (i=0; i<sizeof(tests)/sizeof(char*); ) {
ASSERT_TRUE(parse_hex(tests[i++], &b));
ASSERT_TRUE(parse_hex(tests[i++], &b2));
for (i=0; i<sizeof(basic_tests)/sizeof(char*); i+=2) {
ASSERT_TRUE(parse_hex(basic_tests[i], &b));
ASSERT_TRUE(parse_hex(basic_tests[i+1], &b2));
err.err = CN_CBOR_NO_ERROR;
cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
CTEST_LOG("%s: %s", tests[i], cn_cbor_error_str[err.err]);
CTEST_LOG("%s: %s", basic_tests[i], cn_cbor_error_str[err.err]);
ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
ASSERT_NOT_NULL(cb);

Expand All @@ -175,6 +180,27 @@ CTEST(cbor, parse_normalize)
free(b2.ptr);
cn_cbor_free(cb CONTEXT_NULL);
}

for (i=0; i<sizeof(float_tests)/sizeof(char*); i+=2) {
ASSERT_TRUE(parse_hex(float_tests[i], &b));
ASSERT_TRUE(parse_hex(float_tests[i+1], &b2));
err.err = CN_CBOR_NO_ERROR;
cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
CTEST_LOG("%s: %s", float_tests[i], cn_cbor_error_str[err.err]);
#ifndef CBOR_NO_FLOAT
ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
ASSERT_NOT_NULL(cb);
#else /* CBOR_NO_FLOAT */
ASSERT_EQUAL(err.err, CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
ASSERT_NULL(cb);
#endif /* CBOR_NO_FLOAT */

/* enc_sz = cbor_encoder_write(encoded, 0, sizeof(encoded), cb); */
/* ASSERT_DATA(b2.ptr, b2.sz, encoded, enc_sz); */
free(b.ptr);
free(b2.ptr);
cn_cbor_free(cb CONTEXT_NULL);
}
}

typedef struct _cbor_failure
Expand Down Expand Up @@ -217,6 +243,7 @@ CTEST(cbor, fail)
// Decoder loses float size information
CTEST(cbor, float)
{
#ifndef CBOR_NO_FLOAT
cn_cbor_errback err;
char *tests[] = {
"f90001", // 5.960464477539063e-08
Expand All @@ -243,6 +270,7 @@ CTEST(cbor, float)
free(b.ptr);
cn_cbor_free(cb CONTEXT_NULL);
}
#endif /* CBOR_NO_FLOAT */
}

CTEST(cbor, getset)
Expand Down
1 change: 1 addition & 0 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const char *err_name[] = {
"CN_CBOR_ERR_RESERVED_AI",
"CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING",
"CN_CBOR_ERR_OUT_OF_MEMORY",
"CN_CBOR_ERR_FLOAT_NOT_SUPPORTED",
};

static void cn_cbor_decode_test(const unsigned char *buf, int len) {
Expand Down

0 comments on commit 241bc28

Please sign in to comment.