Add wuffs_base__uxx__rotate_etc functions
diff --git a/fuzz/c/std/bmp_fuzzer.c b/fuzz/c/std/bmp_fuzzer.c
index 139e109..2f0f45d 100644
--- a/fuzz/c/std/bmp_fuzzer.c
+++ b/fuzz/c/std/bmp_fuzzer.c
@@ -66,7 +66,7 @@
wuffs_base__status status = wuffs_bmp__decoder__initialize(
&dec, sizeof dec, WUFFS_VERSION,
(hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED : 0);
- hash >>= 1;
+ hash = wuffs_base__u64__rotate_right(hash, 1);
if (!wuffs_base__status__is_ok(&status)) {
return wuffs_base__status__message(&status);
}
diff --git a/fuzz/c/std/cbor_fuzzer.c b/fuzz/c/std/cbor_fuzzer.c
index 1df5b55..6b49617 100644
--- a/fuzz/c/std/cbor_fuzzer.c
+++ b/fuzz/c/std/cbor_fuzzer.c
@@ -221,12 +221,13 @@
}
uint64_t //
-buffer_limit(uint64_t hash_6_bits, uint64_t min, uint64_t max) {
+buffer_limit(uint64_t hash, uint64_t min, uint64_t max) {
+ hash &= 0x3F;
uint64_t n;
- if (hash_6_bits < 0x20) {
- n = min + hash_6_bits;
+ if (hash < 0x20) {
+ n = min + hash;
} else {
- n = max - (0x3F - hash_6_bits);
+ n = max - (0x3F - hash);
}
if (n < min) {
return min;
@@ -237,15 +238,15 @@
}
const char* //
-fuzz_complex(wuffs_base__io_buffer* full_src, uint64_t hash_56_bits) {
+fuzz_complex(wuffs_base__io_buffer* full_src, uint64_t hash) {
uint64_t tok_limit = buffer_limit(
- hash_56_bits & 0x3F, WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL,
+ hash & 0x3F, WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL,
TOK_BUFFER_ARRAY_SIZE);
- uint64_t hash_50_bits = hash_56_bits >> 6;
+ hash = wuffs_base__u64__rotate_right(hash, 6);
- uint64_t src_limit =
- buffer_limit(hash_50_bits & 0x3F,
- WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL, 4096);
+ uint64_t src_limit = buffer_limit(
+ hash & 0x3F, WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL, 4096);
+ hash = wuffs_base__u64__rotate_right(hash, 6);
// ----
@@ -407,7 +408,7 @@
// The fuzz_complex implementation adds many more Wuffs API specific checks
// (e.g. that the sum of the tokens' lengths do not exceed the input length).
if ((hash & 0xFF) != 0xA5) {
- return fuzz_complex(full_src, hash >> 8);
+ return fuzz_complex(full_src, wuffs_base__u64__rotate_right(hash, 8));
}
return fuzz_simple(full_src);
}
diff --git a/fuzz/c/std/gif_fuzzer.c b/fuzz/c/std/gif_fuzzer.c
index 2da0d1b..1dcfb44 100644
--- a/fuzz/c/std/gif_fuzzer.c
+++ b/fuzz/c/std/gif_fuzzer.c
@@ -61,7 +61,7 @@
#include "../fuzzlib/fuzzlib.c"
#include "../fuzzlib/fuzzlib_image_decoder.c"
-void set_quirks(wuffs_gif__decoder* dec, uint64_t hash_55_bits) {
+void set_quirks(wuffs_gif__decoder* dec, uint64_t hash) {
uint32_t quirks[] = {
WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES,
WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND,
@@ -75,8 +75,8 @@
uint32_t i;
for (i = 0; quirks[i]; i++) {
- uint64_t bit = 1 << (i % 55);
- if (hash_55_bits & bit) {
+ uint64_t bit = 1 << (i & 63);
+ if (hash & bit) {
wuffs_gif__decoder__set_quirk_enabled(dec, quirks[i], true);
}
}
@@ -88,13 +88,13 @@
wuffs_base__status status = wuffs_gif__decoder__initialize(
&dec, sizeof dec, WUFFS_VERSION,
(hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED : 0);
- hash >>= 1;
+ hash = wuffs_base__u64__rotate_right(hash, 1);
uint64_t hash_8_bits = hash & 0xFF;
- uint64_t hash_55_bits = hash >> 8;
+ hash = wuffs_base__u64__rotate_right(hash, 8);
if (!wuffs_base__status__is_ok(&status)) {
return wuffs_base__status__message(&status);
}
- set_quirks(&dec, hash_55_bits);
+ set_quirks(&dec, hash);
return fuzz_image_decoder(
src, hash_8_bits,
wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(&dec));
diff --git a/fuzz/c/std/json_fuzzer.c b/fuzz/c/std/json_fuzzer.c
index 0c22678..1a6a858 100644
--- a/fuzz/c/std/json_fuzzer.c
+++ b/fuzz/c/std/json_fuzzer.c
@@ -209,12 +209,13 @@
}
uint64_t //
-buffer_limit(uint64_t hash_6_bits, uint64_t min, uint64_t max) {
+buffer_limit(uint64_t hash, uint64_t min, uint64_t max) {
+ hash &= 0x3F;
uint64_t n;
- if (hash_6_bits < 0x20) {
- n = min + hash_6_bits;
+ if (hash < 0x20) {
+ n = min + hash;
} else {
- n = max - (0x3F - hash_6_bits);
+ n = max - (0x3F - hash);
}
if (n < min) {
return min;
@@ -224,7 +225,7 @@
return n;
}
-void set_quirks(wuffs_json__decoder* dec, uint64_t hash_44_bits) {
+void set_quirks(wuffs_json__decoder* dec, uint64_t hash) {
uint32_t quirks[] = {
WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A,
WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U,
@@ -247,24 +248,23 @@
uint32_t i;
for (i = 0; quirks[i]; i++) {
- uint64_t bit = 1 << (i % 44);
- if (hash_44_bits & bit) {
+ uint64_t bit = 1 << (i & 63);
+ if (hash & bit) {
wuffs_json__decoder__set_quirk_enabled(dec, quirks[i], true);
}
}
}
const char* //
-fuzz_complex(wuffs_base__io_buffer* full_src, uint64_t hash_56_bits) {
+fuzz_complex(wuffs_base__io_buffer* full_src, uint64_t hash) {
uint64_t tok_limit = buffer_limit(
- hash_56_bits & 0x3F, WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL,
+ hash & 0x3F, WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL,
TOK_BUFFER_ARRAY_SIZE);
- uint64_t hash_50_bits = hash_56_bits >> 6;
+ hash = wuffs_base__u64__rotate_right(hash, 6);
- uint64_t src_limit =
- buffer_limit(hash_50_bits & 0x3F,
- WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL, 4096);
- uint64_t hash_44_bits = hash_50_bits >> 6;
+ uint64_t src_limit = buffer_limit(
+ hash & 0x3F, WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL, 4096);
+ hash = wuffs_base__u64__rotate_right(hash, 6);
// ----
@@ -275,7 +275,7 @@
if (!wuffs_base__status__is_ok(&status)) {
return wuffs_base__status__message(&status);
}
- set_quirks(&dec, hash_44_bits);
+ set_quirks(&dec, hash);
wuffs_base__token tok_array[TOK_BUFFER_ARRAY_SIZE];
wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
@@ -427,7 +427,7 @@
// The fuzz_complex implementation adds many more Wuffs API specific checks
// (e.g. that the sum of the tokens' lengths do not exceed the input length).
if ((hash & 0xFF) != 0xA5) {
- return fuzz_complex(full_src, hash >> 8);
+ return fuzz_complex(full_src, wuffs_base__u64__rotate_right(hash, 8));
}
return fuzz_simple(full_src);
}
diff --git a/fuzz/c/std/png_fuzzer.c b/fuzz/c/std/png_fuzzer.c
index 1191fda..d6cc049 100644
--- a/fuzz/c/std/png_fuzzer.c
+++ b/fuzz/c/std/png_fuzzer.c
@@ -70,7 +70,7 @@
wuffs_base__status status = wuffs_png__decoder__initialize(
&dec, sizeof dec, WUFFS_VERSION,
(hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED : 0);
- hash >>= 1;
+ hash = wuffs_base__u64__rotate_right(hash, 1);
if (!wuffs_base__status__is_ok(&status)) {
return wuffs_base__status__message(&status);
}
diff --git a/internal/cgen/base/fundamental-public.h b/internal/cgen/base/fundamental-public.h
index 7d4a0e7..67ada28 100644
--- a/internal/cgen/base/fundamental-public.h
+++ b/internal/cgen/base/fundamental-public.h
@@ -581,6 +581,56 @@
// --------
+static inline uint8_t //
+wuffs_base__u8__rotate_left(uint8_t x, uint32_t n) {
+ n &= 7;
+ return (x << n) | (x >> (8 - n));
+}
+
+static inline uint8_t //
+wuffs_base__u8__rotate_right(uint8_t x, uint32_t n) {
+ n &= 7;
+ return (x >> n) | (x << (8 - n));
+}
+
+static inline uint16_t //
+wuffs_base__u16__rotate_left(uint16_t x, uint32_t n) {
+ n &= 15;
+ return (x << n) | (x >> (16 - n));
+}
+
+static inline uint16_t //
+wuffs_base__u16__rotate_right(uint16_t x, uint32_t n) {
+ n &= 15;
+ return (x >> n) | (x << (16 - n));
+}
+
+static inline uint32_t //
+wuffs_base__u32__rotate_left(uint32_t x, uint32_t n) {
+ n &= 31;
+ return (x << n) | (x >> (32 - n));
+}
+
+static inline uint32_t //
+wuffs_base__u32__rotate_right(uint32_t x, uint32_t n) {
+ n &= 31;
+ return (x >> n) | (x << (32 - n));
+}
+
+static inline uint64_t //
+wuffs_base__u64__rotate_left(uint64_t x, uint32_t n) {
+ n &= 63;
+ return (x << n) | (x >> (64 - n));
+}
+
+static inline uint64_t //
+wuffs_base__u64__rotate_right(uint64_t x, uint32_t n) {
+ n &= 63;
+ return (x >> n) | (x << (64 - n));
+}
+
+// --------
+
// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms
// are per https://locklessinc.com/articles/sat_arithmetic/
//
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index 2dc1bf7..16a3420 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -91,6 +91,9 @@
"int32_t //\nwuffs_base__i32__max(int32_t x, int32_t y) {\n return x > y ? x : y;\n}\n\nstatic inline int64_t //\nwuffs_base__i64__min(int64_t x, int64_t y) {\n return x < y ? x : y;\n}\n\nstatic inline int64_t //\nwuffs_base__i64__max(int64_t x, int64_t y) {\n return x > y ? x : y;\n}\n\nstatic inline uint8_t //\nwuffs_base__u8__min(uint8_t x, uint8_t y) {\n return x < y ? x : y;\n}\n\nstatic inline uint8_t //\nwuffs_base__u8__max(uint8_t x, uint8_t y) {\n return x > y ? x : y;\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__min(uint16_t x, uint16_t y) {\n return x < y ? x : y;\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__max(uint16_t x, uint16_t y) {\n return x > y ? x : y;\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__min(uint32_t x, uint32_t y) {\n return x < y ? x : y;\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__max(uint32_t x, uint32_t y) {\n return x > y ? x : y;\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__min(uint64_t x, uint64_t y) {\n return x < y ? x : y;\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__m" +
"ax(uint64_t x, uint64_t y) {\n return x > y ? x : y;\n}\n\n" +
"" +
+ "// --------\n\nstatic inline uint8_t //\nwuffs_base__u8__rotate_left(uint8_t x, uint32_t n) {\n n &= 7;\n return (x << n) | (x >> (8 - n));\n}\n\nstatic inline uint8_t //\nwuffs_base__u8__rotate_right(uint8_t x, uint32_t n) {\n n &= 7;\n return (x >> n) | (x << (8 - n));\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__rotate_left(uint16_t x, uint32_t n) {\n n &= 15;\n return (x << n) | (x >> (16 - n));\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__rotate_right(uint16_t x, uint32_t n) {\n n &= 15;\n return (x >> n) | (x << (16 - n));\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__rotate_left(uint32_t x, uint32_t n) {\n n &= 31;\n return (x << n) | (x >> (32 - n));\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__rotate_right(uint32_t x, uint32_t n) {\n n &= 31;\n return (x >> n) | (x << (32 - n));\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__rotate_left(uint64_t x, uint32_t n) {\n n &= 63;\n return (x << n) | (x >> (64 - n));\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__rotate_right(uint64_t x, uint32_t n) {\n n " +
+ "&= 63;\n return (x >> n) | (x << (64 - n));\n}\n\n" +
+ "" +
"// --------\n\n// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms\n// are per https://locklessinc.com/articles/sat_arithmetic/\n//\n// It is important that the underlying types are unsigned integers, as signed\n// integer arithmetic overflow is undefined behavior in C.\n\nstatic inline uint8_t //\nwuffs_base__u8__sat_add(uint8_t x, uint8_t y) {\n uint8_t res = (uint8_t)(x + y);\n res |= (uint8_t)(-(res < x));\n return res;\n}\n\nstatic inline uint8_t //\nwuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {\n uint8_t res = (uint8_t)(x - y);\n res &= (uint8_t)(-(res <= x));\n return res;\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__sat_add(uint16_t x, uint16_t y) {\n uint16_t res = (uint16_t)(x + y);\n res |= (uint16_t)(-(res < x));\n return res;\n}\n\nstatic inline uint16_t //\nwuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {\n uint16_t res = (uint16_t)(x - y);\n res &= (uint16_t)(-(res <= x));\n return res;\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__sat_add(uint32_t x, uint32_t y) {\n uint32" +
"_t res = (uint32_t)(x + y);\n res |= (uint32_t)(-(res < x));\n return res;\n}\n\nstatic inline uint32_t //\nwuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {\n uint32_t res = (uint32_t)(x - y);\n res &= (uint32_t)(-(res <= x));\n return res;\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__sat_add(uint64_t x, uint64_t y) {\n uint64_t res = (uint64_t)(x + y);\n res |= (uint64_t)(-(res < x));\n return res;\n}\n\nstatic inline uint64_t //\nwuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {\n uint64_t res = (uint64_t)(x - y);\n res &= (uint64_t)(-(res <= x));\n return res;\n}\n\n" +
"" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 2989dcd..c3eddad 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -804,6 +804,56 @@
// --------
+static inline uint8_t //
+wuffs_base__u8__rotate_left(uint8_t x, uint32_t n) {
+ n &= 7;
+ return (x << n) | (x >> (8 - n));
+}
+
+static inline uint8_t //
+wuffs_base__u8__rotate_right(uint8_t x, uint32_t n) {
+ n &= 7;
+ return (x >> n) | (x << (8 - n));
+}
+
+static inline uint16_t //
+wuffs_base__u16__rotate_left(uint16_t x, uint32_t n) {
+ n &= 15;
+ return (x << n) | (x >> (16 - n));
+}
+
+static inline uint16_t //
+wuffs_base__u16__rotate_right(uint16_t x, uint32_t n) {
+ n &= 15;
+ return (x >> n) | (x << (16 - n));
+}
+
+static inline uint32_t //
+wuffs_base__u32__rotate_left(uint32_t x, uint32_t n) {
+ n &= 31;
+ return (x << n) | (x >> (32 - n));
+}
+
+static inline uint32_t //
+wuffs_base__u32__rotate_right(uint32_t x, uint32_t n) {
+ n &= 31;
+ return (x >> n) | (x << (32 - n));
+}
+
+static inline uint64_t //
+wuffs_base__u64__rotate_left(uint64_t x, uint32_t n) {
+ n &= 63;
+ return (x << n) | (x >> (64 - n));
+}
+
+static inline uint64_t //
+wuffs_base__u64__rotate_right(uint64_t x, uint32_t n) {
+ n &= 63;
+ return (x >> n) | (x << (64 - n));
+}
+
+// --------
+
// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms
// are per https://locklessinc.com/articles/sat_arithmetic/
//