Select Git revision
ResourceCompiler.cpp
Forked from
einsteinathome / graphicsframework
230 commits behind the upstream repository.
-
Oliver Bock authoredOliver Bock authored
ResourceCompiler.cpp 6.57 KiB
/***************************************************************************
* Copyright (C) 2008 by Oliver Bock *
* oliver.bock[AT]aei.mpg.de *
* *
* This file is part of Einstein@Home. *
* *
* Einstein@Home 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, version 2 of the License. *
* *
* Einstein@Home 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 Einstein@Home. If not, see <http://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "ResourceCompiler.h"
ResourceCompiler::ResourceCompiler(const string inputFilename, const string outputFilename)
{
m_ResourceSpecFile = inputFilename;
m_ResourceCodeFile = outputFilename;
}
ResourceCompiler::~ResourceCompiler()
{
}
void ResourceCompiler::compile()
{
// parse input file (resource <-> file mapping)
parseInputFile();
// load the binary files (resource <-> data mapping)
loadBinaryData();
// temporary variables
ostringstream resourceIdentifierInitializer;
ostringstream resourceIndexInitializer;
ostringstream resourceStorageInitializer;
map<string, vector<unsigned char> >::iterator mapPos;
vector<unsigned char>::iterator dataPos;
unsigned int currentIndex = 0;
// store total amount of resources
resourceIndexInitializer << "{0x" << hex << m_ResourceDataMap.size() << ", 0x0},";
// iterate over all resource data mappings we have
for(mapPos = m_ResourceDataMap.begin(); mapPos != m_ResourceDataMap.end(); ++mapPos) {
// store identifier
resourceIdentifierInitializer << "\"" << mapPos->first << "\",";
// store data base index
resourceIndexInitializer << "{0x" << hex << currentIndex << ",";
resourceIndexInitializer << "0x" << hex << mapPos->second.size() << "},";
currentIndex += mapPos->second.size();
// iterate over the data content byte by byte
for(dataPos = mapPos->second.begin(); dataPos != mapPos->second.end(); ++dataPos) {
// store byte value as part of array initializer
resourceStorageInitializer << "0x" << hex << (int)*dataPos << ",";
}
}
// open the output code file
ofstream outputFile(m_ResourceCodeFile.c_str(), ios::out);
if(!outputFile) {
cerr << "Couldn't open output file \"" << m_ResourceCodeFile << "\"!" << endl,
exit(1);
}
// let's get some exceptions
outputFile.exceptions(ios::failbit | ios::badbit);
try {
// write header
outputFile << "#include <string>" << endl << endl;
// write code file contents (remove trailing commas)
string output = resourceIdentifierInitializer.str();
outputFile << "extern const std::string c_ResourceIdentifiers[] = {" << endl;
outputFile << output.substr(0, output.length() - 1);
outputFile << endl << "};" << endl << endl;
output = resourceIndexInitializer.str();
outputFile << "extern const unsigned int c_ResourceIndex[][2] = {" << endl;
outputFile << output.substr(0, output.length() - 1);
outputFile << endl << "};" << endl << endl;
output = resourceStorageInitializer.str();
outputFile << "extern const unsigned char c_ResourceStorage[] = {" << endl;
outputFile << output.substr(0, output.length() - 1);
outputFile << endl << "};" << endl << endl;
}
catch(const ios::failure& error) {
cerr << "Error during output file processing: " << error.what() << endl;
}
// clean up and clode file
outputFile.flush();
outputFile.close();
}
void ResourceCompiler::parseInputFile()
{
// open input file
ifstream inputFile(m_ResourceSpecFile.c_str(), ios::in);
if(!inputFile) {
cerr << "Couldn't open input file \"" << m_ResourceSpecFile << "\"!" << endl,
exit(1);
}
// let's get some exceptions
inputFile.exceptions(ios::failbit | ios::badbit);
try {
string line;
// read input file line by line
while(getline(inputFile, line)) {
unsigned int firstCharacter = line.find_first_not_of(" \t\r\n\f");
// we (sort of) allow for empty lines and comments
if(firstCharacter != string::npos && line.substr(firstCharacter, 1) != "#") {
// find our token delimiter
unsigned int separator = line.find("|");
// make sure there's exactly one delimiter
if(separator == string::npos || separator != line.rfind("|")) {
cerr << "Unexpected resource specification: " << line << endl;
}
else {
// store tokens in resource file map
m_ResourceFileMap[line.substr(0, separator)] = line.substr(separator + 1);
}
}
}
}
catch(const ios::failure& error) {
// check stream state for real error
if(!inputFile.eof()) {
cerr << "Error during input file processing: " << error.what();
}
}
// close input file
inputFile.close();
}
void ResourceCompiler::loadBinaryData()
{
map<string, string>::iterator pos;
// iterate over all resource file mappings we have
for(pos = m_ResourceFileMap.begin(); pos != m_ResourceFileMap.end(); ++pos) {
// open given resource file
ifstream binaryFile(pos->second.c_str(), ios::in | ios::binary);
if(!binaryFile) {
cerr << "Couldn't open binary file \"" << pos->second << "\"!" << endl,
exit(1);
}
// let's get some exceptions
binaryFile.exceptions(ios::failbit | ios::badbit);
try {
// store binary resource file using stream iterators
// copy( istream_iterator<unsigned char>(binaryFile),
// istream_iterator<unsigned char>(),
// back_inserter(m_ResourceDataMap[pos->first])
// );
// "copy" ends prematurely, so use the crude way instead
char c = 0;
while(binaryFile.get(c)) {
m_ResourceDataMap[pos->first].push_back(c);
}
}
catch(const ios::failure& error) {
// check stream state for real error
if(!binaryFile.eof()) {
cerr << "Error during binary file processing: " << error.what();
}
}
// close current file
binaryFile.close();
}
}