Update wuffs to match the version used by Skia
Change-Id: I4c98412464785f1175af68d6d7ae9f8b1038ace2
diff --git a/cmd/ractool/main.go b/cmd/ractool/main.go
new file mode 100644
index 0000000..c552ba3
--- /dev/null
+++ b/cmd/ractool/main.go
@@ -0,0 +1,148 @@
+// Copyright 2019 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ----------------
+
+// ractool manipulates Random Access Compression (RAC) files.
+package main
+
+import (
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/google/wuffs/lib/raczlib"
+)
+
+// TODO: a flag to use a disk-backed (not memory-backed) TempFile.
+
+var (
+ decodeFlag = flag.Bool("decode", false, "whether to decode the input")
+ encodeFlag = flag.Bool("encode", false, "whether to encode the input")
+
+ codecFlag = flag.String("codec", "zlib", "when encoding, the compression codec")
+ cpagesizeFlag = flag.Uint64("cpagesize", 0, "when encoding, the page size (in CSpace)")
+ cchunksizeFlag = flag.Uint64("cchunksize", 0, "when encoding, the chunk size (in CSpace)")
+ dchunksizeFlag = flag.Uint64("dchunksize", 0, "when encoding, the chunk size (in DSpace)")
+ indexlocationFlag = flag.String("indexlocation", "start",
+ "when encoding, the index location, \"start\" or \"end\"")
+)
+
+const usageStr = `usage: ractool [flags] [input_filename]
+
+If no input_filename is given, stdin is used. Either way, output is written to
+stdout.
+
+The flags should include exactly one of -decode or -encode.
+
+Decoding is not yet implemented.
+
+When encoding, the input is partitioned into chunks and each chunk is
+compressed independently. You can specify the target chunk size in terms of
+either its compressed size or decompressed size. By default (if both
+-cchunksize and -dchunksize are zero), a 64KiB -cchunksize is used.
+
+You can also specify a -cpagesize, which is similar to but not exactly the same
+concept as alignment. If non-zero, padding is inserted into the output to
+minimize the number of pages that each chunk occupies. Look for "CPageSize" in
+the "package rac" documentation for more details.
+
+A RAC file consists of an index and the chunks. The index may be either at the
+start or at the end of the file. See the RAC specification for more details:
+
+https://github.com/google/wuffs/blob/master/doc/spec/rac-spec.md
+
+`
+
+func usage() {
+ fmt.Fprintf(os.Stderr, usageStr)
+ flag.PrintDefaults()
+}
+
+func main() {
+ if err := main1(); err != nil {
+ os.Stderr.WriteString(err.Error() + "\n")
+ os.Exit(1)
+ }
+}
+
+func main1() error {
+ flag.Usage = usage
+ flag.Parse()
+
+ r := io.Reader(os.Stdin)
+ switch flag.NArg() {
+ case 0:
+ // No-op.
+ case 1:
+ f, err := os.Open(flag.Arg(0))
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ r = f
+ default:
+ return errors.New("too many filenames; the maximum is one")
+ }
+
+ if *decodeFlag && !*encodeFlag {
+ return decode(r)
+ }
+ if *encodeFlag && !*decodeFlag {
+ return encode(r)
+ }
+ return errors.New("must specify exactly one of -decode or -encode")
+}
+
+func decode(r io.Reader) error {
+ return errors.New("TODO: implement a decoder")
+}
+
+func encode(r io.Reader) error {
+ indexLocation := raczlib.IndexLocation(0)
+ switch *indexlocationFlag {
+ case "start":
+ indexLocation = raczlib.IndexLocationAtStart
+ case "end":
+ indexLocation = raczlib.IndexLocationAtEnd
+ default:
+ return errors.New("invalid -indexlocation")
+ }
+
+ if (*cchunksizeFlag != 0) && (*dchunksizeFlag != 0) {
+ return errors.New("must specify none or one of -cchunksize or -dchunksize")
+ } else if (*cchunksizeFlag == 0) && (*dchunksizeFlag == 0) {
+ *cchunksizeFlag = 65536 // 64 KiB.
+ }
+
+ switch *codecFlag {
+ case "zlib":
+ w := &raczlib.Writer{
+ Writer: os.Stdout,
+ IndexLocation: indexLocation,
+ TempFile: &bytes.Buffer{},
+ CPageSize: *cpagesizeFlag,
+ CChunkSize: *cchunksizeFlag,
+ DChunkSize: *dchunksizeFlag,
+ }
+ if _, err := io.Copy(w, r); err != nil {
+ return err
+ }
+ return w.Close()
+ }
+ return errors.New("unsupported -codec")
+}
diff --git a/doc/changelog.md b/doc/changelog.md
index 205ad84..3d9501c 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -37,6 +37,7 @@
- Added a `reset` method.
- Added `peek_uxx`, `skip_fast` and `write_fast_uxx` methods.
- Renamed some `read_uxx` methods as `read_uxx_as_uyy`.
+- Report image metadata such as ICCP and XMP.
- Added I/O positions.
- Added extra fields (uninitialized internal buffers) to structs.
- Tweaked how marks and limits work.
@@ -68,4 +69,4 @@
---
-Updated on March 2019.
+Updated on April 2019.
diff --git a/doc/note/README.md b/doc/note/README.md
new file mode 100644
index 0000000..d1ec6fd
--- /dev/null
+++ b/doc/note/README.md
@@ -0,0 +1,2 @@
+This directory contains notes: short articles about various Wuffs concepts that
+aren't specific to any one file format or package.
diff --git a/doc/note/base38-and-fourcc.md b/doc/note/base38-and-fourcc.md
new file mode 100644
index 0000000..dc3c83f
--- /dev/null
+++ b/doc/note/base38-and-fourcc.md
@@ -0,0 +1,53 @@
+# Base38 and FourCC Codes
+
+Both of these encode a four-character string such as `"JPEG"` as a `uint32_t`
+value. Computers can compare two integer values faster than they can compare
+two arbitrary strings.
+
+Both schemes maintain ordering: if two four-character strings `s` and `t`
+satisfy `(s < t)`, and those strings have valid numerical encodings, then the
+numerical values also satisfy `(encoding(s) < encoding(t))`.
+
+
+## FourCC
+
+FourCC codes are not specific to Wuffs. For example, the AVI multimedia
+container format can hold various sub-formats, such as "H264" or "YV12",
+distinguished in the overall file format by their FourCC code.
+
+The FourCC encoding is the straightforward sequence of each character's ASCII
+encoding. The FourCC code for `"JPEG"` is `0x4A504547`, since `'J'` is `0x4A`,
+`'P'` is `0x50`, etc. This is essentially 8 bits for each character, 32 bits
+overall. The big-endian representation of this number is exactly the ASCII (and
+UTF-8) string `"JPEG"`.
+
+Other FourCC documentation sometimes use a little-endian convention, so that
+the `{0x4A, 0x50, 0x45, 0x47}` bytes on the wire for `"JPEG"` corresponds to
+the number `0x4745504A` (little-endian) instead of `0x4A504547` (big-endian).
+Wuffs uses the big-endian interpretation, as it maintains ordering.
+
+
+## Base38
+
+Base38 is a tighter encoding than FourCC, fitting four characters into 21 bits
+instead of 32 bits. This is achieved by using a smaller alphabet of 38 possible
+values (space, 0-9, ? or a-z), so that it cannot distinguish between e.g. an
+upper case 'X' and a lower case 'x'. There's also the happy coincidence that
+`38 ** 4` is slightly smaller than `2 ** 21`.
+
+The base38 encoding of `"JPEG"` is `0x122FF6`, which is `1191926`, which is
+`((21 * (38 ** 3)) + (27 * (38 ** 2)) + (16 * (38 ** 1)) + (18 * (38 ** 0)))`.
+
+Using only 21 bits means that we can use base38 values to partition the set of
+possible `uint32_t` values into file-format specific enumerations. Each package
+(i.e. Wuffs implementation of a specific file format) can define up to 1024
+different values in their own namespace, without conflicting with other
+packages (assuming that there aren't e.g. two `"JPEG"` Wuffs packages in the
+same library). The conventional `uint32_t` packing is:
+
+- Bit 31 is reserved (zero).
+- Bits 30 .. 10 are the base38 value, shifted by 10.
+- Bits 9 .. 0 are the enumeration value.
+
+For example, [quirk values](/doc/note/quirks.md) use this `((base38 << 10) |
+enumeration)` scheme.
diff --git a/doc/note/io-input-output.md b/doc/note/io-input-output.md
new file mode 100644
index 0000000..056ae43
--- /dev/null
+++ b/doc/note/io-input-output.md
@@ -0,0 +1,212 @@
+# I/O (Input / Output)
+
+Wuffs per se doesn't have the ability to read or write to files or network
+connections. Recall that Wuffs is a programming language for writing libraries,
+not applications, and that having fewer capabilities means that it's trivial to
+prove that you can't misuse a capability, even when given malicious input.
+
+Instead, the code that calls into Wuffs libraries is responsible for
+interfacing with e.g. the file system or the network system. An `io_buffer` is
+the mechanism for transferring data into and out of Wuffs libraries. For
+example, when decompressing gzip, there are two `io_buffer`'s: the caller fills
+a source buffer with e.g. the compressed file's contents and the callee (the
+Wuffs library) reads compressed bytes from that source buffer and writes
+decompressed bytes to a destination buffer.
+
+
+## I/O Buffers
+
+An `io_buffer` is a [slice](/doc/note/slices-and-tables.md) of bytes (the data,
+a `ptr` and `len`) with additional fields (the metadata): a read index (`ri`),
+a write index (`wi`), a position (`pos`) and whether or not it is `closed`.
+
+
+## Read Index and Write Index
+
+Writing to an `io_buffer`, e.g. copying from a file to a buffer, increments
+`wi`. The buffer is full for writing (no more can be written) when `wi` equals
+`len`. Writing does not have to fill a buffer before further processing.
+
+Reading from an `io_buffer`, e.g. copying from a buffer to a file, increments
+`ri`. The buffer is empty for reading (no more can be read) when `ri` equals
+`wi`. Reading does not have to empty a buffer before further processing.
+
+An invariant condition is that `((0 <= ri) and (ri <= wi) and (wi <= len))`.
+
+Having separate read and write indexes simplifies connecting a sequence of
+filters or processors with `io_buffer`'s, similar to connecting Unix processes
+with pipes. Each filter reads from the previous buffer and writes to the next
+buffer. Each buffer is written to by the previous filter and is read from by
+the next filter. There's no need to flip a buffer between reading and writing
+modes. Nonetheless, `io_buffer`'s are generally not thread-safe.
+
+Continuing the "decompressing gzip" example, the application would write to the
+source buffer by copying from e.g. `/dev/stdin`. The Wuffs library would read
+from the source buffer and write to the destination buffer. The application
+would read from the destination buffer by copying to e.g. `stdout`. Buffer
+space can be re-used, via compaction (see below), so that neither the source
+(`/dev/stdin`) or destination (`/dev/stdout`) data needs to be entirely in
+memory at any point.
+
+For example, an `io_buffer` of length 8 could have 4 bytes available to read
+and 1 byte available to write. If 1 byte was written, there would then be 5
+bytes available to read. Visually:
+
+```
+[.. .. .. .. .. .. .. ..]
+ |<- ri ->| | |
+ |<------- wi ------->| |
+ |<-------- len -------->|
+```
+
+
+## Position
+
+An `io_buffer` is a sliding window into a stream of bytes. Its position (`pos`)
+is the number of bytes in the stream prior to the first element of the slice.
+The total number of bytes read from and written to the stream are therefore
+`(pos + ri)` and `(pos + wi)`.
+
+While every slice element is in-memory, the stream's prior bytes do not
+necessarily have to be in-memory now, or have been in-memory in the past. It is
+valid to open a file, seek to the 1000'th byte and start copying from there to
+an `io_buffer`, provided that `pos` was also initialized to 1000.
+
+
+## Closed-ness
+
+The `closed` field indicates that no further writes are expected to the
+`io_buffer`. When copying from a file to a buffer, `closed` means that we have
+reached EOF (End Of File).
+
+For example, decoding a particular file format might, at some point, expect at
+least another 4 bytes of data, but only 3 are available to read. If `closed` is
+false, this isn't necessarily an error, since an `io_buffer` holds only a
+partial view of the underlying data stream, and more data might be forthcoming
+but not yet buffered. If `closed` is true, it is definitely an error.
+
+
+## Undoing Reads and Writes
+
+It is possible to decrement `ri` or `wi`, undoing previous reads or writes,
+provided that the invariant `((0 <= ri) and (ri <= wi) and (wi <= len))` holds.
+For example, it can be faster on 64 bit (8 byte) systems, if buffer space is
+available, to write 8 bytes and then undo 1 byte than to write exactly 7 bytes.
+
+The Wuffs compiler enforces that, during a Wuffs function, `ri` and `wi` will
+never be decremented (by an undo operation) to be less than the initial values
+at the time of the call. When considering a function as a 'black box', the two
+indexes can only travel forward, and it is up to the application code (not
+Wuffs library) code to rewind the indexes (e.g. by compaction).
+
+Even though `ri` can not drop below its initial value, Wuffs code can still
+read the contents of the slice before `ri` (in sub-slice notation,
+`data[0:ri]`) and it should still contain the `(pos + 0)`th, `(pos + 1)`th,
+etc. byte of the stream.
+
+The contents of the slice after `wi` (in sub-slice notation, `data[wi:len]`)
+are undefined, and code should not rely on its values. When passing an
+`io_buffer` into a function, that function is free to modify anything in
+`data[wi:len]`, for either value of `wi` before or after the function returns.
+
+
+## Compaction
+
+Compacting an `io_buffer` moves any written but unread bytes (those in
+`data[ri:wi]`) to the start of the buffer, and updates the metadata fields
+`ri`, `wi` and `pos`. Equivalently, it moves the sliding window that is the
+`io_buffer` as far forward as possible along the stream.
+
+This generally increases `(len - wi)`, the number of bytes available for
+writing, allowing for re-using the allocated buffer memory (the data slice).
+
+Suppose that the underlying data stream's `i`th byte has value `i`, and that we
+start with `ri`, `wi` and `pos` were `3`, `7` and `20`. Compaction will
+subtract 3 from the first two and add 3 to the last, so that the new `ri`, `wi`
+and `pos` are `0`, `4` and `23`. Note that `len`, `(pos + ri)` and `(pos + wi)`
+are all unchanged.
+
+Here are two equivalent visualizations of before and after compaction. The `xx`
+means a byte whose value is undefined (as it is at or past `wi`).
+
+The first visualization is where the slice is fixed and its contents (its view
+of the stream) moves relative to the slice:
+
+```
+Before:
+[20 21 22 23 24 25 26 xx]
+ |<- ri ->| | |
+ |<------- wi ------->| |
+ |<-------- len -------->|
+
+After:
+[23 24 25 26 xx xx xx xx]
+ || | |
+ |<-- wi --->| |
+ |<-------- len -------->|
+```
+
+The second visualization is where the stream (and its contents) is fixed and
+the slice (the sliding window) moves relative to the stream:
+
+```
+ pos+ri pos+wi
+ | |
+Before: [20 21 22 23 24 25 26 xx]
+Stream: ... 18 19 20 21 22 23 24 25 26 27 27 28 29 30 31 ...
+After: [23 24 25 26 xx xx xx xx]
+ | |
+ pos+ri pos+wi
+```
+
+
+## Seeking and I/O Positions
+
+Recall that Wuffs code has limited capabilities, and cannot seek in the
+underlying I/O data streams per se. When it needs to seek (e.g. when jumping
+between video frames), it will typically provide an "I/O position", a
+`uint64_t` value, via some package-specific API. The application (the caller of
+the Wuffs code) is then responsible for configuring an `io_buffer` whose
+`(pos + ri)` or `(pos + wi)` value, depending on whether we're reading or
+writing, is at that "I/O position".
+
+If the underlying file (or equivalent) isn't seekable, e.g. it's `/dev/stdin`
+instead of a regular file, then the request cannot be satisfied. The
+application should then decide whether that error is recoverable or fatal. This
+is the application's responsibility, not the library's, as the application
+usually has more context to make that decision.
+
+If that "I/O position" is already within the sliding window, it might not be
+necessary to seek in the underlying file, as it may be possible to e.g. simply
+decrement `ri` to reach a target `(pos + ri)`, for the reading case. Otherwise,
+the typical process is:
+
+1. Set `ri`, `wi` and `pos` to `0`, `0` and that "I/O position". This discards
+ any buffered data (but does not free the buffer's memory).
+2. Seek in the underlying file to that same "I/O position".
+3. Copy from the underlying file to the `io_buffer`, incrementing `wi`.
+
+Whether or not it was necessary to seek and copy from the underlying file, when
+calling back into the Wuffs library, it typically checks that the `io_buffer`'s
+`(pos + ri)` is now at the expected "I/O position".
+
+
+## I/O Reader and I/O Writer
+
+An `io_buffer` is the mechanism for transferring data between the application
+and the Wuffs library. Application code can manipulate an `io_buffer`'s fields
+as it wishes (but is responsible for maintaining the invariant condition).
+Wuffs library code places a further restriction that `io_buffer`s are used
+exclusively either for reading or for writing, as optimizing incremental access
+to an `io_buffer`'s data, while enforcing invariants, is simpler when only one
+of `ri` and `wi` can vary.
+
+Wuffs code therefore refers to either a `base.io_reader` or `base.io_writer`,
+both of which are essentially the same type (an `io_buffer`) with different
+methods. Wuffs code does not reference an `io_buffer` directly.
+
+
+## Binding
+
+TODO: discuss `io_bind`, which temporarily adapts a slice of bytes into an
+`io_buffer`.
diff --git a/doc/note/quirks.md b/doc/note/quirks.md
new file mode 100644
index 0000000..f919da3
--- /dev/null
+++ b/doc/note/quirks.md
@@ -0,0 +1,34 @@
+# Quirks
+
+Quirks are configuration options that let Wuffs more closely match other codec
+implementations.
+
+Some codecs and file formats are more tightly specified than others. When a
+spec doesn't fully dictate how to treat malformed files, different codec
+implementations have disagreed on whether to accept it (e.g. whether they
+follow Postel's Principle of "be liberal in what you accept") and if so, how to
+interpret it. Some implementations also raise those decisions to the
+application level, not the library level: "provide mechanism, not policy".
+
+For example, in an animated GIF image, the first frame might not fill out the
+entire image, and different implementations choose a different default color
+for the outside pixels: opaque black, transparent black, or something else.
+
+Wuffs, out of the box, makes particular choices (typically mimicking the de
+facto canonical implementation), but enabling various quirks result in
+different choices. In particular, quirks are useful in regression testing that
+Wuffs and another implementation produce the same output for the same input,
+even for malformed input.
+
+
+## Wuffs API
+
+Each quirk is assigned a `uint32_t` value, packed using the [base38 namespace
+convention](/doc/note/base38-and-fourcc.md). Decoders and encoders can have a
+`set_quirk_enabled!(quirk base.u32, enabled base.bool)` method whose first
+argument is this `uint32_t` value.
+
+For example, the base38 encoding of `"gif "` is `0xF8586`, so that the
+GIF-specific quirks have a `uint32_t` value of `((0xF8586 << 10) | n)`, for
+some small integer `n`. The generated `C` language file defines human-readable
+names for those constant values.
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c
index 74ff1be..703b968 100644
--- a/example/gifplayer/gifplayer.c
+++ b/example/gifplayer/gifplayer.c
@@ -130,6 +130,7 @@
const char* reset_color = "\x1B[0m";
bool color_flag = false;
+bool quirk_honor_background_color_flag = false;
const int stdout_fd = 1;
static inline uint32_t load_u32le(uint8_t* p) {
@@ -138,7 +139,8 @@
}
void restore_background(wuffs_base__pixel_buffer* pb,
- wuffs_base__rect_ie_u32 bounds) {
+ wuffs_base__rect_ie_u32 bounds,
+ wuffs_base__color_u32_argb_premul background_color) {
size_t width = wuffs_base__pixel_config__width(&pb->pixcfg);
size_t y;
for (y = bounds.min_incl_y; y < bounds.max_excl_y; y++) {
@@ -146,7 +148,7 @@
wuffs_base__color_u32_argb_premul* d =
curr_dst_buffer + (y * width) + bounds.min_incl_x;
for (x = bounds.min_incl_x; x < bounds.max_excl_x; x++) {
- *d++ = 0;
+ *d++ = background_color;
}
}
}
@@ -296,6 +298,11 @@
return status;
}
+ if (quirk_honor_background_color_flag) {
+ wuffs_gif__decoder__set_quirk_enabled(
+ &dec, wuffs_gif__quirk_honor_background_color, true);
+ }
+
wuffs_base__io_buffer src;
src.data.ptr = src_buffer;
src.data.len = src_len;
@@ -303,11 +310,10 @@
src.meta.ri = 0;
src.meta.pos = 0;
src.meta.closed = true;
- wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
if (first_play) {
wuffs_base__image_config ic = {0};
- status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+ status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
if (status) {
return status;
}
@@ -334,13 +340,12 @@
return status;
}
memset(pixbuf.ptr, 0, pixbuf.len);
- memset(curr_dst_buffer, 0, dst_len);
}
while (1) {
wuffs_base__frame_config fc = {0};
wuffs_base__status status =
- wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+ wuffs_gif__decoder__decode_frame_config(&dec, &fc, &src);
if (status) {
if (status == wuffs_base__warning__end_of_data) {
break;
@@ -348,6 +353,16 @@
return status;
}
+ if (wuffs_base__frame_config__index(&fc) == 0) {
+ wuffs_base__color_u32_argb_premul background_color =
+ wuffs_base__frame_config__background_color(&fc);
+ size_t i;
+ size_t n = dst_len / sizeof(wuffs_base__color_u32_argb_premul);
+ for (i = 0; i < n; i++) {
+ curr_dst_buffer[i] = background_color;
+ }
+ }
+
switch (wuffs_base__frame_config__disposal(&fc)) {
case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS: {
memcpy(prev_dst_buffer, curr_dst_buffer, dst_len);
@@ -355,8 +370,7 @@
}
}
- status =
- wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader, workbuf, NULL);
+ status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src, workbuf, NULL);
if (status) {
if (status == wuffs_base__warning__end_of_data) {
break;
@@ -370,7 +384,8 @@
switch (wuffs_base__frame_config__disposal(&fc)) {
case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND: {
- restore_background(&pb, wuffs_base__frame_config__bounds(&fc));
+ restore_background(&pb, wuffs_base__frame_config__bounds(&fc),
+ wuffs_base__frame_config__background_color(&fc));
break;
}
case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS: {
@@ -423,6 +438,9 @@
if (!strcmp(argv[i], "-color")) {
color_flag = true;
}
+ if (!strcmp(argv[i], "-quirk_honor_background_color")) {
+ quirk_honor_background_color_flag = true;
+ }
}
const char* status = read_stdin();
diff --git a/example/library/library.c b/example/library/library.c
index 8726ca3..f8e258a 100644
--- a/example/library/library.c
+++ b/example/library/library.c
@@ -93,9 +93,6 @@
src.meta.pos = 0;
src.meta.closed = true;
- wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&dst);
- wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
-
wuffs_gzip__decoder* dec =
(wuffs_gzip__decoder*)(calloc(sizeof__wuffs_gzip__decoder(), 1));
if (!dec) {
@@ -109,7 +106,7 @@
return status;
}
status = wuffs_gzip__decoder__decode_io_writer(
- dec, dst_writer, src_reader,
+ dec, &dst, &src,
wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
if (status) {
free(dec);
diff --git a/example/zcat/zcat.c b/example/zcat/zcat.c
index c2bf06a..20d7fe4 100644
--- a/example/zcat/zcat.c
+++ b/example/zcat/zcat.c
@@ -124,8 +124,7 @@
while (true) {
status = wuffs_gzip__decoder__decode_io_writer(
- &dec, wuffs_base__io_buffer__writer(&dst),
- wuffs_base__io_buffer__reader(&src),
+ &dec, &dst, &src,
wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
if (dst.meta.wi) {
diff --git a/fuzz/c/fuzzlib/fuzzlib.c b/fuzz/c/fuzzlib/fuzzlib.c
index 03050f9..a91e1e4 100644
--- a/fuzz/c/fuzzlib/fuzzlib.c
+++ b/fuzz/c/fuzzlib/fuzzlib.c
@@ -27,7 +27,7 @@
*intentional_segfault_ptr = 0;
}
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash);
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash);
static const char* llvmFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Hash input as per https://en.wikipedia.org/wiki/Jenkins_hash_function
@@ -55,7 +55,7 @@
}),
});
- const char* msg = fuzz(wuffs_base__io_buffer__reader(&src), hash);
+ const char* msg = fuzz(&src, hash);
if (msg && strstr(msg, "internal error:")) {
fprintf(stderr, "internal errors shouldn't occur: \"%s\"\n", msg);
intentional_segfault();
diff --git a/fuzz/c/std/gif_fuzzer.c b/fuzz/c/std/gif_fuzzer.c
index c3ce2fd..2858c1c 100644
--- a/fuzz/c/std/gif_fuzzer.c
+++ b/fuzz/c/std/gif_fuzzer.c
@@ -48,7 +48,7 @@
#include "../../../release/c/wuffs-unsupported-snapshot.c"
#include "../fuzzlib/fuzzlib.c"
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash) {
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash) {
const char* ret = NULL;
wuffs_base__slice_u8 pixbuf = ((wuffs_base__slice_u8){});
wuffs_base__slice_u8 workbuf = ((wuffs_base__slice_u8){});
@@ -67,7 +67,7 @@
}
wuffs_base__image_config ic = ((wuffs_base__image_config){});
- status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+ status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src);
if (status) {
ret = status;
goto exit;
@@ -115,7 +115,7 @@
bool seen_ok = false;
while (true) {
wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
- status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src_reader);
+ status = wuffs_gif__decoder__decode_frame_config(&dec, &fc, src);
if (status) {
if ((status != wuffs_base__warning__end_of_data) || !seen_ok) {
ret = status;
@@ -123,8 +123,7 @@
goto exit;
}
- status = wuffs_gif__decoder__decode_frame(&dec, &pb, src_reader, workbuf,
- NULL);
+ status = wuffs_gif__decoder__decode_frame(&dec, &pb, src, workbuf, NULL);
wuffs_base__rect_ie_u32 frame_rect =
wuffs_base__frame_config__bounds(&fc);
diff --git a/fuzz/c/std/zlib_fuzzer.c b/fuzz/c/std/zlib_fuzzer.c
index ffded01..b452582 100644
--- a/fuzz/c/std/zlib_fuzzer.c
+++ b/fuzz/c/std/zlib_fuzzer.c
@@ -60,7 +60,7 @@
uint8_t work_buffer[1];
#endif
-const char* fuzz(wuffs_base__io_reader src_reader, uint32_t hash) {
+const char* fuzz(wuffs_base__io_buffer* src, uint32_t hash) {
wuffs_zlib__decoder dec;
const char* status = wuffs_zlib__decoder__initialize(
&dec, sizeof dec, WUFFS_VERSION,
@@ -81,11 +81,10 @@
.len = DST_BUFFER_SIZE,
}),
});
- wuffs_base__io_writer dst_writer = wuffs_base__io_buffer__writer(&dst);
while (true) {
dst.meta.wi = 0;
- status = wuffs_zlib__decoder__decode_io_writer(&dec, dst_writer, src_reader,
+ status = wuffs_zlib__decoder__decode_io_writer(&dec, &dst, src,
((wuffs_base__slice_u8){
.ptr = work_buffer,
.len = WORK_BUFFER_SIZE,
diff --git a/go.mod b/go.mod
index 3279328..4ec9849 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
module github.com/google/wuffs
-go 1.13
+go 1.12
diff --git a/internal/cgen/base/core-public.h b/internal/cgen/base/core-public.h
index dc7e7fb..f642fb7 100644
--- a/internal/cgen/base/core-public.h
+++ b/internal/cgen/base/core-public.h
@@ -197,6 +197,12 @@
// --------
+// FourCC constants.
+
+// !! INSERT FourCCs.
+
+// --------
+
// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
// second. See https://github.com/OculusVR/Flicks
typedef int64_t wuffs_base__flicks;
diff --git a/internal/cgen/base/image-impl.c b/internal/cgen/base/image-impl.c
index 6674c4a..7f62677 100644
--- a/internal/cgen/base/image-impl.c
+++ b/internal/cgen/base/image-impl.c
@@ -29,6 +29,61 @@
}
static uint64_t //
+wuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
+ if (dst_palette.len != 1024) {
+ return 0;
+ }
+ size_t dst_len3 = dst.len / 3;
+ size_t len = dst_len3 < src.len ? dst_len3 : src.len;
+ uint8_t* d = dst.ptr;
+ uint8_t* s = src.ptr;
+ size_t n = len;
+
+ // N is the loop unroll count.
+ const int N = 4;
+
+ // The comparison in the while condition is ">", not ">=", because with ">=",
+ // the last 4-byte store could write past the end of the dst slice.
+ //
+ // Each 4-byte store writes one too many bytes, but a subsequent store will
+ // overwrite that with the correct byte. There is always another store,
+ // whether a 4-byte store in this loop or a 1-byte store in the next loop.
+ while (n > N) {
+ wuffs_base__store_u32le(
+ d + (0 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));
+ wuffs_base__store_u32le(
+ d + (1 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));
+ wuffs_base__store_u32le(
+ d + (2 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));
+ wuffs_base__store_u32le(
+ d + (3 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));
+
+ s += 1 * N;
+ d += 3 * N;
+ n -= (size_t)(1 * N);
+ }
+
+ while (n >= 1) {
+ uint32_t color =
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));
+ d[0] = (uint8_t)(color >> 0);
+ d[1] = (uint8_t)(color >> 8);
+ d[2] = (uint8_t)(color >> 16);
+
+ s += 1 * 1;
+ d += 3 * 1;
+ n -= (size_t)(1 * 1);
+ }
+
+ return len;
+}
+static uint64_t //
wuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) {
@@ -39,8 +94,9 @@
size_t len = dst_len4 < src.len ? dst_len4 : src.len;
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
-
size_t n = len;
+
+ // N is the loop unroll count.
const int N = 4;
while (n >= N) {
@@ -98,14 +154,14 @@
return len4 * 4;
}
-void //
+wuffs_base__status //
wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette) {
if (!p) {
- return;
+ return wuffs_base__error__bad_receiver;
}
// TODO: support many more formats.
@@ -125,6 +181,13 @@
}
func = wuffs_base__pixel_swizzler__copy_1_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
+ 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
@@ -134,6 +197,13 @@
}
func = wuffs_base__pixel_swizzler__copy_4_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,
+ src_palette) != 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
@@ -153,13 +223,15 @@
}
p->private_impl.func = func;
+ return func ? NULL : wuffs_base__error__unsupported_option;
}
uint64_t //
-wuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,
- wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src) {
+wuffs_base__pixel_swizzler__swizzle_interleaved(
+ const wuffs_base__pixel_swizzler* p,
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
if (p && p->private_impl.func) {
return (*(p->private_impl.func))(dst, dst_palette, src);
}
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h
index f452b3b..0a18365 100644
--- a/internal/cgen/base/image-public.h
+++ b/internal/cgen/base/image-public.h
@@ -33,9 +33,9 @@
// - bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).
// - bit 19 indicates floating point (as opposed to integer).
// - bit 18 indicates palette-indexed. The number-of-planes (the next
-// field) will be zero, as the format is considered packed,
+// field) will be 0, as the format is considered interleaved,
// but the 8-bit N-BGRA color data is stored in plane 3.
-// - bits 17 .. 16 are the number of planes, minus 1. Zero means packed.
+// - bits 17 .. 16 are the number of planes, minus 1. Zero means interleaved.
// - bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.
// - bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.
// - bits 7 .. 4 encodes the number of bits (depth) in the 1st channel.
@@ -52,14 +52,14 @@
// channels: cyan, magenta, yellow, black).
//
// For direct formats with N > 1 channels, those channels can be laid out in
-// either 1 (packed) or N (planar) planes. For example, RGBA data is usually
-// packed, but YCbCr data is usually planar, due to chroma subsampling (for
-// details, see the wuffs_base__pixel_subsampling type).
+// either 1 (interleaved) or N (planar) planes. For example, RGBA data is
+// usually interleaved, but YCbCr data is usually planar, due to chroma
+// subsampling (for details, see the wuffs_base__pixel_subsampling type).
//
// For indexed formats, the palette (always 256 × 4 bytes) holds 8 bits per
// channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for
-// the index), as the format is considered packed. Plane 0 holds the per-pixel
-// indices. Plane 3 is re-purposed to hold the per-index colors.
+// the index), as the format is considered interleaved. Plane 0 holds the
+// per-pixel indices. Plane 3 is re-purposed to hold the per-index colors.
//
// The color field is encoded in 3 bits:
// - 0 means A (Alpha).
@@ -73,8 +73,8 @@
//
// In Wuffs, channels are given in memory order (also known as byte order),
// regardless of endianness, since the C type for the pixel data is an array of
-// bytes, not an array of uint32_t. For example, packed BGRA with 8 bits per
-// channel means that the bytes in memory are always Blue, Green, Red then
+// bytes, not an array of uint32_t. For example, interleaved BGRA with 8 bits
+// per channel means that the bytes in memory are always Blue, Green, Red then
// Alpha. On big-endian systems, that is the uint32_t 0xBBGGRRAA. On
// little-endian, 0xAARRGGBB.
//
@@ -107,15 +107,15 @@
//
// For example, wuffs_base__pixel_format 0x5510BBBB is a natural format for
// decoding a PNG image - network byte order (also known as big-endian),
-// packed, non-premultiplied alpha - that happens to be 16-bit-depth truecolor
-// with alpha (RGBA). In memory order:
+// interleaved, non-premultiplied alpha - that happens to be 16-bit-depth
+// truecolor with alpha (RGBA). In memory order:
//
// ptr+0 ptr+1 ptr+2 ptr+3 ptr+4 ptr+5 ptr+6 ptr+7
// Rhi Rlo Ghi Glo Bhi Blo Ahi Alo
//
// For example, the value wuffs_base__pixel_format 0x40000565 means BGR with no
-// alpha or padding, 5/6/5 bits for blue/green/red, packed 2 bytes per pixel,
-// laid out LSB-first in memory order:
+// alpha or padding, 5/6/5 bits for blue/green/red, interleaved 2 bytes per
+// pixel, laid out LSB-first in memory order:
//
// ptr+0........... ptr+1...........
// MSB LSB MSB LSB
@@ -200,8 +200,8 @@
return f != 0;
}
-// wuffs_base__pixel_format__bits_per_pixel returns, for packed pixel formats,
-// the number of bits per pixel. It returns 0 for planar pixel formats.
+// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per
+// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.
static inline uint32_t //
wuffs_base__pixel_format__bits_per_pixel(wuffs_base__pixel_format f) {
if (((f >> 16) & 0x03) != 0) {
@@ -219,7 +219,7 @@
}
static inline bool //
-wuffs_base__pixel_format__is_packed(wuffs_base__pixel_format f) {
+wuffs_base__pixel_format__is_interleaved(wuffs_base__pixel_format f) {
return ((f >> 16) & 0x03) == 0;
}
@@ -245,7 +245,7 @@
// plane p. For a depth of 8 bits (1 byte), the p'th plane's sample starts at
// (planes[p].ptr + (j * planes[p].stride) + i).
//
-// For packed pixel formats, the mapping is trivial: i = x and j = y. For
+// For interleaved pixel formats, the mapping is trivial: i = x and j = y. For
// planar pixel formats, the mapping can differ due to chroma subsampling. For
// example, consider a three plane YCbCr pixel format with 4:2:2 subsampling.
// For the luma (Y) channel, there is one sample for every pixel, but for the
@@ -336,13 +336,13 @@
uint32_t width,
uint32_t height);
inline void invalidate();
- inline bool is_valid();
- inline wuffs_base__pixel_format pixel_format();
- inline wuffs_base__pixel_subsampling pixel_subsampling();
- inline wuffs_base__rect_ie_u32 bounds();
- inline uint32_t width();
- inline uint32_t height();
- inline uint64_t pixbuf_len();
+ inline bool is_valid() const;
+ inline wuffs_base__pixel_format pixel_format() const;
+ inline wuffs_base__pixel_subsampling pixel_subsampling() const;
+ inline wuffs_base__rect_ie_u32 bounds() const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
+ inline uint64_t pixbuf_len() const;
#endif // __cplusplus
} wuffs_base__pixel_config;
@@ -396,22 +396,22 @@
}
static inline bool //
-wuffs_base__pixel_config__is_valid(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {
return c && c->private_impl.pixfmt;
}
static inline wuffs_base__pixel_format //
-wuffs_base__pixel_config__pixel_format(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixfmt : 0;
}
static inline wuffs_base__pixel_subsampling //
-wuffs_base__pixel_config__pixel_subsampling(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixsub : 0;
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__pixel_config__bounds(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {
if (c) {
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = 0;
@@ -430,20 +430,20 @@
}
static inline uint32_t //
-wuffs_base__pixel_config__width(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.width : 0;
}
static inline uint32_t //
-wuffs_base__pixel_config__height(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.height : 0;
}
-// TODO: this is the right API for planar (not packed) pixbufs? Should it allow
-// decoding into a color model different from the format's intrinsic one? For
-// example, decoding a JPEG image straight to RGBA instead of to YCbCr?
+// TODO: this is the right API for planar (not interleaved) pixbufs? Should it
+// allow decoding into a color model different from the format's intrinsic one?
+// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?
static inline uint64_t //
-wuffs_base__pixel_config__pixbuf_len(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {
if (!c) {
return 0;
}
@@ -492,37 +492,37 @@
}
inline bool //
-wuffs_base__pixel_config::is_valid() {
+wuffs_base__pixel_config::is_valid() const {
return wuffs_base__pixel_config__is_valid(this);
}
inline wuffs_base__pixel_format //
-wuffs_base__pixel_config::pixel_format() {
+wuffs_base__pixel_config::pixel_format() const {
return wuffs_base__pixel_config__pixel_format(this);
}
inline wuffs_base__pixel_subsampling //
-wuffs_base__pixel_config::pixel_subsampling() {
+wuffs_base__pixel_config::pixel_subsampling() const {
return wuffs_base__pixel_config__pixel_subsampling(this);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__pixel_config::bounds() {
+wuffs_base__pixel_config::bounds() const {
return wuffs_base__pixel_config__bounds(this);
}
inline uint32_t //
-wuffs_base__pixel_config::width() {
+wuffs_base__pixel_config::width() const {
return wuffs_base__pixel_config__width(this);
}
inline uint32_t //
-wuffs_base__pixel_config::height() {
+wuffs_base__pixel_config::height() const {
return wuffs_base__pixel_config__height(this);
}
inline uint64_t //
-wuffs_base__pixel_config::pixbuf_len() {
+wuffs_base__pixel_config::pixbuf_len() const {
return wuffs_base__pixel_config__pixbuf_len(this);
}
@@ -548,9 +548,9 @@
uint64_t first_frame_io_position,
bool first_frame_is_opaque);
inline void invalidate();
- inline bool is_valid();
- inline uint64_t first_frame_io_position();
- inline bool first_frame_is_opaque();
+ inline bool is_valid() const;
+ inline uint64_t first_frame_io_position() const;
+ inline bool first_frame_is_opaque() const;
#endif // __cplusplus
} wuffs_base__image_config;
@@ -607,17 +607,19 @@
}
static inline bool //
-wuffs_base__image_config__is_valid(wuffs_base__image_config* c) {
+wuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {
return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));
}
static inline uint64_t //
-wuffs_base__image_config__first_frame_io_position(wuffs_base__image_config* c) {
+wuffs_base__image_config__first_frame_io_position(
+ const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_io_position : 0;
}
static inline bool //
-wuffs_base__image_config__first_frame_is_opaque(wuffs_base__image_config* c) {
+wuffs_base__image_config__first_frame_is_opaque(
+ const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_is_opaque : false;
}
@@ -640,17 +642,17 @@
}
inline bool //
-wuffs_base__image_config::is_valid() {
+wuffs_base__image_config::is_valid() const {
return wuffs_base__image_config__is_valid(this);
}
inline uint64_t //
-wuffs_base__image_config::first_frame_io_position() {
+wuffs_base__image_config::first_frame_io_position() const {
return wuffs_base__image_config__first_frame_io_position(this);
}
inline bool //
-wuffs_base__image_config::first_frame_is_opaque() {
+wuffs_base__image_config::first_frame_is_opaque() const {
return wuffs_base__image_config__first_frame_is_opaque(this);
}
@@ -706,6 +708,7 @@
uint64_t io_position;
wuffs_base__animation_blend blend;
wuffs_base__animation_disposal disposal;
+ wuffs_base__color_u32_argb_premul background_color;
} private_impl;
#ifdef __cplusplus
@@ -714,15 +717,17 @@
uint64_t index,
uint64_t io_position,
wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal);
- inline wuffs_base__rect_ie_u32 bounds();
- inline uint32_t width();
- inline uint32_t height();
- inline wuffs_base__flicks duration();
- inline uint64_t index();
- inline uint64_t io_position();
- inline wuffs_base__animation_blend blend();
- inline wuffs_base__animation_disposal disposal();
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color);
+ inline wuffs_base__rect_ie_u32 bounds() const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
+ inline wuffs_base__flicks duration() const;
+ inline uint64_t index() const;
+ inline uint64_t io_position() const;
+ inline wuffs_base__animation_blend blend() const;
+ inline wuffs_base__animation_disposal disposal() const;
+ inline wuffs_base__color_u32_argb_premul background_color() const;
#endif // __cplusplus
} wuffs_base__frame_config;
@@ -740,13 +745,15 @@
}
static inline void //
-wuffs_base__frame_config__update(wuffs_base__frame_config* c,
- wuffs_base__rect_ie_u32 bounds,
- wuffs_base__flicks duration,
- uint64_t index,
- uint64_t io_position,
- wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal) {
+wuffs_base__frame_config__update(
+ wuffs_base__frame_config* c,
+ wuffs_base__rect_ie_u32 bounds,
+ wuffs_base__flicks duration,
+ uint64_t index,
+ uint64_t io_position,
+ wuffs_base__animation_blend blend,
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color) {
if (!c) {
return;
}
@@ -757,10 +764,11 @@
c->private_impl.io_position = io_position;
c->private_impl.blend = blend;
c->private_impl.disposal = disposal;
+ c->private_impl.background_color = background_color;
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__frame_config__bounds(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {
if (c) {
return c->private_impl.bounds;
}
@@ -774,103 +782,115 @@
}
static inline uint32_t //
-wuffs_base__frame_config__width(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__width(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;
}
static inline uint32_t //
-wuffs_base__frame_config__height(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__height(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;
}
// wuffs_base__frame_config__duration returns the amount of time to display
// this frame. Zero means to display forever - a still (non-animated) image.
static inline wuffs_base__flicks //
-wuffs_base__frame_config__duration(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {
return c ? c->private_impl.duration : 0;
}
// wuffs_base__frame_config__index returns the index of this frame. The first
// frame in an image has index 0, the second frame has index 1, and so on.
static inline uint64_t //
-wuffs_base__frame_config__index(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__index(const wuffs_base__frame_config* c) {
return c ? c->private_impl.index : 0;
}
// wuffs_base__frame_config__io_position returns the I/O stream position before
// the frame config.
static inline uint64_t //
-wuffs_base__frame_config__io_position(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {
return c ? c->private_impl.io_position : 0;
}
// wuffs_base__frame_config__blend returns, for an animated image, how to blend
// the transparent pixels of this frame with the existing canvas.
static inline wuffs_base__animation_blend //
-wuffs_base__frame_config__blend(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {
return c ? c->private_impl.blend : 0;
}
// wuffs_base__frame_config__disposal returns, for an animated image, how to
// dispose of this frame after displaying it.
static inline wuffs_base__animation_disposal //
-wuffs_base__frame_config__disposal(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {
return c ? c->private_impl.disposal : 0;
}
+static inline wuffs_base__color_u32_argb_premul //
+wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
+ return c ? c->private_impl.background_color : 0;
+}
+
#ifdef __cplusplus
inline void //
-wuffs_base__frame_config::update(wuffs_base__rect_ie_u32 bounds,
- wuffs_base__flicks duration,
- uint64_t index,
- uint64_t io_position,
- wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal) {
+wuffs_base__frame_config::update(
+ wuffs_base__rect_ie_u32 bounds,
+ wuffs_base__flicks duration,
+ uint64_t index,
+ uint64_t io_position,
+ wuffs_base__animation_blend blend,
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color) {
wuffs_base__frame_config__update(this, bounds, duration, index, io_position,
- blend, disposal);
+ blend, disposal, background_color);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__frame_config::bounds() {
+wuffs_base__frame_config::bounds() const {
return wuffs_base__frame_config__bounds(this);
}
inline uint32_t //
-wuffs_base__frame_config::width() {
+wuffs_base__frame_config::width() const {
return wuffs_base__frame_config__width(this);
}
inline uint32_t //
-wuffs_base__frame_config::height() {
+wuffs_base__frame_config::height() const {
return wuffs_base__frame_config__height(this);
}
inline wuffs_base__flicks //
-wuffs_base__frame_config::duration() {
+wuffs_base__frame_config::duration() const {
return wuffs_base__frame_config__duration(this);
}
inline uint64_t //
-wuffs_base__frame_config::index() {
+wuffs_base__frame_config::index() const {
return wuffs_base__frame_config__index(this);
}
inline uint64_t //
-wuffs_base__frame_config::io_position() {
+wuffs_base__frame_config::io_position() const {
return wuffs_base__frame_config__io_position(this);
}
inline wuffs_base__animation_blend //
-wuffs_base__frame_config::blend() {
+wuffs_base__frame_config::blend() const {
return wuffs_base__frame_config__blend(this);
}
inline wuffs_base__animation_disposal //
-wuffs_base__frame_config::disposal() {
+wuffs_base__frame_config::disposal() const {
return wuffs_base__frame_config__disposal(this);
}
+inline wuffs_base__color_u32_argb_premul //
+wuffs_base__frame_config::background_color() const {
+ return wuffs_base__frame_config__background_color(this);
+}
+
#endif // __cplusplus
// --------
@@ -888,8 +908,10 @@
#ifdef __cplusplus
inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,
wuffs_base__slice_u8 pixbuf_memory);
+ inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory);
inline wuffs_base__slice_u8 palette();
- inline wuffs_base__pixel_format pixel_format();
+ inline wuffs_base__pixel_format pixel_format() const;
inline wuffs_base__table_u8 plane(uint32_t p);
#endif // __cplusplus
@@ -919,12 +941,13 @@
}
if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
// TODO: support planar pixel formats, concious of pixel subsampling.
- return wuffs_base__error__bad_argument;
+ return wuffs_base__error__unsupported_option;
}
uint32_t bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
- return wuffs_base__error__bad_argument;
+ // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+ return wuffs_base__error__unsupported_option;
}
uint64_t bytes_per_pixel = bits_per_pixel / 8;
@@ -970,6 +993,38 @@
return NULL;
}
+static inline wuffs_base__status //
+wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,
+ wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory) {
+ if (!b) {
+ return wuffs_base__error__bad_receiver;
+ }
+ memset(b, 0, sizeof(*b));
+ if (!pixcfg ||
+ wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
+ return wuffs_base__error__bad_argument;
+ }
+ uint32_t bits_per_pixel =
+ wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
+ if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
+ // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+ return wuffs_base__error__unsupported_option;
+ }
+ uint64_t bytes_per_pixel = bits_per_pixel / 8;
+
+ uint64_t width_in_bytes =
+ ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
+ if ((width_in_bytes > pixbuf_memory.width) ||
+ (pixcfg->private_impl.height > pixbuf_memory.height)) {
+ return wuffs_base__error__bad_argument;
+ }
+
+ b->pixcfg = *pixcfg;
+ b->private_impl.planes[0] = pixbuf_memory;
+ return NULL;
+}
+
// wuffs_base__pixel_buffer__palette returns the palette color data. If
// non-empty, it will have length 1024.
static inline wuffs_base__slice_u8 //
@@ -986,7 +1041,7 @@
}
static inline wuffs_base__pixel_format //
-wuffs_base__pixel_buffer__pixel_format(wuffs_base__pixel_buffer* b) {
+wuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {
if (b) {
return b->pixcfg.private_impl.pixfmt;
}
@@ -1015,13 +1070,19 @@
return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);
}
+inline wuffs_base__status //
+wuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory) {
+ return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);
+}
+
inline wuffs_base__slice_u8 //
wuffs_base__pixel_buffer::palette() {
return wuffs_base__pixel_buffer__palette(this);
}
inline wuffs_base__pixel_format //
-wuffs_base__pixel_buffer::pixel_format() {
+wuffs_base__pixel_buffer::pixel_format() const {
return wuffs_base__pixel_buffer__pixel_format(this);
}
@@ -1063,20 +1124,18 @@
} private_impl;
#ifdef __cplusplus
- inline void prepare(wuffs_base__pixel_format dst_format,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__pixel_format src_format,
- wuffs_base__slice_u8 src_palette);
- inline uint64_t swizzle_packed(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src);
+ inline wuffs_base__status prepare(wuffs_base__pixel_format dst_format,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__pixel_format src_format,
+ wuffs_base__slice_u8 src_palette);
+ inline uint64_t swizzle_interleaved(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) const;
#endif // __cplusplus
} wuffs_base__pixel_swizzler;
-// TODO: should prepare (both the C and C++ methods) return a status?
-
-void //
+wuffs_base__status //
wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
@@ -1084,28 +1143,30 @@
wuffs_base__slice_u8 src_palette);
uint64_t //
-wuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,
- wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src);
+wuffs_base__pixel_swizzler__swizzle_interleaved(
+ const wuffs_base__pixel_swizzler* p,
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src);
#ifdef __cplusplus
-inline void //
+inline wuffs_base__status //
wuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette) {
- wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette, src_format,
- src_palette);
+ return wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette,
+ src_format, src_palette);
}
uint64_t //
-wuffs_base__pixel_swizzler::swizzle_packed(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src) {
- return wuffs_base__pixel_swizzler__swizzle_packed(this, dst, dst_palette,
- src);
+wuffs_base__pixel_swizzler::swizzle_interleaved(
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) const {
+ return wuffs_base__pixel_swizzler__swizzle_interleaved(this, dst, dst_palette,
+ src);
}
#endif // __cplusplus
diff --git a/internal/cgen/base/io-private.h b/internal/cgen/base/io-private.h
index 088f3ce..fad529b 100644
--- a/internal/cgen/base/io-private.h
+++ b/internal/cgen/base/io-private.h
@@ -16,65 +16,52 @@
// ---------------- I/O
-static inline bool //
-wuffs_base__io_buffer__is_valid(wuffs_base__io_buffer buf) {
- return (buf.data.ptr || (buf.data.len == 0)) &&
- (buf.data.len >= buf.meta.wi) && (buf.meta.wi >= buf.meta.ri);
-}
-
-// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but
-// it might be handy to programs that use Wuffs. Either delete it, or promote
-// it to the public API.
+// "Null" as in "/dev/null", not as in "nullptr".
//
-// If making this function public (i.e. moving it to base-header.h), it also
-// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
+// TODO: ensure that this is zero-initialized.
+static wuffs_base__io_buffer wuffs_base__global__null_io_buffer;
-static inline bool //
-wuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- return buf && buf->meta.closed &&
- (buf->data.ptr + buf->meta.wi == o.private_impl.limit);
+static inline wuffs_base__io_buffer* //
+wuffs_base__null_io_reader() {
+ return &wuffs_base__global__null_io_buffer;
}
-static inline bool //
-wuffs_base__io_reader__is_valid(wuffs_base__io_reader o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- // Note: if making this function public (i.e. moving it to base-header.h), it
- // also needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
- return buf ? ((buf->data.ptr <= o.private_impl.mark) &&
- (o.private_impl.mark <= o.private_impl.limit) &&
- (o.private_impl.limit <= buf->data.ptr + buf->data.len))
- : ((o.private_impl.mark == NULL) &&
- (o.private_impl.limit == NULL));
+static inline wuffs_base__io_buffer* //
+wuffs_base__null_io_writer() {
+ return &wuffs_base__global__null_io_buffer;
}
-static inline bool //
-wuffs_base__io_writer__is_valid(wuffs_base__io_writer o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- // Note: if making this function public (i.e. moving it to base-header.h), it
- // also needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
- return buf ? ((buf->data.ptr <= o.private_impl.mark) &&
- (o.private_impl.mark <= o.private_impl.limit) &&
- (o.private_impl.limit <= buf->data.ptr + buf->data.len))
- : ((o.private_impl.mark == NULL) &&
- (o.private_impl.limit == NULL));
+static inline uint64_t //
+wuffs_base__io__count_since(uint64_t mark, uint64_t index) {
+ if (index >= mark) {
+ return index - mark;
+ }
+ return 0;
+}
+
+static inline wuffs_base__slice_u8 //
+wuffs_base__io__since(uint64_t mark, uint64_t index, uint8_t* ptr) {
+ if (index >= mark) {
+ return wuffs_base__make_slice_u8(ptr + mark, index - mark);
+ }
+ return wuffs_base__make_slice_u8(NULL, 0);
}
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,
- uint8_t* io0_w,
uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint32_t distance) {
if (!distance) {
return 0;
}
uint8_t* p = *ptr_iop_w;
- if ((size_t)(p - io0_w) < (size_t)(distance)) {
+ if ((size_t)(p - io1_w) < (size_t)(distance)) {
return 0;
}
uint8_t* q = p - distance;
- size_t n = (size_t)(io1_w - p);
+ size_t n = (size_t)(io2_w - p);
if ((size_t)(length) > n) {
length = (uint32_t)(n);
} else {
@@ -106,12 +93,12 @@
// wuffs_base__io_writer__copy_n_from_history function above, but has stronger
// pre-conditions. The caller needs to prove that:
// - distance > 0
-// - distance <= (*ptr_iop_w - io0_w)
-// - length <= (io1_w - *ptr_iop_w)
+// - distance <= (*ptr_iop_w - io1_w)
+// - length <= (io2_w - *ptr_iop_w)
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,
- uint8_t* io0_w,
uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint32_t distance) {
uint8_t* p = *ptr_iop_w;
@@ -131,18 +118,18 @@
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint8_t** ptr_iop_r,
- uint8_t* io1_r) {
+ uint8_t* io2_r) {
uint8_t* iop_w = *ptr_iop_w;
size_t n = length;
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
uint8_t* iop_r = *ptr_iop_r;
- if (n > ((size_t)(io1_r - iop_r))) {
- n = (size_t)(io1_r - iop_r);
+ if (n > ((size_t)(io2_r - iop_r))) {
+ n = (size_t)(io2_r - iop_r);
}
if (n > 0) {
memmove(iop_w, iop_r, n);
@@ -154,12 +141,12 @@
static inline uint64_t //
wuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
wuffs_base__slice_u8 src) {
uint8_t* iop_w = *ptr_iop_w;
size_t n = src.len;
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
if (n > 0) {
memmove(iop_w, src.ptr, n);
@@ -170,7 +157,7 @@
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
wuffs_base__slice_u8 src) {
uint8_t* iop_w = *ptr_iop_w;
@@ -178,8 +165,8 @@
if (n > length) {
n = length;
}
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
if (n > 0) {
memmove(iop_w, src.ptr, n);
@@ -188,11 +175,12 @@
return (uint32_t)(n);
}
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set(wuffs_base__io_reader* o,
- wuffs_base__io_buffer* b,
+static inline wuffs_base__io_buffer* //
+wuffs_base__io_reader__set(wuffs_base__io_buffer* b,
uint8_t** ptr_iop_r,
+ uint8_t** ptr_io0_r,
uint8_t** ptr_io1_r,
+ uint8_t** ptr_io2_r,
wuffs_base__slice_u8 data) {
b->data = data;
b->meta.wi = data.len;
@@ -200,42 +188,17 @@
b->meta.pos = 0;
b->meta.closed = false;
- o->private_impl.buf = b;
- o->private_impl.mark = data.ptr;
- o->private_impl.limit = data.ptr + data.len;
*ptr_iop_r = data.ptr;
- *ptr_io1_r = data.ptr + data.len;
+ *ptr_io0_r = data.ptr;
+ *ptr_io1_r = data.ptr;
+ *ptr_io2_r = data.ptr + data.len;
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set_limit(wuffs_base__io_reader* o,
- uint8_t* iop_r,
- uint64_t limit) {
- if (o && (((size_t)(o->private_impl.limit - iop_r)) > limit)) {
- o->private_impl.limit = iop_r + limit;
- }
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set_mark(wuffs_base__io_reader* o, uint8_t* mark) {
- o->private_impl.mark = mark;
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
+ return b;
}
static inline wuffs_base__slice_u8 //
-wuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io1_r, uint64_t n) {
- if (n <= ((size_t)(io1_r - *ptr_iop_r))) {
+wuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io2_r, uint64_t n) {
+ if (n <= ((size_t)(io2_r - *ptr_iop_r))) {
uint8_t* p = *ptr_iop_r;
*ptr_iop_r += n;
return wuffs_base__make_slice_u8(p, n);
@@ -243,11 +206,12 @@
return wuffs_base__make_slice_u8(NULL, 0);
}
-static inline wuffs_base__empty_struct //
-wuffs_base__io_writer__set(wuffs_base__io_writer* o,
- wuffs_base__io_buffer* b,
+static inline wuffs_base__io_buffer* //
+wuffs_base__io_writer__set(wuffs_base__io_buffer* b,
uint8_t** ptr_iop_w,
+ uint8_t** ptr_io0_w,
uint8_t** ptr_io1_w,
+ uint8_t** ptr_io2_w,
wuffs_base__slice_u8 data) {
b->data = data;
b->meta.wi = 0;
@@ -255,24 +219,12 @@
b->meta.pos = 0;
b->meta.closed = false;
- o->private_impl.buf = b;
- o->private_impl.mark = data.ptr;
- o->private_impl.limit = data.ptr + data.len;
*ptr_iop_w = data.ptr;
- *ptr_io1_w = data.ptr + data.len;
+ *ptr_io0_w = data.ptr;
+ *ptr_io1_w = data.ptr;
+ *ptr_io2_w = data.ptr + data.len;
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_writer__set_mark(wuffs_base__io_writer* o, uint8_t* mark) {
- o->private_impl.mark = mark;
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
+ return b;
}
// ---------------- I/O (Utility)
diff --git a/internal/cgen/base/io-public.h b/internal/cgen/base/io-public.h
index 6e9bb58..271c7f9 100644
--- a/internal/cgen/base/io-public.h
+++ b/internal/cgen/base/io-public.h
@@ -15,34 +15,8 @@
// limitations under the License.
// ---------------- I/O
-
-struct wuffs_base__io_buffer__struct;
-
-typedef struct {
- // Do not access the private_impl's fields directly. There is no API/ABI
- // compatibility or safety guarantee if you do so.
- struct {
- struct wuffs_base__io_buffer__struct* buf;
- // The bounds values are typically NULL, when created by the Wuffs public
- // API. NULL means that the callee substitutes the implicit bounds derived
- // from buf.
- uint8_t* mark;
- uint8_t* limit;
- } private_impl;
-} wuffs_base__io_reader;
-
-typedef struct {
- // Do not access the private_impl's fields directly. There is no API/ABI
- // compatibility or safety guarantee if you do so.
- struct {
- struct wuffs_base__io_buffer__struct* buf;
- // The bounds values are typically NULL, when created by the Wuffs public
- // API. NULL means that the callee substitutes the implicit bounds derived
- // from buf.
- uint8_t* mark;
- uint8_t* limit;
- } private_impl;
-} wuffs_base__io_writer;
+//
+// See (/doc/note/io-input-output.md).
// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
// data.
@@ -63,10 +37,12 @@
#ifdef __cplusplus
inline void compact();
- inline wuffs_base__io_reader reader();
- inline wuffs_base__io_writer writer();
- inline uint64_t reader_io_position();
- inline uint64_t writer_io_position();
+ inline wuffs_base__io_buffer__struct* reader(); // Deprecated.
+ inline wuffs_base__io_buffer__struct* writer(); // Deprecated.
+ inline uint64_t reader_available() const;
+ inline uint64_t reader_io_position() const;
+ inline uint64_t writer_available() const;
+ inline uint64_t writer_io_position() const;
#endif // __cplusplus
} wuffs_base__io_buffer;
@@ -115,24 +91,6 @@
return ret;
}
-static inline wuffs_base__io_reader //
-wuffs_base__null_io_reader() {
- wuffs_base__io_reader ret;
- ret.private_impl.buf = NULL;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
-static inline wuffs_base__io_writer //
-wuffs_base__null_io_writer() {
- wuffs_base__io_writer ret;
- ret.private_impl.buf = NULL;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
// wuffs_base__io_buffer__compact moves any written but unread bytes to the
// start of the buffer.
static inline void //
@@ -149,31 +107,23 @@
buf->meta.ri = 0;
}
-static inline wuffs_base__io_reader //
-wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
- wuffs_base__io_reader ret;
- ret.private_impl.buf = buf;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
-static inline wuffs_base__io_writer //
-wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
- wuffs_base__io_writer ret;
- ret.private_impl.buf = buf;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
+static inline uint64_t //
+wuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {
+ return buf ? buf->meta.wi - buf->meta.ri : 0;
}
static inline uint64_t //
-wuffs_base__io_buffer__reader_io_position(wuffs_base__io_buffer* buf) {
+wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
}
static inline uint64_t //
-wuffs_base__io_buffer__writer_io_position(wuffs_base__io_buffer* buf) {
+wuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {
+ return buf ? buf->data.len - buf->meta.wi : 0;
+}
+
+static inline uint64_t //
+wuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
}
@@ -184,23 +134,33 @@
wuffs_base__io_buffer__compact(this);
}
-inline wuffs_base__io_reader //
+inline wuffs_base__io_buffer* //
wuffs_base__io_buffer__struct::reader() {
- return wuffs_base__io_buffer__reader(this);
+ return this;
}
-inline wuffs_base__io_writer //
+inline wuffs_base__io_buffer* //
wuffs_base__io_buffer__struct::writer() {
- return wuffs_base__io_buffer__writer(this);
+ return this;
}
inline uint64_t //
-wuffs_base__io_buffer__struct::reader_io_position() {
+wuffs_base__io_buffer__struct::reader_available() const {
+ return wuffs_base__io_buffer__reader_available(this);
+}
+
+inline uint64_t //
+wuffs_base__io_buffer__struct::reader_io_position() const {
return wuffs_base__io_buffer__reader_io_position(this);
}
inline uint64_t //
-wuffs_base__io_buffer__struct::writer_io_position() {
+wuffs_base__io_buffer__struct::writer_available() const {
+ return wuffs_base__io_buffer__writer_available(this);
+}
+
+inline uint64_t //
+wuffs_base__io_buffer__struct::writer_io_position() const {
return wuffs_base__io_buffer__writer_io_position(this);
}
diff --git a/internal/cgen/base/range-public.h b/internal/cgen/base/range-public.h
index 69d6ecb..b6f6be7 100644
--- a/internal/cgen/base/range-public.h
+++ b/internal/cgen/base/range-public.h
@@ -52,14 +52,14 @@
uint32_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct intersect(
- wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct unite(
- wuffs_base__range_ii_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u32;
@@ -73,12 +73,12 @@
}
static inline bool //
-wuffs_base__range_ii_u32__is_empty(wuffs_base__range_ii_u32* r) {
+wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u32__equals(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u32__is_empty(r) &&
@@ -86,7 +86,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__intersect(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
wuffs_base__range_ii_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -95,7 +95,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__unite(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
if (wuffs_base__range_ii_u32__is_empty(r)) {
return s;
@@ -110,12 +110,13 @@
}
static inline bool //
-wuffs_base__range_ii_u32__contains(wuffs_base__range_ii_u32* r, uint32_t x) {
+wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u32__contains_range(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return wuffs_base__range_ii_u32__equals(
&s, wuffs_base__range_ii_u32__intersect(r, s));
@@ -124,32 +125,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u32::is_empty() {
+wuffs_base__range_ii_u32::is_empty() const {
return wuffs_base__range_ii_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__equals(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__intersect(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u32::contains(uint32_t x) {
+wuffs_base__range_ii_u32::contains(uint32_t x) const {
return wuffs_base__range_ii_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__contains_range(this, s);
}
@@ -162,15 +163,15 @@
uint32_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct intersect(
- wuffs_base__range_ie_u32__struct s);
+ wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct unite(
- wuffs_base__range_ie_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ie_u32__struct s);
- inline uint32_t length();
+ wuffs_base__range_ie_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
+ inline uint32_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u32;
@@ -184,12 +185,12 @@
}
static inline bool //
-wuffs_base__range_ie_u32__is_empty(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u32__equals(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u32__is_empty(r) &&
@@ -197,7 +198,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__intersect(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
wuffs_base__range_ie_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -206,7 +207,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__unite(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
if (wuffs_base__range_ie_u32__is_empty(r)) {
return s;
@@ -221,56 +222,57 @@
}
static inline bool //
-wuffs_base__range_ie_u32__contains(wuffs_base__range_ie_u32* r, uint32_t x) {
+wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u32__contains_range(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return wuffs_base__range_ie_u32__equals(
&s, wuffs_base__range_ie_u32__intersect(r, s));
}
static inline uint32_t //
-wuffs_base__range_ie_u32__length(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u32::is_empty() {
+wuffs_base__range_ie_u32::is_empty() const {
return wuffs_base__range_ie_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__equals(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__intersect(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u32::contains(uint32_t x) {
+wuffs_base__range_ie_u32::contains(uint32_t x) const {
return wuffs_base__range_ie_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__contains_range(this, s);
}
inline uint32_t //
-wuffs_base__range_ie_u32::length() {
+wuffs_base__range_ie_u32::length() const {
return wuffs_base__range_ie_u32__length(this);
}
@@ -283,14 +285,14 @@
uint64_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct intersect(
- wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct unite(
- wuffs_base__range_ii_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u64;
@@ -304,12 +306,12 @@
}
static inline bool //
-wuffs_base__range_ii_u64__is_empty(wuffs_base__range_ii_u64* r) {
+wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u64__equals(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u64__is_empty(r) &&
@@ -317,7 +319,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__intersect(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
wuffs_base__range_ii_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -326,7 +328,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__unite(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
if (wuffs_base__range_ii_u64__is_empty(r)) {
return s;
@@ -341,12 +343,13 @@
}
static inline bool //
-wuffs_base__range_ii_u64__contains(wuffs_base__range_ii_u64* r, uint64_t x) {
+wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u64__contains_range(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return wuffs_base__range_ii_u64__equals(
&s, wuffs_base__range_ii_u64__intersect(r, s));
@@ -355,32 +358,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u64::is_empty() {
+wuffs_base__range_ii_u64::is_empty() const {
return wuffs_base__range_ii_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__equals(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__intersect(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u64::contains(uint64_t x) {
+wuffs_base__range_ii_u64::contains(uint64_t x) const {
return wuffs_base__range_ii_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__contains_range(this, s);
}
@@ -393,15 +396,15 @@
uint64_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct intersect(
- wuffs_base__range_ie_u64__struct s);
+ wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct unite(
- wuffs_base__range_ie_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ie_u64__struct s);
- inline uint64_t length();
+ wuffs_base__range_ie_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
+ inline uint64_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u64;
@@ -415,12 +418,12 @@
}
static inline bool //
-wuffs_base__range_ie_u64__is_empty(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u64__equals(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u64__is_empty(r) &&
@@ -428,7 +431,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__intersect(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
wuffs_base__range_ie_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -437,7 +440,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__unite(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
if (wuffs_base__range_ie_u64__is_empty(r)) {
return s;
@@ -452,56 +455,57 @@
}
static inline bool //
-wuffs_base__range_ie_u64__contains(wuffs_base__range_ie_u64* r, uint64_t x) {
+wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u64__contains_range(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return wuffs_base__range_ie_u64__equals(
&s, wuffs_base__range_ie_u64__intersect(r, s));
}
static inline uint64_t //
-wuffs_base__range_ie_u64__length(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u64::is_empty() {
+wuffs_base__range_ie_u64::is_empty() const {
return wuffs_base__range_ie_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__equals(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__intersect(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u64::contains(uint64_t x) {
+wuffs_base__range_ie_u64::contains(uint64_t x) const {
return wuffs_base__range_ie_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__contains_range(this, s);
}
inline uint64_t //
-wuffs_base__range_ie_u64::length() {
+wuffs_base__range_ie_u64::length() const {
return wuffs_base__range_ie_u64__length(this);
}
@@ -525,14 +529,14 @@
uint32_t max_incl_y;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__rect_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct intersect(
- wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct unite(
- wuffs_base__rect_ii_u32__struct s);
- inline bool contains(uint32_t x, uint32_t y);
- inline bool contains_rect(wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
+ inline bool contains(uint32_t x, uint32_t y) const;
+ inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__rect_ii_u32;
@@ -551,12 +555,12 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__is_empty(wuffs_base__rect_ii_u32* r) {
+wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {
return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);
}
static inline bool //
-wuffs_base__rect_ii_u32__equals(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||
@@ -565,7 +569,7 @@
}
static inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32__intersect(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
wuffs_base__rect_ii_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
@@ -576,7 +580,7 @@
}
static inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32__unite(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__unite(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
if (wuffs_base__rect_ii_u32__is_empty(r)) {
return s;
@@ -593,7 +597,7 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__contains(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&
@@ -601,7 +605,7 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__contains_rect(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return wuffs_base__rect_ii_u32__equals(
&s, wuffs_base__rect_ii_u32__intersect(r, s));
@@ -610,32 +614,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__rect_ii_u32::is_empty() {
+wuffs_base__rect_ii_u32::is_empty() const {
return wuffs_base__rect_ii_u32__is_empty(this);
}
inline bool //
-wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__equals(this, s);
}
inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__intersect(this, s);
}
inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__unite(this, s);
}
inline bool //
-wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) {
+wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ii_u32__contains(this, x, y);
}
inline bool //
-wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__contains_rect(this, s);
}
@@ -660,16 +664,16 @@
uint32_t max_excl_y;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__rect_ie_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct intersect(
- wuffs_base__rect_ie_u32__struct s);
+ wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct unite(
- wuffs_base__rect_ie_u32__struct s);
- inline bool contains(uint32_t x, uint32_t y);
- inline bool contains_rect(wuffs_base__rect_ie_u32__struct s);
- inline uint32_t width();
- inline uint32_t height();
+ wuffs_base__rect_ie_u32__struct s) const;
+ inline bool contains(uint32_t x, uint32_t y) const;
+ inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
#endif // __cplusplus
} wuffs_base__rect_ie_u32;
@@ -688,12 +692,12 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__is_empty(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {
return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);
}
static inline bool //
-wuffs_base__rect_ie_u32__equals(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||
@@ -702,7 +706,7 @@
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32__intersect(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
wuffs_base__rect_ie_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
@@ -713,7 +717,7 @@
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32__unite(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__unite(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
if (wuffs_base__rect_ie_u32__is_empty(r)) {
return s;
@@ -730,7 +734,7 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__contains(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&
@@ -738,61 +742,61 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__contains_rect(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return wuffs_base__rect_ie_u32__equals(
&s, wuffs_base__rect_ie_u32__intersect(r, s));
}
static inline uint32_t //
-wuffs_base__rect_ie_u32__width(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__width(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_x, r->min_incl_x);
}
static inline uint32_t //
-wuffs_base__rect_ie_u32__height(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__height(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__rect_ie_u32::is_empty() {
+wuffs_base__rect_ie_u32::is_empty() const {
return wuffs_base__rect_ie_u32__is_empty(this);
}
inline bool //
-wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__equals(this, s);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__intersect(this, s);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__unite(this, s);
}
inline bool //
-wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) {
+wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ie_u32__contains(this, x, y);
}
inline bool //
-wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__contains_rect(this, s);
}
inline uint32_t //
-wuffs_base__rect_ie_u32::width() {
+wuffs_base__rect_ie_u32::width() const {
return wuffs_base__rect_ie_u32__width(this);
}
inline uint32_t //
-wuffs_base__rect_ie_u32::height() {
+wuffs_base__rect_ie_u32::height() const {
return wuffs_base__rect_ie_u32__height(this);
}
diff --git a/internal/cgen/builtin.go b/internal/cgen/builtin.go
index 636637e..1529d6b 100644
--- a/internal/cgen/builtin.go
+++ b/internal/cgen/builtin.go
@@ -102,75 +102,68 @@
func (g *gen) writeBuiltinIO(b *buffer, recv *a.Expr, method t.ID, args []*a.Node, depth uint32) error {
switch method {
case t.IDAvailable:
- p0, p1 := "", ""
+ p, q := "", ""
// TODO: don't hard-code these.
switch recv.Str(g.tm) {
case "args.dst":
- p0 = "io1_a_dst"
- p1 = "iop_a_dst"
+ p = "io2_a_dst"
+ q = "iop_a_dst"
case "args.src":
- p0 = "io1_a_src"
- p1 = "iop_a_src"
+ p = "io2_a_src"
+ q = "iop_a_src"
case "w":
- p0 = "io1_v_w"
- p1 = "iop_v_w"
+ p = "io2_v_w"
+ q = "iop_v_w"
}
- if p0 == "" {
+ if p == "" {
return fmt.Errorf(`TODO: cgen a "foo.available" expression`)
}
- b.printf("((uint64_t)(%s - %s))", p0, p1)
+ b.printf("((uint64_t)(%s - %s))", p, q)
return nil
-
- case t.IDSet:
- typ, v := "reader", "r"
- if len(args) == 1 {
- typ, v = "writer", "w"
- }
- b.printf("wuffs_base__io_%s__set(&v_%s, &u_%s, &iop_v_%s, &io1_v_%s,", typ, v, v, v, v)
- return g.writeArgs(b, args, depth)
-
}
return errNoSuchBuiltin
}
func (g *gen) writeBuiltinIOReader(b *buffer, recv *a.Expr, method t.ID, args []*a.Node, depth uint32) error {
// TODO: don't hard-code the recv being a_src.
+ prefix, name := aPrefix, "src"
+ if recv.Operator() == 0 {
+ prefix, name = vPrefix, recv.Ident().Str(g.tm)
+ }
+
switch method {
case t.IDUndoByte:
b.writes("(iop_a_src--, wuffs_base__make_empty_struct())")
return nil
case t.IDCanUndoByte:
- b.writes("(iop_a_src > io0_a_src)")
+ b.writes("(iop_a_src > io1_a_src)")
+ return nil
+
+ case t.IDCountSince:
+ b.printf("wuffs_base__io__count_since(")
+ if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+ return err
+ }
+ b.printf(", ((uint64_t)(%s%s%s - %s%s%s)))", iopPrefix, prefix, name, io0Prefix, prefix, name)
+ return nil
+
+ case t.IDMark:
+ b.printf("((uint64_t)(%s%s%s - %s%s%s))", iopPrefix, prefix, name, io0Prefix, prefix, name)
return nil
case t.IDPosition:
- b.printf("(a_src.private_impl.buf ? wuffs_base__u64__sat_add(" +
- "a_src.private_impl.buf->meta.pos, ((uint64_t)(iop_a_src - a_src.private_impl.buf->data.ptr))) : 0)")
+ b.printf("(a_src ? wuffs_base__u64__sat_add(" +
+ "a_src->meta.pos, ((uint64_t)(iop_a_src - a_src->data.ptr))) : 0)")
return nil
- case t.IDSetLimit:
- b.printf("wuffs_base__io_reader__set_limit(&%ssrc, iop_a_src,", aPrefix)
- // TODO: update the iop variables?
- return g.writeArgs(b, args, depth)
-
- case t.IDSetMark:
- b.printf("wuffs_base__io_reader__set_mark(&%ssrc, iop_a_src)", aPrefix)
- return nil
-
- case t.IDSinceMark, t.IDSinceMarkLength:
- prefix, name := aPrefix, "src"
- if recv.Operator() == 0 {
- prefix, name = vPrefix, recv.Ident().Str(g.tm)
+ case t.IDSince:
+ b.printf("wuffs_base__io__since(")
+ if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+ return err
}
-
- if method == t.IDSinceMark {
- b.printf("wuffs_base__make_slice_u8(%s%s.private_impl.mark, (size_t)(", prefix, name)
- }
- b.printf("iop_%s%s - %s%s.private_impl.mark", prefix, name, prefix, name)
- if method == t.IDSinceMark {
- b.writes("))")
- }
+ b.printf(", ((uint64_t)(%s%s%s - %s%s%s)), %s%s%s)",
+ iopPrefix, prefix, name, io0Prefix, prefix, name, io0Prefix, prefix, name)
return nil
case t.IDSkipFast:
@@ -186,7 +179,7 @@
return nil
case t.IDTake:
- b.printf("wuffs_base__io_reader__take(&iop_a_src, io1_a_src,")
+ b.printf("wuffs_base__io_reader__take(&iop_a_src, io2_a_src,")
return g.writeArgs(b, args, depth)
}
@@ -210,6 +203,11 @@
func (g *gen) writeBuiltinIOWriter(b *buffer, recv *a.Expr, method t.ID, args []*a.Node, depth uint32) error {
// TODO: don't hard-code the recv being a_dst or w.
+ prefix, name := aPrefix, "dst"
+ if recv.Operator() == 0 {
+ prefix, name = vPrefix, recv.Ident().Str(g.tm)
+ }
+
switch method {
case t.IDCopyNFromHistory, t.IDCopyNFromHistoryFast:
suffix := ""
@@ -217,7 +215,7 @@
suffix = "_fast"
}
b.printf("wuffs_base__io_writer__copy_n_from_history%s("+
- "&iop_a_dst, %sdst.private_impl.mark, io1_a_dst",
+ "&iop_a_dst, %sdst->data.ptr, io2_a_dst",
suffix, aPrefix)
for _, o := range args {
b.writeb(',')
@@ -229,48 +227,48 @@
return nil
case t.IDCopyNFromReader:
- b.printf("wuffs_base__io_writer__copy_n_from_reader(&iop_a_dst, io1_a_dst,")
+ b.printf("wuffs_base__io_writer__copy_n_from_reader(&iop_a_dst, io2_a_dst,")
if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
return err
}
// TODO: don't assume that the last argument is "args.src".
- b.printf(", &iop_a_src, io1_a_src)")
+ b.printf(", &iop_a_src, io2_a_src)")
return nil
case t.IDCopyFromSlice:
- b.printf("wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io1_a_dst,")
+ b.printf("wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,")
return g.writeArgs(b, args, depth)
case t.IDCopyNFromSlice:
- b.printf("wuffs_base__io_writer__copy_n_from_slice(&iop_a_dst, io1_a_dst,")
+ b.printf("wuffs_base__io_writer__copy_n_from_slice(&iop_a_dst, io2_a_dst,")
return g.writeArgs(b, args, depth)
+ case t.IDCountSince:
+ b.printf("wuffs_base__io__count_since(")
+ if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+ return err
+ }
+ b.printf(", ((uint64_t)(iop_a_dst - io0_a_dst)))")
+ return nil
+
+ case t.IDHistoryAvailable:
+ b.printf("((uint64_t)(iop_%s%s - %s%s->data.ptr))", prefix, name, prefix, name)
+ return nil
+
+ case t.IDMark:
+ b.printf("((uint64_t)(iop_a_dst - io0_a_dst))")
+ return nil
+
case t.IDPosition:
- b.printf("(a_dst.private_impl.buf ? wuffs_base__u64__sat_add(" +
- "a_dst.private_impl.buf->meta.pos, iop_a_dst - a_dst.private_impl.buf->data.ptr) : 0)")
+ b.printf("(a_dst ? wuffs_base__u64__sat_add(a_dst->meta.pos, iop_a_dst - a_dst->data.ptr) : 0)")
return nil
- case t.IDSetMark:
- // TODO: is a private_impl.mark the right representation? What
- // if the function is passed a (ptr io_writer) instead of a
- // (io_writer)? Do we still want to have that mark live outside of
- // the function scope?
- b.printf("wuffs_base__io_writer__set_mark(&%sdst, iop_a_dst)", aPrefix)
- return nil
-
- case t.IDSinceMark, t.IDSinceMarkLength:
- prefix, name := aPrefix, "dst"
- if recv.Operator() == 0 {
- prefix, name = vPrefix, recv.Ident().Str(g.tm)
+ case t.IDSince:
+ b.printf("wuffs_base__io__since(")
+ if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+ return err
}
-
- if method == t.IDSinceMark {
- b.printf("wuffs_base__make_slice_u8(%s%s.private_impl.mark, (size_t)(", prefix, name)
- }
- b.printf("iop_%s%s - %s%s.private_impl.mark", prefix, name, prefix, name)
- if method == t.IDSinceMark {
- b.writes("))")
- }
+ b.printf(", ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst)")
return nil
}
@@ -401,25 +399,6 @@
return g.writeArgs(b, args, depth)
case t.IDLength:
- if recv.Operator() == t.IDOpenParen {
- if method := recv.LHS().AsExpr(); method.Operator() == t.IDDot && method.Ident() == t.IDSinceMark {
- if lhs := method.LHS().AsExpr(); lhs.MType().IsIOType() {
- b.writes("((uint64_t)(")
- if lhs.MType().QID()[1] == t.IDIOReader {
- if err := g.writeBuiltinIOReader(b, lhs, t.IDSinceMarkLength, nil, depth); err != nil {
- return err
- }
- } else {
- if err := g.writeBuiltinIOWriter(b, lhs, t.IDSinceMarkLength, nil, depth); err != nil {
- return err
- }
- }
- b.writes("))")
- return nil
- }
- }
- }
-
b.writes("((uint64_t)(")
if err := g.writeExpr(b, recv, depth); err != nil {
return err
@@ -579,7 +558,7 @@
temp := g.currFunk.tempW
g.currFunk.tempW++
- b.printf("if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {" +
+ b.printf("if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {" +
"status = wuffs_base__suspension__short_read; goto suspend; }")
// TODO: watch for passing an array type to writeCTypeName? In C, an
@@ -596,7 +575,7 @@
if err := g.writeCoroSuspPoint(b, false); err != nil {
return err
}
- b.printf("if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {" +
+ b.printf("if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {" +
"status = wuffs_base__suspension__short_read; goto suspend; }")
b.printf("iop_a_src++;\n")
return nil
@@ -617,9 +596,9 @@
return err
}
- b.printf("if (%s > ((uint64_t)(io1_a_src - iop_a_src))) {\n", scratchName)
- b.printf("%s -= ((uint64_t)(io1_a_src - iop_a_src));\n", scratchName)
- b.printf("iop_a_src = io1_a_src;\n")
+ b.printf("if (%s > ((uint64_t)(io2_a_src - iop_a_src))) {\n", scratchName)
+ b.printf("%s -= ((uint64_t)(io2_a_src - iop_a_src));\n", scratchName)
+ b.printf("iop_a_src = io2_a_src;\n")
b.writes("status = wuffs_base__suspension__short_read; goto suspend; }\n")
b.printf("iop_a_src += %s;\n", scratchName)
@@ -643,7 +622,7 @@
if err := g.writeCoroSuspPoint(b, false); err != nil {
return err
}
- b.writes("if (iop_a_dst == io1_a_dst) {\n" +
+ b.writes("if (iop_a_dst == io2_a_dst) {\n" +
"status = wuffs_base__suspension__short_write; goto suspend; }\n" +
"*iop_a_dst++ = ")
x := n.Args()[0].AsArg().Value()
@@ -681,7 +660,7 @@
scratchName := fmt.Sprintf("self->private_data.%s%s[0].scratch",
sPrefix, g.currFunk.astFunc.FuncName().Str(g.tm))
- b.printf("if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= %d)) {", xx/8)
+ b.printf("if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= %d)) {", xx/8)
b.printf("%s%d =", tPrefix, temp)
if xx != yy {
b.printf("((uint%d_t)(", yy)
@@ -699,7 +678,7 @@
}
b.printf("while (true) {")
- b.printf("if (WUFFS_BASE__UNLIKELY(iop_%s == io1_%s)) {"+
+ b.printf("if (WUFFS_BASE__UNLIKELY(iop_%s == io2_%s)) {"+
"status = wuffs_base__suspension__short_read; goto suspend; }",
preName, preName)
diff --git a/internal/cgen/cgen.go b/internal/cgen/cgen.go
index 52f9b3c..d5cb53b 100644
--- a/internal/cgen/cgen.go
+++ b/internal/cgen/cgen.go
@@ -68,27 +68,29 @@
// reading or writing the next byte (and advancing the stream) is essentially
// "etc = *iop_a_src++" or "*io_a_dst++ = etc".
//
-// The other two prefixes, giving names like io0_etc and io1_etc, are
+// The other two prefixes, giving names like io1_etc and io2_etc, are
// auxilliary pointers: lower and upper inclusive bounds. As an iop_etc pointer
-// advances, it cannot advance past io1_etc. In the rarer case that an iop_etc
-// pointer retreats, undoing a read or write, it cannot retreat past io0_etc.
+// advances, it cannot advance past io2_etc. In the rarer case that an iop_etc
+// pointer retreats, undoing a read or write, it cannot retreat past io1_etc.
+//
+// The iop_etc pointer can change over the lifetime of a function. The ioN_etc
+// pointers, for numeric N, cannot.
//
// At the start of a function, these pointers are initialized from an
-// io_buffer's fields (ptr, ri, wi, len), or possibly a limit field. For an
-// io_reader:
-// - io0_etc = ptr + ri
+// io_buffer's fields (ptr, ri, wi, len). For an io_reader:
+// - io0_etc = ptr
+// - io1_etc = ptr + ri
// - iop_etc = ptr + ri
-// - io1_etc = ptr + wi or limit
+// - io2_etc = ptr + wi
// and for an io_writer:
-// - io0_etc = ptr + wi
+// - io0_etc = ptr
+// - io1_etc = ptr + wi
// - iop_etc = ptr + wi
-// - io1_etc = ptr + len or limit
-//
-// TODO: discuss marks and limits, and how (if at all) auxilliary pointers can
-// change over a function's lifetime.
+// - io2_etc = ptr + len
const (
- io0Prefix = "io0_" // Lower bound.
- io1Prefix = "io1_" // Upper bound.
+ io0Prefix = "io0_" // Base.
+ io1Prefix = "io1_" // Lower bound.
+ io2Prefix = "io2_" // Upper bound.
iopPrefix = "iop_" // Pointer.
)
@@ -263,6 +265,19 @@
func insertBaseAllPublicH(buf *buffer) error {
if err := expandBangBangInsert(buf, baseCorePublicH, map[string]func(*buffer) error{
+ "// !! INSERT FourCCs.\n": func(b *buffer) error {
+ for _, z := range builtin.FourCCs {
+ b.printf("// %s.\n#define WUFFS_BASE__FOURCC__%s 0x%02X%02X%02X%02X\n\n",
+ z[1],
+ strings.ToUpper(strings.TrimSpace(z[0])),
+ z[0][0],
+ z[0][1],
+ z[0][2],
+ z[0][3],
+ )
+ }
+ return nil
+ },
"// !! INSERT wuffs_base__status names.\n": func(b *buffer) error {
for _, z := range builtin.Statuses {
msg, _ := t.Unescape(z)
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 9b91b5e..09121da 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -24,11 +24,13 @@
""
const baseImageImplC = "" +
- "// ---------------- Images\n\nconst uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {\n 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,\n};\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_1_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n return wuffs_base__slice_u8__copy_from_slice(dst, src);\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len4 = dst.len / 4;\n size_t len = dst_len4 < src.len ? dst_len4 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len;\n const int N = 4;\n\n while (n >= N) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u3" +
- "2le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 4 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n\n s += 1 * 1;\n d += 4 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__swap_rgbx_bgrx(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t len4 = (dst.len < src.len ? dst.len : src.len) / 4;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len4;\n while (n--) {\n uin" +
- "t8_t b0 = s[0];\n uint8_t b1 = s[1];\n uint8_t b2 = s[2];\n uint8_t b3 = s[3];\n d[0] = b2;\n d[1] = b1;\n d[2] = b0;\n d[3] = b3;\n s += 4;\n d += 4;\n }\n return len4 * 4;\n}\n\nvoid //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n if (!p) {\n return;\n }\n\n // TODO: support many more formats.\n\n uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) = NULL;\n\n switch (src_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n switch (dst_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL" +
- "_FORMAT__INDEXED__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_1_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n d" +
- "efault:\n break;\n }\n break;\n\n default:\n break;\n }\n\n p->private_impl.func = func;\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,\n wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (p && p->private_impl.func) {\n return (*(p->private_impl.func))(dst, dst_palette, src);\n }\n return 0;\n}\n" +
+ "// ---------------- Images\n\nconst uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {\n 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,\n};\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_1_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n return wuffs_base__slice_u8__copy_from_slice(dst, src);\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len3 = dst.len / 3;\n size_t len = dst_len3 < src.len ? dst_len3 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n // N is the loop unroll count.\n const int N = 4;\n\n // The comparison in the while condition is \">\", not \">=\", be" +
+ "cause with \">=\",\n // the last 4-byte store could write past the end of the dst slice.\n //\n // Each 4-byte store writes one too many bytes, but a subsequent store will\n // overwrite that with the correct byte. There is always another store,\n // whether a 4-byte store in this loop or a 1-byte store in the next loop.\n while (n > N) {\n wuffs_base__store_u32le(\n d + (0 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 3 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n uint32_t color =\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));\n d[0" +
+ "] = (uint8_t)(color >> 0);\n d[1] = (uint8_t)(color >> 8);\n d[2] = (uint8_t)(color >> 16);\n\n s += 1 * 1;\n d += 3 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len4 = dst.len / 4;\n size_t len = dst_len4 < src.len ? dst_len4 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n // N is the loop unroll count.\n const int N = 4;\n\n while (n >= N) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + (" +
+ "(uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 4 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n\n s += 1 * 1;\n d += 4 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__swap_rgbx_bgrx(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t len4 = (dst.len < src.len ? dst.len : src.len) / 4;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len4;\n while (n--) {\n uint8_t b0 = s[0];\n uint8_t b1 = s[1];\n uint8_t b2 = s[2];\n uint8_t b3 = s[3];\n d[0] = b2;\n d[1] = b1;\n d[2] = b0;\n d[3] = b3;\n s += 4;\n d += 4;\n }\n return len4 * 4;\n}\n\nwuffs_base__status //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_s" +
+ "wizzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n if (!p) {\n return wuffs_base__error__bad_receiver;\n }\n\n // TODO: support many more formats.\n\n uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) = NULL;\n\n switch (src_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n switch (dst_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_1_1;\n " +
+ " break;\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_3_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_3_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PR" +
+ "EMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n default:\n break;\n }\n break;\n\n default:\n break;\n }\n\n p->private_impl.func = func;\n return func ? NULL : wuffs_base__error__unsupported_option;\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_interleaved(\n const wuffs_base__pixel_swizzler* p,\n wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (p && p->private_impl.func) {\n return (*(p->private_impl.func))(dst, dst_palette, src);\n }\n return 0;\n}\n" +
""
const baseCorePrivateH = "" +
@@ -71,6 +73,8 @@
"// --------\n\n// A status is either NULL (meaning OK) or a string message. That message is\n// human-readable, for programmers, but it is not for end users. It is not\n// localized, and does not contain additional contextual information such as a\n// source filename.\n//\n// Status strings are statically allocated and should never be free'd. They can\n// be compared by the == operator and not just by strcmp.\n//\n// Statuses come in four categories:\n// - OK: the request was completed, successfully.\n// - Warnings: the request was completed, unsuccessfully.\n// - Suspensions: the request was not completed, but can be re-tried.\n// - Errors: the request was not completed, permanently.\n//\n// When a function returns an incomplete status, a suspension means that that\n// function should be called again within a new context, such as after flushing\n// or re-filling an I/O buffer. An error means that an irrecoverable failure\n// state was reached.\ntypedef const char* wuffs_base__status;\n\n// !! INSERT wuffs_bas" +
"e__status names.\n\nstatic inline bool //\nwuffs_base__status__is_complete(wuffs_base__status z) {\n return (z == NULL) || ((*z != '$') && (*z != '#'));\n}\n\nstatic inline bool //\nwuffs_base__status__is_error(wuffs_base__status z) {\n return z && (*z == '#');\n}\n\nstatic inline bool //\nwuffs_base__status__is_ok(wuffs_base__status z) {\n return z == NULL;\n}\n\nstatic inline bool //\nwuffs_base__status__is_suspension(wuffs_base__status z) {\n return z && (*z == '$');\n}\n\nstatic inline bool //\nwuffs_base__status__is_warning(wuffs_base__status z) {\n return z && (*z != '$') && (*z != '#');\n}\n\n" +
"" +
+ "// --------\n\n// FourCC constants.\n\n// !! INSERT FourCCs.\n\n" +
+ "" +
"// --------\n\n// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a\n// second. See https://github.com/OculusVR/Flicks\ntypedef int64_t wuffs_base__flicks;\n\n#define WUFFS_BASE__FLICKS_PER_SECOND ((uint64_t)705600000)\n#define WUFFS_BASE__FLICKS_PER_MILLISECOND ((uint64_t)705600)\n\n" +
"" +
"// ---------------- Numeric Types\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__max(uint64_t x, uint64_t y) {\n return x > y ? x : y;\n}\n\n" +
@@ -101,80 +105,81 @@
const baseImagePublicH = "" +
"// ---------------- Images\n\n// wuffs_base__color_u32_argb_premul is an 8 bit per channel premultiplied\n// Alpha, Red, Green, Blue color, as a uint32_t value. It is in word order, not\n// byte order: its value is always 0xAARRGGBB, regardless of endianness.\ntypedef uint32_t wuffs_base__color_u32_argb_premul;\n\n" +
"" +
- "// --------\n\n// wuffs_base__pixel_format encodes the format of the bytes that constitute an\n// image frame's pixel data. Its bits:\n// - bit 31 is reserved.\n// - bits 30 .. 28 encodes color (and channel order, in terms of memory).\n// - bit 27 is reserved.\n// - bits 26 .. 24 encodes transparency.\n// - bits 23 .. 21 are reserved.\n// - bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).\n// - bit 19 indicates floating point (as opposed to integer).\n// - bit 18 indicates palette-indexed. The number-of-planes (the next\n// field) will be zero, as the format is considered packed,\n// but the 8-bit N-BGRA color data is stored in plane 3.\n// - bits 17 .. 16 are the number of planes, minus 1. Zero means packed.\n// - bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.\n// - bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.\n// - bits 7 .. 4 encodes the number of bits (depth) in the 1st channe" +
- "l.\n// - bits 3 .. 0 encodes the number of bits (depth) in the 0th channel.\n//\n// The bit fields of a wuffs_base__pixel_format are not independent. For\n// example, the number of planes should not be greater than the number of\n// channels. Similarly, bits 15..4 are unused (and should be zero) if bits\n// 31..24 (color and transparency) together imply only 1 channel (gray, no\n// alpha) and floating point samples should mean a bit depth of 16, 32 or 64.\n//\n// Formats hold between 1 and 4 channels. For example: Y (1 channel: gray), YA\n// (2 channels: gray and alpha), BGR (3 channels: blue, green, red) or CMYK (4\n// channels: cyan, magenta, yellow, black).\n//\n// For direct formats with N > 1 channels, those channels can be laid out in\n// either 1 (packed) or N (planar) planes. For example, RGBA data is usually\n// packed, but YCbCr data is usually planar, due to chroma subsampling (for\n// details, see the wuffs_base__pixel_subsampling type).\n//\n// For indexed formats, the palette (always 256 × 4 bytes) holds 8 bi" +
- "ts per\n// channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for\n// the index), as the format is considered packed. Plane 0 holds the per-pixel\n// indices. Plane 3 is re-purposed to hold the per-index colors.\n//\n// The color field is encoded in 3 bits:\n// - 0 means A (Alpha).\n// - 1 means Y or YA (Gray, Alpha).\n// - 2 means YCbCr or YCbCrA (Luma, Chroma-blue, Chroma-red, Alpha).\n// - 3 means YCoCg or YCoCgA (Luma, Chroma-orange, Chroma-green, Alpha).\n// - 4 means BGR, BGRX or BGRA (Blue, Green, Red, X-padding or Alpha).\n// - 5 means RGB, RGBX or RGBA (Red, Green, Blue, X-padding or Alpha).\n// - 6 means CMY or CMYK (Cyan, Magenta, Yellow, Black).\n// - all other values are reserved.\n//\n// In Wuffs, channels are given in memory order (also known as byte order),\n// regardless of endianness, since the C type for the pixel data is an array of\n// bytes, not an array of uint32_t. For example, packed BGRA with 8 bits per\n// channel means th" +
- "at the bytes in memory are always Blue, Green, Red then\n// Alpha. On big-endian systems, that is the uint32_t 0xBBGGRRAA. On\n// little-endian, 0xAARRGGBB.\n//\n// When the color field (3 bits) encodes multiple options, the transparency\n// field (3 bits) distinguishes them:\n// - 0 means fully opaque, no extra channels\n// - 1 means fully opaque, one extra channel (X or K, padding or black).\n// - 5 means one extra alpha channel, other channels are non-premultiplied.\n// - 6 means one extra alpha channel, other channels are premultiplied.\n// - 7 means one extra alpha channel, binary alpha.\n// - all other values are reserved.\n//\n// Binary alpha means that if a color is not completely opaque, it is\n// completely transparent black. As a source pixel format, it can therefore be\n// treated as either non-premultiplied or premultiplied.\n//\n// The zero wuffs_base__pixel_format value is an invalid pixel format, as it is\n// invalid to combine the zero color (alpha only) with the zero transparency.\n//\n// Bit depth is" +
- " encoded in 4 bits:\n// - 0 means the channel or index is unused.\n// - x means a bit depth of x, for x in the range 1..8.\n// - 9 means a bit depth of 10.\n// - 10 means a bit depth of 12.\n// - 11 means a bit depth of 16.\n// - 12 means a bit depth of 24.\n// - 13 means a bit depth of 32.\n// - 14 means a bit depth of 48.\n// - 15 means a bit depth of 64.\n//\n// For example, wuffs_base__pixel_format 0x5510BBBB is a natural format for\n// decoding a PNG image - network byte order (also known as big-endian),\n// packed, non-premultiplied alpha - that happens to be 16-bit-depth truecolor\n// with alpha (RGBA). In memory order:\n//\n// ptr+0 ptr+1 ptr+2 ptr+3 ptr+4 ptr+5 ptr+6 ptr+7\n// Rhi Rlo Ghi Glo Bhi Blo Ahi Alo\n//\n// For example, the value wuffs_base__pixel_format 0x40000565 means BGR with no\n// alpha or padding, 5/6/5 bits for blue/green/red, packed 2 bytes per pixel,\n// laid out LSB-first in memory order:\n//\n// ptr+0........... ptr+1...........\n// MSB LSB MSB " +
- " LSB\n// G₂G₁G₀B₄B₃B₂B₁B₀ R₄R₃R₂R₁R₀G₅G₄G₃\n//\n// On little-endian systems (but not big-endian), this Wuffs pixel format value\n// (0x40000565) corresponds to the Cairo library's CAIRO_FORMAT_RGB16_565, the\n// SDL2 (Simple DirectMedia Layer 2) library's SDL_PIXELFORMAT_RGB565 and the\n// Skia library's kRGB_565_SkColorType. Note BGR in Wuffs versus RGB in the\n// other libraries.\n//\n// Regardless of endianness, this Wuffs pixel format value (0x40000565)\n// corresponds to the V4L2 (Video For Linux 2) library's V4L2_PIX_FMT_RGB565\n// and the Wayland-DRM library's WL_DRM_FORMAT_RGB565.\n//\n// Different software libraries name their pixel formats (and especially their\n// channel order) either according to memory layout or as bits of a native\n// integer type like uint32_t. The two conventions differ because of a system's\n// endianness. As mentioned earlier, Wuffs pixel formats are always in memory\n// order. More detail of other software libraries' naming conventions is in the\n// Pi" +
- "xel Format Guide at https://afrantzis.github.io/pixel-format-guide/\n//\n// Do not manipulate these bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_format__num_planes instead.\ntypedef uint32_t wuffs_base__pixel_format;\n\n// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid\n// wuffs_base__pixel_format values are present.\n\n#define WUFFS_BASE__PIXEL_FORMAT__INVALID ((wuffs_base__pixel_format)0x00000000)\n\n#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x15000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \\\n ((wuffs_base__pixel_format)0x16000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL \\\n ((w" +
- "uffs_base__pixel_format)0x25038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x35038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \\\n ((wuffs_base__pixel_format)0x46040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \\\n ((wuffs_base__pixel_format)0x47040008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \\\n ((wuffs_base__pixel_format)0x46008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \\\n ((wuffs_base__pixel_format)0x47008888)\n\n#define W" +
- "UFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x55008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \\\n ((wuffs_base__pixel_format)0x56008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \\\n ((wuffs_base__pixel_format)0x57008888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888)\n#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888)\n\nextern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];\n\nstatic inline bool //\nwuffs_base__pixel_format__is_valid(wuffs_base__pixel_format f) {\n return f != 0;\n}\n\n// wuffs_base__pixel_format__bits_per_pixel returns, for packed pixel formats,\n// the number of bits per pixel. It returns 0 for planar pixel formats.\nstatic inline uint32_t //\nwuffs_base__pixel_format__bits_per_pixel(wuffs_base__pixel_format f) {\n if (((f >> 16) & 0x03" +
- ") != 0) {\n return 0;\n }\n return wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 0)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 4)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 8)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 12)];\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_indexed(wuffs_base__pixel_format f) {\n return (f >> 18) & 0x01;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_packed(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) == 0;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_planar(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) != 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_format__num_planes(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) + 1;\n}\n\n#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3\n\n" +
+ "// --------\n\n// wuffs_base__pixel_format encodes the format of the bytes that constitute an\n// image frame's pixel data. Its bits:\n// - bit 31 is reserved.\n// - bits 30 .. 28 encodes color (and channel order, in terms of memory).\n// - bit 27 is reserved.\n// - bits 26 .. 24 encodes transparency.\n// - bits 23 .. 21 are reserved.\n// - bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).\n// - bit 19 indicates floating point (as opposed to integer).\n// - bit 18 indicates palette-indexed. The number-of-planes (the next\n// field) will be 0, as the format is considered interleaved,\n// but the 8-bit N-BGRA color data is stored in plane 3.\n// - bits 17 .. 16 are the number of planes, minus 1. Zero means interleaved.\n// - bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.\n// - bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.\n// - bits 7 .. 4 encodes the number of bits (depth) in the 1st" +
+ " channel.\n// - bits 3 .. 0 encodes the number of bits (depth) in the 0th channel.\n//\n// The bit fields of a wuffs_base__pixel_format are not independent. For\n// example, the number of planes should not be greater than the number of\n// channels. Similarly, bits 15..4 are unused (and should be zero) if bits\n// 31..24 (color and transparency) together imply only 1 channel (gray, no\n// alpha) and floating point samples should mean a bit depth of 16, 32 or 64.\n//\n// Formats hold between 1 and 4 channels. For example: Y (1 channel: gray), YA\n// (2 channels: gray and alpha), BGR (3 channels: blue, green, red) or CMYK (4\n// channels: cyan, magenta, yellow, black).\n//\n// For direct formats with N > 1 channels, those channels can be laid out in\n// either 1 (interleaved) or N (planar) planes. For example, RGBA data is\n// usually interleaved, but YCbCr data is usually planar, due to chroma\n// subsampling (for details, see the wuffs_base__pixel_subsampling type).\n//\n// For indexed formats, the palette (always 256 × 4 " +
+ "bytes) holds 8 bits per\n// channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for\n// the index), as the format is considered interleaved. Plane 0 holds the\n// per-pixel indices. Plane 3 is re-purposed to hold the per-index colors.\n//\n// The color field is encoded in 3 bits:\n// - 0 means A (Alpha).\n// - 1 means Y or YA (Gray, Alpha).\n// - 2 means YCbCr or YCbCrA (Luma, Chroma-blue, Chroma-red, Alpha).\n// - 3 means YCoCg or YCoCgA (Luma, Chroma-orange, Chroma-green, Alpha).\n// - 4 means BGR, BGRX or BGRA (Blue, Green, Red, X-padding or Alpha).\n// - 5 means RGB, RGBX or RGBA (Red, Green, Blue, X-padding or Alpha).\n// - 6 means CMY or CMYK (Cyan, Magenta, Yellow, Black).\n// - all other values are reserved.\n//\n// In Wuffs, channels are given in memory order (also known as byte order),\n// regardless of endianness, since the C type for the pixel data is an array of\n// bytes, not an array of uint32_t. For example, interleaved BGRA with 8 b" +
+ "its\n// per channel means that the bytes in memory are always Blue, Green, Red then\n// Alpha. On big-endian systems, that is the uint32_t 0xBBGGRRAA. On\n// little-endian, 0xAARRGGBB.\n//\n// When the color field (3 bits) encodes multiple options, the transparency\n// field (3 bits) distinguishes them:\n// - 0 means fully opaque, no extra channels\n// - 1 means fully opaque, one extra channel (X or K, padding or black).\n// - 5 means one extra alpha channel, other channels are non-premultiplied.\n// - 6 means one extra alpha channel, other channels are premultiplied.\n// - 7 means one extra alpha channel, binary alpha.\n// - all other values are reserved.\n//\n// Binary alpha means that if a color is not completely opaque, it is\n// completely transparent black. As a source pixel format, it can therefore be\n// treated as either non-premultiplied or premultiplied.\n//\n// The zero wuffs_base__pixel_format value is an invalid pixel format, as it is\n// invalid to combine the zero color (alpha only) with the zero trans" +
+ "parency.\n//\n// Bit depth is encoded in 4 bits:\n// - 0 means the channel or index is unused.\n// - x means a bit depth of x, for x in the range 1..8.\n// - 9 means a bit depth of 10.\n// - 10 means a bit depth of 12.\n// - 11 means a bit depth of 16.\n// - 12 means a bit depth of 24.\n// - 13 means a bit depth of 32.\n// - 14 means a bit depth of 48.\n// - 15 means a bit depth of 64.\n//\n// For example, wuffs_base__pixel_format 0x5510BBBB is a natural format for\n// decoding a PNG image - network byte order (also known as big-endian),\n// interleaved, non-premultiplied alpha - that happens to be 16-bit-depth\n// truecolor with alpha (RGBA). In memory order:\n//\n// ptr+0 ptr+1 ptr+2 ptr+3 ptr+4 ptr+5 ptr+6 ptr+7\n// Rhi Rlo Ghi Glo Bhi Blo Ahi Alo\n//\n// For example, the value wuffs_base__pixel_format 0x40000565 means BGR with no\n// alpha or padding, 5/6/5 bits for blue/green/red, interleaved 2 bytes per\n// pixel, laid out LSB-first in memory order:\n//\n// ptr+0........... ptr+1...." +
+ ".......\n// MSB LSB MSB LSB\n// G₂G₁G₀B₄B₃B₂B₁B₀ R₄R₃R₂R₁R₀G₅G₄G₃\n//\n// On little-endian systems (but not big-endian), this Wuffs pixel format value\n// (0x40000565) corresponds to the Cairo library's CAIRO_FORMAT_RGB16_565, the\n// SDL2 (Simple DirectMedia Layer 2) library's SDL_PIXELFORMAT_RGB565 and the\n// Skia library's kRGB_565_SkColorType. Note BGR in Wuffs versus RGB in the\n// other libraries.\n//\n// Regardless of endianness, this Wuffs pixel format value (0x40000565)\n// corresponds to the V4L2 (Video For Linux 2) library's V4L2_PIX_FMT_RGB565\n// and the Wayland-DRM library's WL_DRM_FORMAT_RGB565.\n//\n// Different software libraries name their pixel formats (and especially their\n// channel order) either according to memory layout or as bits of a native\n// integer type like uint32_t. The two conventions differ because of a system's\n// endianness. As mentioned earlier, Wuffs pixel formats are always in memory\n// order. More detail of other software librarie" +
+ "s' naming conventions is in the\n// Pixel Format Guide at https://afrantzis.github.io/pixel-format-guide/\n//\n// Do not manipulate these bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_format__num_planes instead.\ntypedef uint32_t wuffs_base__pixel_format;\n\n// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid\n// wuffs_base__pixel_format values are present.\n\n#define WUFFS_BASE__PIXEL_FORMAT__INVALID ((wuffs_base__pixel_format)0x00000000)\n\n#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x15000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \\\n ((wuffs_base__pixel_format)0x16000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888)\n#define WUFFS_BASE__P" +
+ "IXEL_FORMAT__YCBCRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x25038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x35038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \\\n ((wuffs_base__pixel_format)0x46040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \\\n ((wuffs_base__pixel_format)0x47040008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \\\n ((wuffs_base__pixel_format)0x46008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \\\n ((wuffs_base" +
+ "__pixel_format)0x47008888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x55008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \\\n ((wuffs_base__pixel_format)0x56008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \\\n ((wuffs_base__pixel_format)0x57008888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888)\n#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888)\n\nextern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];\n\nstatic inline bool //\nwuffs_base__pixel_format__is_valid(wuffs_base__pixel_format f) {\n return f != 0;\n}\n\n// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per\n// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.\nstatic inline uint32_t //\nwuffs_base__pixel_format__bits_per_pixel(wuffs_base__" +
+ "pixel_format f) {\n if (((f >> 16) & 0x03) != 0) {\n return 0;\n }\n return wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 0)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 4)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 8)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 12)];\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_indexed(wuffs_base__pixel_format f) {\n return (f >> 18) & 0x01;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_interleaved(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) == 0;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_planar(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) != 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_format__num_planes(wuffs_base__pixel_format f) {\n return ((f >> 16) & 0x03) + 1;\n}\n\n#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLA" +
+ "NE 3\n\n" +
"" +
- "// --------\n\n// wuffs_base__pixel_subsampling encodes the mapping of pixel space coordinates\n// (x, y) to pixel buffer indices (i, j). That mapping can differ for each\n// plane p. For a depth of 8 bits (1 byte), the p'th plane's sample starts at\n// (planes[p].ptr + (j * planes[p].stride) + i).\n//\n// For packed pixel formats, the mapping is trivial: i = x and j = y. For\n// planar pixel formats, the mapping can differ due to chroma subsampling. For\n// example, consider a three plane YCbCr pixel format with 4:2:2 subsampling.\n// For the luma (Y) channel, there is one sample for every pixel, but for the\n// chroma (Cb, Cr) channels, there is one sample for every two pixels: pairs of\n// horizontally adjacent pixels form one macropixel, i = x / 2 and j == y. In\n// general, for a given p:\n// - i = (x + bias_x) >> shift_x.\n// - j = (y + bias_y) >> shift_y.\n// where biases and shifts are in the range 0..3 and 0..2 respectively.\n//\n// In general, the biases will be zero after decoding an image. However, making\n// a su" +
- "b-image may change the bias, since the (x, y) coordinates are relative\n// to the sub-image's top-left origin, but the backing pixel buffers were\n// created relative to the original image's origin.\n//\n// For each plane p, each of those four numbers (biases and shifts) are encoded\n// in two bits, which combine to form an 8 bit unsigned integer:\n//\n// e_p = (bias_x << 6) | (shift_x << 4) | (bias_y << 2) | (shift_y << 0)\n//\n// Those e_p values (e_0 for the first plane, e_1 for the second plane, etc)\n// combine to form a wuffs_base__pixel_subsampling value:\n//\n// pixsub = (e_3 << 24) | (e_2 << 16) | (e_1 << 8) | (e_0 << 0)\n//\n// Do not manipulate these bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.\ntypedef uint32_t wuffs_base__pixel_subsampling;\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE ((wuffs_base__pixel_subsampling)0)\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 \\\n ((wuffs_base__pixel_subsampling)0x000000)\n#define WUFFS_BASE__PI" +
- "XEL_SUBSAMPLING__440 \\\n ((wuffs_base__pixel_subsampling)0x010100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 \\\n ((wuffs_base__pixel_subsampling)0x101000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \\\n ((wuffs_base__pixel_subsampling)0x111100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \\\n ((wuffs_base__pixel_subsampling)0x202000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \\\n ((wuffs_base__pixel_subsampling)0x212100)\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 6;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__shift_x(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 4;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__bias_y(wuffs_base__pixel_subsampling s,\n " +
- " uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 2;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__shift_y(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 0;\n return (s >> shift) & 0x03;\n}\n\n" +
+ "// --------\n\n// wuffs_base__pixel_subsampling encodes the mapping of pixel space coordinates\n// (x, y) to pixel buffer indices (i, j). That mapping can differ for each\n// plane p. For a depth of 8 bits (1 byte), the p'th plane's sample starts at\n// (planes[p].ptr + (j * planes[p].stride) + i).\n//\n// For interleaved pixel formats, the mapping is trivial: i = x and j = y. For\n// planar pixel formats, the mapping can differ due to chroma subsampling. For\n// example, consider a three plane YCbCr pixel format with 4:2:2 subsampling.\n// For the luma (Y) channel, there is one sample for every pixel, but for the\n// chroma (Cb, Cr) channels, there is one sample for every two pixels: pairs of\n// horizontally adjacent pixels form one macropixel, i = x / 2 and j == y. In\n// general, for a given p:\n// - i = (x + bias_x) >> shift_x.\n// - j = (y + bias_y) >> shift_y.\n// where biases and shifts are in the range 0..3 and 0..2 respectively.\n//\n// In general, the biases will be zero after decoding an image. However, making\n//" +
+ " a sub-image may change the bias, since the (x, y) coordinates are relative\n// to the sub-image's top-left origin, but the backing pixel buffers were\n// created relative to the original image's origin.\n//\n// For each plane p, each of those four numbers (biases and shifts) are encoded\n// in two bits, which combine to form an 8 bit unsigned integer:\n//\n// e_p = (bias_x << 6) | (shift_x << 4) | (bias_y << 2) | (shift_y << 0)\n//\n// Those e_p values (e_0 for the first plane, e_1 for the second plane, etc)\n// combine to form a wuffs_base__pixel_subsampling value:\n//\n// pixsub = (e_3 << 24) | (e_2 << 16) | (e_1 << 8) | (e_0 << 0)\n//\n// Do not manipulate these bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.\ntypedef uint32_t wuffs_base__pixel_subsampling;\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE ((wuffs_base__pixel_subsampling)0)\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 \\\n ((wuffs_base__pixel_subsampling)0x000000)\n#define WUFFS_BAS" +
+ "E__PIXEL_SUBSAMPLING__440 \\\n ((wuffs_base__pixel_subsampling)0x010100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 \\\n ((wuffs_base__pixel_subsampling)0x101000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \\\n ((wuffs_base__pixel_subsampling)0x111100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \\\n ((wuffs_base__pixel_subsampling)0x202000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \\\n ((wuffs_base__pixel_subsampling)0x212100)\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 6;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__shift_x(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 4;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__bias_y(wuffs_base__pixel_subsampling s,\n " +
+ " uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 2;\n return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_subsampling__shift_y(wuffs_base__pixel_subsampling s,\n uint32_t plane) {\n uint32_t shift = ((plane & 0x03) * 8) + 0;\n return (s >> shift) & 0x03;\n}\n\n" +
"" +
- "// --------\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__pixel_format pixfmt;\n wuffs_base__pixel_subsampling pixsub;\n uint32_t width;\n uint32_t height;\n } private_impl;\n\n#ifdef __cplusplus\n inline void set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height);\n inline void invalidate();\n inline bool is_valid();\n inline wuffs_base__pixel_format pixel_format();\n inline wuffs_base__pixel_subsampling pixel_subsampling();\n inline wuffs_base__rect_ie_u32 bounds();\n inline uint32_t width();\n inline uint32_t height();\n inline uint64_t pixbuf_len();\n#endif // __cplusplus\n\n} wuffs_base__pixel_config;\n\nstatic inline wuffs_base__pixel_config //\nwuffs_base__null_pixel_config() {\n wuffs_base__pixel_config ret;\n ret.private_impl.pixfmt = 0;\n ret.private_impl.pixsub = 0;\n " +
- "ret.private_impl.width = 0;\n ret.private_impl.height = 0;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__pixel_config__set(wuffs_base__pixel_config* c,\n wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n if (!c) {\n return;\n }\n if (pixfmt) {\n uint64_t wh = ((uint64_t)width) * ((uint64_t)height);\n // TODO: handle things other than 1 byte per pixel.\n if (wh <= ((uint64_t)SIZE_MAX)) {\n c->private_impl.pixfmt = pixfmt;\n c->private_impl.pixsub = pixsub;\n c->private_impl.width = width;\n c->private_impl.height = height;\n return;\n }\n }\n\n c->private_impl.pixfmt = 0;\n c->private_impl.pixsub = 0;\n c->private_impl.width = 0;\n c->private_impl.height = 0;\n}\n\nstatic inline void //\nwuffs_base__pixel_config__invalidate(wuffs_base__pixel_config*" +
- " c) {\n if (c) {\n c->private_impl.pixfmt = 0;\n c->private_impl.pixsub = 0;\n c->private_impl.width = 0;\n c->private_impl.height = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__pixel_config__is_valid(wuffs_base__pixel_config* c) {\n return c && c->private_impl.pixfmt;\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_config__pixel_format(wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixfmt : 0;\n}\n\nstatic inline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config__pixel_subsampling(wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixsub : 0;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config__bounds(wuffs_base__pixel_config* c) {\n if (c) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = c->private_impl.width;\n ret.max_excl_y = c->private_impl.height;\n return ret;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl" +
- "_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__width(wuffs_base__pixel_config* c) {\n return c ? c->private_impl.width : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__height(wuffs_base__pixel_config* c) {\n return c ? c->private_impl.height : 0;\n}\n\n// TODO: this is the right API for planar (not packed) pixbufs? Should it allow\n// decoding into a color model different from the format's intrinsic one? For\n// example, decoding a JPEG image straight to RGBA instead of to YCbCr?\nstatic inline uint64_t //\nwuffs_base__pixel_config__pixbuf_len(wuffs_base__pixel_config* c) {\n if (!c) {\n return 0;\n }\n if (wuffs_base__pixel_format__is_planar(c->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return 0;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(c->private_impl.pixfmt);\n if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n // TODO: support fraction-of-byte pixels, e.g. 1 " +
- "bit per pixel?\n return 0;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint64_t n =\n ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);\n if (n > (UINT64_MAX / bytes_per_pixel)) {\n return 0;\n }\n n *= bytes_per_pixel;\n\n if (wuffs_base__pixel_format__is_indexed(c->private_impl.pixfmt)) {\n if (n > (UINT64_MAX - 1024)) {\n return 0;\n }\n n += 1024;\n }\n\n return n;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);\n}\n\ninline void //\nwuffs_base__pixel_config::invalidate() {\n wuffs_base__pixel_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__pixel_config::is_valid() {\n return wuffs_base__pixel_config__is_valid(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__p" +
- "ixel_config::pixel_format() {\n return wuffs_base__pixel_config__pixel_format(this);\n}\n\ninline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config::pixel_subsampling() {\n return wuffs_base__pixel_config__pixel_subsampling(this);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config::bounds() {\n return wuffs_base__pixel_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::width() {\n return wuffs_base__pixel_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::height() {\n return wuffs_base__pixel_config__height(this);\n}\n\ninline uint64_t //\nwuffs_base__pixel_config::pixbuf_len() {\n return wuffs_base__pixel_config__pixbuf_len(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\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__pixel_format pixfmt;\n wuffs_base__pixel_subsampling pixsub;\n uint32_t width;\n uint32_t height;\n } private_impl;\n\n#ifdef __cplusplus\n inline void set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height);\n inline void invalidate();\n inline bool is_valid() const;\n inline wuffs_base__pixel_format pixel_format() const;\n inline wuffs_base__pixel_subsampling pixel_subsampling() const;\n inline wuffs_base__rect_ie_u32 bounds() const;\n inline uint32_t width() const;\n inline uint32_t height() const;\n inline uint64_t pixbuf_len() const;\n#endif // __cplusplus\n\n} wuffs_base__pixel_config;\n\nstatic inline wuffs_base__pixel_config //\nwuffs_base__null_pixel_config() {\n wuffs_base__pixel_config ret;\n ret.private_impl.pix" +
+ "fmt = 0;\n ret.private_impl.pixsub = 0;\n ret.private_impl.width = 0;\n ret.private_impl.height = 0;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__pixel_config__set(wuffs_base__pixel_config* c,\n wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n if (!c) {\n return;\n }\n if (pixfmt) {\n uint64_t wh = ((uint64_t)width) * ((uint64_t)height);\n // TODO: handle things other than 1 byte per pixel.\n if (wh <= ((uint64_t)SIZE_MAX)) {\n c->private_impl.pixfmt = pixfmt;\n c->private_impl.pixsub = pixsub;\n c->private_impl.width = width;\n c->private_impl.height = height;\n return;\n }\n }\n\n c->private_impl.pixfmt = 0;\n c->private_impl.pixsub = 0;\n c->private_impl.width = 0;\n c->private_impl.height = 0;\n}\n\nstatic inline void //\nwuffs_base__pixel_co" +
+ "nfig__invalidate(wuffs_base__pixel_config* c) {\n if (c) {\n c->private_impl.pixfmt = 0;\n c->private_impl.pixsub = 0;\n c->private_impl.width = 0;\n c->private_impl.height = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {\n return c && c->private_impl.pixfmt;\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixfmt : 0;\n}\n\nstatic inline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixsub : 0;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {\n if (c) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = c->private_impl.width;\n ret.max_excl_y = c->private_impl.height;\n return ret;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl" +
+ "_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.width : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.height : 0;\n}\n\n// TODO: this is the right API for planar (not interleaved) pixbufs? Should it\n// allow decoding into a color model different from the format's intrinsic one?\n// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?\nstatic inline uint64_t //\nwuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {\n if (!c) {\n return 0;\n }\n if (wuffs_base__pixel_format__is_planar(c->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return 0;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(c->private_impl.pixfmt);\n if ((bits_per_pixel == 0" +
+ ") || ((bits_per_pixel % 8) != 0)) {\n // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n return 0;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint64_t n =\n ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);\n if (n > (UINT64_MAX / bytes_per_pixel)) {\n return 0;\n }\n n *= bytes_per_pixel;\n\n if (wuffs_base__pixel_format__is_indexed(c->private_impl.pixfmt)) {\n if (n > (UINT64_MAX - 1024)) {\n return 0;\n }\n n += 1024;\n }\n\n return n;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);\n}\n\ninline void //\nwuffs_base__pixel_config::invalidate() {\n wuffs_base__pixel_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__pixel_config::is_valid() const {\n return" +
+ " wuffs_base__pixel_config__is_valid(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__pixel_config::pixel_format() const {\n return wuffs_base__pixel_config__pixel_format(this);\n}\n\ninline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config::pixel_subsampling() const {\n return wuffs_base__pixel_config__pixel_subsampling(this);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config::bounds() const {\n return wuffs_base__pixel_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::width() const {\n return wuffs_base__pixel_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::height() const {\n return wuffs_base__pixel_config__height(this);\n}\n\ninline uint64_t //\nwuffs_base__pixel_config::pixbuf_len() const {\n return wuffs_base__pixel_config__pixbuf_len(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\ntypedef struct {\n wuffs_base__pixel_config pixcfg;\n\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 uint64_t first_frame_io_position;\n bool first_frame_is_opaque;\n } private_impl;\n\n#ifdef __cplusplus\n inline void set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque);\n inline void invalidate();\n inline bool is_valid();\n inline uint64_t first_frame_io_position();\n inline bool first_frame_is_opaque();\n#endif // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_config //\nwuffs_base__null_image_config() {\n wuffs_base__image_config ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.first_frame_io_position = 0;\n ret.private_impl.first_frame_is_opaque" +
- " = false;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__image_config__set(wuffs_base__image_config* c,\n wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n if (!c) {\n return;\n }\n if (wuffs_base__pixel_format__is_valid(pixfmt)) {\n c->pixcfg.private_impl.pixfmt = pixfmt;\n c->pixcfg.private_impl.pixsub = pixsub;\n c->pixcfg.private_impl.width = width;\n c->pixcfg.private_impl.height = height;\n c->private_impl.first_frame_io_position = first_frame_io_position;\n c->private_impl.first_frame_is_opaque = first_frame_is_opaque;\n return;\n }\n\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.w" +
- "idth = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n}\n\nstatic inline void //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n if (c) {\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__image_config__is_valid(wuffs_base__image_config* c) {\n return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t //\nwuffs_base__image_config__first_frame_io_position(wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool //\nwuffs_base__image_config__first_frame_is_opaque(wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_is_opaque : false;\n}\n\n#ifdef __cplusplus\n\ninline void " +
- " //\nwuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,\n first_frame_io_position, first_frame_is_opaque);\n}\n\ninline void //\nwuffs_base__image_config::invalidate() {\n wuffs_base__image_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__image_config::is_valid() {\n return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t //\nwuffs_base__image_config::first_frame_io_position() {\n return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool //\nwuffs_base__image_config::first_frame_is_opaque() {\n return wuffs_base__image_config__first_frame_is_opaque(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct {\n wuffs_base__pixel_config pixcfg;\n\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 uint64_t first_frame_io_position;\n bool first_frame_is_opaque;\n } private_impl;\n\n#ifdef __cplusplus\n inline void set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque);\n inline void invalidate();\n inline bool is_valid() const;\n inline uint64_t first_frame_io_position() const;\n inline bool first_frame_is_opaque() const;\n#endif // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_config //\nwuffs_base__null_image_config() {\n wuffs_base__image_config ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.first_frame_io_position = 0;\n ret.private_impl.fir" +
+ "st_frame_is_opaque = false;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__image_config__set(wuffs_base__image_config* c,\n wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n if (!c) {\n return;\n }\n if (wuffs_base__pixel_format__is_valid(pixfmt)) {\n c->pixcfg.private_impl.pixfmt = pixfmt;\n c->pixcfg.private_impl.pixsub = pixsub;\n c->pixcfg.private_impl.width = width;\n c->pixcfg.private_impl.height = height;\n c->private_impl.first_frame_io_position = first_frame_io_position;\n c->private_impl.first_frame_is_opaque = first_frame_is_opaque;\n return;\n }\n\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pix" +
+ "cfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n}\n\nstatic inline void //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n if (c) {\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {\n return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t //\nwuffs_base__image_config__first_frame_io_position(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool //\nwuffs_base__image_config__first_frame_is_opaque(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_is_opaqu" +
+ "e : false;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,\n first_frame_io_position, first_frame_is_opaque);\n}\n\ninline void //\nwuffs_base__image_config::invalidate() {\n wuffs_base__image_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__image_config::is_valid() const {\n return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t //\nwuffs_base__image_config::first_frame_io_position() const {\n return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool //\nwuffs_base__image_config::first_frame_is_opaque() const {\n return wuffs_base__image_co" +
+ "nfig__first_frame_is_opaque(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
"// --------\n\n// wuffs_base__animation_blend encodes, for an animated image, how to blend the\n// transparent pixels of this frame with the existing canvas. In Porter-Duff\n// compositing operator terminology:\n// - 0 means the frame may be transparent, and should be blended \"src over\n// dst\", also known as just \"over\".\n// - 1 means the frame may be transparent, and should be blended \"src\".\n// - 2 means the frame is completely opaque, so that \"src over dst\" and \"src\"\n// are equivalent.\n//\n// These semantics are conservative. It is valid for a completely opaque frame\n// to have a blend value other than 2.\ntypedef uint8_t wuffs_base__animation_blend;\n\n#define WUFFS_BASE__ANIMATION_BLEND__SRC_OVER_DST \\\n ((wuffs_base__animation_blend)0)\n#define WUFFS_BASE__ANIMATION_BLEND__SRC ((wuffs_base__animation_blend)1)\n#define WUFFS_BASE__ANIMATION_BLEND__OPAQUE ((wuffs_base__animation_blend)2)\n\n" +
"" +
"// --------\n\n// wuffs_base__animation_disposal encodes, for an animated image, how to\n// dispose of a frame after displaying it:\n// - None means to draw the next frame on top of this one.\n// - Restore Background means to clear the frame's dirty rectangle to \"the\n// background color\" (in practice, this means transparent black) before\n// drawing the next frame.\n// - Restore Previous means to undo the current frame, so that the next frame\n// is drawn on top of the previous one.\ntypedef uint8_t wuffs_base__animation_disposal;\n\n#define WUFFS_BASE__ANIMATION_DISPOSAL__NONE ((wuffs_base__animation_disposal)0)\n#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND \\\n ((wuffs_base__animation_disposal)1)\n#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS \\\n ((wuffs_base__animation_disposal)2)\n\n" +
"" +
- "// --------\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__rect_ie_u32 bounds;\n wuffs_base__flicks duration;\n uint64_t index;\n uint64_t io_position;\n wuffs_base__animation_blend blend;\n wuffs_base__animation_disposal disposal;\n } private_impl;\n\n#ifdef __cplusplus\n inline void update(wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal);\n inline wuffs_base__rect_ie_u32 bounds();\n inline uint32_t width();\n inline uint32_t height();\n inline wuffs_base__flicks duration();\n inline uint64_t index();\n inline uint64_t io_position();\n inline wuffs_base__animation_blend blend();\n inline wuffs_base__animation_disposal disposal();\n#endif // __cpluspl" +
- "us\n\n} wuffs_base__frame_config;\n\nstatic inline wuffs_base__frame_config //\nwuffs_base__null_frame_config() {\n wuffs_base__frame_config ret;\n ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);\n ret.private_impl.duration = 0;\n ret.private_impl.index = 0;\n ret.private_impl.io_position = 0;\n ret.private_impl.blend = 0;\n ret.private_impl.disposal = 0;\n return ret;\n}\n\nstatic inline void //\nwuffs_base__frame_config__update(wuffs_base__frame_config* c,\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal) {\n if (!c) {\n return;\n }\n\n c->private_impl.bounds = bounds;\n c->private_impl.duration = duration;\n c->private_impl.index = index;\n c->private_impl.io_position = io_po" +
- "sition;\n c->private_impl.blend = blend;\n c->private_impl.disposal = disposal;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config__bounds(wuffs_base__frame_config* c) {\n if (c) {\n return c->private_impl.bounds;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__width(wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__height(wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;\n}\n\n// wuffs_base__frame_config__duration returns the amount of time to display\n// this frame. Zero means to display forever - a still (non-animated) image.\nstatic inline wuffs_base__flicks //\nwuffs_base__frame_config__duration(wuffs_base__frame_config* c) {\n return c ? c->private_impl.duration : 0;\n}\n\n// wuffs_b" +
- "ase__frame_config__index returns the index of this frame. The first\n// frame in an image has index 0, the second frame has index 1, and so on.\nstatic inline uint64_t //\nwuffs_base__frame_config__index(wuffs_base__frame_config* c) {\n return c ? c->private_impl.index : 0;\n}\n\n// wuffs_base__frame_config__io_position returns the I/O stream position before\n// the frame config.\nstatic inline uint64_t //\nwuffs_base__frame_config__io_position(wuffs_base__frame_config* c) {\n return c ? c->private_impl.io_position : 0;\n}\n\n// wuffs_base__frame_config__blend returns, for an animated image, how to blend\n// the transparent pixels of this frame with the existing canvas.\nstatic inline wuffs_base__animation_blend //\nwuffs_base__frame_config__blend(wuffs_base__frame_config* c) {\n return c ? c->private_impl.blend : 0;\n}\n\n// wuffs_base__frame_config__disposal returns, for an animated image, how to\n// dispose of this frame after displaying it.\nstatic inline wuffs_base__animation_disposal //\nwuffs_base__frame_config__dispos" +
- "al(wuffs_base__frame_config* c) {\n return c ? c->private_impl.disposal : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__frame_config::update(wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal) {\n wuffs_base__frame_config__update(this, bounds, duration, index, io_position,\n blend, disposal);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config::bounds() {\n return wuffs_base__frame_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::width() {\n return wuffs_base__frame_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::height() {\n return wuffs_base__frame_config__height(this);\n}\n\ninline wuffs_base__flicks //\nwuffs_base__frame_config::du" +
- "ration() {\n return wuffs_base__frame_config__duration(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::index() {\n return wuffs_base__frame_config__index(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::io_position() {\n return wuffs_base__frame_config__io_position(this);\n}\n\ninline wuffs_base__animation_blend //\nwuffs_base__frame_config::blend() {\n return wuffs_base__frame_config__blend(this);\n}\n\ninline wuffs_base__animation_disposal //\nwuffs_base__frame_config::disposal() {\n return wuffs_base__frame_config__disposal(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\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__rect_ie_u32 bounds;\n wuffs_base__flicks duration;\n uint64_t index;\n uint64_t io_position;\n wuffs_base__animation_blend blend;\n wuffs_base__animation_disposal disposal;\n wuffs_base__color_u32_argb_premul background_color;\n } private_impl;\n\n#ifdef __cplusplus\n inline void update(wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color);\n inline wuffs_base__rect_ie_u32 bounds() const;\n inline uint32_t width() const;\n inline uint32_t height() const;\n inline wuffs_base__flicks duration() const;\n inline uint64_t index()" +
+ " const;\n inline uint64_t io_position() const;\n inline wuffs_base__animation_blend blend() const;\n inline wuffs_base__animation_disposal disposal() const;\n inline wuffs_base__color_u32_argb_premul background_color() const;\n#endif // __cplusplus\n\n} wuffs_base__frame_config;\n\nstatic inline wuffs_base__frame_config //\nwuffs_base__null_frame_config() {\n wuffs_base__frame_config ret;\n ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);\n ret.private_impl.duration = 0;\n ret.private_impl.index = 0;\n ret.private_impl.io_position = 0;\n ret.private_impl.blend = 0;\n ret.private_impl.disposal = 0;\n return ret;\n}\n\nstatic inline void //\nwuffs_base__frame_config__update(\n wuffs_base__frame_config* c,\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color) {\n if (!c) {\n return;\n }\n\n c->privat" +
+ "e_impl.bounds = bounds;\n c->private_impl.duration = duration;\n c->private_impl.index = index;\n c->private_impl.io_position = io_position;\n c->private_impl.blend = blend;\n c->private_impl.disposal = disposal;\n c->private_impl.background_color = background_color;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {\n if (c) {\n return c->private_impl.bounds;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__width(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__frame_config__height(const wuffs_base__frame_config* c) {\n return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;\n}\n\n// wuffs_base__frame_config__duration returns the amount of time to display\n// this frame. Zero means to d" +
+ "isplay forever - a still (non-animated) image.\nstatic inline wuffs_base__flicks //\nwuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.duration : 0;\n}\n\n// wuffs_base__frame_config__index returns the index of this frame. The first\n// frame in an image has index 0, the second frame has index 1, and so on.\nstatic inline uint64_t //\nwuffs_base__frame_config__index(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.index : 0;\n}\n\n// wuffs_base__frame_config__io_position returns the I/O stream position before\n// the frame config.\nstatic inline uint64_t //\nwuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.io_position : 0;\n}\n\n// wuffs_base__frame_config__blend returns, for an animated image, how to blend\n// the transparent pixels of this frame with the existing canvas.\nstatic inline wuffs_base__animation_blend //\nwuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {\n return c ? c->p" +
+ "rivate_impl.blend : 0;\n}\n\n// wuffs_base__frame_config__disposal returns, for an animated image, how to\n// dispose of this frame after displaying it.\nstatic inline wuffs_base__animation_disposal //\nwuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.disposal : 0;\n}\n\nstatic inline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {\n return c ? c->private_impl.background_color : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__frame_config::update(\n wuffs_base__rect_ie_u32 bounds,\n wuffs_base__flicks duration,\n uint64_t index,\n uint64_t io_position,\n wuffs_base__animation_blend blend,\n wuffs_base__animation_disposal disposal,\n wuffs_base__color_u32_argb_premul background_color) {\n wuffs_base__frame_config__update(this, bounds, duration, index, io_position,\n blend, disposal, background_color);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_b" +
+ "ase__frame_config::bounds() const {\n return wuffs_base__frame_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::width() const {\n return wuffs_base__frame_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__frame_config::height() const {\n return wuffs_base__frame_config__height(this);\n}\n\ninline wuffs_base__flicks //\nwuffs_base__frame_config::duration() const {\n return wuffs_base__frame_config__duration(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::index() const {\n return wuffs_base__frame_config__index(this);\n}\n\ninline uint64_t //\nwuffs_base__frame_config::io_position() const {\n return wuffs_base__frame_config__io_position(this);\n}\n\ninline wuffs_base__animation_blend //\nwuffs_base__frame_config::blend() const {\n return wuffs_base__frame_config__blend(this);\n}\n\ninline wuffs_base__animation_disposal //\nwuffs_base__frame_config::disposal() const {\n return wuffs_base__frame_config__disposal(this);\n}\n\ninline wuffs_base__color_u32_argb_premul //\nwuffs_base__frame_confi" +
+ "g::background_color() const {\n return wuffs_base__frame_config__background_color(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\ntypedef struct {\n wuffs_base__pixel_config pixcfg;\n\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__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];\n // TODO: color spaces.\n } private_impl;\n\n#ifdef __cplusplus\n inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory);\n inline wuffs_base__slice_u8 palette();\n inline wuffs_base__pixel_format pixel_format();\n inline wuffs_base__table_u8 plane(uint32_t p);\n#endif // __cplusplus\n\n} wuffs_base__pixel_buffer;\n\nstatic inline wuffs_base__pixel_buffer //\nwuffs_base__null_pixel_buffer() {\n wuffs_base__pixel_buffer ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.planes[0] = wuffs_base__null_table_u8();\n ret.private_impl.planes[1] = wuffs_base__null_table_u8();\n ret.private_impl.planes[2] = wuffs_base__null_tabl" +
- "e_u8();\n ret.private_impl.planes[3] = wuffs_base__null_table_u8();\n return ret;\n}\n\nstatic inline wuffs_base__status //\nwuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,\n wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory) {\n if (!b) {\n return wuffs_base__error__bad_receiver;\n }\n memset(b, 0, sizeof(*b));\n if (!pixcfg) {\n return wuffs_base__error__bad_argument;\n }\n if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return wuffs_base__error__bad_argument;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n return wuffs_base__error__bad_argument;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint8_t* ptr = pixbuf_memory.ptr;\n uint64_t len = pixbuf_memo" +
- "ry.len;\n if (wuffs_base__pixel_format__is_indexed(pixcfg->private_impl.pixfmt)) {\n // Split a 1024 byte chunk (256 palette entries × 4 bytes per entry) from\n // the start of pixbuf_memory. We split from the start, not the end, so\n // that the both chunks' pointers have the same alignment as the original\n // pointer, up to an alignment of 1024.\n if (len < 1024) {\n return wuffs_base__error__bad_argument_length_too_short;\n }\n wuffs_base__table_u8* tab =\n &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n tab->ptr = ptr;\n tab->width = 1024;\n tab->height = 1;\n tab->stride = 1024;\n ptr += 1024;\n len -= 1024;\n }\n\n uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *\n ((uint64_t)pixcfg->private_impl.height);\n size_t width = (size_t)(pixcfg->private_impl.width);\n if ((wh > (UINT64_MAX / bytes_per_pixel)) ||\n (width > (SIZE_MAX / bytes_per_pixel))) {\n return wuffs_base__error__bad_argument;\n }\n wh *= bytes_per_pix" +
- "el;\n width *= bytes_per_pixel;\n if (wh > len) {\n return wuffs_base__error__bad_argument_length_too_short;\n }\n\n b->pixcfg = *pixcfg;\n wuffs_base__table_u8* tab = &b->private_impl.planes[0];\n tab->ptr = ptr;\n tab->width = width;\n tab->height = pixcfg->private_impl.height;\n tab->stride = width;\n return NULL;\n}\n\n// wuffs_base__pixel_buffer__palette returns the palette color data. If\n// non-empty, it will have length 1024.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* b) {\n if (b &&\n wuffs_base__pixel_format__is_indexed(b->pixcfg.private_impl.pixfmt)) {\n wuffs_base__table_u8* tab =\n &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n if ((tab->width == 1024) && (tab->height == 1)) {\n return wuffs_base__make_slice_u8(tab->ptr, 1024);\n }\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_buffer__pixel_format(wuffs_base__pixel_buffer* b) {\n i" +
- "f (b) {\n return b->pixcfg.private_impl.pixfmt;\n }\n return WUFFS_BASE__PIXEL_FORMAT__INVALID;\n}\n\nstatic inline wuffs_base__table_u8 //\nwuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* b, uint32_t p) {\n if (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {\n return b->private_impl.planes[p];\n }\n\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\n#ifdef __cplusplus\n\ninline wuffs_base__status //\nwuffs_base__pixel_buffer::set_from_slice(wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory) {\n return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__slice_u8 //\nwuffs_base__pixel_buffer::palette() {\n return wuffs_base__pixel_buffer__palette(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__pixel_buffer::pixel_format() {\n return wuffs_base__pixel_buffer__pixel_format(this);\n}\n\ninline wuffs_base__table_u8 //\nwuffs_base" +
- "__pixel_buffer::plane(uint32_t p) {\n return wuffs_base__pixel_buffer__plane(this, p);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct {\n wuffs_base__pixel_config pixcfg;\n\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__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];\n // TODO: color spaces.\n } private_impl;\n\n#ifdef __cplusplus\n inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory);\n inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,\n wuffs_base__table_u8 pixbuf_memory);\n inline wuffs_base__slice_u8 palette();\n inline wuffs_base__pixel_format pixel_format() const;\n inline wuffs_base__table_u8 plane(uint32_t p);\n#endif // __cplusplus\n\n} wuffs_base__pixel_buffer;\n\nstatic inline wuffs_base__pixel_buffer //\nwuffs_base__null_pixel_buffer() {\n wuffs_base__pixel_buffer ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.pri" +
+ "vate_impl.planes[0] = wuffs_base__null_table_u8();\n ret.private_impl.planes[1] = wuffs_base__null_table_u8();\n ret.private_impl.planes[2] = wuffs_base__null_table_u8();\n ret.private_impl.planes[3] = wuffs_base__null_table_u8();\n return ret;\n}\n\nstatic inline wuffs_base__status //\nwuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,\n wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory) {\n if (!b) {\n return wuffs_base__error__bad_receiver;\n }\n memset(b, 0, sizeof(*b));\n if (!pixcfg) {\n return wuffs_base__error__bad_argument;\n }\n if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return wuffs_base__error__unsupported_option;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) !=" +
+ " 0)) {\n // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n return wuffs_base__error__unsupported_option;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint8_t* ptr = pixbuf_memory.ptr;\n uint64_t len = pixbuf_memory.len;\n if (wuffs_base__pixel_format__is_indexed(pixcfg->private_impl.pixfmt)) {\n // Split a 1024 byte chunk (256 palette entries × 4 bytes per entry) from\n // the start of pixbuf_memory. We split from the start, not the end, so\n // that the both chunks' pointers have the same alignment as the original\n // pointer, up to an alignment of 1024.\n if (len < 1024) {\n return wuffs_base__error__bad_argument_length_too_short;\n }\n wuffs_base__table_u8* tab =\n &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n tab->ptr = ptr;\n tab->width = 1024;\n tab->height = 1;\n tab->stride = 1024;\n ptr += 1024;\n len -= 1024;\n }\n\n uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *\n ((uint64_t)pixcfg" +
+ "->private_impl.height);\n size_t width = (size_t)(pixcfg->private_impl.width);\n if ((wh > (UINT64_MAX / bytes_per_pixel)) ||\n (width > (SIZE_MAX / bytes_per_pixel))) {\n return wuffs_base__error__bad_argument;\n }\n wh *= bytes_per_pixel;\n width *= bytes_per_pixel;\n if (wh > len) {\n return wuffs_base__error__bad_argument_length_too_short;\n }\n\n b->pixcfg = *pixcfg;\n wuffs_base__table_u8* tab = &b->private_impl.planes[0];\n tab->ptr = ptr;\n tab->width = width;\n tab->height = pixcfg->private_impl.height;\n tab->stride = width;\n return NULL;\n}\n\nstatic inline wuffs_base__status //\nwuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,\n wuffs_base__pixel_config* pixcfg,\n wuffs_base__table_u8 pixbuf_memory) {\n if (!b) {\n return wuffs_base__error__bad_receiver;\n }\n memset(b, 0, sizeof(*b));\n if (!pixcfg ||\n wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n return wuffs_b" +
+ "ase__error__bad_argument;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n return wuffs_base__error__unsupported_option;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint64_t width_in_bytes =\n ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;\n if ((width_in_bytes > pixbuf_memory.width) ||\n (pixcfg->private_impl.height > pixbuf_memory.height)) {\n return wuffs_base__error__bad_argument;\n }\n\n b->pixcfg = *pixcfg;\n b->private_impl.planes[0] = pixbuf_memory;\n return NULL;\n}\n\n// wuffs_base__pixel_buffer__palette returns the palette color data. If\n// non-empty, it will have length 1024.\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* b) {\n if (b &&\n wuffs_base__pixel_format__is_indexed(b->pixcfg.private_impl.pixfmt)) {\n wuffs_base" +
+ "__table_u8* tab =\n &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n if ((tab->width == 1024) && (tab->height == 1)) {\n return wuffs_base__make_slice_u8(tab->ptr, 1024);\n }\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {\n if (b) {\n return b->pixcfg.private_impl.pixfmt;\n }\n return WUFFS_BASE__PIXEL_FORMAT__INVALID;\n}\n\nstatic inline wuffs_base__table_u8 //\nwuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* b, uint32_t p) {\n if (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {\n return b->private_impl.planes[p];\n }\n\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\n#ifdef __cplusplus\n\ninline wuffs_base__status //\nwuffs_base__pixel_buffer::set_from_slice(wuffs_base__pixel_config* pixcfg,\n wuffs_base__slice_u8 pixbuf_memory" +
+ ") {\n return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__status //\nwuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,\n wuffs_base__table_u8 pixbuf_memory) {\n return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__slice_u8 //\nwuffs_base__pixel_buffer::palette() {\n return wuffs_base__pixel_buffer__palette(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__pixel_buffer::pixel_format() const {\n return wuffs_base__pixel_buffer__pixel_format(this);\n}\n\ninline wuffs_base__table_u8 //\nwuffs_base__pixel_buffer::plane(uint32_t p) {\n return wuffs_base__pixel_buffer__plane(this, p);\n}\n\n#endif // __cplusplus\n\n" +
"" +
"// --------\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 uint8_t TODO;\n } private_impl;\n\n#ifdef __cplusplus\n#endif // __cplusplus\n\n} wuffs_base__decode_frame_options;\n\n#ifdef __cplusplus\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\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 // TODO: should the func type take restrict pointers?\n uint64_t (*func)(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src);\n } private_impl;\n\n#ifdef __cplusplus\n inline void prepare(wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette);\n inline uint64_t swizzle_packed(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src);\n#endif // __cplusplus\n\n} wuffs_base__pixel_swizzler;\n\n// TODO: should prepare (both the C and C++ methods) return a status?\n\nvoid //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swi" +
- "zzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette);\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,\n wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src);\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette, src_format,\n " +
- " src_palette);\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler::swizzle_packed(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n return wuffs_base__pixel_swizzler__swizzle_packed(this, dst, dst_palette,\n src);\n}\n\n#endif // __cplusplus\n" +
+ "// --------\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 // TODO: should the func type take restrict pointers?\n uint64_t (*func)(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src);\n } private_impl;\n\n#ifdef __cplusplus\n inline wuffs_base__status prepare(wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette);\n inline uint64_t swizzle_interleaved(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) const;\n#endif // __cplusplus\n\n} wuffs_base__pixel_swizzler;\n\nwuffs_base__status //\nwuffs_base__pixel_swizzler__prepare(w" +
+ "uffs_base__pixel_swizzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette);\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_interleaved(\n const wuffs_base__pixel_swizzler* p,\n wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src);\n\n#ifdef __cplusplus\n\ninline wuffs_base__status //\nwuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n return wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette,\n src_format, src_palette);\n}\n\nuint64_t //\nwu" +
+ "ffs_base__pixel_swizzler::swizzle_interleaved(\n wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) const {\n return wuffs_base__pixel_swizzler__swizzle_interleaved(this, dst, dst_palette,\n src);\n}\n\n#endif // __cplusplus\n" +
""
const baseIOPrivateH = "" +
- "// ---------------- I/O\n\nstatic inline bool //\nwuffs_base__io_buffer__is_valid(wuffs_base__io_buffer buf) {\n return (buf.data.ptr || (buf.data.len == 0)) &&\n (buf.data.len >= buf.meta.wi) && (buf.meta.wi >= buf.meta.ri);\n}\n\n// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but\n// it might be handy to programs that use Wuffs. Either delete it, or promote\n// it to the public API.\n//\n// If making this function public (i.e. moving it to base-header.h), it also\n// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.\n\nstatic inline bool //\nwuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {\n wuffs_base__io_buffer* buf = o.private_impl.buf;\n return buf && buf->meta.closed &&\n (buf->data.ptr + buf->meta.wi == o.private_impl.limit);\n}\n\nstatic inline bool //\nwuffs_base__io_reader__is_valid(wuffs_base__io_reader o) {\n wuffs_base__io_buffer* buf = o.private_impl.buf;\n // Note: if making this function public (i.e. moving it to base-header.h), it\n // also " +
- "needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.\n return buf ? ((buf->data.ptr <= o.private_impl.mark) &&\n (o.private_impl.mark <= o.private_impl.limit) &&\n (o.private_impl.limit <= buf->data.ptr + buf->data.len))\n : ((o.private_impl.mark == NULL) &&\n (o.private_impl.limit == NULL));\n}\n\nstatic inline bool //\nwuffs_base__io_writer__is_valid(wuffs_base__io_writer o) {\n wuffs_base__io_buffer* buf = o.private_impl.buf;\n // Note: if making this function public (i.e. moving it to base-header.h), it\n // also needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.\n return buf ? ((buf->data.ptr <= o.private_impl.mark) &&\n (o.private_impl.mark <= o.private_impl.limit) &&\n (o.private_impl.limit <= buf->data.ptr + buf->data.len))\n : ((o.private_impl.mark == NULL) &&\n (o.private_impl.limit == NULL));\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_history(uin" +
- "t8_t** ptr_iop_w,\n uint8_t* io0_w,\n uint8_t* io1_w,\n uint32_t length,\n uint32_t distance) {\n if (!distance) {\n return 0;\n }\n uint8_t* p = *ptr_iop_w;\n if ((size_t)(p - io0_w) < (size_t)(distance)) {\n return 0;\n }\n uint8_t* q = p - distance;\n size_t n = (size_t)(io1_w - p);\n if ((size_t)(length) > n) {\n length = (uint32_t)(n);\n } else {\n n = (size_t)(length);\n }\n // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that\n // is mostly because 3 is the minimum length for the deflate format. This\n // function implementation shouldn't overfit to that one format. Perhaps the\n // copy_n_from_history Wuffs method should also take an unroll hint argument,\n // and the cgen can look if that argument is the constant expression '3'.\n //\n // See also wuffs_base__io_writer__copy_n_from_history_fast below.\n //\n " +
- "// Alternatively, or additionally, have a sloppy_copy_n_from_history method\n // that copies 8 bytes at a time, possibly writing more than length bytes?\n for (; n >= 3; n -= 3) {\n *p++ = *q++;\n *p++ = *q++;\n *p++ = *q++;\n }\n for (; n; n--) {\n *p++ = *q++;\n }\n *ptr_iop_w = p;\n return length;\n}\n\n// wuffs_base__io_writer__copy_n_from_history_fast is like the\n// wuffs_base__io_writer__copy_n_from_history function above, but has stronger\n// pre-conditions. The caller needs to prove that:\n// - distance > 0\n// - distance <= (*ptr_iop_w - io0_w)\n// - length <= (io1_w - *ptr_iop_w)\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,\n uint8_t* io0_w,\n uint8_t* io1_w,\n uint32_t length,\n uint32_t distance) {\n uint8_t* p = *ptr_iop_w;\n uint8_t* q = p - distance;\n " +
- " uint32_t n = length;\n for (; n >= 3; n -= 3) {\n *p++ = *q++;\n *p++ = *q++;\n *p++ = *q++;\n }\n for (; n; n--) {\n *p++ = *q++;\n }\n *ptr_iop_w = p;\n return length;\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,\n uint8_t* io1_w,\n uint32_t length,\n uint8_t** ptr_iop_r,\n uint8_t* io1_r) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = length;\n if (n > ((size_t)(io1_w - iop_w))) {\n n = (size_t)(io1_w - iop_w);\n }\n uint8_t* iop_r = *ptr_iop_r;\n if (n > ((size_t)(io1_r - iop_r))) {\n n = (size_t)(io1_r - iop_r);\n }\n if (n > 0) {\n memmove(iop_w, iop_r, n);\n *ptr_iop_w += n;\n *ptr_iop_r += n;\n }\n return (uint32_t)(n);\n}\n\nstatic inline uint64_t //\nwuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,\n uint8_t* io1_w,\n " +
- " wuffs_base__slice_u8 src) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = src.len;\n if (n > ((size_t)(io1_w - iop_w))) {\n n = (size_t)(io1_w - iop_w);\n }\n if (n > 0) {\n memmove(iop_w, src.ptr, n);\n *ptr_iop_w += n;\n }\n return (uint64_t)(n);\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,\n uint8_t* io1_w,\n uint32_t length,\n wuffs_base__slice_u8 src) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = src.len;\n if (n > length) {\n n = length;\n }\n if (n > ((size_t)(io1_w - iop_w))) {\n n = (size_t)(io1_w - iop_w);\n }\n if (n > 0) {\n memmove(iop_w, src.ptr, n);\n *ptr_iop_w += n;\n }\n return (uint32_t)(n);\n}\n\nstatic inline wuffs_base__empty_struct //\nwuffs_base__io_reader__set(wuffs_base__io_reader* o,\n wuffs_base__io_buffer* b,\n uint8_t** ptr_iop_r,\n " +
- " uint8_t** ptr_io1_r,\n wuffs_base__slice_u8 data) {\n b->data = data;\n b->meta.wi = data.len;\n b->meta.ri = 0;\n b->meta.pos = 0;\n b->meta.closed = false;\n\n o->private_impl.buf = b;\n o->private_impl.mark = data.ptr;\n o->private_impl.limit = data.ptr + data.len;\n *ptr_iop_r = data.ptr;\n *ptr_io1_r = data.ptr + data.len;\n\n wuffs_base__empty_struct ret;\n ret.private_impl = 0;\n return ret;\n}\n\nstatic inline wuffs_base__empty_struct //\nwuffs_base__io_reader__set_limit(wuffs_base__io_reader* o,\n uint8_t* iop_r,\n uint64_t limit) {\n if (o && (((size_t)(o->private_impl.limit - iop_r)) > limit)) {\n o->private_impl.limit = iop_r + limit;\n }\n\n wuffs_base__empty_struct ret;\n ret.private_impl = 0;\n return ret;\n}\n\nstatic inline wuffs_base__empty_struct //\nwuffs_base__io_reader__set_mark(wuffs_base__io_reader* o, uint8_t* mark) {\n o->private_impl.mark = mark;\n\n wuffs_base__empty_struct ret;\n ret." +
- "private_impl = 0;\n return ret;\n}\n\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io1_r, uint64_t n) {\n if (n <= ((size_t)(io1_r - *ptr_iop_r))) {\n uint8_t* p = *ptr_iop_r;\n *ptr_iop_r += n;\n return wuffs_base__make_slice_u8(p, n);\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__empty_struct //\nwuffs_base__io_writer__set(wuffs_base__io_writer* o,\n wuffs_base__io_buffer* b,\n uint8_t** ptr_iop_w,\n uint8_t** ptr_io1_w,\n wuffs_base__slice_u8 data) {\n b->data = data;\n b->meta.wi = 0;\n b->meta.ri = 0;\n b->meta.pos = 0;\n b->meta.closed = false;\n\n o->private_impl.buf = b;\n o->private_impl.mark = data.ptr;\n o->private_impl.limit = data.ptr + data.len;\n *ptr_iop_w = data.ptr;\n *ptr_io1_w = data.ptr + data.len;\n\n wuffs_base__empty_struct ret;\n ret.private_impl = 0;\n return ret;\n}\n\nstatic inline wuffs_base__empty_str" +
- "uct //\nwuffs_base__io_writer__set_mark(wuffs_base__io_writer* o, uint8_t* mark) {\n o->private_impl.mark = mark;\n\n wuffs_base__empty_struct ret;\n ret.private_impl = 0;\n return ret;\n}\n\n" +
+ "// ---------------- I/O\n\n// \"Null\" as in \"/dev/null\", not as in \"nullptr\".\n//\n// TODO: ensure that this is zero-initialized.\nstatic wuffs_base__io_buffer wuffs_base__global__null_io_buffer;\n\nstatic inline wuffs_base__io_buffer* //\nwuffs_base__null_io_reader() {\n return &wuffs_base__global__null_io_buffer;\n}\n\nstatic inline wuffs_base__io_buffer* //\nwuffs_base__null_io_writer() {\n return &wuffs_base__global__null_io_buffer;\n}\n\nstatic inline uint64_t //\nwuffs_base__io__count_since(uint64_t mark, uint64_t index) {\n if (index >= mark) {\n return index - mark;\n }\n return 0;\n}\n\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__io__since(uint64_t mark, uint64_t index, uint8_t* ptr) {\n if (index >= mark) {\n return wuffs_base__make_slice_u8(ptr + mark, index - mark);\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,\n uint8_t* io1_w,\n " +
+ " uint8_t* io2_w,\n uint32_t length,\n uint32_t distance) {\n if (!distance) {\n return 0;\n }\n uint8_t* p = *ptr_iop_w;\n if ((size_t)(p - io1_w) < (size_t)(distance)) {\n return 0;\n }\n uint8_t* q = p - distance;\n size_t n = (size_t)(io2_w - p);\n if ((size_t)(length) > n) {\n length = (uint32_t)(n);\n } else {\n n = (size_t)(length);\n }\n // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that\n // is mostly because 3 is the minimum length for the deflate format. This\n // function implementation shouldn't overfit to that one format. Perhaps the\n // copy_n_from_history Wuffs method should also take an unroll hint argument,\n // and the cgen can look if that argument is the constant expression '3'.\n //\n // See also wuffs_base__io_writer__copy_n_from_history_fast below.\n //\n // Alternatively, or additionally, have a sloppy_copy_n_from_history method\n // that copies 8 bytes at a time, poss" +
+ "ibly writing more than length bytes?\n for (; n >= 3; n -= 3) {\n *p++ = *q++;\n *p++ = *q++;\n *p++ = *q++;\n }\n for (; n; n--) {\n *p++ = *q++;\n }\n *ptr_iop_w = p;\n return length;\n}\n\n// wuffs_base__io_writer__copy_n_from_history_fast is like the\n// wuffs_base__io_writer__copy_n_from_history function above, but has stronger\n// pre-conditions. The caller needs to prove that:\n// - distance > 0\n// - distance <= (*ptr_iop_w - io1_w)\n// - length <= (io2_w - *ptr_iop_w)\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,\n uint8_t* io1_w,\n uint8_t* io2_w,\n uint32_t length,\n uint32_t distance) {\n uint8_t* p = *ptr_iop_w;\n uint8_t* q = p - distance;\n uint32_t n = length;\n for (; n >= 3; n -= 3) {\n *p++ = *q++;\n *p++ = *q++;\n *p++ = *q++;\n }\n for (; n; " +
+ "n--) {\n *p++ = *q++;\n }\n *ptr_iop_w = p;\n return length;\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,\n uint8_t* io2_w,\n uint32_t length,\n uint8_t** ptr_iop_r,\n uint8_t* io2_r) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = length;\n if (n > ((size_t)(io2_w - iop_w))) {\n n = (size_t)(io2_w - iop_w);\n }\n uint8_t* iop_r = *ptr_iop_r;\n if (n > ((size_t)(io2_r - iop_r))) {\n n = (size_t)(io2_r - iop_r);\n }\n if (n > 0) {\n memmove(iop_w, iop_r, n);\n *ptr_iop_w += n;\n *ptr_iop_r += n;\n }\n return (uint32_t)(n);\n}\n\nstatic inline uint64_t //\nwuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,\n uint8_t* io2_w,\n wuffs_base__slice_u8 src) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = src.len;\n if (n > ((s" +
+ "ize_t)(io2_w - iop_w))) {\n n = (size_t)(io2_w - iop_w);\n }\n if (n > 0) {\n memmove(iop_w, src.ptr, n);\n *ptr_iop_w += n;\n }\n return (uint64_t)(n);\n}\n\nstatic inline uint32_t //\nwuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,\n uint8_t* io2_w,\n uint32_t length,\n wuffs_base__slice_u8 src) {\n uint8_t* iop_w = *ptr_iop_w;\n size_t n = src.len;\n if (n > length) {\n n = length;\n }\n if (n > ((size_t)(io2_w - iop_w))) {\n n = (size_t)(io2_w - iop_w);\n }\n if (n > 0) {\n memmove(iop_w, src.ptr, n);\n *ptr_iop_w += n;\n }\n return (uint32_t)(n);\n}\n\nstatic inline wuffs_base__io_buffer* //\nwuffs_base__io_reader__set(wuffs_base__io_buffer* b,\n uint8_t** ptr_iop_r,\n uint8_t** ptr_io0_r,\n uint8_t** ptr_io1_r,\n uint8_t** ptr_io2_r,\n wuffs_ba" +
+ "se__slice_u8 data) {\n b->data = data;\n b->meta.wi = data.len;\n b->meta.ri = 0;\n b->meta.pos = 0;\n b->meta.closed = false;\n\n *ptr_iop_r = data.ptr;\n *ptr_io0_r = data.ptr;\n *ptr_io1_r = data.ptr;\n *ptr_io2_r = data.ptr + data.len;\n\n return b;\n}\n\nstatic inline wuffs_base__slice_u8 //\nwuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io2_r, uint64_t n) {\n if (n <= ((size_t)(io2_r - *ptr_iop_r))) {\n uint8_t* p = *ptr_iop_r;\n *ptr_iop_r += n;\n return wuffs_base__make_slice_u8(p, n);\n }\n return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__io_buffer* //\nwuffs_base__io_writer__set(wuffs_base__io_buffer* b,\n uint8_t** ptr_iop_w,\n uint8_t** ptr_io0_w,\n uint8_t** ptr_io1_w,\n uint8_t** ptr_io2_w,\n wuffs_base__slice_u8 data) {\n b->data = data;\n b->meta.wi = 0;\n b->meta.ri = 0;\n b->meta.pos = 0;\n b->meta.closed = false;\n\n *ptr_iop_w = dat" +
+ "a.ptr;\n *ptr_io0_w = data.ptr;\n *ptr_io1_w = data.ptr;\n *ptr_io2_w = data.ptr + data.len;\n\n return b;\n}\n\n" +
"" +
"// ---------------- I/O (Utility)\n\n#define wuffs_base__utility__null_io_reader wuffs_base__null_io_reader\n#define wuffs_base__utility__null_io_writer wuffs_base__null_io_writer\n" +
""
const baseIOPublicH = "" +
- "// ---------------- I/O\n\nstruct wuffs_base__io_buffer__struct;\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 struct wuffs_base__io_buffer__struct* 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* mark;\n uint8_t* limit;\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/ABI\n // compatibility or safety guarantee if you do so.\n struct {\n struct wuffs_base__io_buffer__struct* 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* mark;\n uint8_t* limit;\n } private_impl;\n} wuffs_base__io_writer;\n\n// wuffs_base__io_buffer_meta is the met" +
- "adata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n size_t wi; // Write index. Invariant: wi <= len.\n size_t ri; // Read index. Invariant: ri <= wi.\n uint64_t pos; // Position of the buffer start relative to the stream start.\n bool closed; // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct wuffs_base__io_buffer__struct {\n wuffs_base__slice_u8 data;\n wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n inline void compact();\n inline wuffs_base__io_reader reader();\n inline wuffs_base__io_writer writer();\n inline uint64_t reader_io_position();\n inline uint64_t writer_io_position();\n#endif // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuffs_base__io_buffer //\nwuffs_base__make_io_buffer(wuffs_base__slice_u8 data,\n wuffs_base__io_buffer_meta meta) {\n w" +
- "uffs_base__io_buffer ret;\n ret.data = data;\n ret.meta = meta;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta //\nwuffs_base__make_io_buffer_meta(size_t wi,\n size_t ri,\n uint64_t pos,\n bool closed) {\n wuffs_base__io_buffer_meta ret;\n ret.wi = wi;\n ret.ri = ri;\n ret.pos = pos;\n ret.closed = closed;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer //\nwuffs_base__null_io_buffer() {\n wuffs_base__io_buffer ret;\n ret.data.ptr = NULL;\n ret.data.len = 0;\n ret.meta.wi = 0;\n ret.meta.ri = 0;\n ret.meta.pos = 0;\n ret.meta.closed = false;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta //\nwuffs_base__null_io_buffer_meta() {\n wuffs_base__io_buffer_meta ret;\n ret.wi = 0;\n ret.ri = 0;\n ret.pos = 0;\n ret.closed = false;\n return ret;\n}\n\nstatic inline wuffs_base__io_reader //\nwuffs_base__null_io_reader() {\n wuffs_base__io_reader ret;\n ret.private_impl.buf = NULL;\n ret.private_impl.mark =" +
- " NULL;\n ret.private_impl.limit = NULL;\n return ret;\n}\n\nstatic inline wuffs_base__io_writer //\nwuffs_base__null_io_writer() {\n wuffs_base__io_writer ret;\n ret.private_impl.buf = NULL;\n ret.private_impl.mark = NULL;\n ret.private_impl.limit = NULL;\n return ret;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void //\nwuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {\n if (!buf || (buf->meta.ri == 0)) {\n return;\n }\n buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n size_t n = buf->meta.wi - buf->meta.ri;\n if (n != 0) {\n memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n }\n buf->meta.wi = n;\n buf->meta.ri = 0;\n}\n\nstatic inline wuffs_base__io_reader //\nwuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {\n wuffs_base__io_reader ret;\n ret.private_impl.buf = buf;\n ret.private_impl.mark = NULL;\n ret.private_impl.limit = NULL;\n return ret;\n}\n\nstatic inline wuffs_base__io_writer " +
- "//\nwuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {\n wuffs_base__io_writer ret;\n ret.private_impl.buf = buf;\n ret.private_impl.mark = NULL;\n ret.private_impl.limit = NULL;\n return ret;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__reader_io_position(wuffs_base__io_buffer* buf) {\n return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__writer_io_position(wuffs_base__io_buffer* buf) {\n return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__io_buffer__struct::compact() {\n wuffs_base__io_buffer__compact(this);\n}\n\ninline wuffs_base__io_reader //\nwuffs_base__io_buffer__struct::reader() {\n return wuffs_base__io_buffer__reader(this);\n}\n\ninline wuffs_base__io_writer //\nwuffs_base__io_buffer__struct::writer() {\n return wuffs_base__io_buffer__writer(this);\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::reader_io_position() {\n return wuffs_base__io_" +
- "buffer__reader_io_position(this);\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::writer_io_position() {\n return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif // __cplusplus\n" +
+ "// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\n\n// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n size_t wi; // Write index. Invariant: wi <= len.\n size_t ri; // Read index. Invariant: ri <= wi.\n uint64_t pos; // Position of the buffer start relative to the stream start.\n bool closed; // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct wuffs_base__io_buffer__struct {\n wuffs_base__slice_u8 data;\n wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n inline void compact();\n inline wuffs_base__io_buffer__struct* reader(); // Deprecated.\n inline wuffs_base__io_buffer__struct* writer(); // Deprecated.\n inline uint64_t reader_available() const;\n inline uint64_t reader_io_position() const;\n inline uint64_t writer_available() const" +
+ ";\n inline uint64_t writer_io_position() const;\n#endif // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuffs_base__io_buffer //\nwuffs_base__make_io_buffer(wuffs_base__slice_u8 data,\n wuffs_base__io_buffer_meta meta) {\n wuffs_base__io_buffer ret;\n ret.data = data;\n ret.meta = meta;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta //\nwuffs_base__make_io_buffer_meta(size_t wi,\n size_t ri,\n uint64_t pos,\n bool closed) {\n wuffs_base__io_buffer_meta ret;\n ret.wi = wi;\n ret.ri = ri;\n ret.pos = pos;\n ret.closed = closed;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer //\nwuffs_base__null_io_buffer() {\n wuffs_base__io_buffer ret;\n ret.data.ptr = NULL;\n ret.data.len = 0;\n ret.meta.wi = 0;\n ret.meta.ri = 0;\n ret.meta.pos = 0;\n ret.meta.closed = false;\n return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta //\nwuffs_base__null_io_buffer_meta() {\n wuffs_base__i" +
+ "o_buffer_meta ret;\n ret.wi = 0;\n ret.ri = 0;\n ret.pos = 0;\n ret.closed = false;\n return ret;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void //\nwuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {\n if (!buf || (buf->meta.ri == 0)) {\n return;\n }\n buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n size_t n = buf->meta.wi - buf->meta.ri;\n if (n != 0) {\n memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n }\n buf->meta.wi = n;\n buf->meta.ri = 0;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {\n return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {\n return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {\n return" +
+ " buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t //\nwuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {\n return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__io_buffer__struct::compact() {\n wuffs_base__io_buffer__compact(this);\n}\n\ninline wuffs_base__io_buffer* //\nwuffs_base__io_buffer__struct::reader() {\n return this;\n}\n\ninline wuffs_base__io_buffer* //\nwuffs_base__io_buffer__struct::writer() {\n return this;\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::reader_available() const {\n return wuffs_base__io_buffer__reader_available(this);\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::reader_io_position() const {\n return wuffs_base__io_buffer__reader_io_position(this);\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::writer_available() const {\n return wuffs_base__io_buffer__writer_available(this);\n}\n\ninline uint64_t //\nwuffs_base__io_buffer__struct::writer_io_position() c" +
+ "onst {\n return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif // __cplusplus\n" +
""
const baseRangePrivateH = "" +
@@ -186,39 +191,39 @@
const baseRangePublicH = "" +
"// ---------------- Ranges and Rects\n\n// Ranges are either inclusive (\"range_ii\") or exclusive (\"range_ie\") on the\n// high end. Both the \"ii\" and \"ie\" flavors are useful in practice.\n//\n// The \"ei\" and \"ee\" flavors also exist in theory, but aren't widely used. In\n// Wuffs, the low end is always inclusive.\n//\n// The \"ii\" (closed interval) flavor is useful when refining e.g. \"the set of\n// all uint32_t values\" to a contiguous subset: \"uint32_t values in the closed\n// interval [M, N]\", for uint32_t values M and N. An unrefined type (in other\n// words, the set of all uint32_t values) is not representable in the \"ie\"\n// flavor because if N equals ((1<<32) - 1) then (N + 1) will overflow.\n//\n// On the other hand, the \"ie\" (half-open interval) flavor is recommended by\n// Dijkstra's \"Why numbering should start at zero\" at\n// http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF and a further\n// discussion of motivating rationale is at\n// https://www.quora.com/Why-are-Python-ranges-half-open-exclusive-instead-of-close" +
- "d-inclusive\n//\n// For example, with \"ie\", the number of elements in \"uint32_t values in the\n// half-open interval [M, N)\" is equal to max(0, N-M). Furthermore, that number\n// of elements (in one dimension, a length, in two dimensions, a width or\n// height) is itself representable as a uint32_t without overflow, again for\n// uint32_t values M and N. In the contrasting \"ii\" flavor, the length of the\n// closed interval [0, (1<<32) - 1] is 1<<32, which cannot be represented as a\n// uint32_t. In Wuffs, because of this potential overflow, the \"ie\" flavor has\n// length / width / height methods, but the \"ii\" flavor does not.\n//\n// It is valid for min > max (for range_ii) or for min >= max (for range_ie),\n// in which case the range is empty. There are multiple representations of an\n// empty range.\n\ntypedef struct wuffs_base__range_ii_u32__struct {\n uint32_t min_incl;\n uint32_t max_incl;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__range_ii_u32__struct s);\n inline wuffs_base__range_" +
- "ii_u32__struct intersect(\n wuffs_base__range_ii_u32__struct s);\n inline wuffs_base__range_ii_u32__struct unite(\n wuffs_base__range_ii_u32__struct s);\n inline bool contains(uint32_t x);\n inline bool contains_range(wuffs_base__range_ii_u32__struct s);\n#endif // __cplusplus\n\n} wuffs_base__range_ii_u32;\n\nstatic inline wuffs_base__range_ii_u32 //\nwuffs_base__make_range_ii_u32(uint32_t min_incl, uint32_t max_incl) {\n wuffs_base__range_ii_u32 ret;\n ret.min_incl = min_incl;\n ret.max_incl = max_incl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__is_empty(wuffs_base__range_ii_u32* r) {\n return r->min_incl > r->max_incl;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__equals(wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||\n (wuffs_base__range_ii_u32__is_empty(r) &&\n wuffs_base__range_ii_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ii_u32 //" +
- "\nwuffs_base__range_ii_u32__intersect(wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n wuffs_base__range_ii_u32 t;\n t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u32__min(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32__unite(wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n if (wuffs_base__range_ii_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ii_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ii_u32 t;\n t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u32__max(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__contains(wuffs_base__range_ii_u32* r, uint32_t x) {\n return (r->min_incl <= x) && (x <= r->max_incl);\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__contains_range(wuffs_base__range_ii_u32* r,\n " +
- " wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__equals(\n &s, wuffs_base__range_ii_u32__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ii_u32::is_empty() {\n return wuffs_base__range_ii_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__equals(this, s);\n}\n\ninline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__intersect(this, s);\n}\n\ninline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ii_u32::contains(uint32_t x) {\n return wuffs_base__range_ii_u32__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__contains_range(this, s);\n}\n\n#endif // __c" +
- "plusplus\n\n" +
+ "d-inclusive\n//\n// For example, with \"ie\", the number of elements in \"uint32_t values in the\n// half-open interval [M, N)\" is equal to max(0, N-M). Furthermore, that number\n// of elements (in one dimension, a length, in two dimensions, a width or\n// height) is itself representable as a uint32_t without overflow, again for\n// uint32_t values M and N. In the contrasting \"ii\" flavor, the length of the\n// closed interval [0, (1<<32) - 1] is 1<<32, which cannot be represented as a\n// uint32_t. In Wuffs, because of this potential overflow, the \"ie\" flavor has\n// length / width / height methods, but the \"ii\" flavor does not.\n//\n// It is valid for min > max (for range_ii) or for min >= max (for range_ie),\n// in which case the range is empty. There are multiple representations of an\n// empty range.\n\ntypedef struct wuffs_base__range_ii_u32__struct {\n uint32_t min_incl;\n uint32_t max_incl;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__range_ii_u32__struct s) const;\n inline wuffs_" +
+ "base__range_ii_u32__struct intersect(\n wuffs_base__range_ii_u32__struct s) const;\n inline wuffs_base__range_ii_u32__struct unite(\n wuffs_base__range_ii_u32__struct s) const;\n inline bool contains(uint32_t x) const;\n inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;\n#endif // __cplusplus\n\n} wuffs_base__range_ii_u32;\n\nstatic inline wuffs_base__range_ii_u32 //\nwuffs_base__make_range_ii_u32(uint32_t min_incl, uint32_t max_incl) {\n wuffs_base__range_ii_u32 ret;\n ret.min_incl = min_incl;\n ret.max_incl = max_incl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {\n return r->min_incl > r->max_incl;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||\n (wuffs_base__range_ii_u32__is_empty(r) &&\n wuffs_base__range_ii_u32__is_empty(&s)" +
+ ");\n}\n\nstatic inline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n wuffs_base__range_ii_u32 t;\n t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u32__min(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n if (wuffs_base__range_ii_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ii_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ii_u32 t;\n t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u32__max(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,\n uint32_t x) {\n return (r->min_incl <= x) && (x <= r->max_incl);\n}\n\n" +
+ "static inline bool //\nwuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,\n wuffs_base__range_ii_u32 s) {\n return wuffs_base__range_ii_u32__equals(\n &s, wuffs_base__range_ii_u32__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ii_u32::is_empty() const {\n return wuffs_base__range_ii_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {\n return wuffs_base__range_ii_u32__equals(this, s);\n}\n\ninline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {\n return wuffs_base__range_ii_u32__intersect(this, s);\n}\n\ninline wuffs_base__range_ii_u32 //\nwuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {\n return wuffs_base__range_ii_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ii_u32::contains(uint32_t x) const {\n return wuffs_base__range_ii_u32__contains(this, x);\n}\n\ninline bool //\nwuffs_base_" +
+ "_range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {\n return wuffs_base__range_ii_u32__contains_range(this, s);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\ntypedef struct wuffs_base__range_ie_u32__struct {\n uint32_t min_incl;\n uint32_t max_excl;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__range_ie_u32__struct s);\n inline wuffs_base__range_ie_u32__struct intersect(\n wuffs_base__range_ie_u32__struct s);\n inline wuffs_base__range_ie_u32__struct unite(\n wuffs_base__range_ie_u32__struct s);\n inline bool contains(uint32_t x);\n inline bool contains_range(wuffs_base__range_ie_u32__struct s);\n inline uint32_t length();\n#endif // __cplusplus\n\n} wuffs_base__range_ie_u32;\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__make_range_ie_u32(uint32_t min_incl, uint32_t max_excl) {\n wuffs_base__range_ie_u32 ret;\n ret.min_incl = min_incl;\n ret.max_excl = max_excl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__is_empty(wuffs_base__range_ie_u32* r) {\n return r->min_incl >= r->max_excl;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__equals(wuffs_base__range_ie_u32* r,\n " +
- " wuffs_base__range_ie_u32 s) {\n return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||\n (wuffs_base__range_ie_u32__is_empty(r) &&\n wuffs_base__range_ie_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32__intersect(wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n wuffs_base__range_ie_u32 t;\n t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u32__min(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32__unite(wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n if (wuffs_base__range_ie_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ie_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ie_u32 t;\n t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u32__max(r->max_excl, s.max_excl);\n retu" +
- "rn t;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__contains(wuffs_base__range_ie_u32* r, uint32_t x) {\n return (r->min_incl <= x) && (x < r->max_excl);\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__contains_range(wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__equals(\n &s, wuffs_base__range_ie_u32__intersect(r, s));\n}\n\nstatic inline uint32_t //\nwuffs_base__range_ie_u32__length(wuffs_base__range_ie_u32* r) {\n return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ie_u32::is_empty() {\n return wuffs_base__range_ie_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__equals(this, s);\n}\n\ninline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__intersect(this, s);\n}\n\ninline wuffs_base__" +
- "range_ie_u32 //\nwuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::contains(uint32_t x) {\n return wuffs_base__range_ie_u32__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__contains_range(this, s);\n}\n\ninline uint32_t //\nwuffs_base__range_ie_u32::length() {\n return wuffs_base__range_ie_u32__length(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct wuffs_base__range_ie_u32__struct {\n uint32_t min_incl;\n uint32_t max_excl;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__range_ie_u32__struct s) const;\n inline wuffs_base__range_ie_u32__struct intersect(\n wuffs_base__range_ie_u32__struct s) const;\n inline wuffs_base__range_ie_u32__struct unite(\n wuffs_base__range_ie_u32__struct s) const;\n inline bool contains(uint32_t x) const;\n inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;\n inline uint32_t length() const;\n#endif // __cplusplus\n\n} wuffs_base__range_ie_u32;\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__make_range_ie_u32(uint32_t min_incl, uint32_t max_excl) {\n wuffs_base__range_ie_u32 ret;\n ret.min_incl = min_incl;\n ret.max_excl = max_excl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {\n return r->min_incl >= r->max_excl;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__eq" +
+ "uals(const wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||\n (wuffs_base__range_ie_u32__is_empty(r) &&\n wuffs_base__range_ie_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n wuffs_base__range_ie_u32 t;\n t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u32__min(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n if (wuffs_base__range_ie_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ie_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ie_u32 t;\n t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);\n " +
+ "t.max_excl = wuffs_base__u32__max(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,\n uint32_t x) {\n return (r->min_incl <= x) && (x < r->max_excl);\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,\n wuffs_base__range_ie_u32 s) {\n return wuffs_base__range_ie_u32__equals(\n &s, wuffs_base__range_ie_u32__intersect(r, s));\n}\n\nstatic inline uint32_t //\nwuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {\n return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ie_u32::is_empty() const {\n return wuffs_base__range_ie_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {\n return wuffs_base__range_ie_u32__equals(this, s);\n}\n\ninline wuffs_base__range_ie_u32 //\nwuffs_base__" +
+ "range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {\n return wuffs_base__range_ie_u32__intersect(this, s);\n}\n\ninline wuffs_base__range_ie_u32 //\nwuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {\n return wuffs_base__range_ie_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::contains(uint32_t x) const {\n return wuffs_base__range_ie_u32__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {\n return wuffs_base__range_ie_u32__contains_range(this, s);\n}\n\ninline uint32_t //\nwuffs_base__range_ie_u32::length() const {\n return wuffs_base__range_ie_u32__length(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\ntypedef struct wuffs_base__range_ii_u64__struct {\n uint64_t min_incl;\n uint64_t max_incl;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__range_ii_u64__struct s);\n inline wuffs_base__range_ii_u64__struct intersect(\n wuffs_base__range_ii_u64__struct s);\n inline wuffs_base__range_ii_u64__struct unite(\n wuffs_base__range_ii_u64__struct s);\n inline bool contains(uint64_t x);\n inline bool contains_range(wuffs_base__range_ii_u64__struct s);\n#endif // __cplusplus\n\n} wuffs_base__range_ii_u64;\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__make_range_ii_u64(uint64_t min_incl, uint64_t max_incl) {\n wuffs_base__range_ii_u64 ret;\n ret.min_incl = min_incl;\n ret.max_incl = max_incl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__is_empty(wuffs_base__range_ii_u64* r) {\n return r->min_incl > r->max_incl;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__equals(wuffs_base__range_ii_u64* r,\n wuffs_base" +
- "__range_ii_u64 s) {\n return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||\n (wuffs_base__range_ii_u64__is_empty(r) &&\n wuffs_base__range_ii_u64__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64__intersect(wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n wuffs_base__range_ii_u64 t;\n t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u64__min(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64__unite(wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n if (wuffs_base__range_ii_u64__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ii_u64__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ii_u64 t;\n t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u64__max(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline bool " +
- "//\nwuffs_base__range_ii_u64__contains(wuffs_base__range_ii_u64* r, uint64_t x) {\n return (r->min_incl <= x) && (x <= r->max_incl);\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__contains_range(wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__equals(\n &s, wuffs_base__range_ii_u64__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ii_u64::is_empty() {\n return wuffs_base__range_ii_u64__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__equals(this, s);\n}\n\ninline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__intersect(this, s);\n}\n\ninline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::contains" +
- "(uint64_t x) {\n return wuffs_base__range_ii_u64__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__contains_range(this, s);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct wuffs_base__range_ii_u64__struct {\n uint64_t min_incl;\n uint64_t max_incl;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__range_ii_u64__struct s) const;\n inline wuffs_base__range_ii_u64__struct intersect(\n wuffs_base__range_ii_u64__struct s) const;\n inline wuffs_base__range_ii_u64__struct unite(\n wuffs_base__range_ii_u64__struct s) const;\n inline bool contains(uint64_t x) const;\n inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;\n#endif // __cplusplus\n\n} wuffs_base__range_ii_u64;\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__make_range_ii_u64(uint64_t min_incl, uint64_t max_incl) {\n wuffs_base__range_ii_u64 ret;\n ret.min_incl = min_incl;\n ret.max_incl = max_incl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {\n return r->min_incl > r->max_incl;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64" +
+ "* r,\n wuffs_base__range_ii_u64 s) {\n return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||\n (wuffs_base__range_ii_u64__is_empty(r) &&\n wuffs_base__range_ii_u64__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n wuffs_base__range_ii_u64 t;\n t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u64__min(r->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n if (wuffs_base__range_ii_u64__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ii_u64__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ii_u64 t;\n t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);\n t.max_incl = wuffs_base__u64__max(r" +
+ "->max_incl, s.max_incl);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,\n uint64_t x) {\n return (r->min_incl <= x) && (x <= r->max_incl);\n}\n\nstatic inline bool //\nwuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,\n wuffs_base__range_ii_u64 s) {\n return wuffs_base__range_ii_u64__equals(\n &s, wuffs_base__range_ii_u64__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ii_u64::is_empty() const {\n return wuffs_base__range_ii_u64__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {\n return wuffs_base__range_ii_u64__equals(this, s);\n}\n\ninline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {\n return wuffs_base__range_ii_u64__intersect(this, s);\n}\n\ninline wuffs_base__range_ii_u64 //\nwuffs_base__range_ii_u64::unite(wuffs_bas" +
+ "e__range_ii_u64 s) const {\n return wuffs_base__range_ii_u64__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::contains(uint64_t x) const {\n return wuffs_base__range_ii_u64__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {\n return wuffs_base__range_ii_u64__contains_range(this, s);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\ntypedef struct wuffs_base__range_ie_u64__struct {\n uint64_t min_incl;\n uint64_t max_excl;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__range_ie_u64__struct s);\n inline wuffs_base__range_ie_u64__struct intersect(\n wuffs_base__range_ie_u64__struct s);\n inline wuffs_base__range_ie_u64__struct unite(\n wuffs_base__range_ie_u64__struct s);\n inline bool contains(uint64_t x);\n inline bool contains_range(wuffs_base__range_ie_u64__struct s);\n inline uint64_t length();\n#endif // __cplusplus\n\n} wuffs_base__range_ie_u64;\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__make_range_ie_u64(uint64_t min_incl, uint64_t max_excl) {\n wuffs_base__range_ie_u64 ret;\n ret.min_incl = min_incl;\n ret.max_excl = max_excl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__is_empty(wuffs_base__range_ie_u64* r) {\n return r->min_incl >= r->max_excl;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__equals(wuffs_base__range_ie_u64* r,\n " +
- " wuffs_base__range_ie_u64 s) {\n return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||\n (wuffs_base__range_ie_u64__is_empty(r) &&\n wuffs_base__range_ie_u64__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64__intersect(wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n wuffs_base__range_ie_u64 t;\n t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u64__min(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64__unite(wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n if (wuffs_base__range_ie_u64__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ie_u64__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ie_u64 t;\n t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u64__max(r->max_excl, s.max_excl);\n retu" +
- "rn t;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__contains(wuffs_base__range_ie_u64* r, uint64_t x) {\n return (r->min_incl <= x) && (x < r->max_excl);\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__contains_range(wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__equals(\n &s, wuffs_base__range_ie_u64__intersect(r, s));\n}\n\nstatic inline uint64_t //\nwuffs_base__range_ie_u64__length(wuffs_base__range_ie_u64* r) {\n return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ie_u64::is_empty() {\n return wuffs_base__range_ie_u64__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__equals(this, s);\n}\n\ninline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__intersect(this, s);\n}\n\ninline wuffs_base__" +
- "range_ie_u64 //\nwuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::contains(uint64_t x) {\n return wuffs_base__range_ie_u64__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__contains_range(this, s);\n}\n\ninline uint64_t //\nwuffs_base__range_ie_u64::length() {\n return wuffs_base__range_ie_u64__length(this);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\ntypedef struct wuffs_base__range_ie_u64__struct {\n uint64_t min_incl;\n uint64_t max_excl;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__range_ie_u64__struct s) const;\n inline wuffs_base__range_ie_u64__struct intersect(\n wuffs_base__range_ie_u64__struct s) const;\n inline wuffs_base__range_ie_u64__struct unite(\n wuffs_base__range_ie_u64__struct s) const;\n inline bool contains(uint64_t x) const;\n inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;\n inline uint64_t length() const;\n#endif // __cplusplus\n\n} wuffs_base__range_ie_u64;\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__make_range_ie_u64(uint64_t min_incl, uint64_t max_excl) {\n wuffs_base__range_ie_u64 ret;\n ret.min_incl = min_incl;\n ret.max_excl = max_excl;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {\n return r->min_incl >= r->max_excl;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__eq" +
+ "uals(const wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||\n (wuffs_base__range_ie_u64__is_empty(r) &&\n wuffs_base__range_ie_u64__is_empty(&s));\n}\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n wuffs_base__range_ie_u64 t;\n t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);\n t.max_excl = wuffs_base__u64__min(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n if (wuffs_base__range_ie_u64__is_empty(r)) {\n return s;\n }\n if (wuffs_base__range_ie_u64__is_empty(&s)) {\n return *r;\n }\n wuffs_base__range_ie_u64 t;\n t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);\n " +
+ "t.max_excl = wuffs_base__u64__max(r->max_excl, s.max_excl);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,\n uint64_t x) {\n return (r->min_incl <= x) && (x < r->max_excl);\n}\n\nstatic inline bool //\nwuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,\n wuffs_base__range_ie_u64 s) {\n return wuffs_base__range_ie_u64__equals(\n &s, wuffs_base__range_ie_u64__intersect(r, s));\n}\n\nstatic inline uint64_t //\nwuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {\n return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__range_ie_u64::is_empty() const {\n return wuffs_base__range_ie_u64__is_empty(this);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {\n return wuffs_base__range_ie_u64__equals(this, s);\n}\n\ninline wuffs_base__range_ie_u64 //\nwuffs_base__" +
+ "range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {\n return wuffs_base__range_ie_u64__intersect(this, s);\n}\n\ninline wuffs_base__range_ie_u64 //\nwuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {\n return wuffs_base__range_ie_u64__unite(this, s);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::contains(uint64_t x) const {\n return wuffs_base__range_ie_u64__contains(this, x);\n}\n\ninline bool //\nwuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {\n return wuffs_base__range_ie_u64__contains_range(this, s);\n}\n\ninline uint64_t //\nwuffs_base__range_ie_u64::length() const {\n return wuffs_base__range_ie_u64__length(this);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\n// wuffs_base__rect_ii_u32 is a rectangle (a 2-dimensional range) on the\n// integer grid. The \"ii\" means that the bounds are inclusive on the low end\n// and inclusive on the high end. It contains all points (x, y) such that\n// ((min_incl_x <= x) && (x <= max_incl_x)) and likewise for y.\n//\n// It is valid for min > max, in which case the rectangle is empty. There are\n// multiple representations of an empty rectangle.\n//\n// The X and Y axes increase right and down.\ntypedef struct wuffs_base__rect_ii_u32__struct {\n uint32_t min_incl_x;\n uint32_t min_incl_y;\n uint32_t max_incl_x;\n uint32_t max_incl_y;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__rect_ii_u32__struct s);\n inline wuffs_base__rect_ii_u32__struct intersect(\n wuffs_base__rect_ii_u32__struct s);\n inline wuffs_base__rect_ii_u32__struct unite(\n wuffs_base__rect_ii_u32__struct s);\n inline bool contains(uint32_t x, uint32_t y);\n inline bool contains_rect(wuffs_base__rect_ii_u32__struct s);\n#en" +
- "dif // __cplusplus\n\n} wuffs_base__rect_ii_u32;\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__make_rect_ii_u32(uint32_t min_incl_x,\n uint32_t min_incl_y,\n uint32_t max_incl_x,\n uint32_t max_incl_y) {\n wuffs_base__rect_ii_u32 ret;\n ret.min_incl_x = min_incl_x;\n ret.min_incl_y = min_incl_y;\n ret.max_incl_x = max_incl_x;\n ret.max_incl_y = max_incl_y;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__is_empty(wuffs_base__rect_ii_u32* r) {\n return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__equals(wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&\n r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||\n (wuffs_base__rect_ii_u32__is_empty(r) &&\n wuffs_base__rect_ii_u32__is_empty(&" +
- "s));\n}\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32__intersect(wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n wuffs_base__rect_ii_u32 t;\n t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);\n t.max_incl_x = wuffs_base__u32__min(r->max_incl_x, s.max_incl_x);\n t.max_incl_y = wuffs_base__u32__min(r->max_incl_y, s.max_incl_y);\n return t;\n}\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32__unite(wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n if (wuffs_base__rect_ii_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__rect_ii_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__rect_ii_u32 t;\n t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);\n t.max_incl_x = wuffs_base__u32__max(r->max_incl_x, s.max_incl_x);\n t.max" +
- "_incl_y = wuffs_base__u32__max(r->max_incl_y, s.max_incl_y);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__contains(wuffs_base__rect_ii_u32* r,\n uint32_t x,\n uint32_t y) {\n return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&\n (y <= r->max_incl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__contains_rect(wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__equals(\n &s, wuffs_base__rect_ii_u32__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__rect_ii_u32::is_empty() {\n return wuffs_base__rect_ii_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__equals(this, s);\n}\n\ninline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__interse" +
- "ct(this, s);\n}\n\ninline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) {\n return wuffs_base__rect_ii_u32__contains(this, x, y);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__contains_rect(this, s);\n}\n\n#endif // __cplusplus\n\n" +
+ "// --------\n\n// wuffs_base__rect_ii_u32 is a rectangle (a 2-dimensional range) on the\n// integer grid. The \"ii\" means that the bounds are inclusive on the low end\n// and inclusive on the high end. It contains all points (x, y) such that\n// ((min_incl_x <= x) && (x <= max_incl_x)) and likewise for y.\n//\n// It is valid for min > max, in which case the rectangle is empty. There are\n// multiple representations of an empty rectangle.\n//\n// The X and Y axes increase right and down.\ntypedef struct wuffs_base__rect_ii_u32__struct {\n uint32_t min_incl_x;\n uint32_t min_incl_y;\n uint32_t max_incl_x;\n uint32_t max_incl_y;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__rect_ii_u32__struct s) const;\n inline wuffs_base__rect_ii_u32__struct intersect(\n wuffs_base__rect_ii_u32__struct s) const;\n inline wuffs_base__rect_ii_u32__struct unite(\n wuffs_base__rect_ii_u32__struct s) const;\n inline bool contains(uint32_t x, uint32_t y) const;\n inline bool contains_rect(wuffs_bas" +
+ "e__rect_ii_u32__struct s) const;\n#endif // __cplusplus\n\n} wuffs_base__rect_ii_u32;\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__make_rect_ii_u32(uint32_t min_incl_x,\n uint32_t min_incl_y,\n uint32_t max_incl_x,\n uint32_t max_incl_y) {\n wuffs_base__rect_ii_u32 ret;\n ret.min_incl_x = min_incl_x;\n ret.min_incl_y = min_incl_y;\n ret.max_incl_x = max_incl_x;\n ret.max_incl_y = max_incl_y;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {\n return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&\n r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||\n (wuffs_base__rect_ii_u32__is_empty(r) " +
+ "&&\n wuffs_base__rect_ii_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n wuffs_base__rect_ii_u32 t;\n t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);\n t.max_incl_x = wuffs_base__u32__min(r->max_incl_x, s.max_incl_x);\n t.max_incl_y = wuffs_base__u32__min(r->max_incl_y, s.max_incl_y);\n return t;\n}\n\nstatic inline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32__unite(const wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n if (wuffs_base__rect_ii_u32__is_empty(r)) {\n return s;\n }\n if (wuffs_base__rect_ii_u32__is_empty(&s)) {\n return *r;\n }\n wuffs_base__rect_ii_u32 t;\n t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);\n t.max_incl_x " +
+ "= wuffs_base__u32__max(r->max_incl_x, s.max_incl_x);\n t.max_incl_y = wuffs_base__u32__max(r->max_incl_y, s.max_incl_y);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,\n uint32_t x,\n uint32_t y) {\n return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&\n (y <= r->max_incl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,\n wuffs_base__rect_ii_u32 s) {\n return wuffs_base__rect_ii_u32__equals(\n &s, wuffs_base__rect_ii_u32__intersect(r, s));\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__rect_ii_u32::is_empty() const {\n return wuffs_base__rect_ii_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {\n return wuffs_base__rect_ii_u32__equals(this, s);\n}\n\ninline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u" +
+ "32::intersect(wuffs_base__rect_ii_u32 s) const {\n return wuffs_base__rect_ii_u32__intersect(this, s);\n}\n\ninline wuffs_base__rect_ii_u32 //\nwuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {\n return wuffs_base__rect_ii_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {\n return wuffs_base__rect_ii_u32__contains(this, x, y);\n}\n\ninline bool //\nwuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {\n return wuffs_base__rect_ii_u32__contains_rect(this, s);\n}\n\n#endif // __cplusplus\n\n" +
"" +
- "// --------\n\n// wuffs_base__rect_ie_u32 is a rectangle (a 2-dimensional range) on the\n// integer grid. The \"ie\" means that the bounds are inclusive on the low end\n// and exclusive on the high end. It contains all points (x, y) such that\n// ((min_incl_x <= x) && (x < max_excl_x)) and likewise for y.\n//\n// It is valid for min >= max, in which case the rectangle is empty. There are\n// multiple representations of an empty rectangle, including a value with all\n// fields zero.\n//\n// The X and Y axes increase right and down.\ntypedef struct wuffs_base__rect_ie_u32__struct {\n uint32_t min_incl_x;\n uint32_t min_incl_y;\n uint32_t max_excl_x;\n uint32_t max_excl_y;\n\n#ifdef __cplusplus\n inline bool is_empty();\n inline bool equals(wuffs_base__rect_ie_u32__struct s);\n inline wuffs_base__rect_ie_u32__struct intersect(\n wuffs_base__rect_ie_u32__struct s);\n inline wuffs_base__rect_ie_u32__struct unite(\n wuffs_base__rect_ie_u32__struct s);\n inline bool contains(uint32_t x, uint32_t y);\n inline bool contains_r" +
- "ect(wuffs_base__rect_ie_u32__struct s);\n inline uint32_t width();\n inline uint32_t height();\n#endif // __cplusplus\n\n} wuffs_base__rect_ie_u32;\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__make_rect_ie_u32(uint32_t min_incl_x,\n uint32_t min_incl_y,\n uint32_t max_excl_x,\n uint32_t max_excl_y) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = min_incl_x;\n ret.min_incl_y = min_incl_y;\n ret.max_excl_x = max_excl_x;\n ret.max_excl_y = max_excl_y;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__is_empty(wuffs_base__rect_ie_u32* r) {\n return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__equals(wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&\n r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y" +
- ") ||\n (wuffs_base__rect_ie_u32__is_empty(r) &&\n wuffs_base__rect_ie_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32__intersect(wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n wuffs_base__rect_ie_u32 t;\n t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);\n t.max_excl_x = wuffs_base__u32__min(r->max_excl_x, s.max_excl_x);\n t.max_excl_y = wuffs_base__u32__min(r->max_excl_y, s.max_excl_y);\n return t;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32__unite(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 wuffs_base__rect_ie_u32 t;\n t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__min(r->mi" +
- "n_incl_y, s.min_incl_y);\n t.max_excl_x = wuffs_base__u32__max(r->max_excl_x, s.max_excl_x);\n t.max_excl_y = wuffs_base__u32__max(r->max_excl_y, s.max_excl_y);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__contains(wuffs_base__rect_ie_u32* r,\n uint32_t x,\n uint32_t y) {\n return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&\n (y < r->max_excl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__contains_rect(wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__equals(\n &s, wuffs_base__rect_ie_u32__intersect(r, s));\n}\n\nstatic inline uint32_t //\nwuffs_base__rect_ie_u32__width(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 //\nwuffs_base__rect_ie_u32__height(wuffs_base__rect_ie_u32* r) {\n return wuffs_base__u32__sat_sub(r->max_excl_y, r->min" +
- "_incl_y);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__rect_ie_u32::is_empty() {\n return wuffs_base__rect_ie_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__equals(this, s);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__intersect(this, s);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) {\n return wuffs_base__rect_ie_u32__contains(this, x, y);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__contains_rect(this, s);\n}\n\ninline uint32_t //\nwuffs_base__rect_ie_u32::width() {\n return wuffs_base__rect_ie_u32__width(this);\n}\n\ninline uint32_t //\nwuffs_base__rect_ie_u32::height() {\n return" +
- " wuffs_base__rect_ie_u32__height(this);\n}\n\n#endif // __cplusplus\n" +
+ "// --------\n\n// wuffs_base__rect_ie_u32 is a rectangle (a 2-dimensional range) on the\n// integer grid. The \"ie\" means that the bounds are inclusive on the low end\n// and exclusive on the high end. It contains all points (x, y) such that\n// ((min_incl_x <= x) && (x < max_excl_x)) and likewise for y.\n//\n// It is valid for min >= max, in which case the rectangle is empty. There are\n// multiple representations of an empty rectangle, including a value with all\n// fields zero.\n//\n// The X and Y axes increase right and down.\ntypedef struct wuffs_base__rect_ie_u32__struct {\n uint32_t min_incl_x;\n uint32_t min_incl_y;\n uint32_t max_excl_x;\n uint32_t max_excl_y;\n\n#ifdef __cplusplus\n inline bool is_empty() const;\n inline bool equals(wuffs_base__rect_ie_u32__struct s) const;\n inline wuffs_base__rect_ie_u32__struct intersect(\n wuffs_base__rect_ie_u32__struct s) const;\n inline wuffs_base__rect_ie_u32__struct unite(\n wuffs_base__rect_ie_u32__struct s) const;\n inline bool contains(uint32_t x, uint32_t y) c" +
+ "onst;\n inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;\n inline uint32_t width() const;\n inline uint32_t height() const;\n#endif // __cplusplus\n\n} wuffs_base__rect_ie_u32;\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__make_rect_ie_u32(uint32_t min_incl_x,\n uint32_t min_incl_y,\n uint32_t max_excl_x,\n uint32_t max_excl_y) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = min_incl_x;\n ret.min_incl_y = min_incl_y;\n ret.max_excl_x = max_excl_x;\n ret.max_excl_y = max_excl_y;\n return ret;\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {\n return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&\n r-" +
+ ">max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||\n (wuffs_base__rect_ie_u32__is_empty(r) &&\n wuffs_base__rect_ie_u32__is_empty(&s));\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n wuffs_base__rect_ie_u32 t;\n t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);\n t.max_excl_x = wuffs_base__u32__min(r->max_excl_x, s.max_excl_x);\n t.max_excl_y = wuffs_base__u32__min(r->max_excl_y, s.max_excl_y);\n return t;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32__unite(const 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 wuffs_base__rect_ie_u32 t;\n t.min_incl_x = wuffs_base__u32__min(r" +
+ "->min_incl_x, s.min_incl_x);\n t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);\n t.max_excl_x = wuffs_base__u32__max(r->max_excl_x, s.max_excl_x);\n t.max_excl_y = wuffs_base__u32__max(r->max_excl_y, s.max_excl_y);\n return t;\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,\n uint32_t x,\n uint32_t y) {\n return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&\n (y < r->max_excl_y);\n}\n\nstatic inline bool //\nwuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,\n wuffs_base__rect_ie_u32 s) {\n return wuffs_base__rect_ie_u32__equals(\n &s, wuffs_base__rect_ie_u32__intersect(r, s));\n}\n\nstatic inline uint32_t //\nwuffs_base__rect_ie_u32__width(const 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 //\nwuffs_base__rect_ie_u32__he" +
+ "ight(const wuffs_base__rect_ie_u32* r) {\n return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);\n}\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__rect_ie_u32::is_empty() const {\n return wuffs_base__rect_ie_u32__is_empty(this);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {\n return wuffs_base__rect_ie_u32__equals(this, s);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {\n return wuffs_base__rect_ie_u32__intersect(this, s);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {\n return wuffs_base__rect_ie_u32__unite(this, s);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {\n return wuffs_base__rect_ie_u32__contains(this, x, y);\n}\n\ninline bool //\nwuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {\n return wuffs_base__rect_ie_u32__contains_rect(this, s);\n}\n\ninline uint32_t //\nwuffs_base__rect_" +
+ "ie_u32::width() const {\n return wuffs_base__rect_ie_u32__width(this);\n}\n\ninline uint32_t //\nwuffs_base__rect_ie_u32::height() const {\n return wuffs_base__rect_ie_u32__height(this);\n}\n\n#endif // __cplusplus\n" +
""
const baseCopyright = "" +
diff --git a/internal/cgen/expr.go b/internal/cgen/expr.go
index 3315531..4a326c8 100644
--- a/internal/cgen/expr.go
+++ b/internal/cgen/expr.go
@@ -461,8 +461,8 @@
t.IDU32: "uint32_t",
t.IDU64: "uint64_t",
t.IDBool: "bool",
- t.IDIOReader: "wuffs_base__io_reader",
- t.IDIOWriter: "wuffs_base__io_writer",
+ t.IDIOReader: "wuffs_base__io_buffer*",
+ t.IDIOWriter: "wuffs_base__io_buffer*",
}
const noSuchCOperator = " no_such_C_operator "
diff --git a/internal/cgen/func.go b/internal/cgen/func.go
index 1030f78..3f8daf5 100644
--- a/internal/cgen/func.go
+++ b/internal/cgen/func.go
@@ -368,10 +368,12 @@
b.writes("goto suspend;suspend:") // The goto avoids the "unused label" warning.
- b.printf("self->private_impl.%s%s[0] = coro_susp_point;\n",
+ b.printf("self->private_impl.%s%s[0] = "+
+ "wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;\n",
pPrefix, g.currFunk.astFunc.FuncName().Str(g.tm))
if g.currFunk.astFunc.Public() {
- b.printf("self->private_impl.active_coroutine = %d;\n", g.currFunk.coroID)
+ b.printf("self->private_impl.active_coroutine = "+
+ "wuffs_base__status__is_suspension(status) ? %d : 0;\n", g.currFunk.coroID)
}
if err := g.writeResumeSuspend(b, &g.currFunk, true); err != nil {
return err
@@ -418,13 +420,10 @@
for _, o := range n.In().Fields() {
o := o.AsField()
oTyp := o.XType()
- if oTyp.Decorator() != t.IDPtr && !oTyp.IsRefined() {
- // TODO: Also check elements, for array-typed arguments.
- continue
- }
+ // TODO: Also check elements, for array-typed arguments.
switch {
- case oTyp.Decorator() == t.IDPtr:
+ case oTyp.IsIOType() || (oTyp.Decorator() == t.IDPtr):
checks = append(checks, fmt.Sprintf("!%s%s", aPrefix, o.Name().Str(g.tm)))
case oTyp.IsRefined():
diff --git a/internal/cgen/resume.go b/internal/cgen/resume.go
index 09bf05c..1ade456 100644
--- a/internal/cgen/resume.go
+++ b/internal/cgen/resume.go
@@ -236,8 +236,14 @@
}
func (h *resumabilityHelper) doAssign(r resumabilities, n *a.Assign, depth uint32) error {
- if err := h.doExpr(r, n.RHS()); err != nil {
- return err
+ if n.Operator() == t.IDEqQuestion {
+ if err := h.doExpr1(r, n.RHS(), subExprFilterNone, 0); err != nil {
+ return err
+ }
+ } else {
+ if err := h.doExpr(r, n.RHS()); err != nil {
+ return err
+ }
}
if n.LHS() == nil {
@@ -302,12 +308,14 @@
}
return nil
}
+ panic("TODO: unreachable; delete")
processOnlySubExprs = true
case subExprFilterAfterCoroutine:
if n.Effect().Coroutine() {
return nil
}
+ panic("TODO: unreachable; delete")
}
}
diff --git a/internal/cgen/statement.go b/internal/cgen/statement.go
index 6fca3e8..7a57e9d 100644
--- a/internal/cgen/statement.go
+++ b/internal/cgen/statement.go
@@ -267,8 +267,8 @@
cTyp = "writer"
}
name := e.Ident().Str(g.tm)
- b.printf("wuffs_base__io_%s %s%d_%s%s = %s%s;\n",
- cTyp, oPrefix, ioBindNum, prefix, name, prefix, name)
+ b.printf("wuffs_base__io_buffer* %s%d_%s%s = %s%s;\n",
+ oPrefix, ioBindNum, prefix, name, prefix, name)
// TODO: save / restore all iop vars, not just for local IO vars? How
// does this work if the io_bind body advances these pointers, either
@@ -277,25 +277,24 @@
b.printf("uint8_t *%s%d_%s%s%s = %s%s%s;\n",
oPrefix, ioBindNum, iopPrefix, prefix, name, iopPrefix, prefix, name)
b.printf("uint8_t *%s%d_%s%s%s = %s%s%s;\n",
+ oPrefix, ioBindNum, io0Prefix, prefix, name, io0Prefix, prefix, name)
+ b.printf("uint8_t *%s%d_%s%s%s = %s%s%s;\n",
oPrefix, ioBindNum, io1Prefix, prefix, name, io1Prefix, prefix, name)
+ b.printf("uint8_t *%s%d_%s%s%s = %s%s%s;\n",
+ oPrefix, ioBindNum, io2Prefix, prefix, name, io2Prefix, prefix, name)
}
if n.Keyword() == t.IDIOBind {
- b.printf("wuffs_base__io_%s__set(&%s%s, &u_%s, &iop_%s%s, &io1_%s%s,",
- cTyp, prefix, name, name, prefix, name, prefix, name)
+ b.printf("%s%s = wuffs_base__io_%s__set(&%s%s, &%s%s%s, &%s%s%s, &%s%s%s, &%s%s%s,",
+ prefix, name, cTyp, uPrefix, name, iopPrefix, prefix, name,
+ io0Prefix, prefix, name, io1Prefix, prefix, name, io2Prefix, prefix, name)
if err := g.writeExpr(b, n.Arg1(), 0); err != nil {
return err
}
b.writes(");\n")
} else {
- // TODO: restrict (in the type checker or parser) that e is
- // args.foo?
- b.printf("wuffs_base__io_%s__set_limit(&%s%s, iop_%s%s,\n", cTyp, prefix, name, prefix, name)
- if err := g.writeExpr(b, n.Arg1(), 0); err != nil {
- return err
- }
- b.writes(");\n")
+ return fmt.Errorf("TODO: implement io_limit (or remove it from the parser)")
}
}
@@ -318,7 +317,11 @@
b.printf("%s%s%s = %s%d_%s%s%s;\n",
iopPrefix, prefix, name, oPrefix, ioBindNum, iopPrefix, prefix, name)
b.printf("%s%s%s = %s%d_%s%s%s;\n",
+ io0Prefix, prefix, name, oPrefix, ioBindNum, io0Prefix, prefix, name)
+ b.printf("%s%s%s = %s%d_%s%s%s;\n",
io1Prefix, prefix, name, oPrefix, ioBindNum, io1Prefix, prefix, name)
+ b.printf("%s%s%s = %s%d_%s%s%s;\n",
+ io2Prefix, prefix, name, oPrefix, ioBindNum, io2Prefix, prefix, name)
}
}
b.writes("}\n")
diff --git a/internal/cgen/var.go b/internal/cgen/var.go
index 5a2cb50..9263d1c 100644
--- a/internal/cgen/var.go
+++ b/internal/cgen/var.go
@@ -95,37 +95,33 @@
}
preName := prefix + name.Str(g.tm)
- i0, i1 := "meta.ri", "meta.wi"
+ i1, i2 := "meta.ri", "meta.wi"
if typ.QID()[1] == t.IDIOWriter {
- i0, i1 = "meta.wi", "data.len"
+ i1, i2 = "meta.wi", "data.len"
}
if header {
b.printf("uint8_t* %s%s = NULL;", iopPrefix, preName)
b.printf("uint8_t* %s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;", io0Prefix, preName)
b.printf("uint8_t* %s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;", io1Prefix, preName)
+ b.printf("uint8_t* %s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;", io2Prefix, preName)
}
- b.printf("if (%s.private_impl.buf) {", preName)
-
- b.printf("%s%s = %s.private_impl.buf->data.ptr + %s.private_impl.buf->%s;",
- iopPrefix, preName, preName, preName, i0)
+ b.printf("if (%s) {", preName)
if header {
- b.printf("if (!%s.private_impl.mark) {", preName)
- b.printf("%s.private_impl.mark = %s%s;", preName, iopPrefix, preName)
- b.printf("%s.private_impl.limit = %s.private_impl.buf->data.ptr + %s.private_impl.buf->%s;",
- preName, preName, preName, i1)
- b.printf("}\n")
+ b.printf("%s%s = %s->data.ptr;", io0Prefix, preName, preName)
+ b.printf("%s%s = %s%s + %s->%s;", io1Prefix, preName, io0Prefix, preName, preName, i1)
+ b.printf("%s%s = %s%s;", iopPrefix, preName, io1Prefix, preName)
+ b.printf("%s%s = %s%s + %s->%s;", io2Prefix, preName, io0Prefix, preName, preName, i2)
if typ.QID()[1] == t.IDIOWriter {
- b.printf("if (%s.private_impl.buf->meta.closed) {", preName)
- b.printf("%s.private_impl.limit = %s%s;", preName, iopPrefix, preName)
+ b.printf("if (%s->meta.closed) {", preName)
+ b.printf("%s%s = %s%s;", io2Prefix, preName, iopPrefix, preName)
b.printf("}\n")
}
-
- b.printf("%s%s = %s.private_impl.mark;", io0Prefix, preName, preName)
- b.printf("%s%s = %s.private_impl.limit;", io1Prefix, preName, preName)
+ } else {
+ b.printf("%s%s = %s->data.ptr + %s->%s;", iopPrefix, preName, preName, preName, i1)
}
b.printf("}\n")
@@ -158,15 +154,13 @@
}
preName := prefix + name.Str(g.tm)
- i0 := "ri"
+ index := "ri"
if typ.QID()[1] == t.IDIOWriter {
- i0 = "wi"
+ index = "wi"
}
- b.printf("if (%s.private_impl.buf) {", preName)
- b.printf("%s.private_impl.buf->meta.%s = ((size_t)(%s%s - %s.private_impl.buf->data.ptr));",
- preName, i0, iopPrefix, preName, preName)
- b.printf("}\n")
+ b.printf("if (%s) { %s->meta.%s = ((size_t)(%s%s - %s->data.ptr)); }\n",
+ preName, preName, index, iopPrefix, preName, preName)
return nil
}
@@ -278,6 +272,11 @@
}
name := n.Name().Str(g.tm)
+
+ if typ.IsIOType() {
+ b.printf("wuffs_base__io_buffer %s%s = wuffs_base__null_io_buffer();\n", uPrefix, name)
+ }
+
if err := g.writeCTypeName(b, typ, vPrefix, name); err != nil {
return err
}
@@ -290,22 +289,16 @@
} else if typ.IsStatus() {
b.writes(" = NULL;\n")
} else if typ.IsIOType() {
- typName := "reader"
- if typ.QID()[1] == t.IDIOWriter {
- typName = "writer"
- }
- b.printf(" = wuffs_base__null_io_%s();\n", typName)
+ b.printf(" = &%s%s;\n", uPrefix, name)
} else {
b.writes(" = {0};\n")
}
if typ.IsIOType() {
- b.printf("wuffs_base__io_buffer %s%s WUFFS_BASE__POTENTIALLY_UNUSED = "+
- "wuffs_base__null_io_buffer();\n", uPrefix, name)
- preName := vPrefix + name
- // TODO: io0_etc variables?
- b.printf("uint8_t* %s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", iopPrefix, preName)
- b.printf("uint8_t* %s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", io1Prefix, preName)
+ b.printf("uint8_t* %s%s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", iopPrefix, vPrefix, name)
+ b.printf("uint8_t* %s%s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", io0Prefix, vPrefix, name)
+ b.printf("uint8_t* %s%s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", io1Prefix, vPrefix, name)
+ b.printf("uint8_t* %s%s%s WUFFS_BASE__POTENTIALLY_UNUSED = NULL;\n", io2Prefix, vPrefix, name)
}
}
return nil
diff --git a/internal/testcut/testcut.go b/internal/testcut/testcut.go
index ba2d0ca..f15b8a5 100644
--- a/internal/testcut/testcut.go
+++ b/internal/testcut/testcut.go
@@ -43,7 +43,7 @@
func Test(t *testing.T,
smallestValidMaxEncodedLen int,
- cut func([]byte, int) (int, int, error),
+ cut func(io.Writer, []byte, int) (int, int, error),
newReader func(io.Reader) (io.ReadCloser, error),
filenames []string) {
@@ -90,8 +90,9 @@
if maxEncodedLen < smallestValidMaxEncodedLen {
continue
}
+ w0 := &bytes.Buffer{}
encoded := clone(full)
- encLen, decLen, err := cut(encoded, maxEncodedLen)
+ encLen, decLen, err := cut(w0, encoded, maxEncodedLen)
if err != nil {
t.Errorf("f=%q, mEL=%d: cut: %v", filename, maxEncodedLen, err)
continue
@@ -107,13 +108,13 @@
continue
}
- w := &bytes.Buffer{}
+ w1 := &bytes.Buffer{}
r, err := newReader(bytes.NewReader(encoded[:encLen]))
if err != nil {
t.Errorf("f=%q, mEL=%d: newReader: %v", filename, maxEncodedLen, err)
continue
}
- if n, err := io.Copy(w, r); err != nil {
+ if n, err := io.Copy(w1, r); err != nil {
t.Errorf("f=%q, mEL=%d: io.Copy: %v", filename, maxEncodedLen, err)
continue
} else if n != int64(decLen) {
@@ -122,6 +123,11 @@
continue
}
+ if !bytes.Equal(w0.Bytes(), w1.Bytes()) {
+ t.Errorf("f=%q, mEL=%d: decoded bytes were not equal", filename, maxEncodedLen)
+ continue
+ }
+
if (maxEncodedLen == len(encoded)) && (int64(decLen) != fullDecodedLen) {
t.Errorf("f=%q, mEL=%d: full decode: got %d, want %d",
filename, maxEncodedLen, decLen, fullDecodedLen)
@@ -138,7 +144,7 @@
func Benchmark(b *testing.B,
smallestValidMaxEncodedLen int,
- cut func([]byte, int) (int, int, error),
+ cut func(io.Writer, []byte, int) (int, int, error),
newReader func(io.Reader) (io.ReadCloser, error),
filename string,
trimPrefix int,
@@ -168,7 +174,7 @@
continue
}
encoded := clone(full)
- if _, _, err := cut(encoded, maxEncodedLen); err != nil {
+ if _, _, err := cut(nil, encoded, maxEncodedLen); err != nil {
b.Fatalf("cut: %v", err)
}
if maxEncodedLen >= len(full) {
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 47de929..919fe86 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -19,15 +19,22 @@
t "github.com/google/wuffs/lang/token"
)
+var FourCCs = [...][2]string{
+ {"ICCP", "International Color Consortium Profile"},
+ {"XMP ", "Extensible Metadata Platform"},
+}
+
var Statuses = [...]string{
// Warnings.
`"@end of data"`,
+ `"@metadata reported"`,
// Suspensions.
`"$short read"`,
`"$short write"`,
// Errors.
+ `"#bad I/O position"`,
`"#bad argument (length too short)"`,
`"#bad argument"`,
`"#bad call sequence"`,
@@ -42,6 +49,7 @@
`"#initialize not called"`,
`"#interleaved coroutine calls"`,
`"#not enough data"`,
+ `"#unsupported option"`,
`"#too much data"`,
}
@@ -209,11 +217,10 @@
"io_reader.peek_u64le() u64",
"io_reader.available() u64",
+ "io_reader.count_since(mark u64) u64",
+ "io_reader.mark() u64",
"io_reader.position() u64",
- "io_reader.set!(s slice u8, closed bool)", // TODO: remove, as it's no longer used?
- "io_reader.set_limit!(l u64)", // TODO: remove, as it's no longer used?
- "io_reader.set_mark!()",
- "io_reader.since_mark() slice u8",
+ "io_reader.since(mark u64) slice u8",
"io_reader.take!(n u64) slice u8",
"io_reader.skip?(n u32)",
@@ -264,11 +271,11 @@
"io_writer.write_fast_u64le!(x u64)",
"io_writer.available() u64",
+ "io_writer.count_since(mark u64) u64",
+ "io_writer.history_available() u64",
+ "io_writer.mark() u64",
"io_writer.position() u64",
- "io_writer.set!(s slice u8)", // TODO: remove, as it's no longer used?
- "io_writer.set_limit!(l u64)", // TODO: remove, as it's no longer used?
- "io_writer.set_mark!()",
- "io_writer.since_mark() slice u8",
+ "io_writer.since(mark u64) slice u8",
"io_writer.copy_from_slice!(s slice u8) u64",
"io_writer.copy_n_from_history!(n u32, distance u32) u32",
@@ -300,7 +307,7 @@
"frame_config.io_position() u64",
"frame_config.update!(bounds rect_ie_u32, duration u64[..0x7FFFFFFFFFFFFFFF], " +
- "index u64, io_position u64, blend u8, disposal u8)",
+ "index u64, io_position u64, blend u8, disposal u8, background_color u32)",
// ---- image_config
@@ -315,8 +322,8 @@
// ---- pixel_swizzler
- "pixel_swizzler.prepare!(dst_pixfmt u32, dst_palette slice u8, src_pixfmt u32, src_palette slice u8)",
- "pixel_swizzler.swizzle_packed!(dst slice u8, dst_palette slice u8, src slice u8) u64",
+ "pixel_swizzler.prepare!(dst_pixfmt u32, dst_palette slice u8, src_pixfmt u32, src_palette slice u8) status",
+ "pixel_swizzler.swizzle_interleaved!(dst slice u8, dst_palette slice u8, src slice u8) u64",
}
// The "T1" and "T2" types here are placeholders for generic "slice T" or
diff --git a/lang/check/bounds.go b/lang/check/bounds.go
index a2d36ef..6e3c7d9 100644
--- a/lang/check/bounds.go
+++ b/lang/check/bounds.go
@@ -1113,10 +1113,10 @@
}
func (q *checker) canCopyNFromHistoryFast(recv *a.Expr, args []*a.Node) error {
- // As per cgen's base-private.h, there are three pre-conditions:
+ // As per cgen's io-private.h, there are three pre-conditions:
// - n <= this.available()
// - distance > 0
- // - distance <= this.since_mark().length()
+ // - distance <= this.history_available()
if len(args) != 2 {
return fmt.Errorf("check: internal error: inconsistent copy_n_from_history_fast arguments")
@@ -1174,7 +1174,7 @@
return fmt.Errorf("check: could not prove distance > 0")
}
- // Check "distance <= this.since_mark().length()".
+ // Check "distance <= this.history_available()".
check2:
for {
for _, x := range q.facts {
@@ -1192,22 +1192,18 @@
continue
}
- // Check that the RHS is "recv.since_mark().length()".
+ // Check that the RHS is "recv.history_available()".
y, method, yArgs := splitReceiverMethodArgs(x.RHS().AsExpr())
- if method != t.IDLength || len(yArgs) != 0 {
+ if method != t.IDHistoryAvailable || len(yArgs) != 0 {
continue
}
- z, method, zArgs := splitReceiverMethodArgs(y)
- if method != t.IDSinceMark || len(zArgs) != 0 {
- continue
- }
- if !z.Eq(recv) {
+ if !y.Eq(recv) {
continue
}
break check2
}
- return fmt.Errorf("check: could not prove distance <= %s.since_mark().length()", recv.Str(q.tm))
+ return fmt.Errorf("check: could not prove distance <= %s.history_available()", recv.Str(q.tm))
}
return nil
diff --git a/lang/token/list.go b/lang/token/list.go
index 85cb5c5..765ef80 100644
--- a/lang/token/list.go
+++ b/lang/token/list.go
@@ -459,15 +459,15 @@
IDDecodeFrameOptions = ID(0x158)
- IDCanUndoByte = ID(0x160)
- IDPosition = ID(0x161)
- IDSetLimit = ID(0x162)
- IDSetMark = ID(0x163)
- IDSinceMark = ID(0x164)
- IDSinceMarkLength = ID(0x165)
- IDSkip = ID(0x166)
- IDSkipFast = ID(0x167)
- IDTake = ID(0x168)
+ IDCanUndoByte = ID(0x160)
+ IDCountSince = ID(0x161)
+ IDHistoryAvailable = ID(0x162)
+ IDMark = ID(0x163)
+ IDPosition = ID(0x164)
+ IDSince = ID(0x165)
+ IDSkip = ID(0x166)
+ IDSkipFast = ID(0x167)
+ IDTake = ID(0x168)
IDCopyFromSlice = ID(0x170)
IDCopyNFromHistory = ID(0x171)
@@ -791,15 +791,15 @@
IDDecodeFrameOptions: "decode_frame_options",
- IDCanUndoByte: "can_undo_byte",
- IDPosition: "position",
- IDSetLimit: "set_limit",
- IDSetMark: "set_mark",
- IDSinceMark: "since_mark",
- IDSinceMarkLength: "since_mark_length",
- IDSkip: "skip",
- IDSkipFast: "skip_fast",
- IDTake: "take",
+ IDCanUndoByte: "can_undo_byte",
+ IDCountSince: "count_since",
+ IDHistoryAvailable: "history_available",
+ IDMark: "mark",
+ IDPosition: "position",
+ IDSince: "since",
+ IDSkip: "skip",
+ IDSkipFast: "skip_fast",
+ IDTake: "take",
IDCopyFromSlice: "copy_from_slice",
IDCopyNFromHistory: "copy_n_from_history",
diff --git a/lib/flatecut/flatecut.go b/lib/flatecut/flatecut.go
index cc4e7fc..0557168 100644
--- a/lib/flatecut/flatecut.go
+++ b/lib/flatecut/flatecut.go
@@ -23,14 +23,19 @@
package flatecut
import (
+ "bytes"
+ "compress/flate"
"errors"
+ "io"
)
var (
errMaxEncodedLenTooSmall = errors.New("flatecut: maxEncodedLen is too small")
- errInternalNoProgress = errors.New("flatecut: internal: no progress")
- errInternalSomeProgress = errors.New("flatecut: internal: some progress")
+ errInternalInconsistentDecodedLen = errors.New("flatecut: internal: inconsistent decodedLen")
+ errInternalNoProgress = errors.New("flatecut: internal: no progress")
+ errInternalReplaceWithSingleBlock = errors.New("flatecut: internal: replace with single block")
+ errInternalSomeProgress = errors.New("flatecut: internal: some progress")
errInvalidBadBlockLength = errors.New("flatecut: invalid input: bad block length")
errInvalidBadBlockType = errors.New("flatecut: invalid input: bad block type")
@@ -84,6 +89,13 @@
mostNegativeInt32 = -0x80000000
)
+func loadU64LE(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+
+}
+
type bitstream struct {
// bytes[index] is the next byte to load into the 'bits' field.
bytes []byte
@@ -91,7 +103,7 @@
// The low nBits bits of the 'bits' field hold the next bits (in LSB-first
// order).
- bits uint32
+ bits uint64
nBits uint32
}
@@ -100,13 +112,13 @@
if b.index >= len(b.bytes) {
return mostNegativeInt32
}
- b.bits |= uint32(b.bytes[b.index]) << b.nBits
+ b.bits |= uint64(b.bytes[b.index]) << b.nBits
b.nBits += 8
b.index++
}
mask := ((uint32(1)) << nBits) - 1
- ret := b.bits & mask
+ ret := uint32(b.bits) & mask
b.bits >>= nBits
b.nBits -= nBits
return int32(ret)
@@ -125,12 +137,15 @@
// which results in:
//
// huffman{
-// counts: []uint32{
+// counts: [maxCodeBits + 1]uint32{
// 2: 1, 3: 5, 4: 2,
// },
-// symbols: []int32{
+// symbols: [maxNumCodes]int32{
// 0: 'F', 1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E', 6: 'G', 7: 'H',
// },
+// lookUpTable: [256]uint32{
+// etc,
+// },
// }
//
// Continuing the example from the RFC, decoding "1110" from the bitstream will
@@ -138,9 +153,49 @@
type huffman struct {
counts [maxCodeBits + 1]uint32
symbols [maxNumCodes]int32
+
+ // lookUpTable holds cached results of the slowDecode method.
+ //
+ // The uint8 key is the next 8 bits of input.
+ //
+ // The uint32 value's low 16 bits are the symbol, the high 16 bits are the
+ // number of bits used to encode that symbol.
+ //
+ // Zero means that the entry is invalid. For example, the encoded symbol
+ // might be longer than 8 bits.
+ lookUpTable [256]uint32
}
func (h *huffman) decode(b *bitstream) int32 {
+ if b.nBits >= 8 {
+ // No-op.
+ } else if b.index < (len(b.bytes) - 8) {
+ // This is "Variant 4" of
+ // https://fgiesen.wordpress.com/2018/02/20/reading-bits-in-far-too-many-ways-part-2/
+ u := loadU64LE(b.bytes[b.index:])
+ b.bits |= u << b.nBits
+ b.index += int((63 - b.nBits) >> 3)
+ b.nBits |= 56
+ } else if b.index < len(b.bytes) {
+ b.bits |= uint64(b.bytes[b.index]) << b.nBits
+ b.nBits += 8
+ b.index++
+ } else {
+ goto slow
+ }
+
+ if x := h.lookUpTable[b.bits&0xFF]; x != 0 {
+ n := x >> 16
+ b.bits >>= n
+ b.nBits -= n
+ return int32(x & 0xFFFF)
+ }
+
+slow:
+ return h.slowDecode(b)
+}
+
+func (h *huffman) slowDecode(b *bitstream) int32 {
code := uint32(0) // The i bits from the bitstream.
first := uint32(0) // The first Huffman code of length i.
symIndex := uint32(0) // How many elements of h.symbols we've gone past.
@@ -154,12 +209,12 @@
if b.index >= len(b.bytes) {
return mostNegativeInt32
}
- b.bits = uint32(b.bytes[b.index])
+ b.bits = uint64(b.bytes[b.index])
b.nBits = 8
b.index++
}
- code |= b.bits & 1
+ code |= uint32(b.bits & 1)
b.bits >>= 1
b.nBits -= 1
@@ -199,7 +254,7 @@
for _, x := range lengths {
h.counts[x]++
}
- if h.counts[0] == uint32(len(lengths)) {
+ if h.counts[0] >= uint32(len(lengths)) {
return 0, 0, errInvalidBadHuffmanTree
}
@@ -230,7 +285,12 @@
}
}
if remaining != 0 {
- return 0, 0, errInvalidBadHuffmanTree
+ if ((h.counts[0] + 1) == uint32(len(lengths))) && (h.counts[1] == 1) {
+ // No-op. We allow a degenerate Huffman tree with only one code (of
+ // length 1 bit).
+ } else {
+ return 0, 0, errInvalidBadHuffmanTree
+ }
}
offsets := [maxCodeBits + 1]uint32{}
@@ -244,18 +304,68 @@
offsets[length]++
}
}
+ h.constructLookUpTable()
return endCodeBits, endCodeNBits, nil
}
-// cutEmpty sets encoding[:2] to contain valid DEFLATE-encoded data. Decoding
-// that data produces zero bytes.
-func cutEmpty(encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
+func (h *huffman) constructLookUpTable() {
+ b := bitstream{
+ bytes: []byte{0x00},
+ }
+ for i := range h.lookUpTable {
+ b.bytes[0] = uint8(i)
+ b.index = 0
+ b.bits = 0
+ b.nBits = 0
+ if x := h.slowDecode(&b); x >= 0 {
+ h.lookUpTable[i] = ((8 - b.nBits) << 16) | uint32(x)
+ } else {
+ h.lookUpTable[i] = 0
+ }
+ }
+}
+
+// cutSingleBlock is an implementation of Cut whose output consists of a single
+// DEFLATE block.
+//
+// If maxEncodedLen is sufficiently large, this will be a Stored block (i.e. a
+// header followed by literal bytes). Otherwise, it will set encoding[:2] so
+// that decoding produces zero bytes.
+//
+// A precondition is that maxEncodedLen >= SmallestValidMaxEncodedLen.
+func cutSingleBlock(encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
if maxEncodedLen < SmallestValidMaxEncodedLen {
panic("unreachable")
}
+
+ // Try re-encoding as a single Stored block: up to 0xFFFF literal bytes,
+ // with a 5 byte prefix.
+ if maxEncodedLen > 5 {
+ n := maxEncodedLen - 5
+ if n > 0xFFFF {
+ n = 0xFFFF
+ }
+
+ buf := make([]byte, n)
+ n, err := io.ReadFull(flate.NewReader(bytes.NewReader(encoded)), buf)
+ if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+ return 0, 0, err
+ }
+
+ if n > 0 {
+ encoded[0] = 0x01 // finalBlock = true, blockType = 0 (Stored).
+ encoded[1] = uint8(n >> 0)
+ encoded[2] = uint8(n >> 8)
+ encoded[3] = ^encoded[1]
+ encoded[4] = ^encoded[2]
+ copy(encoded[5:], buf[:n])
+ return n + 5, n, nil
+ }
+ }
+
// Set encoded[:2] to hold:
// - 1 bit ...._...._...._...1 finalBlock = true.
- // - 2 bits ...._...._...._.01. blockType = 1 (static Huffman).
+ // - 2 bits ...._...._...._.01. blockType = 1 (Static Huffman).
// - 7 bits ...._..00_0000_0... litLenSymbol = 256 (end-of-block).
// - 6 bits 0000_00.._...._.... padding.
encoded[0] = 0x03
@@ -267,11 +377,16 @@
// DEFLATE-compressed data, assuming that encoded starts off containing valid
// DEFLATE-compressed data.
//
+// If a nil error is returned, then encodedLen <= maxEncodedLen will hold.
+//
// Decompressing that modified, shorter byte slice produces a prefix (of length
// decodedLen) of the decompression of the original, longer byte slice.
//
+// If w is non-nil, that prefix is also written to w. If a non-nil error is
+// returned, incomplete data might still be written to w.
+//
// It does not necessarily return the largest possible decodedLen.
-func Cut(encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
+func Cut(w io.Writer, encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
if maxEncodedLen < SmallestValidMaxEncodedLen {
return 0, 0, errMaxEncodedLenTooSmall
}
@@ -292,7 +407,28 @@
},
maxEncodedLen: maxEncodedLen,
}
- return c.cut()
+ encodedLen, decodedLen, err := c.cut()
+ if err != nil {
+ return 0, 0, err
+ }
+
+ if w != nil {
+ // TODO: writing to w directly, in cutter's doStored and doHuffman,
+ // might be faster than re-walking the bitstream with compress/flate.
+ r := flate.NewReader(bytes.NewReader(encoded[:encodedLen]))
+ if n, err := io.Copy(w, r); err != nil {
+ r.Close()
+ return 0, 0, err
+ } else if n != int64(decodedLen) {
+ r.Close()
+ return 0, 0, errInternalInconsistentDecodedLen
+ }
+ if err := r.Close(); err != nil {
+ return 0, 0, err
+ }
+ }
+
+ return encodedLen, decodedLen, nil
}
type cutter struct {
@@ -320,6 +456,10 @@
finalBlockIndex := c.bits.index
finalBlockNBits := c.bits.nBits
+ for finalBlockNBits >= 8 {
+ finalBlockIndex--
+ finalBlockNBits -= 8
+ }
blockType := c.bits.take(2)
if blockType < 0 {
@@ -331,13 +471,18 @@
case 0:
err = c.doStored()
case 1:
- err = c.doStaticHuffman()
+ err = c.doStaticHuffman(prevFinalBlockIndex < 0)
case 2:
- err = c.doDynamicHuffman()
+ err = c.doDynamicHuffman(prevFinalBlockIndex < 0)
case 3:
return 0, 0, errInvalidBadBlockType
}
+ for c.bits.nBits >= 8 {
+ c.bits.index--
+ c.bits.nBits -= 8
+ }
+
switch err {
case nil:
if finalBlock == 0 {
@@ -348,15 +493,15 @@
case errInternalNoProgress:
if prevFinalBlockIndex < 0 {
- return cutEmpty(c.bits.bytes, c.maxEncodedLen)
+ return cutSingleBlock(c.bits.bytes, c.maxEncodedLen)
}
// Un-read to just before the finalBlock bit.
c.bits.index = finalBlockIndex
c.bits.nBits = finalBlockNBits + 1
- if c.bits.nBits == 8 {
+ for c.bits.nBits >= 8 {
c.bits.index--
- c.bits.nBits = 0
+ c.bits.nBits -= 8
}
finalBlockIndex = prevFinalBlockIndex
@@ -370,6 +515,9 @@
mask := uint32(1) << n
c.bits.bytes[finalBlockIndex-1] |= uint8(mask)
+ case errInternalReplaceWithSingleBlock:
+ return cutSingleBlock(c.bits.bytes, c.maxEncodedLen)
+
default:
return 0, 0, err
@@ -387,9 +535,14 @@
}
func (c *cutter) doStored() error {
- if (c.maxEncodedLen - c.bits.index) < 4 {
+ for c.bits.nBits >= 8 {
+ c.bits.index--
+ c.bits.nBits -= 8
+ }
+ if (c.maxEncodedLen < c.bits.index) || ((c.maxEncodedLen - c.bits.index) < 4) {
return errInternalNoProgress
}
+
length := uint32(c.bits.bytes[c.bits.index+0]) | uint32(c.bits.bytes[c.bits.index+1])<<8
invLen := uint32(c.bits.bytes[c.bits.index+2]) | uint32(c.bits.bytes[c.bits.index+3])<<8
if length+invLen != 0xFFFF {
@@ -426,7 +579,7 @@
return errInternalSomeProgress
}
-func (c *cutter) doStaticHuffman() error {
+func (c *cutter) doStaticHuffman(isFirstBlock bool) error {
const (
numLCodes = 288
numDCodes = 32
@@ -451,10 +604,10 @@
lengths[i] = 5
}
- return c.doHuffman(lengths[:numLCodes], lengths[numLCodes:])
+ return c.doHuffman(isFirstBlock, lengths[:numLCodes], lengths[numLCodes:])
}
-func (c *cutter) doDynamicHuffman() error {
+func (c *cutter) doDynamicHuffman(isFirstBlock bool) error {
numLCodes := 257 + c.bits.take(5)
if numLCodes < 0 {
return errInvalidNotEnoughData
@@ -527,10 +680,10 @@
}
}
- return c.doHuffman(lengths[:numLCodes], lengths[numLCodes:])
+ return c.doHuffman(isFirstBlock, lengths[:numLCodes], lengths[numLCodes:])
}
-func (c *cutter) doHuffman(lLengths []uint32, dLengths []uint32) error {
+func (c *cutter) doHuffman(isFirstBlock bool, lLengths []uint32, dLengths []uint32) error {
err := error(nil)
if c.endCodeBits, c.endCodeNBits, err = c.lHuff.construct(lLengths); err != nil {
return err
@@ -542,6 +695,10 @@
return err
}
+ for c.bits.nBits >= 8 {
+ c.bits.index--
+ c.bits.nBits -= 8
+ }
if c.bits.index > c.maxEncodedLen {
return errInternalNoProgress
}
@@ -609,8 +766,25 @@
if checkpointIndex < 0 {
return errInternalNoProgress
}
+
+ // If we're the first block in the DEFLATE stream, check if we would be
+ // better off replacing the Huffman block with a Stored block.
+ if isFirstBlock && (c.maxEncodedLen > 5) {
+ n := c.maxEncodedLen - 5
+ if n > 0xFFFF {
+ n = 0xFFFF
+ }
+ if c.decodedLen < int32(n) {
+ return errInternalReplaceWithSingleBlock
+ }
+ }
+
c.bits.index = checkpointIndex
c.bits.nBits = checkpointNBits
+ for c.bits.nBits >= 8 {
+ c.bits.index--
+ c.bits.nBits -= 8
+ }
c.writeEndCode()
return errInternalSomeProgress
}
diff --git a/lib/flatecut/flatecut_test.go b/lib/flatecut/flatecut_test.go
index 7c649ca..5b0035e 100644
--- a/lib/flatecut/flatecut_test.go
+++ b/lib/flatecut/flatecut_test.go
@@ -15,8 +15,10 @@
package flatecut
import (
+ "bytes"
"compress/flate"
"io"
+ "io/ioutil"
"testing"
"github.com/google/wuffs/internal/testcut"
@@ -39,3 +41,191 @@
func newReader(r io.Reader) (io.ReadCloser, error) {
return flate.NewReader(r), nil
}
+
+func decodeFlate(src []byte) string {
+ dst, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(src)))
+ if err != nil {
+ return err.Error()
+ }
+ return string(dst)
+}
+
+func TestHuffmanDecode(t *testing.T) {
+ // This exercises the "ABCDEFGH" example from RFC 1951 section 3.2.2,
+ // discussed in the "type huffman" doc comment.
+
+ const src = "HEADFACE"
+ codes := []string{
+ 'A': " 010",
+ 'B': " 011",
+ 'C': " 100",
+ 'D': " 101",
+ 'E': " 110",
+ 'F': " 00",
+ 'G': "1110",
+ 'H': "1111",
+ }
+
+ encoded := []byte(nil)
+ encBits := uint32(0)
+ encNBits := uint32(0)
+ for _, s := range src {
+ for _, c := range codes[s] {
+ if c == ' ' {
+ continue
+ }
+
+ if c == '1' {
+ encBits |= 1 << encNBits
+ }
+ encNBits++
+
+ if encNBits == 8 {
+ encoded = append(encoded, uint8(encBits))
+ encBits = 0
+ encNBits = 0
+ }
+ }
+ }
+ if encNBits > 0 {
+ encoded = append(encoded, uint8(encBits))
+ }
+
+ h := huffman{
+ counts: [maxCodeBits + 1]uint32{
+ 2: 1, 3: 5, 4: 2,
+ },
+ symbols: [maxNumCodes]int32{
+ 0: 'F', 1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E', 6: 'G', 7: 'H',
+ },
+ }
+ h.constructLookUpTable()
+
+ b := &bitstream{
+ bytes: encoded,
+ }
+
+ decoded := []byte(nil)
+ for _ = range src {
+ c := h.decode(b)
+ if c < 0 {
+ decoded = append(decoded, '!')
+ break
+ }
+ decoded = append(decoded, uint8(c))
+ }
+
+ if got, want := string(decoded), src; got != want {
+ t.Fatalf("got %q, want %q", got, want)
+ }
+}
+
+// A DEFLATE encoding of the first 64 bytes of the AUTHORS file in the
+// repository root directory.
+//
+// The encoding uses a Dynamic Huffman block, but one whose H-D Huffman
+// distance tree is degenerate (there's a mapping for the "0" code but no
+// mapping for the "1" code) and unused.
+//
+// The first 25-30 bytes contain the encoded H-L and H-D Huffman trees. The
+// last 30-35 bytes contain the actual payload, encoded with H-L.
+//
+// The high 7 bits of the final byte is unused padding.
+const (
+ degenerateHuffmanDec = "# This is the official list of Wuffs authors for copyright purpo"
+ degenerateHuffmanEnc = "" +
+ "\x05\xc0\xc1\x09\xc5\x30\x0c\x03\xd0\x55\x04\x7f\xa5\x0f\x3d\x87" +
+ "\x50\xd5\x82\x80\x82\xed\x1c\xba\x7d\xdf\x0f\xff\x50\x41\x85\x8e" +
+ "\x1b\x26\x35\x35\x16\x96\xaa\x61\xe2\x3a\x64\x61\x9c\x0e\x67\x81" +
+ "\x4e\x4c\xef\x37\xf5\x44\x63\x9f\xdc\xfe\x00"
+)
+
+func TestReplaceHuffmanWithStored(t *testing.T) {
+ const dec = degenerateHuffmanDec
+ const enc = degenerateHuffmanEnc
+ if (len(dec) != 64) || (len(enc) != 59) {
+ panic("inconsistent const string lengths")
+ }
+ if got, want := decodeFlate([]byte(enc)), dec; got != want {
+ t.Fatalf("before Cut: got %q, want %q", got, want)
+ }
+
+ for i := 4; i <= 59; i += 5 {
+ b := []byte(enc)
+ encLen, decLen, err := Cut(nil, b, i)
+ if err != nil {
+ t.Errorf("i=%d: %v", i, err)
+ continue
+ }
+ if encLen < 1 {
+ t.Errorf("i=%d: encLen: got %d, want >= 1", i, encLen)
+ continue
+ } else if encLen > len(enc) {
+ t.Errorf("i=%d: encLen: got %d, want <= %d", i, encLen, len(enc))
+ continue
+ }
+ // If we can make some progress (decLen > 0), even if the input uses a
+ // Huffman block, one option is to re-encode to a single Stored block
+ // (for 5 bytes of overhead). It's single because len(dec) < 0xFFFF.
+ // Regardless of whether the cut form uses a Huffman or Stored block,
+ // we should be able to produce at least i-5 bytes of decoded output.
+ if (decLen > 0) && (i > 5) && (decLen < i-5) {
+ t.Errorf("i=%d: decLen: got %d, want >= %d", i, decLen, i-5)
+ continue
+ } else if decLen > len(dec) {
+ t.Errorf("i=%d: decLen: got %d, want <= %d", i, decLen, len(dec))
+ continue
+ }
+
+ if got, want := decodeFlate(b[:encLen]), dec[:decLen]; got != want {
+ t.Errorf("i=%d: after Cut: got %q, want %q", i, got, want)
+ continue
+ }
+
+ // Check that we are using a space-efficient block type.
+ {
+ got := (b[0] >> 1) & 3
+ want := uint8(0xFF)
+
+ switch i {
+ case 4:
+ want = 1 // Static Huffman, for a decLen of 0.
+ case 9:
+ want = 0 // Stored.
+ case 59:
+ want = 2 // Dynamic Huffman.
+ default:
+ continue
+ }
+
+ if got != want {
+ t.Errorf("i=%d: block type: got %d, want %d", i, got, want)
+ }
+ }
+ }
+}
+
+func TestDegenerateHuffmanUnused(t *testing.T) {
+ const dec = degenerateHuffmanDec
+ const enc = degenerateHuffmanEnc
+
+ // Cutting 1 byte off the end of the encoded form will lead to cutting n
+ // bytes off the decoded form. Coincidentally, n equals 1, even though each
+ // decoded byte (8 bits) is packed into smaller number of bits, as most of
+ // the final encoded byte's bits are unused padding.
+ const n = 1
+
+ b := []byte(enc)
+ encLen, decLen, err := Cut(nil, b, len(enc)-1)
+ if err != nil {
+ t.Fatalf("Cut: %v", err)
+ } else if encLen != len(enc)-1 {
+ t.Fatalf("encLen: got %d, want %d", encLen, len(enc)-1)
+ } else if decLen != len(dec)-n {
+ t.Fatalf("decLen: got %d, want %d", decLen, len(dec)-n)
+ }
+
+ if got, want := decodeFlate(b[:encLen]), dec[:decLen]; got != want {
+ t.Fatalf("after Cut: got %q, want %q", got, want)
+ }
+}
diff --git a/lib/rac/rac.go b/lib/rac/rac.go
index 905fb15..03b9ffb 100644
--- a/lib/rac/rac.go
+++ b/lib/rac/rac.go
@@ -26,7 +26,7 @@
package rac
const (
- // MaxCSize is the maximum RAC file size (in both CSpace and DSpace).
+ // MaxSize is the maximum RAC file size (in both CSpace and DSpace).
MaxSize = (1 << 48) - 1
// invalidCOffsetCLength is ((1 << 64) - 1).
diff --git a/lib/rac/writer.go b/lib/rac/writer.go
index 002365f..b699120 100644
--- a/lib/rac/writer.go
+++ b/lib/rac/writer.go
@@ -21,6 +21,13 @@
"sort"
)
+func btoi(b bool) int {
+ if b {
+ return 1
+ }
+ return 0
+}
+
func isZeroOrAPowerOf2(x uint64) bool {
return (x & (x - 1)) == 0
}
@@ -593,8 +600,18 @@
w.buffer[4] = uint8(checksum >> 0)
w.buffer[5] = uint8(checksum >> 8)
- _, err := w.w.Write(w.buffer[:size])
- return err
+ if _, err := w.w.Write(w.buffer[:size]); err != nil {
+ return err
+ }
+
+ for i, o := range n.children {
+ if len(o.children) != 0 {
+ if err := w.writeIndex(&n.children[i]); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
}
func calcCLength(primarySize int) uint64 {
@@ -640,37 +657,51 @@
}
resources := map[OptResource]bool{}
- arity := 0
for {
- i, j, newNodes := 0, 0, []node(nil)
+ i, j, arity, newNodes := 0, 0, 0, []node(nil)
for ; j < len(nodes); j++ {
o := &nodes[j]
- arity++
- if (o.secondary != 0) && !resources[o.secondary] {
- resources[o.secondary] = true
- arity++
- }
- if (o.tertiary != 0) && !resources[o.tertiary] {
- resources[o.tertiary] = true
- arity++
- }
+ new2 := (o.secondary != 0) && !resources[o.secondary]
+ new3 := (o.tertiary != 0) && !resources[o.tertiary]
+ arity += 1 + btoi(new2) + btoi(new3)
if arity <= 0xFF {
+ if new2 {
+ resources[o.secondary] = true
+ }
+ if new3 {
+ resources[o.tertiary] = true
+ }
continue
}
newNodes = append(newNodes, makeBranch(nodes[i:j], resources))
- i = j
- arity = 0
if len(resources) != 0 {
resources = map[OptResource]bool{}
}
+
+ i = j
+ arity = 1
+ if o.secondary != 0 {
+ resources[o.secondary] = true
+ arity++
+ }
+ if o.tertiary != 0 {
+ resources[o.tertiary] = true
+ arity++
+ }
}
if i == 0 {
return makeBranch(nodes, resources)
}
+
+ newNodes = append(newNodes, makeBranch(nodes[i:], resources))
+ if len(resources) != 0 {
+ resources = map[OptResource]bool{}
+ }
+
nodes, newNodes = newNodes, nil
}
}
diff --git a/lib/rac/writer_test.go b/lib/rac/writer_test.go
index 08982af..596c407 100644
--- a/lib/rac/writer_test.go
+++ b/lib/rac/writer_test.go
@@ -25,6 +25,10 @@
"testing"
)
+const bytesPerHexDumpLine = 79
+
+const fakeCodec = Codec(0xEE)
+
// Note that these exact bytes depends on the zlib encoder's algorithm, but
// there is more than one valid zlib encoding of any given input. This "compare
// to golden output" test is admittedly brittle, as the standard library's zlib
@@ -164,7 +168,6 @@
func testWriter(iloc IndexLocation, tempFile io.ReadWriter, cPageSize uint64, empty bool) error {
buf := &bytes.Buffer{}
- const fakeCodec = Codec(0xEE)
w := &Writer{
Writer: buf,
Codec: fakeCodec,
@@ -211,3 +214,127 @@
}
return nil
}
+
+func TestWriterMultiLevelIndex(t *testing.T) {
+ buf := &bytes.Buffer{}
+ w := &Writer{
+ Writer: buf,
+ Codec: fakeCodec,
+ IndexLocation: IndexLocationAtStart,
+ TempFile: &bytes.Buffer{},
+ }
+
+ // Write 260 chunks with 3 resources. With the current "func gather"
+ // algorithm, this results in a root node with two children, both of which
+ // are branch nodes. The first branch contains 252 chunks and refers to 3
+ // resources (so that its arity is 255). The second branch contains 8
+ // chunks and refers to 1 resource (so that its arity is 9).
+ xRes := OptResource(0)
+ yRes := OptResource(0)
+ zRes := OptResource(0)
+ for i := 0; i < 260; i++ {
+ secondary := OptResource(0)
+ tertiary := OptResource(0)
+
+ switch i {
+ case 3:
+ xRes, _ = w.AddResource([]byte("XX"))
+ yRes, _ = w.AddResource([]byte("YY"))
+ secondary = xRes
+ tertiary = yRes
+
+ case 4:
+ zRes, _ = w.AddResource([]byte("ZZ"))
+ secondary = yRes
+ tertiary = zRes
+
+ case 259:
+ secondary = yRes
+ }
+
+ primary := []byte(fmt.Sprintf("p%02x", i&0xFF))
+ _ = w.AddChunk(0x10000, primary, secondary, tertiary)
+ }
+
+ if err := w.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+
+ encoded := buf.Bytes()
+ if got, want := len(encoded), 0x13E2; got != want {
+ t.Fatalf("len(encoded): got 0x%X, want 0x%X", got, want)
+ }
+
+ got := hex.Dump(encoded)
+ got = "" +
+ got[0x000*bytesPerHexDumpLine:0x008*bytesPerHexDumpLine] +
+ "...\n" +
+ got[0x080*bytesPerHexDumpLine:0x088*bytesPerHexDumpLine] +
+ "...\n" +
+ got[0x100*bytesPerHexDumpLine:0x110*bytesPerHexDumpLine] +
+ "...\n" +
+ got[0x13C*bytesPerHexDumpLine:]
+
+ const want = "" +
+ "00000000 72 c3 63 02 a0 24 00 ff 00 00 fc 00 00 00 00 ff |r.c..$..........|\n" +
+ "00000010 00 00 04 01 00 00 00 ee 30 00 00 00 00 00 04 ff |........0.......|\n" +
+ "00000020 30 10 00 00 00 00 01 ff e2 13 00 00 00 00 01 02 |0...............|\n" +
+ "00000030 72 c3 63 ff 4c be 00 ff 00 00 00 00 00 00 00 ff |r.c.L...........|\n" +
+ "00000040 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00 ff |................|\n" +
+ "00000050 00 00 01 00 00 00 00 ff 00 00 02 00 00 00 00 ff |................|\n" +
+ "00000060 00 00 03 00 00 00 00 01 00 00 04 00 00 00 00 02 |................|\n" +
+ "00000070 00 00 05 00 00 00 00 ff 00 00 06 00 00 00 00 ff |................|\n" +
+ "...\n" +
+ "00000800 00 00 f7 00 00 00 00 ff 00 00 f8 00 00 00 00 ff |................|\n" +
+ "00000810 00 00 f9 00 00 00 00 ff 00 00 fa 00 00 00 00 ff |................|\n" +
+ "00000820 00 00 fb 00 00 00 00 ff 00 00 fc 00 00 00 00 ee |................|\n" +
+ "00000830 d9 10 00 00 00 00 01 ff db 10 00 00 00 00 01 ff |................|\n" +
+ "00000840 e0 10 00 00 00 00 01 ff d0 10 00 00 00 00 01 ff |................|\n" +
+ "00000850 d3 10 00 00 00 00 01 ff d6 10 00 00 00 00 01 ff |................|\n" +
+ "00000860 dd 10 00 00 00 00 01 00 e2 10 00 00 00 00 01 01 |................|\n" +
+ "00000870 e5 10 00 00 00 00 01 ff e8 10 00 00 00 00 01 ff |................|\n" +
+ "...\n" +
+ "00001000 bb 13 00 00 00 00 01 ff be 13 00 00 00 00 01 ff |................|\n" +
+ "00001010 c1 13 00 00 00 00 01 ff c4 13 00 00 00 00 01 ff |................|\n" +
+ "00001020 c7 13 00 00 00 00 01 ff e2 13 00 00 00 00 01 ff |................|\n" +
+ "00001030 72 c3 63 09 f0 09 00 ff 00 00 00 00 00 00 00 ff |r.c.............|\n" +
+ "00001040 00 00 01 00 00 00 00 ff 00 00 02 00 00 00 00 ff |................|\n" +
+ "00001050 00 00 03 00 00 00 00 ff 00 00 04 00 00 00 00 ff |................|\n" +
+ "00001060 00 00 05 00 00 00 00 ff 00 00 06 00 00 00 00 ff |................|\n" +
+ "00001070 00 00 07 00 00 00 00 ff 00 00 08 00 00 00 00 ee |................|\n" +
+ "00001080 db 10 00 00 00 00 01 ff ca 13 00 00 00 00 01 ff |................|\n" +
+ "00001090 cd 13 00 00 00 00 01 ff d0 13 00 00 00 00 01 ff |................|\n" +
+ "000010a0 d3 13 00 00 00 00 01 ff d6 13 00 00 00 00 01 ff |................|\n" +
+ "000010b0 d9 13 00 00 00 00 01 ff dc 13 00 00 00 00 01 ff |................|\n" +
+ "000010c0 df 13 00 00 00 00 01 00 e2 13 00 00 00 00 01 09 |................|\n" +
+ "000010d0 70 30 30 70 30 31 70 30 32 58 58 59 59 70 30 33 |p00p01p02XXYYp03|\n" +
+ "000010e0 5a 5a 70 30 34 70 30 35 70 30 36 70 30 37 70 30 |ZZp04p05p06p07p0|\n" +
+ "000010f0 38 70 30 39 70 30 61 70 30 62 70 30 63 70 30 64 |8p09p0ap0bp0cp0d|\n" +
+ "...\n" +
+ "000013c0 38 70 66 39 70 66 61 70 66 62 70 66 63 70 66 64 |8pf9pfapfbpfcpfd|\n" +
+ "000013d0 70 66 65 70 66 66 70 30 30 70 30 31 70 30 32 70 |pfepffp00p01p02p|\n" +
+ "000013e0 30 33 |03|\n"
+
+ if got != want {
+ t.Fatalf("\ngot:\n%s\nwant:\n%s", got, want)
+ }
+}
+
+func TestWriter1000Chunks(t *testing.T) {
+ w := &Writer{
+ Writer: ioutil.Discard,
+ Codec: fakeCodec,
+ }
+ data := make([]byte, 1)
+ res, _ := w.AddResource(data)
+ for i := 0; i < 1000; i++ {
+ if i == 2*255 {
+ _ = w.AddChunk(1, data, res, 0)
+ } else {
+ _ = w.AddChunk(1, data, 0, 0)
+ }
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+}
diff --git a/lib/raczlib/raczlib.go b/lib/raczlib/raczlib.go
new file mode 100644
index 0000000..d41b8df
--- /dev/null
+++ b/lib/raczlib/raczlib.go
@@ -0,0 +1,41 @@
+// Copyright 2019 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ----------------
+
+// Package raczlib provides access to RAC (Random Access Compression) files
+// with the Zlib compression codec.
+//
+// The RAC specification is at
+// https://github.com/google/wuffs/blob/master/doc/spec/rac-spec.md
+package raczlib
+
+import (
+ "github.com/google/wuffs/lib/rac"
+)
+
+const (
+ // MaxSize is the maximum RAC file size (in both CSpace and DSpace).
+ MaxSize = rac.MaxSize
+)
+
+// IndexLocation is whether the index is at the start or end of the RAC file.
+//
+// See the RAC specification for further discussion.
+type IndexLocation = rac.IndexLocation
+
+const (
+ IndexLocationAtEnd = rac.IndexLocationAtEnd
+ IndexLocationAtStart = rac.IndexLocationAtStart
+)
diff --git a/lib/raczlib/writer.go b/lib/raczlib/writer.go
new file mode 100644
index 0000000..00c4815
--- /dev/null
+++ b/lib/raczlib/writer.go
@@ -0,0 +1,470 @@
+// Copyright 2019 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package raczlib
+
+// TODO: API for shared dictionaries.
+
+import (
+ "bytes"
+ "compress/zlib"
+ "errors"
+ "io"
+
+ "github.com/google/wuffs/lib/rac"
+ "github.com/google/wuffs/lib/zlibcut"
+)
+
+const (
+ defaultDChunkSize = 65536 // 64 KiB.
+
+ maxCChunkSize = 1 << 30 // 1 GiB.
+ maxTargetDChunkSize = 1 << 31 // 2 GiB.
+)
+
+var (
+ errCChunkSizeIsTooSmall = errors.New("raczlib: CChunkSize is too small")
+ errInvalidWriter = errors.New("raczlib: invalid Writer")
+ errWriterIsClosed = errors.New("raczlib: Writer is closed")
+
+ errInternalShortCSize = errors.New("raczlib: internal error: short CSize")
+)
+
+func startingTargetDChunkSize(cChunkSize uint64) uint64 { return 2 * cChunkSize }
+
+// stripTrailingZeroes returns b shorn of any trailing '\x00' bytes. The RAC
+// file format will implicitly set any trailing zeroes.
+func stripTrailingZeroes(b []byte) []byte {
+ n := len(b)
+ for (n > 0) && (b[n-1] == 0) {
+ n--
+ }
+ return b[:n]
+}
+
+// writeBuffer is a sequence of bytes, split into two slices: prev[p:] and
+// curr. Together, they hold the tail (so far) of the stream of bytes given to
+// an io.Writer.
+//
+// Conceptually, it is the concatenation of those two slices, but the struct
+// holds two slices, not one, to minimize copying and memory allocation.
+//
+// The first slice, prev[p:], is those bytes from all previous Write calls that
+// have been copied to an internal buffer but not yet fully processed.
+//
+// The second slice, curr, is those bytes from the current Write call that have
+// not been processed.
+//
+// The underlying array that backs the prev slice is owned by the writeBuffer,
+// and is re-used to minimize memory allocations. The curr slice is a sub-slice
+// of the []byte passed to the Write method, and is owned by the caller, not by
+// the writeBuffer.
+//
+// As bytes are fully processed, prev[p:] shrinks (by incrementing "p += etc")
+// and after len(prev[p:]) hits zero, curr shrinks (by re-assigning "curr =
+// curr[etc:]"). The two mechanisms differ (e.g. there is a p int that offsets
+// prev but not a corresponding c int that offsets curr) because of the
+// difference in backing-array memory ownership, mentioned above.
+//
+// The intended usage is for an io.Writer's Write(data) method to first call
+// writeBuffer.extend(data), then a mixture of multiple writeBuffer.peek(n) and
+// writeBuffer.advance(n), and finally writeBuffer.compact(). Thus, before and
+// after every Write call, writeBuffer.curr is empty and writebuffer.p is 0.
+type writeBuffer struct {
+ prev []byte
+ curr []byte
+ p int
+}
+
+// extend extends b's view of an io.Writer's incoming byte stream.
+func (b *writeBuffer) extend(curr []byte) {
+ if len(b.curr) != 0 {
+ panic("inconsistent writeBuffer state")
+ }
+ b.curr = curr
+}
+
+// length returns the total number of bytes available in b's buffers.
+func (b *writeBuffer) length() uint64 {
+ return uint64(len(b.prev)-b.p) + uint64(len(b.curr))
+}
+
+// peek returns the next m bytes in b's buffers, where m is the minimum of n
+// and b.length().
+//
+// The bytes are returned in two slices, not a single contiguous slice, in
+// order to minimize copying and memory allocation.
+func (b *writeBuffer) peek(n uint64) ([]byte, []byte) {
+ available := uint64(len(b.prev) - b.p)
+ if n <= available {
+ return b.prev[b.p : b.p+int(n)], nil
+ }
+ n -= available
+ if n <= uint64(len(b.curr)) {
+ return b.prev[b.p:], b.curr[:n]
+ }
+ return b.prev[b.p:], b.curr
+}
+
+// advance consumes the next n bytes.
+func (b *writeBuffer) advance(n uint64) {
+ available := uint64(len(b.prev) - b.p)
+ if n <= available {
+ b.p += int(n)
+ return
+ }
+ n -= available
+ b.curr = b.curr[n:]
+ b.p = len(b.prev)
+}
+
+// compact moves and copies any unprocessed bytes in b.prev and b.curr to be at
+// the start of b.prev.
+func (b *writeBuffer) compact() {
+ // Move any remaining bytes in prev to the front.
+ n := copy(b.prev, b.prev[b.p:])
+ b.prev = b.prev[:n]
+ b.p = 0
+ // Move any remaining bytes in curr to prev.
+ b.prev = append(b.prev, b.curr...)
+ b.curr = nil
+}
+
+// Writer provides a relatively simple way to write a RAC file (with the Zlib
+// compression codec) - one that is created starting from nothing, as opposed
+// to incrementally modifying an existing RAC file.
+//
+// Other packages may provide a more flexible (and more complicated) way to
+// write or append to RAC files, but that is out of scope of this package.
+//
+// Do not modify its exported fields after calling any of its methods.
+//
+// Writer implements the io.Writer interface.
+type Writer struct {
+ // Writer is where the RAC-encoded data is written to.
+ //
+ // Nil is an invalid value.
+ Writer io.Writer
+
+ // IndexLocation is whether the index is at the start or end of the RAC
+ // file.
+ //
+ // See the RAC specification for further discussion.
+ //
+ // The zero value of this field is IndexLocationAtEnd: a one pass encoding.
+ IndexLocation IndexLocation
+
+ // TempFile is a temporary file to use for a two pass encoding. The field
+ // name says "file" but it need not be a real file, in the operating system
+ // sense.
+ //
+ // For IndexLocationAtEnd, this must be nil. For IndexLocationAtStart, this
+ // must be non-nil.
+ //
+ // It does not need to implement io.Seeker, if it supports separate read
+ // and write positions (e.g. it is a bytes.Buffer). If it does implement
+ // io.Seeker (e.g. it is an os.File), its current position will be noted
+ // (via SeekCurrent), then it will be written to (via the
+ // raczlib.Writer.Write method), then its position will be reset (via
+ // SeekSet), then it will be read from (via the raczlib.Writer.Close
+ // method).
+ //
+ // The raczlib.Writer does not call TempFile.Close even if that method
+ // exists (e.g. the TempFile is an os.File). In that case, closing the
+ // temporary file (and deleting it) after the raczlib.Writer is closed is
+ // the responsibility of the raczlib.Writer caller, not the raczlib.Writer
+ // itself.
+ TempFile io.ReadWriter
+
+ // CPageSize guides padding the output to minimize the number of pages that
+ // each chunk occupies (in what the RAC spec calls CSpace).
+ //
+ // It must either be zero (which means no padding is inserted) or a power
+ // of 2, and no larger than MaxSize.
+ //
+ // For example, suppose that CSpace is partitioned into 1024-byte pages,
+ // that 1000 bytes have already been written to the output, and the next
+ // chunk is 1500 bytes long.
+ //
+ // - With no padding (i.e. with CPageSize set to 0), this chunk will
+ // occupy the half-open range [1000, 2500) in CSpace, which straddles
+ // three 1024-byte pages: the page [0, 1024), the page [1024, 2048) and
+ // the page [2048, 3072). Call those pages p0, p1 and p2.
+ //
+ // - With padding (i.e. with CPageSize set to 1024), 24 bytes of zeroes
+ // are first inserted so that this chunk occupies the half-open range
+ // [1024, 2524) in CSpace, which straddles only two pages (p1 and p2).
+ //
+ // This concept is similar, but not identical, to alignment. Even with a
+ // non-zero CPageSize, chunk start offsets are not necessarily aligned to
+ // page boundaries. For example, suppose that the chunk size was only 1040
+ // bytes, not 1500 bytes. No padding will be inserted, as both [1000, 2040)
+ // and [1024, 2064) straddle two pages: either pages p0 and p1, or pages p1
+ // and p2.
+ //
+ // Nonetheless, if all chunks (or all but the final chunk) have a size
+ // equal to (or just under) a multiple of the page size, then in practice,
+ // each chunk's starting offset will be aligned to a page boundary.
+ CPageSize uint64
+
+ // CChunkSize is the compressed size (i.e. size in CSpace) of each chunk.
+ // The final chunk might be smaller than this.
+ //
+ // This field is ignored if DChunkSize is non-zero.
+ CChunkSize uint64
+
+ // DChunkSize is the uncompressed size (i.e. size in DSpace) of each chunk.
+ // The final chunk might be smaller than this.
+ //
+ // If both CChunkSize and DChunkSize are non-zero, DChunkSize takes
+ // precedence and CChunkSize is ignored.
+ //
+ // If both CChunkSize and DChunkSize are zero, a default DChunkSize value
+ // will be used.
+ DChunkSize uint64
+
+ // cChunkSize and dChunkSize are copies of CChunkSize and DChunkSize,
+ // validated during the initialize method. For example, if both CChunkSize
+ // and DChunkSize are zero, dChunkSize will be defaultDChunkSize.
+ cChunkSize uint64
+ dChunkSize uint64
+
+ // err is the first error encountered. It is sticky: once a non-nil error
+ // occurs, all public methods will return that error.
+ err error
+
+ racWriter rac.Writer
+ zlibWriter *zlib.Writer
+
+ compressed bytes.Buffer
+ uncompressed writeBuffer
+}
+
+func (w *Writer) initialize() error {
+ if w.err != nil {
+ return w.err
+ }
+ if w.racWriter.Writer != nil {
+ // We're already initialized.
+ return nil
+ }
+ if w.Writer == nil {
+ w.err = errInvalidWriter
+ return w.err
+ }
+
+ if w.DChunkSize > 0 {
+ w.dChunkSize = w.DChunkSize
+ } else if w.CChunkSize > 0 {
+ w.cChunkSize = w.CChunkSize
+ if w.cChunkSize > maxCChunkSize {
+ w.cChunkSize = maxCChunkSize
+ }
+ } else {
+ w.dChunkSize = defaultDChunkSize
+ }
+
+ w.racWriter.Writer = w.Writer
+ w.racWriter.Codec = rac.CodecZlib
+ w.racWriter.IndexLocation = w.IndexLocation
+ w.racWriter.TempFile = w.TempFile
+ w.racWriter.CPageSize = w.CPageSize
+
+ w.zlibWriter, w.err = zlib.NewWriterLevel(&w.compressed, zlib.BestCompression)
+ return w.err
+}
+
+func (w *Writer) compress(dBytes0 []byte, dBytes1 []byte) ([]byte, error) {
+ w.compressed.Reset()
+ w.zlibWriter.Reset(&w.compressed)
+ if len(dBytes0) > 0 {
+ if _, err := w.zlibWriter.Write(dBytes0); err != nil {
+ w.err = err
+ return nil, err
+ }
+ }
+ if len(dBytes1) > 0 {
+ if _, err := w.zlibWriter.Write(dBytes1); err != nil {
+ w.err = err
+ return nil, err
+ }
+ }
+ if err := w.zlibWriter.Close(); err != nil {
+ w.err = err
+ return nil, err
+ }
+ return w.compressed.Bytes(), nil
+}
+
+// Write implements io.Writer.
+func (w *Writer) Write(p []byte) (int, error) {
+ if err := w.initialize(); err != nil {
+ return 0, err
+ }
+ w.uncompressed.extend(p)
+ n, err := len(p), w.write(false)
+ w.uncompressed.compact()
+ if err != nil {
+ return 0, err
+ }
+ return n, nil
+}
+
+func (w *Writer) write(eof bool) error {
+ if w.dChunkSize > 0 {
+ return w.writeDChunks(eof)
+ }
+ return w.writeCChunks(eof)
+}
+
+func (w *Writer) writeDChunks(eof bool) error {
+ for {
+ peek0, peek1 := w.uncompressed.peek(w.dChunkSize)
+ dSize := uint64(len(peek0)) + uint64(len(peek1))
+ if dSize == 0 {
+ return nil
+ }
+ if !eof && (dSize < w.dChunkSize) {
+ return nil
+ }
+
+ peek1 = stripTrailingZeroes(peek1)
+ if len(peek1) == 0 {
+ peek0 = stripTrailingZeroes(peek0)
+ }
+ cBytes, err := w.compress(peek0, peek1)
+ if err != nil {
+ return err
+ }
+
+ if err := w.racWriter.AddChunk(dSize, cBytes, 0, 0); err != nil {
+ w.err = err
+ return err
+ }
+ w.uncompressed.advance(dSize)
+ }
+}
+
+func (w *Writer) writeCChunks(eof bool) error {
+ // Each outer loop iteration tries to write exactly one chunk.
+outer:
+ for {
+ // We don't know, a priori, how many w.uncompressed bytes are needed to
+ // produce a compressed chunk of size cChunkSize. We use a
+ // startingTargetDChunkSize that is a small multiple of cChunkSize, and
+ // keep doubling that until we build something at least as large as
+ // cChunkSize, then zlibcut it back to be exactly cChunkSize.
+ targetDChunkSize := uint64(maxTargetDChunkSize)
+ if !eof {
+ targetDChunkSize = startingTargetDChunkSize(w.cChunkSize)
+ }
+
+ if n := w.uncompressed.length(); n == 0 {
+ return nil
+ } else if !eof && (n < targetDChunkSize) {
+ return nil
+ }
+
+ // The inner loop keeps doubling the targetDChunkSize until it's big
+ // enough to produce at least cChunkSize bytes of compressed data.
+ for {
+ next := targetDChunkSize * 2
+ if next > maxTargetDChunkSize {
+ next = maxTargetDChunkSize
+ }
+ force := next <= targetDChunkSize
+
+ if err := w.tryCChunk(targetDChunkSize, force); err == nil {
+ continue outer
+ } else if err != errInternalShortCSize {
+ return err
+ }
+
+ if w.uncompressed.length() <= targetDChunkSize {
+ // Growing the targetDChunkSize isn't going to change anything.
+ return nil
+ }
+ targetDChunkSize = next
+ }
+ }
+}
+
+func (w *Writer) tryCChunk(targetDChunkSize uint64, force bool) error {
+ peek0, peek1 := w.uncompressed.peek(targetDChunkSize)
+ dSize := uint64(len(peek0)) + uint64(len(peek1))
+ cBytes, err := w.compress(peek0, peek1)
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case uint64(len(cBytes)) < w.cChunkSize:
+ if !force {
+ return errInternalShortCSize
+ }
+ fallthrough
+ case uint64(len(cBytes)) == w.cChunkSize:
+ if err := w.racWriter.AddChunk(dSize, cBytes, 0, 0); err != nil {
+ w.err = err
+ return err
+ }
+ w.uncompressed.advance(dSize)
+ return nil
+ }
+
+ eLen, dLen, err := zlibcut.Cut(nil, cBytes, int(w.cChunkSize))
+ if err != nil {
+ w.err = err
+ return err
+ }
+ if dLen == 0 {
+ w.err = errCChunkSizeIsTooSmall
+ return w.err
+ }
+ if err := w.racWriter.AddChunk(uint64(dLen), cBytes[:eLen], 0, 0); err != nil {
+ w.err = err
+ return err
+ }
+ w.uncompressed.advance(uint64(dLen))
+ return nil
+}
+
+// Close writes the RAC index to w.Writer and marks that w accepts no further
+// method calls.
+//
+// For a one pass encoding, no further action is taken. For a two pass encoding
+// (i.e. IndexLocationAtStart), it then copies w.TempFile to w.Writer. Either
+// way, if this method returns nil error, the entirety of what was written to
+// w.Writer constitutes a valid RAC file.
+//
+// Closing the underlying w.Writer, w.TempFile or both is the responsibility of
+// the raczlib.Writer caller, not the raczlib.Writer itself.
+//
+// It is not necessary to call Close, e.g. if an earlier Write call returned a
+// non-nil error. Unlike an os.File, failing to call raczlib.Writer.Close will
+// not leak resources such as file descriptors.
+func (w *Writer) Close() error {
+ if err := w.initialize(); err != nil {
+ return err
+ }
+ if err := w.write(true); err != nil {
+ return err
+ }
+ if err := w.racWriter.Close(); err != nil {
+ w.err = err
+ return err
+ }
+ w.err = errWriterIsClosed
+ return nil
+}
diff --git a/lib/zlibcut/example_test.go b/lib/zlibcut/example_test.go
new file mode 100644
index 0000000..76f4f4f
--- /dev/null
+++ b/lib/zlibcut/example_test.go
@@ -0,0 +1,121 @@
+// Copyright 2019 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package zlibcut_test
+
+import (
+ "bytes"
+ "compress/zlib"
+ "fmt"
+ "io/ioutil"
+ "strings"
+
+ "github.com/google/wuffs/lib/zlibcut"
+)
+
+func ExampleCut() {
+ const sonnet18 = "" +
+ "Shall I compare thee to a summer’s day?\n" +
+ "Thou art more lovely and more temperate.\n" +
+ "Rough winds do shake the darling buds of May,\n" +
+ "And summer’s lease hath all too short a date.\n" +
+ "Sometime too hot the eye of heaven shines,\n" +
+ "And often is his gold complexion dimmed;\n" +
+ "And every fair from fair sometime declines,\n" +
+ "By chance, or nature’s changing course, untrimmed;\n" +
+ "But thy eternal summer shall not fade,\n" +
+ "Nor lose possession of that fair thou ow’st,\n" +
+ "Nor shall death brag thou wand'rest in his shade,\n" +
+ "When in eternal lines to Time thou grow'st.\n" +
+ "So long as men can breathe, or eyes can see,\n" +
+ "So long lives this, and this gives life to thee.\n"
+
+ if n := len(sonnet18); n != 632 {
+ fmt.Printf("len(sonnet18): got %d, want 632", n)
+ return
+ }
+
+ // Compress the input text, sonnet18.
+ buffer := &bytes.Buffer{}
+ w := zlib.NewWriter(buffer)
+ w.Write([]byte(sonnet18))
+ w.Close()
+ compressed := buffer.Bytes()
+
+ // The exact length of the zlib-compressed form of sonnet18 depends on the
+ // compression algorithm used, which can change from version to version of
+ // the Go standard library. Nonetheless, for a 632 byte input, we expect
+ // the compressed form to be between 300 and 500 bytes.
+ if n := len(compressed); (n < 300) || (500 < n) {
+ fmt.Printf("len(compressed): got %d, want something in [300, 500]", n)
+ return
+ }
+
+ // Cut the 300-or-more bytes to be 200.
+ encodedLen, decodedLen, err := zlibcut.Cut(nil, compressed, 200)
+ if err != nil {
+ fmt.Printf("Cut: %v", err)
+ return
+ }
+
+ // The encodedLen should be equal to or just under the requested 200.
+ cut := compressed[:encodedLen]
+ if n := len(cut); (n < 190) || (200 < n) {
+ fmt.Printf("len(cut): got %d, want something in [190, 200]", n)
+ return
+ }
+
+ // At this point, a real program would write that cut slice somewhere. The
+ // rest of this example verifies that the cut data has the properties we
+ // expect, given the semantics of zlibcut.Cut.
+
+ // Uncompress the cut data. It should be a valid zlib-compressed stream, so
+ // no errors should be encountered.
+ r, err := zlib.NewReader(bytes.NewReader(cut))
+ if err != nil {
+ fmt.Printf("NewReader: %v", err)
+ return
+ }
+ uncompressed, err := ioutil.ReadAll(r)
+ if err != nil {
+ fmt.Printf("ReadAll: %v", err)
+ return
+ }
+ err = r.Close()
+ if err != nil {
+ fmt.Printf("Close: %v", err)
+ return
+ }
+
+ // The uncompressed form of the cut data should be a prefix (of length
+ // decodedLen) of the original input, sonnet18. Again, the exact length
+ // depends on the zlib compression algorithm, but uncompressing 200 or so
+ // bytes should give between 250 and 400 bytes.
+ if n := len(uncompressed); n != decodedLen {
+ fmt.Printf("len(uncompressed): got %d, want %d", n, decodedLen)
+ return
+ } else if (n < 250) || (400 < n) {
+ fmt.Printf("len(uncompressed): got %d, want something in [250, 400]", n)
+ return
+ } else if !strings.HasPrefix(sonnet18, string(uncompressed)) {
+ fmt.Printf("uncompressed was not a prefix of the original input")
+ return
+ }
+
+ // The first two lines of the sonnet take 83 bytes.
+ fmt.Println(string(uncompressed[:83]))
+ // Output:
+ // Shall I compare thee to a summer’s day?
+ // Thou art more lovely and more temperate.
+}
diff --git a/lib/zlibcut/zlibcut.go b/lib/zlibcut/zlibcut.go
index 4f7da1c..6554ea1 100644
--- a/lib/zlibcut/zlibcut.go
+++ b/lib/zlibcut/zlibcut.go
@@ -23,8 +23,6 @@
package zlibcut
import (
- "bytes"
- "compress/flate"
"errors"
"hash/adler32"
"io"
@@ -52,11 +50,16 @@
// zlib-compressed data, assuming that encoded starts off containing valid
// zlib-compressed data.
//
+// If a nil error is returned, then encodedLen <= maxEncodedLen will hold.
+//
// Decompressing that modified, shorter byte slice produces a prefix (of length
// decodedLen) of the decompression of the original, longer byte slice.
//
+// If w is non-nil, that prefix is also written to w. If a non-nil error is
+// returned, incomplete data might still be written to w.
+//
// It does not necessarily return the largest possible decodedLen.
-func Cut(encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
+func Cut(w io.Writer, encoded []byte, maxEncodedLen int) (encodedLen int, decodedLen int, retErr error) {
if len(encoded) < 2 {
return 0, 0, errInvalidNotEnoughData
}
@@ -85,7 +88,15 @@
return 0, 0, errMaxEncodedLenTooSmall
}
+ hasher := adler32.New()
+ if w == nil {
+ w = hasher
+ } else {
+ w = io.MultiWriter(w, hasher)
+ }
+
encodedLen, decodedLen, err := flatecut.Cut(
+ w,
encoded[payloadStart:len(encoded)-4],
maxEncodedLen-payloadStart-4,
)
@@ -93,15 +104,7 @@
return 0, 0, err
}
- w := adler32.New()
- r := bytes.NewReader(encoded[payloadStart : payloadStart+encodedLen])
- if n, err := io.Copy(w, flate.NewReader(r)); err != nil {
- return 0, 0, err
- } else if n != int64(decodedLen) {
- return 0, 0, errInternalInconsistentDecodedLen
- }
-
- hash := w.Sum32()
+ hash := hasher.Sum32()
hashBytes := encoded[payloadStart+encodedLen : payloadStart+encodedLen+4]
hashBytes[0] = uint8(hash >> 24)
hashBytes[1] = uint8(hash >> 16)
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index dc00a84..964d7dd 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -191,8 +191,10 @@
typedef const char* wuffs_base__status;
extern const char* wuffs_base__warning__end_of_data;
+extern const char* wuffs_base__warning__metadata_reported;
extern const char* wuffs_base__suspension__short_read;
extern const char* wuffs_base__suspension__short_write;
+extern const char* wuffs_base__error__bad_i_o_position;
extern const char* wuffs_base__error__bad_argument_length_too_short;
extern const char* wuffs_base__error__bad_argument;
extern const char* wuffs_base__error__bad_call_sequence;
@@ -207,6 +209,7 @@
extern const char* wuffs_base__error__initialize_not_called;
extern const char* wuffs_base__error__interleaved_coroutine_calls;
extern const char* wuffs_base__error__not_enough_data;
+extern const char* wuffs_base__error__unsupported_option;
extern const char* wuffs_base__error__too_much_data;
static inline bool //
@@ -236,6 +239,16 @@
// --------
+// FourCC constants.
+
+// International Color Consortium Profile.
+#define WUFFS_BASE__FOURCC__ICCP 0x49434350
+
+// Extensible Metadata Platform.
+#define WUFFS_BASE__FOURCC__XMP 0x584D5020
+
+// --------
+
// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
// second. See https://github.com/OculusVR/Flicks
typedef int64_t wuffs_base__flicks;
@@ -509,14 +522,14 @@
uint32_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct intersect(
- wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct unite(
- wuffs_base__range_ii_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u32;
@@ -530,12 +543,12 @@
}
static inline bool //
-wuffs_base__range_ii_u32__is_empty(wuffs_base__range_ii_u32* r) {
+wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u32__equals(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u32__is_empty(r) &&
@@ -543,7 +556,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__intersect(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
wuffs_base__range_ii_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -552,7 +565,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__unite(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
if (wuffs_base__range_ii_u32__is_empty(r)) {
return s;
@@ -567,12 +580,13 @@
}
static inline bool //
-wuffs_base__range_ii_u32__contains(wuffs_base__range_ii_u32* r, uint32_t x) {
+wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u32__contains_range(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return wuffs_base__range_ii_u32__equals(
&s, wuffs_base__range_ii_u32__intersect(r, s));
@@ -581,32 +595,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u32::is_empty() {
+wuffs_base__range_ii_u32::is_empty() const {
return wuffs_base__range_ii_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__equals(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__intersect(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u32::contains(uint32_t x) {
+wuffs_base__range_ii_u32::contains(uint32_t x) const {
return wuffs_base__range_ii_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__contains_range(this, s);
}
@@ -619,15 +633,15 @@
uint32_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct intersect(
- wuffs_base__range_ie_u32__struct s);
+ wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct unite(
- wuffs_base__range_ie_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ie_u32__struct s);
- inline uint32_t length();
+ wuffs_base__range_ie_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
+ inline uint32_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u32;
@@ -641,12 +655,12 @@
}
static inline bool //
-wuffs_base__range_ie_u32__is_empty(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u32__equals(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u32__is_empty(r) &&
@@ -654,7 +668,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__intersect(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
wuffs_base__range_ie_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -663,7 +677,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__unite(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
if (wuffs_base__range_ie_u32__is_empty(r)) {
return s;
@@ -678,56 +692,57 @@
}
static inline bool //
-wuffs_base__range_ie_u32__contains(wuffs_base__range_ie_u32* r, uint32_t x) {
+wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u32__contains_range(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return wuffs_base__range_ie_u32__equals(
&s, wuffs_base__range_ie_u32__intersect(r, s));
}
static inline uint32_t //
-wuffs_base__range_ie_u32__length(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u32::is_empty() {
+wuffs_base__range_ie_u32::is_empty() const {
return wuffs_base__range_ie_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__equals(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__intersect(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u32::contains(uint32_t x) {
+wuffs_base__range_ie_u32::contains(uint32_t x) const {
return wuffs_base__range_ie_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__contains_range(this, s);
}
inline uint32_t //
-wuffs_base__range_ie_u32::length() {
+wuffs_base__range_ie_u32::length() const {
return wuffs_base__range_ie_u32__length(this);
}
@@ -740,14 +755,14 @@
uint64_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct intersect(
- wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct unite(
- wuffs_base__range_ii_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u64;
@@ -761,12 +776,12 @@
}
static inline bool //
-wuffs_base__range_ii_u64__is_empty(wuffs_base__range_ii_u64* r) {
+wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u64__equals(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u64__is_empty(r) &&
@@ -774,7 +789,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__intersect(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
wuffs_base__range_ii_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -783,7 +798,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__unite(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
if (wuffs_base__range_ii_u64__is_empty(r)) {
return s;
@@ -798,12 +813,13 @@
}
static inline bool //
-wuffs_base__range_ii_u64__contains(wuffs_base__range_ii_u64* r, uint64_t x) {
+wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u64__contains_range(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return wuffs_base__range_ii_u64__equals(
&s, wuffs_base__range_ii_u64__intersect(r, s));
@@ -812,32 +828,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u64::is_empty() {
+wuffs_base__range_ii_u64::is_empty() const {
return wuffs_base__range_ii_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__equals(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__intersect(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u64::contains(uint64_t x) {
+wuffs_base__range_ii_u64::contains(uint64_t x) const {
return wuffs_base__range_ii_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__contains_range(this, s);
}
@@ -850,15 +866,15 @@
uint64_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct intersect(
- wuffs_base__range_ie_u64__struct s);
+ wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct unite(
- wuffs_base__range_ie_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ie_u64__struct s);
- inline uint64_t length();
+ wuffs_base__range_ie_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
+ inline uint64_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u64;
@@ -872,12 +888,12 @@
}
static inline bool //
-wuffs_base__range_ie_u64__is_empty(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u64__equals(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u64__is_empty(r) &&
@@ -885,7 +901,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__intersect(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
wuffs_base__range_ie_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -894,7 +910,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__unite(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
if (wuffs_base__range_ie_u64__is_empty(r)) {
return s;
@@ -909,56 +925,57 @@
}
static inline bool //
-wuffs_base__range_ie_u64__contains(wuffs_base__range_ie_u64* r, uint64_t x) {
+wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u64__contains_range(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return wuffs_base__range_ie_u64__equals(
&s, wuffs_base__range_ie_u64__intersect(r, s));
}
static inline uint64_t //
-wuffs_base__range_ie_u64__length(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u64::is_empty() {
+wuffs_base__range_ie_u64::is_empty() const {
return wuffs_base__range_ie_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__equals(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__intersect(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u64::contains(uint64_t x) {
+wuffs_base__range_ie_u64::contains(uint64_t x) const {
return wuffs_base__range_ie_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__contains_range(this, s);
}
inline uint64_t //
-wuffs_base__range_ie_u64::length() {
+wuffs_base__range_ie_u64::length() const {
return wuffs_base__range_ie_u64__length(this);
}
@@ -982,14 +999,14 @@
uint32_t max_incl_y;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__rect_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct intersect(
- wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct unite(
- wuffs_base__rect_ii_u32__struct s);
- inline bool contains(uint32_t x, uint32_t y);
- inline bool contains_rect(wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
+ inline bool contains(uint32_t x, uint32_t y) const;
+ inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__rect_ii_u32;
@@ -1008,12 +1025,12 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__is_empty(wuffs_base__rect_ii_u32* r) {
+wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {
return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);
}
static inline bool //
-wuffs_base__rect_ii_u32__equals(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||
@@ -1022,7 +1039,7 @@
}
static inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32__intersect(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
wuffs_base__rect_ii_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
@@ -1033,7 +1050,7 @@
}
static inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32__unite(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__unite(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
if (wuffs_base__rect_ii_u32__is_empty(r)) {
return s;
@@ -1050,7 +1067,7 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__contains(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&
@@ -1058,7 +1075,7 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__contains_rect(wuffs_base__rect_ii_u32* r,
+wuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,
wuffs_base__rect_ii_u32 s) {
return wuffs_base__rect_ii_u32__equals(
&s, wuffs_base__rect_ii_u32__intersect(r, s));
@@ -1067,32 +1084,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__rect_ii_u32::is_empty() {
+wuffs_base__rect_ii_u32::is_empty() const {
return wuffs_base__rect_ii_u32__is_empty(this);
}
inline bool //
-wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__equals(this, s);
}
inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__intersect(this, s);
}
inline wuffs_base__rect_ii_u32 //
-wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__unite(this, s);
}
inline bool //
-wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) {
+wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ii_u32__contains(this, x, y);
}
inline bool //
-wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) {
+wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {
return wuffs_base__rect_ii_u32__contains_rect(this, s);
}
@@ -1117,16 +1134,16 @@
uint32_t max_excl_y;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__rect_ie_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct intersect(
- wuffs_base__rect_ie_u32__struct s);
+ wuffs_base__rect_ie_u32__struct s) const;
inline wuffs_base__rect_ie_u32__struct unite(
- wuffs_base__rect_ie_u32__struct s);
- inline bool contains(uint32_t x, uint32_t y);
- inline bool contains_rect(wuffs_base__rect_ie_u32__struct s);
- inline uint32_t width();
- inline uint32_t height();
+ wuffs_base__rect_ie_u32__struct s) const;
+ inline bool contains(uint32_t x, uint32_t y) const;
+ inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
#endif // __cplusplus
} wuffs_base__rect_ie_u32;
@@ -1145,12 +1162,12 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__is_empty(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {
return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);
}
static inline bool //
-wuffs_base__rect_ie_u32__equals(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||
@@ -1159,7 +1176,7 @@
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32__intersect(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
wuffs_base__rect_ie_u32 t;
t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
@@ -1170,7 +1187,7 @@
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32__unite(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__unite(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
if (wuffs_base__rect_ie_u32__is_empty(r)) {
return s;
@@ -1187,7 +1204,7 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__contains(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,
uint32_t x,
uint32_t y) {
return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&
@@ -1195,95 +1212,69 @@
}
static inline bool //
-wuffs_base__rect_ie_u32__contains_rect(wuffs_base__rect_ie_u32* r,
+wuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,
wuffs_base__rect_ie_u32 s) {
return wuffs_base__rect_ie_u32__equals(
&s, wuffs_base__rect_ie_u32__intersect(r, s));
}
static inline uint32_t //
-wuffs_base__rect_ie_u32__width(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__width(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_x, r->min_incl_x);
}
static inline uint32_t //
-wuffs_base__rect_ie_u32__height(wuffs_base__rect_ie_u32* r) {
+wuffs_base__rect_ie_u32__height(const wuffs_base__rect_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__rect_ie_u32::is_empty() {
+wuffs_base__rect_ie_u32::is_empty() const {
return wuffs_base__rect_ie_u32__is_empty(this);
}
inline bool //
-wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__equals(this, s);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__intersect(this, s);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__unite(this, s);
}
inline bool //
-wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) {
+wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {
return wuffs_base__rect_ie_u32__contains(this, x, y);
}
inline bool //
-wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) {
+wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {
return wuffs_base__rect_ie_u32__contains_rect(this, s);
}
inline uint32_t //
-wuffs_base__rect_ie_u32::width() {
+wuffs_base__rect_ie_u32::width() const {
return wuffs_base__rect_ie_u32__width(this);
}
inline uint32_t //
-wuffs_base__rect_ie_u32::height() {
+wuffs_base__rect_ie_u32::height() const {
return wuffs_base__rect_ie_u32__height(this);
}
#endif // __cplusplus
// ---------------- I/O
-
-struct wuffs_base__io_buffer__struct;
-
-typedef struct {
- // Do not access the private_impl's fields directly. There is no API/ABI
- // compatibility or safety guarantee if you do so.
- struct {
- struct wuffs_base__io_buffer__struct* buf;
- // The bounds values are typically NULL, when created by the Wuffs public
- // API. NULL means that the callee substitutes the implicit bounds derived
- // from buf.
- uint8_t* mark;
- uint8_t* limit;
- } private_impl;
-} wuffs_base__io_reader;
-
-typedef struct {
- // Do not access the private_impl's fields directly. There is no API/ABI
- // compatibility or safety guarantee if you do so.
- struct {
- struct wuffs_base__io_buffer__struct* buf;
- // The bounds values are typically NULL, when created by the Wuffs public
- // API. NULL means that the callee substitutes the implicit bounds derived
- // from buf.
- uint8_t* mark;
- uint8_t* limit;
- } private_impl;
-} wuffs_base__io_writer;
+//
+// See (/doc/note/io-input-output.md).
// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
// data.
@@ -1304,10 +1295,12 @@
#ifdef __cplusplus
inline void compact();
- inline wuffs_base__io_reader reader();
- inline wuffs_base__io_writer writer();
- inline uint64_t reader_io_position();
- inline uint64_t writer_io_position();
+ inline wuffs_base__io_buffer__struct* reader(); // Deprecated.
+ inline wuffs_base__io_buffer__struct* writer(); // Deprecated.
+ inline uint64_t reader_available() const;
+ inline uint64_t reader_io_position() const;
+ inline uint64_t writer_available() const;
+ inline uint64_t writer_io_position() const;
#endif // __cplusplus
} wuffs_base__io_buffer;
@@ -1356,24 +1349,6 @@
return ret;
}
-static inline wuffs_base__io_reader //
-wuffs_base__null_io_reader() {
- wuffs_base__io_reader ret;
- ret.private_impl.buf = NULL;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
-static inline wuffs_base__io_writer //
-wuffs_base__null_io_writer() {
- wuffs_base__io_writer ret;
- ret.private_impl.buf = NULL;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
// wuffs_base__io_buffer__compact moves any written but unread bytes to the
// start of the buffer.
static inline void //
@@ -1390,31 +1365,23 @@
buf->meta.ri = 0;
}
-static inline wuffs_base__io_reader //
-wuffs_base__io_buffer__reader(wuffs_base__io_buffer* buf) {
- wuffs_base__io_reader ret;
- ret.private_impl.buf = buf;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
-}
-
-static inline wuffs_base__io_writer //
-wuffs_base__io_buffer__writer(wuffs_base__io_buffer* buf) {
- wuffs_base__io_writer ret;
- ret.private_impl.buf = buf;
- ret.private_impl.mark = NULL;
- ret.private_impl.limit = NULL;
- return ret;
+static inline uint64_t //
+wuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {
+ return buf ? buf->meta.wi - buf->meta.ri : 0;
}
static inline uint64_t //
-wuffs_base__io_buffer__reader_io_position(wuffs_base__io_buffer* buf) {
+wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
}
static inline uint64_t //
-wuffs_base__io_buffer__writer_io_position(wuffs_base__io_buffer* buf) {
+wuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {
+ return buf ? buf->data.len - buf->meta.wi : 0;
+}
+
+static inline uint64_t //
+wuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {
return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
}
@@ -1425,23 +1392,33 @@
wuffs_base__io_buffer__compact(this);
}
-inline wuffs_base__io_reader //
+inline wuffs_base__io_buffer* //
wuffs_base__io_buffer__struct::reader() {
- return wuffs_base__io_buffer__reader(this);
+ return this;
}
-inline wuffs_base__io_writer //
+inline wuffs_base__io_buffer* //
wuffs_base__io_buffer__struct::writer() {
- return wuffs_base__io_buffer__writer(this);
+ return this;
}
inline uint64_t //
-wuffs_base__io_buffer__struct::reader_io_position() {
+wuffs_base__io_buffer__struct::reader_available() const {
+ return wuffs_base__io_buffer__reader_available(this);
+}
+
+inline uint64_t //
+wuffs_base__io_buffer__struct::reader_io_position() const {
return wuffs_base__io_buffer__reader_io_position(this);
}
inline uint64_t //
-wuffs_base__io_buffer__struct::writer_io_position() {
+wuffs_base__io_buffer__struct::writer_available() const {
+ return wuffs_base__io_buffer__writer_available(this);
+}
+
+inline uint64_t //
+wuffs_base__io_buffer__struct::writer_io_position() const {
return wuffs_base__io_buffer__writer_io_position(this);
}
@@ -1525,9 +1502,9 @@
// - bit 20 indicates big-endian/MSB-first (as opposed to little/LSB).
// - bit 19 indicates floating point (as opposed to integer).
// - bit 18 indicates palette-indexed. The number-of-planes (the next
-// field) will be zero, as the format is considered packed,
+// field) will be 0, as the format is considered interleaved,
// but the 8-bit N-BGRA color data is stored in plane 3.
-// - bits 17 .. 16 are the number of planes, minus 1. Zero means packed.
+// - bits 17 .. 16 are the number of planes, minus 1. Zero means interleaved.
// - bits 15 .. 12 encodes the number of bits (depth) in the 3rd channel.
// - bits 11 .. 8 encodes the number of bits (depth) in the 2nd channel.
// - bits 7 .. 4 encodes the number of bits (depth) in the 1st channel.
@@ -1544,14 +1521,14 @@
// channels: cyan, magenta, yellow, black).
//
// For direct formats with N > 1 channels, those channels can be laid out in
-// either 1 (packed) or N (planar) planes. For example, RGBA data is usually
-// packed, but YCbCr data is usually planar, due to chroma subsampling (for
-// details, see the wuffs_base__pixel_subsampling type).
+// either 1 (interleaved) or N (planar) planes. For example, RGBA data is
+// usually interleaved, but YCbCr data is usually planar, due to chroma
+// subsampling (for details, see the wuffs_base__pixel_subsampling type).
//
// For indexed formats, the palette (always 256 × 4 bytes) holds 8 bits per
// channel non-alpha-premultiplied BGRA color data. There is only 1 plane (for
-// the index), as the format is considered packed. Plane 0 holds the per-pixel
-// indices. Plane 3 is re-purposed to hold the per-index colors.
+// the index), as the format is considered interleaved. Plane 0 holds the
+// per-pixel indices. Plane 3 is re-purposed to hold the per-index colors.
//
// The color field is encoded in 3 bits:
// - 0 means A (Alpha).
@@ -1565,8 +1542,8 @@
//
// In Wuffs, channels are given in memory order (also known as byte order),
// regardless of endianness, since the C type for the pixel data is an array of
-// bytes, not an array of uint32_t. For example, packed BGRA with 8 bits per
-// channel means that the bytes in memory are always Blue, Green, Red then
+// bytes, not an array of uint32_t. For example, interleaved BGRA with 8 bits
+// per channel means that the bytes in memory are always Blue, Green, Red then
// Alpha. On big-endian systems, that is the uint32_t 0xBBGGRRAA. On
// little-endian, 0xAARRGGBB.
//
@@ -1599,15 +1576,15 @@
//
// For example, wuffs_base__pixel_format 0x5510BBBB is a natural format for
// decoding a PNG image - network byte order (also known as big-endian),
-// packed, non-premultiplied alpha - that happens to be 16-bit-depth truecolor
-// with alpha (RGBA). In memory order:
+// interleaved, non-premultiplied alpha - that happens to be 16-bit-depth
+// truecolor with alpha (RGBA). In memory order:
//
// ptr+0 ptr+1 ptr+2 ptr+3 ptr+4 ptr+5 ptr+6 ptr+7
// Rhi Rlo Ghi Glo Bhi Blo Ahi Alo
//
// For example, the value wuffs_base__pixel_format 0x40000565 means BGR with no
-// alpha or padding, 5/6/5 bits for blue/green/red, packed 2 bytes per pixel,
-// laid out LSB-first in memory order:
+// alpha or padding, 5/6/5 bits for blue/green/red, interleaved 2 bytes per
+// pixel, laid out LSB-first in memory order:
//
// ptr+0........... ptr+1...........
// MSB LSB MSB LSB
@@ -1692,8 +1669,8 @@
return f != 0;
}
-// wuffs_base__pixel_format__bits_per_pixel returns, for packed pixel formats,
-// the number of bits per pixel. It returns 0 for planar pixel formats.
+// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per
+// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.
static inline uint32_t //
wuffs_base__pixel_format__bits_per_pixel(wuffs_base__pixel_format f) {
if (((f >> 16) & 0x03) != 0) {
@@ -1711,7 +1688,7 @@
}
static inline bool //
-wuffs_base__pixel_format__is_packed(wuffs_base__pixel_format f) {
+wuffs_base__pixel_format__is_interleaved(wuffs_base__pixel_format f) {
return ((f >> 16) & 0x03) == 0;
}
@@ -1737,7 +1714,7 @@
// plane p. For a depth of 8 bits (1 byte), the p'th plane's sample starts at
// (planes[p].ptr + (j * planes[p].stride) + i).
//
-// For packed pixel formats, the mapping is trivial: i = x and j = y. For
+// For interleaved pixel formats, the mapping is trivial: i = x and j = y. For
// planar pixel formats, the mapping can differ due to chroma subsampling. For
// example, consider a three plane YCbCr pixel format with 4:2:2 subsampling.
// For the luma (Y) channel, there is one sample for every pixel, but for the
@@ -1828,13 +1805,13 @@
uint32_t width,
uint32_t height);
inline void invalidate();
- inline bool is_valid();
- inline wuffs_base__pixel_format pixel_format();
- inline wuffs_base__pixel_subsampling pixel_subsampling();
- inline wuffs_base__rect_ie_u32 bounds();
- inline uint32_t width();
- inline uint32_t height();
- inline uint64_t pixbuf_len();
+ inline bool is_valid() const;
+ inline wuffs_base__pixel_format pixel_format() const;
+ inline wuffs_base__pixel_subsampling pixel_subsampling() const;
+ inline wuffs_base__rect_ie_u32 bounds() const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
+ inline uint64_t pixbuf_len() const;
#endif // __cplusplus
} wuffs_base__pixel_config;
@@ -1888,22 +1865,22 @@
}
static inline bool //
-wuffs_base__pixel_config__is_valid(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {
return c && c->private_impl.pixfmt;
}
static inline wuffs_base__pixel_format //
-wuffs_base__pixel_config__pixel_format(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixfmt : 0;
}
static inline wuffs_base__pixel_subsampling //
-wuffs_base__pixel_config__pixel_subsampling(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.pixsub : 0;
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__pixel_config__bounds(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {
if (c) {
wuffs_base__rect_ie_u32 ret;
ret.min_incl_x = 0;
@@ -1922,20 +1899,20 @@
}
static inline uint32_t //
-wuffs_base__pixel_config__width(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.width : 0;
}
static inline uint32_t //
-wuffs_base__pixel_config__height(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {
return c ? c->private_impl.height : 0;
}
-// TODO: this is the right API for planar (not packed) pixbufs? Should it allow
-// decoding into a color model different from the format's intrinsic one? For
-// example, decoding a JPEG image straight to RGBA instead of to YCbCr?
+// TODO: this is the right API for planar (not interleaved) pixbufs? Should it
+// allow decoding into a color model different from the format's intrinsic one?
+// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?
static inline uint64_t //
-wuffs_base__pixel_config__pixbuf_len(wuffs_base__pixel_config* c) {
+wuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {
if (!c) {
return 0;
}
@@ -1984,37 +1961,37 @@
}
inline bool //
-wuffs_base__pixel_config::is_valid() {
+wuffs_base__pixel_config::is_valid() const {
return wuffs_base__pixel_config__is_valid(this);
}
inline wuffs_base__pixel_format //
-wuffs_base__pixel_config::pixel_format() {
+wuffs_base__pixel_config::pixel_format() const {
return wuffs_base__pixel_config__pixel_format(this);
}
inline wuffs_base__pixel_subsampling //
-wuffs_base__pixel_config::pixel_subsampling() {
+wuffs_base__pixel_config::pixel_subsampling() const {
return wuffs_base__pixel_config__pixel_subsampling(this);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__pixel_config::bounds() {
+wuffs_base__pixel_config::bounds() const {
return wuffs_base__pixel_config__bounds(this);
}
inline uint32_t //
-wuffs_base__pixel_config::width() {
+wuffs_base__pixel_config::width() const {
return wuffs_base__pixel_config__width(this);
}
inline uint32_t //
-wuffs_base__pixel_config::height() {
+wuffs_base__pixel_config::height() const {
return wuffs_base__pixel_config__height(this);
}
inline uint64_t //
-wuffs_base__pixel_config::pixbuf_len() {
+wuffs_base__pixel_config::pixbuf_len() const {
return wuffs_base__pixel_config__pixbuf_len(this);
}
@@ -2040,9 +2017,9 @@
uint64_t first_frame_io_position,
bool first_frame_is_opaque);
inline void invalidate();
- inline bool is_valid();
- inline uint64_t first_frame_io_position();
- inline bool first_frame_is_opaque();
+ inline bool is_valid() const;
+ inline uint64_t first_frame_io_position() const;
+ inline bool first_frame_is_opaque() const;
#endif // __cplusplus
} wuffs_base__image_config;
@@ -2099,17 +2076,19 @@
}
static inline bool //
-wuffs_base__image_config__is_valid(wuffs_base__image_config* c) {
+wuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {
return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));
}
static inline uint64_t //
-wuffs_base__image_config__first_frame_io_position(wuffs_base__image_config* c) {
+wuffs_base__image_config__first_frame_io_position(
+ const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_io_position : 0;
}
static inline bool //
-wuffs_base__image_config__first_frame_is_opaque(wuffs_base__image_config* c) {
+wuffs_base__image_config__first_frame_is_opaque(
+ const wuffs_base__image_config* c) {
return c ? c->private_impl.first_frame_is_opaque : false;
}
@@ -2132,17 +2111,17 @@
}
inline bool //
-wuffs_base__image_config::is_valid() {
+wuffs_base__image_config::is_valid() const {
return wuffs_base__image_config__is_valid(this);
}
inline uint64_t //
-wuffs_base__image_config::first_frame_io_position() {
+wuffs_base__image_config::first_frame_io_position() const {
return wuffs_base__image_config__first_frame_io_position(this);
}
inline bool //
-wuffs_base__image_config::first_frame_is_opaque() {
+wuffs_base__image_config::first_frame_is_opaque() const {
return wuffs_base__image_config__first_frame_is_opaque(this);
}
@@ -2198,6 +2177,7 @@
uint64_t io_position;
wuffs_base__animation_blend blend;
wuffs_base__animation_disposal disposal;
+ wuffs_base__color_u32_argb_premul background_color;
} private_impl;
#ifdef __cplusplus
@@ -2206,15 +2186,17 @@
uint64_t index,
uint64_t io_position,
wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal);
- inline wuffs_base__rect_ie_u32 bounds();
- inline uint32_t width();
- inline uint32_t height();
- inline wuffs_base__flicks duration();
- inline uint64_t index();
- inline uint64_t io_position();
- inline wuffs_base__animation_blend blend();
- inline wuffs_base__animation_disposal disposal();
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color);
+ inline wuffs_base__rect_ie_u32 bounds() const;
+ inline uint32_t width() const;
+ inline uint32_t height() const;
+ inline wuffs_base__flicks duration() const;
+ inline uint64_t index() const;
+ inline uint64_t io_position() const;
+ inline wuffs_base__animation_blend blend() const;
+ inline wuffs_base__animation_disposal disposal() const;
+ inline wuffs_base__color_u32_argb_premul background_color() const;
#endif // __cplusplus
} wuffs_base__frame_config;
@@ -2232,13 +2214,15 @@
}
static inline void //
-wuffs_base__frame_config__update(wuffs_base__frame_config* c,
- wuffs_base__rect_ie_u32 bounds,
- wuffs_base__flicks duration,
- uint64_t index,
- uint64_t io_position,
- wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal) {
+wuffs_base__frame_config__update(
+ wuffs_base__frame_config* c,
+ wuffs_base__rect_ie_u32 bounds,
+ wuffs_base__flicks duration,
+ uint64_t index,
+ uint64_t io_position,
+ wuffs_base__animation_blend blend,
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color) {
if (!c) {
return;
}
@@ -2249,10 +2233,11 @@
c->private_impl.io_position = io_position;
c->private_impl.blend = blend;
c->private_impl.disposal = disposal;
+ c->private_impl.background_color = background_color;
}
static inline wuffs_base__rect_ie_u32 //
-wuffs_base__frame_config__bounds(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {
if (c) {
return c->private_impl.bounds;
}
@@ -2266,103 +2251,115 @@
}
static inline uint32_t //
-wuffs_base__frame_config__width(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__width(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;
}
static inline uint32_t //
-wuffs_base__frame_config__height(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__height(const wuffs_base__frame_config* c) {
return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;
}
// wuffs_base__frame_config__duration returns the amount of time to display
// this frame. Zero means to display forever - a still (non-animated) image.
static inline wuffs_base__flicks //
-wuffs_base__frame_config__duration(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {
return c ? c->private_impl.duration : 0;
}
// wuffs_base__frame_config__index returns the index of this frame. The first
// frame in an image has index 0, the second frame has index 1, and so on.
static inline uint64_t //
-wuffs_base__frame_config__index(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__index(const wuffs_base__frame_config* c) {
return c ? c->private_impl.index : 0;
}
// wuffs_base__frame_config__io_position returns the I/O stream position before
// the frame config.
static inline uint64_t //
-wuffs_base__frame_config__io_position(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {
return c ? c->private_impl.io_position : 0;
}
// wuffs_base__frame_config__blend returns, for an animated image, how to blend
// the transparent pixels of this frame with the existing canvas.
static inline wuffs_base__animation_blend //
-wuffs_base__frame_config__blend(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__blend(const wuffs_base__frame_config* c) {
return c ? c->private_impl.blend : 0;
}
// wuffs_base__frame_config__disposal returns, for an animated image, how to
// dispose of this frame after displaying it.
static inline wuffs_base__animation_disposal //
-wuffs_base__frame_config__disposal(wuffs_base__frame_config* c) {
+wuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {
return c ? c->private_impl.disposal : 0;
}
+static inline wuffs_base__color_u32_argb_premul //
+wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
+ return c ? c->private_impl.background_color : 0;
+}
+
#ifdef __cplusplus
inline void //
-wuffs_base__frame_config::update(wuffs_base__rect_ie_u32 bounds,
- wuffs_base__flicks duration,
- uint64_t index,
- uint64_t io_position,
- wuffs_base__animation_blend blend,
- wuffs_base__animation_disposal disposal) {
+wuffs_base__frame_config::update(
+ wuffs_base__rect_ie_u32 bounds,
+ wuffs_base__flicks duration,
+ uint64_t index,
+ uint64_t io_position,
+ wuffs_base__animation_blend blend,
+ wuffs_base__animation_disposal disposal,
+ wuffs_base__color_u32_argb_premul background_color) {
wuffs_base__frame_config__update(this, bounds, duration, index, io_position,
- blend, disposal);
+ blend, disposal, background_color);
}
inline wuffs_base__rect_ie_u32 //
-wuffs_base__frame_config::bounds() {
+wuffs_base__frame_config::bounds() const {
return wuffs_base__frame_config__bounds(this);
}
inline uint32_t //
-wuffs_base__frame_config::width() {
+wuffs_base__frame_config::width() const {
return wuffs_base__frame_config__width(this);
}
inline uint32_t //
-wuffs_base__frame_config::height() {
+wuffs_base__frame_config::height() const {
return wuffs_base__frame_config__height(this);
}
inline wuffs_base__flicks //
-wuffs_base__frame_config::duration() {
+wuffs_base__frame_config::duration() const {
return wuffs_base__frame_config__duration(this);
}
inline uint64_t //
-wuffs_base__frame_config::index() {
+wuffs_base__frame_config::index() const {
return wuffs_base__frame_config__index(this);
}
inline uint64_t //
-wuffs_base__frame_config::io_position() {
+wuffs_base__frame_config::io_position() const {
return wuffs_base__frame_config__io_position(this);
}
inline wuffs_base__animation_blend //
-wuffs_base__frame_config::blend() {
+wuffs_base__frame_config::blend() const {
return wuffs_base__frame_config__blend(this);
}
inline wuffs_base__animation_disposal //
-wuffs_base__frame_config::disposal() {
+wuffs_base__frame_config::disposal() const {
return wuffs_base__frame_config__disposal(this);
}
+inline wuffs_base__color_u32_argb_premul //
+wuffs_base__frame_config::background_color() const {
+ return wuffs_base__frame_config__background_color(this);
+}
+
#endif // __cplusplus
// --------
@@ -2380,8 +2377,10 @@
#ifdef __cplusplus
inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,
wuffs_base__slice_u8 pixbuf_memory);
+ inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory);
inline wuffs_base__slice_u8 palette();
- inline wuffs_base__pixel_format pixel_format();
+ inline wuffs_base__pixel_format pixel_format() const;
inline wuffs_base__table_u8 plane(uint32_t p);
#endif // __cplusplus
@@ -2411,12 +2410,13 @@
}
if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
// TODO: support planar pixel formats, concious of pixel subsampling.
- return wuffs_base__error__bad_argument;
+ return wuffs_base__error__unsupported_option;
}
uint32_t bits_per_pixel =
wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
- return wuffs_base__error__bad_argument;
+ // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+ return wuffs_base__error__unsupported_option;
}
uint64_t bytes_per_pixel = bits_per_pixel / 8;
@@ -2462,6 +2462,38 @@
return NULL;
}
+static inline wuffs_base__status //
+wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,
+ wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory) {
+ if (!b) {
+ return wuffs_base__error__bad_receiver;
+ }
+ memset(b, 0, sizeof(*b));
+ if (!pixcfg ||
+ wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
+ return wuffs_base__error__bad_argument;
+ }
+ uint32_t bits_per_pixel =
+ wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
+ if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
+ // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+ return wuffs_base__error__unsupported_option;
+ }
+ uint64_t bytes_per_pixel = bits_per_pixel / 8;
+
+ uint64_t width_in_bytes =
+ ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
+ if ((width_in_bytes > pixbuf_memory.width) ||
+ (pixcfg->private_impl.height > pixbuf_memory.height)) {
+ return wuffs_base__error__bad_argument;
+ }
+
+ b->pixcfg = *pixcfg;
+ b->private_impl.planes[0] = pixbuf_memory;
+ return NULL;
+}
+
// wuffs_base__pixel_buffer__palette returns the palette color data. If
// non-empty, it will have length 1024.
static inline wuffs_base__slice_u8 //
@@ -2478,7 +2510,7 @@
}
static inline wuffs_base__pixel_format //
-wuffs_base__pixel_buffer__pixel_format(wuffs_base__pixel_buffer* b) {
+wuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {
if (b) {
return b->pixcfg.private_impl.pixfmt;
}
@@ -2507,13 +2539,19 @@
return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);
}
+inline wuffs_base__status //
+wuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,
+ wuffs_base__table_u8 pixbuf_memory) {
+ return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);
+}
+
inline wuffs_base__slice_u8 //
wuffs_base__pixel_buffer::palette() {
return wuffs_base__pixel_buffer__palette(this);
}
inline wuffs_base__pixel_format //
-wuffs_base__pixel_buffer::pixel_format() {
+wuffs_base__pixel_buffer::pixel_format() const {
return wuffs_base__pixel_buffer__pixel_format(this);
}
@@ -2555,20 +2593,18 @@
} private_impl;
#ifdef __cplusplus
- inline void prepare(wuffs_base__pixel_format dst_format,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__pixel_format src_format,
- wuffs_base__slice_u8 src_palette);
- inline uint64_t swizzle_packed(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src);
+ inline wuffs_base__status prepare(wuffs_base__pixel_format dst_format,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__pixel_format src_format,
+ wuffs_base__slice_u8 src_palette);
+ inline uint64_t swizzle_interleaved(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) const;
#endif // __cplusplus
} wuffs_base__pixel_swizzler;
-// TODO: should prepare (both the C and C++ methods) return a status?
-
-void //
+wuffs_base__status //
wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
@@ -2576,28 +2612,30 @@
wuffs_base__slice_u8 src_palette);
uint64_t //
-wuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,
- wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src);
+wuffs_base__pixel_swizzler__swizzle_interleaved(
+ const wuffs_base__pixel_swizzler* p,
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src);
#ifdef __cplusplus
-inline void //
+inline wuffs_base__status //
wuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette) {
- wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette, src_format,
- src_palette);
+ return wuffs_base__pixel_swizzler__prepare(this, dst_format, dst_palette,
+ src_format, src_palette);
}
uint64_t //
-wuffs_base__pixel_swizzler::swizzle_packed(wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src) {
- return wuffs_base__pixel_swizzler__swizzle_packed(this, dst, dst_palette,
- src);
+wuffs_base__pixel_swizzler::swizzle_interleaved(
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) const {
+ return wuffs_base__pixel_swizzler__swizzle_interleaved(this, dst, dst_palette,
+ src);
}
#endif // __cplusplus
@@ -2900,8 +2938,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf);
// ---------------- Struct Definitions
@@ -3019,8 +3057,8 @@
}
inline wuffs_base__status //
- decode_io_writer(wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ decode_io_writer(wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
return wuffs_deflate__decoder__decode_io_writer(this, a_dst, a_src,
a_workbuf);
@@ -3091,8 +3129,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_lzw__decoder__decode_io_writer(wuffs_lzw__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf);
WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8 //
@@ -3189,8 +3227,8 @@
}
inline wuffs_base__status //
- decode_io_writer(wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ decode_io_writer(wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
return wuffs_lzw__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
}
@@ -3225,9 +3263,11 @@
extern const char* wuffs_gif__error__bad_block;
extern const char* wuffs_gif__error__bad_extension_label;
+extern const char* wuffs_gif__error__bad_frame_size;
extern const char* wuffs_gif__error__bad_graphic_control;
extern const char* wuffs_gif__error__bad_header;
extern const char* wuffs_gif__error__bad_literal_width;
+extern const char* wuffs_gif__error__bad_palette;
// ---------------- Public Consts
@@ -3237,6 +3277,49 @@
wuffs_gif__decoder_workbuf_len_max_incl_worst_case //
WUFFS_BASE__POTENTIALLY_UNUSED = 1;
+#define WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES 1041635328
+
+static const uint32_t //
+ wuffs_gif__quirk_delay_num_decoded_frames //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635328;
+
+#define WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND \
+ 1041635329
+
+static const uint32_t //
+ wuffs_gif__quirk_first_frame_local_palette_means_black_background //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635329;
+
+#define WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR 1041635330
+
+static const uint32_t //
+ wuffs_gif__quirk_honor_background_color //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635330;
+
+#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635331
+
+static const uint32_t //
+ wuffs_gif__quirk_ignore_too_much_pixel_data //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635331;
+
+#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635332
+
+static const uint32_t //
+ wuffs_gif__quirk_image_bounds_are_strict //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635332;
+
+#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333
+
+static const uint32_t //
+ wuffs_gif__quirk_reject_empty_frame //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635333;
+
+#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635334
+
+static const uint32_t //
+ wuffs_gif__quirk_reject_empty_palette //
+ WUFFS_BASE__POTENTIALLY_UNUSED = 1041635334;
+
// ---------------- Struct Declarations
typedef struct wuffs_gif__decoder__struct wuffs_gif__decoder;
@@ -3260,10 +3343,30 @@
// ---------------- Public Function Prototypes
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_gif__decoder__set_quirk_enabled(wuffs_gif__decoder* self,
+ uint32_t a_quirk,
+ bool a_enabled);
+
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_image_config(wuffs_gif__decoder* self,
wuffs_base__image_config* a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_gif__decoder__set_report_metadata(wuffs_gif__decoder* self,
+ uint32_t a_fourcc,
+ bool a_report);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_gif__decoder__ack_metadata_chunk(wuffs_gif__decoder* self,
+ wuffs_base__io_buffer* a_src);
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_gif__decoder__metadata_fourcc(const wuffs_gif__decoder* self);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_gif__decoder__metadata_chunk_length(const wuffs_gif__decoder* self);
WUFFS_BASE__MAYBE_STATIC uint32_t //
wuffs_gif__decoder__num_animation_loops(const wuffs_gif__decoder* self);
@@ -3288,12 +3391,12 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_frame_config(wuffs_gif__decoder* self,
wuffs_base__frame_config* a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_frame(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf,
wuffs_base__decode_frame_options* a_opts);
@@ -3323,14 +3426,29 @@
uint32_t f_width;
uint32_t f_height;
uint8_t f_call_sequence;
+ bool f_ignore_metadata;
+ bool f_report_metadata_iccp;
+ bool f_report_metadata_xmp;
+ uint32_t f_metadata_fourcc_value;
+ uint64_t f_metadata_chunk_length_value;
+ uint64_t f_metadata_io_position;
+ bool f_quirk_enabled_delay_num_decoded_frames;
+ bool f_quirk_enabled_first_frame_local_palette_means_black_background;
+ bool f_quirk_enabled_honor_background_color;
+ bool f_quirk_enabled_ignore_too_much_pixel_data;
+ bool f_quirk_enabled_image_bounds_are_strict;
+ bool f_quirk_enabled_reject_empty_frame;
+ bool f_quirk_enabled_reject_empty_palette;
+ bool f_delayed_num_decoded_frames;
bool f_end_of_data;
bool f_restarted;
bool f_previous_lzw_decode_ended_abruptly;
- uint8_t f_which_palette;
+ bool f_has_global_palette;
uint8_t f_interlace;
bool f_seen_num_loops;
uint32_t f_num_loops;
- bool f_seen_graphic_control;
+ uint32_t f_background_color_u32_argb_premul;
+ uint32_t f_black_color_u32_argb_premul;
bool f_gc_has_transparent_index;
uint8_t f_gc_transparent_index;
uint8_t f_gc_disposal;
@@ -3350,6 +3468,7 @@
wuffs_base__pixel_swizzler f_swizzler;
uint32_t p_decode_image_config[1];
+ uint32_t p_ack_metadata_chunk[1];
uint32_t p_decode_frame_config[1];
uint32_t p_skip_frame[1];
uint32_t p_decode_frame[1];
@@ -3372,6 +3491,10 @@
wuffs_lzw__decoder f_lzw;
struct {
+ uint8_t v_blend;
+ uint32_t v_background_color;
+ } s_decode_frame_config[1];
+ struct {
uint64_t scratch;
} s_skip_frame[1];
struct {
@@ -3380,6 +3503,7 @@
} s_decode_header[1];
struct {
uint8_t v_flags;
+ uint8_t v_background_color_index;
uint32_t v_num_palette_entries;
uint32_t v_i;
uint64_t scratch;
@@ -3389,8 +3513,10 @@
} s_skip_blocks[1];
struct {
uint8_t v_block_size;
- bool v_not_animexts;
- bool v_not_netscape;
+ bool v_is_animexts;
+ bool v_is_netscape;
+ bool v_is_iccp;
+ bool v_is_xmp;
uint64_t scratch;
} s_decode_ae[1];
struct {
@@ -3400,6 +3526,7 @@
uint64_t scratch;
} s_decode_id_part0[1];
struct {
+ uint8_t v_which_palette;
uint32_t v_num_palette_entries;
uint32_t v_i;
uint64_t scratch;
@@ -3444,12 +3571,37 @@
initialize_flags);
}
+ inline wuffs_base__empty_struct //
+ set_quirk_enabled(uint32_t a_quirk, bool a_enabled) {
+ return wuffs_gif__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
+ }
+
inline wuffs_base__status //
decode_image_config(wuffs_base__image_config* a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
return wuffs_gif__decoder__decode_image_config(this, a_dst, a_src);
}
+ inline wuffs_base__empty_struct //
+ set_report_metadata(uint32_t a_fourcc, bool a_report) {
+ return wuffs_gif__decoder__set_report_metadata(this, a_fourcc, a_report);
+ }
+
+ inline wuffs_base__status //
+ ack_metadata_chunk(wuffs_base__io_buffer* a_src) {
+ return wuffs_gif__decoder__ack_metadata_chunk(this, a_src);
+ }
+
+ inline uint32_t //
+ metadata_fourcc() const {
+ return wuffs_gif__decoder__metadata_fourcc(this);
+ }
+
+ inline uint64_t //
+ metadata_chunk_length() const {
+ return wuffs_gif__decoder__metadata_chunk_length(this);
+ }
+
inline uint32_t //
num_animation_loops() const {
return wuffs_gif__decoder__num_animation_loops(this);
@@ -3482,13 +3634,13 @@
inline wuffs_base__status //
decode_frame_config(wuffs_base__frame_config* a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
return wuffs_gif__decoder__decode_frame_config(this, a_dst, a_src);
}
inline wuffs_base__status //
decode_frame(wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf,
wuffs_base__decode_frame_options* a_opts) {
return wuffs_gif__decoder__decode_frame(this, a_dst, a_src, a_workbuf,
@@ -3562,8 +3714,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gzip__decoder__decode_io_writer(wuffs_gzip__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf);
// ---------------- Struct Definitions
@@ -3650,8 +3802,8 @@
}
inline wuffs_base__status //
- decode_io_writer(wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ decode_io_writer(wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
return wuffs_gzip__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
}
@@ -3723,8 +3875,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_zlib__decoder__decode_io_writer(wuffs_zlib__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf);
// ---------------- Struct Definitions
@@ -3808,8 +3960,8 @@
}
inline wuffs_base__status //
- decode_io_writer(wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ decode_io_writer(wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
return wuffs_zlib__decoder__decode_io_writer(this, a_dst, a_src, a_workbuf);
}
@@ -4304,65 +4456,52 @@
// ---------------- I/O
-static inline bool //
-wuffs_base__io_buffer__is_valid(wuffs_base__io_buffer buf) {
- return (buf.data.ptr || (buf.data.len == 0)) &&
- (buf.data.len >= buf.meta.wi) && (buf.meta.wi >= buf.meta.ri);
-}
-
-// TODO: wuffs_base__io_reader__is_eof is no longer used by Wuffs per se, but
-// it might be handy to programs that use Wuffs. Either delete it, or promote
-// it to the public API.
+// "Null" as in "/dev/null", not as in "nullptr".
//
-// If making this function public (i.e. moving it to base-header.h), it also
-// needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
+// TODO: ensure that this is zero-initialized.
+static wuffs_base__io_buffer wuffs_base__global__null_io_buffer;
-static inline bool //
-wuffs_base__io_reader__is_eof(wuffs_base__io_reader o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- return buf && buf->meta.closed &&
- (buf->data.ptr + buf->meta.wi == o.private_impl.limit);
+static inline wuffs_base__io_buffer* //
+wuffs_base__null_io_reader() {
+ return &wuffs_base__global__null_io_buffer;
}
-static inline bool //
-wuffs_base__io_reader__is_valid(wuffs_base__io_reader o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- // Note: if making this function public (i.e. moving it to base-header.h), it
- // also needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
- return buf ? ((buf->data.ptr <= o.private_impl.mark) &&
- (o.private_impl.mark <= o.private_impl.limit) &&
- (o.private_impl.limit <= buf->data.ptr + buf->data.len))
- : ((o.private_impl.mark == NULL) &&
- (o.private_impl.limit == NULL));
+static inline wuffs_base__io_buffer* //
+wuffs_base__null_io_writer() {
+ return &wuffs_base__global__null_io_buffer;
}
-static inline bool //
-wuffs_base__io_writer__is_valid(wuffs_base__io_writer o) {
- wuffs_base__io_buffer* buf = o.private_impl.buf;
- // Note: if making this function public (i.e. moving it to base-header.h), it
- // also needs to allow NULL (i.e. implicit, callee-calculated) mark/limit.
- return buf ? ((buf->data.ptr <= o.private_impl.mark) &&
- (o.private_impl.mark <= o.private_impl.limit) &&
- (o.private_impl.limit <= buf->data.ptr + buf->data.len))
- : ((o.private_impl.mark == NULL) &&
- (o.private_impl.limit == NULL));
+static inline uint64_t //
+wuffs_base__io__count_since(uint64_t mark, uint64_t index) {
+ if (index >= mark) {
+ return index - mark;
+ }
+ return 0;
+}
+
+static inline wuffs_base__slice_u8 //
+wuffs_base__io__since(uint64_t mark, uint64_t index, uint8_t* ptr) {
+ if (index >= mark) {
+ return wuffs_base__make_slice_u8(ptr + mark, index - mark);
+ }
+ return wuffs_base__make_slice_u8(NULL, 0);
}
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_history(uint8_t** ptr_iop_w,
- uint8_t* io0_w,
uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint32_t distance) {
if (!distance) {
return 0;
}
uint8_t* p = *ptr_iop_w;
- if ((size_t)(p - io0_w) < (size_t)(distance)) {
+ if ((size_t)(p - io1_w) < (size_t)(distance)) {
return 0;
}
uint8_t* q = p - distance;
- size_t n = (size_t)(io1_w - p);
+ size_t n = (size_t)(io2_w - p);
if ((size_t)(length) > n) {
length = (uint32_t)(n);
} else {
@@ -4394,12 +4533,12 @@
// wuffs_base__io_writer__copy_n_from_history function above, but has stronger
// pre-conditions. The caller needs to prove that:
// - distance > 0
-// - distance <= (*ptr_iop_w - io0_w)
-// - length <= (io1_w - *ptr_iop_w)
+// - distance <= (*ptr_iop_w - io1_w)
+// - length <= (io2_w - *ptr_iop_w)
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_history_fast(uint8_t** ptr_iop_w,
- uint8_t* io0_w,
uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint32_t distance) {
uint8_t* p = *ptr_iop_w;
@@ -4419,18 +4558,18 @@
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_reader(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
uint8_t** ptr_iop_r,
- uint8_t* io1_r) {
+ uint8_t* io2_r) {
uint8_t* iop_w = *ptr_iop_w;
size_t n = length;
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
uint8_t* iop_r = *ptr_iop_r;
- if (n > ((size_t)(io1_r - iop_r))) {
- n = (size_t)(io1_r - iop_r);
+ if (n > ((size_t)(io2_r - iop_r))) {
+ n = (size_t)(io2_r - iop_r);
}
if (n > 0) {
memmove(iop_w, iop_r, n);
@@ -4442,12 +4581,12 @@
static inline uint64_t //
wuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
wuffs_base__slice_u8 src) {
uint8_t* iop_w = *ptr_iop_w;
size_t n = src.len;
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
if (n > 0) {
memmove(iop_w, src.ptr, n);
@@ -4458,7 +4597,7 @@
static inline uint32_t //
wuffs_base__io_writer__copy_n_from_slice(uint8_t** ptr_iop_w,
- uint8_t* io1_w,
+ uint8_t* io2_w,
uint32_t length,
wuffs_base__slice_u8 src) {
uint8_t* iop_w = *ptr_iop_w;
@@ -4466,8 +4605,8 @@
if (n > length) {
n = length;
}
- if (n > ((size_t)(io1_w - iop_w))) {
- n = (size_t)(io1_w - iop_w);
+ if (n > ((size_t)(io2_w - iop_w))) {
+ n = (size_t)(io2_w - iop_w);
}
if (n > 0) {
memmove(iop_w, src.ptr, n);
@@ -4476,11 +4615,12 @@
return (uint32_t)(n);
}
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set(wuffs_base__io_reader* o,
- wuffs_base__io_buffer* b,
+static inline wuffs_base__io_buffer* //
+wuffs_base__io_reader__set(wuffs_base__io_buffer* b,
uint8_t** ptr_iop_r,
+ uint8_t** ptr_io0_r,
uint8_t** ptr_io1_r,
+ uint8_t** ptr_io2_r,
wuffs_base__slice_u8 data) {
b->data = data;
b->meta.wi = data.len;
@@ -4488,42 +4628,17 @@
b->meta.pos = 0;
b->meta.closed = false;
- o->private_impl.buf = b;
- o->private_impl.mark = data.ptr;
- o->private_impl.limit = data.ptr + data.len;
*ptr_iop_r = data.ptr;
- *ptr_io1_r = data.ptr + data.len;
+ *ptr_io0_r = data.ptr;
+ *ptr_io1_r = data.ptr;
+ *ptr_io2_r = data.ptr + data.len;
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set_limit(wuffs_base__io_reader* o,
- uint8_t* iop_r,
- uint64_t limit) {
- if (o && (((size_t)(o->private_impl.limit - iop_r)) > limit)) {
- o->private_impl.limit = iop_r + limit;
- }
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_reader__set_mark(wuffs_base__io_reader* o, uint8_t* mark) {
- o->private_impl.mark = mark;
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
+ return b;
}
static inline wuffs_base__slice_u8 //
-wuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io1_r, uint64_t n) {
- if (n <= ((size_t)(io1_r - *ptr_iop_r))) {
+wuffs_base__io_reader__take(uint8_t** ptr_iop_r, uint8_t* io2_r, uint64_t n) {
+ if (n <= ((size_t)(io2_r - *ptr_iop_r))) {
uint8_t* p = *ptr_iop_r;
*ptr_iop_r += n;
return wuffs_base__make_slice_u8(p, n);
@@ -4531,11 +4646,12 @@
return wuffs_base__make_slice_u8(NULL, 0);
}
-static inline wuffs_base__empty_struct //
-wuffs_base__io_writer__set(wuffs_base__io_writer* o,
- wuffs_base__io_buffer* b,
+static inline wuffs_base__io_buffer* //
+wuffs_base__io_writer__set(wuffs_base__io_buffer* b,
uint8_t** ptr_iop_w,
+ uint8_t** ptr_io0_w,
uint8_t** ptr_io1_w,
+ uint8_t** ptr_io2_w,
wuffs_base__slice_u8 data) {
b->data = data;
b->meta.wi = 0;
@@ -4543,24 +4659,12 @@
b->meta.pos = 0;
b->meta.closed = false;
- o->private_impl.buf = b;
- o->private_impl.mark = data.ptr;
- o->private_impl.limit = data.ptr + data.len;
*ptr_iop_w = data.ptr;
- *ptr_io1_w = data.ptr + data.len;
+ *ptr_io0_w = data.ptr;
+ *ptr_io1_w = data.ptr;
+ *ptr_io2_w = data.ptr + data.len;
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
-}
-
-static inline wuffs_base__empty_struct //
-wuffs_base__io_writer__set_mark(wuffs_base__io_writer* o, uint8_t* mark) {
- o->private_impl.mark = mark;
-
- wuffs_base__empty_struct ret;
- ret.private_impl = 0;
- return ret;
+ return b;
}
// ---------------- I/O (Utility)
@@ -4618,8 +4722,10 @@
};
const char* wuffs_base__warning__end_of_data = "@base: end of data";
+const char* wuffs_base__warning__metadata_reported = "@base: metadata reported";
const char* wuffs_base__suspension__short_read = "$base: short read";
const char* wuffs_base__suspension__short_write = "$base: short write";
+const char* wuffs_base__error__bad_i_o_position = "#base: bad I/O position";
const char* wuffs_base__error__bad_argument_length_too_short =
"#base: bad argument (length too short)";
const char* wuffs_base__error__bad_argument = "#base: bad argument";
@@ -4641,6 +4747,7 @@
const char* wuffs_base__error__interleaved_coroutine_calls =
"#base: interleaved coroutine calls";
const char* wuffs_base__error__not_enough_data = "#base: not enough data";
+const char* wuffs_base__error__unsupported_option = "#base: unsupported option";
const char* wuffs_base__error__too_much_data = "#base: too much data";
// ---------------- Images
@@ -4658,6 +4765,61 @@
}
static uint64_t //
+wuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
+ if (dst_palette.len != 1024) {
+ return 0;
+ }
+ size_t dst_len3 = dst.len / 3;
+ size_t len = dst_len3 < src.len ? dst_len3 : src.len;
+ uint8_t* d = dst.ptr;
+ uint8_t* s = src.ptr;
+ size_t n = len;
+
+ // N is the loop unroll count.
+ const int N = 4;
+
+ // The comparison in the while condition is ">", not ">=", because with ">=",
+ // the last 4-byte store could write past the end of the dst slice.
+ //
+ // Each 4-byte store writes one too many bytes, but a subsequent store will
+ // overwrite that with the correct byte. There is always another store,
+ // whether a 4-byte store in this loop or a 1-byte store in the next loop.
+ while (n > N) {
+ wuffs_base__store_u32le(
+ d + (0 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));
+ wuffs_base__store_u32le(
+ d + (1 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));
+ wuffs_base__store_u32le(
+ d + (2 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));
+ wuffs_base__store_u32le(
+ d + (3 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));
+
+ s += 1 * N;
+ d += 3 * N;
+ n -= (size_t)(1 * N);
+ }
+
+ while (n >= 1) {
+ uint32_t color =
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));
+ d[0] = (uint8_t)(color >> 0);
+ d[1] = (uint8_t)(color >> 8);
+ d[2] = (uint8_t)(color >> 16);
+
+ s += 1 * 1;
+ d += 3 * 1;
+ n -= (size_t)(1 * 1);
+ }
+
+ return len;
+}
+static uint64_t //
wuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) {
@@ -4668,8 +4830,9 @@
size_t len = dst_len4 < src.len ? dst_len4 : src.len;
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
-
size_t n = len;
+
+ // N is the loop unroll count.
const int N = 4;
while (n >= N) {
@@ -4727,14 +4890,14 @@
return len4 * 4;
}
-void //
+wuffs_base__status //
wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
wuffs_base__pixel_format dst_format,
wuffs_base__slice_u8 dst_palette,
wuffs_base__pixel_format src_format,
wuffs_base__slice_u8 src_palette) {
if (!p) {
- return;
+ return wuffs_base__error__bad_receiver;
}
// TODO: support many more formats.
@@ -4754,6 +4917,13 @@
}
func = wuffs_base__pixel_swizzler__copy_1_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
+ 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
@@ -4763,6 +4933,13 @@
}
func = wuffs_base__pixel_swizzler__copy_4_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,
+ src_palette) != 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
@@ -4782,13 +4959,15 @@
}
p->private_impl.func = func;
+ return func ? NULL : wuffs_base__error__unsupported_option;
}
uint64_t //
-wuffs_base__pixel_swizzler__swizzle_packed(wuffs_base__pixel_swizzler* p,
- wuffs_base__slice_u8 dst,
- wuffs_base__slice_u8 dst_palette,
- wuffs_base__slice_u8 src) {
+wuffs_base__pixel_swizzler__swizzle_interleaved(
+ const wuffs_base__pixel_swizzler* p,
+ wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
if (p && p->private_impl.func) {
return (*(p->private_impl.func))(dst, dst_palette, src);
}
@@ -6091,20 +6270,20 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_blocks(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_deflate__decoder__decode_uncompressed(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_deflate__decoder__init_fixed_huffman(wuffs_deflate__decoder* self);
static wuffs_base__status //
wuffs_deflate__decoder__init_dynamic_huffman(wuffs_deflate__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_deflate__decoder__init_huff(wuffs_deflate__decoder* self,
@@ -6115,13 +6294,13 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_huffman_fast(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_deflate__decoder__decode_huffman_slow(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src);
// ---------------- Initializer Implementations
@@ -6196,8 +6375,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_deflate__decoder__decode_io_writer(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
if (!self) {
return wuffs_base__error__bad_receiver;
@@ -6207,6 +6386,10 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_dst || !a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
(self->private_impl.active_coroutine != 1)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
@@ -6215,6 +6398,7 @@
self->private_impl.active_coroutine = 0;
wuffs_base__status status = NULL;
+ uint64_t v_mark = 0;
wuffs_base__status v_status = NULL;
wuffs_base__slice_u8 v_written = {0};
uint64_t v_n_copied = 0;
@@ -6223,19 +6407,15 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint32_t coro_susp_point = self->private_impl.p_decode_io_writer[0];
@@ -6245,17 +6425,15 @@
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
while (true) {
- wuffs_base__io_writer__set_mark(&a_dst, iop_a_dst);
+ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
{
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
wuffs_base__status t_0 =
wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src);
- if (a_dst.private_impl.buf) {
- iop_a_dst = a_dst.private_impl.buf->data.ptr +
- a_dst.private_impl.buf->meta.wi;
+ if (a_dst) {
+ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
}
v_status = t_0;
}
@@ -6269,9 +6447,8 @@
}
goto ok;
}
- v_written = wuffs_base__make_slice_u8(
- a_dst.private_impl.mark,
- (size_t)(iop_a_dst - a_dst.private_impl.mark));
+ v_written = wuffs_base__io__since(
+ v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst);
if (((uint64_t)(v_written.len)) >= 32768) {
v_written = wuffs_base__slice_u8__suffix(v_written, 32768);
wuffs_base__slice_u8__copy_from_slice(
@@ -6313,14 +6490,15 @@
goto suspend;
suspend:
- self->private_impl.p_decode_io_writer[0] = coro_susp_point;
- self->private_impl.active_coroutine = 1;
+ self->private_impl.p_decode_io_writer[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 1 : 0;
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
if (wuffs_base__status__is_error(status)) {
@@ -6333,8 +6511,8 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_blocks(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint32_t v_final = 0;
@@ -6345,16 +6523,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_blocks[0];
@@ -6369,7 +6543,7 @@
while (self->private_impl.f_n_bits < 3) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6384,16 +6558,14 @@
self->private_impl.f_bits >>= 3;
self->private_impl.f_n_bits -= 3;
if (v_type == 0) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status =
wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -6412,15 +6584,13 @@
goto ok;
}
} else if (v_type == 2) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -6431,15 +6601,13 @@
}
self->private_impl.f_end_of_block = false;
while (true) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
v_status =
wuffs_deflate__decoder__decode_huffman_fast(self, a_dst, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (wuffs_base__status__is_error(v_status)) {
status = v_status;
@@ -6448,16 +6616,14 @@
if (self->private_impl.f_end_of_block) {
goto label_0_continue;
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
status =
wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -6476,14 +6642,14 @@
goto suspend;
suspend:
- self->private_impl.p_decode_blocks[0] = coro_susp_point;
+ self->private_impl.p_decode_blocks[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_blocks[0].v_final = v_final;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -6493,8 +6659,8 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_uncompressed(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint32_t v_length = 0;
@@ -6503,33 +6669,25 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_uncompressed[0];
@@ -6550,14 +6708,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
uint32_t t_0;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 4)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
t_0 = wuffs_base__load_u32le(iop_a_src);
iop_a_src += 4;
} else {
self->private_data.s_decode_uncompressed[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6584,13 +6742,13 @@
v_length = ((v_length)&0xFFFF);
while (true) {
v_n_copied = wuffs_base__io_writer__copy_n_from_reader(
- &iop_a_dst, io1_a_dst, v_length, &iop_a_src, io1_a_src);
+ &iop_a_dst, io2_a_dst, v_length, &iop_a_src, io2_a_src);
if (v_length <= v_n_copied) {
status = NULL;
goto ok;
}
v_length -= v_n_copied;
- if (((uint64_t)(io1_a_dst - iop_a_dst)) == 0) {
+ if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0) {
status = wuffs_base__suspension__short_write;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
} else {
@@ -6607,18 +6765,17 @@
goto suspend;
suspend:
- self->private_impl.p_decode_uncompressed[0] = coro_susp_point;
+ self->private_impl.p_decode_uncompressed[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_uncompressed[0].v_length = v_length;
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -6666,7 +6823,7 @@
static wuffs_base__status //
wuffs_deflate__decoder__init_dynamic_huffman(wuffs_deflate__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint32_t v_bits = 0;
@@ -6690,16 +6847,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_init_dynamic_huffman[0];
@@ -6725,7 +6878,7 @@
while (v_n_bits < 14) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6755,7 +6908,7 @@
while (v_n_bits < 3) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6794,7 +6947,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6843,7 +6996,7 @@
while (v_n_bits < v_n_extra_bits) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -6896,7 +7049,8 @@
goto suspend;
suspend:
- self->private_impl.p_init_dynamic_huffman[0] = coro_susp_point;
+ self->private_impl.p_init_dynamic_huffman[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_init_dynamic_huffman[0].v_bits = v_bits;
self->private_data.s_init_dynamic_huffman[0].v_n_bits = v_n_bits;
self->private_data.s_init_dynamic_huffman[0].v_n_lit = v_n_lit;
@@ -6911,9 +7065,8 @@
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -7178,8 +7331,8 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_huffman_fast(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint32_t v_bits = 0;
@@ -7199,33 +7352,25 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
if ((self->private_impl.f_n_bits >= 8) ||
@@ -7238,8 +7383,8 @@
v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
label_0_continue:;
- while ((((uint64_t)(io1_a_dst - iop_a_dst)) >= 258) &&
- (((uint64_t)(io1_a_src - iop_a_src)) >= 12)) {
+ while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 258) &&
+ (((uint64_t)(io2_a_src - iop_a_src)) >= 12)) {
if (v_n_bits < 15) {
v_bits |= (((uint32_t)(wuffs_base__load_u8be(iop_a_src))) << v_n_bits);
(iop_a_src += 1, wuffs_base__make_empty_struct());
@@ -7391,11 +7536,10 @@
v_n_copied = 0;
while (true) {
if (((uint64_t)((v_dist_minus_1 + 1))) >
- ((uint64_t)(iop_a_dst - a_dst.private_impl.mark))) {
+ ((uint64_t)(iop_a_dst - a_dst->data.ptr))) {
v_hlen = 0;
- v_hdist =
- ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) -
- ((uint64_t)(iop_a_dst - a_dst.private_impl.mark)))));
+ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) -
+ ((uint64_t)(iop_a_dst - a_dst->data.ptr)))));
if (v_length > v_hdist) {
v_length -= v_hdist;
v_hlen = v_hdist;
@@ -7410,7 +7554,7 @@
v_hdist = (self->private_impl.f_history_index - v_hdist);
while (true) {
v_n_copied = wuffs_base__io_writer__copy_n_from_slice(
- &iop_a_dst, io1_a_dst, v_hlen,
+ &iop_a_dst, io2_a_dst, v_hlen,
wuffs_base__slice_u8__subslice_i(
wuffs_base__make_slice_u8(self->private_data.f_history,
32768),
@@ -7420,7 +7564,7 @@
}
v_hlen -= v_n_copied;
wuffs_base__io_writer__copy_n_from_slice(
- &iop_a_dst, io1_a_dst, v_hlen,
+ &iop_a_dst, io2_a_dst, v_hlen,
wuffs_base__make_slice_u8(self->private_data.f_history, 32768));
goto label_1_break;
}
@@ -7429,13 +7573,13 @@
goto label_0_continue;
}
if (((uint64_t)((v_dist_minus_1 + 1))) >
- ((uint64_t)(iop_a_dst - a_dst.private_impl.mark))) {
+ ((uint64_t)(iop_a_dst - a_dst->data.ptr))) {
status = wuffs_deflate__error__internal_error_inconsistent_distance;
goto exit;
}
}
wuffs_base__io_writer__copy_n_from_history_fast(
- &iop_a_dst, a_dst.private_impl.mark, io1_a_dst, v_length,
+ &iop_a_dst, a_dst->data.ptr, io2_a_dst, v_length,
(v_dist_minus_1 + 1));
goto label_2_break;
}
@@ -7444,7 +7588,7 @@
label_0_break:;
while (v_n_bits >= 8) {
v_n_bits -= 8;
- if (iop_a_src > io0_a_src) {
+ if (iop_a_src > io1_a_src) {
(iop_a_src--, wuffs_base__make_empty_struct());
} else {
status = wuffs_deflate__error__internal_error_inconsistent_i_o;
@@ -7460,13 +7604,11 @@
}
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -7476,8 +7618,8 @@
static wuffs_base__status //
wuffs_deflate__decoder__decode_huffman_slow(wuffs_deflate__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint32_t v_bits = 0;
@@ -7503,33 +7645,25 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0];
@@ -7573,7 +7707,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7586,7 +7720,7 @@
label_1_break:;
if ((v_table_entry >> 31) != 0) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
- if (iop_a_dst == io1_a_dst) {
+ if (iop_a_dst == io2_a_dst) {
status = wuffs_base__suspension__short_write;
goto suspend;
}
@@ -7611,7 +7745,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7624,7 +7758,7 @@
label_2_break:;
if ((v_table_entry >> 31) != 0) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
- if (iop_a_dst == io1_a_dst) {
+ if (iop_a_dst == io2_a_dst) {
status = wuffs_base__suspension__short_write;
goto suspend;
}
@@ -7660,7 +7794,7 @@
while (v_n_bits < v_table_entry_n_bits) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7688,7 +7822,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7714,7 +7848,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7741,7 +7875,7 @@
while (v_n_bits < v_table_entry_n_bits) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -7760,10 +7894,9 @@
}
while (true) {
if (((uint64_t)((v_dist_minus_1 + 1))) >
- ((uint64_t)(iop_a_dst - a_dst.private_impl.mark))) {
- v_hdist =
- ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) -
- ((uint64_t)(iop_a_dst - a_dst.private_impl.mark)))));
+ ((uint64_t)(iop_a_dst - a_dst->data.ptr))) {
+ v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) -
+ ((uint64_t)(iop_a_dst - a_dst->data.ptr)))));
if (v_length > v_hdist) {
v_length -= v_hdist;
v_hlen = v_hdist;
@@ -7778,7 +7911,7 @@
v_hdist = (self->private_impl.f_history_index - v_hdist);
while (true) {
v_n_copied = wuffs_base__io_writer__copy_n_from_slice(
- &iop_a_dst, io1_a_dst, v_hlen,
+ &iop_a_dst, io2_a_dst, v_hlen,
wuffs_base__slice_u8__subslice_i(
wuffs_base__make_slice_u8(self->private_data.f_history,
32768),
@@ -7801,7 +7934,7 @@
if (v_hlen > 0) {
while (true) {
v_n_copied = wuffs_base__io_writer__copy_n_from_slice(
- &iop_a_dst, io1_a_dst, v_hlen,
+ &iop_a_dst, io2_a_dst, v_hlen,
wuffs_base__slice_u8__subslice_i(
wuffs_base__make_slice_u8(self->private_data.f_history,
32768),
@@ -7822,7 +7955,7 @@
}
}
v_n_copied = wuffs_base__io_writer__copy_n_from_history(
- &iop_a_dst, a_dst.private_impl.mark, io1_a_dst, v_length,
+ &iop_a_dst, a_dst->data.ptr, io2_a_dst, v_length,
(v_dist_minus_1 + 1));
if (v_length <= v_n_copied) {
v_length = 0;
@@ -7852,7 +7985,8 @@
goto suspend;
suspend:
- self->private_impl.p_decode_huffman_slow[0] = coro_susp_point;
+ self->private_impl.p_decode_huffman_slow[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_huffman_slow[0].v_bits = v_bits;
self->private_data.s_decode_huffman_slow[0].v_n_bits = v_n_bits;
self->private_data.s_decode_huffman_slow[0].v_table_entry = v_table_entry;
@@ -7869,13 +8003,11 @@
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -7900,11 +8032,11 @@
static wuffs_base__empty_struct //
wuffs_lzw__decoder__read_from(wuffs_lzw__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_lzw__decoder__write_to(wuffs_lzw__decoder* self,
- wuffs_base__io_writer a_dst);
+ wuffs_base__io_buffer* a_dst);
// ---------------- Initializer Implementations
@@ -7970,12 +8102,12 @@
if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
return wuffs_base__make_empty_struct();
}
- if (a_lw < 2 || a_lw > 8) {
+ if (a_lw > 8) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
return wuffs_base__make_empty_struct();
}
- self->private_impl.f_set_literal_width_arg = a_lw;
+ self->private_impl.f_set_literal_width_arg = (a_lw + 1);
return wuffs_base__make_empty_struct();
}
@@ -7998,8 +8130,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_lzw__decoder__decode_io_writer(wuffs_lzw__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
if (!self) {
return wuffs_base__error__bad_receiver;
@@ -8009,6 +8141,10 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_dst || !a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
(self->private_impl.active_coroutine != 1)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
@@ -8026,9 +8162,9 @@
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
self->private_impl.f_literal_width = 8;
- if (self->private_impl.f_set_literal_width_arg >= 2) {
+ if (self->private_impl.f_set_literal_width_arg > 0) {
self->private_impl.f_literal_width =
- self->private_impl.f_set_literal_width_arg;
+ (self->private_impl.f_set_literal_width_arg - 1);
}
self->private_impl.f_clear_code =
(((uint32_t)(1)) << self->private_impl.f_literal_width);
@@ -8081,8 +8217,10 @@
goto suspend;
suspend:
- self->private_impl.p_decode_io_writer[0] = coro_susp_point;
- self->private_impl.active_coroutine = 1;
+ self->private_impl.p_decode_io_writer[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 1 : 0;
goto exit;
exit:
@@ -8096,7 +8234,7 @@
static wuffs_base__empty_struct //
wuffs_lzw__decoder__read_from(wuffs_lzw__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
uint32_t v_clear_code = 0;
uint32_t v_end_code = 0;
uint32_t v_save_code = 0;
@@ -8116,16 +8254,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
v_clear_code = self->private_impl.f_clear_code;
@@ -8138,11 +8272,11 @@
v_output_wi = self->private_impl.f_output_wi;
while (true) {
if (v_n_bits < v_width) {
- if (((uint64_t)(io1_a_src - iop_a_src)) >= 4) {
+ if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
v_bits |= (wuffs_base__load_u32le(iop_a_src) << v_n_bits);
(iop_a_src += ((31 - v_n_bits) >> 3), wuffs_base__make_empty_struct());
v_n_bits |= 24;
- } else if (((uint64_t)(io1_a_src - iop_a_src)) <= 0) {
+ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
self->private_impl.f_read_from_return_value = 2;
goto label_0_break;
} else {
@@ -8150,7 +8284,7 @@
(iop_a_src += 1, wuffs_base__make_empty_struct());
v_n_bits += 8;
if (v_n_bits >= v_width) {
- } else if (((uint64_t)(io1_a_src - iop_a_src)) <= 0) {
+ } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
self->private_impl.f_read_from_return_value = 2;
goto label_0_break;
} else {
@@ -8265,7 +8399,7 @@
if (self->private_impl.f_read_from_return_value != 2) {
while (v_n_bits >= 8) {
v_n_bits -= 8;
- if (iop_a_src > io0_a_src) {
+ if (iop_a_src > io1_a_src) {
(iop_a_src--, wuffs_base__make_empty_struct());
} else {
self->private_impl.f_read_from_return_value = 4;
@@ -8280,9 +8414,8 @@
self->private_impl.f_bits = v_bits;
self->private_impl.f_n_bits = v_n_bits;
self->private_impl.f_output_wi = v_output_wi;
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return wuffs_base__make_empty_struct();
@@ -8292,7 +8425,7 @@
static wuffs_base__status //
wuffs_lzw__decoder__write_to(wuffs_lzw__decoder* self,
- wuffs_base__io_writer a_dst) {
+ wuffs_base__io_buffer* a_dst) {
wuffs_base__status status = NULL;
wuffs_base__slice_u8 v_s = {0};
@@ -8301,19 +8434,15 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint32_t coro_susp_point = self->private_impl.p_write_to[0];
@@ -8330,7 +8459,7 @@
v_s = wuffs_base__slice_u8__subslice_ij(
wuffs_base__make_slice_u8(self->private_data.f_output, 8199),
self->private_impl.f_output_ri, self->private_impl.f_output_wi);
- v_n = wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io1_a_dst, v_s);
+ v_n = wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst, v_s);
if (v_n == ((uint64_t)(v_s.len))) {
self->private_impl.f_output_ri = 0;
self->private_impl.f_output_wi = 0;
@@ -8352,13 +8481,13 @@
goto suspend;
suspend:
- self->private_impl.p_write_to[0] = coro_susp_point;
+ self->private_impl.p_write_to[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
return status;
@@ -8395,9 +8524,11 @@
const char* wuffs_gif__error__bad_block = "#gif: bad block";
const char* wuffs_gif__error__bad_extension_label = "#gif: bad extension label";
+const char* wuffs_gif__error__bad_frame_size = "#gif: bad frame size";
const char* wuffs_gif__error__bad_graphic_control = "#gif: bad graphic control";
const char* wuffs_gif__error__bad_header = "#gif: bad header";
const char* wuffs_gif__error__bad_literal_width = "#gif: bad literal width";
+const char* wuffs_gif__error__bad_palette = "#gif: bad palette";
const char* wuffs_gif__error__internal_error_inconsistent_ri_wi =
"#gif: internal error: inconsistent ri/wi";
@@ -8427,58 +8558,70 @@
78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48,
};
+static const uint8_t //
+ wuffs_gif__iccrgbg1012[11] //
+ WUFFS_BASE__POTENTIALLY_UNUSED = {
+ 73, 67, 67, 82, 71, 66, 71, 49, 48, 49, 50,
+};
+
+static const uint8_t //
+ wuffs_gif__xmpdataxmp[11] //
+ WUFFS_BASE__POTENTIALLY_UNUSED = {
+ 88, 77, 80, 32, 68, 97, 116, 97, 88, 77, 80,
+};
+
// ---------------- Private Initializer Prototypes
// ---------------- Private Function Prototypes
static wuffs_base__status //
wuffs_gif__decoder__skip_frame(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__empty_struct //
wuffs_gif__decoder__reset_gc(wuffs_gif__decoder* self);
static wuffs_base__status //
wuffs_gif__decoder__decode_up_to_id_part1(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_header(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_lsd(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_extension(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__skip_blocks(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_ae(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_gc(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part0(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part1(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src);
+ wuffs_base__io_buffer* a_src);
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part2(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf);
static wuffs_base__status //
@@ -8548,12 +8691,47 @@
// ---------------- Function Implementations
+// -------- func gif.decoder.set_quirk_enabled
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_gif__decoder__set_quirk_enabled(wuffs_gif__decoder* self,
+ uint32_t a_quirk,
+ bool a_enabled) {
+ if (!self) {
+ return wuffs_base__make_empty_struct();
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_empty_struct();
+ }
+
+ if (self->private_impl.f_call_sequence == 0) {
+ if (a_quirk == 1041635328) {
+ self->private_impl.f_quirk_enabled_delay_num_decoded_frames = a_enabled;
+ } else if (a_quirk == 1041635329) {
+ self->private_impl
+ .f_quirk_enabled_first_frame_local_palette_means_black_background =
+ a_enabled;
+ } else if (a_quirk == 1041635330) {
+ self->private_impl.f_quirk_enabled_honor_background_color = a_enabled;
+ } else if (a_quirk == 1041635331) {
+ self->private_impl.f_quirk_enabled_ignore_too_much_pixel_data = a_enabled;
+ } else if (a_quirk == 1041635332) {
+ self->private_impl.f_quirk_enabled_image_bounds_are_strict = a_enabled;
+ } else if (a_quirk == 1041635333) {
+ self->private_impl.f_quirk_enabled_reject_empty_frame = a_enabled;
+ } else if (a_quirk == 1041635334) {
+ self->private_impl.f_quirk_enabled_reject_empty_palette = a_enabled;
+ }
+ }
+ return wuffs_base__make_empty_struct();
+}
+
// -------- func gif.decoder.decode_image_config
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_image_config(wuffs_gif__decoder* self,
wuffs_base__image_config* a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
if (!self) {
return wuffs_base__error__bad_receiver;
}
@@ -8562,6 +8740,10 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
(self->private_impl.active_coroutine != 1)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
@@ -8578,38 +8760,47 @@
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
- if (self->private_impl.f_call_sequence >= 1) {
+ if (self->private_impl.f_call_sequence == 0) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
+ status = wuffs_gif__decoder__decode_header(self, a_src);
+ if (status) {
+ goto suspend;
+ }
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
+ status = wuffs_gif__decoder__decode_lsd(self, a_src);
+ if (status) {
+ goto suspend;
+ }
+ } else if (self->private_impl.f_call_sequence != 2) {
status = wuffs_base__error__bad_call_sequence;
goto exit;
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- status = wuffs_gif__decoder__decode_header(self, a_src);
- if (status) {
- goto suspend;
- }
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
- status = wuffs_gif__decoder__decode_lsd(self, a_src);
- if (status) {
- goto suspend;
- }
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
if (status) {
goto suspend;
}
- v_ffio =
- (!self->private_impl.f_gc_has_transparent_index &&
- (self->private_impl.f_frame_rect_x0 == 0) &&
- (self->private_impl.f_frame_rect_y0 == 0) &&
- (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) &&
- (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height));
+ v_ffio = !self->private_impl.f_gc_has_transparent_index;
+ if (!self->private_impl.f_quirk_enabled_honor_background_color) {
+ v_ffio =
+ (v_ffio && (self->private_impl.f_frame_rect_x0 == 0) &&
+ (self->private_impl.f_frame_rect_y0 == 0) &&
+ (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) &&
+ (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height));
+ } else if (v_ffio) {
+ self->private_impl.f_black_color_u32_argb_premul = 4278190080;
+ }
+ if (self->private_impl.f_background_color_u32_argb_premul == 77) {
+ self->private_impl.f_background_color_u32_argb_premul =
+ self->private_impl.f_black_color_u32_argb_premul;
+ }
if (a_dst != NULL) {
wuffs_base__image_config__set(
a_dst, 1191444488, 0, self->private_impl.f_width,
self->private_impl.f_height,
self->private_impl.f_frame_config_io_position, v_ffio);
}
- self->private_impl.f_call_sequence = 1;
+ self->private_impl.f_call_sequence = 3;
goto ok;
ok:
@@ -8619,8 +8810,10 @@
goto suspend;
suspend:
- self->private_impl.p_decode_image_config[0] = coro_susp_point;
- self->private_impl.active_coroutine = 1;
+ self->private_impl.p_decode_image_config[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 1 : 0;
goto exit;
exit:
@@ -8630,6 +8823,172 @@
return status;
}
+// -------- func gif.decoder.set_report_metadata
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct //
+wuffs_gif__decoder__set_report_metadata(wuffs_gif__decoder* self,
+ uint32_t a_fourcc,
+ bool a_report) {
+ if (!self) {
+ return wuffs_base__make_empty_struct();
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return wuffs_base__make_empty_struct();
+ }
+
+ if (a_fourcc == 1229144912) {
+ self->private_impl.f_report_metadata_iccp = a_report;
+ } else if (a_fourcc == 1481461792) {
+ self->private_impl.f_report_metadata_xmp = a_report;
+ }
+ return wuffs_base__make_empty_struct();
+}
+
+// -------- func gif.decoder.ack_metadata_chunk
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_gif__decoder__ack_metadata_chunk(wuffs_gif__decoder* self,
+ wuffs_base__io_buffer* a_src) {
+ if (!self) {
+ return wuffs_base__error__bad_receiver;
+ }
+ if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+ return (self->private_impl.magic == WUFFS_BASE__DISABLED)
+ ? wuffs_base__error__disabled_by_previous_error
+ : wuffs_base__error__initialize_not_called;
+ }
+ if (!a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
+ if ((self->private_impl.active_coroutine != 0) &&
+ (self->private_impl.active_coroutine != 2)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__interleaved_coroutine_calls;
+ }
+ self->private_impl.active_coroutine = 0;
+ wuffs_base__status status = NULL;
+
+ uint8_t* iop_a_src = NULL;
+ uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
+
+ uint32_t coro_susp_point = self->private_impl.p_ack_metadata_chunk[0];
+ if (coro_susp_point) {
+ }
+ switch (coro_susp_point) {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+ if (self->private_impl.f_call_sequence != 1) {
+ status = wuffs_base__error__bad_call_sequence;
+ goto exit;
+ }
+ if ((a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos, ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0) != self->private_impl.f_metadata_io_position) {
+ status = wuffs_base__error__bad_i_o_position;
+ goto exit;
+ }
+ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+ status = wuffs_base__suspension__short_read;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+ }
+ if (self->private_impl.f_metadata_fourcc_value == 1481461792) {
+ self->private_impl.f_metadata_chunk_length_value =
+ (((uint64_t)(wuffs_base__load_u8be(iop_a_src))) + 1);
+ if (self->private_impl.f_metadata_chunk_length_value > 1) {
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ }
+ } else {
+ self->private_impl.f_metadata_chunk_length_value =
+ ((uint64_t)(wuffs_base__load_u8be(iop_a_src)));
+ if (self->private_impl.f_metadata_chunk_length_value > 0) {
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ }
+ }
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ self->private_impl.f_call_sequence = 2;
+ self->private_impl.f_metadata_fourcc_value = 0;
+ self->private_impl.f_metadata_io_position = 0;
+ status = NULL;
+ goto ok;
+ goto ok;
+ ok:
+ self->private_impl.p_ack_metadata_chunk[0] = 0;
+ goto exit;
+ }
+
+ goto suspend;
+suspend:
+ self->private_impl.p_ack_metadata_chunk[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 2 : 0;
+
+ goto exit;
+exit:
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
+ if (wuffs_base__status__is_error(status)) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ }
+ return status;
+}
+
+// -------- func gif.decoder.metadata_fourcc
+
+WUFFS_BASE__MAYBE_STATIC uint32_t //
+wuffs_gif__decoder__metadata_fourcc(const wuffs_gif__decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ return self->private_impl.f_metadata_fourcc_value;
+}
+
+// -------- func gif.decoder.metadata_chunk_length
+
+WUFFS_BASE__MAYBE_STATIC uint64_t //
+wuffs_gif__decoder__metadata_chunk_length(const wuffs_gif__decoder* self) {
+ if (!self) {
+ return 0;
+ }
+ if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+ (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+ return 0;
+ }
+
+ return self->private_impl.f_metadata_chunk_length_value;
+}
+
// -------- func gif.decoder.num_animation_loops
WUFFS_BASE__MAYBE_STATIC uint32_t //
@@ -8732,6 +9091,7 @@
if (self->private_impl.f_call_sequence == 0) {
return wuffs_base__error__bad_call_sequence;
}
+ self->private_impl.f_delayed_num_decoded_frames = false;
self->private_impl.f_end_of_data = false;
self->private_impl.f_restarted = true;
self->private_impl.f_frame_config_io_position = a_io_position;
@@ -8746,7 +9106,7 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_frame_config(wuffs_gif__decoder* self,
wuffs_base__frame_config* a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
if (!self) {
return wuffs_base__error__bad_receiver;
}
@@ -8755,8 +9115,12 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
- (self->private_impl.active_coroutine != 2)) {
+ (self->private_impl.active_coroutine != 3)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
return wuffs_base__error__interleaved_coroutine_calls;
}
@@ -8764,32 +9128,67 @@
wuffs_base__status status = NULL;
uint8_t v_blend = 0;
+ uint32_t v_background_color = 0;
+ uint8_t v_flags = 0;
+
+ uint8_t* iop_a_src = NULL;
+ uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
+ }
uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
if (coro_susp_point) {
+ v_blend = self->private_data.s_decode_frame_config[0].v_blend;
+ v_background_color =
+ self->private_data.s_decode_frame_config[0].v_background_color;
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+ self->private_impl.f_ignore_metadata = true;
(memset(&self->private_impl.f_dirty_y, 0, sizeof(wuffs_base__range_ie_u32)),
wuffs_base__make_empty_struct());
if (!self->private_impl.f_end_of_data) {
if (self->private_impl.f_call_sequence == 0) {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
status = wuffs_gif__decoder__decode_image_config(self, NULL, a_src);
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
if (status) {
goto suspend;
}
- } else if (self->private_impl.f_call_sequence != 1) {
- if (self->private_impl.f_call_sequence == 2) {
+ } else if (self->private_impl.f_call_sequence != 3) {
+ if (self->private_impl.f_call_sequence == 4) {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status = wuffs_gif__decoder__skip_frame(self, a_src);
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
if (status) {
goto suspend;
}
}
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
if (status) {
goto suspend;
}
@@ -8800,8 +9199,23 @@
goto ok;
}
v_blend = 0;
+ v_background_color = self->private_impl.f_black_color_u32_argb_premul;
if (!self->private_impl.f_gc_has_transparent_index) {
v_blend = 2;
+ v_background_color =
+ self->private_impl.f_background_color_u32_argb_premul;
+ if (self->private_impl
+ .f_quirk_enabled_first_frame_local_palette_means_black_background &&
+ (self->private_impl.f_num_decoded_frame_configs_value == 0)) {
+ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+ status = wuffs_base__suspension__short_read;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+ }
+ v_flags = wuffs_base__load_u8be(iop_a_src);
+ if ((v_flags & 128) != 0) {
+ v_background_color = self->private_impl.f_black_color_u32_argb_premul;
+ }
+ }
}
if (a_dst != NULL) {
wuffs_base__frame_config__update(
@@ -8818,11 +9232,11 @@
((wuffs_base__flicks)(self->private_impl.f_gc_duration)),
self->private_impl.f_num_decoded_frame_configs_value,
self->private_impl.f_frame_config_io_position, v_blend,
- self->private_impl.f_gc_disposal);
+ self->private_impl.f_gc_disposal, v_background_color);
}
wuffs_base__u64__sat_add_indirect(
&self->private_impl.f_num_decoded_frame_configs_value, 1);
- self->private_impl.f_call_sequence = 2;
+ self->private_impl.f_call_sequence = 4;
goto ok;
ok:
@@ -8832,11 +9246,20 @@
goto suspend;
suspend:
- self->private_impl.p_decode_frame_config[0] = coro_susp_point;
- self->private_impl.active_coroutine = 2;
+ self->private_impl.p_decode_frame_config[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 3 : 0;
+ self->private_data.s_decode_frame_config[0].v_blend = v_blend;
+ self->private_data.s_decode_frame_config[0].v_background_color =
+ v_background_color;
goto exit;
exit:
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+
if (wuffs_base__status__is_error(status)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
}
@@ -8847,24 +9270,21 @@
static wuffs_base__status //
wuffs_gif__decoder__skip_frame(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_flags = 0;
+ uint8_t v_lw = 0;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
@@ -8875,7 +9295,7 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -8887,36 +9307,45 @@
(((uint32_t)(3)) << (1 + (v_flags & 7)));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (self->private_data.s_skip_frame[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_skip_frame[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
iop_a_src += self->private_data.s_skip_frame[0].scratch;
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
- status = wuffs_base__suspension__short_read;
- goto suspend;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ uint8_t t_1 = *iop_a_src++;
+ v_lw = t_1;
}
- iop_a_src++;
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (v_lw > 8) {
+ status = wuffs_gif__error__bad_literal_width;
+ goto exit;
+ }
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
status = wuffs_gif__decoder__skip_blocks(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
}
- wuffs_base__u64__sat_add_indirect(
- &self->private_impl.f_num_decoded_frames_value, 1);
+ if (self->private_impl.f_quirk_enabled_delay_num_decoded_frames) {
+ self->private_impl.f_delayed_num_decoded_frames = true;
+ } else {
+ wuffs_base__u64__sat_add_indirect(
+ &self->private_impl.f_num_decoded_frames_value, 1);
+ }
wuffs_gif__decoder__reset_gc(self);
goto ok;
@@ -8927,13 +9356,13 @@
goto suspend;
suspend:
- self->private_impl.p_skip_frame[0] = coro_susp_point;
+ self->private_impl.p_skip_frame[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -8944,7 +9373,7 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gif__decoder__decode_frame(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf,
wuffs_base__decode_frame_options* a_opts) {
if (!self) {
@@ -8955,12 +9384,12 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
- if (!a_dst) {
+ if (!a_dst || !a_src) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
return wuffs_base__error__bad_argument;
}
if ((self->private_impl.active_coroutine != 0) &&
- (self->private_impl.active_coroutine != 3)) {
+ (self->private_impl.active_coroutine != 4)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
return wuffs_base__error__interleaved_coroutine_calls;
}
@@ -8973,13 +9402,22 @@
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
- if (self->private_impl.f_call_sequence != 2) {
+ self->private_impl.f_ignore_metadata = true;
+ if (self->private_impl.f_call_sequence != 4) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
status = wuffs_gif__decoder__decode_frame_config(self, NULL, a_src);
if (status) {
goto suspend;
}
}
+ if (self->private_impl.f_quirk_enabled_reject_empty_frame &&
+ ((self->private_impl.f_frame_rect_x0 ==
+ self->private_impl.f_frame_rect_x1) ||
+ (self->private_impl.f_frame_rect_y0 ==
+ self->private_impl.f_frame_rect_y1))) {
+ status = wuffs_gif__error__bad_frame_size;
+ goto exit;
+ }
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status = wuffs_gif__decoder__decode_id_part1(self, a_dst, a_src);
if (status) {
@@ -9002,8 +9440,10 @@
goto suspend;
suspend:
- self->private_impl.p_decode_frame[0] = coro_susp_point;
- self->private_impl.active_coroutine = 3;
+ self->private_impl.p_decode_frame[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 4 : 0;
goto exit;
exit:
@@ -9017,8 +9457,7 @@
static wuffs_base__empty_struct //
wuffs_gif__decoder__reset_gc(wuffs_gif__decoder* self) {
- self->private_impl.f_call_sequence = 3;
- self->private_impl.f_seen_graphic_control = false;
+ self->private_impl.f_call_sequence = 5;
self->private_impl.f_gc_has_transparent_index = false;
self->private_impl.f_gc_transparent_index = 0;
self->private_impl.f_gc_disposal = 0;
@@ -9030,7 +9469,7 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_up_to_id_part1(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_block_type = 0;
@@ -9038,16 +9477,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0];
@@ -9057,19 +9492,18 @@
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
if (!self->private_impl.f_restarted) {
- self->private_impl.f_frame_config_io_position =
- (a_src.private_impl.buf
- ? wuffs_base__u64__sat_add(
- a_src.private_impl.buf->meta.pos,
- ((uint64_t)(iop_a_src - a_src.private_impl.buf->data.ptr)))
- : 0);
+ if (self->private_impl.f_call_sequence != 2) {
+ self->private_impl.f_frame_config_io_position =
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0);
+ }
} else if (self->private_impl.f_frame_config_io_position !=
- (a_src.private_impl.buf
- ? wuffs_base__u64__sat_add(
- a_src.private_impl.buf->meta.pos,
- ((uint64_t)(iop_a_src -
- a_src.private_impl.buf->data.ptr)))
- : 0)) {
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0)) {
status = wuffs_base__error__bad_restart;
goto exit;
} else {
@@ -9078,7 +9512,7 @@
while (true) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9086,35 +9520,41 @@
v_block_type = t_0;
}
if (v_block_type == 33) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status = wuffs_gif__decoder__decode_extension(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
}
} else if (v_block_type == 44) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (self->private_impl.f_delayed_num_decoded_frames) {
+ self->private_impl.f_delayed_num_decoded_frames = false;
+ wuffs_base__u64__sat_add_indirect(
+ &self->private_impl.f_num_decoded_frames_value, 1);
+ }
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_gif__decoder__decode_id_part0(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
}
goto label_0_break;
} else if (v_block_type == 59) {
+ if (self->private_impl.f_delayed_num_decoded_frames) {
+ self->private_impl.f_delayed_num_decoded_frames = false;
+ wuffs_base__u64__sat_add_indirect(
+ &self->private_impl.f_num_decoded_frames_value, 1);
+ }
self->private_impl.f_end_of_data = true;
goto label_0_break;
} else {
@@ -9132,13 +9572,13 @@
goto suspend;
suspend:
- self->private_impl.p_decode_up_to_id_part1[0] = coro_susp_point;
+ self->private_impl.p_decode_up_to_id_part1[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9148,7 +9588,7 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_header(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_c[6] = {0};
@@ -9157,16 +9597,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_header[0];
@@ -9180,7 +9616,7 @@
while (v_i < 6) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9203,15 +9639,15 @@
goto suspend;
suspend:
- self->private_impl.p_decode_header[0] = coro_susp_point;
+ self->private_impl.p_decode_header[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
memcpy(self->private_data.s_decode_header[0].v_c, v_c, sizeof(v_c));
self->private_data.s_decode_header[0].v_i = v_i;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9221,32 +9657,32 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_lsd(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_flags = 0;
+ uint8_t v_background_color_index = 0;
uint32_t v_num_palette_entries = 0;
uint32_t v_i = 0;
+ uint32_t v_j = 0;
uint32_t v_argb = 0;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_lsd[0];
if (coro_susp_point) {
v_flags = self->private_data.s_decode_lsd[0].v_flags;
+ v_background_color_index =
+ self->private_data.s_decode_lsd[0].v_background_color_index;
v_num_palette_entries =
self->private_data.s_decode_lsd[0].v_num_palette_entries;
v_i = self->private_data.s_decode_lsd[0].v_i;
@@ -9257,14 +9693,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
uint32_t t_0;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_0 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_lsd[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9286,14 +9722,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
uint32_t t_1;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_1 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_lsd[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9314,56 +9750,61 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
uint8_t t_2 = *iop_a_src++;
v_flags = t_2;
}
- self->private_data.s_decode_lsd[0].scratch = 2;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
- if (self->private_data.s_decode_lsd[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
- self->private_data.s_decode_lsd[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ uint8_t t_3 = *iop_a_src++;
+ v_background_color_index = t_3;
+ }
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
- iop_a_src += self->private_data.s_decode_lsd[0].scratch;
- if ((v_flags & 128) != 0) {
+ iop_a_src++;
+ v_i = 0;
+ self->private_impl.f_has_global_palette = ((v_flags & 128) != 0);
+ if (self->private_impl.f_has_global_palette) {
v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
- v_i = 0;
while (v_i < v_num_palette_entries) {
{
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
- uint32_t t_3;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 3)) {
- t_3 = ((uint32_t)(wuffs_base__load_u24be(iop_a_src)));
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+ uint32_t t_4;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
+ t_4 = ((uint32_t)(wuffs_base__load_u24be(iop_a_src)));
iop_a_src += 3;
} else {
self->private_data.s_decode_lsd[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
- uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
+ uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
*scratch >>= 8;
*scratch <<= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
- if (num_bits_3 == 16) {
- t_3 = ((uint32_t)(*scratch >> 40));
+ *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
+ if (num_bits_4 == 16) {
+ t_4 = ((uint32_t)(*scratch >> 40));
break;
}
- num_bits_3 += 8;
- *scratch |= ((uint64_t)(num_bits_3));
+ num_bits_4 += 8;
+ *scratch |= ((uint64_t)(num_bits_4));
}
}
- v_argb = t_3;
+ v_argb = t_4;
}
v_argb |= 4278190080;
self->private_data.f_palettes[0][((4 * v_i) + 0)] =
@@ -9376,14 +9817,31 @@
((uint8_t)(((v_argb >> 24) & 255)));
v_i += 1;
}
- while (v_i < 256) {
- self->private_data.f_palettes[0][((4 * v_i) + 0)] = 0;
- self->private_data.f_palettes[0][((4 * v_i) + 1)] = 0;
- self->private_data.f_palettes[0][((4 * v_i) + 2)] = 0;
- self->private_data.f_palettes[0][((4 * v_i) + 3)] = 255;
- v_i += 1;
+ if (self->private_impl.f_quirk_enabled_honor_background_color) {
+ if ((v_background_color_index != 0) &&
+ (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) {
+ v_j = (4 * ((uint32_t)(v_background_color_index)));
+ self->private_impl.f_background_color_u32_argb_premul =
+ ((((uint32_t)(self->private_data.f_palettes[0][(v_j + 0)]))
+ << 0) |
+ (((uint32_t)(self->private_data.f_palettes[0][(v_j + 1)]))
+ << 8) |
+ (((uint32_t)(self->private_data.f_palettes[0][(v_j + 2)]))
+ << 16) |
+ (((uint32_t)(self->private_data.f_palettes[0][(v_j + 3)]))
+ << 24));
+ } else {
+ self->private_impl.f_background_color_u32_argb_premul = 77;
+ }
}
}
+ while (v_i < 256) {
+ self->private_data.f_palettes[0][((4 * v_i) + 0)] = 0;
+ self->private_data.f_palettes[0][((4 * v_i) + 1)] = 0;
+ self->private_data.f_palettes[0][((4 * v_i) + 2)] = 0;
+ self->private_data.f_palettes[0][((4 * v_i) + 3)] = 255;
+ v_i += 1;
+ }
goto ok;
ok:
@@ -9393,17 +9851,19 @@
goto suspend;
suspend:
- self->private_impl.p_decode_lsd[0] = coro_susp_point;
+ self->private_impl.p_decode_lsd[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_lsd[0].v_flags = v_flags;
+ self->private_data.s_decode_lsd[0].v_background_color_index =
+ v_background_color_index;
self->private_data.s_decode_lsd[0].v_num_palette_entries =
v_num_palette_entries;
self->private_data.s_decode_lsd[0].v_i = v_i;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9413,7 +9873,7 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_extension(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_label = 0;
@@ -9421,16 +9881,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_extension[0];
@@ -9441,7 +9897,7 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9449,15 +9905,13 @@
v_label = t_0;
}
if (v_label == 249) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
status = wuffs_gif__decoder__decode_gc(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -9465,15 +9919,13 @@
status = NULL;
goto ok;
} else if (v_label == 255) {
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
status = wuffs_gif__decoder__decode_ae(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -9481,15 +9933,13 @@
status = NULL;
goto ok;
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
status = wuffs_gif__decoder__skip_blocks(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -9503,13 +9953,13 @@
goto suspend;
suspend:
- self->private_impl.p_decode_extension[0] = coro_susp_point;
+ self->private_impl.p_decode_extension[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9519,7 +9969,7 @@
static wuffs_base__status //
wuffs_gif__decoder__skip_blocks(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_block_size = 0;
@@ -9527,16 +9977,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0];
@@ -9548,7 +9994,7 @@
while (true) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9562,10 +10008,10 @@
self->private_data.s_skip_blocks[0].scratch = ((uint32_t)(v_block_size));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (self->private_data.s_skip_blocks[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_skip_blocks[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9580,13 +10026,13 @@
goto suspend;
suspend:
- self->private_impl.p_skip_blocks[0] = coro_susp_point;
+ self->private_impl.p_skip_blocks[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9596,34 +10042,34 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_ae(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_c = 0;
uint8_t v_block_size = 0;
- bool v_not_animexts = false;
- bool v_not_netscape = false;
+ bool v_is_animexts = false;
+ bool v_is_netscape = false;
+ bool v_is_iccp = false;
+ bool v_is_xmp = false;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_ae[0];
if (coro_susp_point) {
v_block_size = self->private_data.s_decode_ae[0].v_block_size;
- v_not_animexts = self->private_data.s_decode_ae[0].v_not_animexts;
- v_not_netscape = self->private_data.s_decode_ae[0].v_not_netscape;
+ v_is_animexts = self->private_data.s_decode_ae[0].v_is_animexts;
+ v_is_netscape = self->private_data.s_decode_ae[0].v_is_netscape;
+ v_is_iccp = self->private_data.s_decode_ae[0].v_is_iccp;
+ v_is_xmp = self->private_data.s_decode_ae[0].v_is_xmp;
}
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
@@ -9631,7 +10077,7 @@
while (true) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9646,33 +10092,38 @@
self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
if (self->private_data.s_decode_ae[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_ae[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
iop_a_src += self->private_data.s_decode_ae[0].scratch;
goto label_0_break;
}
- v_not_animexts = false;
- v_not_netscape = false;
+ v_is_animexts = true;
+ v_is_netscape = true;
+ v_is_iccp = true;
+ v_is_xmp = true;
v_block_size = 0;
while (v_block_size < 11) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
uint8_t t_1 = *iop_a_src++;
v_c = t_1;
}
- v_not_animexts =
- (v_not_animexts || (v_c != wuffs_gif__animexts1dot0[v_block_size]));
- v_not_netscape =
- (v_not_netscape || (v_c != wuffs_gif__netscape2dot0[v_block_size]));
+ v_is_animexts =
+ (v_is_animexts && (v_c == wuffs_gif__animexts1dot0[v_block_size]));
+ v_is_netscape =
+ (v_is_netscape && (v_c == wuffs_gif__netscape2dot0[v_block_size]));
+ v_is_iccp =
+ (v_is_iccp && (v_c == wuffs_gif__iccrgbg1012[v_block_size]));
+ v_is_xmp = (v_is_xmp && (v_c == wuffs_gif__xmpdataxmp[v_block_size]));
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
@@ -9682,101 +10133,135 @@
#pragma GCC diagnostic pop
#endif
}
- if (v_not_animexts && v_not_netscape) {
- goto label_0_break;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
- status = wuffs_base__suspension__short_read;
- goto suspend;
- }
- uint8_t t_2 = *iop_a_src++;
- v_block_size = t_2;
- }
- if (v_block_size != 3) {
- self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
- if (self->private_data.s_decode_ae[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
- self->private_data.s_decode_ae[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
- status = wuffs_base__suspension__short_read;
- goto suspend;
- }
- iop_a_src += self->private_data.s_decode_ae[0].scratch;
- goto label_0_break;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
- status = wuffs_base__suspension__short_read;
- goto suspend;
- }
- uint8_t t_3 = *iop_a_src++;
- v_c = t_3;
- }
- if (v_c != 1) {
- self->private_data.s_decode_ae[0].scratch = 2;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
- if (self->private_data.s_decode_ae[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
- self->private_data.s_decode_ae[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
- status = wuffs_base__suspension__short_read;
- goto suspend;
- }
- iop_a_src += self->private_data.s_decode_ae[0].scratch;
- goto label_0_break;
- }
- {
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
- uint32_t t_4;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
- t_4 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
- iop_a_src += 2;
- } else {
- self->private_data.s_decode_ae[0].scratch = 0;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
- while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
- status = wuffs_base__suspension__short_read;
- goto suspend;
- }
- uint64_t* scratch = &self->private_data.s_decode_ae[0].scratch;
- uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
- *scratch <<= 8;
- *scratch >>= 8;
- *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
- if (num_bits_4 == 8) {
- t_4 = ((uint32_t)(*scratch));
- break;
- }
- num_bits_4 += 8;
- *scratch |= ((uint64_t)(num_bits_4)) << 56;
+ if (v_is_animexts || v_is_netscape) {
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
}
+ uint8_t t_2 = *iop_a_src++;
+ v_block_size = t_2;
}
- self->private_impl.f_num_loops = t_4;
- }
- self->private_impl.f_seen_num_loops = true;
- if ((0 < self->private_impl.f_num_loops) &&
- (self->private_impl.f_num_loops <= 65535)) {
- self->private_impl.f_num_loops += 1;
+ if (v_block_size != 3) {
+ self->private_data.s_decode_ae[0].scratch =
+ ((uint32_t)(v_block_size));
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
+ if (self->private_data.s_decode_ae[0].scratch >
+ ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_decode_ae[0].scratch -=
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ iop_a_src += self->private_data.s_decode_ae[0].scratch;
+ goto label_0_break;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ uint8_t t_3 = *iop_a_src++;
+ v_c = t_3;
+ }
+ if (v_c != 1) {
+ self->private_data.s_decode_ae[0].scratch = 2;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
+ if (self->private_data.s_decode_ae[0].scratch >
+ ((uint64_t)(io2_a_src - iop_a_src))) {
+ self->private_data.s_decode_ae[0].scratch -=
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ iop_a_src += self->private_data.s_decode_ae[0].scratch;
+ goto label_0_break;
+ }
+ {
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+ uint32_t t_4;
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
+ t_4 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
+ iop_a_src += 2;
+ } else {
+ self->private_data.s_decode_ae[0].scratch = 0;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
+ while (true) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
+ status = wuffs_base__suspension__short_read;
+ goto suspend;
+ }
+ uint64_t* scratch = &self->private_data.s_decode_ae[0].scratch;
+ uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
+ *scratch <<= 8;
+ *scratch >>= 8;
+ *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
+ if (num_bits_4 == 8) {
+ t_4 = ((uint32_t)(*scratch));
+ break;
+ }
+ num_bits_4 += 8;
+ *scratch |= ((uint64_t)(num_bits_4)) << 56;
+ }
+ }
+ self->private_impl.f_num_loops = t_4;
+ }
+ self->private_impl.f_seen_num_loops = true;
+ if ((0 < self->private_impl.f_num_loops) &&
+ (self->private_impl.f_num_loops <= 65535)) {
+ self->private_impl.f_num_loops += 1;
+ }
+ } else if (self->private_impl.f_ignore_metadata) {
+ } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) {
+ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+ status = wuffs_base__suspension__short_read;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
+ }
+ self->private_impl.f_metadata_chunk_length_value =
+ ((uint64_t)(wuffs_base__load_u8be(iop_a_src)));
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ self->private_impl.f_metadata_fourcc_value = 1229144912;
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ self->private_impl.f_call_sequence = 1;
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) {
+ while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+ status = wuffs_base__suspension__short_read;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
+ }
+ self->private_impl.f_metadata_chunk_length_value =
+ (((uint64_t)(wuffs_base__load_u8be(iop_a_src))) + 1);
+ self->private_impl.f_metadata_fourcc_value = 1481461792;
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src ? wuffs_base__u64__sat_add(
+ a_src->meta.pos,
+ ((uint64_t)(iop_a_src - a_src->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ self->private_impl.f_call_sequence = 1;
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
}
goto label_0_break;
}
label_0_break:;
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
status = wuffs_gif__decoder__skip_blocks(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -9790,16 +10275,18 @@
goto suspend;
suspend:
- self->private_impl.p_decode_ae[0] = coro_susp_point;
+ self->private_impl.p_decode_ae[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_ae[0].v_block_size = v_block_size;
- self->private_data.s_decode_ae[0].v_not_animexts = v_not_animexts;
- self->private_data.s_decode_ae[0].v_not_netscape = v_not_netscape;
+ self->private_data.s_decode_ae[0].v_is_animexts = v_is_animexts;
+ self->private_data.s_decode_ae[0].v_is_netscape = v_is_netscape;
+ self->private_data.s_decode_ae[0].v_is_iccp = v_is_iccp;
+ self->private_data.s_decode_ae[0].v_is_xmp = v_is_xmp;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9809,7 +10296,7 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_gc(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_c = 0;
@@ -9819,16 +10306,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_gc[0];
@@ -9837,13 +10320,9 @@
switch (coro_susp_point) {
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
- if (self->private_impl.f_seen_graphic_control) {
- status = wuffs_gif__error__bad_graphic_control;
- goto exit;
- }
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9856,7 +10335,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9875,14 +10354,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
uint16_t t_2;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_2 = wuffs_base__load_u16le(iop_a_src);
iop_a_src += 2;
} else {
self->private_data.s_decode_gc[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9905,7 +10384,7 @@
(((uint64_t)(v_gc_duration_centiseconds)) * 7056000);
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9914,7 +10393,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -9925,7 +10404,6 @@
status = wuffs_gif__error__bad_graphic_control;
goto exit;
}
- self->private_impl.f_seen_graphic_control = true;
goto ok;
ok:
@@ -9935,13 +10413,13 @@
goto suspend;
suspend:
- self->private_impl.p_decode_gc[0] = coro_susp_point;
+ self->private_impl.p_decode_gc[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -9951,22 +10429,18 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part0(wuffs_gif__decoder* self,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0];
@@ -9978,14 +10452,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
uint32_t t_0;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_0 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_id_part0[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10007,14 +10481,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
uint32_t t_1;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_1 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_id_part0[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10036,14 +10510,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
uint32_t t_2;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_2 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_id_part0[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10066,14 +10540,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
uint32_t t_3;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_3 = ((uint32_t)(wuffs_base__load_u16le(iop_a_src)));
iop_a_src += 2;
} else {
self->private_data.s_decode_id_part0[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10095,7 +10569,8 @@
self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0;
self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0;
- if (self->private_impl.f_call_sequence == 0) {
+ if ((self->private_impl.f_call_sequence == 0) &&
+ !self->private_impl.f_quirk_enabled_image_bounds_are_strict) {
self->private_impl.f_width = wuffs_base__u32__max(
self->private_impl.f_width, self->private_impl.f_frame_rect_x1);
self->private_impl.f_height = wuffs_base__u32__max(
@@ -10110,13 +10585,13 @@
goto suspend;
suspend:
- self->private_impl.p_decode_id_part0[0] = coro_susp_point;
+ self->private_impl.p_decode_id_part0[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -10127,33 +10602,32 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part1(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src) {
+ wuffs_base__io_buffer* a_src) {
wuffs_base__status status = NULL;
uint8_t v_flags = 0;
+ uint8_t v_which_palette = 0;
uint32_t v_num_palette_entries = 0;
uint32_t v_i = 0;
uint32_t v_argb = 0;
wuffs_base__slice_u8 v_dst_palette = {0};
+ wuffs_base__status v_status = NULL;
uint8_t v_lw = 0;
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_id_part1[0];
if (coro_susp_point) {
+ v_which_palette = self->private_data.s_decode_id_part1[0].v_which_palette;
v_num_palette_entries =
self->private_data.s_decode_id_part1[0].v_num_palette_entries;
v_i = self->private_data.s_decode_id_part1[0].v_i;
@@ -10163,7 +10637,7 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10175,7 +10649,7 @@
} else {
self->private_impl.f_interlace = 0;
}
- self->private_impl.f_which_palette = 1;
+ v_which_palette = 1;
if ((v_flags & 128) != 0) {
v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
v_i = 0;
@@ -10183,14 +10657,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
uint32_t t_1;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 3)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
t_1 = ((uint32_t)(wuffs_base__load_u24be(iop_a_src)));
iop_a_src += 3;
} else {
self->private_data.s_decode_id_part1[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10228,12 +10702,16 @@
self->private_data.f_palettes[1][((4 * v_i) + 3)] = 255;
v_i += 1;
}
+ } else if (self->private_impl.f_quirk_enabled_reject_empty_palette &&
+ !self->private_impl.f_has_global_palette) {
+ status = wuffs_gif__error__bad_palette;
+ goto exit;
} else if (self->private_impl.f_gc_has_transparent_index) {
wuffs_base__slice_u8__copy_from_slice(
wuffs_base__make_slice_u8(self->private_data.f_palettes[1], 1024),
wuffs_base__make_slice_u8(self->private_data.f_palettes[0], 1024));
} else {
- self->private_impl.f_which_palette = 0;
+ v_which_palette = 0;
}
if (self->private_impl.f_gc_has_transparent_index) {
self->private_data.f_palettes[1][(
@@ -10254,13 +10732,22 @@
v_dst_palette =
wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024);
}
- wuffs_base__pixel_swizzler__prepare(
+ v_status = wuffs_base__pixel_swizzler__prepare(
&self->private_impl.f_swizzler,
wuffs_base__pixel_buffer__pixel_format(a_dst), v_dst_palette,
1191444488,
wuffs_base__make_slice_u8(
- self->private_data.f_palettes[self->private_impl.f_which_palette],
- 1024));
+ self->private_data.f_palettes[v_which_palette], 1024));
+ if (!wuffs_base__status__is_ok(v_status)) {
+ status = v_status;
+ if (wuffs_base__status__is_error(status)) {
+ goto exit;
+ } else if (wuffs_base__status__is_suspension(status)) {
+ status = wuffs_base__error__cannot_return_a_suspension;
+ goto exit;
+ }
+ goto ok;
+ }
if (self->private_impl.f_previous_lzw_decode_ended_abruptly) {
wuffs_base__ignore_status(wuffs_lzw__decoder__initialize(
&self->private_data.f_lzw, sizeof(wuffs_lzw__decoder), WUFFS_VERSION,
@@ -10268,14 +10755,14 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
uint8_t t_2 = *iop_a_src++;
v_lw = t_2;
}
- if ((v_lw < 2) || (8 < v_lw)) {
+ if (v_lw > 8) {
status = wuffs_gif__error__bad_literal_width;
goto exit;
}
@@ -10291,16 +10778,17 @@
goto suspend;
suspend:
- self->private_impl.p_decode_id_part1[0] = coro_susp_point;
+ self->private_impl.p_decode_id_part1[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_data.s_decode_id_part1[0].v_which_palette = v_which_palette;
self->private_data.s_decode_id_part1[0].v_num_palette_entries =
v_num_palette_entries;
self->private_data.s_decode_id_part1[0].v_i = v_i;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -10311,7 +10799,7 @@
static wuffs_base__status //
wuffs_gif__decoder__decode_id_part2(wuffs_gif__decoder* self,
wuffs_base__pixel_buffer* a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
wuffs_base__status status = NULL;
@@ -10319,11 +10807,13 @@
bool v_need_block_size = false;
uint64_t v_n_compressed = 0;
wuffs_base__slice_u8 v_compressed = {0};
- wuffs_base__io_reader v_r = wuffs_base__null_io_reader();
- wuffs_base__io_buffer u_r WUFFS_BASE__POTENTIALLY_UNUSED =
- wuffs_base__null_io_buffer();
+ wuffs_base__io_buffer u_r = wuffs_base__null_io_buffer();
+ wuffs_base__io_buffer* v_r = &u_r;
uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ uint64_t v_mark = 0;
wuffs_base__status v_lzw_status = NULL;
wuffs_base__status v_copy_status = NULL;
wuffs_base__slice_u8 v_uncompressed = {0};
@@ -10331,16 +10821,12 @@
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_id_part2[0];
@@ -10360,7 +10846,7 @@
v_need_block_size = false;
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10371,7 +10857,7 @@
if (v_block_size == 0) {
goto label_0_break;
}
- while (((uint64_t)(io1_a_src - iop_a_src)) == 0) {
+ while (((uint64_t)(io2_a_src - iop_a_src)) == 0) {
status = wuffs_base__suspension__short_read;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
}
@@ -10382,12 +10868,12 @@
}
while (self->private_impl.f_compressed_wi <= 3841) {
v_n_compressed = wuffs_base__u64__min(
- v_block_size, ((uint64_t)(io1_a_src - iop_a_src)));
+ v_block_size, ((uint64_t)(io2_a_src - iop_a_src)));
if (v_n_compressed <= 0) {
goto label_1_break;
}
v_compressed =
- wuffs_base__io_reader__take(&iop_a_src, io1_a_src, v_n_compressed);
+ wuffs_base__io_reader__take(&iop_a_src, io2_a_src, v_n_compressed);
wuffs_base__slice_u8__copy_from_slice(
wuffs_base__slice_u8__subslice_i(
wuffs_base__make_slice_u8(self->private_data.f_compressed,
@@ -10400,7 +10886,7 @@
if (v_block_size > 0) {
goto label_1_break;
}
- if (((uint64_t)(io1_a_src - iop_a_src)) <= 0) {
+ if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
v_need_block_size = true;
goto label_1_break;
}
@@ -10421,16 +10907,19 @@
goto exit;
}
{
- wuffs_base__io_reader o_0_v_r = v_r;
+ wuffs_base__io_buffer* o_0_v_r = v_r;
uint8_t* o_0_iop_v_r = iop_v_r;
+ uint8_t* o_0_io0_v_r = io0_v_r;
uint8_t* o_0_io1_v_r = io1_v_r;
- wuffs_base__io_reader__set(
- &v_r, &u_r, &iop_v_r, &io1_v_r,
+ uint8_t* o_0_io2_v_r = io2_v_r;
+ v_r = wuffs_base__io_reader__set(
+ &u_r, &iop_v_r, &io0_v_r, &io1_v_r, &io2_v_r,
wuffs_base__slice_u8__subslice_ij(
wuffs_base__make_slice_u8(self->private_data.f_compressed,
4096),
self->private_impl.f_compressed_ri,
self->private_impl.f_compressed_wi));
+ v_mark = ((uint64_t)(iop_v_r - io0_v_r));
{
u_r.meta.ri = ((size_t)(iop_v_r - u_r.data.ptr));
wuffs_base__status t_1 = wuffs_lzw__decoder__decode_io_writer(
@@ -10442,10 +10931,13 @@
}
wuffs_base__u64__sat_add_indirect(
&self->private_impl.f_compressed_ri,
- ((uint64_t)(iop_v_r - v_r.private_impl.mark)));
+ wuffs_base__io__count_since(v_mark,
+ ((uint64_t)(iop_v_r - io0_v_r))));
v_r = o_0_v_r;
iop_v_r = o_0_iop_v_r;
+ io0_v_r = o_0_io0_v_r;
io1_v_r = o_0_io1_v_r;
+ io2_v_r = o_0_io2_v_r;
}
v_uncompressed = wuffs_lzw__decoder__flush(&self->private_data.f_lzw);
if (((uint64_t)(v_uncompressed.len)) > 0) {
@@ -10463,23 +10955,21 @@
((uint32_t)(v_block_size));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
if (self->private_data.s_decode_id_part2[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_id_part2[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
iop_a_src += self->private_data.s_decode_id_part2[0].scratch;
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
status = wuffs_gif__decoder__skip_blocks(self, a_src);
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
if (status) {
goto suspend;
@@ -10521,16 +11011,16 @@
goto suspend;
suspend:
- self->private_impl.p_decode_id_part2[0] = coro_susp_point;
+ self->private_impl.p_decode_id_part2[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
self->private_data.s_decode_id_part2[0].v_block_size = v_block_size;
self->private_data.s_decode_id_part2[0].v_need_block_size = v_need_block_size;
self->private_data.s_decode_id_part2[0].v_lzw_status = v_lzw_status;
goto exit;
exit:
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
return status;
@@ -10547,23 +11037,29 @@
uint64_t v_n = 0;
uint64_t v_src_ri = 0;
uint32_t v_bytes_per_pixel = 0;
- uint32_t v_pixfmt = 0;
+ uint32_t v_pixfmt_channels = 0;
wuffs_base__table_u8 v_tab = {0};
uint64_t v_i = 0;
uint64_t v_j = 0;
- v_bytes_per_pixel = 1;
- v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb);
- if ((v_pixfmt == 1157662856) || (v_pixfmt == 1426098312) ||
- (v_pixfmt == 1174440072) || (v_pixfmt == 1442875528) ||
- (v_pixfmt == 1191217288) || (v_pixfmt == 1459652744)) {
+ v_pixfmt_channels = (wuffs_base__pixel_buffer__pixel_format(a_pb) & 65535);
+ if (v_pixfmt_channels == 34952) {
v_bytes_per_pixel = 4;
+ } else if (v_pixfmt_channels == 2184) {
+ v_bytes_per_pixel = 3;
+ } else if (v_pixfmt_channels == 8) {
+ v_bytes_per_pixel = 1;
+ } else {
+ return wuffs_base__error__unsupported_option;
}
v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0);
label_0_continue:;
while (v_src_ri < ((uint64_t)(a_src.len))) {
v_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_ri);
if (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) {
+ if (self->private_impl.f_quirk_enabled_ignore_too_much_pixel_data) {
+ return NULL;
+ }
return wuffs_base__error__too_much_data;
}
v_dst = wuffs_base__table_u8__row(v_tab, self->private_impl.f_dst_y);
@@ -10577,7 +11073,7 @@
} else {
v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i);
}
- v_n = wuffs_base__pixel_swizzler__swizzle_packed(
+ v_n = wuffs_base__pixel_swizzler__swizzle_interleaved(
&self->private_impl.f_swizzler, v_dst,
wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024),
v_src);
@@ -10778,8 +11274,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_gzip__decoder__decode_io_writer(wuffs_gzip__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
if (!self) {
return wuffs_base__error__bad_receiver;
@@ -10789,6 +11285,10 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_dst || !a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
(self->private_impl.active_coroutine != 1)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
@@ -10800,6 +11300,7 @@
uint8_t v_c = 0;
uint8_t v_flags = 0;
uint16_t v_xlen = 0;
+ uint64_t v_mark = 0;
uint32_t v_checksum_got = 0;
uint32_t v_decoded_length_got = 0;
wuffs_base__status v_status = NULL;
@@ -10809,33 +11310,25 @@
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_io_writer[0];
@@ -10851,7 +11344,7 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10864,7 +11357,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10877,7 +11370,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10890,7 +11383,7 @@
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10900,10 +11393,10 @@
self->private_data.s_decode_io_writer[0].scratch = 6;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
if (self->private_data.s_decode_io_writer[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_io_writer[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10912,14 +11405,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
uint16_t t_4;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_4 = wuffs_base__load_u16le(iop_a_src);
iop_a_src += 2;
} else {
self->private_data.s_decode_io_writer[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10942,10 +11435,10 @@
self->private_data.s_decode_io_writer[0].scratch = ((uint32_t)(v_xlen));
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
if (self->private_data.s_decode_io_writer[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_io_writer[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10955,7 +11448,7 @@
while (true) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10972,7 +11465,7 @@
while (true) {
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -10989,10 +11482,10 @@
self->private_data.s_decode_io_writer[0].scratch = 2;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
if (self->private_data.s_decode_io_writer[0].scratch >
- ((uint64_t)(io1_a_src - iop_a_src))) {
+ ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_decode_io_writer[0].scratch -=
- ((uint64_t)(io1_a_src - iop_a_src));
- iop_a_src = io1_a_src;
+ ((uint64_t)(io2_a_src - iop_a_src));
+ iop_a_src = io2_a_src;
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -11003,36 +11496,33 @@
goto exit;
}
while (true) {
- wuffs_base__io_writer__set_mark(&a_dst, iop_a_dst);
+ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
{
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
wuffs_base__status t_7 = wuffs_deflate__decoder__decode_io_writer(
&self->private_data.f_flate, a_dst, a_src, a_workbuf);
- if (a_dst.private_impl.buf) {
- iop_a_dst = a_dst.private_impl.buf->data.ptr +
- a_dst.private_impl.buf->meta.wi;
+ if (a_dst) {
+ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
}
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
v_status = t_7;
}
if (!self->private_impl.f_ignore_checksum) {
v_checksum_got = wuffs_crc32__ieee_hasher__update(
&self->private_data.f_checksum,
- wuffs_base__make_slice_u8(
- a_dst.private_impl.mark,
- (size_t)(iop_a_dst - a_dst.private_impl.mark)));
- v_decoded_length_got += ((uint32_t)(
- (((uint64_t)(iop_a_dst - a_dst.private_impl.mark)) & 4294967295)));
+ wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)),
+ io0_a_dst));
+ v_decoded_length_got +=
+ ((uint32_t)((wuffs_base__io__count_since(
+ v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))) &
+ 4294967295)));
}
if (wuffs_base__status__is_ok(v_status)) {
goto label_2_break;
@@ -11044,14 +11534,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
uint32_t t_8;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 4)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
t_8 = wuffs_base__load_u32le(iop_a_src);
iop_a_src += 4;
} else {
self->private_data.s_decode_io_writer[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -11073,14 +11563,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
uint32_t t_9;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 4)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
t_9 = wuffs_base__load_u32le(iop_a_src);
iop_a_src += 4;
} else {
self->private_data.s_decode_io_writer[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -11114,8 +11604,10 @@
goto suspend;
suspend:
- self->private_impl.p_decode_io_writer[0] = coro_susp_point;
- self->private_impl.active_coroutine = 1;
+ self->private_impl.p_decode_io_writer[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 1 : 0;
self->private_data.s_decode_io_writer[0].v_flags = v_flags;
self->private_data.s_decode_io_writer[0].v_checksum_got = v_checksum_got;
self->private_data.s_decode_io_writer[0].v_decoded_length_got =
@@ -11124,13 +11616,11 @@
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
if (wuffs_base__status__is_error(status)) {
@@ -11265,8 +11755,8 @@
WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
wuffs_zlib__decoder__decode_io_writer(wuffs_zlib__decoder* self,
- wuffs_base__io_writer a_dst,
- wuffs_base__io_reader a_src,
+ wuffs_base__io_buffer* a_dst,
+ wuffs_base__io_buffer* a_src,
wuffs_base__slice_u8 a_workbuf) {
if (!self) {
return wuffs_base__error__bad_receiver;
@@ -11276,6 +11766,10 @@
? wuffs_base__error__disabled_by_previous_error
: wuffs_base__error__initialize_not_called;
}
+ if (!a_dst || !a_src) {
+ self->private_impl.magic = WUFFS_BASE__DISABLED;
+ return wuffs_base__error__bad_argument;
+ }
if ((self->private_impl.active_coroutine != 0) &&
(self->private_impl.active_coroutine != 1)) {
self->private_impl.magic = WUFFS_BASE__DISABLED;
@@ -11288,37 +11782,30 @@
uint32_t v_checksum_got = 0;
wuffs_base__status v_status = NULL;
uint32_t v_checksum_want = 0;
+ uint64_t v_mark = 0;
uint8_t* iop_a_dst = NULL;
uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_dst.private_impl.buf) {
- iop_a_dst =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->meta.wi;
- if (!a_dst.private_impl.mark) {
- a_dst.private_impl.mark = iop_a_dst;
- a_dst.private_impl.limit =
- a_dst.private_impl.buf->data.ptr + a_dst.private_impl.buf->data.len;
+ uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_dst) {
+ io0_a_dst = a_dst->data.ptr;
+ io1_a_dst = io0_a_dst + a_dst->meta.wi;
+ iop_a_dst = io1_a_dst;
+ io2_a_dst = io0_a_dst + a_dst->data.len;
+ if (a_dst->meta.closed) {
+ io2_a_dst = iop_a_dst;
}
- if (a_dst.private_impl.buf->meta.closed) {
- a_dst.private_impl.limit = iop_a_dst;
- }
- io0_a_dst = a_dst.private_impl.mark;
- io1_a_dst = a_dst.private_impl.limit;
}
uint8_t* iop_a_src = NULL;
uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
- if (a_src.private_impl.buf) {
- iop_a_src =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.ri;
- if (!a_src.private_impl.mark) {
- a_src.private_impl.mark = iop_a_src;
- a_src.private_impl.limit =
- a_src.private_impl.buf->data.ptr + a_src.private_impl.buf->meta.wi;
- }
- io0_a_src = a_src.private_impl.mark;
- io1_a_src = a_src.private_impl.limit;
+ uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+ if (a_src) {
+ io0_a_src = a_src->data.ptr;
+ io1_a_src = io0_a_src + a_src->meta.ri;
+ iop_a_src = io1_a_src;
+ io2_a_src = io0_a_src + a_src->meta.wi;
}
uint32_t coro_susp_point = self->private_impl.p_decode_io_writer[0];
@@ -11331,14 +11818,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
uint16_t t_0;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 2)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
t_0 = wuffs_base__load_u16be(iop_a_src);
iop_a_src += 2;
} else {
self->private_data.s_decode_io_writer[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -11374,34 +11861,29 @@
goto exit;
}
while (true) {
- wuffs_base__io_writer__set_mark(&a_dst, iop_a_dst);
+ v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
{
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
wuffs_base__status t_1 = wuffs_deflate__decoder__decode_io_writer(
&self->private_data.f_flate, a_dst, a_src, a_workbuf);
- if (a_dst.private_impl.buf) {
- iop_a_dst = a_dst.private_impl.buf->data.ptr +
- a_dst.private_impl.buf->meta.wi;
+ if (a_dst) {
+ iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
}
- if (a_src.private_impl.buf) {
- iop_a_src = a_src.private_impl.buf->data.ptr +
- a_src.private_impl.buf->meta.ri;
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
}
v_status = t_1;
}
if (!self->private_impl.f_ignore_checksum) {
v_checksum_got = wuffs_adler32__hasher__update(
&self->private_data.f_checksum,
- wuffs_base__make_slice_u8(
- a_dst.private_impl.mark,
- (size_t)(iop_a_dst - a_dst.private_impl.mark)));
+ wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)),
+ io0_a_dst));
}
if (wuffs_base__status__is_ok(v_status)) {
goto label_0_break;
@@ -11413,14 +11895,14 @@
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
uint32_t t_2;
- if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 4)) {
+ if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
t_2 = wuffs_base__load_u32be(iop_a_src);
iop_a_src += 4;
} else {
self->private_data.s_decode_io_writer[0].scratch = 0;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
while (true) {
- if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+ if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
status = wuffs_base__suspension__short_read;
goto suspend;
}
@@ -11453,19 +11935,19 @@
goto suspend;
suspend:
- self->private_impl.p_decode_io_writer[0] = coro_susp_point;
- self->private_impl.active_coroutine = 1;
+ self->private_impl.p_decode_io_writer[0] =
+ wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
+ self->private_impl.active_coroutine =
+ wuffs_base__status__is_suspension(status) ? 1 : 0;
self->private_data.s_decode_io_writer[0].v_checksum_got = v_checksum_got;
goto exit;
exit:
- if (a_dst.private_impl.buf) {
- a_dst.private_impl.buf->meta.wi =
- ((size_t)(iop_a_dst - a_dst.private_impl.buf->data.ptr));
+ if (a_dst) {
+ a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
}
- if (a_src.private_impl.buf) {
- a_src.private_impl.buf->meta.ri =
- ((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
if (wuffs_base__status__is_error(status)) {
diff --git a/release/c/wuffs-v0.2.c b/release/c/wuffs-v0.2.c
index 8ea6abd..2a0215b 100644
--- a/release/c/wuffs-v0.2.c
+++ b/release/c/wuffs-v0.2.c
@@ -60,15 +60,15 @@
// each major.minor branch, the commit count should increase monotonically.
//
// WUFFS_VERSION was overridden by "wuffs gen -version" based on revision
-// 6b9f658c593bb57851e3fac7df2e5f3949a4fac8 committed on 2019-04-07.
+// 3037f1e389b54f9721161cc92c9b00372254cafc committed on 2019-07-07.
#define WUFFS_VERSION ((uint64_t)0x0000000000020000)
#define WUFFS_VERSION_MAJOR ((uint64_t)0x00000000)
#define WUFFS_VERSION_MINOR ((uint64_t)0x0002)
#define WUFFS_VERSION_PATCH ((uint64_t)0x0000)
-#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.36"
-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 1675
-#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20190407
-#define WUFFS_VERSION_STRING "0.2.0-alpha.36+1675.20190407"
+#define WUFFS_VERSION_PRE_RELEASE_LABEL "alpha.44"
+#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 1776
+#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20190707
+#define WUFFS_VERSION_STRING "0.2.0-alpha.44+1776.20190707"
// Define WUFFS_CONFIG__STATIC_FUNCTIONS to make all of Wuffs' functions have
// static storage. The motivation is discussed in the "ALLOW STATIC
@@ -192,8 +192,10 @@
typedef const char* wuffs_base__status;
extern const char* wuffs_base__warning__end_of_data;
+extern const char* wuffs_base__warning__metadata_reported;
extern const char* wuffs_base__suspension__short_read;
extern const char* wuffs_base__suspension__short_write;
+extern const char* wuffs_base__error__bad_i_o_position;
extern const char* wuffs_base__error__bad_argument_length_too_short;
extern const char* wuffs_base__error__bad_argument;
extern const char* wuffs_base__error__bad_call_sequence;
@@ -208,6 +210,7 @@
extern const char* wuffs_base__error__initialize_not_called;
extern const char* wuffs_base__error__interleaved_coroutine_calls;
extern const char* wuffs_base__error__not_enough_data;
+extern const char* wuffs_base__error__unsupported_option;
extern const char* wuffs_base__error__too_much_data;
static inline bool //
@@ -237,6 +240,16 @@
// --------
+// FourCC constants.
+
+// International Color Consortium Profile.
+#define WUFFS_BASE__FOURCC__ICCP 0x49434350
+
+// Extensible Metadata Platform.
+#define WUFFS_BASE__FOURCC__XMP 0x584D5020
+
+// --------
+
// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
// second. See https://github.com/OculusVR/Flicks
typedef int64_t wuffs_base__flicks;
@@ -510,14 +523,14 @@
uint32_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct intersect(
- wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
inline wuffs_base__range_ii_u32__struct unite(
- wuffs_base__range_ii_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ii_u32__struct s);
+ wuffs_base__range_ii_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u32;
@@ -531,12 +544,12 @@
}
static inline bool //
-wuffs_base__range_ii_u32__is_empty(wuffs_base__range_ii_u32* r) {
+wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u32__equals(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u32__is_empty(r) &&
@@ -544,7 +557,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__intersect(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
wuffs_base__range_ii_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -553,7 +566,7 @@
}
static inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32__unite(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
if (wuffs_base__range_ii_u32__is_empty(r)) {
return s;
@@ -568,12 +581,13 @@
}
static inline bool //
-wuffs_base__range_ii_u32__contains(wuffs_base__range_ii_u32* r, uint32_t x) {
+wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u32__contains_range(wuffs_base__range_ii_u32* r,
+wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
wuffs_base__range_ii_u32 s) {
return wuffs_base__range_ii_u32__equals(
&s, wuffs_base__range_ii_u32__intersect(r, s));
@@ -582,32 +596,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u32::is_empty() {
+wuffs_base__range_ii_u32::is_empty() const {
return wuffs_base__range_ii_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__equals(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__intersect(this, s);
}
inline wuffs_base__range_ii_u32 //
-wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u32::contains(uint32_t x) {
+wuffs_base__range_ii_u32::contains(uint32_t x) const {
return wuffs_base__range_ii_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) {
+wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
return wuffs_base__range_ii_u32__contains_range(this, s);
}
@@ -620,15 +634,15 @@
uint32_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct intersect(
- wuffs_base__range_ie_u32__struct s);
+ wuffs_base__range_ie_u32__struct s) const;
inline wuffs_base__range_ie_u32__struct unite(
- wuffs_base__range_ie_u32__struct s);
- inline bool contains(uint32_t x);
- inline bool contains_range(wuffs_base__range_ie_u32__struct s);
- inline uint32_t length();
+ wuffs_base__range_ie_u32__struct s) const;
+ inline bool contains(uint32_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
+ inline uint32_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u32;
@@ -642,12 +656,12 @@
}
static inline bool //
-wuffs_base__range_ie_u32__is_empty(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u32__equals(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u32__is_empty(r) &&
@@ -655,7 +669,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__intersect(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
wuffs_base__range_ie_u32 t;
t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
@@ -664,7 +678,7 @@
}
static inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32__unite(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
if (wuffs_base__range_ie_u32__is_empty(r)) {
return s;
@@ -679,56 +693,57 @@
}
static inline bool //
-wuffs_base__range_ie_u32__contains(wuffs_base__range_ie_u32* r, uint32_t x) {
+wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
+ uint32_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u32__contains_range(wuffs_base__range_ie_u32* r,
+wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
wuffs_base__range_ie_u32 s) {
return wuffs_base__range_ie_u32__equals(
&s, wuffs_base__range_ie_u32__intersect(r, s));
}
static inline uint32_t //
-wuffs_base__range_ie_u32__length(wuffs_base__range_ie_u32* r) {
+wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u32::is_empty() {
+wuffs_base__range_ie_u32::is_empty() const {
return wuffs_base__range_ie_u32__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__equals(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__intersect(this, s);
}
inline wuffs_base__range_ie_u32 //
-wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u32::contains(uint32_t x) {
+wuffs_base__range_ie_u32::contains(uint32_t x) const {
return wuffs_base__range_ie_u32__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) {
+wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
return wuffs_base__range_ie_u32__contains_range(this, s);
}
inline uint32_t //
-wuffs_base__range_ie_u32::length() {
+wuffs_base__range_ie_u32::length() const {
return wuffs_base__range_ie_u32__length(this);
}
@@ -741,14 +756,14 @@
uint64_t max_incl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ii_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct intersect(
- wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
inline wuffs_base__range_ii_u64__struct unite(
- wuffs_base__range_ii_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ii_u64__struct s);
+ wuffs_base__range_ii_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
#endif // __cplusplus
} wuffs_base__range_ii_u64;
@@ -762,12 +777,12 @@
}
static inline bool //
-wuffs_base__range_ii_u64__is_empty(wuffs_base__range_ii_u64* r) {
+wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
return r->min_incl > r->max_incl;
}
static inline bool //
-wuffs_base__range_ii_u64__equals(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
(wuffs_base__range_ii_u64__is_empty(r) &&
@@ -775,7 +790,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__intersect(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
wuffs_base__range_ii_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -784,7 +799,7 @@
}
static inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64__unite(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
if (wuffs_base__range_ii_u64__is_empty(r)) {
return s;
@@ -799,12 +814,13 @@
}
static inline bool //
-wuffs_base__range_ii_u64__contains(wuffs_base__range_ii_u64* r, uint64_t x) {
+wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x <= r->max_incl);
}
static inline bool //
-wuffs_base__range_ii_u64__contains_range(wuffs_base__range_ii_u64* r,
+wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
wuffs_base__range_ii_u64 s) {
return wuffs_base__range_ii_u64__equals(
&s, wuffs_base__range_ii_u64__intersect(r, s));
@@ -813,32 +829,32 @@
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ii_u64::is_empty() {
+wuffs_base__range_ii_u64::is_empty() const {
return wuffs_base__range_ii_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__equals(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__intersect(this, s);
}
inline wuffs_base__range_ii_u64 //
-wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ii_u64::contains(uint64_t x) {
+wuffs_base__range_ii_u64::contains(uint64_t x) const {
return wuffs_base__range_ii_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) {
+wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
return wuffs_base__range_ii_u64__contains_range(this, s);
}
@@ -851,15 +867,15 @@
uint64_t max_excl;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__range_ie_u64__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct intersect(
- wuffs_base__range_ie_u64__struct s);
+ wuffs_base__range_ie_u64__struct s) const;
inline wuffs_base__range_ie_u64__struct unite(
- wuffs_base__range_ie_u64__struct s);
- inline bool contains(uint64_t x);
- inline bool contains_range(wuffs_base__range_ie_u64__struct s);
- inline uint64_t length();
+ wuffs_base__range_ie_u64__struct s) const;
+ inline bool contains(uint64_t x) const;
+ inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
+ inline uint64_t length() const;
#endif // __cplusplus
} wuffs_base__range_ie_u64;
@@ -873,12 +889,12 @@
}
static inline bool //
-wuffs_base__range_ie_u64__is_empty(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
return r->min_incl >= r->max_excl;
}
static inline bool //
-wuffs_base__range_ie_u64__equals(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
(wuffs_base__range_ie_u64__is_empty(r) &&
@@ -886,7 +902,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__intersect(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
wuffs_base__range_ie_u64 t;
t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
@@ -895,7 +911,7 @@
}
static inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64__unite(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
if (wuffs_base__range_ie_u64__is_empty(r)) {
return s;
@@ -910,56 +926,57 @@
}
static inline bool //
-wuffs_base__range_ie_u64__contains(wuffs_base__range_ie_u64* r, uint64_t x) {
+wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
+ uint64_t x) {
return (r->min_incl <= x) && (x < r->max_excl);
}
static inline bool //
-wuffs_base__range_ie_u64__contains_range(wuffs_base__range_ie_u64* r,
+wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
wuffs_base__range_ie_u64 s) {
return wuffs_base__range_ie_u64__equals(
&s, wuffs_base__range_ie_u64__intersect(r, s));
}
static inline uint64_t //
-wuffs_base__range_ie_u64__length(wuffs_base__range_ie_u64* r) {
+wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
}
#ifdef __cplusplus
inline bool //
-wuffs_base__range_ie_u64::is_empty() {
+wuffs_base__range_ie_u64::is_empty() const {
return wuffs_base__range_ie_u64__is_empty(this);
}
inline bool //
-wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__equals(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__intersect(this, s);
}
inline wuffs_base__range_ie_u64 //
-wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__unite(this, s);
}
inline bool //
-wuffs_base__range_ie_u64::contains(uint64_t x) {
+wuffs_base__range_ie_u64::contains(uint64_t x) const {
return wuffs_base__range_ie_u64__contains(this, x);
}
inline bool //
-wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) {
+wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
return wuffs_base__range_ie_u64__contains_range(this, s);
}
inline uint64_t //
-wuffs_base__range_ie_u64::length() {
+wuffs_base__range_ie_u64::length() const {
return wuffs_base__range_ie_u64__length(this);
}
@@ -983,14 +1000,14 @@
uint32_t max_incl_y;
#ifdef __cplusplus
- inline bool is_empty();
- inline bool equals(wuffs_base__rect_ii_u32__struct s);
+ inline bool is_empty() const;
+ inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct intersect(
- wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
inline wuffs_base__rect_ii_u32__struct unite(
- wuffs_base__rect_ii_u32__struct s);
- inline bool contains(uint32_t x, uint32_t y);
- inline bool contains_rect(wuffs_base__rect_ii_u32__struct s);
+ wuffs_base__rect_ii_u32__struct s) const;
+ inline bool contains(uint32_t x, uint32_t y) const;
+ inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
#endif // __cplusplus
} wuffs_base__rect_ii_u32;
@@ -1009,12 +1026,12 @@
}
static inline bool //
-wuffs_base__rect_ii_u32__is_empty(wuffs_base__rect_ii_u32* r) {
+wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {