oopless-parser.hpp 6.5 KB

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