diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index 720a964..357dbe9 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -1507,7 +1507,7 @@ sw buf_parse_quote (s_buf *buf, s_quote *dest)
return r;
}
-#define DEF_BUF_PARSE_S(bits) \
+#define DEF_BUF_PARSE_S(BITS, bits) \
sw buf_parse_s ## bits (s_buf *buf, s ## bits *dest) \
{ \
s_buf_save digits; \
@@ -1607,7 +1607,7 @@ sw buf_parse_quote (s_buf *buf, s_quote *dest)
assert(dest); \
buf_save_init(buf, &save); \
radix = str_length_utf8(base); \
- if (radix < 2 || radix > S ## bits ## _MAX) { \
+ if (radix < 2 || radix > S ## BITS ## _MAX) { \
buf_save_clean(buf, &save); \
assert(! "buf_parse_s" # bits "_base: invalid radix"); \
errx(1, "buf_parse_s" # bits "_base: invalid radix: %ld", \
@@ -1625,15 +1625,15 @@ sw buf_parse_quote (s_buf *buf, s_quote *dest)
digit); \
return -1; \
} \
- if (u > (u ## bits) ceiling_s ## bits (S ## bits ## _MAX, \
+ if (u > (u ## bits) ceiling_s ## bits (S ## BITS ## _MAX, \
radix)) { \
warnx("buf_parse_s" # bits "_base: *: integer overflow"); \
r = -1; \
goto restore; \
} \
u *= radix; \
- if (negative ? u > (u ## bits) -S ## bits ## _MIN - digit : \
- u > (u ## bits) (S ## bits ## _MAX - digit)) { \
+ if (negative ? u > (u ## bits) -S ## BITS ## _MIN - digit : \
+ u > (u ## bits) (S ## BITS ## _MAX - digit)) { \
warnx("buf_parse_s" # bits "_base: +: integer overflow"); \
r = -1; \
goto restore; \
@@ -1650,10 +1650,11 @@ sw buf_parse_quote (s_buf *buf, s_quote *dest)
return r; \
}
-DEF_BUF_PARSE_S(8)
-DEF_BUF_PARSE_S(16)
-DEF_BUF_PARSE_S(32)
-DEF_BUF_PARSE_S(64)
+DEF_BUF_PARSE_S(8, 8)
+DEF_BUF_PARSE_S(16, 16)
+DEF_BUF_PARSE_S(32, 32)
+DEF_BUF_PARSE_S(64, 64)
+DEF_BUF_PARSE_S(W, w)
sw buf_parse_str (s_buf *buf, s_str *dest)
{
@@ -2224,7 +2225,7 @@ sw buf_parse_tuple (s_buf *buf, s_tuple *tuple)
return r;
}
-#define DEF_BUF_PARSE_U(bits) \
+#define DEF_BUF_PARSE_U(BITS, bits) \
sw buf_parse_u ## bits (s_buf *buf, u ## bits *dest) \
{ \
s_buf_save digits; \
@@ -2314,7 +2315,7 @@ sw buf_parse_tuple (s_buf *buf, s_tuple *tuple)
assert(dest); \
buf_save_init(buf, &save); \
radix = str_length_utf8(base); \
- if (radix < 2 || (uw) radix > U ## bits ## _MAX) { \
+ if (radix < 2 || (uw) radix > U ## BITS ## _MAX) { \
buf_save_clean(buf, &save); \
assert(! "buf_parse_u" # bits "_base: invalid radix"); \
errx(1, "buf_parse_u" # bits "_base: invalid radix: %ld", \
@@ -2332,13 +2333,13 @@ sw buf_parse_tuple (s_buf *buf, s_tuple *tuple)
digit); \
return -1; \
} \
- if (u > ceiling_u ## bits (U ## bits ## _MAX, radix)) { \
+ if (u > ceiling_u ## bits (U ## BITS ## _MAX, radix)) { \
warnx("buf_parse_u" # bits "_base: *: integer overflow"); \
r = -1; \
goto restore; \
} \
u *= radix; \
- if (u > (u ## bits) (U ## bits ## _MAX - digit)) { \
+ if (u > (u ## bits) (U ## BITS ## _MAX - digit)) { \
warnx("buf_parse_u" # bits "_base: +: integer overflow"); \
r = -1; \
goto restore; \
@@ -2355,139 +2356,11 @@ sw buf_parse_tuple (s_buf *buf, s_tuple *tuple)
return r; \
}
-DEF_BUF_PARSE_U(8)
-DEF_BUF_PARSE_U(16)
-DEF_BUF_PARSE_U(32)
-DEF_BUF_PARSE_U(64)
-
-sw buf_parse_uw (s_buf *buf, uw *dest)
-{
- s_buf_save digits;
- sw r;
- sw r1;
- sw result = 0;
- s_buf_save save;
- uw tmp;
- uw tmp1;
- buf_save_init(buf, &save);
- if ((r = buf_read_1(buf, "0b")) < 0)
- goto restore;
- if (r > 0) {
- result += r;
- if ((r = buf_parse_uw_base(buf, &g_c3_base_bin,
- dest)) <= 0)
- goto restore;
- result += r;
- goto ok;
- }
- if ((r = buf_read_1(buf, "0o")) < 0)
- goto restore;
- if (r > 0) {
- result += r;
- if ((r = buf_parse_uw_base(buf, &g_c3_base_oct,
- dest)) <= 0)
- goto restore;
- result += r;
- goto ok;
- }
- if ((r = buf_read_1(buf, "0x")) < 0)
- goto restore;
- if (r > 0) {
- result += r;
- buf_save_init(buf, &digits);
- if ((r = buf_parse_uw_base(buf, g_c3_bases_hex,
- &tmp)) < 0) {
- buf_save_clean(buf, &digits);
- goto restore;
- }
- buf_save_restore_rpos(buf, &digits);
- buf_save_clean(buf, &digits);
- if ((r1 = buf_parse_uw_base(buf, g_c3_bases_hex + 1,
- &tmp1)) < 0) {
- r = r1;
- goto restore;
- }
- if (r == 0 && r1 == 0) {
- warnx("invalid number: 0x");
- goto restore;
- }
- if (r > r1) {
- result += r;
- *dest = tmp;
- }
- else {
- result += r1;
- *dest = tmp1;
- }
- goto ok;
- }
- if ((r = buf_parse_uw_base(buf, &g_c3_base_dec,
- dest)) <= 0)
- goto restore;
- result += r;
- ok:
- r = result;
- goto clean;
- restore:
- buf_save_restore_rpos(buf, &save);
- clean:
- buf_save_clean(buf, &save);
- return r;
-}
-
-sw buf_parse_uw_base (s_buf *buf, const s_str *base,
- uw *dest)
-{
- u8 digit;
- sw r;
- sw radix;
- sw result = 0;
- s_buf_save save;
- uw u = 0;
- assert(buf);
- assert(base);
- assert(dest);
- buf_save_init(buf, &save);
- radix = str_length_utf8(base);
- if (radix < 2 || (uw) radix > UW_MAX) {
- buf_save_clean(buf, &save);
- assert(! "buf_parse_uw_base: invalid radix");
- errx(1, "buf_parse_uw_base: invalid radix: %ld",
- radix);
- return -1;
- }
- while ((r = buf_parse_digit(buf, base, &digit)) > 0) {
- result += r;
- if (digit >= radix) {
- buf_save_clean(buf, &save);
- assert(! "buf_parse_uw_base: digit greater than or equal to "
- "radix");
- errx(1, "buf_parse_uw_base: digit greater than or equal to "
- "radix: %u", digit);
- return -1;
- }
- if (u > ceiling_uw(UW_MAX, radix)) {
- warnx("buf_parse_uw_base: *: integer overflow");
- r = -1;
- goto restore;
- }
- u *= radix;
- if (u > (uw) (UW_MAX - digit)) {
- warnx("buf_parse_uw_base: +: integer overflow");
- r = -1;
- goto restore;
- }
- u += digit;
- }
- *dest = u;
- r = result;
- goto clean;
- restore:
- buf_save_restore_rpos(buf, &save);
- clean:
- buf_save_clean(buf, &save);
- return r;
-}
+DEF_BUF_PARSE_U(8, 8)
+DEF_BUF_PARSE_U(16, 16)
+DEF_BUF_PARSE_U(32, 32)
+DEF_BUF_PARSE_U(64, 64)
+DEF_BUF_PARSE_U(W, w)
sw buf_parse_u64_dec (s_buf *buf, u64 *dest)
{
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index 6e677ba..e85540b 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -30,6 +30,16 @@
* dest is untouched.
*/
+#define BUF_PARSE_S_PROTOTYPES(bits) \
+ sw buf_parse_s ## bits (s_buf *buf, s ## bits *dest); \
+ sw buf_parse_s ## bits ## _base (s_buf *buf, const s_str *base, \
+ bool negative, s ## bits *dest)
+
+#define BUF_PARSE_U_PROTOTYPES(bits) \
+ sw buf_parse_u ## bits (s_buf *buf, u ## bits *dest); \
+ sw buf_parse_u ## bits ## _base (s_buf *buf, const s_str *base, \
+ u ## bits *dest)
+
sw buf_parse_array (s_buf *buf, s_array *dest);
sw buf_parse_bool (s_buf *buf, bool *dest);
sw buf_parse_call (s_buf *buf, s_call *dest);
@@ -64,18 +74,11 @@ sw buf_parse_module_name (s_buf *buf, const s_sym **dest);
sw buf_parse_new_tag (s_buf *buf, s_tag **dest);
sw buf_parse_ptag (s_buf *buf, p_tag *dest);
sw buf_parse_quote (s_buf *buf, s_quote *dest);
-sw buf_parse_s8 (s_buf *buf, s8 *dest);
-sw buf_parse_s8_base (s_buf *buf, const s_str *base, bool negative,
- s8 *dest);
-sw buf_parse_s16 (s_buf *buf, s16 *dest);
-sw buf_parse_s16_base (s_buf *buf, const s_str *base, bool negative,
- s16 *dest);
-sw buf_parse_s32 (s_buf *buf, s32 *dest);
-sw buf_parse_s32_base (s_buf *buf, const s_str *base, bool negative,
- s32 *dest);
-sw buf_parse_s64 (s_buf *buf, s64 *dest);
-sw buf_parse_s64_base (s_buf *buf, const s_str *base, bool negative,
- s64 *dest);
+BUF_PARSE_S_PROTOTYPES(8);
+BUF_PARSE_S_PROTOTYPES(16);
+BUF_PARSE_S_PROTOTYPES(32);
+BUF_PARSE_S_PROTOTYPES(64);
+BUF_PARSE_S_PROTOTYPES(w);
sw buf_parse_str (s_buf *buf, s_str *dest);
sw buf_parse_str_character (s_buf *buf, character *dest);
sw buf_parse_str_character_unicode (s_buf *buf, character *dest);
@@ -100,17 +103,12 @@ sw buf_parse_tag_str_u8 (s_buf *buf, s_tag *dest);
sw buf_parse_tag_sym (s_buf *buf, s_tag *dest);
sw buf_parse_tag_tuple (s_buf *buf, s_tag *dest);
sw buf_parse_tuple (s_buf *buf, s_tuple *dest);
-sw buf_parse_u8 (s_buf *buf, u8 *dest);
-sw buf_parse_u8_base (s_buf *buf, const s_str *base, u8 *dest);
-sw buf_parse_u16 (s_buf *buf, u16 *dest);
-sw buf_parse_u16_base (s_buf *buf, const s_str *base, u16 *dest);
-sw buf_parse_u32 (s_buf *buf, u32 *dest);
-sw buf_parse_u32_base (s_buf *buf, const s_str *base, u32 *dest);
-sw buf_parse_u64 (s_buf *buf, u64 *dest);
-sw buf_parse_u64_base (s_buf *buf, const s_str *base, u64 *dest);
+BUF_PARSE_U_PROTOTYPES(8);
+BUF_PARSE_U_PROTOTYPES(16);
+BUF_PARSE_U_PROTOTYPES(32);
+BUF_PARSE_U_PROTOTYPES(64);
sw buf_parse_u64_hex (s_buf *buf, u64 *dest);
-sw buf_parse_uw (s_buf *buf, uw *dest);
-sw buf_parse_uw_base (s_buf *buf, const s_str *base, uw *dest);
+BUF_PARSE_U_PROTOTYPES(w);
sw buf_parse_var (s_buf *buf, void *dest);
sw buf_parse_void (s_buf *buf, void *dest);
diff --git a/test/buf_parse_test.c b/test/buf_parse_test.c
index a3fb433..89c4801 100644
--- a/test/buf_parse_test.c
+++ b/test/buf_parse_test.c
@@ -506,6 +506,7 @@
buf_init_1(&buf, (test)); \
TEST_EQ(buf_parse_s ## bits(&buf, &s), strlen(test)); \
TEST_EQ(s, (expected)); \
+ buf_clean(&buf); \
test_context(NULL); \
} while (0)
@@ -656,6 +657,7 @@
buf_init_1(&buf, (test)); \
TEST_EQ(buf_parse_u ## bits(&buf, &u), strlen(test)); \
TEST_EQ(u, (expected)); \
+ buf_clean(&buf); \
test_context(NULL); \
} while (0)
@@ -1141,6 +1143,8 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "-0b101", -5);
BUF_PARSE_TEST_S(8, "-0b110", -6);
BUF_PARSE_TEST_S(8, "-0b111", -7);
+ BUF_PARSE_TEST_S(8, "-0b1111111", -127);
+ BUF_PARSE_TEST_S(8, "-0b01111111", -127);
BUF_PARSE_TEST_S(8, "-0b10000000", -128);
BUF_PARSE_TEST_S(8, "-0b010000000", -128);
BUF_PARSE_TEST_S(8, "-0o0", 0);
@@ -1156,6 +1160,8 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "-0o10", -8);
BUF_PARSE_TEST_S(8, "-0o11", -9);
BUF_PARSE_TEST_S(8, "-0o000", 0);
+ BUF_PARSE_TEST_S(8, "-0o177", -127);
+ BUF_PARSE_TEST_S(8, "-0o0177", -127);
BUF_PARSE_TEST_S(8, "-0o200", -128);
BUF_PARSE_TEST_S(8, "-0o0200", -128);
BUF_PARSE_TEST_S(8, "-0x0", 0);
@@ -1215,6 +1221,8 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "-020", -20);
BUF_PARSE_TEST_S(8, "-021", -21);
BUF_PARSE_TEST_S(8, "-022", -22);
+ BUF_PARSE_TEST_S(8, "-127", -127);
+ BUF_PARSE_TEST_S(8, "-0127", -127);
BUF_PARSE_TEST_S(8, "-128", -128);
BUF_PARSE_TEST_S(8, "-0128", -128);
BUF_PARSE_TEST_S(8, "0b0", 0);
@@ -1231,6 +1239,8 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "0b101", 5);
BUF_PARSE_TEST_S(8, "0b110", 6);
BUF_PARSE_TEST_S(8, "0b111", 7);
+ BUF_PARSE_TEST_S(8, "0b1000000", 64);
+ BUF_PARSE_TEST_S(8, "0b01000000", 64);
BUF_PARSE_TEST_S(8, "0b1111111", 127);
BUF_PARSE_TEST_S(8, "0b01111111", 127);
BUF_PARSE_TEST_S(8, "0o0", 0);
@@ -1246,6 +1256,8 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "0o10", 8);
BUF_PARSE_TEST_S(8, "0o11", 9);
BUF_PARSE_TEST_S(8, "0o000", 0);
+ BUF_PARSE_TEST_S(8, "0b100", 64);
+ BUF_PARSE_TEST_S(8, "0b0100", 64);
BUF_PARSE_TEST_S(8, "0o177", 127);
BUF_PARSE_TEST_S(8, "0o0177", 127);
BUF_PARSE_TEST_S(8, "0x0", 0);
@@ -1258,18 +1270,25 @@ void buf_parse_test_s8 ()
BUF_PARSE_TEST_S(8, "0x7", 7);
BUF_PARSE_TEST_S(8, "0x8", 8);
BUF_PARSE_TEST_S(8, "0x9", 9);
+ BUF_PARSE_TEST_S(8, "0xa", 10);
BUF_PARSE_TEST_S(8, "0xA", 10);
+ BUF_PARSE_TEST_S(8, "0xb", 11);
BUF_PARSE_TEST_S(8, "0xB", 11);
+ BUF_PARSE_TEST_S(8, "0xc", 12);
BUF_PARSE_TEST_S(8, "0xC", 12);
+ BUF_PARSE_TEST_S(8, "0xd", 13);
BUF_PARSE_TEST_S(8, "0xD", 13);
+ BUF_PARSE_TEST_S(8, "0xe", 14);
BUF_PARSE_TEST_S(8, "0xE", 14);
+ BUF_PARSE_TEST_S(8, "0xf", 15);
BUF_PARSE_TEST_S(8, "0xF", 15);
- BUF_PARSE_TEST_S(8, "0x00", 0);
- BUF_PARSE_TEST_S(8, "0x01", 1);
BUF_PARSE_TEST_S(8, "0x10", 16);
BUF_PARSE_TEST_S(8, "0x11", 17);
- BUF_PARSE_TEST_S(8, "0x000", 0);
+ BUF_PARSE_TEST_S(8, "0x40", 64);
+ BUF_PARSE_TEST_S(8, "0x040", 64);
+ BUF_PARSE_TEST_S(8, "0x7f", 127);
BUF_PARSE_TEST_S(8, "0x7F", 127);
+ BUF_PARSE_TEST_S(8, "0x07f", 127);
BUF_PARSE_TEST_S(8, "0x07F", 127);
BUF_PARSE_TEST_S(8, "0", 0);
BUF_PARSE_TEST_S(8, "1", 1);
@@ -1315,6 +1334,8 @@ void buf_parse_test_s16 ()
BUF_PARSE_TEST_S(16, "-0b101", -5);
BUF_PARSE_TEST_S(16, "-0b110", -6);
BUF_PARSE_TEST_S(16, "-0b111", -7);
+ BUF_PARSE_TEST_S(16, "-0b1111111", -127);
+ BUF_PARSE_TEST_S(16, "-0b01111111", -127);
BUF_PARSE_TEST_S(16, "-0b10000000", -128);
BUF_PARSE_TEST_S(16, "-0b010000000", -128);
BUF_PARSE_TEST_S(16, "-0b111111111111111", -32767);
@@ -1553,6 +1574,8 @@ void buf_parse_test_s32 ()
BUF_PARSE_TEST_S(32, "-0b101", -5);
BUF_PARSE_TEST_S(32, "-0b110", -6);
BUF_PARSE_TEST_S(32, "-0b111", -7);
+ BUF_PARSE_TEST_S(32, "-0b1111111", -127);
+ BUF_PARSE_TEST_S(32, "-0b01111111", -127);
BUF_PARSE_TEST_S(32, "-0b10000000", -128);
BUF_PARSE_TEST_S(32, "-0b010000000", -128);
BUF_PARSE_TEST_S(32, "-0b111111111111111", -32767);
@@ -1828,6 +1851,8 @@ void buf_parse_test_s64 ()
BUF_PARSE_TEST_S(64, "-0b101", -5);
BUF_PARSE_TEST_S(64, "-0b110", -6);
BUF_PARSE_TEST_S(64, "-0b111", -7);
+ BUF_PARSE_TEST_S(64, "-0b1111111", -127);
+ BUF_PARSE_TEST_S(64, "-0b01111111", -127);
BUF_PARSE_TEST_S(64, "-0b10000000", -128);
BUF_PARSE_TEST_S(64, "-0b010000000", -128);
BUF_PARSE_TEST_S(64, "-0b111111111111111", -32767);
diff --git a/test/buf_parse_test_s.rb b/test/buf_parse_test_s.rb
new file mode 100644
index 0000000..1835e9c
--- /dev/null
+++ b/test/buf_parse_test_s.rb
@@ -0,0 +1,20 @@
+File.open("buf_parse_test_s.out", "w") do |out|
+ result = 0
+ base = 0..7
+ base_prefix = "0o"
+ negative = "-"
+ base.each do |i|
+ base.each do |j|
+ base.each do |k|
+ if (i == 0 && j == 0)
+ out.puts " BUF_PARSE_TEST_S(8, \"#{negative}#{base_prefix}#{k}\", #{negative}#{result});"
+ end
+ if (i == 0)
+ out.puts " BUF_PARSE_TEST_S(8, \"#{negative}#{base_prefix}#{j}#{k}\", #{negative}#{result});"
+ end
+ out.puts " BUF_PARSE_TEST_S(8, \"#{negative}#{base_prefix}#{i}#{j}#{k}\", #{negative}#{result});"
+ result += 1
+ end
+ end
+ end
+end