introduce intmax_t
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index b6ab489..194f745 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -111,15 +111,15 @@
char scratch[32]; /* Enough for 64-bit integer */
uint8_t *buf = st->buf;
uint8_t *buf_end = st->buf + st->size;
- signed long value;
+ intmax_t value;
ssize_t wrote = 0;
char *p;
int ret;
if(specs && specs->field_unsigned)
- ret = asn_INTEGER2ulong(st, (unsigned long *)&value);
+ ret = asn_INTEGER2umax(st, (uintmax_t *)&value);
else
- ret = asn_INTEGER2long(st, &value);
+ ret = asn_INTEGER2imax(st, &value);
/* Simple case: the integer size is small */
if(ret == 0) {
@@ -134,7 +134,7 @@
scr = (char *)alloca(scrsize);
if(plainOrXER == 0)
ret = snprintf(scr, scrsize,
- "%ld (%s)", value, el->enum_name);
+ "%" PRIdMAX " (%s)", value, el->enum_name);
else
ret = snprintf(scr, scrsize,
"<%s/>", el->enum_name);
@@ -146,10 +146,11 @@
} else {
scrsize = sizeof(scratch);
scr = scratch;
- ret = snprintf(scr, scrsize,
- (specs && specs->field_unsigned)
- ?"%lu":"%ld", value);
- }
+ ret = snprintf(
+ scr, scrsize,
+ (specs && specs->field_unsigned) ? "%" PRIuMAX : "%" PRIdMAX,
+ value);
+ }
assert(ret > 0 && (size_t)ret < scrsize);
return (cb(scr, ret, app_key) < 0) ? -1 : ret;
} else if(plainOrXER && specs && specs->strict_enumeration) {
@@ -307,8 +308,8 @@
static enum xer_pbd_rval
INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
INTEGER_t *st = (INTEGER_t *)sptr;
- long dec_value;
- long hex_value = 0;
+ intmax_t dec_value;
+ intmax_t hex_value = 0;
const char *lp;
const char *lstart = (const char *)chunk_buf;
const char *lstop = lstart + chunk_size;
@@ -486,13 +487,13 @@
case ST_DIGITS_TRAILSPACE:
/* The last symbol encountered was a digit. */
switch(asn_strtol_lim(dec_value_start, &dec_value_end, &dec_value)) {
- case ASN_STRTOL_OK:
+ case ASN_STRTOX_OK:
break;
- case ASN_STRTOL_ERROR_RANGE:
+ case ASN_STRTOX_ERROR_RANGE:
return XPBD_DECODER_LIMIT;
- case ASN_STRTOL_ERROR_INVAL:
- case ASN_STRTOL_EXPECT_MORE:
- case ASN_STRTOL_EXTRA_DATA:
+ case ASN_STRTOX_ERROR_INVAL:
+ case ASN_STRTOX_EXPECT_MORE:
+ case ASN_STRTOX_EXTRA_DATA:
return XPBD_BROKEN_ENCODING;
}
break;
@@ -604,7 +605,7 @@
ASN__DECODE_FAILED;
if(specs && specs->field_unsigned) {
- unsigned long uvalue;
+ unsigned long uvalue = 0;
if(uper_get_constrained_whole_number(pd,
&uvalue, ct->range_bits))
ASN__DECODE_STARVED;
@@ -614,7 +615,7 @@
if(asn_ulong2INTEGER(st, uvalue))
ASN__DECODE_FAILED;
} else {
- unsigned long svalue;
+ unsigned long svalue = 0;
if(uper_get_constrained_whole_number(pd,
&svalue, ct->range_bits))
ASN__DECODE_STARVED;
@@ -632,9 +633,9 @@
/* X.691, #12.2.3, #12.2.4 */
do {
- ssize_t len;
- void *p;
- int ret;
+ ssize_t len = 0;
+ void *p = NULL;
+ int ret = 0;
/* Get the PER length */
len = uper_get_length(pd, -1, &repeat);
@@ -655,10 +656,10 @@
/*
* TODO: replace by in-place arithmetics.
*/
- long value;
+ long value = 0;
if(asn_INTEGER2long(st, &value))
ASN__DECODE_FAILED;
- if(asn_long2INTEGER(st, value + ct->lower_bound))
+ if(asn_imax2INTEGER(st, value + ct->lower_bound))
ASN__DECODE_FAILED;
}
@@ -763,10 +764,10 @@
#endif /* ASN_DISABLE_PER_SUPPORT */
int
-asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
+asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {
uint8_t *b, *end;
size_t size;
- long l;
+ intmax_t value;
/* Sanity checking */
if(!iptr || !iptr->buf || !lptr) {
@@ -779,26 +780,26 @@
size = iptr->size;
end = b + size; /* Where to stop */
- if(size > sizeof(long)) {
+ if(size > sizeof(value)) {
uint8_t *end1 = end - 1;
/*
* Slightly more advanced processing,
- * able to >sizeof(long) bytes,
- * when the actual value is small
- * (0x0000000000abcdef would yield a fine 0x00abcdef)
+ * able to process INTEGERs with >sizeof(value) bytes
+ * when the actual value is small, e.g. for intmax_t == int32_t
+ * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)
*/
/* Skip out the insignificant leading bytes */
for(; b < end1; b++) {
switch(*b) {
- case 0x00: if((b[1] & 0x80) == 0) continue; break;
- case 0xff: if((b[1] & 0x80) != 0) continue; break;
+ case 0x00: if((b[1] & 0x80) == 0) continue; break;
+ case 0xff: if((b[1] & 0x80) != 0) continue; break;
}
break;
}
size = end - b;
- if(size > sizeof(long)) {
- /* Still cannot fit the long */
+ if(size > sizeof(value)) {
+ /* Still cannot fit the sizeof(value) */
errno = ERANGE;
return -1;
}
@@ -811,21 +812,23 @@
}
/* Perform the sign initialization */
- /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */
- if((*b >> 7)) l = -1; else l = 0;
+ /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
+ if((*b >> 7)) value = -1; else value = 0;
/* Conversion engine */
- for(; b < end; b++)
- l = (l << 8) | *b;
+ for(; b < end; b++) {
+ value = (value << 8) | *b;
+ }
- *lptr = l;
+ *lptr = value;
return 0;
}
+/* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */
int
-asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *lptr) {
+asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {
uint8_t *b, *end;
- unsigned long l;
+ uintmax_t value;
size_t size;
if(!iptr || !iptr->buf || !lptr) {
@@ -838,49 +841,50 @@
end = b + size;
/* If all extra leading bytes are zeroes, ignore them */
- for(; size > sizeof(unsigned long); b++, size--) {
+ for(; size > sizeof(value); b++, size--) {
if(*b) {
- /* Value won't fit unsigned long */
+ /* Value won't fit into uintmax_t */
errno = ERANGE;
return -1;
}
}
/* Conversion engine */
- for(l = 0; b < end; b++)
- l = (l << 8) | *b;
+ for(value = 0; b < end; b++)
+ value = (value << 8) | *b;
- *lptr = l;
+ *lptr = value;
return 0;
}
int
-asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
- uint8_t *buf;
- uint8_t *end;
- uint8_t *b;
- int shr;
+asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {
+ uint8_t *buf;
+ uint8_t *end;
+ uint8_t *b;
+ int shr;
- if(value <= LONG_MAX)
- return asn_long2INTEGER(st, value);
+ if(value <= INTMAX_MAX) {
+ return asn_imax2INTEGER(st, value);
+ }
- buf = (uint8_t *)MALLOC(1 + sizeof(value));
- if(!buf) return -1;
+ buf = (uint8_t *)MALLOC(1 + sizeof(value));
+ if(!buf) return -1;
- end = buf + (sizeof(value) + 1);
- buf[0] = 0;
- for(b = buf + 1, shr = (sizeof(long)-1)*8; b < end; shr -= 8, b++)
- *b = (uint8_t)(value >> shr);
+ end = buf + (sizeof(value) + 1);
+ buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */
+ for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)
+ *b = (uint8_t)(value >> shr);
- if(st->buf) FREEMEM(st->buf);
- st->buf = buf;
- st->size = 1 + sizeof(value);
+ if(st->buf) FREEMEM(st->buf);
+ st->buf = buf;
+ st->size = 1 + sizeof(value);
return 0;
}
int
-asn_long2INTEGER(INTEGER_t *st, long value) {
+asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
uint8_t *buf, *bp;
uint8_t *p;
uint8_t *pstart;
@@ -934,44 +938,61 @@
return 0;
}
-/*
- * This function is going to be DEPRECATED soon.
- */
-enum asn_strtol_result_e
-asn_strtol(const char *str, const char *end, long *lp) {
- const char *endp = end;
-
- switch(asn_strtol_lim(str, &endp, lp)) {
- case ASN_STRTOL_ERROR_RANGE:
- return ASN_STRTOL_ERROR_RANGE;
- case ASN_STRTOL_ERROR_INVAL:
- return ASN_STRTOL_ERROR_INVAL;
- case ASN_STRTOL_EXPECT_MORE:
- return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
- case ASN_STRTOL_OK:
- return ASN_STRTOL_OK;
- case ASN_STRTOL_EXTRA_DATA:
- return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
+int
+asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
+ intmax_t v;
+ if(asn_INTEGER2imax(iptr, &v) == 0) {
+ if(v < LONG_MIN || v > LONG_MAX) {
+ errno = ERANGE;
+ return -1;
+ }
+ *l = v;
+ return 0;
+ } else {
+ return -1;
}
+}
- return ASN_STRTOL_ERROR_INVAL; /* Retain old behavior */
+int
+asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {
+ uintmax_t v;
+ if(asn_INTEGER2umax(iptr, &v) == 0) {
+ if(v > ULONG_MAX) {
+ errno = ERANGE;
+ return -1;
+ }
+ *l = v;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int
+asn_long2INTEGER(INTEGER_t *st, long value) {
+ return asn_imax2INTEGER(st, value);
+}
+
+int
+asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
+ return asn_imax2INTEGER(st, value);
}
/*
* Parse the number in the given string until the given *end position,
* returning the position after the last parsed character back using the
* same (*end) pointer.
- * WARNING: This behavior is different from the standard strtol(3).
+ * WARNING: This behavior is different from the standard strtol/strtoimax(3).
*/
-enum asn_strtol_result_e
-asn_strtol_lim(const char *str, const char **end, long *lp) {
+enum asn_strtox_result_e
+asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
int sign = 1;
- long l;
+ intmax_t value;
- const long upper_boundary = LONG_MAX / 10;
- long last_digit_max = LONG_MAX % 10;
+ const intmax_t upper_boundary = INTMAX_MAX / 10;
+ intmax_t last_digit_max = INTMAX_MAX % 10;
- if(str >= *end) return ASN_STRTOL_ERROR_INVAL;
+ if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
switch(*str) {
case '-':
@@ -982,44 +1003,71 @@
str++;
if(str >= *end) {
*end = str;
- return ASN_STRTOL_EXPECT_MORE;
+ return ASN_STRTOX_EXPECT_MORE;
}
}
- for(l = 0; str < (*end); str++) {
+ for(value = 0; str < (*end); str++) {
switch(*str) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: {
int d = *str - '0';
- if(l < upper_boundary) {
- l = l * 10 + d;
- } else if(l == upper_boundary) {
+ if(value < upper_boundary) {
+ value = value * 10 + d;
+ } else if(value == upper_boundary) {
if(d <= last_digit_max) {
if(sign > 0) {
- l = l * 10 + d;
+ value = value * 10 + d;
} else {
sign = 1;
- l = -l * 10 - d;
+ value = -value * 10 - d;
}
} else {
*end = str;
- return ASN_STRTOL_ERROR_RANGE;
+ return ASN_STRTOX_ERROR_RANGE;
}
} else {
*end = str;
- return ASN_STRTOL_ERROR_RANGE;
+ return ASN_STRTOX_ERROR_RANGE;
}
}
continue;
default:
*end = str;
- *lp = sign * l;
- return ASN_STRTOL_EXTRA_DATA;
+ *intp = sign * value;
+ return ASN_STRTOX_EXTRA_DATA;
}
}
*end = str;
- *lp = sign * l;
- return ASN_STRTOL_OK;
+ *intp = sign * value;
+ return ASN_STRTOX_OK;
+}
+
+enum asn_strtox_result_e
+asn_strtol_lim(const char *str, const char **end, long *lp) {
+ intmax_t value;
+ switch(asn_strtoimax_lim(str, end, &value)) {
+ case ASN_STRTOX_ERROR_RANGE:
+ return ASN_STRTOX_ERROR_RANGE;
+ case ASN_STRTOX_ERROR_INVAL:
+ return ASN_STRTOX_ERROR_INVAL;
+ case ASN_STRTOX_EXPECT_MORE:
+ return ASN_STRTOX_EXPECT_MORE;
+ case ASN_STRTOX_OK:
+ if(value >= LONG_MIN && value <= LONG_MAX) {
+ *lp = value;
+ return ASN_STRTOX_OK;
+ } else {
+ return ASN_STRTOX_ERROR_RANGE;
+ }
+ case ASN_STRTOX_EXTRA_DATA:
+ if(value >= LONG_MIN && value <= LONG_MAX) {
+ *lp = value;
+ return ASN_STRTOX_EXTRA_DATA;
+ } else {
+ return ASN_STRTOX_ERROR_RANGE;
+ }
+ }
}
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 9a88097..626288a 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -41,34 +41,44 @@
xer_type_encoder_f INTEGER_encode_xer;
per_type_decoder_f INTEGER_decode_uper;
per_type_encoder_f INTEGER_encode_uper;
+per_type_decoder_f INTEGER_decode_aper;
+per_type_encoder_f INTEGER_encode_aper;
/***********************************
* Some handy conversion routines. *
***********************************/
/*
+ * Natiwe size-independent conversion of native integers to/from INTEGER.
+ * (l_size) is in bytes.
* Returns 0 if it was possible to convert, -1 otherwise.
* -1/EINVAL: Mandatory argument missing
* -1/ERANGE: Value encoded is out of range for long representation
- * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()).
+ * -1/ENOMEM: Memory allocation failed (in asn_*2INTEGER()).
+ */
+int asn_INTEGER2imax(const INTEGER_t *i, intmax_t *l);
+int asn_INTEGER2umax(const INTEGER_t *i, uintmax_t *l);
+int asn_imax2INTEGER(INTEGER_t *i, intmax_t l);
+int asn_umax2INTEGER(INTEGER_t *i, uintmax_t l);
+
+/*
+ * Size-specific conversion helpers.
*/
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);
-/* A a reified version of strtol(3) with nicer error reporting. */
-enum asn_strtol_result_e {
- ASN_STRTOL_ERROR_RANGE = -3, /* Input outside of numeric range for long type */
- ASN_STRTOL_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
- ASN_STRTOL_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
- ASN_STRTOL_OK = 0, /* Conversion succeded, number ends at (*end) */
- ASN_STRTOL_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */
+/* A version of strtol/strtoimax(3) with nicer error reporting. */
+enum asn_strtox_result_e {
+ ASN_STRTOX_ERROR_RANGE = -3, /* Input outside of supported numeric range */
+ ASN_STRTOX_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
+ ASN_STRTOX_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
+ ASN_STRTOX_OK = 0, /* Conversion succeded, number ends at (*end) */
+ ASN_STRTOX_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */
};
-enum asn_strtol_result_e asn_strtol_lim(const char *str, const char **end, long *l);
-
-/* The asn_strtol is going to be DEPRECATED soon */
-enum asn_strtol_result_e asn_strtol(const char *str, const char *end, long *l);
+enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end, long *l);
+enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end, intmax_t *l);
/*
* Convert the integer value into the corresponding enumeration map entry.
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index d0f8b31..cc1a421 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -668,20 +668,20 @@
const char *endp = oid_end; \
long value; \
switch(asn_strtol_lim(oid_text, &endp, &value)) { \
- case ASN_STRTOL_EXTRA_DATA: \
- case ASN_STRTOL_OK: \
+ case ASN_STRTOX_EXTRA_DATA: \
+ case ASN_STRTOX_OK: \
if(arcs_count < arcs_slots) \
arcs[arcs_count] = value; \
arcs_count++; \
oid_text = endp - 1; \
break; \
- case ASN_STRTOL_ERROR_RANGE: \
+ case ASN_STRTOX_ERROR_RANGE: \
if(opt_oid_text_end) \
*opt_oid_text_end = oid_text; \
errno = ERANGE; \
return -1; \
- case ASN_STRTOL_ERROR_INVAL: \
- case ASN_STRTOL_EXPECT_MORE: \
+ case ASN_STRTOX_ERROR_INVAL: \
+ case ASN_STRTOX_EXPECT_MORE: \
if(opt_oid_text_end) \
*opt_oid_text_end = oid_text; \
errno = EINVAL; \