oopless-parser.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #ifndef __OOPLESS_PARSER__
  2. #define __OOPLESS_PARSER__
  3. #include "planes.h"
  4. #include "worldspawn.h"
  5. #include <string>
  6. #include <vector>
  7. #include <fstream>
  8. #include <queue>
  9. #include "EntityConverter.hpp"
  10. bool is_ebrush(const std::vector<std::string> &);
  11. std::vector<std::string> extract_brush(const std::vector<std::string> &);
  12. struct TBrush override_textures(struct TBrush, const char*);
  13. bool write(const struct TBrush &,
  14. std::ofstream &,
  15. void (*f) (std::stringstream &, const std::vector<TPlanePoints> &));
  16. void write(const std::vector<std::string> &,
  17. std::ofstream &,
  18. void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
  19. EntityConverter &);
  20. bool convertmap(std::stringstream &,
  21. const char * const,
  22. void (*f) (std::stringstream &, const std::vector<TPlanePoints> &),
  23. std::vector<std::vector<std::string> > &);
  24. #define KEYWORD_ENTITY "entity"
  25. #define KEYWORD_BRUSH "brush"
  26. #define KEYWORD_VERTICES "vertices"
  27. #define KEYWORD_FACES "faces"
  28. #define KEYWORD_GLOBAL "global"
  29. #define KEYWORD_PREFAB "prefab"
  30. template <class STREAMOBJ>
  31. std::vector<std::string> get_entity(STREAMOBJ &f) {
  32. using namespace std;
  33. vector<string> output;
  34. string line;
  35. unsigned int pos = f.tellg();
  36. while (getline(f, line)) {
  37. // stop when
  38. // entity or a prefab keyword
  39. // brush keyword and the entity is not of the type teleporter or jumppad.
  40. if ((line.find(KEYWORD_ENTITY) != string::npos ||
  41. line.find(KEYWORD_PREFAB) != string::npos) || (
  42. line.find(KEYWORD_BRUSH) != string::npos && !is_ebrush(output))) {
  43. f.seekg(pos);
  44. return output;
  45. } else {
  46. output.push_back(line);
  47. }
  48. pos = f.tellg();
  49. }
  50. }
  51. template <class STREAMOBJ>
  52. std::vector<Eigen::Vector3f> parse_vertices(STREAMOBJ &f) {
  53. using namespace std;
  54. #define FIRSTCH(x) x[0]
  55. vector<Eigen::Vector3f> output;
  56. string line;
  57. unsigned int pos = f.tellg();
  58. while(getline(f, line)) {
  59. if (line.find(KEYWORD_FACES) != string::npos ||
  60. line.find(KEYWORD_BRUSH) != string::npos ||
  61. line.find(KEYWORD_ENTITY) != string::npos ||
  62. line.find(KEYWORD_PREFAB) != string::npos) {
  63. f.seekg(pos);
  64. return output;
  65. } else {
  66. Eigen::Vector3f v;
  67. stringstream ss(line);
  68. string vdata;
  69. unsigned int i = 0;
  70. while (ss >> vdata) {
  71. if (isdigit(FIRSTCH(vdata)) || FIRSTCH(vdata) == '-') {
  72. double dvalue = stod(vdata);
  73. v[i] = (float)dvalue;
  74. }
  75. // note: this prevents the index growing out of vector capacity
  76. // alternatively can throw an exception when that happens instead
  77. // to make it clear that an illegal line has been hit.
  78. i = (i + 1) % 3;
  79. }
  80. output.push_back(v);
  81. }
  82. pos = f.tellg();
  83. }
  84. return output;
  85. }
  86. template <class STREAMOBJ>
  87. std::vector<struct TFace> parse_face(STREAMOBJ &f) {
  88. using namespace std;
  89. #define FIRSTCH(x) x[0]
  90. #define SECONDCH(x) x[1]
  91. // it is possible for the next line to be unrelated to faces
  92. // so it is needed to reset the stream prior to reading
  93. // the new label, e.g '\tbrush'.
  94. vector<struct TFace> output;
  95. string line;
  96. unsigned int pos = f.tellg();
  97. while(getline(f, line)) {
  98. if (line.find(KEYWORD_VERTICES) != string::npos ||
  99. line.find(KEYWORD_BRUSH) != string::npos ||
  100. line.find(KEYWORD_ENTITY) != string::npos ||
  101. line.find(KEYWORD_PREFAB) != string::npos ||
  102. line.find(KEYWORD_GLOBAL) != string::npos) {
  103. f.seekg(pos);
  104. return output;
  105. } else {
  106. struct TFace x;
  107. float *f = &x.m_fXOffset;;
  108. stringstream ss(line);
  109. string fdata;
  110. bool hex = false;
  111. unsigned int i = 0;
  112. while (ss >> fdata) {
  113. if (i < 5) {
  114. if (isdigit(FIRSTCH(fdata)) || FIRSTCH(fdata) == '-') {
  115. double dvalue = stod(fdata);
  116. *f = (float)dvalue;
  117. f++;
  118. }
  119. // note: if there is a non-digit in the first 5 fields
  120. // then it qualifies as an illegal line.
  121. } else if (4 < i && i < 8) {
  122. x.m_Indices.push_back(stoi(fdata));
  123. } else if (8 <= i) {
  124. if (!hex && fdata.length() > 1) {
  125. if (SECONDCH(fdata) == 'x') {
  126. // this is the unidentified hex digit.
  127. // out of range for stoi
  128. x.hex = fdata;
  129. hex = true;
  130. }
  131. } else if (!hex) {
  132. x.m_Indices.push_back(stoi(fdata));
  133. } else if (hex) {
  134. x.m_Material = fdata;
  135. } else {
  136. ;
  137. }
  138. }
  139. i++;
  140. } // end, per field iteration
  141. output.push_back(x);
  142. } // end else case, if line did not contain other keywords
  143. pos = f.tellg();
  144. } // end, per line iteration
  145. // the odd case when the map file ends with a face indent.
  146. return output;
  147. }
  148. template <class STREAMOBJ>
  149. struct TBrush parse_brush(STREAMOBJ &f) {
  150. using namespace std;
  151. struct TBrush output;
  152. string l;
  153. getline(f, l);
  154. if (l.find(KEYWORD_VERTICES) != string::npos) {
  155. output.m_Vertices = parse_vertices<STREAMOBJ>(f);
  156. }
  157. getline(f, l);
  158. if (l.find(KEYWORD_FACES) != string::npos) {
  159. output.m_Faces = parse_face<STREAMOBJ>(f);
  160. }
  161. return output;
  162. }
  163. template <class ISTR>
  164. void parse_prefab(ISTR &f,
  165. std::ofstream &out,
  166. void (*b) (std::stringstream &, const std::vector<TPlanePoints> &),
  167. std::vector<std::vector<std::string> > &entities) {
  168. using namespace std;
  169. string l;
  170. getline(f, l);
  171. if (l.find(KEYWORD_BRUSH) != string::npos) {
  172. write(parse_brush<ISTR>(f), out, b);
  173. } else if (l.find(KEYWORD_ENTITY) != string::npos) {
  174. entities.push_back(get_entity<ISTR>(f));
  175. }
  176. }
  177. #endif