work in 128-bit integer values while compiling
diff --git a/libasn1parser/asn1p_integer.c b/libasn1parser/asn1p_integer.c
new file mode 100644
index 0000000..98cfe08
--- /dev/null
+++ b/libasn1parser/asn1p_integer.c
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "asn1p_integer.h"
+
+#define ASN_INTEGER_MAX    \
+    (~((asn1c_integer_t)0) \
+     & ~((asn1c_integer_t)1 << (8 * sizeof(asn1c_integer_t) - 1)))
+#define ASN_INTEGER_MIN (-(ASN_INTEGER_MAX)-1)
+
+/*
+ * 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/strtoimax(3).
+ */
+enum strtox_result_e {
+    STRTOX_ERROR_RANGE = -3, /* Input outside of supported numeric range */
+    STRTOX_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
+    STRTOX_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
+    STRTOX_OK = 0,           /* Conversion succeded, number ends at (*end) */
+    STRTOX_EXTRA_DATA =
+        1 /* Conversion succeded, but the string has extra stuff */
+};
+
+static enum strtox_result_e
+strtoaint_lim(const char *str, const char **end, asn1c_integer_t *intp) {
+	const asn1c_integer_t upper_boundary = ASN_INTEGER_MAX / 10;
+	int last_digit_max = ASN_INTEGER_MAX % 10;
+	int sign = 1;
+	asn1c_integer_t value;
+
+	if(str >= *end) return STRTOX_ERROR_INVAL;
+
+	switch(*str) {
+	case '-':
+		last_digit_max++;
+		sign = -1;
+		/* FALL THROUGH */
+	case '+':
+		str++;
+		if(str >= *end) {
+			*end = str;
+			return 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: {
+			int d = *str - '0';
+			if(value < upper_boundary) {
+				value = value * 10 + d;
+			} else if(value == upper_boundary) {
+				if(d <= last_digit_max) {
+					if(sign > 0) {
+						value = value * 10 + d;
+					} else {
+						sign = 1;
+						value = -value * 10 - d;
+					}
+				} else {
+					*end = str;
+					return STRTOX_ERROR_RANGE;
+				}
+			} else {
+				*end = str;
+				return STRTOX_ERROR_RANGE;
+			}
+		    }
+		    continue;
+		default:
+		    *end = str;
+		    *intp = sign * value;
+		    return STRTOX_EXTRA_DATA;
+		}
+	}
+
+	*end = str;
+	*intp = sign * value;
+	return STRTOX_OK;
+}
+
+int
+asn1p_atoi(const char *ptr, asn1c_integer_t *value) {
+    const char *end = ptr + strlen(ptr);
+    if(strtoaint_lim(ptr, &end, value) == STRTOX_OK) {
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+const char *asn1p_itoa(asn1c_integer_t v) {
+    static char static_buf[128];
+    int ret = asn1p_itoa_s(static_buf, sizeof(static_buf), v);
+    if(ret > 0) {
+        assert(ret < sizeof(static_buf));
+        return static_buf;
+    } else {
+        return NULL;
+    }
+}
+
+int asn1p_itoa_s(char *buf, size_t size, asn1c_integer_t v) {
+    char tmp_buf[128];
+
+    if(v >= LONG_MIN && v < LONG_MAX) {
+        int ret = snprintf(buf, size, "%ld", (long)v);
+        if(ret < 0 || ret >= size) {
+            return -1;
+        }
+        return ret;
+    }
+
+    int sign = 0;
+    if(v < 0) {
+        if(v == ASN_INTEGER_MIN) {
+            switch(sizeof(v)) {
+            case 16:
+                if(size < 41)
+                    return -1;
+                memcpy(buf, "-170141183460469231731687303715884105729", 41);
+                return 41;
+            case 8:
+                if(size < 21)
+                    return -1;
+                memcpy(buf, "-9223372036854775809", 21);
+                return 21;
+            default:
+                assert(!"unreachable");
+            }
+        }
+
+        sign = -1;
+        v = -v; /* Ditch the sign */
+    }
+
+    assert(v > 1000000000L);
+    char restbuf[10] = "000000000\0";
+    const char *rest = asn1p_itoa((long)(v % 1000000000L));
+    size_t restlen = strlen(rest);
+    assert(restlen <= 9);
+    memcpy(restbuf + (9 - restlen), rest, restlen);
+    rest = restbuf;
+
+    const char *head = asn1p_itoa(v / 1000000000L);
+    assert(head);
+    int ret = snprintf(tmp_buf, sizeof(tmp_buf), "%s%s%s", sign ? "-" : "",
+                       head, rest);
+    assert(ret > 0 && ret < sizeof(tmp_buf));
+    if(size <= ret)
+        return -1;
+    memcpy(buf, tmp_buf, ret);
+    buf[ret] = '\0';
+    return ret;
+}
+