1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-26 04:12:41 +01:00

Merge pull request #547 from ShFil119/safe_convertion

Safer convertion strings to numbers
This commit is contained in:
Daniel Evans 2018-07-26 17:57:08 +01:00 committed by GitHub
commit 1586a90401
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 67 deletions

View File

@ -13,6 +13,7 @@
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <data/Clump.hpp> #include <data/Clump.hpp>
#include <rw/casts.hpp>
#include <rw/debug.hpp> #include <rw/debug.hpp>
#include <rw/types.hpp> #include <rw/types.hpp>
@ -105,7 +106,7 @@ void GameData::loadLevelFile(const std::string& path) {
} else if (cmd == "SPLASH") { } else if (cmd == "SPLASH") {
splash = line.substr(space + 1); splash = line.substr(space + 1);
} else if (cmd == "COLFILE") { } else if (cmd == "COLFILE") {
int zone = atoi(line.substr(space + 1, 1).c_str()); int zone = lexical_cast<int>(line.substr(space + 1, 1));
auto path = line.substr(space + 3); auto path = line.substr(space + 3);
loadCOL(zone, path); loadCOL(zone, path);
} else if (cmd == "IPL") { } else if (cmd == "IPL") {
@ -252,7 +253,9 @@ void GameData::loadCarcols(const std::string& path) {
if (std::getline(ss, r, ',') && std::getline(ss, g, ',') && if (std::getline(ss, r, ',') && std::getline(ss, g, ',') &&
std::getline(ss, b)) { std::getline(ss, b)) {
vehicleColours.emplace_back( vehicleColours.emplace_back(
atoi(r.c_str()), atoi(g.c_str()), atoi(b.c_str())); lexical_cast<int>(r),
lexical_cast<int>(g),
lexical_cast<int>(b));
} }
} else if (currentSection == CAR) { } else if (currentSection == CAR) {
std::string vehicle, p, s; std::string vehicle, p, s;
@ -262,7 +265,8 @@ void GameData::loadCarcols(const std::string& path) {
std::vector<std::pair<size_t, size_t>> colours; std::vector<std::pair<size_t, size_t>> colours;
while (std::getline(ss, p, ',') && std::getline(ss, s, ',')) { 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<int>(p),
lexical_cast<int>(s));
} }
vehiclePalettes.insert({vehicle, colours}); vehiclePalettes.insert({vehicle, colours});
@ -336,11 +340,11 @@ void GameData::loadWater(const std::string& path) {
std::getline(ss, e, ',')) { std::getline(ss, e, ',')) {
waterBlocks.emplace_back( waterBlocks.emplace_back(
atof(a.c_str()), lexical_cast<float>(a),
atof(b.c_str()), lexical_cast<float>(b),
atof(c.c_str()), lexical_cast<float>(c),
atof(d.c_str()), lexical_cast<float>(d),
atof(e.c_str())); lexical_cast<float>(e));
} }
} }
} }
@ -386,7 +390,7 @@ TextureArchive GameData::loadTextureArchive(const std::string& name) {
void GameData::getNameAndLod(std::string& name, int& lod) { void GameData::getNameAndLod(std::string& name, int& lod) {
auto lodpos = name.rfind("_l"); auto lodpos = name.rfind("_l");
if (lodpos != std::string::npos) { if (lodpos != std::string::npos) {
lod = std::atoi(name.substr(lodpos + 2).c_str()); lod = lexical_cast<int>(name.substr(lodpos + 2));
name = name.substr(0, lodpos); name = name.substr(0, lodpos);
} }
} }
@ -464,7 +468,7 @@ bool GameData::loadModel(ModelID model) {
static const std::string specialPrefix("special"); static const std::string specialPrefix("special");
if (!name.compare(0, specialPrefix.size(), specialPrefix)) { if (!name.compare(0, specialPrefix.size(), specialPrefix)) {
auto sid = name.substr(specialPrefix.size()); auto sid = name.substr(specialPrefix.size());
unsigned short specialID = std::atoi(sid.c_str()); unsigned short specialID = lexical_cast<int>(sid);
name = engine->state->specialCharacters[specialID]; name = engine->state->specialCharacters[specialID];
slotname = name; slotname = name;
break; break;

View File

@ -11,6 +11,8 @@
#include "data/PathData.hpp" #include "data/PathData.hpp"
#include <rw/casts.hpp>
bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) { bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
std::ifstream str(filename); std::ifstream str(filename);
@ -71,30 +73,30 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
auto objs = std::make_unique<SimpleModelInfo>(); auto objs = std::make_unique<SimpleModelInfo>();
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->setModelID(atoi(buff.c_str())); objs->setModelID(lexical_cast<int>(buff));
getline(strstream, objs->name, ','); getline(strstream, objs->name, ',');
getline(strstream, objs->textureslot, ','); getline(strstream, objs->textureslot, ',');
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->setNumAtomics(atoi(buff.c_str())); objs->setNumAtomics(lexical_cast<int>(buff));
for (int i = 0; i < objs->getNumAtomics(); i++) { for (int i = 0; i < objs->getNumAtomics(); i++) {
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->setLodDistance(i, atof(buff.c_str())); objs->setLodDistance(i, lexical_cast<float>(buff));
} }
objs->determineFurthest(); objs->determineFurthest();
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->flags = atoi(buff.c_str()); objs->flags = lexical_cast<int>(buff);
// Keep reading TOBJ data // Keep reading TOBJ data
if (section == LoaderIDE::TOBJ) { if (section == LoaderIDE::TOBJ) {
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->timeOn = atoi(buff.c_str()); objs->timeOn = lexical_cast<int>(buff);
getline(strstream, buff, ','); getline(strstream, buff, ',');
objs->timeOff = atoi(buff.c_str()); objs->timeOff = lexical_cast<int>(buff);
} else { } else {
objs->timeOn = 0; objs->timeOn = 0;
objs->timeOff = 24; objs->timeOff = 24;
@ -107,7 +109,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
auto cars = std::make_unique<VehicleModelInfo>(); auto cars = std::make_unique<VehicleModelInfo>();
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->setModelID(std::atoi(buff.c_str())); cars->setModelID(lexical_cast<int>(buff));
getline(strstream, cars->name, ','); getline(strstream, cars->name, ',');
getline(strstream, cars->textureslot, ','); getline(strstream, cars->textureslot, ',');
@ -123,10 +125,10 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
VehicleModelInfo::findVehicleClass(buff); VehicleModelInfo::findVehicleClass(buff);
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->frequency_ = std::atoi(buff.c_str()); cars->frequency_ = lexical_cast<int>(buff);
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->level_ = std::atoi(buff.c_str()); cars->level_ = lexical_cast<int>(buff);
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->componentrules_ = std::stoul(buff, nullptr, 16); cars->componentrules_ = std::stoul(buff, nullptr, 16);
@ -134,14 +136,14 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
switch (cars->vehicletype_) { switch (cars->vehicletype_) {
case VehicleModelInfo::CAR: case VehicleModelInfo::CAR:
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->wheelmodel_ = std::atoi(buff.c_str()); cars->wheelmodel_ = lexical_cast<int>(buff);
getline(strstream, buff, ','); getline(strstream, buff, ',');
cars->wheelscale_ = std::atof(buff.c_str()); cars->wheelscale_ = lexical_cast<float>(buff);
break; break;
case VehicleModelInfo::PLANE: case VehicleModelInfo::PLANE:
/// @todo load LOD /// @todo load LOD
getline(strstream, buff, ','); getline(strstream, buff, ',');
// cars->planeLOD_ = std::atoi(buff.c_str()); // cars->planeLOD_ = lexical_cast<int>(buff);
break; break;
default: default:
break; break;
@ -154,7 +156,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
auto peds = std::make_unique<PedModelInfo>(); auto peds = std::make_unique<PedModelInfo>();
getline(strstream, buff, ','); getline(strstream, buff, ',');
peds->setModelID(std::atoi(buff.c_str())); peds->setModelID(lexical_cast<int>(buff));
getline(strstream, peds->name, ','); getline(strstream, peds->name, ',');
getline(strstream, peds->textureslot, ','); getline(strstream, peds->textureslot, ',');
@ -168,7 +170,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
getline(strstream, peds->animgroup_, ','); getline(strstream, peds->animgroup_, ',');
getline(strstream, buff, ','); getline(strstream, buff, ',');
peds->carsmask_ = std::atoi(buff.c_str()); peds->carsmask_ = lexical_cast<int>(buff);
objects.emplace(peds->id(), std::move(peds)); objects.emplace(peds->id(), std::move(peds));
break; break;
@ -186,7 +188,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
std::string id; std::string id;
getline(strstream, id, ','); getline(strstream, id, ',');
path.ID = atoi(id.c_str()); path.ID = lexical_cast<int>(id);
getline(strstream, path.modelName); getline(strstream, path.modelName);
@ -198,7 +200,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
std::stringstream buffstream(linebuff); std::stringstream buffstream(linebuff);
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
switch (atoi(buff.c_str())) { switch (lexical_cast<int>(buff)) {
case 0: case 0:
node.type = PathNode::EMPTY; node.type = PathNode::EMPTY;
break; break;
@ -215,27 +217,27 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
} }
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.next = atoi(buff.c_str()); node.next = lexical_cast<int>(buff);
getline(buffstream, buff, ','); // "Always 0" getline(buffstream, buff, ','); // "Always 0"
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.position.x = strtof(buff.c_str(), nullptr) / 16.f; node.position.x = lexical_cast<float>(buff) / 16.f;
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.position.y = strtof(buff.c_str(), nullptr) / 16.f; node.position.y = lexical_cast<float>(buff) / 16.f;
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.position.z = strtof(buff.c_str(), nullptr) / 16.f; node.position.z = lexical_cast<float>(buff) / 16.f;
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.size = strtof(buff.c_str(), nullptr) / 16.f; node.size = lexical_cast<float>(buff) / 16.f;
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.leftLanes = atoi(buff.c_str()); node.leftLanes = lexical_cast<int>(buff);
getline(buffstream, buff, ','); getline(buffstream, buff, ',');
node.rightLanes = atoi(buff.c_str()); node.rightLanes = lexical_cast<int>(buff);
path.nodes.push_back(node); path.nodes.push_back(node);
} }
@ -250,7 +252,7 @@ bool LoaderIDE::load(const std::string &filename, const PedStatsList &stats) {
auto hier = std::make_unique<ClumpModelInfo>(); auto hier = std::make_unique<ClumpModelInfo>();
getline(strstream, buff, ','); getline(strstream, buff, ',');
hier->setModelID(std::atoi(buff.c_str())); hier->setModelID(lexical_cast<int>(buff));
getline(strstream, hier->name, ','); getline(strstream, hier->name, ',');
getline(strstream, hier->textureslot, ','); getline(strstream, hier->textureslot, ',');

View File

@ -14,6 +14,8 @@
#include "data/InstanceData.hpp" #include "data/InstanceData.hpp"
#include "data/ZoneData.hpp" #include "data/ZoneData.hpp"
#include <rw/casts.hpp>
enum SectionTypes { INST, PICK, CULL, ZONE, NONE }; enum SectionTypes { INST, PICK, CULL, ZONE, NONE };
/// Load the IPL data into memory /// Load the IPL data into memory
@ -76,15 +78,15 @@ bool LoaderIPL::load(const std::string& filename) {
getline(strstream, rotW, ','); getline(strstream, rotW, ',');
auto instance = std::make_shared<InstanceData>( auto instance = std::make_shared<InstanceData>(
atoi(id.c_str()), // ID lexical_cast<int>(id), // ID
model.substr(1, model.size() - 1), model.substr(1, model.size() - 1),
glm::vec3(atof(posX.c_str()), atof(posY.c_str()), glm::vec3(lexical_cast<float>(posX), lexical_cast<float>(posY),
atof(posZ.c_str())), lexical_cast<float>(posZ)),
glm::vec3(atof(scaleX.c_str()), atof(scaleY.c_str()), glm::vec3(lexical_cast<float>(scaleX), lexical_cast<float>(scaleY),
atof(scaleZ.c_str())), lexical_cast<float>(scaleZ)),
glm::normalize( glm::normalize(
glm::quat(-atof(rotW.c_str()), atof(rotX.c_str()), glm::quat(-lexical_cast<float>(rotW), lexical_cast<float>(rotX),
atof(rotY.c_str()), atof(rotZ.c_str())))); lexical_cast<float>(rotY), lexical_cast<float>(rotZ))));
m_instances.push_back(instance); m_instances.push_back(instance);
} else if (section == ZONE) { } else if (section == ZONE) {
@ -98,24 +100,24 @@ bool LoaderIPL::load(const std::string& filename) {
zone.name = value; zone.name = value;
getline(strstream, value, ','); getline(strstream, value, ',');
zone.type = atoi(value.c_str()); zone.type = lexical_cast<int>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.min.x = atof(value.c_str()); zone.min.x = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.min.y = atof(value.c_str()); zone.min.y = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.min.z = atof(value.c_str()); zone.min.z = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.max.x = atof(value.c_str()); zone.max.x = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.max.y = atof(value.c_str()); zone.max.y = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.max.z = atof(value.c_str()); zone.max.z = lexical_cast<float>(value);
getline(strstream, value, ','); getline(strstream, value, ',');
zone.island = atoi(value.c_str()); zone.island = lexical_cast<int>(value);
for (int i = 0; i < ZONE_GANG_COUNT; i++) { for (int i = 0; i < ZONE_GANG_COUNT; i++) {
zone.gangCarDensityDay[i] = zone.gangCarDensityNight[i] = zone.gangCarDensityDay[i] = zone.gangCarDensityNight[i] =

View File

@ -3,7 +3,7 @@
#include "script/ScriptTypes.hpp" #include "script/ScriptTypes.hpp"
#include <rw/bit_cast.hpp> #include <rw/casts.hpp>
#include <cstdint> #include <cstdint>
#include <string> #include <string>

View File

@ -14,7 +14,7 @@ SET(RWLIB_SOURCES
source/gl/TextureData.cpp source/gl/TextureData.cpp
source/rw/abort.cpp source/rw/abort.cpp
source/rw/bit_cast.hpp source/rw/casts.hpp
source/rw/filesystem.hpp source/rw/filesystem.hpp
source/rw/forward.hpp source/rw/forward.hpp
source/rw/types.hpp source/rw/types.hpp

View File

@ -7,7 +7,7 @@
#include <cstddef> #include <cstddef>
#include "rw/debug.hpp" #include "rw/debug.hpp"
#include "rw/bit_cast.hpp" #include "rw/casts.hpp"
/** /**
* @brief Class for working with RenderWare binary streams. * @brief Class for working with RenderWare binary streams.

View File

@ -1,15 +0,0 @@
#ifndef _LIBRW_BIT_CAST_HPP_
#define _LIBRW_BIT_CAST_HPP_
//Based on https://gist.github.com/socantre/3472964
#include <cstring> // memcpy
#include <type_traits> // is_trivially_copyable
template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
Dest dest = Dest{};
std::memcpy(&dest, &source, sizeof(Dest));
return dest;
}
#endif

35
rwlib/source/rw/casts.hpp Normal file
View File

@ -0,0 +1,35 @@
#ifndef _LIBRW_CASTS_HPP_
#define _LIBRW_CASTS_HPP_
#include <cstring> // memcpy
#include "rw/debug.hpp"
//Based on https://gist.github.com/socantre/3472964
template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
Dest dest = Dest{};
std::memcpy(&dest, &source, sizeof(Dest));
return dest;
}
template <class T, class S>
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