diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index f811c23c8..8ea2fffdb 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -414,6 +414,33 @@ asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) { return asn_imax2INTEGER(st, value); } +int asn_INTEGER2int64(const INTEGER_t *st, int64_t *value) { + intmax_t v; + if(asn_INTEGER2imax(st, &v) == 0) { + if(v < INT64_MIN || v > INT64_MAX) { + errno = ERANGE; + return -1; + } + *value = v; + return 0; + } else { + return -1; + } +} + +int asn_INTEGER2uint64(const INTEGER_t *st, uint64_t *value) { + uintmax_t v; + if(asn_INTEGER2umax(st, &v) == 0) { + if(v > UINT64_MAX) { + errno = ERANGE; + return -1; + } + *value = v; + return 0; + } else { + return -1; + } +} int asn_uint642INTEGER(INTEGER_t *st, uint64_t value) { diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h index aa24be18c..5fa1c7b8d 100644 --- a/skeletons/INTEGER.h +++ b/skeletons/INTEGER.h @@ -108,6 +108,8 @@ int asn_INTEGER2long(const INTEGER_t *i, long *l); int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l); int asn_long2INTEGER(INTEGER_t *i, long l); int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l); +int asn_INTEGER2int64(const INTEGER_t *i, int64_t *l); +int asn_INTEGER2uint64(const INTEGER_t *i, uint64_t *l); int asn_int642INTEGER(INTEGER_t *i, int64_t l); int asn_uint642INTEGER(INTEGER_t *i, uint64_t l); diff --git a/tests/tests-skeletons/check-INTEGER.c b/tests/tests-skeletons/check-INTEGER.c index 446ac710e..b9e2231d3 100644 --- a/tests/tests-skeletons/check-INTEGER.c +++ b/tests/tests-skeletons/check-INTEGER.c @@ -147,6 +147,136 @@ check_unsigned(uint8_t *buf, int size, unsigned long check_long, int check_ret) } } +static void +check_64(uint8_t *buf, size_t size, int64_t check_i64, int check_ret) { + char scratch[128]; + char verify[32]; + INTEGER_t val; + uint8_t *buf_end = buf + size; + int ret; + int64_t rint64 = 123; + + assert(buf); + assert(size > 0); + + val.buf = buf; + val.size = size; + + printf("Testing: ["); + for(; buf < buf_end; buf++) { + if(buf != val.buf) printf(":"); + printf("%02x", *buf); + } + printf("]: "); + + ret = asn_INTEGER2int64(&val, &rint64); + printf(" (%ld, %d) vs (%ld, %d)\n", + rint64, ret, check_i64, check_ret); + assert(ret == check_ret); + printf("%ld %ld\n", rint64, check_i64); + assert(rint64 == check_i64); + + if(check_ret == 0) { + INTEGER_t val2; + int64_t rint642; + val2.buf = 0; + val2.size = 0; + ret = asn_int642INTEGER(&val2, rint64); + assert(ret == 0); + assert(val2.buf); + assert(val2.size <= val.size); /* At least as compact */ + ret = asn_INTEGER2int64(&val, &rint642); + assert(ret == 0); + assert(rint64 == rint642); + ASN_STRUCT_RESET(asn_DEF_INTEGER, &val2); + } + + shared_scratch_start = scratch; + ret = INTEGER_print(&asn_DEF_INTEGER, &val, 0, _print2buf, scratch); + assert(shared_scratch_start < scratch + sizeof(scratch)); + assert(ret == 0); + ret = snprintf(verify, sizeof(verify), "%ld", check_i64); + assert(ret < 0 || (size_t)ret < sizeof(verify)); + ret = strcmp(scratch, verify); + printf(" [%s] vs [%s]: %d%s\n", + scratch, verify, ret, + (check_ret == -1)?" (expected to fail)":"" + ); + if(check_ret == -1) { + assert(strcmp(scratch, verify)); + } else { + assert(strcmp(scratch, verify) == 0); + } +} + +static void +check_unsigned_64(uint8_t *buf, int size, uint64_t check_u64, int check_ret) { + char scratch[128]; + char verify[32]; + INTEGER_t val; + uint8_t *buf_end = buf + size; + int ret; + uint64_t ruint64 = 123; + + assert(buf); + assert(size >= 0); + + val.buf = buf; + val.size = size; + + printf("Testing: ["); + for(; buf < buf_end; buf++) { + if(buf != val.buf) printf(":"); + printf("%02x", *buf); + } + printf("]: "); + + ret = asn_INTEGER2uint64(&val, &ruint64); + printf(" (%lu, %d) vs (%lu, %d)\n", + ruint64, ret, check_u64, check_ret); + assert(ret == check_ret); + assert(ruint64 == check_u64); + + if(check_ret == 0) { + INTEGER_t val2; + uint64_t ruint642; + val2.buf = 0; + val2.size = 0; + ret = asn_uint642INTEGER(&val2, ruint64); + assert(ret == 0); + assert(val2.buf); + if(val2.size > val.size) { + /* At least as compact */ + printf("val2.size=%d, val.size=%d\n", + (int)val2.size, (int)val.size); + assert(val2.size <= val.size); + } + ret = asn_INTEGER2uint64(&val, &ruint642); + assert(ret == 0); + assert(ruint64 == ruint642); + ASN_STRUCT_RESET(asn_DEF_INTEGER, &val2); + } + + return; + + shared_scratch_start = scratch; + ret = INTEGER_print(&asn_DEF_INTEGER, &val, 0, _print2buf, scratch); + assert(shared_scratch_start < scratch + sizeof(scratch)); + assert(ret == 0); + ret = snprintf(verify, sizeof(verify), "%lu", check_u64); + assert(ret < (int)sizeof(verify)); + ret = strcmp(scratch, verify); + printf(" [%s] vs [%s]: %d%s\n", + scratch, verify, ret, + (check_ret == -1)?" (expected to fail)":"" + ); + if(check_ret == -1) { + assert(strcmp(scratch, verify)); + } else { + assert(strcmp(scratch, verify) == 0); + } +} + static void check_xer(int lineno, int tofail, char *xmldata, long orig_value) { INTEGER_t *st = 0; @@ -353,10 +483,15 @@ main() { uint8_t buf14[] = { 0x00, 0x80, 0x00, 0x00 }; uint8_t buf15[] = { 0x00, 0x80, 0x00, 0x00, 0x00 }; uint8_t buf16[] = { 0x00, 0xff, 0xff, 0x00, 0x00 }; + uint8_t buf17[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + uint8_t buf18[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + uint8_t buf19[] = { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + uint8_t buf20[] = { 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define UCHECK(buf, val, ret) check_unsigned(buf, sizeof(buf), val, ret) - #define CHECK(buf, val, ret) check(buf, sizeof(buf), val, ret) +#define UCHECK64(buf, val, ret) check_unsigned_64(buf, sizeof(buf), val, ret) +#define CHECK64(buf, val, ret) check_64(buf, sizeof(buf), val, ret) CHECK(buf1, 1, 0); CHECK(buf2, -1, 0); @@ -376,6 +511,28 @@ main() { UCHECK(buf15, 0x80000000UL, 0); UCHECK(buf16, 0xffff0000UL, 0); + CHECK64(buf1, 1, 0); + CHECK64(buf2, -1, 0); + CHECK64(buf3, -1, 0); + CHECK64(buf4, -16, 0); + CHECK64(buf5, 257, 0); + CHECK64(buf6, 123, -1); + CHECK64(buf7, 123, -1); + CHECK64(buf8, 0x7F7E7D7C, 0); + CHECK64(buf9, 0x7F7E7D7C, 0); + CHECK64(buf10, 0x7F7E7D7C, 0); + UCHECK64(buf10, 0x7F7E7D7C, 0); + CHECK64(buf11, -2147483647-1, 0); /* 0x80000000 */ + CHECK64(buf12, -32768, 0); + CHECK64(buf13, -128, 0); + UCHECK64(buf14, 0x800000, 0); + UCHECK64(buf15, 0x80000000UL, 0); + UCHECK64(buf16, 0xffff0000UL, 0); + CHECK64(buf17, 0xffffffffffffffffLL, 0); + UCHECK64(buf18, 0xffffffffffffffffULL, 0); + CHECK64(buf19, 0x7fffffffffffffffLL, 0); + UCHECK64(buf20, 0x7fffffffffffffffULL, 0); + CHECK_XER(-1, "", 0); CHECK_XER(-1, "", 0); CHECK_XER(-1, " ", 0);