Have wuffs_aux's CopyIn compact the dst buffer
diff --git a/internal/cgen/auxiliary/base.cc b/internal/cgen/auxiliary/base.cc
index 3246567..5e09762 100644
--- a/internal/cgen/auxiliary/base.cc
+++ b/internal/cgen/auxiliary/base.cc
@@ -40,7 +40,12 @@
FileInput::CopyIn(IOBuffer* dst) {
if (!m_f) {
return "wuffs_aux::sync_io::FileInput: nullptr file";
- } else if (dst && !dst->meta.closed) {
+ } else if (!dst) {
+ return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
+ } else if (dst->meta.closed) {
+ return "wuffs_aux::sync_io::FileInput: end of file";
+ } else {
+ dst->compact();
size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
dst->meta.wi += n;
dst->meta.closed = feof(m_f);
@@ -69,7 +74,16 @@
std::string //
MemoryInput::CopyIn(IOBuffer* dst) {
- if (dst && !dst->meta.closed && (dst != &m_io)) {
+ if (!dst) {
+ return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
+ } else if (dst->meta.closed) {
+ return "wuffs_aux::sync_io::MemoryInput: end of file";
+ } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
+ // Treat m_io's data as immutable, so don't compact dst or otherwise write
+ // to it.
+ return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
+ } else {
+ dst->compact();
size_t nd = dst->writer_length();
size_t ns = m_io.reader_length();
size_t n = (nd < ns) ? nd : ns;
diff --git a/internal/cgen/base/fundamental-public.h b/internal/cgen/base/fundamental-public.h
index cfcc753..20939d8 100644
--- a/internal/cgen/base/fundamental-public.h
+++ b/internal/cgen/base/fundamental-public.h
@@ -1065,6 +1065,12 @@
return ret;
}
+static inline bool //
+wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
+ return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
+ ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
+}
+
// wuffs_base__slice_u8__subslice_i returns s[i:].
//
// It returns an empty slice if i is out of bounds.
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index a157c84..535b79a 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -111,8 +111,8 @@
"// ---------------- Slices and Tables\n\n// WUFFS_BASE__SLICE is a 1-dimensional buffer.\n//\n// len measures a number of elements, not necessarily a size in bytes.\n//\n// A value with all fields NULL or zero is a valid, empty slice.\n#define WUFFS_BASE__SLICE(T) \\\n struct { \\\n T* ptr; \\\n size_t len; \\\n }\n\n// WUFFS_BASE__TABLE is a 2-dimensional buffer.\n//\n// width height, and stride measure a number of elements, not necessarily a\n// size in bytes.\n//\n// A value with all fields NULL or zero is a valid, empty table.\n#define WUFFS_BASE__TABLE(T) \\\n struct { \\\n T* ptr; \\\n size_t width; \\\n size_t height; \\\n size_t stride; \\\n }\n\ntypedef WUFFS_BASE__SLICE(uint8_t) wuffs_base__slice_u8;\ntypedef WUFFS_BASE__SLICE(uint16_t) wuffs_base__slice_u16;\ntypedef WUFFS_BASE__SLICE(uint32_t) wuffs_base__slice_u32;\ntypedef WUFFS_BASE__SLICE(uint64_t) wuffs_base__slice_u64;\n\ntypedef WUFFS_BASE__TABLE(u" +
"int8_t) wuffs_base__table_u8;\ntypedef WUFFS_BASE__TABLE(uint16_t) wuffs_base__table_u16;\ntypedef WUFFS_BASE__TABLE(uint32_t) wuffs_base__table_u32;\ntypedef WUFFS_BASE__TABLE(uint64_t) wuffs_base__table_u64;\n\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__make_slice_u8(uint8_t* ptr, size_t len) {\n wuffs_base__slice_u8 ret;\n ret.ptr = ptr;\n ret.len = len;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u16 //\nwuffs_base__make_slice_u16(uint16_t* ptr, size_t len) {\n wuffs_base__slice_u16 ret;\n ret.ptr = ptr;\n ret.len = len;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u32 //\nwuffs_base__make_slice_u32(uint32_t* ptr, size_t len) {\n wuffs_base__slice_u32 ret;\n ret.ptr = ptr;\n ret.len = len;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u64 //\nwuffs_base__make_slice_u64(uint64_t* ptr, size_t len) {\n wuffs_base__slice_u64 ret;\n ret.ptr = ptr;\n ret.len = len;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__empty_slice_u8() {\n wuffs_base__slice_u8 ret;\n ret.ptr = NULL;\n" +
" ret.len = 0;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u16 //\nwuffs_base__empty_slice_u16() {\n wuffs_base__slice_u16 ret;\n ret.ptr = NULL;\n ret.len = 0;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u32 //\nwuffs_base__empty_slice_u32() {\n wuffs_base__slice_u32 ret;\n ret.ptr = NULL;\n ret.len = 0;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u64 //\nwuffs_base__empty_slice_u64() {\n wuffs_base__slice_u64 ret;\n ret.ptr = NULL;\n ret.len = 0;\n return ret;\n}\n\nstatic inline wuffs_base__table_u8 //\nwuffs_base__empty_table_u8() {\n wuffs_base__table_u8 ret;\n ret.ptr = NULL;\n ret.width = 0;\n ret.height = 0;\n ret.stride = 0;\n return ret;\n}\n\nstatic inline wuffs_base__table_u16 //\nwuffs_base__empty_table_u16() {\n wuffs_base__table_u16 ret;\n ret.ptr = NULL;\n ret.width = 0;\n ret.height = 0;\n ret.stride = 0;\n return ret;\n}\n\nstatic inline wuffs_base__table_u32 //\nwuffs_base__empty_table_u32() {\n wuffs_base__table_u32 ret;\n ret.ptr = NULL;\n ret.width = 0;\n ret.height = 0;\n ret.stri" +
- "de = 0;\n return ret;\n}\n\nstatic inline wuffs_base__table_u64 //\nwuffs_base__empty_table_u64() {\n wuffs_base__table_u64 ret;\n ret.ptr = NULL;\n ret.width = 0;\n ret.height = 0;\n ret.stride = 0;\n return ret;\n}\n\n// wuffs_base__slice_u8__subslice_i returns s[i:].\n//\n// It returns an empty slice if i is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {\n if ((i <= SIZE_MAX) && (i <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_j returns s[:j].\n//\n// It returns an empty slice if j is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, uint64_t j) {\n if ((j <= SIZE_MAX) && (j <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_ij returns s[i:j].\n//\n// It " +
- "returns an empty slice if i or j is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,\n uint64_t i,\n uint64_t j) {\n if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n" +
+ "de = 0;\n return ret;\n}\n\nstatic inline wuffs_base__table_u64 //\nwuffs_base__empty_table_u64() {\n wuffs_base__table_u64 ret;\n ret.ptr = NULL;\n ret.width = 0;\n ret.height = 0;\n ret.stride = 0;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {\n return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||\n ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));\n}\n\n// wuffs_base__slice_u8__subslice_i returns s[i:].\n//\n// It returns an empty slice if i is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {\n if ((i <= SIZE_MAX) && (i <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_j returns s[:j].\n//\n// It returns an empty slice if j is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, ui" +
+ "nt64_t j) {\n if ((j <= SIZE_MAX) && (j <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n// wuffs_base__slice_u8__subslice_ij returns s[i:j].\n//\n// It returns an empty slice if i or j is out of bounds.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,\n uint64_t i,\n uint64_t j) {\n if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {\n return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\n" +
"" +
"// ---------------- Magic Numbers\n\n// wuffs_base__magic_number_guess_fourcc guesses the file format of some data,\n// given its opening bytes. It returns a positive FourCC value on success.\n//\n// It returns zero if nothing matches its hard-coded list of 'magic numbers'.\n//\n// It returns a negative value if a longer prefix is required for a conclusive\n// result. For example, seeing a single 'B' byte is not enough to discriminate\n// the BMP and BPG image file formats.\n//\n// It does not do a full validity check. Like any guess made from a short\n// prefix of the data, it may return false positives. Data that starts with 99\n// bytes of valid JPEG followed by corruption or truncation is an invalid JPEG\n// image overall, but this function will still return WUFFS_BASE__FOURCC__JPEG.\n//\n// Another source of false positives is that some 'magic numbers' are valid\n// ASCII data. A file starting with \"GIF87a and GIF89a are the two versions of\n// GIF\" will match GIF's 'magic number' even if it's plain text, not an image.\n//" +
"\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__MAGIC sub-module, not just\n// WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC int32_t //\nwuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix);\n" +
@@ -690,9 +690,10 @@
"" +
"// --------\n\nIOBuffer* //\nInput::BringsItsOwnIOBuffer() {\n return nullptr;\n}\n\n" +
"" +
- "// --------\n\nFileInput::FileInput(FILE* f) : m_f(f) {}\n\nstd::string //\nFileInput::CopyIn(IOBuffer* dst) {\n if (!m_f) {\n return \"wuffs_aux::sync_io::FileInput: nullptr file\";\n } else if (dst && !dst->meta.closed) {\n size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);\n dst->meta.wi += n;\n dst->meta.closed = feof(m_f);\n if (ferror(m_f)) {\n return \"wuffs_aux::sync_io::FileInput: error reading file\";\n }\n }\n return \"\";\n}\n\n" +
+ "// --------\n\nFileInput::FileInput(FILE* f) : m_f(f) {}\n\nstd::string //\nFileInput::CopyIn(IOBuffer* dst) {\n if (!m_f) {\n return \"wuffs_aux::sync_io::FileInput: nullptr file\";\n } else if (!dst) {\n return \"wuffs_aux::sync_io::FileInput: nullptr IOBuffer\";\n } else if (dst->meta.closed) {\n return \"wuffs_aux::sync_io::FileInput: end of file\";\n } else {\n dst->compact();\n size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);\n dst->meta.wi += n;\n dst->meta.closed = feof(m_f);\n if (ferror(m_f)) {\n return \"wuffs_aux::sync_io::FileInput: error reading file\";\n }\n }\n return \"\";\n}\n\n" +
"" +
- "// --------\n\nMemoryInput::MemoryInput(const char* ptr, size_t len)\n : m_io(wuffs_base__ptr_u8__reader(\n static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),\n len,\n true)) {}\n\nMemoryInput::MemoryInput(const uint8_t* ptr, size_t len)\n : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}\n\nIOBuffer* //\nMemoryInput::BringsItsOwnIOBuffer() {\n return &m_io;\n}\n\nstd::string //\nMemoryInput::CopyIn(IOBuffer* dst) {\n if (dst && !dst->meta.closed && (dst != &m_io)) {\n size_t nd = dst->writer_length();\n size_t ns = m_io.reader_length();\n size_t n = (nd < ns) ? nd : ns;\n memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);\n m_io.meta.ri += n;\n dst->meta.wi += n;\n dst->meta.closed = m_io.reader_length() == 0;\n }\n return \"\";\n}\n\n" +
+ "// --------\n\nMemoryInput::MemoryInput(const char* ptr, size_t len)\n : m_io(wuffs_base__ptr_u8__reader(\n static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),\n len,\n true)) {}\n\nMemoryInput::MemoryInput(const uint8_t* ptr, size_t len)\n : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}\n\nIOBuffer* //\nMemoryInput::BringsItsOwnIOBuffer() {\n return &m_io;\n}\n\nstd::string //\nMemoryInput::CopyIn(IOBuffer* dst) {\n if (!dst) {\n return \"wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer\";\n } else if (dst->meta.closed) {\n return \"wuffs_aux::sync_io::MemoryInput: end of file\";\n } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {\n // Treat m_io's data as immutable, so don't compact dst or otherwise write\n // to it.\n return \"wuffs_aux::sync_io::MemoryInput: overlapping buffers\";\n } else {\n dst->compact();\n size_t nd = dst->writer_length();\n size_t ns = m_io.reader_length();\n size_t n = (nd < ns) ? nd : ns;\n " +
+ " memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);\n m_io.meta.ri += n;\n dst->meta.wi += n;\n dst->meta.closed = m_io.reader_length() == 0;\n }\n return \"\";\n}\n\n" +
"" +
"// --------\n\n} // namespace sync_io\n\n} // namespace wuffs_aux\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__AUX__BASE)\n" +
""
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 82d30ed..ac2284e 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1271,6 +1271,12 @@
return ret;
}
+static inline bool //
+wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
+ return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
+ ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
+}
+
// wuffs_base__slice_u8__subslice_i returns s[i:].
//
// It returns an empty slice if i is out of bounds.
@@ -36065,7 +36071,12 @@
FileInput::CopyIn(IOBuffer* dst) {
if (!m_f) {
return "wuffs_aux::sync_io::FileInput: nullptr file";
- } else if (dst && !dst->meta.closed) {
+ } else if (!dst) {
+ return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
+ } else if (dst->meta.closed) {
+ return "wuffs_aux::sync_io::FileInput: end of file";
+ } else {
+ dst->compact();
size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
dst->meta.wi += n;
dst->meta.closed = feof(m_f);
@@ -36094,7 +36105,16 @@
std::string //
MemoryInput::CopyIn(IOBuffer* dst) {
- if (dst && !dst->meta.closed && (dst != &m_io)) {
+ if (!dst) {
+ return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
+ } else if (dst->meta.closed) {
+ return "wuffs_aux::sync_io::MemoryInput: end of file";
+ } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
+ // Treat m_io's data as immutable, so don't compact dst or otherwise write
+ // to it.
+ return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
+ } else {
+ dst->compact();
size_t nd = dst->writer_length();
size_t ns = m_io.reader_length();
size_t n = (nd < ns) ? nd : ns;