Add a wuffs_base__io_buffer__compact function
diff --git a/cmd/wuffs-c/internal/cgen/base/base-public.h b/cmd/wuffs-c/internal/cgen/base/base-public.h
index 3b10b7c..ede1cd7 100644
--- a/cmd/wuffs-c/internal/cgen/base/base-public.h
+++ b/cmd/wuffs-c/internal/cgen/base/base-public.h
@@ -687,6 +687,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/cmd/wuffs-c/internal/cgen/data.go b/cmd/wuffs-c/internal/cgen/data.go
index 7b06455..34cebd1 100644
--- a/cmd/wuffs-c/internal/cgen/data.go
+++ b/cmd/wuffs-c/internal/cgen/data.go
@@ -59,7 +59,8 @@
"(\n wuffs_base__rect_ie_u32 r,\n wuffs_base__rect_ie_u32 s) {\n if (wuffs_base__rect_ie_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__rect_ie_u32__is_empty(s)) {\n return r;\n }\n r.min_incl_x = wuffs_base__u32__min(r.min_incl_x, s.min_incl_x);\n r.min_incl_y = wuffs_base__u32__min(r.min_incl_y, s.min_incl_y);\n r.max_excl_x = wuffs_base__u32__max(r.max_excl_x, s.max_excl_x);\n r.max_excl_y = wuffs_base__u32__max(r.max_excl_y, s.max_excl_y);\n return r;\n}\n\nstatic inline uint32_t wuffs_base__rect_ie_u32__width(\n wuffs_base__rect_ie_u32 r) {\n return wuffs_base__u32__sat_sub(r.max_excl_x, r.min_incl_x);\n}\n\nstatic inline uint32_t wuffs_base__rect_ie_u32__height(\n wuffs_base__rect_ie_u32 r) {\n return wuffs_base__u32__sat_sub(r.max_excl_y, r.min_incl_y);\n}\n\n" +
"" +
"// ---------------- I/O\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length), plus\n// additional indexes into that buffer, plus an opened / closed flag.\n//\n// A value with all fields NULL or zero is a valid, empty buffer.\ntypedef struct {\n uint8_t* ptr; // Pointer.\n size_t len; // Length.\n size_t wi; // Write index. Invariant: wi <= len.\n size_t ri; // Read index. Invariant: ri <= wi.\n bool closed; // No further writes are expected.\n} wuffs_base__io_buffer;\n\ntypedef struct {\n // Do not access the private_impl's fields directly. There is no API/ABI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__io_buffer* buf;\n // The bounds values are typically NULL, when created by the Wuffs public\n // API. NULL means that the callee substitutes the implicit bounds derived\n // from buf.\n uint8_t* bounds[2];\n } private_impl;\n} wuffs_base__io_reader;\n\ntypedef struct {\n // Do not access the private_impl's fields directly. There is no API/A" +
- "BI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__io_buffer* buf;\n // The bounds values are typically NULL, when created by the Wuffs public\n // API. NULL means that the callee substitutes the implicit bounds derived\n // from buf.\n uint8_t* bounds[2];\n } private_impl;\n} wuffs_base__io_writer;\n\nstatic inline wuffs_base__io_reader wuffs_base__io_buffer__reader(\n wuffs_base__io_buffer* buf) {\n wuffs_base__io_reader ret = ((wuffs_base__io_reader){});\n ret.private_impl.buf = buf;\n return ret;\n}\n\nstatic inline wuffs_base__io_writer wuffs_base__io_buffer__writer(\n wuffs_base__io_buffer* buf) {\n wuffs_base__io_writer ret = ((wuffs_base__io_writer){});\n ret.private_impl.buf = buf;\n return ret;\n}\n\n" +
+ "BI\n // compatibility or safety guarantee if you do so.\n struct {\n wuffs_base__io_buffer* buf;\n // The bounds values are typically NULL, when created by the Wuffs public\n // API. NULL means that the callee substitutes the implicit bounds derived\n // from buf.\n uint8_t* bounds[2];\n } private_impl;\n} wuffs_base__io_writer;\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {\n if (!buf || (buf->ri == 0)) {\n return;\n }\n size_t n = buf->wi - buf->ri;\n if (n != 0) {\n memmove(buf->ptr, buf->ptr + buf->ri, n);\n }\n buf->wi = n;\n buf->ri = 0;\n}\n\nstatic inline wuffs_base__io_reader wuffs_base__io_buffer__reader(\n wuffs_base__io_buffer* buf) {\n wuffs_base__io_reader ret = ((wuffs_base__io_reader){});\n ret.private_impl.buf = buf;\n return ret;\n}\n\nstatic inline wuffs_base__io_writer wuffs_base__io_buffer__writer(\n wuffs_base__io_buffer* buf) {\n wuffs_base__io" +
+ "_writer ret = ((wuffs_base__io_writer){});\n ret.private_impl.buf = buf;\n return ret;\n}\n\n" +
"" +
"// ---------------- Images\n\n// wuffs_base__color_u32argb is an 8 bit per channel Alpha, Red, Green, Blue\n// color, as a uint32_t value. It is in word order, not byte order: its value\n// is always 0xAARRGGBB, regardless of endianness. It uses premultiplied alpha.\ntypedef uint32_t wuffs_base__color_u32argb;\n\n" +
"" +
diff --git a/example/zcat/zcat.c b/example/zcat/zcat.c
index d227f1b..fbd5df1 100644
--- a/example/zcat/zcat.c
+++ b/example/zcat/zcat.c
@@ -78,30 +78,30 @@
wuffs_gzip__decoder dec = ((wuffs_gzip__decoder){});
wuffs_gzip__decoder__check_wuffs_version(&dec, sizeof dec, WUFFS_VERSION);
+ wuffs_base__io_buffer src =
+ ((wuffs_base__io_buffer){.ptr = src_buffer, .len = SRC_BUFFER_SIZE});
+
while (true) {
const int stdin_fd = 0;
- ssize_t n_src = read(stdin_fd, src_buffer, SRC_BUFFER_SIZE);
- if (n_src < 0) {
+ ssize_t n = read(stdin_fd, src.ptr + src.wi, src.len - src.wi);
+ if (n < 0) {
if (errno != EINTR) {
return strerror(errno);
}
continue;
}
-
- wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
- .ptr = src_buffer,
- .len = SRC_BUFFER_SIZE,
- .wi = n_src,
- .closed = n_src == 0,
- });
- wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
+ src.wi += n;
+ if (n == 0) {
+ src.closed = true;
+ }
while (true) {
wuffs_base__io_buffer dst =
((wuffs_base__io_buffer){.ptr = dst_buffer, .len = DST_BUFFER_SIZE});
- wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&dst);
+
wuffs_base__status s =
- wuffs_gzip__decoder__decode(&dec, dst_writer, src_reader);
+ wuffs_gzip__decoder__decode(&dec, wuffs_base__io_buffer__writer(&dst),
+ wuffs_base__io_buffer__reader(&src));
if (dst.wi) {
// TODO: handle EINTR and other write errors; see "man 2 write".
@@ -115,9 +115,15 @@
if (s == WUFFS_BASE__SUSPENSION_SHORT_READ) {
break;
}
- if (s != WUFFS_BASE__SUSPENSION_SHORT_WRITE) {
- return wuffs_gzip__status__string(s);
+ if (s == WUFFS_BASE__SUSPENSION_SHORT_WRITE) {
+ continue;
}
+ return wuffs_gzip__status__string(s);
+ }
+
+ wuffs_base__io_buffer__compact(&src);
+ if (src.wi == src.len) {
+ return "internal error: no I/O progress possible";
}
}
}
diff --git a/gen/c/base.c b/gen/c/base.c
index 32be2ea..7372620 100644
--- a/gen/c/base.c
+++ b/gen/c/base.c
@@ -718,6 +718,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/adler32.c b/gen/c/std/adler32.c
index 5c11a70..974bcff 100644
--- a/gen/c/std/adler32.c
+++ b/gen/c/std/adler32.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/crc32.c b/gen/c/std/crc32.c
index b04901e..22d7a08 100644
--- a/gen/c/std/crc32.c
+++ b/gen/c/std/crc32.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/deflate.c b/gen/c/std/deflate.c
index 0d26ace..0fe9318 100644
--- a/gen/c/std/deflate.c
+++ b/gen/c/std/deflate.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/gif.c b/gen/c/std/gif.c
index 4bea40a..8f6c16a 100644
--- a/gen/c/std/gif.c
+++ b/gen/c/std/gif.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/gzip.c b/gen/c/std/gzip.c
index 8b8866d..ed899b7 100644
--- a/gen/c/std/gzip.c
+++ b/gen/c/std/gzip.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/lzw.c b/gen/c/std/lzw.c
index 611b39c..41703b6 100644
--- a/gen/c/std/lzw.c
+++ b/gen/c/std/lzw.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/c/std/zlib.c b/gen/c/std/zlib.c
index 42e00ca..5480b1c 100644
--- a/gen/c/std/zlib.c
+++ b/gen/c/std/zlib.c
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/adler32.h b/gen/h/std/adler32.h
index eaf0778..fcebcc1 100644
--- a/gen/h/std/adler32.h
+++ b/gen/h/std/adler32.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/crc32.h b/gen/h/std/crc32.h
index 64c8916..37f7d7d 100644
--- a/gen/h/std/crc32.h
+++ b/gen/h/std/crc32.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/deflate.h b/gen/h/std/deflate.h
index 5a94749..71f94f2 100644
--- a/gen/h/std/deflate.h
+++ b/gen/h/std/deflate.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/gif.h b/gen/h/std/gif.h
index 2825a46..48c65c0 100644
--- a/gen/h/std/gif.h
+++ b/gen/h/std/gif.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/gzip.h b/gen/h/std/gzip.h
index 9cf0a75..33a48b4 100644
--- a/gen/h/std/gzip.h
+++ b/gen/h/std/gzip.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/lzw.h b/gen/h/std/lzw.h
index e71e8a6..18e23a2 100644
--- a/gen/h/std/lzw.h
+++ b/gen/h/std/lzw.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});
diff --git a/gen/h/std/zlib.h b/gen/h/std/zlib.h
index 077f63a..5ee4b9c 100644
--- a/gen/h/std/zlib.h
+++ b/gen/h/std/zlib.h
@@ -707,6 +707,20 @@
} private_impl;
} wuffs_base__io_writer;
+// wuffs_base__io_buffer__compact moves any written but unread bytes to the
+// start of the buffer.
+static inline void wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
+ if (!buf || (buf->ri == 0)) {
+ return;
+ }
+ size_t n = buf->wi - buf->ri;
+ if (n != 0) {
+ memmove(buf->ptr, buf->ptr + buf->ri, n);
+ }
+ buf->wi = n;
+ buf->ri = 0;
+}
+
static inline wuffs_base__io_reader wuffs_base__io_buffer__reader(
wuffs_base__io_buffer* buf) {
wuffs_base__io_reader ret = ((wuffs_base__io_reader){});