Skip to content
Snippets Groups Projects
Commit 02669413 authored by Oliver Bock's avatar Oliver Bock
Browse files

Added the "Open Resource Compiler" subproject

parent 09ed5dfe
No related branches found
No related tags found
No related merge requests found
# config values
CXX?=g++
DEBUGFLAGSCPP=-DDEBUG -pg -ggdb -O0
OBJS=ResourceCompiler.o orc.o
DEPS=Makefile ResourceCompiler.h
# primary role based tagets
default: release
debug: orc
release: clean orc
# target specific options
debug: CPPFLAGS += $(DEBUGFLAGSCPP)
release: CPPFLAGS += -O3 -Wall -Wno-switch-enum
release: LDFLAGS += -s
# file specific targets
orc: $(DEPS) ResourceCompiler.cpp orc.cpp ${OBJS}
$(CXX) -g ${CPPFLAGS} ResourceCompiler.cpp orc.cpp -o orc
orc.o: $(DEPS) orc.cpp
$(CXX) -g ${CPPFLAGS} -c orc.cpp
ResourceCompiler.o: $(DEPS) ResourceCompiler.cpp
$(CXX) -g ${CPPFLAGS} -c ResourceCompiler.cpp
clean:
rm -f ${OBJS} orc
\ No newline at end of file
#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;
// 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 << "static const std::string c_ResourceIdentifiers[] = {" << endl;
outputFile << output.substr(0, output.length() - 1);
outputFile << endl << "};" << endl << endl;
output = resourceIndexInitializer.str();
outputFile << "static const unsigned int c_ResourceIndex[][2] = {" << endl;
outputFile << output.substr(0, output.length() - 1);
outputFile << endl << "};" << endl << endl;
output = resourceStorageInitializer.str();
outputFile << "static 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();
}
}
#ifndef RESOURCECOMPILER_H_
#define RESOURCECOMPILER_H_
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iterator>
using namespace std;
class ResourceCompiler
{
public:
ResourceCompiler(const string inputFilename, const string outputFilename);
virtual ~ResourceCompiler();
void compile();
private:
void parseInputFile();
void loadBinaryData();
string m_ResourceSpecFile;
string m_ResourceCodeFile;
map<string, string> m_ResourceFileMap;
map<string, vector<unsigned char> > m_ResourceDataMap;
};
#endif /*RESOURCECOMPILER_H_*/
#include "ResourceCompiler.h"
void printUsage() {
cerr << "Invalid command-line options!" << endl;
cerr << "Usage: orc <input filename> <output filename>" << endl;
}
int main(int argc, char *argv[])
{
if(argc != 3) {
printUsage();
exit(1);
}
else {
string inputFilename(argv[1]);
string outputFilename(argv[2]);
// TODO: better filename checking
if( inputFilename == "." || inputFilename == ".." ||
outputFilename == "." || outputFilename == "..")
{
printUsage();
exit(1);
}
ResourceCompiler rc(inputFilename, outputFilename);
rc.compile();
exit(0);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment