Merge pull request #118779 from Chubercik/tinyexr-1.0.13
tinyexr: Update to 1.0.13
This commit is contained in:
Vendored
+4
-1
@@ -1100,12 +1100,15 @@ Patches:
|
||||
## tinyexr
|
||||
|
||||
- Upstream: https://github.com/syoyo/tinyexr
|
||||
- Version: 1.0.12 (735ff73ce5959cf005eb99ce517c9bcecab89dfb, 2025)
|
||||
- Version: 1.0.13 (4946b5d92e13bcc8102ac2c8efd129596a90bf75, 2026)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `exr_reader.hh`
|
||||
- `streamreader.hh`
|
||||
- `tinyexr.{cc,h}`
|
||||
- `LICENSE`
|
||||
|
||||
Patches:
|
||||
|
||||
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Vendored
+191
@@ -0,0 +1,191 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2025, Syoyo Fujita and many contributors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// EXR Reader: Reader class with error stack for safe memory reading
|
||||
|
||||
#ifndef TINYEXR_EXR_READER_HH_
|
||||
#define TINYEXR_EXR_READER_HH_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "streamreader.hh"
|
||||
|
||||
namespace tinyexr {
|
||||
|
||||
// Reader class that wraps StreamReader and accumulates errors
|
||||
class Reader {
|
||||
public:
|
||||
Reader(const uint8_t* data, size_t length, Endian endian = Endian::Little)
|
||||
: stream_(data, length, endian), has_error_(false) {}
|
||||
|
||||
// Check if any errors have occurred
|
||||
bool has_error() const { return has_error_; }
|
||||
|
||||
// Get all accumulated errors
|
||||
const std::vector<std::string>& errors() const { return errors_; }
|
||||
|
||||
// Get the most recent error
|
||||
std::string last_error() const {
|
||||
return errors_.empty() ? "" : errors_.back();
|
||||
}
|
||||
|
||||
// Get all errors as a single string
|
||||
std::string all_errors() const {
|
||||
std::string result;
|
||||
for (size_t i = 0; i < errors_.size(); i++) {
|
||||
if (i > 0) result += "\n";
|
||||
result += errors_[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clear error stack
|
||||
void clear_errors() {
|
||||
errors_.clear();
|
||||
has_error_ = false;
|
||||
}
|
||||
|
||||
// Read n bytes into destination buffer
|
||||
bool read(size_t n, uint8_t* dst) {
|
||||
if (!stream_.read(n, dst)) {
|
||||
add_error("Failed to read " + std::to_string(n) + " bytes at position " +
|
||||
std::to_string(stream_.tell()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 1 byte
|
||||
bool read1(uint8_t* dst) {
|
||||
if (!stream_.read1(dst)) {
|
||||
add_error("Failed to read 1 byte at position " +
|
||||
std::to_string(stream_.tell()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 2 bytes with endian swap
|
||||
bool read2(uint16_t* dst) {
|
||||
if (!stream_.read2(dst)) {
|
||||
add_error("Failed to read 2 bytes at position " +
|
||||
std::to_string(stream_.tell()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 4 bytes with endian swap
|
||||
bool read4(uint32_t* dst) {
|
||||
if (!stream_.read4(dst)) {
|
||||
add_error("Failed to read 4 bytes at position " +
|
||||
std::to_string(stream_.tell()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 8 bytes with endian swap
|
||||
bool read8(uint64_t* dst) {
|
||||
if (!stream_.read8(dst)) {
|
||||
add_error("Failed to read 8 bytes at position " +
|
||||
std::to_string(stream_.tell()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read a null-terminated string up to max_len bytes
|
||||
// Returns false if no null terminator found within max_len
|
||||
bool read_string(std::string* str, size_t max_len = 256) {
|
||||
if (!str) {
|
||||
add_error("Null pointer passed to read_string");
|
||||
return false;
|
||||
}
|
||||
|
||||
str->clear();
|
||||
size_t start_pos = stream_.tell();
|
||||
|
||||
for (size_t i = 0; i < max_len; i++) {
|
||||
uint8_t c;
|
||||
if (!stream_.read1(&c)) {
|
||||
add_error("Failed to read string at position " + std::to_string(start_pos));
|
||||
return false;
|
||||
}
|
||||
if (c == '\0') {
|
||||
return true;
|
||||
}
|
||||
str->push_back(static_cast<char>(c));
|
||||
}
|
||||
|
||||
add_error("String not null-terminated within " + std::to_string(max_len) +
|
||||
" bytes at position " + std::to_string(start_pos));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Seek to absolute position
|
||||
bool seek(size_t pos) {
|
||||
if (!stream_.seek(pos)) {
|
||||
add_error("Failed to seek to position " + std::to_string(pos));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Seek relative to current position
|
||||
bool seek_relative(int64_t offset) {
|
||||
size_t current = stream_.tell();
|
||||
int64_t new_pos = static_cast<int64_t>(current) + offset;
|
||||
|
||||
if (new_pos < 0) {
|
||||
add_error("Seek would move before start of stream");
|
||||
return false;
|
||||
}
|
||||
|
||||
return seek(static_cast<size_t>(new_pos));
|
||||
}
|
||||
|
||||
// Rewind to beginning
|
||||
void rewind() {
|
||||
stream_.rewind();
|
||||
}
|
||||
|
||||
// Get current position
|
||||
size_t tell() const {
|
||||
return stream_.tell();
|
||||
}
|
||||
|
||||
// Get remaining bytes
|
||||
size_t remaining() const {
|
||||
return stream_.remaining();
|
||||
}
|
||||
|
||||
// Check if at end
|
||||
bool eof() const {
|
||||
return stream_.eof();
|
||||
}
|
||||
|
||||
// Get total length
|
||||
size_t length() const {
|
||||
return stream_.length();
|
||||
}
|
||||
|
||||
// Add a custom error message
|
||||
void add_error(const std::string& msg) {
|
||||
errors_.push_back(msg);
|
||||
has_error_ = true;
|
||||
}
|
||||
|
||||
// Get direct access to underlying StreamReader (use with caution)
|
||||
const StreamReader& stream() const { return stream_; }
|
||||
|
||||
private:
|
||||
StreamReader stream_;
|
||||
std::vector<std::string> errors_;
|
||||
bool has_error_;
|
||||
};
|
||||
|
||||
} // namespace tinyexr
|
||||
|
||||
#endif // TINYEXR_EXR_READER_HH_
|
||||
Vendored
+171
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2025, Syoyo Fujita and many contributors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// StreamReader: Simple header-only stream reader with endian support
|
||||
//
|
||||
// Part of TinyEXR V2 API (EXPERIMENTAL)
|
||||
|
||||
#ifndef TINYEXR_STREAMREADER_HH_
|
||||
#define TINYEXR_STREAMREADER_HH_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace tinyexr {
|
||||
|
||||
enum class Endian {
|
||||
Little,
|
||||
Big,
|
||||
Native
|
||||
};
|
||||
|
||||
class StreamReader {
|
||||
public:
|
||||
// Constructor: takes memory address, length, and endianness
|
||||
StreamReader(const uint8_t* data, size_t length, Endian endian = Endian::Little)
|
||||
: data_(data), length_(length), pos_(0), endian_(endian) {
|
||||
// Detect native endian
|
||||
uint16_t test = 0x0001;
|
||||
native_is_little_ = (*reinterpret_cast<uint8_t*>(&test) == 0x01);
|
||||
|
||||
// Determine if we need to swap bytes
|
||||
if (endian_ == Endian::Native) {
|
||||
needs_swap_ = false;
|
||||
} else {
|
||||
bool data_is_little = (endian_ == Endian::Little);
|
||||
needs_swap_ = (data_is_little != native_is_little_);
|
||||
}
|
||||
}
|
||||
|
||||
// Read n bytes into destination buffer
|
||||
// Returns false on out-of-bounds or error
|
||||
bool read(size_t n, uint8_t* dst) {
|
||||
if (!dst || n == 0) {
|
||||
return false;
|
||||
}
|
||||
if (pos_ + n > length_) {
|
||||
return false; // Out of bounds
|
||||
}
|
||||
std::memcpy(dst, data_ + pos_, n);
|
||||
pos_ += n;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 1 byte (uint8_t)
|
||||
bool read1(uint8_t* dst) {
|
||||
return read(1, dst);
|
||||
}
|
||||
|
||||
// Read 2 bytes (uint16_t) with endian swap if needed
|
||||
bool read2(uint16_t* dst) {
|
||||
if (!dst) {
|
||||
return false;
|
||||
}
|
||||
uint8_t buf[2];
|
||||
if (!read(2, buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (needs_swap_) {
|
||||
*dst = static_cast<uint16_t>(buf[1]) << 8 |
|
||||
static_cast<uint16_t>(buf[0]);
|
||||
} else {
|
||||
std::memcpy(dst, buf, 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 4 bytes (uint32_t) with endian swap if needed
|
||||
bool read4(uint32_t* dst) {
|
||||
if (!dst) {
|
||||
return false;
|
||||
}
|
||||
uint8_t buf[4];
|
||||
if (!read(4, buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (needs_swap_) {
|
||||
*dst = static_cast<uint32_t>(buf[3]) << 24 |
|
||||
static_cast<uint32_t>(buf[2]) << 16 |
|
||||
static_cast<uint32_t>(buf[1]) << 8 |
|
||||
static_cast<uint32_t>(buf[0]);
|
||||
} else {
|
||||
std::memcpy(dst, buf, 4);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read 8 bytes (uint64_t) with endian swap if needed
|
||||
bool read8(uint64_t* dst) {
|
||||
if (!dst) {
|
||||
return false;
|
||||
}
|
||||
uint8_t buf[8];
|
||||
if (!read(8, buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (needs_swap_) {
|
||||
*dst = static_cast<uint64_t>(buf[7]) << 56 |
|
||||
static_cast<uint64_t>(buf[6]) << 48 |
|
||||
static_cast<uint64_t>(buf[5]) << 40 |
|
||||
static_cast<uint64_t>(buf[4]) << 32 |
|
||||
static_cast<uint64_t>(buf[3]) << 24 |
|
||||
static_cast<uint64_t>(buf[2]) << 16 |
|
||||
static_cast<uint64_t>(buf[1]) << 8 |
|
||||
static_cast<uint64_t>(buf[0]);
|
||||
} else {
|
||||
std::memcpy(dst, buf, 8);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Seek to absolute position
|
||||
// Returns false if position is out of bounds
|
||||
bool seek(size_t pos) {
|
||||
if (pos > length_) {
|
||||
return false;
|
||||
}
|
||||
pos_ = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rewind to beginning
|
||||
void rewind() {
|
||||
pos_ = 0;
|
||||
}
|
||||
|
||||
// Get current position
|
||||
size_t tell() const {
|
||||
return pos_;
|
||||
}
|
||||
|
||||
// Get remaining bytes
|
||||
size_t remaining() const {
|
||||
return length_ - pos_;
|
||||
}
|
||||
|
||||
// Check if at end
|
||||
bool eof() const {
|
||||
return pos_ >= length_;
|
||||
}
|
||||
|
||||
// Get total length
|
||||
size_t length() const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t* data_;
|
||||
size_t length_;
|
||||
size_t pos_;
|
||||
Endian endian_;
|
||||
bool native_is_little_;
|
||||
bool needs_swap_;
|
||||
};
|
||||
|
||||
} // namespace tinyexr
|
||||
|
||||
#endif // TINYEXR_STREAMREADER_HH_
|
||||
Vendored
+1991
-46
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user