diff options
author | Colin Snover | 2016-12-31 20:39:57 -0600 |
---|---|---|
committer | Colin Snover | 2017-03-27 19:42:31 -0500 |
commit | 31daa956d62b39429cb6638ed3fb549ac488833a (patch) | |
tree | fa831adefae05d82209b3f565055f7b761ca8691 /engines/sci/util.h | |
parent | 1298762b7665dc1b7aeedf0271eadfb284309ef1 (diff) | |
download | scummvm-rg350-31daa956d62b39429cb6638ed3fb549ac488833a.tar.gz scummvm-rg350-31daa956d62b39429cb6638ed3fb549ac488833a.tar.bz2 scummvm-rg350-31daa956d62b39429cb6638ed3fb549ac488833a.zip |
SCI: Implement bounds-checked reads of game resources
Diffstat (limited to 'engines/sci/util.h')
-rw-r--r-- | engines/sci/util.h | 257 |
1 files changed, 256 insertions, 1 deletions
diff --git a/engines/sci/util.h b/engines/sci/util.h index b0fee5151e..e8b60adf9c 100644 --- a/engines/sci/util.h +++ b/engines/sci/util.h @@ -23,7 +23,13 @@ #ifndef SCI_UTIL_H #define SCI_UTIL_H +#include "common/span.h" +#include "common/endian.h" +#include "common/file.h" +#include "common/memstream.h" #include "common/scummsys.h" +#include "common/str.h" +#include "common/textconsole.h" namespace Sci { @@ -40,11 +46,260 @@ void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val); #ifdef ENABLE_SCI32 void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val); #endif - // Wrappers for reading integer values in resources that are // LE in SCI1.1 Mac, but BE in SCI32 Mac uint16 READ_SCI32ENDIAN_UINT16(const void *ptr); +#pragma mark - +#pragma mark SciSpanImpl - SciSpanIterator + +namespace SciSpanInternal { + template <typename Span, bool IsConst> + class SciSpanIterator : public Common::SpanInternal::SpanIterator<Span, IsConst> { + typedef typename Common::SpanInternal::SpanIterator<Span, IsConst> super_type; + typedef typename Span::value_type span_value_type; + typedef typename Common::Conditional<IsConst, const Span, Span>::type span_type; + + public: + typedef typename Span::difference_type difference_type; + typedef typename Common::RemoveConst<span_value_type>::type value_type; + typedef typename Common::Conditional<IsConst, const span_value_type, span_value_type>::type *pointer; + typedef typename Common::Conditional<IsConst, const span_value_type, span_value_type>::type &reference; + + inline SciSpanIterator() : super_type() {} + + inline SciSpanIterator(span_type *span, const difference_type index) : super_type(span, index) {} + + inline SciSpanIterator(const SciSpanIterator &other) : super_type(other) {} + + inline SciSpanIterator &operator=(const SciSpanIterator &other) { + super_type::operator=(other); + return *this; + } + + inline SciSpanIterator operator+(const difference_type delta) const { + SciSpanIterator it(*this); + it += delta; + return it; + } + + inline SciSpanIterator operator-(const difference_type delta) const { + return operator+(-delta); + } + + inline difference_type operator-(const SciSpanIterator &other) const { + assert(this->_span == other._span); + return this->_index - other._index; + } + + inline int16 getInt16SE() const { + return this->_span->getInt16SEAt(this->_index); + } + + inline uint16 getUint16SE() const { + return this->_span->getUint16SEAt(this->_index); + } + + inline uint16 getUint16SE32() const { + return this->_span->getUint16SE32At(this->_index); + } + + inline int32 getInt32SE() const { + return this->_span->getInt32SEAt(this->_index); + } + + inline uint32 getUint32SE() const { + return this->_span->getUint32SEAt(this->_index); + } + + inline void setUint16SE(uint16 value) const { + this->_span->setUint16SEAt(this->_index, value); + } + +#ifdef ENABLE_SCI32 + inline void setUint32SE(uint32 value) const { + this->_span->setUint32SEAt(this->_index, value); + } +#endif + }; +} // End of namespace SciSpanInternal + +/** + * Bounds-checked random access into a contiguous block of memory, with + * extra methods that automatically read and write using the correct endianness + * for the currently loaded game. + */ +template <typename ValueType, template <typename> class Derived> +class SciSpanImpl : public Common::NamedSpanImpl<ValueType, Derived> { + typedef Common::NamedSpanImpl<ValueType, Derived> super_type; + typedef Derived<ValueType> derived_type; + typedef typename Common::AddConst<Derived<ValueType> >::type const_derived_type; + typedef typename Common::RemoveConst<Derived<ValueType> >::type mutable_derived_type; + +#if !defined(__GNUC__) || GCC_ATLEAST(3, 0) + template <typename T, template <typename> class U> friend class SciSpanImpl; +#endif +#if CXXTEST_RUNNING + friend class ::SpanTestSuite; +#endif + +public: + typedef typename super_type::value_type value_type; + typedef typename super_type::difference_type difference_type; + typedef typename super_type::index_type index_type; + typedef typename super_type::size_type size_type; + typedef SciSpanInternal::SciSpanIterator<derived_type, true> const_iterator; + typedef SciSpanInternal::SciSpanIterator<derived_type, false> iterator; + typedef typename super_type::pointer pointer; + typedef typename super_type::const_pointer const_pointer; + typedef typename super_type::reference reference; + typedef typename super_type::const_reference const_reference; + + inline SciSpanImpl() : super_type() {} + + inline SciSpanImpl(const pointer data_, + const size_type size_, + const Common::String &name = Common::String(), + const size_type sourceByteOffset = 0) : + super_type(data_, size_, name, sourceByteOffset) {} + + template <typename Other> + inline SciSpanImpl(const Other &other) : + super_type(other) {} + + template <typename Other> + inline mutable_derived_type &operator=(const Other &other) { + super_type::operator=(other); + return this->impl(); + } + + inline ~SciSpanImpl() {} + + inline const_iterator cbegin() const { return const_iterator(&this->impl(), 0); } + inline const_iterator cend() const { return const_iterator(&this->impl(), this->size()); } + inline const_iterator begin() const { return const_iterator(&this->impl(), 0); } + inline const_iterator end() const { return const_iterator(&this->impl(), this->size()); } + inline iterator begin() { return iterator(&this->impl(), 0); } + inline iterator end() { return iterator(&this->impl(), this->size()); } + +#pragma mark - +#pragma mark SciSpan - Data access + +public: + inline int16 getInt16SEAt(const size_type index) const { + return (int16)getUint16SEAt(index); + } + + inline uint16 getUint16SEAt(const size_type index) const { + this->validate(index, sizeof(uint16)); + return READ_SCI11ENDIAN_UINT16(this->data() + index); + } + + inline uint16 getUint16SE32At(const size_type index) const { + this->validate(index, sizeof(uint16)); + return READ_SCI32ENDIAN_UINT16(this->data() + index); + } + + inline int32 getInt32SEAt(const size_type index) const { + return (int32)getUint32SEAt(index); + } + + inline uint32 getUint32SEAt(const size_type index) const { + this->validate(index, sizeof(uint32)); + return READ_SCI11ENDIAN_UINT32(this->data() + index); + } + + inline void setUint16SEAt(const size_type index, uint16 value) { + this->validate(index, sizeof(uint16), Common::kValidateWrite); + WRITE_SCI11ENDIAN_UINT16(this->data() + index, value); + } + +#ifdef ENABLE_SCI32 + inline void setUint32SEAt(const size_type index, uint32 value) { + this->validate(index, sizeof(uint32), Common::kValidateWrite); + WRITE_SCI11ENDIAN_UINT32(this->data() + index, value); + } +#endif + +#pragma mark - +#pragma mark SciSpanImpl - ForwardIterator + +// Spans that are used as ForwardIterators must not be allowed inside of +// SpanOwner, since this will result in the wrong pointer to memory to be +// deleted +public: + inline const_reference operator*() const { + this->validate(0, sizeof(value_type)); + return *this->_data; + } + + inline reference operator*() { + this->validate(0, sizeof(value_type)); + return *this->_data; + } + + inline mutable_derived_type &operator+=(const difference_type delta) { + this->validate(0, delta * sizeof(value_type), Common::kValidateSeek); + this->_data += delta; + this->_size -= delta; + return this->impl(); + } + + inline mutable_derived_type &operator++() { + return operator+=(1); + } + + inline mutable_derived_type operator++(int) { + mutable_derived_type span(this->impl()); + operator+=(1); + return span; + } + + inline mutable_derived_type operator+(const difference_type delta) const { + mutable_derived_type span(this->impl()); + span += delta; + return span; + } +}; + +template <typename ValueType> +class SciSpan : public SciSpanImpl<ValueType, SciSpan> { + typedef SciSpanImpl<ValueType, ::Sci::SciSpan> super_type; + typedef typename Common::AddConst<SciSpan<ValueType> >::type const_derived_type; + typedef typename Common::RemoveConst<SciSpan<ValueType> >::type mutable_derived_type; + +public: + typedef typename super_type::value_type value_type; + typedef typename super_type::difference_type difference_type; + typedef typename super_type::index_type index_type; + typedef typename super_type::size_type size_type; + typedef typename super_type::const_iterator const_iterator; + typedef typename super_type::iterator iterator; + typedef typename super_type::pointer pointer; + typedef typename super_type::const_pointer const_pointer; + typedef typename super_type::reference reference; + typedef typename super_type::const_reference const_reference; + + inline SciSpan() : super_type() {} + + inline SciSpan(const pointer data_, + const size_type size_, + const Common::String &name = Common::String(), + const size_type sourceByteOffset = 0) : + super_type(data_, size_, name, sourceByteOffset) {} + + template <typename Other> + inline SciSpan(const Other &other) : super_type(other) {} + + template <typename Other> + inline mutable_derived_type &operator=(const Other &other) { + super_type::operator=(other); + return this->impl(); + } + + ~SciSpan() {} +}; + } // End of namespace Sci #endif |