diff --git a/rwengine/src/engine/GameData.cpp b/rwengine/src/engine/GameData.cpp index bab769f6..47fb2aaa 100644 --- a/rwengine/src/engine/GameData.cpp +++ b/rwengine/src/engine/GameData.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -105,7 +106,7 @@ void GameData::loadLevelFile(const std::string& path) { } else if (cmd == "SPLASH") { splash = line.substr(space + 1); } else if (cmd == "COLFILE") { - int zone = atoi(line.substr(space + 1, 1).c_str()); + int zone = lexical_cast(line.substr(space + 1, 1)); auto path = line.substr(space + 3); loadCOL(zone, path); } else if (cmd == "IPL") { @@ -252,7 +253,9 @@ void GameData::loadCarcols(const std::string& path) { if (std::getline(ss, r, ',') && std::getline(ss, g, ',') && std::getline(ss, b)) { vehicleColours.emplace_back( - atoi(r.c_str()), atoi(g.c_str()), atoi(b.c_str())); + lexical_cast(r), + lexical_cast(g), + lexical_cast(b)); } } else if (currentSection == CAR) { std::string vehicle, p, s; @@ -262,7 +265,8 @@ void GameData::loadCarcols(const std::string& path) { std::vector> colours; while (std::getline(ss, p, ',') && std::getline(ss, s, ',')) { - colours.emplace_back(atoi(p.c_str()), atoi(s.c_str())); + colours.emplace_back(lexical_cast(p), + lexical_cast(s)); } vehiclePalettes.insert({vehicle, colours}); @@ -336,11 +340,11 @@ void GameData::loadWater(const std::string& path) { std::getline(ss, e, ',')) { waterBlocks.emplace_back( - atof(a.c_str()), - atof(b.c_str()), - atof(c.c_str()), - atof(d.c_str()), - atof(e.c_str())); + lexical_cast(a), + lexical_cast(b), + lexical_cast(c), + lexical_cast(d), + lexical_cast(e)); } } } @@ -386,7 +390,7 @@ TextureArchive GameData::loadTextureArchive(const std::string& name) { void GameData::getNameAndLod(std::string& name, int& lod) { auto lodpos = name.rfind("_l"); if (lodpos != std::string::npos) { - lod = std::atoi(name.substr(lodpos + 2).c_str()); + lod = lexical_cast(name.substr(lodpos + 2)); name = name.substr(0, lodpos); } } @@ -464,7 +468,7 @@ bool GameData::loadModel(ModelID model) { static const std::string specialPrefix("special"); if (!name.compare(0, specialPrefix.size(), specialPrefix)) { auto sid = name.substr(specialPrefix.size()); - unsigned short specialID = std::atoi(sid.c_str()); + unsigned short specialID = lexical_cast(sid); name = engine->state->specialCharacters[specialID]; slotname = name; break; diff --git a/rwengine/src/loaders/LoaderIDE.cpp b/rwengine/src/loaders/LoaderIDE.cpp index 9ab0eaad..0a47d5aa 100644 --- a/rwengine/src/loaders/LoaderIDE.cpp +++ b/rwengine/src/loaders/LoaderIDE.cpp @@ -11,6 +11,8 @@ #include "data/PathData.hpp" +#include + bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { std::ifstream str(filename); @@ -71,30 +73,30 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { auto objs = std::make_unique(); getline(strstream, buff, ','); - objs->setModelID(atoi(buff.c_str())); + objs->setModelID(lexical_cast(buff)); getline(strstream, objs->name, ','); getline(strstream, objs->textureslot, ','); getline(strstream, buff, ','); - objs->setNumAtomics(atoi(buff.c_str())); + objs->setNumAtomics(lexical_cast(buff)); for (int i = 0; i < objs->getNumAtomics(); i++) { getline(strstream, buff, ','); - objs->setLodDistance(i, atof(buff.c_str())); + objs->setLodDistance(i, lexical_cast(buff)); } objs->determineFurthest(); getline(strstream, buff, ','); - objs->flags = atoi(buff.c_str()); + objs->flags = lexical_cast(buff); // Keep reading TOBJ data if (section == LoaderIDE::TOBJ) { getline(strstream, buff, ','); - objs->timeOn = atoi(buff.c_str()); + objs->timeOn = lexical_cast(buff); getline(strstream, buff, ','); - objs->timeOff = atoi(buff.c_str()); + objs->timeOff = lexical_cast(buff); } else { objs->timeOn = 0; objs->timeOff = 24; @@ -107,7 +109,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { auto cars = std::make_unique(); getline(strstream, buff, ','); - cars->setModelID(std::atoi(buff.c_str())); + cars->setModelID(lexical_cast(buff)); getline(strstream, cars->name, ','); getline(strstream, cars->textureslot, ','); @@ -123,10 +125,10 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { VehicleModelInfo::findVehicleClass(buff); getline(strstream, buff, ','); - cars->frequency_ = std::atoi(buff.c_str()); + cars->frequency_ = lexical_cast(buff); getline(strstream, buff, ','); - cars->level_ = std::atoi(buff.c_str()); + cars->level_ = lexical_cast(buff); getline(strstream, buff, ','); cars->componentrules_ = std::stoul(buff, nullptr, 16); @@ -134,14 +136,14 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { switch (cars->vehicletype_) { case VehicleModelInfo::CAR: getline(strstream, buff, ','); - cars->wheelmodel_ = std::atoi(buff.c_str()); + cars->wheelmodel_ = lexical_cast(buff); getline(strstream, buff, ','); - cars->wheelscale_ = std::atof(buff.c_str()); + cars->wheelscale_ = lexical_cast(buff); break; case VehicleModelInfo::PLANE: /// @todo load LOD getline(strstream, buff, ','); - // cars->planeLOD_ = std::atoi(buff.c_str()); + // cars->planeLOD_ = lexical_cast(buff); break; default: break; @@ -154,7 +156,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { auto peds = std::make_unique(); getline(strstream, buff, ','); - peds->setModelID(std::atoi(buff.c_str())); + peds->setModelID(lexical_cast(buff)); getline(strstream, peds->name, ','); getline(strstream, peds->textureslot, ','); @@ -168,7 +170,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { getline(strstream, peds->animgroup_, ','); getline(strstream, buff, ','); - peds->carsmask_ = std::atoi(buff.c_str()); + peds->carsmask_ = lexical_cast(buff); objects.emplace(peds->id(), std::move(peds)); break; @@ -186,7 +188,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { std::string id; getline(strstream, id, ','); - path.ID = atoi(id.c_str()); + path.ID = lexical_cast(id); getline(strstream, path.modelName); @@ -198,7 +200,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { std::stringstream buffstream(linebuff); getline(buffstream, buff, ','); - switch (atoi(buff.c_str())) { + switch (lexical_cast(buff)) { case 0: node.type = PathNode::EMPTY; break; @@ -215,27 +217,27 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { } getline(buffstream, buff, ','); - node.next = atoi(buff.c_str()); + node.next = lexical_cast(buff); getline(buffstream, buff, ','); // "Always 0" getline(buffstream, buff, ','); - node.position.x = strtof(buff.c_str(), nullptr) / 16.f; + node.position.x = lexical_cast(buff) / 16.f; getline(buffstream, buff, ','); - node.position.y = strtof(buff.c_str(), nullptr) / 16.f; + node.position.y = lexical_cast(buff) / 16.f; getline(buffstream, buff, ','); - node.position.z = strtof(buff.c_str(), nullptr) / 16.f; + node.position.z = lexical_cast(buff) / 16.f; getline(buffstream, buff, ','); - node.size = strtof(buff.c_str(), nullptr) / 16.f; + node.size = lexical_cast(buff) / 16.f; getline(buffstream, buff, ','); - node.leftLanes = atoi(buff.c_str()); + node.leftLanes = lexical_cast(buff); getline(buffstream, buff, ','); - node.rightLanes = atoi(buff.c_str()); + node.rightLanes = lexical_cast(buff); path.nodes.push_back(node); } @@ -250,7 +252,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { auto hier = std::make_unique(); getline(strstream, buff, ','); - hier->setModelID(std::atoi(buff.c_str())); + hier->setModelID(lexical_cast(buff)); getline(strstream, hier->name, ','); getline(strstream, hier->textureslot, ','); diff --git a/rwengine/src/loaders/LoaderIPL.cpp b/rwengine/src/loaders/LoaderIPL.cpp index c0f14c41..0321d826 100644 --- a/rwengine/src/loaders/LoaderIPL.cpp +++ b/rwengine/src/loaders/LoaderIPL.cpp @@ -14,6 +14,8 @@ #include "data/InstanceData.hpp" #include "data/ZoneData.hpp" +#include + enum SectionTypes { INST, PICK, CULL, ZONE, NONE }; /// Load the IPL data into memory @@ -76,15 +78,15 @@ bool LoaderIPL::load(const std::string& filename) { getline(strstream, rotW, ','); auto instance = std::make_shared( - atoi(id.c_str()), // ID + lexical_cast(id), // ID model.substr(1, model.size() - 1), - glm::vec3(atof(posX.c_str()), atof(posY.c_str()), - atof(posZ.c_str())), - glm::vec3(atof(scaleX.c_str()), atof(scaleY.c_str()), - atof(scaleZ.c_str())), + glm::vec3(lexical_cast(posX), lexical_cast(posY), + lexical_cast(posZ)), + glm::vec3(lexical_cast(scaleX), lexical_cast(scaleY), + lexical_cast(scaleZ)), glm::normalize( - glm::quat(-atof(rotW.c_str()), atof(rotX.c_str()), - atof(rotY.c_str()), atof(rotZ.c_str())))); + glm::quat(-lexical_cast(rotW), lexical_cast(rotX), + lexical_cast(rotY), lexical_cast(rotZ)))); m_instances.push_back(instance); } else if (section == ZONE) { @@ -98,24 +100,24 @@ bool LoaderIPL::load(const std::string& filename) { zone.name = value; getline(strstream, value, ','); - zone.type = atoi(value.c_str()); + zone.type = lexical_cast(value); getline(strstream, value, ','); - zone.min.x = atof(value.c_str()); + zone.min.x = lexical_cast(value); getline(strstream, value, ','); - zone.min.y = atof(value.c_str()); + zone.min.y = lexical_cast(value); getline(strstream, value, ','); - zone.min.z = atof(value.c_str()); + zone.min.z = lexical_cast(value); getline(strstream, value, ','); - zone.max.x = atof(value.c_str()); + zone.max.x = lexical_cast(value); getline(strstream, value, ','); - zone.max.y = atof(value.c_str()); + zone.max.y = lexical_cast(value); getline(strstream, value, ','); - zone.max.z = atof(value.c_str()); + zone.max.z = lexical_cast(value); getline(strstream, value, ','); - zone.island = atoi(value.c_str()); + zone.island = lexical_cast(value); for (int i = 0; i < ZONE_GANG_COUNT; i++) { zone.gangCarDensityDay[i] = zone.gangCarDensityNight[i] = diff --git a/rwengine/src/script/SCMFile.hpp b/rwengine/src/script/SCMFile.hpp index c277333b..92fa7875 100644 --- a/rwengine/src/script/SCMFile.hpp +++ b/rwengine/src/script/SCMFile.hpp @@ -3,7 +3,7 @@ #include "script/ScriptTypes.hpp" -#include +#include #include #include diff --git a/rwlib/CMakeLists.txt b/rwlib/CMakeLists.txt index 685b277d..c4404841 100644 --- a/rwlib/CMakeLists.txt +++ b/rwlib/CMakeLists.txt @@ -14,7 +14,7 @@ SET(RWLIB_SOURCES source/gl/TextureData.cpp source/rw/abort.cpp - source/rw/bit_cast.hpp + source/rw/casts.hpp source/rw/filesystem.hpp source/rw/forward.hpp source/rw/types.hpp diff --git a/rwlib/source/loaders/RWBinaryStream.hpp b/rwlib/source/loaders/RWBinaryStream.hpp index d44224be..af96bff3 100644 --- a/rwlib/source/loaders/RWBinaryStream.hpp +++ b/rwlib/source/loaders/RWBinaryStream.hpp @@ -7,7 +7,7 @@ #include #include "rw/debug.hpp" -#include "rw/bit_cast.hpp" +#include "rw/casts.hpp" /** * @brief Class for working with RenderWare binary streams. diff --git a/rwlib/source/rw/bit_cast.hpp b/rwlib/source/rw/bit_cast.hpp deleted file mode 100644 index d52fcb52..00000000 --- a/rwlib/source/rw/bit_cast.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _LIBRW_BIT_CAST_HPP_ -#define _LIBRW_BIT_CAST_HPP_ - -//Based on https://gist.github.com/socantre/3472964 -#include // memcpy -#include // is_trivially_copyable - -template -inline Dest bit_cast(Source const &source) { - Dest dest = Dest{}; - std::memcpy(&dest, &source, sizeof(Dest)); - return dest; -} - -#endif diff --git a/rwlib/source/rw/casts.hpp b/rwlib/source/rw/casts.hpp new file mode 100644 index 00000000..bcdfc725 --- /dev/null +++ b/rwlib/source/rw/casts.hpp @@ -0,0 +1,35 @@ +#ifndef _LIBRW_CASTS_HPP_ +#define _LIBRW_CASTS_HPP_ + +#include // memcpy + +#include "rw/debug.hpp" + +//Based on https://gist.github.com/socantre/3472964 +template +inline Dest bit_cast(Source const &source) { + Dest dest = Dest{}; + std::memcpy(&dest, &source, sizeof(Dest)); + return dest; +} + +template +inline T lexical_cast(const S& s); + +template <> +inline int lexical_cast(const std::string& source) { + char* end = nullptr; //for errors handling + int result = std::strtol(source.c_str(), &end, 10); + RW_CHECK(end != source.c_str(), "Problem with conversion " << *end << " to int"); + return result; +} + +template <> +inline float lexical_cast(const std::string& source) { + char* end = nullptr; //for errors handling + float result = std::strtof(source.c_str(), &end); + RW_CHECK(end != source.c_str(), "Problem with conversion " << *end << " to float"); + return result; +} + +#endif