diff options
-rw-r--r-- | common/algorithm.h | 103 | ||||
-rw-r--r-- | common/array.h | 34 | ||||
-rw-r--r-- | common/func.h | 240 | ||||
-rw-r--r-- | common/hash-str.h | 2 | ||||
-rw-r--r-- | common/list.h | 6 | ||||
-rw-r--r-- | engines/kyra/resource.cpp | 246 | ||||
-rw-r--r-- | engines/kyra/resource.h | 39 | ||||
-rw-r--r-- | gui/browser.cpp | 2 | ||||
-rw-r--r-- | test/common/array.h | 79 |
9 files changed, 543 insertions, 208 deletions
diff --git a/common/algorithm.h b/common/algorithm.h new file mode 100644 index 0000000000..616dc67317 --- /dev/null +++ b/common/algorithm.h @@ -0,0 +1,103 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2007 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef COMMON_ALGORITHM_H +#define COMMON_ALGORITHM_H + +#include "common/scummsys.h" + +namespace Common { + +template<class In, class Out> +Out copy(In first, In last, Out dst) { + while (first != last) + *dst++ = *first++; + return dst; +} + +template<class In, class Out> +Out copy_backward(In first, In last, Out dst) { + while (first != last) + *--dst = *--last; + return dst; +} + +template<class In, class Out, class Op> +Out copy_if(In first, In last, Out dst, Op op) { + while (first != last) { + if (op(*first)) + *dst++ = *first; + ++first; + } + return dst; +} + +template<class In, class T> +In find(In first, In last, const T &v) { + while (first != last) { + if (*first == v) + return first; + ++first; + } + return last; +} + +template<class In, class Pred> +In find_if(In first, In last, Pred p) { + while (first != last) { + if (p(*first)) + return first; + ++first; + } + return last; +} + +template<class In, class Op> +Op for_each(In first, In last, Op f) { + while (first != last) f(*first++); + return f; +} + +// Simple sort function, modelled after std::sort. +// Use it like this: sort(container.begin(), container.end()). +// Also work on plain old int arrays etc. +template<class T> +void sort(T first, T last) { + if (first == last) + return; + + // Simple selection sort + T i(first); + for (; i != last; ++i) { + T minElem(i); + T j(i); + ++j; + for (; j != last; ++j) + if (*j < *minElem) + minElem = j; + if (minElem != i) + SWAP(*minElem, *i); + } +} + +} // end of namespace Common +#endif + diff --git a/common/array.h b/common/array.h index d0be7fa194..97ee6abdf4 100644 --- a/common/array.h +++ b/common/array.h @@ -23,6 +23,7 @@ #define COMMON_ARRAY_H #include "common/scummsys.h" +#include "common/algorithm.h" namespace Common { @@ -37,14 +38,15 @@ public: typedef T *iterator; typedef const T *const_iterator; + typedef T value_type; + public: Array() : _capacity(0), _size(0), _data(0) {} Array(const Array<T>& array) : _capacity(0), _size(0), _data(0) { _size = array._size; _capacity = _size + 32; _data = new T[_capacity]; - for (int i = 0; i < _size; i++) - _data[i] = array._data[i]; + copy(array._data, array._data + _size, _data); } ~Array() { @@ -59,21 +61,14 @@ public: void push_back(const Array<T>& array) { ensureCapacity(_size + array._size); - for (int i = 0; i < array._size; i++) - _data[_size++] = array._data[i]; + copy(array._data, array._data + array._size, _data + _size); + _size += array._size; } void insert_at(int idx, const T& element) { assert(idx >= 0 && idx <= _size); ensureCapacity(_size + 1); - // The following loop is not efficient if you can just memcpy things around. - // e.g. if you have a list of ints. But for real objects (String...), memcpy - // usually isn't correct (specifically, for any class which has a non-default - // copy behaviour. E.g. the String class uses a refCounter which has to be - // updated whenever a String is copied. - for (int i = _size; i > idx; i--) { - _data[i] = _data[i-1]; - } + copy_backward(_data + idx, _data + _size, _data + _size + 1); _data[idx] = element; _size++; } @@ -81,8 +76,7 @@ public: T remove_at(int idx) { assert(idx >= 0 && idx < _size); T tmp = _data[idx]; - for (int i = idx; i < _size - 1; i++) - _data[i] = _data[i+1]; + copy(_data + idx + 1, _data + _size, _data + idx); _size--; return tmp; } @@ -108,8 +102,7 @@ public: _size = array._size; _capacity = _size + 32; _data = new T[_capacity]; - for (int i = 0; i < _size; i++) - _data[i] = array._data[i]; + copy(array._data, array._data + _size, _data); return *this; } @@ -149,11 +142,7 @@ public: } bool contains(const T &key) const { - for (const_iterator i = begin(); i != end(); ++i) { - if (*i == key) - return true; - } - return false; + return find(begin(), end(), key) != end(); } @@ -168,8 +157,7 @@ protected: if (old_data) { // Copy old data - for (int i = 0; i < _size; i++) - _data[i] = old_data[i]; + copy(old_data, old_data + _size, _data); delete [] old_data; } } diff --git a/common/func.h b/common/func.h index b644f6569b..19d0ceafec 100644 --- a/common/func.h +++ b/common/func.h @@ -26,16 +26,219 @@ namespace Common { -template <class T> -struct EqualTo { - bool operator()(const T& x, const T& y) const { return x == y; } +template<class Arg, class Result> +struct UnaryFunction { + typedef Arg ArgumenType; + typedef Result ResultType; }; -template <class T> -struct Less { - bool operator()(const T& x, const T& y) const { return x < y; } +template<class Arg1, class Arg2, class Result> +struct BinaryFunction { + typedef Arg1 FirstArgumentType; + typedef Arg2 SecondArgumentType; + typedef Result ResultType; }; +template<class T> +struct EqualTo : public BinaryFunction<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x == y; } +}; + +template<class T> +struct Less : public BinaryFunction<T, T, bool> { + bool operator()(const T& x, const T& y) const { return x < y; } +}; + +template<class Op> +class Binder1st : public UnaryFunction<typename Op::SecondArgumentType, typename Op::ResultType> { +private: + Op _op; + typename Op::FirstArgumentType _arg1; +public: + Binder1st(const Op &op, const typename Op::FirstArgumentType &arg1) : _op(op), _arg1(arg1) {} + + typename Op::ResultType operator()(typename Op::SecondArgumentType v) const { + return _op(_arg1, v); + } +}; + +template<class Op, class T> +inline Binder1st<Op> bind1st(const Op &op, const T &t) { + return Binder1st<Op>(op, t); +} + +template<class Op> +class Binder2nd : public UnaryFunction<typename Op::FirstArgumentType, typename Op::ResultType> { +private: + Op _op; + typename Op::SecondArgumentType _arg2; +public: + Binder2nd(const Op &op, const typename Op::SecondArgumentType &arg2) : _op(op), _arg2(arg2) {} + + typename Op::ResultType operator()(typename Op::FirstArgumentType v) const { + return _op(v, _arg2); + } +}; + +template<class Op, class T> +inline Binder2nd<Op> bind2nd(const Op &op, const T &t) { + return Binder2nd<Op>(op, t); +} + +template<class Arg, class Result> +class PointerToUnaryFunc : public UnaryFunction<Arg, Result> { +private: + Result (*_func)(Arg); +public: + typedef Result (*FuncType)(Arg); + + PointerToUnaryFunc(const FuncType &func) : _func(func) {} + Result operator()(Arg v) const { + return _func(v); + } +}; + +template<class Arg1, class Arg2, class Result> +class PointerToBinaryFunc : public BinaryFunction<Arg1, Arg2, Result> { +private: + Result (*_func)(Arg1, Arg2); +public: + typedef Result (*FuncType)(Arg1, Arg2); + + PointerToBinaryFunc(const FuncType &func) : _func(func) {} + Result operator()(Arg1 v1, Arg2 v2) const { + return _func(v1, v2); + } +}; + +template<class Arg, class Result> +inline PointerToUnaryFunc<Arg, Result> ptr_fun(Result (*func)(Arg)) { + return PointerToUnaryFunc<Arg, Result>(func); +} + +template<class Arg1, class Arg2, class Result> +inline PointerToBinaryFunc<Arg1, Arg2, Result> ptr_fun(Result (*func)(Arg1, Arg2)) { + return PointerToBinaryFunc<Arg1, Arg2, Result>(func); +} + +template<class Result, class T> +class MemFunc0 : public UnaryFunction<T*, Result> { +private: + Result (T::*_func)(); +public: + typedef Result (T::*FuncType)(); + + MemFunc0(const FuncType &func) : _func(func) {} + Result operator()(T *v) const { + return (v->*_func)(); + } +}; + +template<class Result, class T> +class ConstMemFunc0 : public UnaryFunction<T*, Result> { +private: + Result (T::*_func)() const; +public: + typedef Result (T::*FuncType)() const; + + ConstMemFunc0(const FuncType &func) : _func(func) {} + Result operator()(T *v) const { + return (v->*_func)(); + } +}; + +template<class Result, class Arg, class T> +class MemFunc1 : public BinaryFunction<T*, Arg, Result> { +private: + Result (T::*_func)(Arg); +public: + typedef Result (T::*FuncType)(Arg); + + MemFunc1(const FuncType &func) : _func(func) {} + Result operator()(T *v1, Arg v2) const { + return (v1->*_func)(v2); + } +}; + +template<class Result, class Arg, class T> +class ConstMemFunc1 : public BinaryFunction<T*, Arg, Result> { +private: + Result (T::*_func)(Arg) const; +public: + typedef Result (T::*FuncType)(Arg) const; + + ConstMemFunc1(const FuncType &func) : _func(func) {} + Result operator()(T *v1, Arg v2) const { + return (v1->*_func)(v2); + } +}; + +template<class Result, class T> +inline MemFunc0<Result, T> mem_fun(Result (T::*f)()) { + return MemFunc0<Result, T>(f); +} + +template<class Result, class T> +inline ConstMemFunc0<Result, T> mem_fun(Result (T::*f)() const) { + return ConstMemFunc0<Result, T>(f); +} + +template<class Result, class Arg, class T> +inline MemFunc1<Result, Arg, T> mem_fun(Result (T::*f)(Arg)) { + return MemFunc1<Result, Arg, T>(f); +} + +template<class Result, class Arg, class T> +inline ConstMemFunc1<Result, Arg, T> mem_fun(Result (T::*f)(Arg) const) { + return ConstMemFunc1<Result, Arg, T>(f); +} + +template<class Cont> +class BackInsertIterator { +private: + Cont *_container; + +public: + BackInsertIterator(Cont &c) : _container(&c) {} + + BackInsertIterator &operator =(const typename Cont::value_type &v) { + _container->push_back(v); + return *this; + } + + BackInsertIterator &operator *() { return *this; } + BackInsertIterator &operator ++() { return *this; } + BackInsertIterator operator ++(int) { return *this; } +}; + +template<class Cont> +BackInsertIterator<Cont> back_inserter(Cont &c) { + return BackInsertIterator<Cont>(c); +} + +template<class Cont> +class FrontInsertIterator { +private: + Cont *_container; + +public: + FrontInsertIterator(Cont &c) : _container(&c) {} + + FrontInsertIterator &operator =(const typename Cont::value_type &v) { + _container->push_front(v); + return *this; + } + + FrontInsertIterator &operator *() { return *this; } + FrontInsertIterator &operator ++() { return *this; } + FrontInsertIterator operator ++(int) { return *this; } +}; + +template<class Cont> +FrontInsertIterator<Cont> front_inserter(Cont &c) { + return FrontInsertIterator<Cont>(c); +} + /** * Base template for hash functor objects, used by HashMap. * This needs to be specialized for every type that you need to hash. @@ -61,30 +264,7 @@ GENERATE_TRIVIAL_HASH_FUNCTOR(unsigned long); #undef GENERATE_TRIVIAL_HASH_FUNCTOR - -// Simple sort function, modelled after std::sort. -// Use it like this: sort(container.begin(), container.end()). -// Also work on plain old int arrays etc. -template <typename T> -void sort(T first, T last) { - if (first == last) - return; - - // Simple selection sort - T i(first); - for (; i != last; ++i) { - T minElem(i); - T j(i); - ++j; - for (; j != last; ++j) - if (*j < *minElem) - minElem = j; - if (minElem != i) - SWAP(*minElem, *i); - } -} - - } // End of namespace Common #endif + diff --git a/common/hash-str.h b/common/hash-str.h index bb61e3091d..99ebf99a10 100644 --- a/common/hash-str.h +++ b/common/hash-str.h @@ -29,6 +29,8 @@ namespace Common { uint hashit(const char *str); uint hashit_lower(const char *str); // Generate a hash based on the lowercase version of the string +inline uint hashit(const String &str) { return hashit(str.c_str()); } +inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str()); } // FIXME: The following functors obviously are not consistently named diff --git a/common/list.h b/common/list.h index da20f22cf1..68a464d194 100644 --- a/common/list.h +++ b/common/list.h @@ -111,8 +111,10 @@ public: NodeBase *_anchor; public: - typedef Iterator<T> iterator; - typedef Iterator<const T> const_iterator; + typedef Iterator<T> iterator; + typedef Iterator<const T> const_iterator; + + typedef T value_type; public: List() { diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 2d6d54da34..ca56ed0f02 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -26,6 +26,8 @@ #include "common/file.h" #include "common/fs.h" #include "common/hash-str.h" +#include "common/func.h" +#include "common/algorithm.h" #include "gui/message.h" @@ -35,12 +37,24 @@ #include "kyra/screen.h" namespace Kyra { + +namespace { +struct ResFilenameEqual : public Common::BinaryFunction<ResourceFile*, uint, bool> { + uint _filename; + ResFilenameEqual(uint file) : _filename(file) {} + + bool operator()(ResourceFile *f) { + return f->filename() == _filename; + } +}; +} // end of anonymous namespace + Resource::Resource(KyraEngine *vm) { _vm = vm; if (_vm->game() == GI_KYRA1) { // we're loading KYRA.DAT here too (but just for Kyrandia 1) - if (!loadPakFile("KYRA.DAT", true) || !StaticResource::checkKyraDat()) { + if (!loadPakFile("KYRA.DAT") || !StaticResource::checkKyraDat()) { GUI::MessageDialog errorMsg("You're missing the 'KYRA.DAT' file or it got corrupted, (re)get it from the ScummVM website"); errorMsg.runModal(); error("You're missing the 'KYRA.DAT' file or it got corrupted, (re)get it from the ScummVM website"); @@ -58,7 +72,7 @@ Resource::Resource(KyraEngine *vm) { INSFile *insFile = new INSFile("WESTWOOD.001"); assert(insFile); if (!insFile->isValid()) - return; + error("'WESTWOOD.001' file not found or corrupt"); _pakfiles.push_back(insFile); } @@ -72,17 +86,11 @@ Resource::Resource(KyraEngine *vm) { static const char *list[] = { "ADL.PAK", "CHAPTER1.VRM", "COL.PAK", "FINALE.PAK", "INTRO1.PAK", "INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "MISC.PAK", "SND.PAK", "STARTUP.PAK", "XMI.PAK", - "CAVE.APK", "DRAGON1.APK", "DRAGON2.APK", "LAGOON.APK", 0 + "CAVE.APK", "DRAGON1.APK", "DRAGON2.APK", "LAGOON.APK" }; - for (int i = 0; list[i]; ++i) { - if (!loadPakFile(list[i])) - error("couldn't open pakfile '%s'", list[i]); - } - - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - for (;start != _pakfiles.end(); ++start) - (*start)->protect(); + Common::for_each(list, list + ARRAYSIZE(list), Common::bind1st(Common::mem_fun(&Resource::loadPakFile), this)); + Common::for_each(_pakfiles.begin(), _pakfiles.end(), Common::bind2nd(Common::mem_fun(&ResourceFile::protect), true)); } else { for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { Common::String filename = file->name(); @@ -99,57 +107,48 @@ Resource::Resource(KyraEngine *vm) { } if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); uint unloadHash = (_vm->gameFlags().lang == Common::EN_ANY) ? Common::hashit_lower("JMC.PAK") : Common::hashit_lower("EMC.PAK"); - for (;start != _pakfiles.end(); ++start) { - if ((*start)->filename() == unloadHash) { - delete *start; - *start = 0; - _pakfiles.erase(start); - break; - } + ResIterator file = Common::find_if(_pakfiles.begin(), _pakfiles.end(), ResFilenameEqual(unloadHash)); + if (file != _pakfiles.end()) { + delete *file; + _pakfiles.erase(file); } } } } Resource::~Resource() { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - - for (;start != _pakfiles.end(); ++start) { + for (ResIterator start = _pakfiles.begin() ;start != _pakfiles.end(); ++start) { delete *start; *start = 0; } } -bool Resource::loadPakFile(const Common::String &filename, const bool forcePC) { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - uint hash = Common::hashit_lower(filename.c_str()); - - for (;start != _pakfiles.end(); ++start) { - if ((*start)->filename() == hash) { - (*start)->open(); - return true; - } +bool Resource::loadPakFile(const Common::String &filename) { + ResIterator listFile = Common::find_if(_pakfiles.begin(), _pakfiles.end(), ResFilenameEqual(Common::hashit_lower(filename))); + if (listFile != _pakfiles.end()) { + (*listFile)->open(); + return true; } + const bool isKyraDat = filename.equalsIgnoreCase("KYRA.DAT"); uint32 size = 0; Common::File handle; if (!getFileHandle(filename.c_str(), &size, handle)) { - warning("couldn't load file: '%s'", filename.c_str()); + (!isKyraDat ? error : warning)("couldn't load file: '%s'", filename.c_str()); return false; } - PAKFile *file = new PAKFile(filename.c_str(), handle.name(), handle, (_vm->gameFlags().platform == Common::kPlatformAmiga) && !forcePC); + PAKFile *file = new PAKFile(filename.c_str(), handle.name(), handle, (_vm->gameFlags().platform == Common::kPlatformAmiga) && !isKyraDat); handle.close(); if (!file) return false; if (!file->isValid()) { - warning("'%s' is no valid pak file", filename.c_str()); + error("'%s' is no valid pak file", filename.c_str()); delete file; return false; } @@ -159,28 +158,16 @@ bool Resource::loadPakFile(const Common::String &filename, const bool forcePC) { } void Resource::unloadPakFile(const Common::String &filename) { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - uint hash = Common::hashit_lower(filename.c_str()); - for (;start != _pakfiles.end(); ++start) { - if ((*start)->filename() == hash) { - (*start)->close(); - break; - } - } - return; + ResIterator pak = Common::find_if(_pakfiles.begin(), _pakfiles.end(), ResFilenameEqual(Common::hashit_lower(filename))); + if (pak != _pakfiles.end()) + (*pak)->close(); } -bool Resource::isInPakList(const Common::String &filename) { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - uint hash = Common::hashit_lower(filename.c_str()); - for (;start != _pakfiles.end(); ++start) { - if ((*start)->filename() == hash) - return true; - } - return false; +bool Resource::isInPakList(const Common::String &filename) const { + return (Common::find_if(_pakfiles.begin(), _pakfiles.end(), ResFilenameEqual(Common::hashit_lower(filename))) != _pakfiles.end()); } -uint8 *Resource::fileData(const char *file, uint32 *size) { +uint8 *Resource::fileData(const char *file, uint32 *size) const { Common::File fileHandle; if (size) @@ -199,15 +186,13 @@ uint8 *Resource::fileData(const char *file, uint32 *size) { return buffer; } else { - // opens the file in a PAK File - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - + // opens the file inside a PAK File uint fileHash = Common::hashit_lower(file); - for (;start != _pakfiles.end(); ++start) { - if (!(*start)->isOpen()) + for (ConstResIterator cur = _pakfiles.begin(); cur != _pakfiles.end(); ++cur) { + if (!(*cur)->isOpen()) continue; - uint32 fileSize = (*start)->getFileSize(fileHash); + uint32 fileSize = (*cur)->getFileSize(fileHash); if (!fileSize) continue; @@ -215,7 +200,7 @@ uint8 *Resource::fileData(const char *file, uint32 *size) { if (size) *size = fileSize; - return (*start)->getFile(fileHash); + return (*cur)->getFile(fileHash); } } @@ -228,10 +213,8 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh if (filehandle.open(file)) return true; - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - uint fileHash = Common::hashit_lower(file); - for (;start != _pakfiles.end(); ++start) { + for (ResIterator start = _pakfiles.begin() ;start != _pakfiles.end(); ++start) { if (!(*start)->isOpen()) continue; @@ -247,15 +230,13 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh return false; } -uint32 Resource::getFileSize(const char *file) { - Common::List<ResourceFile*>::iterator start = _pakfiles.begin(); - +uint32 Resource::getFileSize(const char *file) const { Common::File temp; if (temp.open(file)) return temp.size(); uint fileHash = Common::hashit_lower(file); - for (;start != _pakfiles.end(); ++start) { + for (ConstResIterator start = _pakfiles.begin() ;start != _pakfiles.end(); ++start) { if (!(*start)->isOpen()) continue; @@ -286,7 +267,6 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) { /////////////////////////////////////////// // Pak file manager -#define PAKFile_Iterate Common::List<PakChunk>::iterator start=_files.begin();start != _files.end(); ++start PAKFile::PAKFile(const char *file, const char *physfile, Common::File &pakfile, bool isAmiga) : ResourceFile() { _open = false; @@ -300,10 +280,10 @@ PAKFile::PAKFile(const char *file, const char *physfile, Common::File &pakfile, uint32 pos = 0, startoffset = 0, endoffset = 0; - if (!isAmiga) - startoffset = pakfile.readUint32LE(); - else + if (isAmiga) startoffset = pakfile.readUint32BE(); + else + startoffset = pakfile.readUint32LE(); if (startoffset > filesize) { warning("PAK file '%s' is corrupted", file); @@ -338,10 +318,10 @@ PAKFile::PAKFile(const char *file, const char *physfile, Common::File &pakfile, return; } - if (!isAmiga) - endoffset = READ_LE_UINT32(buffer + nameLength); - else + if (isAmiga) endoffset = READ_BE_UINT32(buffer + nameLength); + else + endoffset = READ_LE_UINT32(buffer + nameLength); if (!endoffset) { endoffset = filesize; @@ -378,47 +358,42 @@ PAKFile::~PAKFile() { _files.clear(); } -uint8 *PAKFile::getFile(uint hash) { - for (PAKFile_Iterate) { - if (start->_name == hash) { - Common::File pakfile; - if (!openFile(pakfile)) - return false; - - pakfile.seek(start->_start, SEEK_CUR); - uint8 *buffer = new uint8[start->_size]; - assert(buffer); - pakfile.read(buffer, start->_size); - return buffer; - } - } - return 0; +uint8 *PAKFile::getFile(uint hash) const { + ConstPakIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); + if (file == _files.end()) + return 0; + + Common::File pakfile; + if (!openFile(pakfile)) + return false; + + pakfile.seek(file->_start, SEEK_CUR); + uint8 *buffer = new uint8[file->_size]; + assert(buffer); + pakfile.read(buffer, file->_size); + return buffer; } -bool PAKFile::getFileHandle(uint hash, Common::File &filehandle) { +bool PAKFile::getFileHandle(uint hash, Common::File &filehandle) const { filehandle.close(); - for (PAKFile_Iterate) { - if (start->_name == hash) { - if (!openFile(filehandle)) - return false; + ConstPakIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); + if (file == _files.end()) + return false; - filehandle.seek(start->_start, SEEK_CUR); - return true; - } - } - return false; + if (!openFile(filehandle)) + return false; + + filehandle.seek(file->_start, SEEK_CUR); + return true; } -uint32 PAKFile::getFileSize(uint hash) { - for (PAKFile_Iterate) { - if (start->_name == hash) - return start->_size; - } - return 0; +uint32 PAKFile::getFileSize(uint hash) const { + ConstPakIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); + return (file != _files.end()) ? file->_size : 0; } -bool PAKFile::openFile(Common::File &filehandle) { +bool PAKFile::openFile(Common::File &filehandle) const { filehandle.close(); if (!filehandle.open(_physfile)) @@ -430,7 +405,6 @@ bool PAKFile::openFile(Common::File &filehandle) { /////////////////////////////////////////// // Ins file manager -#define INSFile_Iterate Common::List<FileEntry>::iterator start=_files.begin();start != _files.end(); ++start INSFile::INSFile(const char *file) : ResourceFile(), _files() { Common::File pakfile; _open = false; @@ -475,7 +449,7 @@ INSFile::INSFile(const char *file) : ResourceFile(), _files() { pakfile.seek(3); - for (INSFile_Iterate) { + for (FileIterator start = _files.begin(); start != _files.end(); ++start) { filesize = pakfile.readUint32LE(); start->_size = filesize; start->_start = pakfile.pos(); @@ -493,42 +467,38 @@ INSFile::~INSFile() { _files.clear(); } -uint8 *INSFile::getFile(uint hash) { - for (INSFile_Iterate) { - if (start->_name == hash) { - Common::File pakfile; - if (!pakfile.open(_physfile)) - return false; - - pakfile.seek(start->_start); - uint8 *buffer = new uint8[start->_size]; - assert(buffer); - pakfile.read(buffer, start->_size); - return buffer; - } - } - return 0; +uint8 *INSFile::getFile(uint hash) const { + ConstFileIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); + if (file == _files.end()) + return 0; + + Common::File pakfile; + if (!pakfile.open(_physfile)) + return false; + + pakfile.seek(file->_start); + uint8 *buffer = new uint8[file->_size]; + assert(buffer); + pakfile.read(buffer, file->_size); + return buffer; } -bool INSFile::getFileHandle(uint hash, Common::File &filehandle) { - for (INSFile_Iterate) { - if (start->_name == hash) { - if (!filehandle.open(_physfile)) - return false; +bool INSFile::getFileHandle(uint hash, Common::File &filehandle) const { + ConstFileIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); - filehandle.seek(start->_start, SEEK_CUR); - return true; - } - } - return false; + if (file == _files.end()) + return false; + + if (!filehandle.open(_physfile)) + return false; + + filehandle.seek(file->_start, SEEK_CUR); + return true; } -uint32 INSFile::getFileSize(uint hash) { - for (INSFile_Iterate) { - if (start->_name == hash) - return start->_size; - } - return 0; +uint32 INSFile::getFileSize(uint hash) const { + ConstFileIterator file = Common::find_if(_files.begin(), _files.end(), Common::bind2nd(Common::EqualTo<uint>(), hash)); + return (file != _files.end()) ? file->_size : 0; } } // end of namespace Kyra diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 08dbe727e3..1e8eddcc4f 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -38,9 +38,9 @@ public: ResourceFile() : _open(false), _protected(false), _filename() {} virtual ~ResourceFile() {} - virtual uint8 *getFile(uint file) = 0; - virtual bool getFileHandle(uint file, Common::File &filehandle) = 0; - virtual uint32 getFileSize(uint file) = 0; + virtual uint8 *getFile(uint file) const = 0; + virtual bool getFileHandle(uint file, Common::File &filehandle) const = 0; + virtual uint32 getFileSize(uint file) const = 0; uint filename() const { return _filename; } @@ -62,21 +62,25 @@ class PAKFile : public ResourceFile { uint _name; uint32 _start; uint32 _size; + + operator uint() const { return _name; } }; public: PAKFile(const char *file, const char *physfile, Common::File &pakfile, bool isAmiga = false); ~PAKFile(); - uint8 *getFile(uint file); - bool getFileHandle(uint file, Common::File &filehandle); - uint32 getFileSize(uint file); + uint8 *getFile(uint file) const; + bool getFileHandle(uint file, Common::File &filehandle) const; + uint32 getFileSize(uint file) const; private: - bool openFile(Common::File &filehandle); + bool openFile(Common::File &filehandle) const; Common::String _physfile; uint32 _physOffset; + typedef Common::List<PakChunk>::iterator PakIterator; + typedef Common::List<PakChunk>::const_iterator ConstPakIterator; Common::List<PakChunk> _files; // the entries }; @@ -86,15 +90,19 @@ class INSFile : public ResourceFile { uint _name; uint32 _start; uint32 _size; + + operator uint() const { return _name; } }; public: INSFile(const char *file); ~INSFile(); - uint8 *getFile(uint file); - bool getFileHandle(uint file, Common::File &filehandle); - uint32 getFileSize(uint file); + uint8 *getFile(uint file) const; + bool getFileHandle(uint file, Common::File &filehandle) const; + uint32 getFileSize(uint file) const; protected: + typedef Common::List<FileEntry>::iterator FileIterator; + typedef Common::List<FileEntry>::const_iterator ConstFileIterator; Common::List<FileEntry> _files; // the entries Common::String _physfile; @@ -105,12 +113,12 @@ public: Resource(KyraEngine *vm); ~Resource(); - bool loadPakFile(const Common::String &filename, const bool forcePC = false); + bool loadPakFile(const Common::String &filename); void unloadPakFile(const Common::String &filename); - bool isInPakList(const Common::String &filename); + bool isInPakList(const Common::String &filename) const; - uint32 getFileSize(const char *file); - uint8* fileData(const char *file, uint32 *size); + uint32 getFileSize(const char *file) const; + uint8* fileData(const char *file, uint32 *size) const; // it gives back a file handle (used for the speech player) // it could be that the needed file is embedded in the returned // handle @@ -119,6 +127,9 @@ public: bool loadFileToBuf(const char *file, void *buf, uint32 maxSize); protected: + typedef Common::List<ResourceFile*>::iterator ResIterator; + typedef Common::List<ResourceFile*>::const_iterator ConstResIterator; + KyraEngine *_vm; Common::List<ResourceFile*> _pakfiles; }; diff --git a/gui/browser.cpp b/gui/browser.cpp index 536cccdb4e..940b92dad8 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -27,7 +27,7 @@ #include "common/config-manager.h" #include "common/fs.h" #include "common/system.h" -#include "common/func.h" +#include "common/algorithm.h" namespace GUI { diff --git a/test/common/array.h b/test/common/array.h index f83c3bf0ea..8e1c53b430 100644 --- a/test/common/array.h +++ b/test/common/array.h @@ -59,4 +59,83 @@ class ArrayTestSuite : public CxxTest::TestSuite TS_ASSERT( array[1] == 33 ); TS_ASSERT( array[2] == -11 ); } + + void test_insert_at( void ) + { + Common::Array<int> array; + + // First of all some data + array.push_back(-12); + array.push_back(17); + array.push_back(25); + array.push_back(-11); + + // Insert some data + array.insert_at(2, 33); + + TS_ASSERT( array[0] == -12 ); + TS_ASSERT( array[1] == 17 ); + TS_ASSERT( array[2] == 33 ); + TS_ASSERT( array[3] == 25 ); + TS_ASSERT( array[4] == -11 ); + } + + void test_remove_at( void ) + { + Common::Array<int> array; + + // First of all some data + array.push_back(-12); + array.push_back(17); + array.push_back(33); + array.push_back(25); + array.push_back(-11); + + // Remove some data + array.remove_at(1); + + TS_ASSERT( array[0] == -12 ); + TS_ASSERT( array[1] == 33 ); + TS_ASSERT( array[2] == 25 ); + TS_ASSERT( array[3] == -11 ); + } + + void test_push_back( void ) + { + Common::Array<int> array1, array2; + + // Some data for both + array1.push_back(-3); + array1.push_back(5); + array1.push_back(9); + + array2.push_back(3); + array2.push_back(-2); + array2.push_back(-131); + + array1.push_back(array2); + + TS_ASSERT( array1[0] == -3 ); + TS_ASSERT( array1[1] == 5 ); + TS_ASSERT( array1[2] == 9 ); + TS_ASSERT( array1[3] == 3 ); + TS_ASSERT( array1[4] == -2 ); + TS_ASSERT( array1[5] == -131 ); + } + + void test_copy_constructor( void ) + { + Common::Array<int> array1; + + // Some data for both + array1.push_back(-3); + array1.push_back(5); + array1.push_back(9); + + Common::Array<int> array2(array1); + + TS_ASSERT( array2[0] == -3 ); + TS_ASSERT( array2[1] == 5 ); + TS_ASSERT( array2[2] == 9 ); + } }; |