From b6053b4d88be6356c34dc288bd06a4cbc21e322d Mon Sep 17 00:00:00 2001 From: vlm Date: Tue, 6 Nov 2007 06:23:31 +0000 Subject: unsigned long support: conversion routines git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1394 59561ff5-6e30-0410-9f3c-9617f08c8826 --- skeletons/INTEGER.c | 59 ++++++++++++++++++++++++++++++- skeletons/INTEGER.h | 2 ++ skeletons/asn_system.h | 1 + skeletons/tests/check-INTEGER.c | 77 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c index 60afa77f..7fe3e84d 100644 --- a/skeletons/INTEGER.c +++ b/skeletons/INTEGER.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * Copyright (c) 2003, 2004, 2005, 2006, 2007 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ @@ -797,6 +797,63 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) { return 0; } +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; diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h index 62832b12..b87c794c 100644 --- a/skeletons/INTEGER.h +++ b/skeletons/INTEGER.h @@ -51,7 +51,9 @@ per_type_encoder_f INTEGER_encode_uper; * -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 fe696454..193a9750 100644 --- a/skeletons/asn_system.h +++ b/skeletons/asn_system.h @@ -17,6 +17,7 @@ #include /* For *alloc(3) */ #include /* For memcpy(3) */ #include /* For size_t */ +#include /* For LONG_MAX */ #include /* For va_start */ #include /* for offsetof and ptrdiff_t */ diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c index bacb618e..a299fcd5 100644 --- a/skeletons/tests/check-INTEGER.c +++ b/skeletons/tests/check-INTEGER.c @@ -74,6 +74,74 @@ check(uint8_t *buf, int size, long check_long, int check_ret) { } } +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; @@ -117,6 +185,11 @@ main(int ac, char **av) { 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 @@ main(int ac, char **av) { 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, "", 0); -- cgit v1.2.3