[Ram Device] Better detection of bad -ramsize strings, move some private code to anonymous namespace (#2336)

* [Ram Device] Better detection of bad -ramsize strings, move code to anonymous namespace

There was a longstanding bug where '-ramsize 16kfoo' would be treated as '-ramsize 16k'

* Changed parse_string() to explicitly look for the suffixes "[k|m][|b|ib]"
This commit is contained in:
npwoods 2017-06-01 06:42:09 -04:00 committed by Olivier Galibert
parent 154976bb85
commit b991f2acd6
2 changed files with 77 additions and 70 deletions

View File

@ -17,6 +17,83 @@
#include <algorithm>
namespace {
//-------------------------------------------------
// parse_string - convert a ram string to an
// integer value
//-------------------------------------------------
uint32_t parse_string(const char *s)
{
static const struct
{
const char *suffix;
unsigned multiple;
} s_suffixes[] =
{
{ "", 1 },
{ "k", 1024 },
{ "kb", 1024 },
{ "kib", 1024 },
{ "m", 1024 * 1024 },
{ "mb", 1024 * 1024 },
{ "mib", 1024 * 1024 }
};
// parse the string
unsigned ram = 0;
char suffix[8] = { 0, };
sscanf(s, "%u%7s", &ram, suffix);
// perform the lookup
auto iter = std::find_if(
std::begin(s_suffixes),
std::end(s_suffixes),
[&suffix](const auto &potential_suffix) { return !core_stricmp(suffix, potential_suffix.suffix); });
// identify the multiplier (or 0 if not recognized, signalling a parse failure)
unsigned multiple = iter != std::end(s_suffixes)
? iter->multiple
: 0;
// return the result
return ram * multiple;
}
//-------------------------------------------------
// calculate_extra_options
//-------------------------------------------------
std::vector<uint32_t> calculate_extra_options(const char *extra_options_string, std::string *bad_option)
{
std::vector<uint32_t> result;
std::string options(extra_options_string);
bool done = false;
for (std::string::size_type start = 0, end = options.find_first_of(','); !done; start = end + 1, end = options.find_first_of(',', start))
{
// parse the option
const std::string ram_option_string = options.substr(start, (end == -1) ? -1 : end - start);
const uint32_t ram_option = parse_string(ram_option_string.c_str());
if (ram_option == 0)
{
if (bad_option)
*bad_option = std::move(ram_option_string);
return result;
}
// and add it to the results
result.push_back(ram_option);
done = end == std::string::npos;
}
return result;
}
};
/*****************************************************************************
LIVE DEVICE
*****************************************************************************/
@ -121,44 +198,6 @@ bool ram_device::is_valid_size(uint32_t size) const
}
//-------------------------------------------------
// parse_string - convert a ram string to an
// integer value
//-------------------------------------------------
uint32_t ram_device::parse_string(const char *s)
{
uint32_t ram;
char suffix = '\0';
sscanf(s, "%u%c", &ram, &suffix);
switch(tolower(suffix))
{
case 'k':
/* kilobytes */
ram *= 1024;
break;
case 'm':
/* megabytes */
ram *= 1024*1024;
break;
case '\0':
/* no suffix */
break;
default:
/* parse failure */
ram = 0;
break;
}
return ram;
}
//-------------------------------------------------
// default_size
//-------------------------------------------------
@ -179,33 +218,3 @@ const std::vector<uint32_t> &ram_device::extra_options(void) const
m_extra_options = calculate_extra_options(m_extra_options_string, nullptr);
return m_extra_options;
}
//-------------------------------------------------
// calculate_extra_options
//-------------------------------------------------
std::vector<uint32_t> ram_device::calculate_extra_options(const char *extra_options_string, std::string *bad_option)
{
std::vector<uint32_t> result;
std::string options(extra_options_string);
bool done = false;
for (std::string::size_type start = 0, end = options.find_first_of(','); !done; start = end + 1, end = options.find_first_of(',', start))
{
// parse the option
const std::string ram_option_string = options.substr(start, (end == -1) ? -1 : end - start);
const uint32_t ram_option = parse_string(ram_option_string.c_str());
if (ram_option == 0)
{
if (bad_option)
*bad_option = std::move(ram_option_string);
return result;
}
// and add it to the results
result.push_back(ram_option);
done = end == std::string::npos;
}
return result;
}

View File

@ -76,8 +76,6 @@ protected:
virtual void device_validity_check(validity_checker &valid) const override;
private:
static std::vector<uint32_t> calculate_extra_options(const char *extra_options_string, std::string *bad_option);
static uint32_t parse_string(const char *s);
bool is_valid_size(uint32_t size) const;
// device state