mirror of https://gerrit.osmocom.org/asn1c
unsigned long support: conversion routines
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1394 59561ff5-6e30-0410-9f3c-9617f08c8826
This commit is contained in:
parent
126a4557bb
commit
b6053b4d88
|
@ -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.
|
* All rights reserved.
|
||||||
* Redistribution and modifications are permitted subject to BSD license.
|
* Redistribution and modifications are permitted subject to BSD license.
|
||||||
*/
|
*/
|
||||||
|
@ -797,6 +797,63 @@ asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
|
||||||
return 0;
|
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
|
int
|
||||||
asn_long2INTEGER(INTEGER_t *st, long value) {
|
asn_long2INTEGER(INTEGER_t *st, long value) {
|
||||||
uint8_t *buf, *bp;
|
uint8_t *buf, *bp;
|
||||||
|
|
|
@ -51,7 +51,9 @@ per_type_encoder_f INTEGER_encode_uper;
|
||||||
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
|
* -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
|
||||||
*/
|
*/
|
||||||
int asn_INTEGER2long(const INTEGER_t *i, long *l);
|
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_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.
|
* Convert the integer value into the corresponding enumeration map entry.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <stdlib.h> /* For *alloc(3) */
|
#include <stdlib.h> /* For *alloc(3) */
|
||||||
#include <string.h> /* For memcpy(3) */
|
#include <string.h> /* For memcpy(3) */
|
||||||
#include <sys/types.h> /* For size_t */
|
#include <sys/types.h> /* For size_t */
|
||||||
|
#include <limits.h> /* For LONG_MAX */
|
||||||
#include <stdarg.h> /* For va_start */
|
#include <stdarg.h> /* For va_start */
|
||||||
#include <stddef.h> /* for offsetof and ptrdiff_t */
|
#include <stddef.h> /* for offsetof and ptrdiff_t */
|
||||||
|
|
||||||
|
|
|
@ -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
|
static void
|
||||||
check_xer(int tofail, char *xmldata, long orig_value) {
|
check_xer(int tofail, char *xmldata, long orig_value) {
|
||||||
INTEGER_t *st = 0;
|
INTEGER_t *st = 0;
|
||||||
|
@ -117,6 +185,11 @@ main(int ac, char **av) {
|
||||||
uint8_t buf11[] = { 0x80, 0, 0, 0 };
|
uint8_t buf11[] = { 0x80, 0, 0, 0 };
|
||||||
uint8_t buf12[] = { 0x80, 0 };
|
uint8_t buf12[] = { 0x80, 0 };
|
||||||
uint8_t buf13[] = { 0x80 };
|
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)
|
#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(buf8, 0x7F7E7D7C, 0);
|
||||||
CHECK(buf9, 0x7F7E7D7C, 0);
|
CHECK(buf9, 0x7F7E7D7C, 0);
|
||||||
CHECK(buf10, 0x7F7E7D7C, 0);
|
CHECK(buf10, 0x7F7E7D7C, 0);
|
||||||
|
UCHECK(buf10, 0x7F7E7D7C, 0);
|
||||||
CHECK(buf11, -2147483647-1, 0); /* 0x80000000 */
|
CHECK(buf11, -2147483647-1, 0); /* 0x80000000 */
|
||||||
CHECK(buf12, -32768, 0);
|
CHECK(buf12, -32768, 0);
|
||||||
CHECK(buf13, -128, 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);
|
||||||
check_xer(-1, "<INTEGER></INTEGER>", 0);
|
check_xer(-1, "<INTEGER></INTEGER>", 0);
|
||||||
|
|
Loading…
Reference in New Issue