/* -------------------------------------------------------------------- EXTREME TUXRACER Copyright (C) 2010 Extreme Tuxracer Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ---------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include #endif #include "depot.h" #include "spx.h" #include #include #include #include const std::string emptyString = ""; const std::string errorString = "error"; // -------------------------------------------------------------------- // elementary string functions // -------------------------------------------------------------------- std::string MakePathStr(const std::string& src, const std::string& add) { std::string res; res.reserve(src.size() + add.size() + 1); res += src; res += SEP; res += add; return res; } void SInsertN(std::string &s, std::size_t pos, const std::string& ins) { if (pos > s.size()) pos = s.size(); s.insert(pos, ins); } void SDeleteN(std::string &s, std::size_t pos, std::size_t count) { if (pos > s.size()) pos = s.size(); s.erase(pos, count); } std::size_t SPosN(const std::string &s, const std::string& find) { return s.find(find); } void STrimLeftN(std::string &s) { std::size_t i = s.find_first_not_of(" \t"); if (i > 0) SDeleteN(s, 0, i); } void STrimRightN(std::string &s) { std::size_t i = s.find_last_not_of(" \t"); if (i != s.size()-1) s.erase(i+1); } void STrimN(std::string &s) { STrimLeftN(s); STrimRightN(s); } // -------------------------------------------------------------------- // conversion functions // -------------------------------------------------------------------- std::string Int_StrN(const int val) { return std::to_string(val); } std::string Int_StrN(const int val, const std::streamsize count) { std::ostringstream os; os << std::setw(count) << std::setfill('0') << val; return os.str(); } std::string Float_StrN(const float val, const std::streamsize count) { std::ostringstream os; os << std::setprecision(count) << std::fixed << val; return os.str(); } std::string Vector_StrN(const TVector3d& v, const std::streamsize count) { std::string res = Float_StrN(v.x, count); res += ' ' + Float_StrN(v.y, count); res += ' ' + Float_StrN(v.z, count); return res; } std::string Bool_StrN(const bool val) { if (val == true) return "true"; else return "false"; } int Str_IntN(const std::string &s, const int def) { int val; std::istringstream is(s); is >> val; if (is.fail()) return def; else return val; } bool Str_BoolN(const std::string &s, const bool def) { if (s == "0" || s == "false") return false; if (s == "1" || s == "true") return true; return Str_IntN(s, (int)def) != 0; // Try to parse as int } float Str_FloatN(const std::string &s, const float def) { float val; std::istringstream is(s); is >> val; if (is.fail()) return def; else return val; } template TVector2 Str_Vector2(const std::string &s, const TVector2 &def) { T x, y; std::istringstream is(s); is >> x >> y; if (is.fail()) return def; else return TVector2(x, y); } template TVector2 Str_Vector2(const std::string &s, const TVector2 &def); template TVector2 Str_Vector2(const std::string &s, const TVector2 &def); template TVector3 Str_Vector3(const std::string &s, const TVector3 &def) { T x, y, z; std::istringstream is(s); is >> x >> y >> z; if (is.fail()) return def; else return TVector3(x, y, z); } template TVector3 Str_Vector3(const std::string &s, const TVector3 &def); template TVector3 Str_Vector3(const std::string &s, const TVector3 &def); template TVector4 Str_Vector4(const std::string &s, const TVector4 &def) { T x, y, z, w; std::istringstream is(s); is >> x >> y >> z >> w; if (is.fail()) return def; else return TVector4(x, y, z, w); } template TVector4 Str_Vector4(const std::string &s, const TVector4 &def); template TVector4 Str_Vector4(const std::string &s, const TVector4 &def); sf::Color Str_ColorN(const std::string &s, const sf::Color &def) { float r, g, b, a; std::istringstream is(s); is >> r >> g >> b >> a; if (is.fail()) return def; else return sf::Color(r * 255, g * 255, b * 255, a * 255); } sf::Color Str_Color3N(const std::string &s, const sf::Color &def) { int r, g, b; std::istringstream is(s); is >> r >> g >> b; if (is.fail()) return def; else return sf::Color(r, g, b); } void Str_ArrN(const std::string &s, float *arr, std::size_t count, float def) { std::istringstream is(s); for (std::size_t i = 0; i < count; i++) is >> arr[i]; if (is.fail()) for (std::size_t i=0; i TVector2 SPVector2(const std::string &s, const std::string &tag, const TVector2& def) { return (Str_Vector2(SPItemN(s, tag), def)); } template TVector2 SPVector2(const std::string &s, const std::string &tag, const TVector2& def); template TVector2 SPVector2(const std::string &s, const std::string &tag, const TVector2& def); template TVector3 SPVector3(const std::string &s, const std::string &tag, const TVector3& def) { return (Str_Vector3(SPItemN(s, tag), def)); } template TVector3 SPVector3(const std::string &s, const std::string &tag, const TVector3& def); template TVector3 SPVector3(const std::string &s, const std::string &tag, const TVector3& def); template TVector4 SPVector4(const std::string &s, const std::string &tag, const TVector4& def) { return (Str_Vector4(SPItemN(s, tag), def)); } template TVector4 SPVector4(const std::string &s, const std::string &tag, const TVector4& def); template TVector4 SPVector4(const std::string &s, const std::string &tag, const TVector4& def); sf::Color SPColorN(const std::string &s, const std::string &tag, const sf::Color& def) { return (Str_ColorN(SPItemN(s, tag), def)); } sf::Color SPColor3N(const std::string &s, const std::string &tag, const sf::Color& def) { return (Str_Color3N(SPItemN(s, tag), def)); } void SPArrN(const std::string &s, const std::string &tag, float *arr, std::size_t count, float def) { Str_ArrN(SPItemN(s, tag), arr, count, def); } std::size_t SPPosN(const std::string &s, const std::string &tag) { std::string tg = '[' + tag + ']'; return SPosN(s, tg); } // ------------------ add --------------------------------------------- void SPAddIntN(std::string &s, const std::string &tag, const int val) { s += '['; s += tag; s += ']'; s += Int_StrN(val); } void SPAddFloatN(std::string &s, const std::string &tag, const float val, std::size_t count) { s += '['; s += tag; s += ']'; s += Float_StrN(val, count); } void SPAddStrN(std::string &s, const std::string &tag, const std::string &val) { size_t addsize = tag.size() + 2 + val.size(); if (s.capacity() < s.size() + addsize) s.reserve(s.size() + addsize); s += '['; s += tag; s += ']'; s += val; } void SPAddVec2N(std::string &s, const std::string &tag, const TVector2d &val, std::size_t count) { s += '['; s += tag; s += ']'; s += ' '; s += Float_StrN(val.x, count); s += ' '; s += Float_StrN(val.y, count); } void SPAddVec3N(std::string &s, const std::string &tag, const TVector3d &val, std::size_t count) { s += '['; s += tag; s += ']'; s += ' '; s += Float_StrN(val.x, count); s += ' '; s += Float_StrN(val.y, count); s += ' '; s += Float_StrN(val.z, count); } void SPAddBoolN(std::string &s, const std::string &tag, const bool val) { size_t addsize = 2 + tag.size() + (val ? 4 : 5); if (s.capacity() < s.size() + addsize) s.reserve(s.size() + addsize); s += '['; s += tag; s += ']'; if (val == true) s += "true"; else s+= "false"; } // -------------------------------------------------------------------- void SPSetIntN(std::string &s, const std::string &tag, const int val) { std::size_t pos = SPPosN(s, tag); if (pos != std::string::npos) { std::size_t ipos = pos + tag.size() + 2; std::string item = SPItemN(s, tag); if (item.size() != std::string::npos) SDeleteN(s, ipos, item.size()); SInsertN(s, ipos, Int_StrN(val)); } else SPAddIntN(s, tag, val); } void SPSetFloatN(std::string &s, const std::string &tag, const float val, std::size_t count) { std::size_t pos = SPPosN(s, tag); if (pos != std::string::npos) { std::size_t ipos = pos + tag.size() + 2; std::string item = SPItemN(s, tag); if (item.size() != std::string::npos) SDeleteN(s, ipos, item.size()); SInsertN(s, ipos, Float_StrN(val, count)); } else SPAddFloatN(s, tag, val, count); } void SPSetStrN(std::string &s, const std::string &tag, const std::string &val) { std::size_t pos = SPPosN(s, tag); if (pos != std::string::npos) { std::size_t ipos = pos + tag.size() + 2; std::string item = SPItemN(s, tag); if (item.size() != std::string::npos) SDeleteN(s, ipos, item.size()); SInsertN(s, ipos, val); } else SPAddStrN(s, tag, val); } // -------------------------------------------------------------------- // class CSPList // -------------------------------------------------------------------- CSPList::CSPList(bool newlineflag) { fnewlineflag = newlineflag; } void CSPList::Add(const std::string& line) { push_back(line); } void CSPList::Add(std::string&& line) { emplace_back(std::move(line)); } void CSPList::Print() const { for (const_iterator line = cbegin(); line != cend(); ++line) std::cout << *line << std::endl; } bool CSPList::Load(const std::string &filepath) { std::ifstream tempfile(filepath); if (!tempfile) { Message("CSPList::Load - unable to open " + filepath); return false; } else { bool backflag = false; std::string line; while (getline(tempfile, line)) { // delete new line char if in string std::size_t npos = line.rfind('\n'); if (npos != std::string::npos) SDeleteN(line, npos, 1); bool valid = true; if (line.empty()) valid = false; // empty line else if (line[0] == '#') valid = false; // comment line if (valid) { if (!fnewlineflag) { if (line[0] == '*' || empty()) Add(line); else back() += line; } else { bool fwdflag = false; if (line.back() == '\\') { SDeleteN(line, line.length()-1, 1); fwdflag = true; } if (backflag == false) Add(line); else back() += line; backflag = fwdflag; } } } return true; } } bool CSPList::Load(const std::string& dir, const std::string& filename) { return Load(MakePathStr(dir, filename)); } bool CSPList::LoadDepot(const std::string &depotpath) { auto path = DepotMustResolveFile(depotpath); return Load(path); } bool CSPList::Save(const std::string &filepath) const { std::ofstream tempfile(filepath); if (!tempfile) { Message("CSPList::Save - unable to open " + filepath); return false; } else { for (const_iterator line = cbegin(); line != cend(); ++line) { tempfile << *line << '\n'; } return true; } } bool CSPList::Save(const std::string& dir, const std::string& filename) const { return Save(MakePathStr(dir, filename)); } void CSPList::MakeIndex(std::unordered_map& index, const std::string &tag) { index.clear(); index.reserve(size()); std::size_t idx = 0; for (const_iterator line = cbegin(); line != cend(); ++line) { std::string item = SPItemN(*line, tag); STrimN(item); if (!item.empty()) { index[item] = idx; idx++; } } }