GRIM: Cleanup Lab file parsing

Common::String's are used directly now (instead of changing back to c-strings half the time) and a hashmap now holds the data.
This commit is contained in:
Matthew Hoops 2011-03-24 22:45:26 +08:00 committed by Pawel Kolodziejski
parent 5f2056068f
commit 4e2781c41e
3 changed files with 60 additions and 85 deletions

View File

@ -31,17 +31,13 @@
namespace Grim {
static int sortCallback(const void *entry1, const void *entry2) {
return strcasecmp(((Lab::LabEntry *)entry1)->filename, ((Lab::LabEntry *)entry2)->filename);
}
bool Lab::open(const char *filename) {
bool Lab::open(const Common::String &filename) {
_labFileName = filename;
close();
_f = new Common::File();
_f->open(filename);
if (!_f->isOpen())
if (!_f->open(filename))
return false;
char header[16];
@ -51,64 +47,60 @@ bool Lab::open(const char *filename) {
return false;
}
_numEntries = READ_LE_UINT32(header + 8);
uint32 entryCount = READ_LE_UINT32(header + 8);
int string_table_size = READ_LE_UINT32(header + 12);
char *string_table = new char[string_table_size];
_f->seek(16 * (_numEntries + 1), SEEK_SET);
_f->seek(16 * (entryCount + 1));
_f->read(string_table, string_table_size);
_f->seek(16);
_entries = new LabEntry[_numEntries];
_f->seek(16, SEEK_SET);
char binary_entry[16];
for (int i = 0; i < _numEntries; i++) {
_f->read(binary_entry, 16);
int fname_offset = READ_LE_UINT32(binary_entry);
int start = READ_LE_UINT32(binary_entry + 4);
int size = READ_LE_UINT32(binary_entry + 8);
for (uint32 i = 0; i < entryCount; i++) {
int fname_offset = _f->readUint32LE();
int start = _f->readUint32LE();
int size = _f->readUint32LE();
_f->readUint32LE();
Common::String fname = string_table + fname_offset;
fname.toLowercase();
_entries[i].offset = start;
_entries[i].len = size;
_entries[i].filename = new char[fname.size() + 1];
strcpy(_entries[i].filename, fname.c_str());
LabEntry entry;
entry.offset = start;
entry.len = size;
_entries[fname] = entry;
}
qsort(_entries, _numEntries, sizeof(LabEntry), sortCallback);
delete[] string_table;
return true;
}
bool Lab::fileExists(const char *filename) const {
return findFilename(filename) != NULL;
bool Lab::fileExists(const Common::String &filename) const {
return _entries.contains(filename);
}
bool Lab::isOpen() const {
return _f && _f->isOpen();
}
Block *Lab::getFileBlock(const char *filename) const {
LabEntry *i = findFilename(filename);
if (!i)
return NULL;
Block *Lab::getFileBlock(const Common::String &filename) const {
if (!fileExists(filename))
return 0;
_f->seek(i->offset, SEEK_SET);
char *data = new char[i->len];
_f->read(data, i->len);
return new Block(data, i->len);
const LabEntry &i = _entries[filename];
_f->seek(i.offset, SEEK_SET);
char *data = new char[i.len];
_f->read(data, i.len);
return new Block(data, i.len);
}
LuaFile *Lab::openNewStreamLua(const char *filename) const {
LabEntry *i = findFilename(filename);
if (!i)
return NULL;
LuaFile *Lab::openNewStreamLua(const Common::String &filename) const {
if (!fileExists(filename))
return 0;
Common::File *file = new Common::File();
file->open(_labFileName);
file->seek(i->offset, SEEK_SET);
file->seek(_entries[filename].offset, SEEK_SET);
LuaFile *filehandle = new LuaFile();
filehandle->_in = file;
@ -116,47 +108,29 @@ LuaFile *Lab::openNewStreamLua(const char *filename) const {
return filehandle;
}
Common::File *Lab::openNewStreamFile(const char *filename) const {
Common::File *file;
LabEntry *i = findFilename(filename);
if (!i)
return NULL;
Common::File *Lab::openNewStreamFile(const Common::String &filename) const {
if (!fileExists(filename))
return 0;
file = new Common::File();
file->open(_labFileName.c_str());
file->seek(i->offset, SEEK_SET);
Common::File *file = new Common::File();
file->open(_labFileName);
file->seek(_entries[filename].offset, SEEK_SET);
return file;
}
int Lab::fileLength(const char *filename) const {
LabEntry *i = findFilename(filename);
if (!i)
int Lab::fileLength(const Common::String &filename) const {
if (!fileExists(filename))
return -1;
return i->len;
}
Lab::LabEntry *Lab::findFilename(const char *filename) const {
LabEntry key;
Common::String s = filename;
s.toLowercase();
key.filename = (char *)s.c_str();
return (Lab::LabEntry *)bsearch(&key, _entries, _numEntries, sizeof(LabEntry), sortCallback);
return _entries[filename].len;
}
void Lab::close() {
delete _f;
_f = NULL;
if (_entries)
for (int i = 0; i < _numEntries; i++)
delete[] _entries[i].filename;
delete[] _entries;
_entries = NULL;
_numEntries = 0;
_entries.clear();
}
} // end of namespace Grim

View File

@ -26,6 +26,8 @@
#ifndef GRIM_LAB_H
#define GRIM_LAB_H
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/str.h"
namespace Common {
@ -52,32 +54,29 @@ private:
class Lab {
public:
Lab() : _f(NULL), _entries(NULL), _numEntries(0) { }
Lab(const char *filename) : _f(NULL), _entries(NULL), _numEntries(0) { open(filename); }
bool open(const char *filename);
Lab() : _f(NULL) { }
bool open(const Common::String &filename);
bool isOpen() const;
void close();
bool fileExists(const char *filename) const;
Block *getFileBlock(const char *filename) const;
Common::File *openNewStreamFile(const char *filename) const;
LuaFile *openNewStreamLua(const char *filename) const;
int fileLength(const char *filename) const;
bool fileExists(const Common::String &filename) const;
Block *getFileBlock(const Common::String &filename) const;
Common::File *openNewStreamFile(const Common::String &filename) const;
LuaFile *openNewStreamLua(const Common::String &filename) const;
int fileLength(const Common::String &filename) const;
~Lab() { close(); }
struct LabEntry {
int offset, len;
char *filename;
};
private:
Common::File *_f;
LabEntry *_entries;
typedef Common::HashMap<Common::String, LabEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> LabMap;
LabMap _entries;
Common::String _labFileName;
int _numEntries;
LabEntry *findFilename(const char *filename) const;
};
} // end of namespace Grim

View File

@ -58,8 +58,9 @@ ResourceLoader::ResourceLoader() {
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
const Common::String filename = (*x)->getName();
l = new Lab(filename.c_str());
if (l->isOpen()) {
l = new Lab();
if (l->open(filename)) {
if (filename.equalsIgnoreCase("data005.lab"))
_labs.push_front(l);
else
@ -77,8 +78,9 @@ ResourceLoader::ResourceLoader() {
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
const Common::String filename = (*x)->getName();
l = new Lab(filename.c_str());
if (l->isOpen()) {
l = new Lab();
if (l->open(filename)) {
_labs.push_back(l);
lab_counter++;
} else {