OBJECT IDENTIFIER and RELATIVE-OID API simplified
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