aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/algorithm.h103
-rw-r--r--common/array.h34
-rw-r--r--common/func.h240
-rw-r--r--common/hash-str.h2
-rw-r--r--common/list.h6
-rw-r--r--engines/kyra/resource.cpp246
-rw-r--r--engines/kyra/resource.h39
-rw-r--r--gui/browser.cpp2
-rw-r--r--test/common/array.h79
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 );
+ }
};