OBJECT IDENTIFIER and RELATIVE-OID API simplified
diff --git a/ChangeLog b/ChangeLog
index f45ec83..3163516 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,7 @@
 
     NOTABLE:
     * converter-sample.c renamed into converter-example.c.
+    * OBJECT IDENTIFIER and RELATIVE-OID API simplified.
     * Added random value generation (-R option to converter-example).
     * Added LibFuzzer-based randomized tests for supported transfer syntaxes
       (DER, OER, UPER, XER) into tests/tests-randomized. See the following
diff --git a/asn1c/unber.c b/asn1c/unber.c
index 1a33b4d..b2fec49 100644
--- a/asn1c/unber.c
+++ b/asn1c/unber.c
@@ -434,7 +434,7 @@
 static int
 print_V(const char *fname, FILE *fp, ber_tlv_tag_t tlv_tag,
         ber_tlv_len_t tlv_len) {
-    asn1c_integer_t *arcs = 0; /* Object identifier arcs */
+    asn_oid_arc_t *arcs = 0; /* Object identifier arcs */
     unsigned char *vbuf = 0;
     asn1p_expr_type_e etype = 0;
     asn1c_integer_t collector = 0;
@@ -577,20 +577,19 @@
         break;
     case ASN_BASIC_OBJECT_IDENTIFIER:
         if(vbuf) {
-            OBJECT_IDENTIFIER_t oid;
-            int arcno;
+            OBJECT_IDENTIFIER_t oid = {0, 0};
+            ssize_t arcno;
 
             oid.buf = vbuf;
             oid.size = tlv_len;
 
-            arcno = OBJECT_IDENTIFIER_get_arcs(&oid, arcs, sizeof(*arcs),
-                                               tlv_len + 1);
+            arcno = OBJECT_IDENTIFIER_get_arcs(&oid, arcs, tlv_len + 1);
             if(arcno >= 0) {
                 assert(arcno <= (tlv_len + 1));
                 printf(" F>");
                 for(i = 0; i < arcno; i++) {
                     if(i) printf(".");
-                    printf("%s", asn1p_itoa(arcs[i]));
+                    printf("%" PRIu32, arcs[i]);
                 }
                 FREEMEM(vbuf);
                 vbuf = 0;
@@ -605,13 +604,13 @@
             oid.buf = vbuf;
             oid.size = tlv_len;
 
-            arcno = RELATIVE_OID_get_arcs(&oid, arcs, sizeof(*arcs), tlv_len);
+            arcno = RELATIVE_OID_get_arcs(&oid, arcs, tlv_len);
             if(arcno >= 0) {
-                assert(arcno <= (tlv_len + 1));
+                assert(arcno <= tlv_len);
                 printf(" F>");
                 for(i = 0; i < arcno; i++) {
                     if(i) printf(".");
-                    printf("%s", asn1p_itoa(arcs[i]));
+                    printf("%" PRIu32, arcs[i]);
                 }
                 FREEMEM(vbuf);
                 vbuf = 0;
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 5650368..3257cf7 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -1028,9 +1028,9 @@
 	intmax_t value;
 
 #define ASN1_INTMAX_MAX ((~(uintmax_t)0) >> 1)
-
     const intmax_t upper_boundary = ASN1_INTMAX_MAX / 10;
 	intmax_t last_digit_max = ASN1_INTMAX_MAX % 10;
+#undef  ASN1_INTMAX_MAX
 
 	if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
 
@@ -1084,6 +1084,66 @@
 	return ASN_STRTOX_OK;
 }
 
+/*
+ * 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 strtoul/strtoumax(3).
+ */
+enum asn_strtox_result_e
+asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
+	uintmax_t value;
+
+#define ASN1_UINTMAX_MAX ((~(uintmax_t)0))
+    const uintmax_t upper_boundary = ASN1_UINTMAX_MAX / 10;
+    uintmax_t last_digit_max = ASN1_UINTMAX_MAX % 10;
+#undef ASN1_UINTMAX_MAX
+
+    if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
+
+	switch(*str) {
+	case '-':
+        return ASN_STRTOX_ERROR_INVAL;
+	case '+':
+		str++;
+		if(str >= *end) {
+			*end = str;
+			return ASN_STRTOX_EXPECT_MORE;
+		}
+	}
+
+	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: {
+			unsigned int d = *str - '0';
+			if(value < upper_boundary) {
+				value = value * 10 + d;
+			} else if(value == upper_boundary) {
+				if(d <= last_digit_max) {
+                    value = value * 10 + d;
+                } else {
+					*end = str;
+					return ASN_STRTOX_ERROR_RANGE;
+				}
+			} else {
+				*end = str;
+				return ASN_STRTOX_ERROR_RANGE;
+			}
+		    }
+		    continue;
+		default:
+		    *end = str;
+		    *uintp = value;
+		    return ASN_STRTOX_EXTRA_DATA;
+		}
+	}
+
+	*end = str;
+	*uintp = value;
+	return ASN_STRTOX_OK;
+}
+
 enum asn_strtox_result_e
 asn_strtol_lim(const char *str, const char **end, long *lp) {
     intmax_t value;
@@ -1114,6 +1174,36 @@
     return ASN_STRTOX_ERROR_INVAL;
 }
 
+enum asn_strtox_result_e
+asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
+    uintmax_t value;
+    switch(asn_strtoumax_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 <= ULONG_MAX) {
+            *ulp = value;
+            return ASN_STRTOX_OK;
+        } else {
+            return ASN_STRTOX_ERROR_RANGE;
+        }
+    case ASN_STRTOX_EXTRA_DATA:
+        if(value <= ULONG_MAX) {
+            *ulp = value;
+            return ASN_STRTOX_EXTRA_DATA;
+        } else {
+            return ASN_STRTOX_ERROR_RANGE;
+        }
+    }
+
+    assert(!"Unreachable");
+    return ASN_STRTOX_ERROR_INVAL;
+}
+
 int
 INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
                      const void *bptr) {
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 70d6a3c..708d845 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -83,8 +83,14 @@
     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_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);
+enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end,
+                                        long *l);
+enum asn_strtox_result_e asn_strtoul_lim(const char *str, const char **end,
+                                         unsigned long *l);
+enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end,
+                                           intmax_t *l);
+enum asn_strtox_result_e asn_strtoumax_lim(const char *str, const char **end,
+                                           uintmax_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 86fee46..73693de 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -55,16 +55,6 @@
 	0	/* No specifics */
 };
 
-
-/*
- * Endianness check. Will be optimized out by the compiler.
- */
-static int
-little_endian() {
-    int le_check = 1;
-    return *(char *)&le_check;
-}
-
 int
 OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
 		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
@@ -88,209 +78,107 @@
 	return 0;
 }
 
-int
-OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
-	const uint8_t *arcend = arcbuf + arclen;	/* End of arc */
-	unsigned int cache = 0;	/* No more than 14 significant bits */
-	unsigned char *rvbuf = (unsigned char *)rvbufp;
-	unsigned char *rvstart = rvbuf;	/* Original start of the value buffer */
-	int inc;	/* Return value growth direction */
+static ssize_t
+OBJECT_IDENTIFIER_get_first_arcs(const uint8_t *arcbuf, size_t arcbuf_len,
+                                 asn_oid_arc_t *arc0, asn_oid_arc_t *arc1) {
+    asn_oid_arc_t value;
 
-	rvsize *= CHAR_BIT;	/* bytes to bits */
-	arclen *= 7;		/* bytes to bits */
+    ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(arcbuf, arcbuf_len, &value);
+    if(rd <= 0) return rd;
 
-	assert(add <= 0);
+    if(value >= 80) {
+        *arc0 = 2;
+        *arc1 = value - 80;
+    } else if(value >= 40) {
+        *arc0 = 1;
+        *arc1 = value - 40;
+    } else {
+        *arc0 = 0;
+        *arc1 = value;
+    }
 
-	/*
-	 * The arc has the number of bits
-	 * cannot be represented using supplied return value type.
-	 */
-	if(arclen > rvsize) {
-		if(arclen > (rvsize + CHAR_BIT)) {
-			errno = ERANGE;	/* Overflow */
-			return -1;
-		} else {
-			/*
-			 * Even if the number of bits in the arc representation
-			 * is higher than the width of supplied * return value
-			 * type, there is still possible to fit it when there
-			 * are few unused high bits in the arc value
-			 * representaion.
-			 * 
-			 * Moreover, there is a possibility that the
-			 * number could actually fit the arc space, given
-			 * that add is negative, but we don't handle
-			 * such "temporary lack of precision" situation here.
-			 * May be considered as a bug.
-			 */
-			uint8_t mask = (0xff << (7-(arclen - rvsize))) & 0x7f;
-			if((*arcbuf & mask)) {
-				errno = ERANGE;	/* Overflow */
-				return -1;
-			}
-			/* Fool the routine computing unused bits */
-			arclen -= 7;
-			cache = *arcbuf & 0x7f;
-			arcbuf++;
-		}
-	}
-	/* Faster path for common size */
-	if(rvsize == (CHAR_BIT * sizeof(unsigned long))
-        && (arcend-arcbuf) <= (ssize_t)sizeof(unsigned long)) {
-		unsigned long accum;
-		/* Gather all bits into the accumulator */
-		for(accum = cache; arcbuf < arcend; arcbuf++)
-			accum = (accum << 7) | (*arcbuf & ~0x80);
-		if(accum < (unsigned)-add
-		|| accum > ULONG_MAX-(unsigned long)(-add)) {
-			errno = ERANGE;	/* Overflow */
-			return -1;
-		}
-		*(unsigned long *)(void *)rvbuf =
-			accum - (unsigned long)(-add); /* alignment OK! */
-		return 0;
-	}
-
-	if(little_endian()) {	/* Little endian (x86) */
-		/* "Convert" to big endian */
-		rvbuf += rvsize / CHAR_BIT - 1;
-		rvstart--;
-		inc = -1;	/* Descending */
-	} else {
-		inc = +1;	/* Big endian */
-        }
-
-	{
-		int bits;	/* typically no more than 3-4 bits */
-
-		/* Clear the high unused bits */
-		for(bits = rvsize - arclen;
-			bits > CHAR_BIT;
-				rvbuf += inc, bits -= CHAR_BIT)
-				*rvbuf = 0;
-
-		/* Fill the body of a value */
-		for(; arcbuf < arcend; arcbuf++) {
-			cache = (cache << 7) | (*arcbuf & 0x7f);
-			bits += 7;
-			if(bits >= CHAR_BIT) {
-				bits -= CHAR_BIT;
-				*rvbuf = (cache >> bits);
-				rvbuf += inc;
-			}
-		}
-		if(bits) {
-			*rvbuf = cache;
-			rvbuf += inc;
-		}
-	}
-
-	if(add) {
-		for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) {
-			int v = add + *rvbuf;
-			if(v & ((unsigned)~0 << CHAR_BIT)) {
-				*rvbuf = (unsigned char)(v + (1 << CHAR_BIT));
-				add = -1;
-			} else {
-				*rvbuf = v;
-				break;
-			}
-		}
-		if(rvbuf == rvstart) {
-			/* No space to carry over */
-			errno = ERANGE;	/* Overflow */
-			return -1;
-		}
-	}
-
-	return 0;
+    return rd;
 }
 
 ssize_t
-OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
-		asn_app_consume_bytes_f *cb, void *app_key) {
-	char scratch[64];	/* Conservative estimate */
-	unsigned long accum;	/* Bits accumulator */
-	char *p;		/* Position in the scratch buffer */
+OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, size_t arcbuf_len,
+                                 asn_oid_arc_t *ret_value) {
+    const uint8_t *b = arcbuf;
+    const uint8_t *arcend = arcbuf + arcbuf_len; /* End of arc */
 
-	if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add,
-			&accum, sizeof(accum)))
-		return -1;
+    if(arcbuf == arcend) {
+        return 0;
+    } else {
+        asn_oid_arc_t accum;
+        /* Gather all bits into the accumulator */
+        for(accum = 0; b < arcend; b++) {
+            accum = (accum << 7) | (*b & ~0x80);
+            if((*b & 0x80) == 0) {
+                if(accum <= ASN_OID_ARC_MAX) {
+                    *ret_value = accum;
+                    return 1 + (b - arcbuf);
+                } else {
+                    errno = ERANGE; /* Overflow */
+                    return -1;
+                }
+            }
+        }
+        errno = EINVAL;
+        return -1;
+    }
 
-	if(accum) {
-		ssize_t len;
-
-		/* Fill the scratch buffer in reverse. */
-		p = scratch + sizeof(scratch);
-		for(; accum; accum /= 10)
-			*(--p) = (char)(accum % 10) + 0x30; /* Put a digit */
-
-		len = sizeof(scratch) - (p - scratch);
-		if(cb(p, len, app_key) < 0)
-			return -1;
-		return len;
-	} else {
-		*scratch = 0x30;
-		if(cb(scratch, 1, app_key) < 0)
-			return -1;
-		return 1;
-	}
-}
-
-int
-OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen, int add,
-		asn_app_consume_bytes_f *cb, void *app_key) {
-
-	if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0)
-		return -1;
-
-	return 0;
 }
 
 static ssize_t
-OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
-	ssize_t wrote_len = 0;
-	size_t startn;
-	int add = 0;
-	size_t i;
+OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st,
+                             asn_app_consume_bytes_f *cb, void *app_key) {
+    char scratch[32];
+    asn_oid_arc_t arc0, arc1;
+    size_t produced = 0;
+    size_t off = 0;
+    ssize_t rd;
+    int ret;
 
-	for(i = 0, startn = 0; i < st->size; i++) {
-		uint8_t b = st->buf[i];
-		if((b & 0x80))			/* Continuation expected */
-			continue;
+    rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);
+    if(rd <= 0) {
+        return -1;
+    }
 
-		if(startn == 0) {
-			/*
-			 * First two arcs are encoded through the backdoor.
-			 */
-			if(i) {
-				add = -80;
-				if(cb("2", 1, app_key) < 0) return -1;
-			} else if(b <= 39) {
-				add = 0;
-				if(cb("0", 1, app_key) < 0) return -1;
-			} else if(b < 79) {
-				add = -40;
-				if(cb("1", 1, app_key) < 0) return -1;
-			} else {
-				add = -80;
-				if(cb("2", 1, app_key) < 0) return -1;
-			}
-			wrote_len += 1;
-		}
+    ret = snprintf(scratch, sizeof(scratch), "%"PRIu32".%"PRIu32, arc0, arc1);
+    if(ret >= (ssize_t)sizeof(scratch)) {
+        return -1;
+    }
+    produced += ret;
+    if(cb(scratch, ret, app_key) < 0)
+        return -1;
 
-		if(cb(".", 1, app_key) < 0)	/* Separate arcs */
-			return -1;
+    for(off = rd; ; ) {
+        asn_oid_arc_t arc;
+        rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,
+                                              &arc);
+        if(rd < 0) {
+            return -1;
+        } else if(rd == 0) {
+            /* No more arcs. */
+            break;
+        } else {
+            off += rd;
+            assert(off <= st->size);
+            ret = snprintf(scratch, sizeof(scratch), ".%" PRIu32, arc);
+            if(ret >= (ssize_t)sizeof(scratch)) {
+                return -1;
+            }
+            produced += ret;
+            if(cb(scratch, ret, app_key) < 0) return -1;
+        }
+    }
 
-		add = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
-				i - startn + 1, add, cb, app_key);
-		if(add < 0) return -1;
-		wrote_len += 1 + add;
-		startn = i + 1;
-		add = 0;
-	}
+    if(off != st->size) {
+        ASN_DEBUG("Could not scan to the end of Object Identifier");
+        return -1;
+    }
 
-	return wrote_len;
+	return produced;
 }
 
 static enum xer_pbd_rval
@@ -298,38 +186,37 @@
 	OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr;
 	const char *chunk_end = (const char *)chunk_buf + chunk_size;
 	const char *endptr;
-	long s_arcs[10];
-	long *arcs = s_arcs;
-	int arcs_count;
-	int ret;
+	asn_oid_arc_t s_arcs[10];
+	asn_oid_arc_t *arcs = s_arcs;
+	ssize_t num_arcs;
+	ssize_t ret;
 
 	(void)td;
 
-	arcs_count = OBJECT_IDENTIFIER_parse_arcs(
-		(const char *)chunk_buf, chunk_size, arcs,
-			sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
-	if(arcs_count < 0) {
+    num_arcs = OBJECT_IDENTIFIER_parse_arcs(
+        (const char *)chunk_buf, chunk_size, arcs,
+        sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
+    if(num_arcs < 0) {
 		/* Expecting more than zero arcs */
 		return XPBD_BROKEN_ENCODING;
-	} else if(arcs_count == 0) {
+	} else if(num_arcs == 0) {
 		return XPBD_NOT_BODY_IGNORE;
 	}
 	assert(endptr == chunk_end);
 
-	if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
-		arcs = (long *)MALLOC(arcs_count * sizeof(long));
+	if((size_t)num_arcs > sizeof(s_arcs)/sizeof(s_arcs[0])) {
+		arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(asn_oid_arc_t));
 		if(!arcs) return XPBD_SYSTEM_FAILURE;
-		ret = OBJECT_IDENTIFIER_parse_arcs(
-			(const char *)chunk_buf, chunk_size,
-			arcs, arcs_count, &endptr);
-		if(ret != arcs_count)
+        ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
+                                           arcs, num_arcs, &endptr);
+        if(ret != num_arcs)
 			return XPBD_SYSTEM_FAILURE;	/* assert?.. */
 	}
 
 	/*
 	 * Convert arcs into BER representation.
 	 */
-	ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
+	ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, num_arcs);
 	if(arcs != s_arcs) FREEMEM(arcs);
 
 	return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
@@ -352,16 +239,17 @@
 	const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
 	asn_enc_rval_t er;
 
-	(void)ilevel;
-	(void)flags;
+    (void)ilevel;
+    (void)flags;
 
-	if(!st || !st->buf)
-		ASN__ENCODE_FAILED;
+    if(!st || !st->buf) {
+        ASN__ENCODE_FAILED;
+    }
 
-	er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
-	if(er.encoded < 0) ASN__ENCODE_FAILED;
+    er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key);
+    if(er.encoded < 0) ASN__ENCODE_FAILED;
 
-	ASN__ENCODED_OK(er);
+    ASN__ENCODED_OK(er);
 }
 
 int
@@ -379,293 +267,201 @@
 	if(cb("{ ", 2, app_key) < 0)
 		return -1;
 
-	if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0)
-		return -1;
+    if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) {
+        return -1;
+    }
 
-	return (cb(" }", 2, app_key) < 0) ? -1 : 0;
+    return (cb(" }", 2, app_key) < 0) ? -1 : 0;
 }
 
-int
-OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid, void *arcs,
-		unsigned int arc_type_size, unsigned int arc_slots) {
-	void *arcs_end = (char *)arcs + (arc_type_size * arc_slots);
-	int num_arcs = 0;
-	int startn = 0;
-	int add = 0;
-	size_t i;
+ssize_t
+OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *st, asn_oid_arc_t *arcs,
+                           size_t arc_slots) {
+    asn_oid_arc_t arc0, arc1;
+    size_t num_arcs = 0;
+    size_t off;
+    ssize_t rd;
 
-	if(!oid || !oid->buf || (arc_slots && arc_type_size <= 1)) {
-		errno = EINVAL;
-		return -1;
-	}
+    if(!st || !st->buf) {
+        errno = EINVAL;
+        return -1;
+    }
 
-	for(i = 0; i < oid->size; i++) {
-		uint8_t b = oid->buf[i];
-		if((b & 0x80))			/* Continuation expected */
-			continue;
+    rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);
+    if(rd <= 0) {
+        return -1;
+    }
+    num_arcs = 2;
+    switch(arc_slots) {
+    default:
+    case 2:
+        arcs[1] = arc1;
+        /* Fall through */
+    case 1:
+        arcs[0] = arc0;
+        /* Fall through */
+    case 0:
+        break;
+    }
 
-		if(num_arcs == 0) {
-			/*
-			 * First two arcs are encoded through the backdoor.
-			 */
-			int first_arc;
-			num_arcs++;
-			if(!arc_slots) { num_arcs++; continue; }
+    for(off = rd; ; ) {
+        asn_oid_arc_t arc;
+        rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,
+                                              &arc);
+        if(rd < 0) {
+            return -1;
+        } else if(rd == 0) {
+            /* No more arcs. */
+            break;
+        } else {
+            off += rd;
+            if(num_arcs < arc_slots) {
+                arcs[num_arcs] = arc;
+            }
+            num_arcs++;
+        }
+    }
 
-			if(i) first_arc = 2;
-			else if(b <= 39) first_arc = 0;
-			else if(b < 79)	first_arc = 1;
-			else first_arc = 2;
+    if(off != st->size) {
+        return -1;
+    }
 
-			add = -40 * first_arc;
-			memset(arcs, 0, arc_type_size);
-			*(unsigned char *)((char *)arcs
-				+ (little_endian()?0:(arc_type_size - 1)))
-					= first_arc;
-			arcs = ((char *)arcs) + arc_type_size;
-		}
-
-		/* Decode, if has space */
-		if(arcs < arcs_end) {
-			if(OBJECT_IDENTIFIER_get_single_arc(&oid->buf[startn],
-				i - startn + 1, add,
-					arcs, arc_type_size)) {
-				return -1;
-                        }
-			startn = i + 1;
-			arcs = ((char *)arcs) + arc_type_size;
-			add = 0;
-		}
-		num_arcs++;
-	}
-
-	return num_arcs;
+    return num_arcs;
 }
 
 
 /*
  * Save the single value as an object identifier arc.
  */
-int
-OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned int arcval_size, int prepared_order) {
-	/*
+ssize_t
+OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len,
+                                 asn_oid_arc_t value) {
+    /*
 	 * The following conditions must hold:
-	 * assert(arcval);
-	 * assert(arcval_size > 0);
-	 * assert(arcval_size <= 16);
 	 * assert(arcbuf);
 	 */
-	const uint8_t *tend, *tp;
-	unsigned int cache;
-	uint8_t *bp = arcbuf;
-	int bits;
-	uint8_t buffer[16];
+    uint8_t scratch[((sizeof(value) * CHAR_BIT + 6) / 7)];
+    uint8_t *scratch_end = &scratch[sizeof(scratch)-1];
+    uint8_t *b;
+    size_t result_len;
+    uint8_t mask;
 
-	if(little_endian() && !prepared_order) {
-		const uint8_t *a = (const unsigned char *)arcval + arcval_size - 1;
-		const uint8_t *aend = (const uint8_t *)arcval;
-		uint8_t *msb = buffer + arcval_size - 1;
-		uint8_t *tb;
-		for(tb = buffer; a >= aend; tb++, a--)
-			if((*tb = *a) && (tb < msb))
-				msb = tb;
-		tend = &buffer[arcval_size];
-		tp = msb;	/* Most significant non-zero byte */
-	} else {
-		/* Look for most significant non-zero byte */
-		tend = (const unsigned char *)arcval + arcval_size;
-		for(tp = (const uint8_t *)arcval; tp < tend - 1; tp++)
-			if(*tp) break;
-	}
+    for(b = scratch_end, mask = 0; ; mask = 0x80, b--) {
+        *b = mask | (value & 0x7f);
+        value >>= 7;
+        if(!value) {
+            break;
+        }
+    }
 
-	/*
-	 * Split the value in 7-bits chunks.
-	 */
-	bits = ((tend - tp) * CHAR_BIT) % 7;
-	if(bits) {
-		cache = *tp >> (CHAR_BIT - bits);
-		if(cache) {
-			*bp++ = cache | 0x80;
-			cache = *tp++;
-			bits = CHAR_BIT - bits;
-		} else {
-			bits = -bits;
-		}
-	} else {
-		cache = 0;
-	}
-	for(; tp < tend; tp++) {
-		cache = (cache << CHAR_BIT) + *tp;
-		bits += CHAR_BIT;
-		while(bits >= 7) {
-			bits -= 7;
-			*bp++ = 0x80 | (cache >> bits);
-		}
-	}
-	if(bits) *bp++ = cache;
-	bp[-1] &= 0x7f;	/* Clear the last bit */
+    result_len = (scratch_end - b) + 1;
 
-	return bp - arcbuf;
+    if(result_len > arcbuf_len) {
+        return -1;
+    }
+
+    memcpy(arcbuf, b, result_len);
+
+	return result_len;
 }
 
 int
-OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
-	uint8_t *buf;
-	uint8_t *bp;
-	unsigned int arc0;
-	unsigned int arc1;
-	unsigned size;
-	unsigned i;
+OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *st, const asn_oid_arc_t *arcs,
+                           size_t arc_slots) {
+    uint8_t *buf;
+    uint8_t *bp;
+    size_t wrote;
+    asn_oid_arc_t arc0;
+    asn_oid_arc_t arc1;
+    size_t size;
+    size_t i;
 
-	if(!oid || !arcs || arc_type_size < 1
-	|| arc_type_size > 16
-	|| arc_slots < 2) {
-		errno = EINVAL;
+    if(!st || !arcs || arc_slots < 2) {
+        errno = EINVAL;
 		return -1;
 	}
 
-	switch(arc_type_size) {
-	case sizeof(char):
-		arc0 = ((const unsigned char *)arcs)[0];
-		arc1 = ((const unsigned char *)arcs)[1];
-		break;
-	case sizeof(short):
-		arc0 = ((const unsigned short *)arcs)[0];
-		arc1 = ((const unsigned short *)arcs)[1];
-		break;
-	case sizeof(int):
-		arc0 = ((const unsigned int *)arcs)[0];
-		arc1 = ((const unsigned int *)arcs)[1];
-		break;
-	default:
-		arc1 = arc0 = 0;
-		if(little_endian()) {	/* Little endian (x86) */
-			const unsigned char *ps, *pe;
-			/* If more significant bytes are present,
-			 * make them > 255 quick */
-			for(ps = (const unsigned char *)arcs + 1, pe = ps+arc_type_size;
-					ps < pe; ps++)
-				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
-			arc0 <<= CHAR_BIT, arc1 <<= CHAR_BIT;
-			arc0 = *((const unsigned char *)arcs + 0);
-			arc1 = *((const unsigned char *)arcs + arc_type_size);
-		} else {
-			const unsigned char *ps, *pe;
-			/* If more significant bytes are present,
-			 * make them > 255 quick */
-			for(ps = (const unsigned char *)arcs, pe = ps+arc_type_size - 1; ps < pe; ps++)
-				arc0 |= *ps, arc1 |= *(ps + arc_type_size);
-			arc0 = *((const unsigned char *)arcs + arc_type_size - 1);
-			arc1 = *((const unsigned char *)arcs +(arc_type_size<< 1)-1);
-		}
-	}
+    arc0 = arcs[0];
+    arc1 = arcs[1];
 
-	/*
-	 * The previous chapter left us with the first and the second arcs.
-	 * The values are not precise (that is, they are valid only if
-	 * they're less than 255), but OK for the purposes of making
-	 * the sanity test below.
-	 */
 	if(arc0 <= 1) {
-		if(arc1 >= 39) {
+		if(arc1 >= 40) {
 			/* 8.19.4: At most 39 subsequent values (including 0) */
 			errno = ERANGE;
 			return -1;
 		}
-	} else if(arc0 > 2) {
-		/* 8.19.4: Only three values are allocated from the root node */
-		errno = ERANGE;
-		return -1;
-	}
-	/*
+    } else if(arc0 == 2) {
+        if(arc1 > ASN_OID_ARC_MAX - 80) {
+            errno = ERANGE;
+            return -1;
+        }
+    } else if(arc0 > 2) {
+        /* 8.19.4: Only three values are allocated from the root node */
+        errno = ERANGE;
+        return -1;
+    }
+
+    /*
 	 * After above tests it is known that the value of arc0 is completely
 	 * trustworthy (0..2). However, the arc1's value is still meaningless.
 	 */
 
-	/*
-	 * Roughly estimate the maximum size necessary to encode these arcs.
-	 * This estimation implicitly takes in account the following facts,
-	 * that cancel each other:
-	 * 	* the first two arcs are encoded in a single value.
-	 * 	* the first value may require more space (+1 byte)
-	 * 	* the value of the first arc which is in range (0..2)
-	 */
-	size = ((arc_type_size * CHAR_BIT + 6) / 7) * arc_slots;
-	bp = buf = (uint8_t *)MALLOC(size + 1);
-	if(!buf) {
-		/* ENOMEM */
-		return -1;
-	}
+    /*
+     * Roughly estimate the maximum size necessary to encode these arcs.
+     * This estimation implicitly takes in account the following facts,
+     * that cancel each other:
+     * 	* the first two arcs are encoded in a single value.
+     * 	* the first value may require more space (+1 byte)
+     * 	* the value of the first arc which is in range (0..2)
+     */
+    size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arc_slots;
+    bp = buf = (uint8_t *)MALLOC(size + 1);
+    if(!buf) {
+        /* ENOMEM */
+        return -1;
+    }
 
-	/*
-	 * Encode the first two arcs.
-	 * These require special treatment.
-	 */
-	{
-		uint8_t *tp;
-		uint8_t first_value[1 + 16];	/* of two arcs */
-		uint8_t *fv = first_value;
+    wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arc0 * 40 + arc1);
+    if(wrote <= 0) {
+        FREEMEM(buf);
+        return -1;
+    }
+    assert(wrote <= size);
+    bp += wrote;
+    size -= wrote;
 
-		/*
-		 * Simulate first_value = arc0 * 40 + arc1;
-		 */
-		/* Copy the second (1'st) arcs[1] into the first_value */
-		*fv++ = 0;
-		arcs = ((const char *)arcs) + arc_type_size;
-		if(little_endian()) {
-			const uint8_t *aend = (const unsigned char *)arcs - 1;
-			const uint8_t *a1 = (const unsigned char *)arcs + arc_type_size - 1;
-			for(; a1 > aend; fv++, a1--) *fv = *a1;
-		} else {
-			const uint8_t *a1 = (const uint8_t *)arcs;
-			const uint8_t *aend = a1 + arc_type_size;
-			for(; a1 < aend; fv++, a1++) *fv = *a1;
-		}
-		/* Increase the first_value by arc0 */
-		arc0 *= 40;	/* (0..80) */
-		for(tp = first_value + arc_type_size; tp >= first_value; tp--) {
-			unsigned int v = *tp;
-			v += arc0;
-			*tp = v;
-			if(v >= (1 << CHAR_BIT)) arc0 = v >> CHAR_BIT;
-			else break;
-		}
+    for(i = 2; i < arc_slots; i++) {
+		wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
+        if(wrote <= 0) {
+            FREEMEM(buf);
+            return -1;
+        }
+        assert(wrote <= size);
+        bp += wrote;
+        size -= wrote;
+        assert(wrote <= size);
+    }
 
-		assert(tp >= first_value);
+    assert(size >= 0);
 
-		bp += OBJECT_IDENTIFIER_set_single_arc(bp, first_value,
-			fv - first_value, 1);
- 	}
-
-	/*
-	 * Save the rest of arcs.
-	 */
-	for(arcs = ((const char *)arcs) + arc_type_size, i = 2;
-		i < arc_slots;
-			i++, arcs = ((const char *)arcs) + arc_type_size) {
-		bp += OBJECT_IDENTIFIER_set_single_arc(bp,
-			arcs, arc_type_size, 0);
-	}
-
-	assert((unsigned)(bp - buf) <= size);
-
-	/*
+    /*
 	 * Replace buffer.
 	 */
-	oid->size = bp - buf;
-	bp = oid->buf;
-	oid->buf = buf;
+	st->size = bp - buf;
+	bp = st->buf;
+	st->buf = buf;
+	st->buf[st->size] = '\0';
 	if(bp) FREEMEM(bp);
 
 	return 0;
 }
 
-
-int
+ssize_t
 OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
-	long *arcs, unsigned int arcs_slots, const char **opt_oid_text_end) {
-	unsigned int arcs_count = 0;
-	const char *oid_end;
+                             asn_oid_arc_t *arcs, size_t arcs_count,
+                             const char **opt_oid_text_end) {
+    size_t num_arcs = 0;
+    const char *oid_end;
 	enum {
 		ST_LEADSPACE,
 		ST_TAILSPACE,
@@ -673,7 +469,7 @@
 		ST_WAITDIGITS 	/* Next character is expected to be a digit */
 	} state = ST_LEADSPACE;
 
-	if(!oid_text || oid_txt_length < -1 || (arcs_slots && !arcs)) {
+	if(!oid_text || oid_txt_length < -1 || (arcs_count && !arcs)) {
 		if(opt_oid_text_end) *opt_oid_text_end = oid_text;
 		errno = EINVAL;
 		return -1;
@@ -682,32 +478,33 @@
 	if(oid_txt_length == -1)
 		oid_txt_length = strlen(oid_text);
 
-#define	_OID_CAPTURE_ARC(oid_text, oid_end)		do {	\
-	const char *endp = oid_end;				\
-	long value;						\
-	switch(asn_strtol_lim(oid_text, &endp, &value)) {	\
-	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_STRTOX_ERROR_RANGE:				\
-		if(opt_oid_text_end)				\
-			*opt_oid_text_end = oid_text;		\
-		errno = ERANGE;					\
-		return -1;					\
-	case ASN_STRTOX_ERROR_INVAL:				\
-	case ASN_STRTOX_EXPECT_MORE:				\
-		if(opt_oid_text_end)				\
-			*opt_oid_text_end = oid_text;		\
-		errno = EINVAL;					\
-		return -1;					\
-	}							\
-  } while(0)
+#define _OID_CAPTURE_ARC(oid_text, oid_end)                       \
+    do {                                                          \
+        const char *endp = oid_end;                               \
+        unsigned long value;                                      \
+        switch(asn_strtoul_lim(oid_text, &endp, &value)) {        \
+        case ASN_STRTOX_EXTRA_DATA:                               \
+        case ASN_STRTOX_OK:                                       \
+            if(value <= ASN_OID_ARC_MAX) {                        \
+                if(num_arcs < arcs_count) arcs[num_arcs] = value; \
+                num_arcs++;                                       \
+                oid_text = endp - 1;                              \
+                break;                                            \
+            }                                                     \
+            /* Fall through */                                    \
+        case ASN_STRTOX_ERROR_RANGE:                              \
+            if(opt_oid_text_end) *opt_oid_text_end = oid_text;    \
+            errno = ERANGE;                                       \
+            return -1;                                            \
+        case ASN_STRTOX_ERROR_INVAL:                              \
+        case ASN_STRTOX_EXPECT_MORE:                              \
+            if(opt_oid_text_end) *opt_oid_text_end = oid_text;    \
+            errno = EINVAL;                                       \
+            return -1;                                            \
+        }                                                         \
+    } while(0)
 
-	for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
+    for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
 	    switch(*oid_text) {
 	    case 0x09: case 0x0a: case 0x0d: case 0x20:	/* whitespace */
 		switch(state) {
@@ -772,7 +569,7 @@
 		return -1;
 	case ST_AFTERVALUE:
 	case ST_TAILSPACE:
-		return arcs_count;
+		return num_arcs;
 	}
 
 	errno = EINVAL;	/* Broken OID */
@@ -783,9 +580,9 @@
  * Generate values from the list of interesting values, or just a random
  * value up to the upper limit.
  */
-static uint32_t
-OBJECT_IDENTIFIER__biased_random_arc(uint32_t upper_bound) {
-    static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
+static asn_oid_arc_t
+OBJECT_IDENTIFIER__biased_random_arc(asn_oid_arc_t upper_bound) {
+    const asn_oid_arc_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
     size_t idx;
 
     switch(asn_random_between(0, 2)) {
@@ -811,7 +608,7 @@
     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
     OBJECT_IDENTIFIER_t *st;
-    uint32_t arcs[5];
+    asn_oid_arc_t arcs[5];
     size_t arcs_len = asn_random_between(2, 5);
     size_t i;
 
@@ -826,13 +623,13 @@
     }
 
     arcs[0] = asn_random_between(0, 2);
-    arcs[1] =
-        OBJECT_IDENTIFIER__biased_random_arc(arcs[0] <= 1 ? 39 : UINT_MAX);
+    arcs[1] = OBJECT_IDENTIFIER__biased_random_arc(
+        arcs[0] <= 1 ? 39 : (ASN_OID_ARC_MAX - 80));
     for(i = 2; i < arcs_len; i++) {
-        arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(UINT_MAX);
+        arcs[i] = OBJECT_IDENTIFIER__biased_random_arc(ASN_OID_ARC_MAX);
     }
 
-    if(OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) {
+    if(OBJECT_IDENTIFIER_set_arcs(st, arcs, arcs_len)) {
         if(st != *sptr) {
             ASN_STRUCT_FREE(*td, st);
         }
@@ -841,5 +638,6 @@
 
     *sptr = st;
 
+    result_ok.length = st->size;
     return result_ok;
 }
diff --git a/skeletons/OBJECT_IDENTIFIER.h b/skeletons/OBJECT_IDENTIFIER.h
index d160e43..7336285 100644
--- a/skeletons/OBJECT_IDENTIFIER.h
+++ b/skeletons/OBJECT_IDENTIFIER.h
@@ -14,6 +14,9 @@
 extern "C" {
 #endif
 
+typedef uint32_t asn_oid_arc_t;
+#define ASN_OID_ARC_MAX (~((asn_oid_arc_t)0))
+
 typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
 
 extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER;
@@ -40,50 +43,45 @@
  **********************************/
 
 /*
- * This function fills an (_arcs) array with OBJECT IDENTIFIER arcs
- * up to specified (_arc_slots) elements.
- * 
+ * This function fills an (arcs) array with OBJECT IDENTIFIER arcs
+ * up to specified (arc_slots) elements.
+ *
  * EXAMPLE:
  * 	void print_arcs(OBJECT_IDENTIFIER_t *oid) {
- * 		unsigned long fixed_arcs[10];	// Try with fixed space first
- * 		unsigned long *arcs = fixed_arcs;
- * 		int arc_type_size = sizeof(fixed_arcs[0]);	// sizeof(long)
- * 		int arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10
- * 		int count;	// Real number of arcs.
+ * 		asn_oid_arc_t fixed_arcs[10];	// Try with fixed space first
+ * 		asn_oid_arc_t *arcs = fixed_arcs;
+ * 		size_t arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10
+ * 		ssize_t count;	// Real number of arcs.
  * 		int i;
- * 
- * 		count = OBJECT_IDENTIFIER_get_arcs(oid, arcs,
- * 			arc_type_size, arc_slots);
+ *
+ * 		count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, arc_slots);
  * 		// If necessary, reallocate arcs array and try again.
  * 		if(count > arc_slots) {
  * 			arc_slots = count;
- * 			arcs = malloc(arc_type_size * arc_slots);
+ * 			arcs = malloc(sizeof(asn_oid_arc_t) * arc_slots);
  * 			if(!arcs) return;
- * 			count = OBJECT_IDENTIFIER_get_arcs(oid, arcs,
- * 				arc_type_size, arc_slots);
+ * 			count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, arc_slots);
  * 			assert(count == arc_slots);
  * 		}
- * 
+ *
  * 		// Print the contents of the arcs array.
  * 		for(i = 0; i < count; i++)
- * 			printf("%d\n", arcs[i]);
- * 
+ * 			printf("%"PRIu32"\n", arcs[i]);
+ *
  * 		// Avoid memory leak.
  * 		if(arcs != fixed_arcs) free(arcs);
  * 	}
- * 
+ *
  * RETURN VALUES:
  * -1/EINVAL:	Invalid arguments (oid is missing)
  * -1/ERANGE:	One or more arcs have value out of array cell type range.
  * >=0:		Number of arcs contained in the OBJECT IDENTIFIER
- * 
- * WARNING: The function always returns the real number of arcs,
- * even if there is no sufficient (_arc_slots) provided.
+ *
+ * WARNING: The function always returns the actual number of arcs,
+ * even if there is no sufficient (arc_slots) provided.
  */
-int OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *_oid,
-	void *_arcs,			/* e.g., unsigned int arcs[N] */
-	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0]) */
-	unsigned int _arc_slots		/* e.g., N */);
+ssize_t OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *oid,
+                                   asn_oid_arc_t *arcs, size_t arc_slots);
 
 /*
  * This functions initializes the OBJECT IDENTIFIER object with
@@ -95,25 +93,13 @@
  * -1/ENOMEM:	Memory allocation failed
  * 0:		The object was initialized with new arcs.
  */
-int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid,
-	const void *_arcs,		/* e.g., unsigned int arcs[N] */
-	unsigned int _arc_type_size,	/* e.g., sizeof(arcs[0]) */
-	unsigned int _arc_slots		/* e.g., N */);
+int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid,
+                               const asn_oid_arc_t *arcs, size_t arcs_count);
 
-/*
- * Print the specified OBJECT IDENTIFIER arc.
- */
-int OBJECT_IDENTIFIER_print_arc(const uint8_t *arcbuf, int arclen,
-	int add, /* Arbitrary offset, required to process the first two arcs */
-	asn_app_consume_bytes_f *cb, void *app_key);
-
-/* Same as above, but returns the number of written digits, instead of 0 */
-ssize_t OBJECT_IDENTIFIER__dump_arc(const uint8_t *arcbuf, int arclen, int add,
-	asn_app_consume_bytes_f *cb, void *app_key);
 
 /*
  * Parse the OBJECT IDENTIFIER textual representation ("1.3.6.1.4.1.9363").
- * No arc can exceed the (0..signed_long_max) range (typically, 0..2G if L32).
+ * No arc can exceed the (0..ASN_OID_ARC_MAX, which is the same as UINT32_MAX).
  * This function is not specific to OBJECT IDENTIFIER, it may be used to parse
  * the RELATIVE-OID data, or any other data consisting of dot-separated
  * series of numeric values.
@@ -129,20 +115,38 @@
  * >= 0:	Number of arcs contained in the OBJECT IDENTIFIER.
  * 
  * WARNING: The function always returns the real number of arcs,
- * even if there is no sufficient (_arc_slots) provided.
- * This is useful for (_arc_slots) value estimation.
+ * even if there is no sufficient (arc_slots) provided.
+ * This is useful for (arc_slots) value estimation.
  */
-int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
-	long arcs[], unsigned int arcs_slots, const char **opt_oid_text_end);
+ssize_t OBJECT_IDENTIFIER_parse_arcs(const char *oid_text,
+                                     ssize_t oid_txt_length,
+                                     asn_oid_arc_t *arcs, size_t arcs_count,
+                                     const char **opt_oid_text_end);
 
 /*
  * Internal functions.
  * Used by RELATIVE-OID implementation in particular.
  */
-int OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, unsigned int arclen,
-	signed int add, void *value, unsigned int value_size);
-int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf,
-	const void *arcval, unsigned int arcval_size, int _prepared_order);
+
+/*
+ * Retrieve a single arc of size from the (arcbuf) buffer.
+ * RETURN VALUES:
+ *  -1: Failed to retrieve the value from the (arcbuf).
+ *  >0: Number of bytes consumed from the (arcbuf), <= (arcbuf_len).
+ */
+ssize_t OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf,
+                                         size_t arcbuf_len,
+                                         asn_oid_arc_t *ret_value);
+
+/*
+ * Write the unterminated arc value into the (arcbuf) which has the size at
+ * least (arcbuf_len).
+ * RETURN VALUES:
+ *   -1: (arcbuf_len) size is not sufficient to write the value.
+ *  <n>: Number of bytes appended to the arcbuf (<= arcbuf_len).
+ */
+ssize_t OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len,
+                                         asn_oid_arc_t arc_value);
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 33bfd4a..3eb2276 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -58,31 +58,38 @@
 
 static ssize_t
 RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
-	ssize_t wrote = 0;
-	ssize_t ret;
-	size_t startn;
-	size_t i;
+    char scratch[32];
+    size_t produced = 0;
+    size_t off = 0;
 
-	for(i = 0, startn = 0; i < st->size; i++) {
-		uint8_t b = st->buf[i];
-		if((b & 0x80))			/* Continuation expected */
-			continue;
-		if(startn) {
-			/* Separate arcs */
-			if(cb(".", 1, app_key) < 0)
-				return -1;
-			wrote++;
-		}
+    for(;;) {
+        asn_oid_arc_t arc;
+        ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
+                                                      st->size - off, &arc);
+        if(rd < 0) {
+            return -1;
+        } else if(rd == 0) {
+            /* No more arcs. */
+            break;
+        } else {
+            int ret = snprintf(scratch, sizeof(scratch), "%s%" PRIu32,
+                               off ? "." : "", arc);
+            if(ret >= (ssize_t)sizeof(scratch)) {
+                return -1;
+            }
+            produced += ret;
+            off += rd;
+            assert(off <= st->size);
+            if(cb(scratch, ret, app_key) < 0) return -1;
+        }
+    }
 
-		ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
-			i - startn + 1, 0, cb, app_key);
-		if(ret < 0) return -1;
-		wrote += ret;
+    if(off != st->size) {
+        ASN_DEBUG("Could not scan to the end of Object Identifier");
+        return -1;
+    }
 
-		startn = i + 1;
-	}
-
-	return wrote;
+	return produced;
 }
 
 int
@@ -111,41 +118,41 @@
 	RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
 	const char *chunk_end = (const char *)chunk_buf + chunk_size;
 	const char *endptr;
-	long s_arcs[6];
-	long *arcs = s_arcs;
-	int arcs_count;
+	asn_oid_arc_t s_arcs[6];
+	asn_oid_arc_t *arcs = s_arcs;
+	ssize_t num_arcs;
 	int ret;
 
 	(void)td;
 
-	arcs_count = OBJECT_IDENTIFIER_parse_arcs(
-		(const char *)chunk_buf, chunk_size,
-		arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
-	if(arcs_count < 0) {
-		/* Expecting at least one arc arcs */
-		return XPBD_BROKEN_ENCODING;
-	} else if(arcs_count == 0) {
-		return XPBD_NOT_BODY_IGNORE;
-	}
-	assert(endptr == chunk_end);
+    num_arcs = OBJECT_IDENTIFIER_parse_arcs(
+        (const char *)chunk_buf, chunk_size, arcs,
+        sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
+    if(num_arcs < 0) {
+        /* Expecting at least one arc arcs */
+        return XPBD_BROKEN_ENCODING;
+    } else if(num_arcs == 0) {
+        return XPBD_NOT_BODY_IGNORE;
+    }
+    assert(endptr == chunk_end);
 
-	if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
-		arcs = (long *)MALLOC(arcs_count * sizeof(long));
-		if(!arcs) return XPBD_SYSTEM_FAILURE;
-		ret = OBJECT_IDENTIFIER_parse_arcs(
-			(const char *)chunk_buf, chunk_size,
-			arcs, arcs_count, &endptr);
-		if(ret != arcs_count)
-			return XPBD_SYSTEM_FAILURE;	/* assert?.. */
-	}
+    if((size_t)num_arcs > sizeof(s_arcs) / sizeof(s_arcs[0])) {
+        arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(arcs[0]));
+        if(!arcs) return XPBD_SYSTEM_FAILURE;
+        ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
+                                           arcs, num_arcs, &endptr);
+        if(ret != num_arcs) {
+            return XPBD_SYSTEM_FAILURE; /* assert?.. */
+        }
+    }
 
-	/*
-	 * Convert arcs into BER representation.
-	 */
-	ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
-	if(arcs != s_arcs) FREEMEM(arcs);
+    /*
+     * Convert arcs into BER representation.
+     */
+    ret = RELATIVE_OID_set_arcs(st, arcs, num_arcs);
+    if(arcs != s_arcs) FREEMEM(arcs);
 
-	return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
+    return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
 }
 
 asn_dec_rval_t
@@ -177,48 +184,51 @@
 	ASN__ENCODED_OK(er);
 }
 
-int
-RELATIVE_OID_get_arcs(const RELATIVE_OID_t *roid,
-	void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
-	void *arcs_end = (char *)arcs + (arc_slots * arc_type_size);
-	int num_arcs = 0;
-	size_t startn = 0;
-	size_t i;
+ssize_t
+RELATIVE_OID_get_arcs(const RELATIVE_OID_t *st, asn_oid_arc_t *arcs,
+                      size_t arcs_count) {
+    size_t num_arcs = 0;
+    size_t off;
 
-	if(!roid || !roid->buf) {
-		errno = EINVAL;
-		return -1;
-	}
+    if(!st || !st->buf) {
+        errno = EINVAL;
+        return -1;
+    }
 
-	for(i = 0; i < roid->size; i++) {
-		uint8_t b = roid->buf[i];
-		if((b & 0x80))			/* Continuation expected */
-			continue;
+    for(off = 0;;) {
+        asn_oid_arc_t arc;
+        ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
+                                                      st->size - off, &arc);
+        if(rd < 0) {
+            return -1;
+        } else if(rd == 0) {
+            /* No more arcs. */
+            break;
+        } else {
+            off += rd;
+            if(num_arcs < arcs_count) {
+                arcs[num_arcs] = arc;
+            }
+            num_arcs++;
+        }
+    }
 
-		if(arcs < arcs_end) {
-			if(OBJECT_IDENTIFIER_get_single_arc(
-				&roid->buf[startn],
-					i - startn + 1, 0,
-					arcs, arc_type_size))
-				return -1;
-			arcs = ((char *)arcs) + arc_type_size;
-			num_arcs++;
-		}
-
-		startn = i + 1;
-	}
+    if(off != st->size) {
+        return -1;
+    }
 
 	return num_arcs;
 }
 
 int
-RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) {
-	uint8_t *buf;
+RELATIVE_OID_set_arcs(RELATIVE_OID_t *st, const asn_oid_arc_t *arcs,
+                      size_t arcs_count) {
+    uint8_t *buf;
 	uint8_t *bp;
-	unsigned int size;
-	unsigned int i;
+    size_t size;
+	size_t i;
 
-	if(roid == NULL || arcs == NULL || arc_type_size < 1) {
+	if(!st || !arcs) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -226,8 +236,8 @@
 	/*
 	 * Roughly estimate the maximum size necessary to encode these arcs.
 	 */
-	size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots;
-	bp = buf = (uint8_t *)MALLOC(size + 1);
+    size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arcs_count;
+    bp = buf = (uint8_t *)MALLOC(size + 1);
 	if(!buf) {
 		/* ENOMEM */
 		return -1;
@@ -236,19 +246,26 @@
 	/*
 	 * Encode the arcs.
 	 */
-	for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) {
-		bp += OBJECT_IDENTIFIER_set_single_arc(bp,
-			arcs, arc_type_size, 0);
-	}
+    for(i = 0; i < arcs_count; i++) {
+        ssize_t wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
+        if(wrote <= 0) {
+            FREEMEM(buf);
+            return -1;
+        }
+        assert((size_t)wrote <= size);
+        bp += wrote;
+        size -= wrote;
+    }
 
-	assert((unsigned)(bp - buf) <= size);
+	assert(size >= 0);
 
 	/*
 	 * Replace buffer.
 	 */
-	roid->size = (int)(bp - buf);
-	bp = roid->buf;
-	roid->buf = buf;
+	st->size = bp - buf;
+	bp = st->buf;
+	st->buf = buf;
+	st->buf[st->size] = '\0';
 	if(bp) FREEMEM(bp);
 
 	return 0;
@@ -258,7 +275,7 @@
 /*
  * Generate values from the list of interesting values, or just a random value.
  */
-static uint32_t
+static asn_oid_arc_t
 RELATIVE_OID__biased_random_arc() {
     static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
 
@@ -276,15 +293,16 @@
 
 asn_random_fill_result_t
 RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
-                              const asn_encoding_constraints_t *constraints,
-                              size_t max_length) {
+                         const asn_encoding_constraints_t *constraints,
+                         size_t max_length) {
     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
     RELATIVE_OID_t *st;
     const int min_arcs = 1; /* A minimum of 1 arc is required */
-    size_t arcs_len = asn_random_between(min_arcs, 3);
-    uint32_t arcs[3];
+    asn_oid_arc_t arcs[3];
+    size_t arcs_len =
+        asn_random_between(min_arcs, sizeof(arcs) / sizeof(arcs[0]));
     size_t i;
 
     (void)constraints;
@@ -301,7 +319,7 @@
         arcs[i] = RELATIVE_OID__biased_random_arc();
     }
 
-    if(RELATIVE_OID_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) {
+    if(RELATIVE_OID_set_arcs(st, arcs, arcs_len)) {
         if(st != *sptr) {
             ASN_STRUCT_FREE(*td, st);
         }
@@ -310,5 +328,6 @@
 
     *sptr = st;
 
+    result_ok.length = st->size;
     return result_ok;
 }
diff --git a/skeletons/RELATIVE-OID.h b/skeletons/RELATIVE-OID.h
index 1eaf559..edae83d 100644
--- a/skeletons/RELATIVE-OID.h
+++ b/skeletons/RELATIVE-OID.h
@@ -37,12 +37,12 @@
  **********************************/
 
 /* See OBJECT_IDENTIFIER_get_arcs() function in OBJECT_IDENTIFIER.h */
-int RELATIVE_OID_get_arcs(const RELATIVE_OID_t *_roid,
-	void *arcs, unsigned int arc_type_size, unsigned int arc_slots);
+ssize_t RELATIVE_OID_get_arcs(const RELATIVE_OID_t *, asn_oid_arc_t *arcs,
+                              size_t arcs_count);
 
 /* See OBJECT_IDENTIFIER_set_arcs() function in OBJECT_IDENTIFIER.h */
-int RELATIVE_OID_set_arcs(RELATIVE_OID_t *_roid,
-	void *arcs, unsigned int arc_type_size, unsigned int arcs_slots);
+int RELATIVE_OID_set_arcs(RELATIVE_OID_t *, const asn_oid_arc_t *arcs,
+                          size_t arcs_count);
 
 #ifdef __cplusplus
 }
diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h
index 09093b9..e308182 100644
--- a/skeletons/asn_internal.h
+++ b/skeletons/asn_internal.h
@@ -38,7 +38,7 @@
  */
 #ifndef	ASN_DEBUG	/* If debugging code is not defined elsewhere... */
 #if	EMIT_ASN_DEBUG == 1	/* And it was asked to emit this code... */
-#ifdef	__GNUC__
+#if __STDC_VERSION__ >= 199901L
 #ifdef	ASN_THREAD_SAFE
 /* Thread safety requires sacrifice in output indentation:
  * Retain empty definition of ASN_DEBUG_INDENT_ADD. */
@@ -55,10 +55,10 @@
 		fprintf(stderr, " (%s:%d)\n",		\
 			__FILE__, __LINE__);		\
 	} while(0)
-#else	/* !__GNUC__ */
+#else	/* !C99 */
 void CC_PRINTFLIKE(1, 2) ASN_DEBUG_f(const char *fmt, ...);
 #define	ASN_DEBUG	ASN_DEBUG_f
-#endif	/* __GNUC__ */
+#endif	/* C99 */
 #else	/* EMIT_ASN_DEBUG != 1 */
 #if __STDC_VERSION__ >= 199901L
 #define ASN_DEBUG(...) do{}while(0)
diff --git a/tests/tests-skeletons/check-OIDs.c b/tests/tests-skeletons/check-OIDs.c
index 951f752..fc87841 100644
--- a/tests/tests-skeletons/check-OIDs.c
+++ b/tests/tests-skeletons/check-OIDs.c
@@ -17,7 +17,7 @@
 check_OID(int lineno, uint8_t *buf, size_t len, unsigned *ck_buf, int ck_len) {
 	OBJECT_IDENTIFIER_t *oid;
 	asn_dec_rval_t rval;
-	unsigned long arcs[10];
+	uint32_t arcs[10];
 	int alen;
 	int i;
 
@@ -41,17 +41,17 @@
 	printf("\n");
 
 	memset(arcs, 'A', sizeof(arcs));
-	alen = OBJECT_IDENTIFIER_get_arcs(oid,
-		arcs, sizeof(arcs[0]), sizeof(arcs)/sizeof(arcs[0]));
-	assert(alen > 0);
+    alen =
+        OBJECT_IDENTIFIER_get_arcs(oid, arcs, sizeof(arcs) / sizeof(arcs[0]));
+    assert(alen > 0);
 
 	printf("OBJECT_IDENTIFIER_get_arcs() => {");
 	/*
 	 * Make sure they are equivalent.
 	 */
 	for(i = 0; i < alen; i++) {
-		printf(" %lu", arcs[i]);
-		if(alen == ck_len) {
+        printf(" %" PRIu32, arcs[i]);
+        if(alen == ck_len) {
 			assert(arcs[i] == ck_buf[i]);
 		}
 	}
@@ -62,15 +62,16 @@
 }
 
 static void
-check_ROID(int lineno, uint8_t *buf, size_t len, unsigned *ck_buf, int ck_len) {
-	RELATIVE_OID_t *oid;
+check_ROID(int lineno, uint8_t *buf, size_t len, unsigned *ck_buf,
+           size_t ck_len) {
+    RELATIVE_OID_t *oid;
 	asn_dec_rval_t rval;
-	unsigned long arcs[10];
+	uint32_t arcs[10];
 	int alen;
-	int i;
+	size_t i;
 
 	printf("%03d: Checking {", lineno);
-	for(i = 0; i < (ssize_t)len; i++) { printf("%s%02x", i?" ":"", buf[i]); }
+	for(i = 0; i < len; i++) { printf("%s%02x", i?" ":"", buf[i]); }
 	printf("} against {");
 	for(i = 0; i < ck_len; i++) { printf("%s%u", i?" ":"", ck_buf[i]); }
 	printf("}\n");
@@ -89,9 +90,8 @@
 	printf("\n");
 
 	memset(arcs, 'A', sizeof(arcs));
-	alen = RELATIVE_OID_get_arcs(oid,
-		arcs, sizeof(arcs[0]), sizeof(arcs)/sizeof(arcs[0]));
-	assert(alen > 0);
+    alen = RELATIVE_OID_get_arcs(oid, arcs, sizeof(arcs) / sizeof(arcs[0]));
+    assert(alen > 0);
 	assert(alen == ck_len);
 
 	/*
@@ -99,8 +99,8 @@
 	 */
 	printf("RELATIVE_OID_get_arcs() => {");
 	for(i = 0; i < alen; i++) {
-		printf(" %lu", arcs[i]);
-		assert(arcs[i] == ck_buf[i]);
+        printf(" %" PRIu32, arcs[i]);
+        assert(arcs[i] == ck_buf[i]);
 	}
 	printf(" }\n");
 	ASN_STRUCT_FREE(asn_DEF_RELATIVE_OID, oid);
@@ -113,27 +113,25 @@
 	int cycles = 100000000;
 	double a, b, c;
 	struct timeval tv;
-	unsigned long value;
+	uint32_t value;
 	int i;
 
-	ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), 0, &value, sizeof(value));
-	assert(ret == 0);
+    ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value);
+    assert(ret == 0);
 	assert(value == 0x7040c20d);
 
 	gettimeofday(&tv, 0);
 	a = tv.tv_sec + tv.tv_usec / 1000000.0;
 	for(i = 0; i < cycles; i++) {
-		ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), 0,
-			&value, sizeof(value));
+		ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value);
 	}
 	assert(ret == 0);
 	assert(value == 0x7040c20d);
 	gettimeofday(&tv, 0);
 	b = tv.tv_sec + tv.tv_usec / 1000000.0;
 	for(i = 0; i < cycles; i++) {
-		ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), 0,
-			&value, sizeof(value));
-	}
+        ret = OBJECT_IDENTIFIER_get_single_arc(buf, sizeof(buf), &value);
+    }
 	assert(ret == 0);
 	assert(value == 0x7040c20d);
 	gettimeofday(&tv, 0);
@@ -147,55 +145,66 @@
 	return 0;
 }
 
-static void check_parse(const char *oid_txt, int retval) {
+#define CHECK_PARSE(a, b) check_parse(__LINE__, a, b)
+static void check_parse(int lineno, const char *oid_txt, int retval) {
 	int ret;
-	long l[2];
+	uint32_t arcs[2];
 	const char *p = oid_txt - 13;
 	assert(p < oid_txt);
 
-	ret = OBJECT_IDENTIFIER_parse_arcs(oid_txt, -1, l, 2, &p);
-	printf("[%s] => %d == %d\n", oid_txt, ret, retval);
+	ret = OBJECT_IDENTIFIER_parse_arcs(oid_txt, -1, arcs, 2, &p);
+	printf("%03d: [%s] => %d == %d\n", lineno, oid_txt, ret, retval);
 	assert(ret == retval);
 	assert(p >= oid_txt);
 }
 
-static void check_xer(int expect_arcs, char *xer) {
-	asn_dec_rval_t rc;
-	RELATIVE_OID_t *st = 0;
-	long arcs[10];
-	int ret;
-	int i;
+static void
+check_xer(int lineno, asn_TYPE_descriptor_t *td, ssize_t expect_arcs, char *xer,
+          const asn_oid_arc_t *expected_arcs) {
+    asn_dec_rval_t rc;
+    void *st = 0;
+    uint32_t arcs[10];
+    ssize_t got_arcs;
+    ssize_t i;
 
-	printf("[%s] => ", xer); fflush(stdout);
-	rc = asn_DEF_RELATIVE_OID.op->xer_decoder(0,
-		&asn_DEF_RELATIVE_OID, (void **)&st, "t",
-			xer, strlen(xer));
-	if(expect_arcs == -1) {
+    printf("%03d: [%s] => ", lineno, xer);
+    fflush(stdout);
+    rc = td->op->xer_decoder(0, td, (void **)&st, "t", xer, strlen(xer));
+    if(expect_arcs == -1) {
 		if(rc.code != RC_OK) {
 			printf("-1\n");
-			ASN_STRUCT_FREE(asn_DEF_RELATIVE_OID, st);
+			ASN_STRUCT_FREE(*td, st);
 			return;
 		}
 	}
 	assert(rc.code == RC_OK);
 
-	ret = RELATIVE_OID_get_arcs(st, arcs, sizeof(arcs[0]),
-			sizeof(arcs)/sizeof(arcs[0]));
-	assert(ret < 10);
+    if(td == &asn_DEF_OBJECT_IDENTIFIER) {
+        got_arcs = OBJECT_IDENTIFIER_get_arcs(st, arcs,
+                                              sizeof(arcs) / sizeof(arcs[0]));
+    } else if(td == &asn_DEF_RELATIVE_OID) {
+        got_arcs =
+            RELATIVE_OID_get_arcs(st, arcs, sizeof(arcs) / sizeof(arcs[0]));
+    } else {
+        assert(!"Unreachable");
+    }
+	assert(got_arcs < 10);
 	if(expect_arcs == -1) {
-		assert(ret == -1);
-		ASN_STRUCT_FREE(asn_DEF_RELATIVE_OID, st);
+		assert(got_arcs == -1);
+		ASN_STRUCT_FREE(*td, st);
 		return;
 	}
-	for(i = 0; i < ret; i++) {
+	for(i = 0; i < got_arcs; i++) {
 		if(i) printf(".");
-		printf("%ld", arcs[i]);
-		if(arcs[i] != i + 1) printf(" != %d\n", i + 1);
-		assert(arcs[i] == i + 1);
+        printf("%" PRIu32, arcs[i]);
+        if(arcs[i] != expected_arcs[i]) {
+            printf(" != %" PRIu32 "\n", expected_arcs[i]);
+        }
+        assert(arcs[i] == expected_arcs[i]);
 	}
-	printf(": %d == %d\n", ret, expect_arcs);
-	assert(ret == expect_arcs);
-	ASN_STRUCT_FREE(asn_DEF_RELATIVE_OID, st);
+	printf(": %zd == %zd\n", got_arcs, expect_arcs);
+	assert(got_arcs == expect_arcs);
+	ASN_STRUCT_FREE(*td, st);
 }
 
 #define CHECK_OID(n)                                            \
@@ -208,118 +217,176 @@
 static void
 check_binary_parsing() {
 
+    /* {0 0} */
+	uint8_t buf0[] = {
+		0x06,	/* OBJECT IDENTIFIER */
+		0x01,	/* Length */
+		0x00
+	};
+	uint32_t buf0_check[] = { 0, 0 };
+
     /* {joint-iso-itu-t 230 3} */
 	uint8_t buf1[] = {
 		0x06,	/* OBJECT IDENTIFIER */
 		0x03,	/* Length */
 		0x82, 0x36, 0x03
 	};
-	unsigned buf1_check[] = { 2, 230, 3 };
-
-	/* {8571 3 2} */
-	uint8_t buf2[] = {
-		0x0D,	/* RELATIVE-OID */
-		0x04,	/* Length */
-		0xC2, 0x7B, 0x03, 0x02
-	};
-	unsigned buf2_check[] = { 8571, 3, 2 };
+	uint32_t buf1_check[] = { 2, 230, 3 };
 
 	/* {joint-iso-itu-t 42 } */
-	uint8_t buf3[] = {
+	uint8_t buf2[] = {
 		0x06,	/* OBJECT IDENTIFIER */
 		0x01,	/* Length */
 		0x7A
 	};
-	unsigned buf3_check[] = { 2, 42 };
+	uint32_t buf2_check[] = { 2, 42 };
 
 	/* {joint-iso-itu-t 25957 } */
-	uint8_t buf4[] = {
+	uint8_t buf3[] = {
 		0x06,	/* OBJECT IDENTIFIER */
 		0x03,	/* Length */
 		0x81, 0x80 + 0x4B, 0x35
 	};
-	unsigned buf4_check[] = { 2, 25957 };
+	uint32_t buf3_check[] = { 2, 25957 };
 
 	/* { jounsigned-iso-itu-t 2 1 1 } */
-	uint8_t buf5[] = {
+	uint8_t buf4[] = {
 		0x06,	/* OBJECT IDENTIFIER */
 		0x03,	/* Length */
 		0x52, 0x01, 0x01
 	};
-	unsigned buf5_check[] = { 2, 2, 1, 1 };
+	uint32_t buf4_check[] = { 2, 2, 1, 1 };
 
 	/* { jounsigned-iso-itu-t 2 1 0 1 } */
-	uint8_t buf6[] = {
+	uint8_t buf5[] = {
 		0x06,	/* OBJECT IDENTIFIER */
 		0x04,	/* Length */
 		0x52, 0x01, 0x00, 0x01
 	};
-	unsigned buf6_check[] = { 2, 2, 1, 0, 1 };
+	uint32_t buf5_check[] = { 2, 2, 1, 0, 1 };
 
+    /* {0 0} */
+	uint8_t buf10[] = {
+		0x0D,	/* RELATIVE-OID */
+		0x01,	/* Length */
+		0x00
+	};
+	uint32_t buf10_check[] = { 0 };
+
+    /* {0 0} */
+	uint8_t buf11[] = {
+		0x0D,	/* RELATIVE-OID */
+		0x02,	/* Length */
+		0x00, 0x00
+	};
+	uint32_t buf11_check[] = { 0, 0 };
+
+	/* {8571 3 2} */
+	uint8_t buf12[] = {
+		0x0D,	/* RELATIVE-OID */
+		0x04,	/* Length */
+		0xC2, 0x7B, 0x03, 0x02
+	};
+	uint32_t buf12_check[] = { 8571, 3, 2 };
+
+	CHECK_OID(0);
 	CHECK_OID(1);
-	CHECK_ROID(2);
+	CHECK_OID(2);
 	CHECK_OID(3);
 	CHECK_OID(4);
 	CHECK_OID(5);
-	CHECK_OID(6);
+
+	CHECK_ROID(10);
+	CHECK_ROID(11);
+	CHECK_ROID(12);
 }
 
 static void
 check_text_parsing() {
-    check_parse("", 0);
-    check_parse(" ", 0);
-	check_parse(".", -1);
-	check_parse(" .", -1);
-	check_parse(".1", -1);
-	check_parse("1.", -1);
-	check_parse("1. ", -1);
-	check_parse(".1. ", -1);
-	check_parse(" .1. ", -1);
-	check_parse(" 1", 1);
-	check_parse(" 1.2", 2);
-	check_parse(" 1.", -1);
-	check_parse(" 1. ", -1);
-	check_parse("1. ", -1);
-	check_parse("1.2", 2);
-	check_parse("1.2 ", 2);
-	check_parse("1.2  ", 2);
-	check_parse("  1.2  ", 2);
-	check_parse("1. 2", -1);
-	check_parse("1 .2", -1);
-	check_parse(" 1 .2", -1);
-	check_parse(" 1 .2 ", -1);
-	check_parse("1 .2 ", -1);
-	check_parse("1.+1", -1);
-	check_parse("10.30.234.234", 4);
-	check_parse("10.30.234.234 ", 4);
-	check_parse("10.30.234. 234 ", -1);
-	check_parse("10.30.234.234.", -1);
-	check_parse("1.2000000000.3", 3);
-	check_parse("1.2147483647.3", 3);
-	if(sizeof(long) == 4) {
-		check_parse("1.2147483648.3", -1);	/* overflow on ILP32 */
-		check_parse("1.2147483649.3", -1);	/* overflow on ILP32 */
-		check_parse("1.3000000000.3", -1);
-		check_parse("1.4000000000.3", -1);
-		check_parse("1.5000000000.3", -1);
-		check_parse("1.6000000000.3", -1);
-		check_parse("1.9000000000.3", -1);
-	} else if(sizeof(long) == 8) {
-		check_parse("1.2147483648.3", 3);
-		check_parse("1.9223372036854775807.3", 3);
-		check_parse("1.9223372036854775808.3", -1);
-	}
-	check_parse("1.900a0000000.3", -1);
-	check_parse("1.900a.3", -1);
+    CHECK_PARSE("", 0);
+    CHECK_PARSE(" ", 0);
+	CHECK_PARSE(".", -1);
+	CHECK_PARSE(" .", -1);
+	CHECK_PARSE(".1", -1);
+	CHECK_PARSE("1.", -1);
+	CHECK_PARSE("1. ", -1);
+	CHECK_PARSE(".1. ", -1);
+	CHECK_PARSE(" .1. ", -1);
+	CHECK_PARSE(" 1", 1);
+	CHECK_PARSE(" 1.2", 2);
+	CHECK_PARSE(" 1.", -1);
+	CHECK_PARSE(" 1. ", -1);
+	CHECK_PARSE("1. ", -1);
+	CHECK_PARSE("1.2", 2);
+	CHECK_PARSE("1.2 ", 2);
+	CHECK_PARSE("1.2  ", 2);
+	CHECK_PARSE("  1.2  ", 2);
+	CHECK_PARSE("1. 2", -1);
+	CHECK_PARSE("1 .2", -1);
+	CHECK_PARSE(" 1 .2", -1);
+	CHECK_PARSE(" 1 .2 ", -1);
+	CHECK_PARSE("1 .2 ", -1);
+	CHECK_PARSE("1.+1", -1);
+	CHECK_PARSE("2.0", 2);
+	CHECK_PARSE("2.1", 2);
+	CHECK_PARSE("10.30.234.234", 4);
+	CHECK_PARSE("10.30.234.234 ", 4);
+	CHECK_PARSE("10.30.234. 234 ", -1);
+	CHECK_PARSE("10.30.234.234.", -1);
+	CHECK_PARSE("1.2000000000.3", 3);
+	CHECK_PARSE("1.2147483647.3", 3);
+    CHECK_PARSE("1.4294967295.3", 3);
+    CHECK_PARSE("1.4294967296.3", -1); /* overflow on ILP32 */
+    CHECK_PARSE("1.3000000000.3", 3);
+    CHECK_PARSE("1.4000000000.3", 3);
+    CHECK_PARSE("1.5000000000.3", -1);
+    CHECK_PARSE("1.6000000000.3", -1);
+    CHECK_PARSE("1.9000000000.3", -1);
+	CHECK_PARSE("1.900a0000000.3", -1);
+	CHECK_PARSE("1.900a.3", -1);
 }
 
+#define CHECK_XER(a, b, c, data) check_xer(__LINE__, &asn_DEF_##a, b, c, data)
+
 static void
 check_xer_parsing() {
-	check_xer(-1, "<t></t>");
-	check_xer(2, "<t>1.2</t>");
-	check_xer(3, "<t>1.2.3</t>");
-	check_xer(3, "<t> 1.2.3 </t>");
-	check_xer(-1, "<t>1.2.3 1</t>");
+    asn_oid_arc_t zero_zero[] = {0, 0};
+    asn_oid_arc_t zero_one[] = {0, 1};
+    asn_oid_arc_t one_zero[] = {1, 0};
+    asn_oid_arc_t one_one[] = {1, 1};
+    asn_oid_arc_t one_two[] = {1, 2};
+    asn_oid_arc_t two_one[] = {2, 1};
+    asn_oid_arc_t one_two_three[] = {1, 2,3};
+
+    CHECK_XER(RELATIVE_OID, -1, "<t></t>", 0);
+	CHECK_XER(RELATIVE_OID, -1, "<t>1.</t>", 0);
+    CHECK_XER(RELATIVE_OID, -1, "<t>2.1.</t>", 0);
+    CHECK_XER(RELATIVE_OID, 2, "<t>0.0</t>", zero_zero);
+    CHECK_XER(RELATIVE_OID, 2, "<t>0.1</t>", zero_one);
+    CHECK_XER(RELATIVE_OID, 2, "<t>1.0</t>", one_zero);
+    CHECK_XER(RELATIVE_OID, 2, "<t>1.2</t>", one_two);
+    CHECK_XER(RELATIVE_OID, -1, "<t>1.-2</t>", 0);
+    CHECK_XER(RELATIVE_OID, -1, "<t>1.+2</t>", 0);
+    CHECK_XER(RELATIVE_OID, 3, "<t>1.2.3</t>", one_two_three);
+    CHECK_XER(RELATIVE_OID, 3, "<t> 1.2.3 </t>", one_two_three);
+    CHECK_XER(RELATIVE_OID, -1, "<t>1.2.3 1</t>", 0);
+	CHECK_XER(RELATIVE_OID, 2, "<t>2.1</t>", two_one);
+
+	CHECK_XER(OBJECT_IDENTIFIER, -1, "<t></t>", 0);
+	CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>1</t>", 0);
+	CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>1.</t>", 0);
+	CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>2.1.</t>", 0);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t>0.0</t>", zero_zero);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t>0.1</t>", zero_one);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t>1.0</t>", one_zero);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t>1.1</t>", one_one);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t>1.2</t>", one_two);
+    CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>1.-2</t>", 0);
+    CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>1.+2</t>", 0);
+    CHECK_XER(OBJECT_IDENTIFIER, 3, "<t>1.2.3</t>", one_two_three);
+    CHECK_XER(OBJECT_IDENTIFIER, 3, "<t> 1.2.3 </t>", one_two_three);
+    CHECK_XER(OBJECT_IDENTIFIER, -1, "<t>1.2.3 1</t>", 0);
+    CHECK_XER(OBJECT_IDENTIFIER, 2, "<t> 2.1 </t>", two_one);
 }
 
 int