Files
wc3re/src/IffFile.hh

243 lines
4.8 KiB
C++

#ifndef WC3RE_IFFFILE_HH__
#define WC3RE_IFFFILE_HH__
#include "Resource.hh"
class IffFile : public RefCounted {
public:
IffFile(Resource::Handle res);
~IffFile();
using Handle = ResourceHandle<IffFile>;
class Object;
class Form;
class ObjectIterator : public std::iterator<std::random_access_iterator_tag, const Object> {
public:
Object const& operator*() const {
return **implIt_;
}
ObjectIterator& operator++() {
++implIt_;
return *this;
}
ObjectIterator& operator--() {
--implIt_;
return *this;
}
bool operator!=(ObjectIterator const& other) const {
return (implIt_ != other.implIt_);
}
bool operator>(ObjectIterator const& other) const {
return (implIt_ > other.implIt_);
}
bool operator>=(ObjectIterator const& other) const {
return (implIt_ >= other.implIt_);
}
bool operator<(ObjectIterator const& other) const {
return (implIt_ < other.implIt_);
}
bool operator<=(ObjectIterator const& other) const {
return (implIt_ <= other.implIt_);
}
Object const* operator->() const {
return implIt_->get();
}
ObjectIterator operator++(int) {
ObjectIterator ret = *this;
++implIt_;
return ret;
}
ObjectIterator operator--(int) {
ObjectIterator ret = *this;
--implIt_;
return ret;
}
ObjectIterator& operator+=(ptrdiff_t n) {
implIt_ += n;
return *this;
}
ObjectIterator operator+(ptrdiff_t n) const {
ObjectIterator ret = *this;
ret += n;
return ret;
}
ObjectIterator& operator-=(ptrdiff_t n) {
implIt_ -= n;
return *this;
}
ObjectIterator operator-(ptrdiff_t n) const {
ObjectIterator ret = *this;
ret -= n;
return ret;
}
ptrdiff_t operator-(ObjectIterator const& other) const {
return implIt_ - other.implIt_;
}
Object const& operator[](ptrdiff_t n) const {
return *(implIt_[n]);
}
private:
ObjectIterator(std::vector<std::unique_ptr<Object> >::const_iterator implIt)
: implIt_(std::move(implIt)) {
}
friend class Form;
friend class IffFile;
std::vector<std::unique_ptr<Object> >::const_iterator implIt_;
};
class Object : public Resource {
public:
Object(Object const& copy) = delete;
~Object() override {
}
std::string const& getType() const {
return type_;
}
bool isForm() const {
return (typeid(*this) == typeid(Form));
}
size_t size() const override {
return length_;
}
uint8_t const* data() const override {
return base_;
}
uint8_t const* begin() const {
return base_;
}
uint8_t const* end() const {
return base_+length_;
}
void incRef() override {
parent_.incRef();
}
void decRef() override {
parent_.decRef();
}
unsigned getRef() const override {
return parent_.getRef();
}
operator std::string() const;
operator bool() const override {
return true;
}
protected:
Object(IffFile& parent, std::string type, uint8_t const* base, size_t length, size_t& footprint);
IffFile& parent_;
uint8_t const* base_;
size_t const length_;
std::string const type_;
friend class IffFile;
};
class Form final : public Object {
public:
~Form() override {
}
std::string const& getSubtype() const {
return subtype_;
}
size_t getChildCount() const {
return children_.size();
}
ObjectIterator childrenBegin() const {
return ObjectIterator(children_.cbegin());
}
ObjectIterator childrenEnd() const {
return ObjectIterator(children_.cend());
}
Object& getObject(std::string const& spec) const;
private:
Form(IffFile& parent, std::string type, uint8_t const* base, size_t length, size_t& footprint);
std::vector<std::unique_ptr<Object> > children_;
std::string subtype_;
friend class IffFile;
};
Object const& getRoot() const {
return *roots_[0];
}
ObjectIterator begin() const {
return ObjectIterator(roots_.cbegin());
}
ObjectIterator end() const {
return ObjectIterator(roots_.cend());
}
void printStructure(unsigned level = 0) const;
Object& getObject(std::string const& spec) const;
size_t size() const {
return res_->size();
}
uint8_t const* data() const {
return res_->data();
}
operator bool() const {
return *res_;
}
size_t footprint() const {
return footprint_;
}
private:
static std::unique_ptr<Object> parseObject(IffFile& parent, uint8_t const* base,
size_t length, size_t& footprint);
Resource::Handle res_;
std::vector<std::unique_ptr<Object> > roots_;
size_t footprint_;
};
#endif