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);