Skip to content

Commit

Permalink
[cleanup] Add toNumber.h utilities to convert std::string_view to `…
Browse files Browse the repository at this point in the history
…int`

Replace `atoi`/`stoi` by `toInt`.
  • Loading branch information
Jarod42 committed May 29, 2024
1 parent d76b324 commit ae28f66
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 79 deletions.
23 changes: 20 additions & 3 deletions src/dedicatedserver/dedicatedserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "defines.h"
#include "settings.h"
#include "utility/listhelpers.h"
#include "utility/string/toNumber.h"
#include "utility/os.h"

#include <algorithm>
Expand Down Expand Up @@ -170,7 +171,14 @@ bool cDedicatedServer::handleInput (const std::string& command)
else if (tokens.at (0) == "loadGame")
{
if (tokens.size() == 2)
startServer (atoi (tokens.at (1).c_str()));
if (auto n = toInt (tokens.at (1)))
{
startServer (*n);
}
else
{
std::cout << "Not a number: " << std::quoted (tokens.at (1)) << std::endl;
}
else
{
std::cout << "No savegame number given. Trying to load auto save (savegame number " << kAutoSaveSlot << ")." << std::endl;
Expand All @@ -181,7 +189,16 @@ bool cDedicatedServer::handleInput (const std::string& command)
{
// TODO: select game, currently apply to first game
if (tokens.size() == 2)
saveGame (atoi (tokens.at (1).c_str()));
{
if (auto n = toInt (tokens.at (1)))
{
saveGame (*n);
}
else
{
std::cout << "Not a number: " << std::quoted (tokens.at (1)) << std::endl;
}
}
else
printHelpWrongArguments();
}
Expand Down Expand Up @@ -265,7 +282,7 @@ void cDedicatedServer::setProperty (const std::string& property, const std::stri
{
if (property == "port")
{
int newPort = atoi (value.c_str());
int newPort = toInt (value).value_or (DEFAULTPORT);
if (newPort < 0 || newPort >= 65536)
newPort = DEFAULTPORT;
port = newPort;
Expand Down
44 changes: 3 additions & 41 deletions src/lib/chatcommand/chatcommandarguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "game/logic/client.h"
#include "game/logic/server.h"
#include "utility/string/toNumber.h"

#include <algorithm>
#include <cassert>
Expand Down Expand Up @@ -329,26 +330,7 @@ size_t cChatCommandArgumentServerPlayer::parse (const std::string& command, size

const auto nextWordLength = getNextWordLength (command, position);

std::optional<int> playerNumber;
try
{
size_t pos{};
playerNumber = std::stoi (command.substr (position, nextWordLength), &pos);
if (pos != nextWordLength)
{
playerNumber.reset();
}
}
catch (const std::invalid_argument&)
{
playerNumber.reset();
}
catch (const std::out_of_range&)
{
// TODO: translate
throw std::runtime_error ("Invalid player number");
}
if (playerNumber)
if (const std::optional<int> playerNumber = toInt (command.substr (position, nextWordLength)))
{
try
{
Expand Down Expand Up @@ -419,27 +401,7 @@ size_t cChatCommandArgumentClientPlayer::parse (const std::string& command, size

const auto nextWordLength = getNextWordLength (command, position);

std::optional<int> playerNumber;
try
{
size_t pos{};
playerNumber = std::stoi (command.substr (position, nextWordLength), &pos);
if (pos != nextWordLength)
{
playerNumber.reset();
}
}
catch (const std::invalid_argument&)
{
playerNumber.reset();
}
catch (const std::out_of_range&)
{
// TODO: translate
throw std::runtime_error ("Invalid player number");
}

if (playerNumber)
if (const std::optional<int> playerNumber = toInt (command.substr (position, nextWordLength)))
{
value = activeClientPointer->getModel().getPlayer (*playerNumber);
if (value == nullptr)
Expand Down
18 changes: 3 additions & 15 deletions src/lib/chatcommand/chatcommandarguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <string>
#include <vector>

#include "utility/string/toNumber.h"

size_t getNextWordLength (const std::string& s, size_t position);

class cPlayer;
Expand Down Expand Up @@ -208,21 +210,7 @@ size_t cChatCommandArgumentInt<T>::parse (const std::string& command, size_t pos
{
const auto nextWordLength = getNextWordLength (command, position);

std::optional<long long> longValue;
try
{
size_t pos{};
longValue = std::stoll (command.substr (position, nextWordLength), &pos);
if (pos != nextWordLength)
{
longValue.reset();
}
}
catch (const std::exception&)
{
longValue.reset();
}

std::optional<long long> longValue = toLongLong (command.substr (position, nextWordLength));
if (longValue && (*longValue < static_cast<long long> (std::numeric_limits<ValueType>::min()) || *longValue > static_cast<long long> (std::numeric_limits<ValueType>::max())))
{
longValue.reset();
Expand Down
6 changes: 3 additions & 3 deletions src/lib/game/data/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "utility/crc.h"
#include "utility/listhelpers.h"
#include "utility/ranges.h"
#include "utility/string/toNumber.h"

#include <cassert>
#include <set>
Expand Down Expand Up @@ -151,10 +152,9 @@ const cPlayer* cModel::getPlayer (int playerNr) const
const cPlayer* cModel::getPlayer (std::string playerName) const
{
// first try to find player by number
const int playerNr = atoi (playerName.c_str());
if (playerNr != 0 || playerName == "0")
if (const auto playerNr = toInt (playerName))
{
return getPlayer (playerNr);
return getPlayer (*playerNr);
}

// try to find player by name
Expand Down
3 changes: 2 additions & 1 deletion src/lib/game/data/savegame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "utility/ranges.h"
#include "utility/serialization/jsonarchive.h"
#include "utility/serialization/serialization.h"
#include "utility/string/toNumber.h"

#include <filesystem>
#include <optional>
Expand Down Expand Up @@ -292,7 +293,7 @@ void fillSaveGames (std::size_t minIndex, std::size_t maxIndex, std::vector<cSav
std::string filename = filepath.string();
std::smatch match;
if (!std::regex_match (filename, match, savename_regex)) continue;
const std::size_t number = atoi (match[1].str().c_str());
const std::size_t number = toInt (match[1].str()).value_or (0);

if (number <= minIndex || number > maxIndex) continue;

Expand Down
3 changes: 2 additions & 1 deletion src/lib/resources/loaddata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "utility/listhelpers.h"
#include "utility/log.h"
#include "utility/serialization/jsonarchive.h"
#include "utility/string/toNumber.h"

#include <SDL_mixer.h>
#include <filesystem>
Expand Down Expand Up @@ -118,7 +119,7 @@ void debugTranslationSize (const cLanguage& language, const cUnicodeFont& font)

if (std::regex_match (key, res, reg))
{
std::size_t maxSize = std::stoi (res[1]);
std::size_t maxSize = toInt (std::string (res[1])).value();
const char referenceLetter = 'a';

if (font.getTextWide (std::string (maxSize, referenceLetter)) < font.getTextWide (translatedText))
Expand Down
65 changes: 65 additions & 0 deletions src/lib/utility/string/toNumber.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/***************************************************************************
* Mechanized Assault and Exploration Reloaded Projectfile *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/

#ifndef utility_string_toNumberH
#define utility_string_toNumberH

#include <charconv>
#include <optional>
#include <string_view>

template <typename T>
std::pair<std::optional<T>, std::size_t> parseIntegerT (std::string_view s)
{
static_assert (std::is_integral_v <T>);
T n;
const auto [ptr, ec] = std::from_chars (s.data(), s.data() + s.size(), n);
if (ec != std::errc{})
{
return {std::nullopt, ptr - s.data()};
}
return {n, ptr - s.data()};
}

//------------------------------------------------------------------------------
template <typename T>
std::optional<T> toIntegerT (std::string_view s)
{
const auto [res, offset] = parseIntegerT<T> (s);
if (offset != s.size())
{
return std::nullopt;
}
return res;
}

//------------------------------------------------------------------------------
inline std::optional<int> toInt (std::string_view s)
{
return toIntegerT<int> (s);
}

//------------------------------------------------------------------------------
inline std::optional<long long> toLongLong (std::string_view s)
{
return toIntegerT<long long> (s);
}


#endif // utility_string_toNumberH
8 changes: 5 additions & 3 deletions src/lib/utility/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "utility/version.h"

#include "utility/string/toNumber.h"

#ifdef major
# undef major
#endif
Expand Down Expand Up @@ -82,7 +84,7 @@ void cVersion::parseFromString (const std::string& string)
// NOTE: do we need this to be more robust?

auto firstDotPos = string.find_first_of (".");
major = atoi (string.substr (0, firstDotPos).c_str());
major = toInt (string.substr (0, firstDotPos)).value_or (0);

if (firstDotPos == std::string::npos)
{
Expand All @@ -92,15 +94,15 @@ void cVersion::parseFromString (const std::string& string)
else
{
auto secondDotPos = string.find_first_of (".", firstDotPos + 1);
minor = atoi (string.substr (firstDotPos + 1, secondDotPos).c_str());
minor = toInt (string.substr (firstDotPos + 1, secondDotPos)).value_or (0);

if (secondDotPos == std::string::npos)
{
revision = 0;
}
else
{
revision = atoi (string.substr (secondDotPos + 1).c_str());
revision = toInt (string.substr (secondDotPos + 1)).value_or (0);
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/ui/graphical/menu/dialogs/dialogcolorpicker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "ui/widgets/validators/validatorint.h"
#include "utility/language.h"
#include "utility/narrow_cast.h"
#include "utility/string/toNumber.h"

//------------------------------------------------------------------------------
cDialogColorPicker::cDialogColorPicker (const cRgbColor& color, eWindowBackgrounds backgroundType) :
Expand Down Expand Up @@ -81,23 +82,23 @@ cDialogColorPicker::cDialogColorPicker (const cRgbColor& color, eWindowBackgroun
});
signalConnectionManager.connect (redValueLineEdit->editingFinished, [this] (eValidatorState) {
const auto color = colorPicker->getSelectedColor();
const auto newRed = narrow_cast<unsigned char> (atoi (redValueLineEdit->getText().c_str()));
const auto newRed = narrow_cast<unsigned char> (toInt (redValueLineEdit->getText()).value_or (color.r));
if (newRed != color.r)
{
colorPicker->setSelectedColor (color.exchangeRed (newRed));
}
});
signalConnectionManager.connect (greenValueLineEdit->editingFinished, [this] (eValidatorState) {
const auto color = colorPicker->getSelectedColor();
const auto newGreen = narrow_cast<unsigned char> (atoi (greenValueLineEdit->getText().c_str()));
const auto newGreen = narrow_cast<unsigned char> (toInt (greenValueLineEdit->getText()).value_or (color.g));
if (newGreen != color.g)
{
colorPicker->setSelectedColor (color.exchangeGreen (newGreen));
}
});
signalConnectionManager.connect (blueValueLineEdit->editingFinished, [this] (eValidatorState) {
const auto color = colorPicker->getSelectedColor();
const auto newBlue = narrow_cast<unsigned char> (atoi (blueValueLineEdit->getText().c_str()));
const auto newBlue = narrow_cast<unsigned char> (toInt (blueValueLineEdit->getText()).value_or (color.b));
if (newBlue != color.b)
{
colorPicker->setSelectedColor (color.exchangeBlue (newBlue));
Expand Down
5 changes: 3 additions & 2 deletions src/ui/graphical/menu/dialogs/dialogpreferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "ui/widgets/validators/validatorint.h"
#include "utility/language.h"
#include "utility/string/iequals.h"
#include "utility/string/toNumber.h"

#include <SDL_mixer.h>
#include <functional>
Expand Down Expand Up @@ -253,8 +254,8 @@ void cDialogPreferences::saveValues()

const auto& resolutionText = resolutionsComboBox->getSelectedText();

const auto newResolutionX = atoi (resolutionText.substr (0, resolutionText.find ("x")).c_str());
const auto newResolutionY = atoi (resolutionText.substr (resolutionText.find ("x") + 1).c_str());
const auto newResolutionX = toInt (resolutionText.substr (0, resolutionText.find ("x"))).value_or (0);
const auto newResolutionY = toInt (resolutionText.substr (resolutionText.find ("x") + 1)).value_or (0);

if (newResolutionX > 0 && newResolutionY > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "ui/widgets/validators/validatorint.h"
#include "utility/language.h"
#include "utility/narrow_cast.h"
#include "utility/string/toNumber.h"

namespace
{
Expand Down Expand Up @@ -331,12 +332,12 @@ cGameSettings cWindowGameSettings::getGameSettings() const
{
case eGameSettingsVictoryCondition::Points:
{
gameSettings.victoryPoints = (victoryCount == custom ? stoi (customVictoryPointsCheckBox->getText()) : victoryCount);
gameSettings.victoryPoints = (victoryCount == custom ? toInt (customVictoryPointsCheckBox->getText()).value_or (0) : victoryCount);
break;
}
case eGameSettingsVictoryCondition::Turns:
{
gameSettings.victoryTurns = (victoryCount == custom ? stoi (customVictoryTurnsCheckBox->getText()) : victoryCount);
gameSettings.victoryTurns = (victoryCount == custom ? toInt (customVictoryTurnsCheckBox->getText()).value_or (0) : victoryCount);
break;
}
case eGameSettingsVictoryCondition::Death: break;
Expand All @@ -345,15 +346,15 @@ cGameSettings cWindowGameSettings::getGameSettings() const
gameSettings.turnLimitActive = true;
switch (*turnLimitGroup->getSelectedValue())
{
case custom: gameSettings.turnLimit = std::chrono::seconds (atoi (customTurnLimitCheckBox->getText().c_str())); break;
case custom: gameSettings.turnLimit = std::chrono::seconds (toInt (customTurnLimitCheckBox->getText()).value_or (0)); break;
case unlimited: gameSettings.turnLimitActive = false; break;
default: gameSettings.turnLimit = std::chrono::seconds (*turnLimitGroup->getSelectedValue()); break;
}

gameSettings.turnEndDeadlineActive = true;
switch (*endTurnDeadlineGroup->getSelectedValue())
{
case custom: gameSettings.turnEndDeadline = std::chrono::seconds (atoi (customEndTurnDeadlineCheckBox->getText().c_str())); break;
case custom: gameSettings.turnEndDeadline = std::chrono::seconds (toInt (customEndTurnDeadlineCheckBox->getText()).value_or (0)); break;
case unlimited: gameSettings.turnEndDeadlineActive = false; break;
default: gameSettings.turnEndDeadline = std::chrono::seconds (*endTurnDeadlineGroup->getSelectedValue()); break;
}
Expand Down
Loading

0 comments on commit ae28f66

Please sign in to comment.