| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | #include "StdInc.h"#include <boost/iostreams/device/mapped_file.hpp>#include <SDL_endian.h>#include "CSndHandler.h"/* * CSndHandler.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * *//* Media file are kept in container files. We map these files in * memory, parse them and create an index of them to easily retrieve * the data+size of the objects. */CMediaHandler::~CMediaHandler(){	std::vector<boost::iostreams::mapped_file_source *>::iterator it;	entries.clear();	fimap.clear();		for (it=mfiles.begin() ; it < mfiles.end(); it++ ) {		(*it)->close();		delete *it;	}}boost::iostreams::mapped_file_source *CMediaHandler::add_file(std::string fname, bool important /*= true*/){	boost::iostreams::mapped_file_source *mfile;	try //c-tor of mapped_file_source throws exception on failure	{		mfile = new boost::iostreams::mapped_file_source(fname);				if (!mfile->is_open()) //just in case			throw std::runtime_error("Cannot open " + fname + ": !mfile->is_open()");	} 	catch(std::exception &e)	{		if(important)			tlog1 << "Cannot open " << fname  << ": " << e.what() << std::endl;		throw;	}	mfiles.push_back(mfile);	return mfile;}void CMediaHandler::extract(int index, std::string dstfile) //saves selected file{	std::ofstream out(dstfile.c_str(),std::ios_base::binary);	Entry &entry = entries[index];	out.write(entry.data, entry.size);	out.close();}void CMediaHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file{	srcfile.erase(srcfile.find_last_of('.'));	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);			}		}	}}const char * CMediaHandler::extract (int index, int & size){	Entry &entry = entries[index];	size = entry.size;	return entry.data;}const char * CMediaHandler::extract (std::string srcName, int &size){	int index;	size_t dotPos = srcName.find_last_of('.');	if (dotPos != std::string::npos)		srcName.erase(dotPos);	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;}void CVidHandler::add_file(std::string fname){	boost::iostreams::mapped_file_source *mfile = NULL;	try	{		mfile = CMediaHandler::add_file(fname);	}	catch(...)	{		return;	}	if(mfile->size() < 48)	{		tlog1 << fname << " doesn't contain needed data!\n";		return;	}	const ui8 *data = (const ui8 *)mfile->data();	ui32 numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]);	struct videoEntry *ve = (struct videoEntry *)&data[4];	for (ui32 i=0; i<numFiles; i++, ve++)	{		Entry entry;		entry.name = ve->filename;		entry.offset = SDL_SwapLE32(ve->offset);		entry.name.erase(entry.name.find_last_of('.'));		// There is no size, so check where the next file is		if (i == numFiles - 1) {			entry.size = mfile->size() - entry.offset;		} else {			struct videoEntry *ve_next = ve+1;			entry.size = SDL_SwapLE32(ve_next->offset) - entry.offset;		}		entry.data = mfile->data() + entry.offset;		entries.push_back(entry);		fimap[entry.name] = i;	}}
 |