#include <string>
#include <iostream>
#include <vector>
#include <array>
#include <complex>
#include <map>
#include <fstream>
#include <climits>
//read in string literals
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e(&sliteral)[N]) {
std::array<e, N-1> buffer; //get buffer
in >> buffer[0]; //skips whitespace
if (N>2)
in.read(&buffer[1], N-2); //read the rest
if (strncmp(&buffer[0], sliteral, N-1)) //if it failed
in.setstate(in.rdstate() | std::ios::failbit); //set the state
return in;
}
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& cliteral) {
e buffer; //get buffer
in >> buffer; //read data
if (buffer != cliteral) //if it failed
in.setstate(in.rdstate() | std::ios::failbit); //set the state
return in;
}
template<class e, class t, int N>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, e(&carray)[N]) {
return std::operator>>(in, carray);
}
//default handlers
typedef void (*handler)(std::string, int);
static void errorHandlerDefault(std::string message, int severity) //Supplies a default error handler
{std::cerr << "ERROR: " << severity << ' ' << message << '\n';}
static void warningHandlerDefault(std::string message, int severity) //Supplies a default warning handler
{std::cerr << "WARNING: " << severity << ' ' << message << '\n';}
//structs
struct libitem {
std::string name;
std::complex<double> somecomplex;
std::complex<double> someothercomplex;
};
struct lib {
std::string filelibfilename;
std::map<std::string, libitem> items;
};
struct myothertag
{
std::string type;
int above, below, id;
};
struct fileset
{
std::string filelibfilename;
std::map<int, std::string> mytagdata;
std::vector<myothertag> myothertagdata;
};
template<class T>
std::istream& loadObjectFromFile(std::istream& file, T& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
return file>>obj;
}
//custom complex parser
template<class T>
std::istream& loadObjectFromFile(std::istream& file, std::complex<T>& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
if (!file)
return file;
std::string fullline;
std::getline(file, fullline);
T r, i;
std::stringstream ss(fullline);
if (ss >> '(' >> r >> ',' >> 'i' >> ')') {
obj = std::complex<T>(r, i);
return file;
}
ss.clear();
ss.seekg(0);
if (ss >> '(' >> r >> 'i' >> ')') {
obj = std::complex<T>(r, i);
return file;
}
ss.clear();
ss.seekg(0);
if (ss >> r >> ',' >> i) {
obj = std::complex<T>(r, i);
return file;
}
ss.clear();
ss.seekg(0);
if (ss >> r >> i) {
obj = std::complex<T>(r, i);
return file;
}
file.setstate(file.rdstate() | std::ios::failbit);
return file;
}
std::istream& loadObjectFromFile(std::istream& file, std::string& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
obj.clear();
//ignore leading whitespace
while(isspace(file.peek()))
file.get();
//read everything but EOF, # and =
int c = file.peek();
for(;
c!=EOF && c!='#' && c!='=' && c<CHAR_MAX && isspace(c)==false;
c = file.peek())
{
obj.append(1, char(c));
file.get();
}
//if there was nothing, return EOF, # or =
if (obj.empty())
obj.append(1, char(c));
return file;
}
std::istream& loadObjectFromFile(std::istream& file, libitem& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
std::string symbol;
while(loadObjectFromFile(file, symbol)) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "<LIBITEM_END>") {
break;
} else if (symbol == "NAME") {
if (! (file>>'=' && loadObjectFromFile(file, obj.name, errorH, warningH)) )
errorH(symbol + " incorrectly formatted", 1);
} else if (symbol == "SOMECOMPLEX") {
if (!(file>>'=' && loadObjectFromFile(file,obj.somecomplex, errorH, warningH)))
errorH(symbol + " incorrectly formatted", 1);
} else if (symbol == "SOMEOTHERCOMPLEX") {
if (!(file>>'=' && loadObjectFromFile(file,obj.someothercomplex, errorH, warningH)))
errorH(symbol + " incorrectly formatted", 1);
} else { //not a member: failure
errorH(symbol + " is not a member of libitem", 1);
file.setstate(file.rdstate() | std::ios::failbit);
break;
}
}
return file;
}
std::istream& loadObjectFromFile(std::istream& file, lib& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
std::string symbol;
while(loadObjectFromFile(file, symbol)) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "<FILE_LIBRARY_END>") {
break;
} else if (symbol == "FILE") {
if (! (file>>'=' && loadObjectFromFile(file, obj.filelibfilename)))
errorH(symbol + " incorrectly formatted", 1);
else {
std::ifstream recur(obj.filelibfilename.c_str());
if (!loadObjectFromFile(recur, obj, errorH, warningH))
file.setstate(file.rdstate() | std::ios::failbit);
}
} else if (symbol == "<LIBITEM_BEG>") {
libitem t;
if (loadObjectFromFile(file, t, errorH, warningH))
obj.items[t.name] = t;
} else {
errorH(symbol + " is not a member of library", 1);
file.setstate(file.rdstate() | std::ios::failbit);
}
}
if (file.eof()) //eof is valid here
file.clear();
return file;
}
std::istream& loadObjectFromFile(std::istream& file, myothertag& obj,
const std::map<int, std::string>& mytagdata,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
std::string symbol;
while(loadObjectFromFile(file, symbol)) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "<MYOTHERTAG_END>") {
break;
} else if (symbol == "ID") {
if (! (file>>'='>>obj.id))
errorH(symbol + " incorrectly formatted", 1);
} else if (symbol == "TYPE") {
if (! (file>>'='>>obj.type))
errorH(symbol + " incorrectly formatted", 1);
} else if (symbol == "MYTAG_BELOW_ID") {
if (! (file>>'='>>obj.below))
errorH(symbol + " incorrectly formatted", 1);
else {
if (obj.below!=-1 && obj.below!=0 && mytagdata.find(obj.below)==mytagdata.cend())
errorH(symbol + " has invalid value", 1);
}
} else if (symbol == "MYTAG_ABOVE_ID") {
if (! (file>>'='>>obj.above))
errorH(symbol + " incorrectly formatted", 1);
else {
if (obj.above!=-1 && obj.above!=0 && mytagdata.find(obj.above)==mytagdata.cend())
errorH(symbol + " has invalid value", 1);
}
} else { //not a member: failure
errorH(symbol + " is not a member of myothertag", 1);
file.setstate(file.rdstate() | std::ios::failbit);
break;
}
}
return file;
}
std::istream& loadObjectFromFile(std::istream& file, std::map<int, std::string>& obj,
const lib& mylib,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
std::string symbol;
while(loadObjectFromFile(file, symbol)) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "<MYTAG_END>") {
break;
} else if (symbol.compare(0,6,"MYTAG<")==0) {
std::string& value = obj[atoi(symbol.data()+6)];
if (! (file>>'=' && loadObjectFromFile(file, value, errorH, warningH)) )
errorH(symbol + " incorrectly formatted", 1);
else if (mylib.items.find(value)==mylib.items.end())
errorH(value + " was not found in the library", 1);
} else { //not a member: failure
errorH(symbol + " is not a member of tags", 1);
file.setstate(file.rdstate() | std::ios::failbit);
break;
}
}
return file;
}
std::istream& loadObjectFromFile(std::istream& file, fileset& obj,
handler errorH = errorHandlerDefault,
handler warningH = warningHandlerDefault)
{
std::string symbol;
lib mylib;
while(loadObjectFromFile(file, symbol)) {
if (symbol[0] == '#') {
std::getline(file, symbol);
} else if (symbol == "<FILE_END>") {
break;
} else if (symbol == "<FILE_BEG>") {
loadObjectFromFile(file, obj, errorH, warningH);
} else if (symbol == "FILE") {
std::string filename;
if (! (file>>'='>>filename) )
errorH(symbol + " incorrectly formatted", 1);
else {
std::ifstream recur(filename.c_str());
if (!loadObjectFromFile(recur, obj, errorH, warningH))
file.setstate(file.rdstate() | std::ios::failbit);
}
} else if (symbol == "<FILE_LIBRARY_BEG>") {
loadObjectFromFile(file, mylib, errorH, warningH);
obj.filelibfilename = mylib.filelibfilename;
} else if (symbol == "<MYTAG_BEG>") {
loadObjectFromFile(file, obj.mytagdata, mylib, errorH, warningH);
} else if (symbol == "<MYOTHERTAG_BEG>") {
myothertag t;
if (loadObjectFromFile(file, t, obj.mytagdata, errorH, warningH))
obj.myothertagdata.push_back(t);
} else { //not a member: failure
errorH(symbol + " is not a member of fileset", 1);
file.setstate(file.rdstate() | std::ios::failbit);
break;
}
}
if (file.eof()) //eof is valid here
file.clear();
return file;
}
int main() {
fileset obj;
std::ifstream file("C:/input.in");
if (!file)
std::cout << "error opening file";
else if (!loadObjectFromFile(file, obj))
std::cout << "error loading file";
else if (obj.myothertagdata.size() == 2)
std::cout << "success";
else
std::cout << "unknown failure";
return 0;
}