reflex2q3/include/oopless-parser.hpp

194 lines
6.5 KiB
C++

#ifndef __OOPLESS_PARSER__
#define __OOPLESS_PARSER__
#include "planes.h"
#include "worldspawn.h"
#include <string>
#include <vector>
#include <fstream>
#include <queue>
#include "EntityConverter.hpp"
bool is_ebrush(const std::vector<std::string> &);
std::vector<std::string> extract_brush(const std::vector<std::string> &);
struct TBrush override_textures(struct TBrush, const char*);
bool write(const struct TBrush &,
std::ofstream &,
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &));
void write(const std::vector<std::string> &,
std::ofstream &,
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
EntityConverter &);
bool convertmap(std::stringstream &,
const char * const,
void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
std::vector<std::vector<std::string> > &);
#define KEYWORD_ENTITY "entity"
#define KEYWORD_BRUSH "brush"
#define KEYWORD_VERTICES "vertices"
#define KEYWORD_FACES "faces"
#define KEYWORD_GLOBAL "global"
#define KEYWORD_PREFAB "prefab"
template <class STREAMOBJ>
std::vector<std::string> get_entity(STREAMOBJ &f) {
using namespace std;
vector<string> output;
string line;
unsigned int pos = f.tellg();
while (getline(f, line)) {
// stop when
// entity or a prefab keyword
// brush keyword and the entity is not of the type teleporter or jumppad.
if ((line.find(KEYWORD_ENTITY) != string::npos ||
line.find(KEYWORD_PREFAB) != string::npos) || (
line.find(KEYWORD_BRUSH) != string::npos && !is_ebrush(output))) {
f.seekg(pos);
return output;
} else {
output.push_back(line);
}
pos = f.tellg();
}
}
template <class STREAMOBJ>
std::vector<Eigen::Vector3f> parse_vertices(STREAMOBJ &f) {
using namespace std;
#define FIRSTCH(x) x[0]
vector<Eigen::Vector3f> output;
string line;
unsigned int pos = f.tellg();
while(getline(f, line)) {
if (line.find(KEYWORD_FACES) != string::npos ||
line.find(KEYWORD_BRUSH) != string::npos ||
line.find(KEYWORD_ENTITY) != string::npos ||
line.find(KEYWORD_PREFAB) != string::npos) {
f.seekg(pos);
return output;
} else {
Eigen::Vector3f v;
stringstream ss(line);
string vdata;
unsigned int i = 0;
while (ss >> vdata) {
if (isdigit(FIRSTCH(vdata)) || FIRSTCH(vdata) == '-') {
double dvalue = stod(vdata);
v[i] = (float)dvalue;
}
// note: this prevents the index growing out of vector capacity
// alternatively can throw an exception when that happens instead
// to make it clear that an illegal line has been hit.
i = (i + 1) % 3;
}
output.push_back(v);
}
pos = f.tellg();
}
return output;
}
template <class STREAMOBJ>
std::vector<struct TFace> parse_face(STREAMOBJ &f) {
using namespace std;
#define FIRSTCH(x) x[0]
#define SECONDCH(x) x[1]
// it is possible for the next line to be unrelated to faces
// so it is needed to reset the stream prior to reading
// the new label, e.g '\tbrush'.
vector<struct TFace> output;
string line;
unsigned int pos = f.tellg();
while(getline(f, line)) {
if (line.find(KEYWORD_VERTICES) != string::npos ||
line.find(KEYWORD_BRUSH) != string::npos ||
line.find(KEYWORD_ENTITY) != string::npos ||
line.find(KEYWORD_PREFAB) != string::npos ||
line.find(KEYWORD_GLOBAL) != string::npos) {
f.seekg(pos);
return output;
} else {
struct TFace x;
float *f = &x.m_fXOffset;;
stringstream ss(line);
string fdata;
bool hex = false;
unsigned int i = 0;
while (ss >> fdata) {
if (i < 5) {
if (isdigit(FIRSTCH(fdata)) || FIRSTCH(fdata) == '-') {
double dvalue = stod(fdata);
*f = (float)dvalue;
f++;
}
// note: if there is a non-digit in the first 5 fields
// then it qualifies as an illegal line.
} else if (4 < i && i < 8) {
x.m_Indices.push_back(stoi(fdata));
} else if (8 <= i) {
if (!hex && fdata.length() > 1) {
if (SECONDCH(fdata) == 'x') {
// this is the unidentified hex digit.
// out of range for stoi
x.hex = fdata;
hex = true;
}
} else if (!hex) {
x.m_Indices.push_back(stoi(fdata));
} else if (hex) {
x.m_Material = fdata;
} else {
;
}
}
i++;
} // end, per field iteration
output.push_back(x);
} // end else case, if line did not contain other keywords
pos = f.tellg();
} // end, per line iteration
// the odd case when the map file ends with a face indent.
return output;
}
template <class STREAMOBJ>
struct TBrush parse_brush(STREAMOBJ &f) {
using namespace std;
struct TBrush output;
string l;
getline(f, l);
if (l.find(KEYWORD_VERTICES) != string::npos) {
output.m_Vertices = parse_vertices<STREAMOBJ>(f);
}
getline(f, l);
if (l.find(KEYWORD_FACES) != string::npos) {
output.m_Faces = parse_face<STREAMOBJ>(f);
}
return output;
}
template <class ISTR>
void parse_prefab(ISTR &f,
std::ofstream &out,
void (*b) (std::stringstream &, const std::vector<TPlanePoints> &),
std::vector<std::vector<std::string> > &entities) {
using namespace std;
string l;
getline(f, l);
if (l.find(KEYWORD_BRUSH) != string::npos) {
write(parse_brush<ISTR>(f), out, b);
} else if (l.find(KEYWORD_ENTITY) != string::npos) {
entities.push_back(get_entity<ISTR>(f));
}
}
#endif