creaturesImage work: add mutableCopy and tint methods to the base class (and change...
[openc2e.git] / Catalogue.cpp
blob8c4870c243161eb771b28418316334fc131b9b2e
1 /*
2 * Catalogue.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Sat 13 Nov 2004.
6 * Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
7 * Copyright (c) 2005-2006 Bryan Donlan. All rights reserved.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
20 #include "Catalogue.h"
21 #include "catalogue.lex.h"
22 #include <boost/filesystem/operations.hpp>
23 #include <boost/filesystem/path.hpp>
24 #include <boost/filesystem/fstream.hpp>
25 #include <boost/filesystem/convenience.hpp>
26 #include <boost/tokenizer.hpp>
27 #include <boost/format.hpp>
28 #include <iostream>
30 #include <cctype>
32 #include "openc2e.h"
34 using boost::str;
36 namespace fs = boost::filesystem;
38 Catalogue catalogue;
40 struct quote_subst {
41 char escape;
42 char subst;
45 static struct quote_subst subst_table[] = {
46 { 'n', '\n' },
47 { '\\', '\\' },
48 { '\"', '\"' },
49 { 't', '\t' },
50 { 0, 0 }
53 char catalogue_descape(char c) {
54 struct quote_subst *qs = subst_table;
55 while (qs->escape) {
56 if (qs->escape == c)
57 return qs->subst;
58 qs++;
60 std::cerr << "Unmatched substitution: \\" << c << std::endl;
61 return c;
64 static const char *tok_str[] = { "EOF", "word", "string", "integer" };
66 std::string cat_str;
67 int cat_int = -1;
69 catalogueFlexLexer *catalexer = NULL;
70 Catalogue *parsing_cat = NULL;
72 void Catalogue::addVals(std::string &title, bool override, int count,
73 const std::list<std::string> &vals)
75 // TODO: how the heck does override work? DS has an "Option Text" tag which has to overwrite the C3 one, so commenting this out for now..
76 /*if (data.find(title) != data.end() && !override)
77 return; // XXX: ?*/
78 data[title].clear();
79 // copy(vals.begin(), vals.end(), data[title].begin());
80 std::list<std::string>::const_iterator i = vals.begin();
81 while(i != vals.end()) {
82 data[title].push_back(*i++);
87 extern int cataparse();
89 void cataerror(const char *err) {
90 // XXX: we may leak here - memory pools?
91 throw catalogueException(err);
93 void catalogueParseError(int lineno) {
94 std::ostringstream oss;
95 oss << "Catalogue parse error at line " << lineno << std::endl;
97 throw catalogueException(oss.str());
100 std::istream &operator >> (std::istream &s, Catalogue &c) {
101 catalogueFlexLexer lex(&s);
102 catalexer = &lex;
103 parsing_cat = &c;
105 cataparse();
107 catalexer = NULL;
108 parsing_cat = NULL;
110 return s;
113 void Catalogue::reset() {
114 data.clear();
117 void Catalogue::addFile(fs::path path) {
118 assert(fs::exists(path));
119 assert(!fs::is_directory(path));
121 try {
122 fs::ifstream f(path);
123 f >> *this;
124 } catch (const catalogueException &ex) {
125 std::cerr << "Error reading catalogue file " << path.string() << ":" << std::endl << '\t' << ex.what() << std::endl;
129 void Catalogue::initFrom(fs::path path) {
130 assert(fs::exists(path));
131 assert(fs::is_directory(path));
133 //std::cout << "Catalogue is reading " << path.native_directory_string() << std::endl;
135 fs::directory_iterator end;
136 std::string file;
137 for (fs::directory_iterator i(path); i != end; ++i) {
138 try {
139 if ((!fs::is_directory(*i)) && (fs::extension(*i) == ".catalogue")) {
140 std::string x = fs::basename(*i);
141 // TODO: '-en-GB' exists too, this doesn't work for that
142 if ((x.size() > 3) && (x[x.size() - 3] == '-')) {
143 // TODO: this is NOT how we should do it
144 if (x[x.size() - 2] != 'e' || x[x.size() - 1] != 'n') continue; // skip all non-english localised files
147 addFile(*i);
150 catch (const std::exception &ex) {
151 std::cerr << "directory_iterator died on '" << i->leaf() << "' with " << ex.what() << std::endl;
156 std::string stringFromInt(int i) {
157 // TODO: hacky? also, put somewhere more appropriate
158 return boost::str(boost::format("%d") % i);
161 const std::string Catalogue::getAgentName(unsigned char family, unsigned char genus, unsigned short species) const {
162 std::string buf;
163 buf = str(boost::format("Agent Help %d %d %d") % (int)family % (int)genus % species);
164 if (hasTag(buf)) {
165 return getTag(buf)[0];
166 } else {
167 return "";
171 std::string Catalogue::calculateWildcardTag(std::string tag, unsigned char family, unsigned char genus, unsigned short species) const {
172 std::string searchstring = tag + " " + stringFromInt(family) + " " + stringFromInt(genus) + " " + stringFromInt(species);
173 if (hasTag(searchstring)) return searchstring;
174 searchstring = tag + " " + stringFromInt(family) + " " + stringFromInt(genus) + " 0";
175 if (hasTag(searchstring)) return searchstring;
176 searchstring = tag + " " + stringFromInt(family) + " 0 0";
177 if (hasTag(searchstring)) return searchstring;
178 searchstring = tag + " 0 0 0";
179 if (hasTag(searchstring)) return searchstring;
180 return "";
183 /* vim: set noet: */