#ifndef LIBHEIF_BITSTREAM_H
#define LIBHEIF_BITSTREAM_H
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#if defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#endif
#if defined(HAVE_STDDEF_H)
#include <stddef.h>
#endif
#include <vector>
#include <string>
#include <memory>
#include <limits>
#include <istream>
#include <string>
#include "error.h"
namespace heif {
class StreamReader
{
public:
virtual ~StreamReader() { }
virtual int64_t get_position() const = 0;
enum grow_status {
size_reached,
timeout,
size_beyond_eof
};
virtual grow_status wait_for_file_size(int64_t target_size) = 0;
virtual bool read(void* data, size_t size) = 0;
virtual bool seek(int64_t position) = 0;
bool seek_cur(int64_t position_offset) {
return seek(get_position() + position_offset);
}
};
class StreamReader_istream : public StreamReader
{
public:
StreamReader_istream(std::unique_ptr<std::istream>&& istr);
int64_t get_position() const override;
grow_status wait_for_file_size(int64_t target_size) override;
bool read(void* data, size_t size) override;
bool seek(int64_t position) override;
private:
std::unique_ptr<std::istream> m_istr;
int64_t m_length;
};
class StreamReader_memory : public StreamReader
{
public:
StreamReader_memory(const uint8_t* data, int64_t size, bool copy);
~StreamReader_memory();
int64_t get_position() const override;
grow_status wait_for_file_size(int64_t target_size) override;
bool read(void* data, size_t size) override;
bool seek(int64_t position) override;
private:
const uint8_t* m_data;
int64_t m_length;
int64_t m_position;
uint8_t* m_owned_data = nullptr;
};
class StreamReader_CApi : public StreamReader
{
public:
StreamReader_CApi(const heif_reader* func_table, void* userdata);
int64_t get_position() const override { return m_func_table->get_position(m_userdata); }
StreamReader::grow_status wait_for_file_size(int64_t target_size) override;
bool read(void* data, size_t size) override { return !m_func_table->read(data,size,m_userdata); }
bool seek(int64_t position) override { return !m_func_table->seek(position,m_userdata); }
private:
const heif_reader* m_func_table;
void* m_userdata;
};
class BitstreamRange
{
public:
BitstreamRange(std::shared_ptr<StreamReader> istr,
uint64_t length,
BitstreamRange* parent = nullptr);
StreamReader::grow_status wait_until_range_is_available();
uint8_t read8();
uint16_t read16();
uint32_t read32();
std::string read_string();
bool prepare_read(int64_t nBytes);
StreamReader::grow_status wait_for_available_bytes(int64_t nBytes);
void skip_to_end_of_file() {
m_remaining = 0;
if (m_parent_range) {
m_parent_range->skip_to_end_of_file();
}
}
void skip_to_end_of_box() {
if (m_remaining>0) {
if (m_parent_range) {
m_parent_range->skip_without_advancing_file_pos(m_remaining);
}
m_istr->seek_cur(m_remaining);
m_remaining = 0;
}
}
void set_eof_while_reading() {
m_remaining = 0;
if (m_parent_range) {
m_parent_range->set_eof_while_reading();
}
m_error = true;
}
bool eof() const {
return m_remaining == 0;
}
bool error() const {
return m_error;
}
Error get_error() const {
if (m_error) {
return Error(heif_error_Invalid_input,
heif_suberror_End_of_data);
}
else {
return Error::Ok;
}
}
std::shared_ptr<StreamReader> get_istream() { return m_istr; }
int get_nesting_level() const { return m_nesting_level; }
private:
std::shared_ptr<StreamReader> m_istr;
BitstreamRange* m_parent_range = nullptr;
int m_nesting_level = 0;
int64_t m_remaining;
bool m_error = false;
void skip_without_advancing_file_pos(int64_t nBytes);
};
class BitReader
{
public:
BitReader(const uint8_t* buffer, int len);
int get_bits(int n);
int get_bits_fast(int n);
int peek_bits(int n);
void skip_bits(int n);
void skip_bits_fast(int n);
void skip_to_byte_boundary();
bool get_uvlc(int* value);
bool get_svlc(int* value);
int get_current_byte_index() const {
return data_length - bytes_remaining - nextbits_cnt/8;
}
private:
const uint8_t* data;
int data_length;
int bytes_remaining;
uint64_t nextbits;
int nextbits_cnt;
void refill();
};
class StreamWriter
{
public:
void write8(uint8_t);
void write16(uint16_t);
void write32(uint32_t);
void write64(uint64_t);
void write(int size, uint64_t value);
void write(const std::string&);
void write(const std::vector<uint8_t>&);
void write(const StreamWriter&);
void skip(int n);
void insert(int nBytes);
size_t data_size() const { return m_data.size(); }
size_t get_position() const { return m_position; }
void set_position(size_t pos) { m_position=pos; }
void set_position_to_end() { m_position=m_data.size(); }
const std::vector<uint8_t> get_data() const { return m_data; }
private:
std::vector<uint8_t> m_data;
size_t m_position = 0;
};
}
#endif