unsigned long support: conversion routines
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 60afa77..7fe3e84 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
+ * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin <vlm@lionet.info>.
* All rights reserved.
* Redistribution and modifications are permitted subject to BSD license.
*/
@@ -798,6 +798,63 @@
}
int
+asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
+ uint8_t *b, *end;
+ unsigned long l;
+ size_t size;
+
+ if(!iptr || !iptr->buf || !lptr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ b = iptr->buf;
+ size = iptr->size;
+ end = b + size;
+
+ /* If all extra leading bytes are zeroes, ignore them */
+ for(; size > sizeof(unsigned long); b++, size--) {
+ if(*b) {
+ /* Value won't fit unsigned long */
+ errno = ERANGE;
+ return -1;
+ }
+ }
+
+ /* Conversion engine */
+ for(l = 0; b < end; b++)
+ l = (l << 8) | *b;
+
+ *lptr = l;
+ return 0;
+}
+
+int
+asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
+ uint8_t *buf;
+ uint8_t *end;
+ uint8_t *b;
+ int shr;
+
+ if(value <= LONG_MAX)
+ return asn_long2INTEGER(st, value);
+
+ buf = (uint8_t *)MALLOC(1 + sizeof(value));
+ if(!buf) return -1;
+
+ end = buf + (sizeof(value) + 1);
+ buf[0] = 0;
+ for(b = buf, shr = (sizeof(long)-1)*8; b < end; shr -= 8)
+ *(++b) = value >> shr;
+
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = 1 + sizeof(value);
+
+ return 0;
+}
+
+int
asn_long2INTEGER(INTEGER_t *st, long value) {
uint8_t *buf, *bp;
uint8_t *p;
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 62832b1..b87c794 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -51,7 +51,9 @@
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
*/
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);
/*
* Convert the integer value into the corresponding enumeration map entry.
diff --git a/skeletons/asn_system.h b/skeletons/asn_system.h
index fe69645..193a975 100644
--- a/skeletons/asn_system.h
+++ b/skeletons/asn_system.h
@@ -17,6 +17,7 @@
#include <stdlib.h> /* For *alloc(3) */
#include <string.h> /* For memcpy(3) */
#include <sys/types.h> /* For size_t */
+#include <limits.h> /* For LONG_MAX */
#include <stdarg.h> /* For va_start */
#include <stddef.h> /* for offsetof and ptrdiff_t */
diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c
index bacb618..a299fcd 100644
--- a/skeletons/tests/check-INTEGER.c
+++ b/skeletons/tests/check-INTEGER.c
@@ -75,6 +75,74 @@
}
static void
+check_unsigned(uint8_t *buf, int size, unsigned long check_long, int check_ret) {
+ char scratch[128];
+ char verify[32];
+ INTEGER_t val;
+ uint8_t *buf_end = buf + size;
+ int ret;
+ unsigned long rlong = 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_INTEGER2ulong(&val, &rlong);
+ printf(" (%lu, %d) vs (%lu, %d)\n",
+ rlong, ret, check_long, check_ret);
+ assert(ret == check_ret);
+ printf("%lu %lu\n", rlong, check_long);
+ assert(rlong == check_long);
+
+ if(check_ret == 0) {
+ INTEGER_t val2;
+ unsigned long rlong2;
+ val2.buf = 0;
+ val2.size = 0;
+ ret = asn_ulong2INTEGER(&val2, rlong);
+ 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_INTEGER2ulong(&val, &rlong2);
+ assert(ret == 0);
+ assert(rlong == rlong2);
+ }
+
+ return 0;
+
+ 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_long);
+ assert(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_xer(int tofail, char *xmldata, long orig_value) {
INTEGER_t *st = 0;
asn_dec_rval_t rc;
@@ -117,6 +185,11 @@
uint8_t buf11[] = { 0x80, 0, 0, 0 };
uint8_t buf12[] = { 0x80, 0 };
uint8_t buf13[] = { 0x80 };
+ uint8_t buf14[] = { 0x00, 0x80, 0x00, 0x00 };
+ uint8_t buf15[] = { 0x00, 0x80, 0x00, 0x00, 0x00 };
+ uint8_t buf16[] = { 0x00, 0xff, 0xff, 0x00, 0x00 };
+
+#define UCHECK(buf, val, ret) check_unsigned(buf, sizeof(buf), val, ret)
#define CHECK(buf, val, ret) check(buf, sizeof(buf), val, ret)
@@ -130,9 +203,13 @@
CHECK(buf8, 0x7F7E7D7C, 0);
CHECK(buf9, 0x7F7E7D7C, 0);
CHECK(buf10, 0x7F7E7D7C, 0);
+ UCHECK(buf10, 0x7F7E7D7C, 0);
CHECK(buf11, -2147483647-1, 0); /* 0x80000000 */
CHECK(buf12, -32768, 0);
CHECK(buf13, -128, 0);
+ UCHECK(buf14, 0x800000, 0);
+ UCHECK(buf15, 0x80000000, 0);
+ UCHECK(buf16, 0xffff0000, 0);
check_xer(-1, "", 0);
check_xer(-1, "<INTEGER></INTEGER>", 0);