diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/advancedDetector.cpp | 6 | ||||
-rw-r--r-- | common/archive.cpp | 288 | ||||
-rw-r--r-- | common/archive.h | 201 | ||||
-rw-r--r-- | common/array.h | 66 | ||||
-rw-r--r-- | common/config-file.cpp | 12 | ||||
-rw-r--r-- | common/fs.cpp | 2 | ||||
-rw-r--r-- | common/hash-str.h | 4 | ||||
-rw-r--r-- | common/hashmap.cpp | 31 | ||||
-rw-r--r-- | common/hashmap.h | 183 | ||||
-rw-r--r-- | common/keyboard.h | 5 | ||||
-rw-r--r-- | common/module.mk | 1 | ||||
-rw-r--r-- | common/queue.h | 51 | ||||
-rw-r--r-- | common/str.cpp | 106 | ||||
-rw-r--r-- | common/str.h | 22 | ||||
-rw-r--r-- | common/util.cpp | 16 |
15 files changed, 767 insertions, 227 deletions
diff --git a/common/advancedDetector.cpp b/common/advancedDetector.cpp index 522b24163e..1b0db4755a 100644 --- a/common/advancedDetector.cpp +++ b/common/advancedDetector.cpp @@ -82,12 +82,12 @@ static void upgradeTargetIfNecessary(const Common::ADParams ¶ms) { if (params.obsoleteList == 0) return; - const char *gameid = ConfMan.get("gameid").c_str(); + String gameid = ConfMan.get("gameid"); for (const Common::ADObsoleteGameID *o = params.obsoleteList; o->from; ++o) { - if (!scumm_stricmp(gameid, o->from)) { + if (gameid.equalsIgnoreCase(o->from)) { gameid = o->to; - ConfMan.set("gameid", o->to); + ConfMan.set("gameid", gameid); if (o->platform != Common::kPlatformUnknown) ConfMan.set("platform", Common::getPlatformCode(o->platform)); diff --git a/common/archive.cpp b/common/archive.cpp new file mode 100644 index 0000000000..b963cf4ceb --- /dev/null +++ b/common/archive.cpp @@ -0,0 +1,288 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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$ + * + */ + +#include "common/archive.h" +#include "common/fs.h" +#include "common/file.h" +#include "common/util.h" + +namespace Common { + + +FSDirectory::FSDirectory(const FilesystemNode &node, int depth) + : _node(node), _cached(false), _depth(depth) { +} + +FSDirectory::FSDirectory(const String &name, int depth) + : _node(name), _cached(false), _depth(depth) { +} + +FSDirectory::~FSDirectory() { +} + +FilesystemNode FSDirectory::getFSNode() const { + return _node; +} + +FilesystemNode FSDirectory::lookupCache(NodeCache &cache, const String &name) { + // make caching as lazy as possible + if (!name.empty()) { + if (!_cached) { + cacheDirectoryRecursive(_node, _depth, ""); + _cached = true; + } + + if (cache.contains(name)) + return cache[name]; + } + + return FilesystemNode(); +} + +bool FSDirectory::hasFile(const String &name) { + if (name.empty() || !_node.isDirectory()) { + return false; + } + + FilesystemNode node = lookupCache(_fileCache, name); + return node.exists(); +} + +FilePtr FSDirectory::openFile(const String &name) { + if (name.empty() || !_node.isDirectory()) { + return FilePtr(); + } + + FilesystemNode node = lookupCache(_fileCache, name); + + if (!node.exists()) { + warning("FSDirectory::openFile: Trying to open a FilesystemNode which does not exist"); + return FilePtr(); + } else if (node.isDirectory()) { + warning("FSDirectory::openFile: Trying to open a FilesystemNode which is a directory"); + return FilePtr(); + } + + SeekableReadStream *stream = node.openForReading(); + if (!stream) { + warning("FSDirectory::openFile: Can't create stream for file '%s'", name.c_str()); + } + + return FilePtr(stream); +} + +SharedPtr<FSDirectory> FSDirectory::getSubDirectory(const String &name) { + if (name.empty() || !_node.isDirectory()) { + // return a null SharedPtr + return SharedPtr<FSDirectory>(); + } + + FilesystemNode node = lookupCache(_subDirCache, name); + return SharedPtr<FSDirectory>(new FSDirectory(node)); +} + +void FSDirectory::cacheDirectoryRecursive(FilesystemNode node, int depth, const String& prefix) { + if (depth <= 0) { + return; + } + + FSList list; + node.getChildren(list, FilesystemNode::kListAll, false); + + FSList::iterator it = list.begin(); + for ( ; it != list.end(); it++) { + String name = prefix + (*it).getName(); + + // don't touch name as it might be used for warning messages + String lowercaseName = name; + lowercaseName.toLowercase(); + + // since the hashmap is case insensitive, we need to check for clashes when caching + if ((*it).isDirectory()) { + if (_subDirCache.contains(lowercaseName)) { + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring sub-directory '%s'", name.c_str()); + } else { + cacheDirectoryRecursive(*it, depth - 1, lowercaseName + "/"); + _subDirCache[lowercaseName] = *it; + } + } else { + if (_fileCache.contains(lowercaseName)) { + warning("FSDirectory::cacheDirectory: name clash when building cache, ignoring file '%s'", name.c_str()); + } else { + _fileCache[lowercaseName] = *it; + } + } + } + +} + +int FSDirectory::matchPattern(StringList &list, const String &pattern) { + if (pattern.empty() || !_node.isDirectory()) { + return 0; + } + + if (!_cached) { + cacheDirectoryRecursive(_node, _depth, ""); + _cached = true; + } + + int matches = 0; + + // need to match lowercase key + String lowercasePattern = pattern; + lowercasePattern.toLowercase(); + + // Full *key* match, with path separators (backslashes) considered + // as normal characters. + NodeCache::iterator it = _fileCache.begin(); + for ( ; it != _fileCache.end(); it++) { + if (matchString((*it)._key.c_str(), lowercasePattern.c_str())) { + list.push_back((*it)._key.c_str()); + } + } + + return matches; +} + + + + + +SearchSet::SearchSet() { + +} + +SearchSet::~SearchSet() { + +} + +SearchSet::ArchiveList::iterator SearchSet::find(const String &name) const { + ArchiveList::iterator it = _list.begin(); + for ( ; it != _list.end(); it++) { + if ((*it)._name == name) { + break; + } + } + return it; +} + +/* + Keep the nodes sorted according to descending priorities. + In case two or node nodes have the same priority, insertion + order prevails. +*/ +void SearchSet::insert(const Node &node) { + ArchiveList::iterator it = _list.begin(); + for ( ; it != _list.end(); it++) { + if ((*it)._priority < node._priority) { + break; + } + } + _list.insert(it, node); +} + +void SearchSet::add(const String& name, ArchivePtr archive, uint priority) { + if (find(name) == _list.end()) { + Node node = { priority, name, archive }; + insert(node); + } else { + warning("SearchSet::add: archive '%s' already present", name.c_str()); + } + +} + +void SearchSet::remove(const String& name) { + ArchiveList::iterator it = find(name); + if (it != _list.end()) { + _list.erase(it); + } +} + +void SearchSet::clear() { + _list.clear(); +} + +void SearchSet::setPriority(const String& name, uint priority) { + ArchiveList::iterator it = find(name); + if (it == _list.end()) { + warning("SearchSet::setPriority: archive '%s' is not present", name.c_str()); + return; + } + + if (priority == (*it)._priority) { + return; + } + + Node node(*it); + _list.erase(it); + node._priority = priority; + insert(node); +} + +bool SearchSet::hasFile(const String &name) { + if (name.empty()) { + return false; + } + + ArchiveList::iterator it = _list.begin(); + for ( ; it != _list.end(); it++) { + if ((*it)._arc->hasFile(name)) { + return true; + } + } + + return false; +} + +int SearchSet::matchPattern(StringList &list, const String &pattern) { + // Shall we short circuit out if pattern is empty? + + int matches = 0; + + ArchiveList::iterator it = _list.begin(); + for ( ; it != _list.end(); it++) { + matches += (*it)._arc->matchPattern(list, pattern); + } + + return matches; +} + +FilePtr SearchSet::openFile(const String &name) { + if (name.empty()) { + return FilePtr(); + } + + ArchiveList::iterator it = _list.begin(); + for ( ; it != _list.end(); it++) { + if ((*it)._arc->hasFile(name)) { + return (*it)._arc->openFile(name); + } + } + + return FilePtr(); +} + + +} // namespace Common diff --git a/common/archive.h b/common/archive.h new file mode 100644 index 0000000000..636fb6383f --- /dev/null +++ b/common/archive.h @@ -0,0 +1,201 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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_ARCHIVES_H +#define COMMON_ARCHIVES_H + +#include "common/fs.h" +#include "common/str.h" +#include "common/hash-str.h" +#include "common/list.h" +#include "common/ptr.h" +#include "common/stream.h" + +namespace Common { + +typedef SharedPtr<SeekableReadStream> FilePtr; + +/** + * Archive allows searches of (file)names into an arbitrary container. + * It also supports opening a file and returning an usable input stream. + */ +class Archive { +public: + virtual ~Archive() { } + + /** + * Check if a name is present in the Archive. Patterns are not allowed, + * as this is meant to be a quick File::exists() replacement. + */ + virtual bool hasFile(const String &name) = 0; + + /** + * Add names to the provided list according to the pattern. Returned + * names can be used as parameters to fileOpen. + * Must not remove elements from the list. + * + * @return The number of names added to list. + */ + virtual int matchPattern(StringList &list, const String &pattern) = 0; + + /** + * Add all the names present in the Archive. Returned + * names can be used as parameters to fileOpen. + * Must not remove elements from the list. + * + * @return The number of names added to list. + */ + virtual int getAllNames(StringList &list) { + return matchPattern(list, "*"); + } + + /** + * Create a stream bound to a file in the archive. + * @return The newly created input stream. + */ + virtual FilePtr openFile(const String &name) = 0; +}; + + +typedef SharedPtr<Archive> ArchivePtr; + + +/** + * FSDirectory models a directory tree from the filesystem and allows users + * to access it through the Archive interface. FSDirectory can represent a + * single directory, or a tree with specified depth, rooted in a 'base' + * directory. + * Searching is case-insensitive, as the main intended goal is supporting + * retrieval of game data. First case-insensitive match is returned when + * searching, thus making FSDirectory heavily dependant on the underlying + * FilesystemNode implementation. + */ +class FSDirectory : public Archive { + FilesystemNode _node; + + // Caches are case insensitive, clashes are dealt with when creating + // Key is stored in lowercase. + typedef HashMap<String, FilesystemNode, IgnoreCase_Hash, IgnoreCase_EqualTo> NodeCache; + NodeCache _fileCache, _subDirCache; + + // look for a match + FilesystemNode lookupCache(NodeCache &cache, const String &name); + + // cache management + void cacheDirectoryRecursive(FilesystemNode node, int depth, const String& prefix); + bool _cached; + int _depth; + +public: + /** + * Create a FSDirectory representing a tree with the specified depth. Will result in an + * unbound FSDirectory if name is not found on the filesystem or is not a directory. + */ + FSDirectory(const String &name, int depth = 1); + + /** + * Create a FSDirectory representing a tree with the specified depth. Will result in an + * unbound FSDirectory if node does not exist or is not a directory. + */ + FSDirectory(const FilesystemNode &node, int depth = 1); + + virtual ~FSDirectory(); + + /** + * This return the underlying FSNode of the FSDirectory. + */ + FilesystemNode getFSNode() const; + + /** + * Create a new FSDirectory pointing to a sub directory of the instance. + * @return A new FSDirectory instance conveniently wrapped in a SharedPtr. + */ + SharedPtr<FSDirectory> getSubDirectory(const String &name); + + virtual bool hasFile(const String &name); + virtual int matchPattern(StringList &list, const String &pattern); + virtual FilePtr openFile(const String &name); +}; + + + +/** + * SearchSet enables access to a group of Archives through the Archive interface. + * Its intended usage is a situation in which there are no name clashes among names in the + * contained Archives, hence the simplistic policy of always looking for the first + * match. SearchSet *DOES* guarantee that searches are performed in *DESCENDING* + * priority order. In case of conflicting priorities, insertion order prevails. + */ + class SearchSet : public Archive { + struct Node { + uint _priority; + String _name; + ArchivePtr _arc; + }; + typedef List<Node> ArchiveList; + ArchiveList _list; + + ArchiveList::iterator find(const String &name) const; + + // Add an archive keeping the list sorted by ascending priorities. + void insert(const Node& node); + +public: + SearchSet(); + virtual ~SearchSet(); + + /** + * Add a new Archive to the searchable set. + */ + void add(const String& name, ArchivePtr archive, uint priority = 0); + + /** + * Remove an Archive from the searchable set. + */ + void remove(const String& name); + + /** + * Empties the searchable set. + */ + void clear(); + + /** + * Change the order of searches. + */ + void setPriority(const String& name, uint priority); + + virtual bool hasFile(const String &name); + virtual int matchPattern(StringList &list, const String &pattern); + + /** + * Implements openFile from Archive base class. The current policy is + * opening the first file encountered that matches the name. + */ + virtual FilePtr openFile(const String &name); +}; + +} // namespace Common + +#endif diff --git a/common/array.h b/common/array.h index 854ce5b91d..693c024d11 100644 --- a/common/array.h +++ b/common/array.h @@ -35,7 +35,7 @@ class Array { protected: uint _capacity; uint _size; - T *_data; + T *_storage; public: typedef T *iterator; @@ -44,41 +44,41 @@ public: typedef T value_type; public: - Array() : _capacity(0), _size(0), _data(0) {} - Array(const Array<T> &array) : _capacity(0), _size(0), _data(0) { + Array() : _capacity(0), _size(0), _storage(0) {} + Array(const Array<T> &array) : _capacity(0), _size(0), _storage(0) { _size = array._size; _capacity = _size + 32; - _data = new T[_capacity]; - copy(array._data, array._data + _size, _data); + _storage = new T[_capacity]; + copy(array._storage, array._storage + _size, _storage); } ~Array() { - delete[] _data; + delete[] _storage; } void push_back(const T &element) { ensureCapacity(_size + 1); - _data[_size++] = element; + _storage[_size++] = element; } void push_back(const Array<T> &array) { ensureCapacity(_size + array._size); - copy(array._data, array._data + array._size, _data + _size); + copy(array._storage, array._storage + array._size, _storage + _size); _size += array._size; } void insert_at(int idx, const T &element) { assert(idx >= 0 && (uint)idx <= _size); ensureCapacity(_size + 1); - copy_backward(_data + idx, _data + _size, _data + _size + 1); - _data[idx] = element; + copy_backward(_storage + idx, _storage + _size, _storage + _size + 1); + _storage[idx] = element; _size++; } T remove_at(int idx) { assert(idx >= 0 && (uint)idx < _size); - T tmp = _data[idx]; - copy(_data + idx + 1, _data + _size, _data + idx); + T tmp = _storage[idx]; + copy(_storage + idx + 1, _storage + _size, _storage + idx); _size--; return tmp; } @@ -87,23 +87,23 @@ public: T& operator[](int idx) { assert(idx >= 0 && (uint)idx < _size); - return _data[idx]; + return _storage[idx]; } const T& operator[](int idx) const { assert(idx >= 0 && (uint)idx < _size); - return _data[idx]; + return _storage[idx]; } Array<T>& operator=(const Array<T> &array) { if (this == &array) return *this; - delete[] _data; + delete[] _storage; _size = array._size; _capacity = _size + 32; - _data = new T[_capacity]; - copy(array._data, array._data + _size, _data); + _storage = new T[_capacity]; + copy(array._storage, array._storage + _size, _storage); return *this; } @@ -113,8 +113,8 @@ public: } void clear() { - delete[] _data; - _data = 0; + delete[] _storage; + _storage = 0; _size = 0; _capacity = 0; } @@ -125,33 +125,33 @@ public: iterator begin() { - return _data; + return _storage; } iterator end() { - return _data + _size; + return _storage + _size; } const_iterator begin() const { - return _data; + return _storage; } const_iterator end() const { - return _data + _size; + return _storage + _size; } void reserve(uint newCapacity) { if (newCapacity <= _capacity) return; - T *old_data = _data; + T *old_storage = _storage; _capacity = newCapacity; - _data = new T[newCapacity]; + _storage = new T[newCapacity]; - if (old_data) { + if (old_storage) { // Copy old data - copy(old_data, old_data + _size, _data); - delete[] old_data; + copy(old_storage, old_storage + _size, _storage); + delete[] old_storage; } } @@ -159,14 +159,14 @@ public: if (newSize == _size) return; - T *old_data = _data; + T *old_storage = _storage; _capacity = newSize; - _data = new T[newSize]; - if (old_data) { + _storage = new T[newSize]; + if (old_storage) { // Copy old data int cnt = (_size < newSize ? _size : newSize); - copy(old_data, old_data + cnt, _data); - delete[] old_data; + copy(old_storage, old_storage + cnt, _storage); + delete[] old_storage; } _size = newSize; } diff --git a/common/config-file.cpp b/common/config-file.cpp index 9f54c9ddde..42d67109fa 100644 --- a/common/config-file.cpp +++ b/common/config-file.cpp @@ -225,7 +225,7 @@ bool ConfigFile::saveToStream(WriteStream &stream) { void ConfigFile::removeSection(const String §ion) { assert(isValidName(section)); for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { - if (!scumm_stricmp(section.c_str(), i->name.c_str())) { + if (section.equalsIgnoreCase(i->name)) { _sections.erase(i); return; } @@ -318,7 +318,7 @@ const ConfigFile::SectionKeyList ConfigFile::getKeys(const String §ion) cons ConfigFile::Section *ConfigFile::getSection(const String §ion) { for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { - if (!scumm_stricmp(section.c_str(), i->name.c_str())) { + if (section.equalsIgnoreCase(i->name)) { return &(*i); } } @@ -327,7 +327,7 @@ ConfigFile::Section *ConfigFile::getSection(const String §ion) { const ConfigFile::Section *ConfigFile::getSection(const String §ion) const { for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) { - if (!scumm_stricmp(section.c_str(), i->name.c_str())) { + if (section.equalsIgnoreCase(i->name)) { return &(*i); } } @@ -340,7 +340,7 @@ bool ConfigFile::Section::hasKey(const String &key) const { const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const { for (List<KeyValue>::const_iterator i = keys.begin(); i != keys.end(); ++i) { - if (!scumm_stricmp(key.c_str(), i->key.c_str())) { + if (key.equalsIgnoreCase(i->key)) { return &(*i); } } @@ -349,7 +349,7 @@ const ConfigFile::KeyValue* ConfigFile::Section::getKey(const String &key) const void ConfigFile::Section::setKey(const String &key, const String &value) { for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) { - if (!scumm_stricmp(key.c_str(), i->key.c_str())) { + if (key.equalsIgnoreCase(i->key)) { i->value = value; return; } @@ -363,7 +363,7 @@ void ConfigFile::Section::setKey(const String &key, const String &value) { void ConfigFile::Section::removeKey(const String &key) { for (List<KeyValue>::iterator i = keys.begin(); i != keys.end(); ++i) { - if (!scumm_stricmp(key.c_str(), i->key.c_str())) { + if (key.equalsIgnoreCase(i->key)) { keys.erase(i); return; } diff --git a/common/fs.cpp b/common/fs.cpp index 3f585c6038..429d388ad1 100644 --- a/common/fs.cpp +++ b/common/fs.cpp @@ -52,7 +52,7 @@ bool FilesystemNode::operator<(const FilesystemNode& node) const { if (isDirectory() != node.isDirectory()) return isDirectory(); - return scumm_stricmp(getDisplayName().c_str(), node.getDisplayName().c_str()) < 0; + return getDisplayName().compareToIgnoreCase(node.getDisplayName()) < 0; } bool FilesystemNode::exists() const { diff --git a/common/hash-str.h b/common/hash-str.h index f64b62daed..40557037e7 100644 --- a/common/hash-str.h +++ b/common/hash-str.h @@ -39,7 +39,7 @@ inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str()); // FIXME: The following functors obviously are not consistently named struct CaseSensitiveString_EqualTo { - bool operator()(const String& x, const String& y) const { return strcmp(x.c_str(), y.c_str()) == 0; } + bool operator()(const String& x, const String& y) const { return x.equals(y); } }; struct CaseSensitiveString_Hash { @@ -48,7 +48,7 @@ struct CaseSensitiveString_Hash { struct IgnoreCase_EqualTo { - bool operator()(const String& x, const String& y) const { return scumm_stricmp(x.c_str(), y.c_str()) == 0; } + bool operator()(const String& x, const String& y) const { return x.equalsIgnoreCase(y); } }; struct IgnoreCase_Hash { diff --git a/common/hashmap.cpp b/common/hashmap.cpp index 4749234740..99ca0713ee 100644 --- a/common/hashmap.cpp +++ b/common/hashmap.cpp @@ -89,5 +89,36 @@ uint nextTableSize(uint x) { return primes[i]; } +#ifdef DEBUG_HASH_COLLISIONS +static double + g_collisions = 0, + g_lookups = 0, + g_collPerLook = 0, + g_capacity = 0, + g_size = 0; +static int g_max_capacity = 0, g_max_size = 0; +static int g_totalHashmaps = 0; + +void updateHashCollisionStats(int collisions, int lookups, int arrsize, int nele) { + g_collisions += collisions; + g_lookups += lookups; + if (lookups) + g_collPerLook += (double)collisions / (double)lookups; + g_capacity += arrsize; + g_size += nele; + g_totalHashmaps++; + + g_max_capacity = MAX(g_max_capacity, arrsize); + g_max_size = MAX(g_max_size, nele); + + fprintf(stdout, "%d hashmaps: colls %.1f; lookups %.1f; ratio %.3f%%; size %f (max: %d); capacity %f (max: %d)\n", + g_totalHashmaps, + g_collisions / g_totalHashmaps, + g_lookups / g_totalHashmaps, + 100 * g_collPerLook / g_totalHashmaps, + g_size / g_totalHashmaps, g_max_size, + g_capacity / g_totalHashmaps, g_max_capacity); +} +#endif } // End of namespace Common diff --git a/common/hashmap.h b/common/hashmap.h index 69f367de97..980e03aa6e 100644 --- a/common/hashmap.h +++ b/common/hashmap.h @@ -136,8 +136,9 @@ public: } #endif - Node **_arr; // hashtable of size arrsize. - uint _arrsize, _nele; + Node **_storage; // hashtable of size arrsize. + uint _capacity; + uint _size; HashFunc _hash; EqualFunc _equal; @@ -174,8 +175,8 @@ public: NodeType *deref() const { assert(_hashmap != 0); - assert(_idx < _hashmap->_arrsize); - Node *node = _hashmap->_arr[_idx]; + assert(_idx < _hashmap->_capacity); + Node *node = _hashmap->_storage[_idx]; assert(node != 0); return node; } @@ -195,8 +196,8 @@ public: assert(_hashmap); do { _idx++; - } while (_idx < _hashmap->_arrsize && _hashmap->_arr[_idx] == 0); - if (_idx >= _hashmap->_arrsize) + } while (_idx < _hashmap->_capacity && _hashmap->_storage[_idx] == 0); + if (_idx >= _hashmap->_capacity) _idx = (uint)-1; return *this; @@ -223,7 +224,7 @@ public: // Remove the previous content and ... clear(); - delete[] _arr; + delete[] _storage; // ... copy the new stuff. assign(map); return *this; @@ -242,12 +243,12 @@ public: void erase(const Key &key); - uint size() const { return _nele; } + uint size() const { return _size; } iterator begin() { // Find and return the _key non-empty entry - for (uint ctr = 0; ctr < _arrsize; ++ctr) { - if (_arr[ctr]) + for (uint ctr = 0; ctr < _capacity; ++ctr) { + if (_storage[ctr]) return iterator(ctr, this); } return end(); @@ -258,8 +259,8 @@ public: const_iterator begin() const { // Find and return the first non-empty entry - for (uint ctr = 0; ctr < _arrsize; ++ctr) { - if (_arr[ctr]) + for (uint ctr = 0; ctr < _capacity; ++ctr) { + if (_storage[ctr]) return const_iterator(ctr, this); } return end(); @@ -270,14 +271,14 @@ public: iterator find(const Key &key) { uint ctr = lookup(key); - if (_arr[ctr]) + if (_storage[ctr]) return iterator(ctr, this); return end(); } const_iterator find(const Key &key) const { uint ctr = lookup(key); - if (_arr[ctr]) + if (_storage[ctr]) return const_iterator(ctr, this); return end(); } @@ -285,7 +286,7 @@ public: // TODO: insert() method? bool empty() const { - return (_nele == 0); + return (_size == 0); } }; @@ -301,12 +302,12 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap() : _nodePool(sizeof(Node)), #endif _defaultVal() { - _arrsize = nextTableSize(0); - _arr = new Node *[_arrsize]; - assert(_arr != NULL); - memset(_arr, 0, _arrsize * sizeof(Node *)); + _capacity = nextTableSize(0); + _storage = new Node *[_capacity]; + assert(_storage != NULL); + memset(_storage, 0, _capacity * sizeof(Node *)); - _nele = 0; + _size = 0; #ifdef DEBUG_HASH_COLLISIONS _collisions = 0; @@ -333,11 +334,15 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap(const HM_t &map) : */ template<class Key, class Val, class HashFunc, class EqualFunc> HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { - for (uint ctr = 0; ctr < _arrsize; ++ctr) - if (_arr[ctr] != NULL) - freeNode(_arr[ctr]); + for (uint ctr = 0; ctr < _capacity; ++ctr) + if (_storage[ctr] != NULL) + freeNode(_storage[ctr]); - delete[] _arr; + delete[] _storage; +#ifdef DEBUG_HASH_COLLISIONS + extern void updateHashCollisionStats(int, int, int, int); + updateHashCollisionStats(_collisions, _lookups, _capacity, _size); +#endif } /** @@ -349,95 +354,95 @@ HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() { */ template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) { - _arrsize = map._arrsize; - _arr = new Node *[_arrsize]; - assert(_arr != NULL); - memset(_arr, 0, _arrsize * sizeof(Node *)); + _capacity = map._capacity; + _storage = new Node *[_capacity]; + assert(_storage != NULL); + memset(_storage, 0, _capacity * sizeof(Node *)); // Simply clone the map given to us, one by one. - _nele = 0; - for (uint ctr = 0; ctr < _arrsize; ++ctr) { - if (map._arr[ctr] != NULL) { - _arr[ctr] = allocNode(map._arr[ctr]->_key); - _arr[ctr]->_value = map._arr[ctr]->_value; - _nele++; + _size = 0; + for (uint ctr = 0; ctr < _capacity; ++ctr) { + if (map._storage[ctr] != NULL) { + _storage[ctr] = allocNode(map._storage[ctr]->_key); + _storage[ctr]->_value = map._storage[ctr]->_value; + _size++; } } // Perform a sanity check (to help track down hashmap corruption) - assert(_nele == map._nele); + assert(_size == map._size); } template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) { - for (uint ctr = 0; ctr < _arrsize; ++ctr) { - if (_arr[ctr] != NULL) { - freeNode(_arr[ctr]); - _arr[ctr] = NULL; + for (uint ctr = 0; ctr < _capacity; ++ctr) { + if (_storage[ctr] != NULL) { + freeNode(_storage[ctr]); + _storage[ctr] = NULL; } } - if (shrinkArray && _arrsize > nextTableSize(0)) { - delete[] _arr; + if (shrinkArray && _capacity > nextTableSize(0)) { + delete[] _storage; - _arrsize = nextTableSize(0); - _arr = new Node *[_arrsize]; - assert(_arr != NULL); - memset(_arr, 0, _arrsize * sizeof(Node *)); + _capacity = nextTableSize(0); + _storage = new Node *[_capacity]; + assert(_storage != NULL); + memset(_storage, 0, _capacity * sizeof(Node *)); } - _nele = 0; + _size = 0; } template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::expand_array(uint newsize) { - assert(newsize > _arrsize); + assert(newsize > _capacity); uint ctr, dex; - const uint old_nele = _nele; - const uint old_arrsize = _arrsize; - Node **old_arr = _arr; + const uint old_size = _size; + const uint old_capacity = _capacity; + Node **old_storage = _storage; // allocate a new array - _nele = 0; - _arrsize = newsize; - _arr = new Node *[_arrsize]; - assert(_arr != NULL); - memset(_arr, 0, _arrsize * sizeof(Node *)); + _size = 0; + _capacity = newsize; + _storage = new Node *[_capacity]; + assert(_storage != NULL); + memset(_storage, 0, _capacity * sizeof(Node *)); // rehash all the old elements - for (ctr = 0; ctr < old_arrsize; ++ctr) { - if (old_arr[ctr] == NULL) + for (ctr = 0; ctr < old_capacity; ++ctr) { + if (old_storage[ctr] == NULL) continue; // Insert the element from the old table into the new table. // Since we know that no key exists twice in the old table, we // can do this slightly better than by calling lookup, since we // don't have to call _equal(). - dex = _hash(old_arr[ctr]->_key) % _arrsize; - while (_arr[dex] != NULL) { - dex = (dex + 1) % _arrsize; + dex = _hash(old_storage[ctr]->_key) % _capacity; + while (_storage[dex] != NULL) { + dex = (dex + 1) % _capacity; } - _arr[dex] = old_arr[ctr]; - _nele++; + _storage[dex] = old_storage[ctr]; + _size++; } // Perform a sanity check: Old number of elements should match the new one! // This check will fail if some previous operation corrupted this hashmap. - assert(_nele == old_nele); + assert(_size == old_size); - delete[] old_arr; + delete[] old_storage; return; } template<class Key, class Val, class HashFunc, class EqualFunc> int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { - uint ctr = _hash(key) % _arrsize; + uint ctr = _hash(key) % _capacity; - while (_arr[ctr] != NULL && !_equal(_arr[ctr]->_key, key)) { - ctr = (ctr + 1) % _arrsize; + while (_storage[ctr] != NULL && !_equal(_storage[ctr]->_key, key)) { + ctr = (ctr + 1) % _capacity; #ifdef DEBUG_HASH_COLLISIONS _collisions++; @@ -448,7 +453,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookup(const Key &key) const { _lookups++; fprintf(stderr, "collisions %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d\n", _collisions, _lookups, ((double) _collisions / (double)_lookups), - (const void *)this, _arrsize, _nele); + (const void *)this, _capacity, _size); #endif return ctr; @@ -458,13 +463,13 @@ template<class Key, class Val, class HashFunc, class EqualFunc> int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key &key) { uint ctr = lookup(key); - if (_arr[ctr] == NULL) { - _arr[ctr] = allocNode(key); - _nele++; + if (_storage[ctr] == NULL) { + _storage[ctr] = allocNode(key); + _size++; // Keep the load factor below 75%. - if (_nele > _arrsize * 75 / 100) { - expand_array(nextTableSize(_arrsize)); + if (_size > _capacity * 75 / 100) { + expand_array(nextTableSize(_capacity)); ctr = lookup(key); } } @@ -476,7 +481,7 @@ int HashMap<Key, Val, HashFunc, EqualFunc>::lookupAndCreateIfMissing(const Key & template<class Key, class Val, class HashFunc, class EqualFunc> bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const { uint ctr = lookup(key); - return (_arr[ctr] != NULL); + return (_storage[ctr] != NULL); } template<class Key, class Val, class HashFunc, class EqualFunc> @@ -492,15 +497,15 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) co template<class Key, class Val, class HashFunc, class EqualFunc> Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) { uint ctr = lookupAndCreateIfMissing(key); - assert(_arr[ctr] != NULL); - return _arr[ctr]->_value; + assert(_storage[ctr] != NULL); + return _storage[ctr]->_value; } template<class Key, class Val, class HashFunc, class EqualFunc> const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const { uint ctr = lookup(key); - if (_arr[ctr] != NULL) - return _arr[ctr]->_value; + if (_storage[ctr] != NULL) + return _storage[ctr]->_value; else return _defaultVal; } @@ -508,38 +513,38 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) { uint ctr = lookupAndCreateIfMissing(key); - assert(_arr[ctr] != NULL); - _arr[ctr]->_value = val; + assert(_storage[ctr] != NULL); + _storage[ctr]->_value = val; } template<class Key, class Val, class HashFunc, class EqualFunc> void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) { // This is based on code in the Wikipedia article on Hash tables. uint i = lookup(key); - if (_arr[i] == NULL) + if (_storage[i] == NULL) return; // key wasn't present, so no work has to be done // If we remove a key, we must check all subsequent keys and possibly // reinsert them. uint j = i; - freeNode(_arr[i]); - _arr[i] = NULL; + freeNode(_storage[i]); + _storage[i] = NULL; while (true) { // Look at the next table slot - j = (j + 1) % _arrsize; + j = (j + 1) % _capacity; // If the next slot is empty, we are done - if (_arr[j] == NULL) + if (_storage[j] == NULL) break; // Compute the slot where the content of the next slot should normally be, // assuming an empty table, and check whether we have to move it. - uint k = _hash(_arr[j]->_key) % _arrsize; + uint k = _hash(_storage[j]->_key) % _capacity; if ((j > i && (k <= i || k > j)) || (j < i && (k <= i && k > j)) ) { - _arr[i] = _arr[j]; + _storage[i] = _storage[j]; i = j; } } - _arr[i] = NULL; - _nele--; + _storage[i] = NULL; + _size--; return; } diff --git a/common/keyboard.h b/common/keyboard.h index fbbc289a3b..93579cbed6 100644 --- a/common/keyboard.h +++ b/common/keyboard.h @@ -178,10 +178,7 @@ enum KeyCode { KEYCODE_MENU = 319, KEYCODE_POWER = 320, // Power Macintosh power key KEYCODE_EURO = 321, // Some european keyboards - KEYCODE_UNDO = 322, // Atari keyboard has Undo - - // Global Main Menu key - KEYCODE_MAINMENU = KEYCODE_F6 + KEYCODE_UNDO = 322 // Atari keyboard has Undo }; /** diff --git a/common/module.mk b/common/module.mk index c3f2a38c3f..599ffcf8a6 100644 --- a/common/module.mk +++ b/common/module.mk @@ -2,6 +2,7 @@ MODULE := common MODULE_OBJS := \ advancedDetector.o \ + archive.o \ config-file.o \ config-manager.o \ file.o \ diff --git a/common/queue.h b/common/queue.h index 51d56ed54b..f1881345e8 100644 --- a/common/queue.h +++ b/common/queue.h @@ -31,39 +31,62 @@ namespace Common { /** - * Variable size Queue class, implemented using our Array class. + * Variable size Queue class, implemented using our List class. */ template<class T> class Queue { -protected: - List<T> _queue; public: - Queue<T>() {} - Queue<T>(const List<T> &queueContent) : _queue(queueContent) {} + typedef T value_type; + +public: + Queue<T>() : _impl() {} + Queue<T>(const Queue<T> &queue) : _impl(queue._impl) {} + + Queue<T> &operator=(const Queue<T> &queue) { + _impl = queue._impl; + return *this; + } bool empty() const { - return _queue.empty(); + return _impl.empty(); } + void clear() { - _queue.clear(); + _impl.clear(); } + void push(const T &x) { - _queue.push_back(x); + _impl.push_back(x); } - T back() const { - return _queue.reverse_begin().operator*(); + + T &front() { + return *_impl.begin(); } - T front() const { - return _queue.begin().operator*(); + + const T &front() const { + return *_impl.begin(); } + + T &back() { + return *_impl.reverse_begin(); + } + + const T &back() const { + return *_impl.reverse_begin(); + } + T pop() { T tmp = front(); - _queue.pop_front(); + _impl.pop_front(); return tmp; } + int size() const { - return _queue.size(); + return _impl.size(); } + +private: + List<T> _impl; }; } // End of namespace Common diff --git a/common/str.cpp b/common/str.cpp index 5f8d4ffb7e..c254d4bbc8 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -43,19 +43,19 @@ static int computeCapacity(int len) { return ((len + 32 - 1) & ~0x1F) - 1; } -String::String(const char *str) : _len(0), _str(_storage) { +String::String(const char *str) : _size(0), _str(_storage) { if (str == 0) { _storage[0] = 0; - _len = 0; + _size = 0; } else initWithCStr(str, strlen(str)); } -String::String(const char *str, uint32 len) : _len(0), _str(_storage) { +String::String(const char *str, uint32 len) : _size(0), _str(_storage) { initWithCStr(str, len); } -String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) { +String::String(const char *beginP, const char *endP) : _size(0), _str(_storage) { assert(endP >= beginP); initWithCStr(beginP, endP - beginP); } @@ -67,7 +67,7 @@ void String::initWithCStr(const char *str, uint32 len) { // for GCC 2.95.x compatibility (see also tracker item #1602879). _storage[0] = 0; - _len = len; + _size = len; if (len >= _builtinCapacity) { // Not enough internal storage, so allocate more @@ -83,7 +83,7 @@ void String::initWithCStr(const char *str, uint32 len) { } String::String(const String &str) - : _len(str._len), _str(str.isStorageIntern() ? _storage : str._str) { + : _size(str._size), _str(str.isStorageIntern() ? _storage : str._str) { if (str.isStorageIntern()) { // String in internal storage: just copy it memcpy(_storage, str._storage, _builtinCapacity); @@ -97,14 +97,14 @@ String::String(const String &str) } String::String(char c) -: _len(0), _str(_storage) { +: _size(0), _str(_storage) { _storage[0] = c; _storage[1] = 0; // TODO/FIXME: There is no reason for the following check -- we *do* // allow strings to contain 0 bytes! - _len = (c == 0) ? 0 : 1; + _size = (c == 0) ? 0 : 1; } String::~String() { @@ -112,16 +112,16 @@ String::~String() { } void String::makeUnique() { - ensureCapacity(_len, true); + ensureCapacity(_size, true); } /** - * Ensure that enough storage is available to store at least new_len + * Ensure that enough storage is available to store at least new_size * characters plus a null byte. In addition, if we currently share * the storage with another string, unshare it, so that we can safely * write to the storage. */ -void String::ensureCapacity(uint32 new_len, bool keep_old) { +void String::ensureCapacity(uint32 new_size, bool keep_old) { bool isShared; uint32 curCapacity, newCapacity; char *newStorage; @@ -137,10 +137,10 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) { // Special case: If there is enough space, and we do not share // the storage, then there is nothing to do. - if (!isShared && new_len <= curCapacity) + if (!isShared && new_size <= curCapacity) return; - if (isShared && new_len <= _builtinCapacity - 1) { + if (isShared && new_size <= _builtinCapacity - 1) { // We share the storage, but there is enough internal storage: Use that. newStorage = _storage; newCapacity = _builtinCapacity - 1; @@ -148,7 +148,7 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) { // We need to allocate storage on the heap! // Compute a suitable new capacity limit - newCapacity = computeCapacity(new_len); + newCapacity = computeCapacity(new_size); // Allocate new storage newStorage = (char *)malloc(newCapacity+1); @@ -157,10 +157,10 @@ void String::ensureCapacity(uint32 new_len, bool keep_old) { // Copy old data if needed, elsewise reset the new storage. if (keep_old) { - assert(_len <= newCapacity); - memcpy(newStorage, _str, _len + 1); + assert(_size <= newCapacity); + memcpy(newStorage, _str, _size + 1); } else { - _len = 0; + _size = 0; newStorage[0] = 0; } @@ -210,7 +210,7 @@ void String::decRefCount(int *oldRefCount) { String& String::operator =(const char *str) { uint32 len = strlen(str); ensureCapacity(len, false); - _len = len; + _size = len; memmove(_str, str, len + 1); return *this; } @@ -221,16 +221,16 @@ String &String::operator =(const String &str) { if (str.isStorageIntern()) { decRefCount(_extern._refCount); - _len = str._len; + _size = str._size; _str = _storage; - memcpy(_str, str._str, _len + 1); + memcpy(_str, str._str, _size + 1); } else { str.incRefCount(); decRefCount(_extern._refCount); _extern._refCount = str._extern._refCount; _extern._capacity = str._extern._capacity; - _len = str._len; + _size = str._size; _str = str._str; } @@ -240,7 +240,7 @@ String &String::operator =(const String &str) { String& String::operator =(char c) { decRefCount(_extern._refCount); _str = _storage; - _len = 1; + _size = 1; _str[0] = c; _str[1] = 0; return *this; @@ -249,30 +249,30 @@ String& String::operator =(char c) { String &String::operator +=(const char *str) { int len = strlen(str); if (len > 0) { - ensureCapacity(_len + len, true); + ensureCapacity(_size + len, true); - memcpy(_str + _len, str, len + 1); - _len += len; + memcpy(_str + _size, str, len + 1); + _size += len; } return *this; } String &String::operator +=(const String &str) { - int len = str._len; + int len = str._size; if (len > 0) { - ensureCapacity(_len + len, true); + ensureCapacity(_size + len, true); - memcpy(_str + _len, str._str, len + 1); - _len += len; + memcpy(_str + _size, str._str, len + 1); + _size += len; } return *this; } String &String::operator +=(char c) { - ensureCapacity(_len + 1, true); + ensureCapacity(_size + 1, true); - _str[_len++] = c; - _str[_len] = 0; + _str[_size++] = c; + _str[_size] = 0; return *this; } @@ -293,10 +293,10 @@ bool String::hasPrefix(const char *x) const { bool String::hasSuffix(const char *x) const { assert(x != 0); // Compare x with the end of _str. - const uint32 x_len = strlen(x); - if (x_len > _len) + const uint32 x_size = strlen(x); + if (x_size > _size) return false; - const char *y = c_str() + _len - x_len; + const char *y = c_str() + _size - x_size; while (*x && *x == *y) { ++x; ++y; @@ -316,65 +316,65 @@ bool String::contains(char x) const { } void String::deleteLastChar() { - deleteChar(_len - 1); + deleteChar(_size - 1); } void String::deleteChar(uint32 p) { - assert(p < _len); + assert(p < _size); makeUnique(); - while (p++ < _len) + while (p++ < _size) _str[p-1] = _str[p]; - _len--; + _size--; } void String::clear() { decRefCount(_extern._refCount); - _len = 0; + _size = 0; _str = _storage; _storage[0] = 0; } void String::setChar(char c, uint32 p) { - assert(p <= _len); + assert(p <= _size); makeUnique(); _str[p] = c; } void String::insertChar(char c, uint32 p) { - assert(p <= _len); + assert(p <= _size); - ensureCapacity(_len + 1, true); - _len++; - for (uint32 i = _len; i > p; --i) + ensureCapacity(_size + 1, true); + _size++; + for (uint32 i = _size; i > p; --i) _str[i] = _str[i-1]; _str[p] = c; } void String::toLowercase() { makeUnique(); - for (uint32 i = 0; i < _len; ++i) + for (uint32 i = 0; i < _size; ++i) _str[i] = tolower(_str[i]); } void String::toUppercase() { makeUnique(); - for (uint32 i = 0; i < _len; ++i) + for (uint32 i = 0; i < _size; ++i) _str[i] = toupper(_str[i]); } void String::trim() { - if (_len == 0) + if (_size == 0) return; makeUnique(); // Trim trailing whitespace - while (_len >= 1 && isspace(_str[_len-1])) - _len--; - _str[_len] = 0; + while (_size >= 1 && isspace(_str[_size-1])) + _size--; + _str[_size] = 0; // Trim leading whitespace char *t = _str; @@ -382,8 +382,8 @@ void String::trim() { t++; if (t != _str) { - _len -= t - _str; - memmove(_str, t, _len + 1); + _size -= t - _str; + memmove(_str, t, _size + 1); } } diff --git a/common/str.h b/common/str.h index 3479fee8e4..663a819e70 100644 --- a/common/str.h +++ b/common/str.h @@ -61,7 +61,7 @@ protected: * a lot. Yes, we limit ourselves to strings shorter than 4GB -- * on purpose :-). */ - uint32 _len; + uint32 _size; /** * Pointer to the actual string storage. Either points to _storage, @@ -97,7 +97,7 @@ public: #endif /** Construct a new empty string. */ - String() : _len(0), _str(_storage) { _storage[0] = 0; } + String() : _size(0), _str(_storage) { _storage[0] = 0; } /** Construct a new string from the given NULL-terminated C string. */ String(const char *str); @@ -150,13 +150,13 @@ public: bool contains(char x) const; inline const char *c_str() const { return _str; } - inline uint size() const { return _len; } + inline uint size() const { return _size; } - inline bool empty() const { return (_len == 0); } - char lastChar() const { return (_len > 0) ? _str[_len-1] : 0; } + inline bool empty() const { return (_size == 0); } + char lastChar() const { return (_size > 0) ? _str[_size-1] : 0; } char operator [](int idx) const { - assert(_str && idx >= 0 && idx < (int)_len); + assert(_str && idx >= 0 && idx < (int)_size); return _str[idx]; } @@ -203,7 +203,7 @@ public: protected: void makeUnique(); - void ensureCapacity(uint32 new_len, bool keep_old); + void ensureCapacity(uint32 new_size, bool keep_old); void incRefCount() const; void decRefCount(int *oldRefCount); void initWithCStr(const char *str, uint32 len); @@ -218,7 +218,7 @@ String operator +(const String &x, const char *y); String operator +(const String &x, char y); String operator +(char x, const String &y); -// Some useful additional comparision operators for Strings +// Some useful additional comparison operators for Strings bool operator == (const char *x, const String &y); bool operator != (const char *x, const String &y); @@ -230,13 +230,11 @@ extern char *trim(char *t); class StringList : public Array<String> { public: void push_back(const char *str) { - ensureCapacity(_size + 1); - _data[_size++] = str; + Array<String>::push_back(str); } void push_back(const String &str) { - ensureCapacity(_size + 1); - _data[_size++] = str; + Array<String>::push_back(str); } }; diff --git a/common/util.cpp b/common/util.cpp index 6f0fdcb233..316f2e39c3 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -237,10 +237,9 @@ Language parseLanguage(const String &str) { if (str.empty()) return UNK_LANG; - const char *s = str.c_str(); const LanguageDescription *l = g_languages; for (; l->code; ++l) { - if (!scumm_stricmp(l->code, s)) + if (str.equalsIgnoreCase(l->code)) return l->id; } @@ -299,20 +298,18 @@ Platform parsePlatform(const String &str) { if (str.empty()) return kPlatformUnknown; - const char *s = str.c_str(); - // Handle some special case separately, for compatibility with old config // files. - if (!strcmp(s, "1")) + if (str == "1") return kPlatformAmiga; - else if (!strcmp(s, "2")) + else if (str == "2") return kPlatformAtariST; - else if (!strcmp(s, "3")) + else if (str == "3") return kPlatformMacintosh; const PlatformDescription *l = g_platforms; for (; l->code; ++l) { - if (!scumm_stricmp(l->code, s) || !scumm_stricmp(l->code2, s) || !scumm_stricmp(l->abbrev, s)) + if (str.equalsIgnoreCase(l->code) || str.equalsIgnoreCase(l->code2) || str.equalsIgnoreCase(l->abbrev)) return l->id; } @@ -364,10 +361,9 @@ RenderMode parseRenderMode(const String &str) { if (str.empty()) return kRenderDefault; - const char *s = str.c_str(); const RenderModeDescription *l = g_renderModes; for (; l->code; ++l) { - if (!scumm_stricmp(l->code, s)) + if (str.equalsIgnoreCase(l->code)) return l->id; } |