Some conversion replacements:
* Replace the (w)stringify functions with the standard std::to_(w)string functions.
* Replace convertTo with versions that use type_traits to determine which standard string conversion function to call, as well as handle enums specically.
--- a/src/in_2sf/XSFConfig_2SF.cpp
+++ b/src/in_2sf/XSFConfig_2SF.cpp
@@ -93,7 +93,7 @@
// Mutes
for (size_t x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
{
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + wstringify(x + 1)).c_str()));
+ SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
}
break;
--- a/src/in_2sf/XSFPlayer_2SF.cpp
+++ b/src/in_2sf/XSFPlayer_2SF.cpp
@@ -162,7 +162,7 @@
do
{
found = false;
- std::string libTag = "_lib" + stringify(n++);
+ std::string libTag = "_lib" + std::to_string(n++);
if (xSFToLoad->GetTagExists(libTag))
{
found = true;
--- a/src/in_gsf/XSFPlayer_GSF.cpp
+++ b/src/in_gsf/XSFPlayer_GSF.cpp
@@ -168,7 +168,7 @@
do
{
found = false;
- std::string libTag = "_lib" + stringify(n++);
+ std::string libTag = "_lib" + std::to_string(n++);
if (xSF->GetTagExists(libTag))
{
found = true;
--- a/src/in_ncsf/SSEQPlayer/SDAT.cpp
+++ b/src/in_ncsf/SSEQPlayer/SDAT.cpp
@@ -42,7 +42,7 @@
throw std::logic_error("No SSEQ records found in SDAT");
if (!infoSection.SEQrecord.entries.count(sseqToLoad))
- throw std::range_error("SSEQ of " + stringify(sseqToLoad) + " is not found");
+ throw std::range_error("SSEQ of " + std::to_string(sseqToLoad) + " is not found");
// Read SSEQ
if (infoSection.SEQrecord.entries.count(sseqToLoad))
--- a/src/in_ncsf/XSFConfig_NCSF.cpp
+++ b/src/in_ncsf/XSFConfig_NCSF.cpp
@@ -85,7 +85,7 @@
// Mutes
for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
{
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + wstringify(x + 1)).c_str()));
+ SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"SPU " + std::to_wstring(x + 1)).c_str()));
SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
}
break;
@@ -259,9 +259,9 @@
ProgressSetPosImmediate(hDlg, IDC_SOUND0VOLBAR + chanId, vol);
if (this->soundViewData->volModeAlternative)
- buf = wstringify(chn.reg.volumeMul) + L"/" + wstringify(1 << datashift);
+ buf = std::to_wstring(chn.reg.volumeMul) + L"/" + std::to_wstring(1 << datashift);
else
- buf = wstringify(vol);
+ buf = std::to_wstring(vol);
SetDlgItemTextW(hDlg, IDC_SOUND0VOL + chanId, buf.c_str());
if (!chn.reg.panning)
@@ -271,18 +271,18 @@
else if (chn.reg.panning == 127)
buf = L"R";
else if (chn.reg.panning < 64)
- buf = L"L" + wstringify(64 - chn.reg.panning);
+ buf = L"L" + std::to_wstring(64 - chn.reg.panning);
else //if (chn.reg.panning > 64)
- buf = L"R" + wstringify(chn.reg.panning - 64);
+ buf = L"R" + std::to_wstring(chn.reg.panning - 64);
SetDlgItemTextW(hDlg, IDC_SOUND0PAN + chanId, buf.c_str());
static const std::wstring modes[] = { L"Manual", L"Loop Infinite", L"One-Shot", L"Prohibited" };
- SetDlgItemTextW(hDlg, IDC_SOUND0REPEATMODE + chanId, (wstringify(chn.reg.repeatMode) + L" (" + modes[chn.reg.repeatMode] + L")").c_str());
+ SetDlgItemTextW(hDlg, IDC_SOUND0REPEATMODE + chanId, (std::to_wstring(chn.reg.repeatMode) + L" (" + modes[chn.reg.repeatMode] + L")").c_str());
if (chn.reg.format != 3)
{
static const std::wstring formats[] = { L"PCM8", L"PCM16", L"IMA-ADPCM" };
- SetDlgItemTextW(hDlg, IDC_SOUND0FORMAT + chanId, (wstringify(chn.reg.format) + L" (" + formats[chn.reg.format] + L")").c_str());
+ SetDlgItemTextW(hDlg, IDC_SOUND0FORMAT + chanId, (std::to_wstring(chn.reg.format) + L" (" + formats[chn.reg.format] + L")").c_str());
}
else
{
@@ -290,7 +290,7 @@
if (chanId < 8)
buf += L"PSG/Noise?";
else if (chanId < 14)
- buf += wstringify(chn.reg.waveDuty == 7 ? 0 : 12.5 * (chn.reg.waveDuty + 1)) + L"% Square";
+ buf += std::to_wstring(chn.reg.waveDuty == 7 ? 0 : 12.5 * (chn.reg.waveDuty + 1)) + L"% Square";
else
buf += L"Noise";
buf += L")";
@@ -300,17 +300,17 @@
static const std::wstring states[] = { L"NONE", L"START", L"ATTACK", L"DECAY", L"SUSTAIN", L"RELEASE" };
SetDlgItemTextW(hDlg, IDC_SOUND0STATE + chanId, states[chn.state].c_str());
- SetDlgItemTextW(hDlg, IDC_SOUND0PNT + chanId, (L"samp #" + wstringify(chn.reg.loopStart)).c_str());
+ SetDlgItemTextW(hDlg, IDC_SOUND0PNT + chanId, (L"samp #" + std::to_wstring(chn.reg.loopStart)).c_str());
std::wstring tmpBuf = ConvertFuncs::StringToWString(NumToHexString(chn.reg.timer)).substr(2);
buf = L"$" + tmpBuf + L" (";
- tmpBuf = wstringify((ARM7_CLOCK / 2) / static_cast<double>(0x10000 - chn.reg.timer) / 8);
+ tmpBuf = std::to_wstring((ARM7_CLOCK / 2) / static_cast<double>(0x10000 - chn.reg.timer) / 8);
if (tmpBuf.find('.') != std::wstring::npos)
tmpBuf = tmpBuf.substr(0, tmpBuf.find('.') + 2);
buf += tmpBuf + L" Hz)";
SetDlgItemTextW(hDlg, IDC_SOUND0TMR + chanId, buf.c_str());
- SetDlgItemTextW(hDlg, IDC_SOUND0POSLEN + chanId, (L"samp #" + wstringify(static_cast<uint32_t>(chn.reg.samplePosition)) + L" / " + wstringify(chn.reg.totalLength)).c_str());
+ SetDlgItemTextW(hDlg, IDC_SOUND0POSLEN + chanId, (L"samp #" + std::to_wstring(static_cast<uint32_t>(chn.reg.samplePosition)) + L" / " + std::to_wstring(chn.reg.totalLength)).c_str());
}
else if (this->soundViewData->channelLastStates[chanId] != CS_NONE)
{
--- a/src/in_ncsf/XSFPlayer_NCSF.cpp
+++ b/src/in_ncsf/XSFPlayer_NCSF.cpp
@@ -83,7 +83,7 @@
do
{
found = false;
- std::string libTag = "_lib" + stringify(n++);
+ std::string libTag = "_lib" + std::to_string(n++);
if (xSFToLoad->GetTagExists(libTag))
{
found = true;
--- a/src/in_snsf/XSFConfig_SNSF.cpp
+++ b/src/in_snsf/XSFConfig_SNSF.cpp
@@ -101,7 +101,7 @@
// Mutes
for (int x = 0, numMutes = this->mutes.size(); x < numMutes; ++x)
{
- SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"BRRPCM " + wstringify(x + 1)).c_str()));
+ SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_ADDSTRING, 0, reinterpret_cast<LPARAM>((L"BRRPCM " + std::to_wstring(x + 1)).c_str()));
SendMessageW(GetDlgItem(hwndDlg, idMutes), LB_SETSEL, this->mutes[x], x);
}
break;
--- a/src/in_snsf/XSFPlayer_SNSF.cpp
+++ b/src/in_snsf/XSFPlayer_SNSF.cpp
@@ -183,7 +183,7 @@
do
{
found = false;
- std::string libTag = "_lib" + stringify(n++);
+ std::string libTag = "_lib" + std::to_string(n++);
if (xSF->GetTagExists(libTag))
{
found = true;
--- a/src/in_xsf_framework/XSFConfig.cpp
+++ b/src/in_xsf_framework/XSFConfig.cpp
@@ -228,7 +228,7 @@
SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::MSToWString(this->defaultFade).c_str());
SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::MSToWString(this->skipSilenceOnStartSec).c_str());
SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::MSToWString(this->detectSilenceSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idVolume), wstringify(this->volume).c_str());
+ SetWindowTextW(GetDlgItem(hwndDlg, idVolume), std::to_wstring(this->volume).c_str());
SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Disabled"));
SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Use Volume Tag"));
SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Track"));
@@ -241,7 +241,7 @@
for (unsigned x = 0, rates = this->supportedSampleRates.size(); x < rates; ++x)
{
unsigned rate = this->supportedSampleRates[x];
- SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(wstringify(rate).c_str()));
+ SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(std::to_wstring(rate).c_str()));
if (this->sampleRate == rate)
SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_SETCURSEL, x, 0);
}
@@ -335,7 +335,7 @@
SetWindowTextW(GetDlgItem(hwndDlg, idDefaultFade), ConvertFuncs::StringToWString(XSFConfig::initDefaultFade).c_str());
SetWindowTextW(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec), ConvertFuncs::StringToWString(XSFConfig::initSkipSilenceOnStartSec).c_str());
SetWindowTextW(GetDlgItem(hwndDlg, idDetectSilenceSec), ConvertFuncs::StringToWString(XSFConfig::initDetectSilenceSec).c_str());
- SetWindowTextW(GetDlgItem(hwndDlg, idVolume), wstringify(XSFConfig::initVolume).c_str());
+ SetWindowTextW(GetDlgItem(hwndDlg, idVolume), std::to_wstring(XSFConfig::initVolume).c_str());
SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_SETCURSEL, XSFConfig::initVolumeType, 0);
SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_SETCURSEL, XSFConfig::initPeakType, 0);
auto found = std::find(this->supportedSampleRates.begin(), this->supportedSampleRates.end(), XSFConfig::initSampleRate);
@@ -352,7 +352,7 @@
this->defaultFade = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDefaultFade)));
this->skipSilenceOnStartSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idSkipSilenceOnStartSec)));
this->detectSilenceSec = ConvertFuncs::StringToMS(this->GetTextFromWindow(GetDlgItem(hwndDlg, idDetectSilenceSec)));
- this->volume = convertTo<double>(this->GetTextFromWindow(GetDlgItem(hwndDlg, idVolume)), false);
+ this->volume = convertTo<double>(this->GetTextFromWindow(GetDlgItem(hwndDlg, idVolume)));
this->volumeType = static_cast<VolumeType>(SendMessageW(GetDlgItem(hwndDlg, idReplayGain), CB_GETCURSEL, 0, 0));
this->peakType = static_cast<PeakType>(SendMessageW(GetDlgItem(hwndDlg, idClipProtect), CB_GETCURSEL, 0, 0));
this->sampleRate = XSFConfig::supportedSampleRates[SendMessageW(GetDlgItem(hwndDlg, idSampleRate), CB_GETCURSEL, 0, 0)];
--- a/src/in_xsf_framework/XSFConfig.h
+++ b/src/in_xsf_framework/XSFConfig.h
@@ -24,10 +24,10 @@
virtual ~XSFConfigIO() { }
virtual void SetValueString(const std::string &name, const std::string &value) = 0;
- template<typename T> void SetValue(const std::string &name, const T &value) { this->SetValueString(name, stringify(value)); }
+ template<typename T> void SetValue(const std::string &name, const T &value) { this->SetValueString(name, std::to_string(value)); }
void SetValue(const std::string &name, const std::string &value) { this->SetValueString(name, value); }
virtual std::string GetValueString(const std::string &name, const std::string &defaultValue) const = 0;
- template<typename T> T GetValue(const std::string &name, const T &defaultValue) const { return convertTo<T>(this->GetValueString(name, stringify(defaultValue))); }
+ template<typename T> T GetValue(const std::string &name, const T &defaultValue) const { return convertTo<T>(this->GetValueString(name, std::to_string(defaultValue))); }
std::string GetValue(const std::string &name, const std::string &defaultValue) const { return this->GetValueString(name, defaultValue); }
virtual void SetHInstance(HINSTANCE) { }
virtual HINSTANCE GetHInstance() const { return nullptr; }
--- a/src/in_xsf_framework/XSFFile.cpp
+++ b/src/in_xsf_framework/XSFFile.cpp
@@ -325,24 +325,24 @@
bool hadReplayGain = false;
if (preferredVolumeType == VOLUMETYPE_REPLAYGAIN_ALBUM && !replaygain_album_gain.empty())
{
- gain = convertTo<double>(replaygain_album_gain, false);
+ gain = convertTo<double>(replaygain_album_gain);
hadReplayGain = true;
}
if (!hadReplayGain && preferredVolumeType != VOLUMETYPE_VOLUME && !replaygain_track_gain.empty())
{
- gain = convertTo<double>(replaygain_track_gain, false);
+ gain = convertTo<double>(replaygain_track_gain);
hadReplayGain = true;
}
if (hadReplayGain)
{
double vol = std::pow(10.0, gain / 20.0), peak = 1.0;
if (preferredPeakType == PEAKTYPE_REPLAYGAIN_ALBUM && !replaygain_album_peak.empty())
- peak = convertTo<double>(replaygain_album_peak, false);
+ peak = convertTo<double>(replaygain_album_peak);
else if (preferredPeakType != PEAKTYPE_NONE && !replaygain_track_peak.empty())
- peak = convertTo<double>(replaygain_track_peak, false);
+ peak = convertTo<double>(replaygain_track_peak);
return !fEqual(peak, 1.0) ? std::min(vol, 1.0 / peak) : vol;
}
- return volume.empty() ? 1.0 : convertTo<double>(volume, false);
+ return volume.empty() ? 1.0 : convertTo<double>(volume);
}
std::string XSFFile::FormattedTitleOptionalBlock(const std::string &block, bool &hadReplacement, unsigned level) const
--- a/src/in_xsf_framework/XSFFile.h
+++ b/src/in_xsf_framework/XSFFile.h
@@ -63,7 +63,7 @@
std::string GetTagValue(const std::string &name) const;
template<typename T> T GetTagValue(const std::string &name, const T &defaultValue) const
{
- return this->GetTagExists(name) ? convertTo<T>(this->GetTagValue(name), false) : defaultValue;
+ return this->GetTagExists(name) ? convertTo<T>(this->GetTagValue(name)) : defaultValue;
}
unsigned long GetLengthMS(unsigned long defaultLength) const;
unsigned long GetFadeMS(unsigned long defaultFade) const;
--- a/src/in_xsf_framework/convert.h
+++ b/src/in_xsf_framework/convert.h
@@ -5,61 +5,54 @@
#pragma once
-#include <stdexcept>
#include <string>
#include <sstream>
-#include <typeinfo>
#include <locale>
-#include <codecvt>
#include <vector>
#include <memory>
+#include <type_traits>
#include <cmath>
#include "windowsh_wrapper.h"
-/*
- * The following exception class and the *stringify and convert* functions are
- * from the C++ FAQ, section 39, entry 3:
- * http://www.parashift.com/c++-faq/convert-string-to-any.html
- *
- * The convert and convertTo functions were made into templates of std::basic_string
- * to handle wide-character strings properly, as well as adding wstringify for the
- * same reason.
- */
-class BadConversion : public std::runtime_error
+ /*
+ * Originally the convert* functions came from the C++ FAQ, Miscellaneous Technical Issues:
+ * https://isocpp.org/wiki/faq/misc-technical-issues#convert-string-to-any
+ *
+ * They have been replaced with a couple functions that use the C++11 std::enable_if
+ * construct along with various other type traits constructs to use the proper
+ * string conversions.
+ */
+template<typename T, typename S> inline typename std::enable_if_t<!std::is_enum_v<T> &&std::is_arithmetic_v<T>, T> convertTo(const std::basic_string<S> &s)
{
-public:
- BadConversion(const std::string &s) : std::runtime_error(s) { }
-};
-
-template<typename T> inline std::string stringify(const T &x)
+ if (std::is_integral_v<T>)
+ {
+ if (std::is_unsigned_v<T>)
+ {
+ if (std::is_same_v<unsigned long long, std::remove_cv_t<T>>)
+ return static_cast<T>(std::stoull(s));
+ else
+ return static_cast<T>(std::stoul(s));
+ }
+ else if (std::is_same_v<long long, std::remove_cv_t<T>>)
+ return static_cast<T>(std::stoll(s));
+ else if (std::is_same_v<long, std::remove_cv_t<T>>)
+ return static_cast<T>(std::stol(s));
+ else
+ return static_cast<T>(std::stoi(s));
+ }
+ else if (std::is_floating_point_v<T>)
+ {
+ if (std::is_same_v<long double, std::remove_cv_t<T>>)
+ return static_cast<T>(std::stold(s));
+ else if (std::is_same_v<double, std::remove_cv_t<T>>)
+ return static_cast<T>(std::stod(s));
+ else
+ return static_cast<T>(std::stof(s));
+ }
+}
+template<typename T, typename S> inline typename std::enable_if_t<std::is_enum_v<T>, T> convertTo(const std::basic_string<S> &s)
{
- std::ostringstream o;
- if (!(o << x))
- throw BadConversion(std::string("stringify(") + typeid(x).name() + ")");
- return o.str();
-}
-
-template<typename T> inline std::wstring wstringify(const T &x)
-{
- std::wostringstream o;
- if (!(o << x))
- throw BadConversion(std::string("wstringify(") + typeid(x).name() + ")");
- return o.str();
-}
-
-template<typename T, typename S> inline void convert(const std::basic_string<S> &s, T &x, bool failIfLeftoverChars = true)
-{
- std::basic_istringstream<S> i(s);
- S c;
- if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
- throw BadConversion(std::string("convert(") + typeid(S).name() + ")");
-}
-
-template<typename T, typename S> inline T convertTo(const std::basic_string<S> &s, bool failIfLeftoverChars = true)
-{
- T x;
- convert(s, x, failIfLeftoverChars);
- return x;
+ return static_cast<T>(convertTo<std::underlying_type_t<T>>(s));
}
// Miscellaneous conversion functions
@@ -107,13 +100,13 @@
{
if (!ConvertFuncs::IsDigitsOnly(hoursStr))
return 0;
- hours = convertTo<unsigned long>(hoursStr, false);
+ hours = convertTo<unsigned long>(hoursStr);
}
if (!minutesStr.empty())
{
if (!ConvertFuncs::IsDigitsOnly(minutesStr))
return 0;
- minutes = convertTo<unsigned long>(minutesStr, false);
+ minutes = convertTo<unsigned long>(minutesStr);
}
if (!secondsStr.empty())
{
@@ -122,7 +115,7 @@
size_t comma = secondsStr.find(',');
if (comma != std::string::npos)
secondsStr[comma] = '.';
- seconds = convertTo<double>(secondsStr, false);
+ seconds = convertTo<double>(secondsStr);
}
seconds += minutes * 60 + hours * 1440;
return static_cast<unsigned long>(std::floor(seconds * 1000 + 0.5));
@@ -137,14 +130,14 @@
{
double seconds = time / 1000.0;
if (seconds < 60)
- return stringify(seconds);
+ return std::to_string(seconds);
unsigned long minutes = static_cast<unsigned long>(seconds) / 60;
seconds -= minutes * 60;
if (minutes < 60)
- return stringify(minutes) + ":" + (seconds < 10 ? "0" : "") + stringify(seconds);
+ return std::to_string(minutes) + ":" + (seconds < 10 ? "0" : "") + std::to_string(seconds);
unsigned long hours = minutes / 60;
minutes %= 60;
- return stringify(hours) + ":" + (minutes < 10 ? "0" : "") + stringify(minutes) + ":" + (seconds < 10 ? "0" : "") + stringify(seconds);
+ return std::to_string(hours) + ":" + (minutes < 10 ? "0" : "") + std::to_string(minutes) + ":" + (seconds < 10 ? "0" : "") + std::to_string(seconds);
}
static std::wstring MSToWString(unsigned long time)
--- a/src/in_xsf_framework/in_xsf.cpp
+++ b/src/in_xsf_framework/in_xsf.cpp
@@ -335,7 +335,7 @@
return 0;
}
else if (eqstr(tagToGet, "length"))
- tag = stringify(file.GetLengthMS(xSFConfig->GetDefaultLength()) + file.GetFadeMS(xSFConfig->GetDefaultFade()));
+ tag = std::to_string(file.GetLengthMS(xSFConfig->GetDefaultLength()) + file.GetFadeMS(xSFConfig->GetDefaultFade()));
else
tag = file.GetTagValue(tagToGet);
CopyToString(tag.substr(0, destlen - 1), dest);