1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Derive CSndHandler and CVidHandler from new class CMediaHandler.

This commit is contained in:
Frank Zago
2009-06-19 04:27:12 +00:00
parent ffe2ff9647
commit 7bb09341a0
2 changed files with 141 additions and 221 deletions

View File

@@ -13,7 +13,7 @@
* *
*/ */
CSndHandler::~CSndHandler() CMediaHandler::~CMediaHandler()
{ {
entries.clear(); entries.clear();
fimap.clear(); fimap.clear();
@@ -25,7 +25,7 @@ CSndHandler::~CSndHandler()
// a simple structure. However, some post treatment would be necessary: file // a simple structure. However, some post treatment would be necessary: file
// size and offsets are little endian, and filename have a NUL in // size and offsets are little endian, and filename have a NUL in
// them. */ // them. */
CSndHandler::CSndHandler(std::string fname) CMediaHandler::CMediaHandler(std::string fname)
{ {
try //c-tor of mapped_file_source throws exception on failure try //c-tor of mapped_file_source throws exception on failure
{ {
@@ -36,7 +36,97 @@ CSndHandler::CSndHandler(std::string fname)
tlog1 << "Cannot open " << fname << std::endl; tlog1 << "Cannot open " << fname << std::endl;
throw std::string("Cannot open ")+fname; throw std::string("Cannot open ")+fname;
} }
}
// Reads a 4 byte integer. Format on file is little endian.
unsigned int CMediaHandler::readNormalNr (const unsigned char *p)
{
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
void CMediaHandler::extract(int index, std::string dstfile) //saves selected file
{
std::ofstream out(dstfile.c_str(),std::ios_base::binary);
const char *data = mfile->data();
out.write(&data[entries[index].offset], entries[index].size);
out.close();
}
void CMediaHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file
{
if (caseSens)
{
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
extract(i,dstfile);
}
}
else
{
std::transform(srcfile.begin(),srcfile.end(),srcfile.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==srcfile)
extract(i,dstfile);
}
}
}
}
#if 0
// unused and not sure what it's supposed to do
MemberFile CMediaHandler::getFile(std::string name)
{
MemberFile ret;
std::transform(name.begin(),name.end(),name.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==name)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==name)
{
ret.length=entries[i].size;
file.seekg(entries[i].offset,std::ios_base::beg);
ret.ifs=&file;
return ret;
}
}
}
return ret;
}
#endif
const char * CMediaHandler::extract (int index, int & size)
{
size = entries[index].size;
const char *data = mfile->data();
return &data[entries[index].offset];
}
const char * CMediaHandler::extract (std::string srcName, int &size)
{
int index;
std::map<std::string, int>::iterator fit;
if ((fit = fimap.find(srcName)) != fimap.end())
{
index = fit->second;
return this->extract(index, size);
}
size = 0;
return NULL;
}
CSndHandler::CSndHandler(std::string fname) : CMediaHandler::CMediaHandler(fname)
{
const unsigned char *data = (const unsigned char *)mfile->data(); const unsigned char *data = (const unsigned char *)mfile->data();
unsigned int numFiles = readNormalNr(&data[0]); unsigned int numFiles = readNormalNr(&data[0]);
@@ -75,209 +165,48 @@ CSndHandler::CSndHandler(std::string fname)
} }
} }
// Reads a 4 byte integer. Format on file is little endian. CVidHandler::CVidHandler(std::string fname) : CMediaHandler::CMediaHandler(fname)
unsigned int CSndHandler::readNormalNr (const unsigned char *p)
{ {
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); const unsigned char *data = (const unsigned char *)mfile->data();
}
void CSndHandler::extract(int index, std::string dstfile) //saves selected file unsigned int numFiles = readNormalNr(&data[0]);
{
std::ofstream out(dstfile.c_str(),std::ios_base::binary);
const char *data = mfile->data();
out.write(&data[entries[index].offset], entries[index].size);
out.close();
}
void CSndHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file for (unsigned int i=0; i<numFiles; i++)
{
if (caseSens)
{
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
extract(i,dstfile);
}
}
else
{
std::transform(srcfile.begin(),srcfile.end(),srcfile.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==srcfile)
extract(i,dstfile);
}
}
}
}
#if 0
// unused and not sure what it's supposed to do
MemberFile CSndHandler::getFile(std::string name)
{
MemberFile ret;
std::transform(name.begin(),name.end(),name.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==name)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==name)
{
ret.length=entries[i].size;
file.seekg(entries[i].offset,std::ios_base::beg);
ret.ifs=&file;
return ret;
}
}
}
return ret;
}
#endif
const char * CSndHandler::extract (int index, int & size)
{
size = entries[index].size;
const char *data = mfile->data();
return &data[entries[index].offset];
}
const char * CSndHandler::extract (std::string srcName, int &size)
{
int index;
std::map<std::string, int>::iterator fit;
if ((fit = fimap.find(srcName)) != fimap.end())
{
index = fit->second;
return this->extract(index, size);
}
size = 0;
return NULL;
}
CVidHandler::~CVidHandler()
{
entries.clear();
file.close();
}
CVidHandler::CVidHandler(std::string fname):CHUNK(65535)
{
file.open(fname.c_str(),std::ios::binary);
if (!file.is_open())
#ifndef __GNUC__
throw new std::exception((std::string("Cannot open ")+fname).c_str());
#else
throw new std::exception();
#endif
int nr = readNormalNr(0,4);
char tempc;
for (int i=0;i<nr;i++)
{ {
Entry entry; Entry entry;
while(true) const unsigned char *p;
{
file.read(&tempc,1); // Read file name and extension
if (tempc) p = &data[4+44*i];
entry.name+=tempc;
else break; while(*p) {
entry.name += *p;
p++;
} }
entry.something=readNormalNr(-1,4);
file.seekg(44-entry.name.length()-9,std::ios_base::cur); entry.name+='.';
entry.offset = readNormalNr(-1,4); p++;
if (i>0)
entries[i-1].size=entry.offset-entries[i-1].offset; while(*p)
if (i==nr-1)
{ {
file.seekg(0,std::ios::end); entry.name += *p;
entry.size = ((int)file.tellg())-entry.offset; p++;
file.seekg(0,std::ios::beg);
} }
// Read offset and size
p = &data[4+44*i+40];
entry.offset = readNormalNr(p);
// There is no size, so check where the next file is
if (i == numFiles - 1) {
entry.size = mfile->size() - entry.offset;
} else {
p = &data[4+44*(i+1)+40];
int next_offset = readNormalNr(p);
entry.size = next_offset - entry.offset;
}
entries.push_back(entry); entries.push_back(entry);
fimap[entry.name] = i;
} }
} }
int CVidHandler::readNormalNr (int pos, int bytCon)
{
if (pos>=0)
file.seekg(pos,std::ios_base::beg);
int ret=0;
int amp=1;
unsigned char zcz=0;
for (int i=0; i<bytCon; i++)
{
file.read((char*)(&zcz),1);
ret+=zcz*amp;
amp*=256;
}
return ret;
}
void CVidHandler::extract(int index, std::string dstfile) //saves selected file
{
std::ofstream out(dstfile.c_str(),std::ios_base::binary);
file.seekg(entries[index].offset,std::ios_base::beg);
int toRead=entries[index].size;
char * buffer = new char[std::min(CHUNK,entries[index].size)];
while (toRead>CHUNK)
{
file.read(buffer,CHUNK);
out.write(buffer,CHUNK);
toRead-=CHUNK;
}
file.read(buffer,toRead);
out.write(buffer,toRead);
out.close();
}
void CVidHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file
{
if (caseSens)
{
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
extract(i,dstfile);
}
}
else
{
std::transform(srcfile.begin(),srcfile.end(),srcfile.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==srcfile)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==srcfile)
extract(i,dstfile);
}
}
}
}
MemberFile CVidHandler::getFile(std::string name)
{
MemberFile ret;
std::transform(name.begin(),name.end(),name.begin(),tolower);
for (size_t i=0;i<entries.size();++i)
{
if (entries[i].name==name)
{
std::string por = entries[i].name;
std::transform(por.begin(),por.end(),por.begin(),tolower);
if (por==name)
{
ret.length=entries[i].size;
file.seekg(entries[i].offset,std::ios_base::beg);
ret.ifs=&file;
return ret;
}
}
}
throw ret;
//return ret;
}

View File

@@ -29,9 +29,10 @@ struct MemberFile
std::ifstream * ifs; std::ifstream * ifs;
int length; int length;
}; };
class CSndHandler
class CMediaHandler
{ {
private: protected:
struct Entry struct Entry
{ {
std::string name; std::string name;
@@ -44,36 +45,26 @@ private:
public: public:
std::vector<Entry> entries; std::vector<Entry> entries;
std::map<std::string, int> fimap; // map of wav file and index std::map<std::string, int> fimap; // map of file and index
~CSndHandler(); //d-tor ~CMediaHandler(); //d-tor
CSndHandler(std::string fname); //c-tor CMediaHandler(std::string fname); //c-tor
void extract(std::string srcfile, std::string dstfile, bool caseSens=true); //saves selected file void extract(std::string srcfile, std::string dstfile, bool caseSens=true); //saves selected file
const char * extract (std::string srcfile, int & size); //return selecte file data, NULL if file doesn't exist const char * extract (std::string srcfile, int & size); //return selecte file data, NULL if file doesn't exist
void extract(int index, std::string dstfile); //saves selected file void extract(int index, std::string dstfile); //saves selected file
MemberFile getFile(std::string name);//nie testowane - sprawdzic MemberFile getFile(std::string name);//nie testowane - sprawdzic
const char * extract (int index, int & size); //return selecte file - NIE TESTOWANE const char * extract (int index, int & size); //return selecte file - NIE TESTOWANE
}; };
class CVidHandler
class CSndHandler: public CMediaHandler
{ {
protected:
const int CHUNK;
struct Entry
{
std::string name;
int size, offset, something;
};
std::ifstream file;
int readNormalNr (int pos, int bytCon);
bool opened;
public: public:
std::vector<Entry> entries; CSndHandler(std::string fname);
~CVidHandler(); //d-tor };
CVidHandler(std::string fname); //c-tor
std::ifstream & extract(std::string srcfile); class CVidHandler: public CMediaHandler
void extract(std::string srcfile, std::string dstfile, bool caseSens=true); //saves selected file {
unsigned char * extract (std::string srcfile, int & size); //return selecte file, public:
void extract(int index, std::string dstfile); //saves selected file CVidHandler(std::string fname);
MemberFile getFile(std::string name); //nie testowane - sprawdzic
}; };