| 239 | } |
| 240 | |
| 241 | inline static bool Read(datafile& n, const std::string& sFileName, const char sListSep = ',') |
| 242 | { |
| 243 | // Open the file! |
| 244 | std::ifstream file(sFileName); |
| 245 | if (file.is_open()) |
| 246 | { |
| 247 | // These variables are outside of the read loop, as we will |
| 248 | // need to refer to previous iteration values in certain conditions |
| 249 | std::string sPropName = ""; |
| 250 | std::string sPropValue = ""; |
| 251 | |
| 252 | // The file is fundamentally structured as a stack, so we will read it |
| 253 | // in a such, but note the data structure in memory is not explicitly |
| 254 | // stored in a stack, but one is constructed implicitly via the nodes |
| 255 | // owning other nodes (aka a tree) |
| 256 | |
| 257 | // I dont want to accidentally create copies all over the place, nor do |
| 258 | // I want to use pointer syntax, so being a bit different and stupidly |
| 259 | // using std::reference_wrapper, so I can store references to datafile |
| 260 | // nodes in a std::container. |
| 261 | std::stack<std::reference_wrapper<datafile>> stkPath; |
| 262 | stkPath.push(n); |
| 263 | |
| 264 | |
| 265 | // Read file line by line and process |
| 266 | while (!file.eof()) |
| 267 | { |
| 268 | // Read line |
| 269 | std::string line; |
| 270 | std::getline(file, line); |
| 271 | |
| 272 | // This little lambda removes whitespace from |
| 273 | // beginning and end of supplied string |
| 274 | auto trim = [](std::string& s) |
| 275 | { |
| 276 | s.erase(0, s.find_first_not_of(" \t\n\r\f\v")); |
| 277 | s.erase(s.find_last_not_of(" \t\n\r\f\v") + 1); |
| 278 | }; |
| 279 | |
| 280 | trim(line); |
| 281 | |
| 282 | // If line has content |
| 283 | if (!line.empty()) |
| 284 | { |
| 285 | // Test if its a comment... |
| 286 | if (line[0] == '#') |
| 287 | { |
| 288 | // ...it is a comment, so ignore |
| 289 | datafile comment; |
| 290 | comment.m_bIsComment = true; |
| 291 | stkPath.top().get().m_vecObjects.push_back({ line, comment }); |
| 292 | } |
| 293 | else |
| 294 | { |
| 295 | // ...it is content, so parse. Firstly, find if the line |
| 296 | // contains an assignment. If it does then it's a property... |
| 297 | size_t x = line.find_first_of('='); |
| 298 | if (x != std::string::npos) |