#include #include #include #include #include /* * Decode decimal integer from 'str'; the value is written in '*v'. * Returned value is a pointer to the next non-decimal character in the * string. If there is no digit at all, or the value encoding is not * minimal (extra leading zeros), or the value does not fit in an * 'unsigned long', then NULL is returned. */ static const char * decode_decimal_pornin(const char *str, unsigned long *v) { const char *orig; unsigned long acc; orig = str; acc = 0; for (orig = str;; str ++) { int c; c = *str; if (c < '0' || c > '9') { break; } c -= '0'; if (acc > (ULONG_MAX / 10)) { return NULL; } acc *= 10; if ((unsigned long)c > (ULONG_MAX - acc)) { return NULL; } acc += (unsigned long)c; } if (str == orig || (*orig == '0' && str != (orig + 1))) { return NULL; } *v = acc; return str; } static const char * decode_decimal_solar(const char *str, unsigned long *v) { char *end; errno = 0; *v = strtoul(str, &end, 10); if (errno || str == end || end - str != strspn(str, "0123456789") || (*v == 0 && end - str != 1)) return NULL; return end; } static void test_simple(const char *str) { unsigned long vp = 1111111111U, vs = 2222222222U; const char *pp, *ps; pp = decode_decimal_pornin(str, &vp); ps = decode_decimal_solar(str, &vs); if (pp != ps || (pp && vp != vs)) printf("%s: %p != %p || %lu != %lu\n", str, pp, ps, vp, vs); } static void test_tree(const char *str, int level) { char buf[100]; test_simple(str); if (++level > 2) return; snprintf(buf, sizeof(buf), "-%s", str); test_tree(buf, level); snprintf(buf, sizeof(buf), "x%s", str); test_tree(buf, level); snprintf(buf, sizeof(buf), " %s", str); test_tree(buf, level); snprintf(buf, sizeof(buf), "\n%s", str); test_tree(buf, level); snprintf(buf, sizeof(buf), "%s%s", str, str); test_tree(buf, level); snprintf(buf, sizeof(buf), "%sx%s", str, str); test_tree(buf, level); snprintf(buf, sizeof(buf), "%s %s", str, str); test_tree(buf, level); snprintf(buf, sizeof(buf), "%s\n%s", str, str); test_tree(buf, level); } static void test(const char *str) { test_tree(str, 0); } int main(void) { test(""); test("0"); test("00"); test("12345678"); test("2147483647"); test("2147483648"); test("4294967295"); test("4294967296"); test("4294967297"); test("9999999999"); test("99999999999999999999"); test("999999999999999999999999999999"); return 0; }