Reformat config and config attribute code
This commit is contained in:
parent
96ca0b026e
commit
1707070d6f
2 changed files with 438 additions and 318 deletions
521
src/config.cpp
521
src/config.cpp
File diff suppressed because it is too large
Load diff
|
@ -23,13 +23,13 @@
|
|||
#include "lexical_cast.hpp"
|
||||
#include "log.hpp"
|
||||
#include "utils/const_clone.hpp"
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <istream>
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
@ -39,14 +39,12 @@ static lg::log_domain log_config("config");
|
|||
#define ERR_CF LOG_STREAM(err, log_config)
|
||||
#define DBG_CF LOG_STREAM(debug, log_config)
|
||||
|
||||
|
||||
// Special string values.
|
||||
const std::string config_attribute_value::s_yes("yes");
|
||||
const std::string config_attribute_value::s_no("no");
|
||||
const std::string config_attribute_value::s_true("true");
|
||||
const std::string config_attribute_value::s_false("false");
|
||||
|
||||
|
||||
/** Default implementation, but defined out-of-line for efficiency reasons. */
|
||||
config_attribute_value::config_attribute_value()
|
||||
: value_()
|
||||
|
@ -59,39 +57,41 @@ config_attribute_value::~config_attribute_value()
|
|||
}
|
||||
|
||||
/** Default implementation, but defined out-of-line for efficiency reasons. */
|
||||
config_attribute_value::config_attribute_value(const config_attribute_value &that)
|
||||
config_attribute_value::config_attribute_value(const config_attribute_value& that)
|
||||
: value_(that.value_)
|
||||
{
|
||||
}
|
||||
|
||||
/** Default implementation, but defined out-of-line for efficiency reasons. */
|
||||
config_attribute_value &config_attribute_value::operator=(const config_attribute_value &that)
|
||||
config_attribute_value& config_attribute_value::operator=(const config_attribute_value& that)
|
||||
{
|
||||
value_ = that.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(bool v)
|
||||
config_attribute_value& config_attribute_value::operator=(bool v)
|
||||
{
|
||||
value_ = yes_no(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(int v)
|
||||
config_attribute_value& config_attribute_value::operator=(int v)
|
||||
{
|
||||
value_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(long long v)
|
||||
config_attribute_value& config_attribute_value::operator=(long long v)
|
||||
{
|
||||
if ( v > 0 )
|
||||
if(v > 0) {
|
||||
// We can store this unsigned.
|
||||
return *this = static_cast<unsigned long long>(v);
|
||||
}
|
||||
|
||||
if ( v >= INT_MIN )
|
||||
if(v >= INT_MIN) {
|
||||
// We can store this as an int.
|
||||
return *this = static_cast<int>(v);
|
||||
}
|
||||
|
||||
// Getting to this point should be rare. (Currently, getting here means
|
||||
// something like there was so much draining in a campaign that the
|
||||
|
@ -102,30 +102,32 @@ config_attribute_value &config_attribute_value::operator=(long long v)
|
|||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(unsigned long long v)
|
||||
config_attribute_value& config_attribute_value::operator=(unsigned long long v)
|
||||
{
|
||||
// Use int for smaller numbers.
|
||||
if ( v <= INT_MAX )
|
||||
if(v <= INT_MAX) {
|
||||
return *this = static_cast<int>(v);
|
||||
}
|
||||
|
||||
value_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(double v)
|
||||
config_attribute_value& config_attribute_value::operator=(double v)
|
||||
{
|
||||
// Try to store integers in other types.
|
||||
if ( v > 0.0 ) {
|
||||
if(v > 0.0) {
|
||||
// Convert to unsigned and pass this off to that assignment operator.
|
||||
unsigned long long ull = static_cast<unsigned long long>(v);
|
||||
if ( static_cast<double>(ull) == v )
|
||||
if(static_cast<double>(ull) == v) {
|
||||
return *this = ull;
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
// Convert to integer and pass this off to that assignment operator.
|
||||
int i = static_cast<int>(v);
|
||||
if ( static_cast<double>(i) == v )
|
||||
if(static_cast<double>(i) == v) {
|
||||
return *this = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, this does in fact get stored as a double.
|
||||
|
@ -133,55 +135,78 @@ config_attribute_value &config_attribute_value::operator=(double v)
|
|||
return *this;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Attempts to convert @a source to the template type.
|
||||
* This is to avoid "overzealous reinterpretations of certain WML strings as
|
||||
* numeric types" (c.f. bug #19201).
|
||||
* @returns true if the conversion was successful and the source string
|
||||
* can be reobtained by streaming the result.
|
||||
*/
|
||||
template<typename To>
|
||||
bool from_string_verify(const std::string & source, To & res)
|
||||
{
|
||||
// Check 1: convertable to the target type.
|
||||
std::istringstream in_str(source);
|
||||
if ( !(in_str >> res) )
|
||||
return false;
|
||||
|
||||
// Check 2: convertable back to the same string.
|
||||
std::ostringstream out_str;
|
||||
out_str << res;
|
||||
return out_str.str() == source;
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* Attempts to convert @a source to the template type.
|
||||
* This is to avoid "overzealous reinterpretations of certain WML strings as
|
||||
* numeric types" (c.f. bug #19201).
|
||||
* @returns true if the conversion was successful and the source string
|
||||
* can be reobtained by streaming the result.
|
||||
*/
|
||||
template<typename To>
|
||||
bool from_string_verify(const std::string& source, To& res)
|
||||
{
|
||||
// Check 1: convertable to the target type.
|
||||
std::istringstream in_str(source);
|
||||
if(!(in_str >> res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check 2: convertable back to the same string.
|
||||
std::ostringstream out_str;
|
||||
out_str << res;
|
||||
return out_str.str() == source;
|
||||
}
|
||||
config_attribute_value &config_attribute_value::operator=(const std::string &v)
|
||||
} // end anon namespace
|
||||
|
||||
config_attribute_value& config_attribute_value::operator=(const std::string& v)
|
||||
{
|
||||
// Handle some special strings.
|
||||
if (v.empty()) { value_ = v; return *this; }
|
||||
if ( v == s_yes ) { value_ = yes_no(true); return *this; }
|
||||
if ( v == s_no ) { value_ = yes_no(false); return *this; }
|
||||
if ( v == s_true ) { value_ = true_false(true); return *this; }
|
||||
if ( v == s_false ) { value_ = true_false(false); return *this; }
|
||||
if(v.empty()) {
|
||||
value_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(v == s_yes) {
|
||||
value_ = yes_no(true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(v == s_no) {
|
||||
value_ = yes_no(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(v == s_true) {
|
||||
value_ = true_false(true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(v == s_false) {
|
||||
value_ = true_false(false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Attempt to convert to a number.
|
||||
char *eptr;
|
||||
char* eptr;
|
||||
double d = strtod(v.c_str(), &eptr);
|
||||
if ( *eptr == '\0' ) {
|
||||
if(*eptr == '\0') {
|
||||
// Possibly a number. See what type it should be stored in.
|
||||
// (All conversions will be from the string since the largest integer
|
||||
// type could have more precision than a double.)
|
||||
if ( d > 0.0 ) {
|
||||
if(d > 0.0) {
|
||||
// The largest type for positive integers is unsigned long long.
|
||||
unsigned long long ull = 0;
|
||||
if ( from_string_verify<unsigned long long>(v, ull) )
|
||||
if(from_string_verify<unsigned long long>(v, ull)) {
|
||||
return *this = ull;
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
// The largest (variant) type for negative integers is int.
|
||||
int i = 0;
|
||||
if ( from_string_verify<int>(v, i) )
|
||||
if(from_string_verify<int>(v, i)) {
|
||||
return *this = i;
|
||||
}
|
||||
}
|
||||
|
||||
// This does not look like an integer, so it should be a double.
|
||||
|
@ -189,7 +214,7 @@ config_attribute_value &config_attribute_value::operator=(const std::string &v)
|
|||
// case this is a string that just looks like a numeric value).
|
||||
std::ostringstream tester;
|
||||
tester << d;
|
||||
if ( tester.str() == v ) {
|
||||
if(tester.str() == v) {
|
||||
value_ = d;
|
||||
return *this;
|
||||
}
|
||||
|
@ -200,46 +225,49 @@ config_attribute_value &config_attribute_value::operator=(const std::string &v)
|
|||
return *this;
|
||||
}
|
||||
|
||||
config_attribute_value &config_attribute_value::operator=(const t_string &v)
|
||||
config_attribute_value& config_attribute_value::operator=(const t_string& v)
|
||||
{
|
||||
if (!v.translatable()) return *this = v.str();
|
||||
if(!v.translatable()) {
|
||||
return *this = v.str();
|
||||
}
|
||||
|
||||
value_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool config_attribute_value::to_bool(bool def) const
|
||||
{
|
||||
if ( const yes_no *p = boost::get<const yes_no>(&value_) )
|
||||
if(const yes_no* p = boost::get<const yes_no>(&value_))
|
||||
return *p;
|
||||
if ( const true_false *p = boost::get<const true_false>(&value_) )
|
||||
if(const true_false* p = boost::get<const true_false>(&value_))
|
||||
return *p;
|
||||
|
||||
// No other types are ever recognized as boolean.
|
||||
return def;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Visitor for converting a variant to a numeric type (T).
|
||||
template <typename T>
|
||||
class attribute_numeric_visitor : public boost::static_visitor<T>
|
||||
{
|
||||
public:
|
||||
// Constructor stores the default value.
|
||||
attribute_numeric_visitor(T def) : def_(def) {}
|
||||
namespace
|
||||
{
|
||||
/// Visitor for converting a variant to a numeric type (T).
|
||||
template<typename T>
|
||||
class attribute_numeric_visitor : public boost::static_visitor<T>
|
||||
{
|
||||
public:
|
||||
// Constructor stores the default value.
|
||||
attribute_numeric_visitor(T def) : def_(def) {}
|
||||
|
||||
T operator()(boost::blank const &) const { return def_; }
|
||||
T operator()(bool) const { return def_; }
|
||||
T operator()(int i) const { return static_cast<T>(i); }
|
||||
T operator()(unsigned long long u) const { return static_cast<T>(u); }
|
||||
T operator()(double d) const { return static_cast<T>(d); }
|
||||
T operator()(const std::string& s) const { return lexical_cast_default<T>(s, def_); }
|
||||
T operator()(t_string const &) const { return def_; }
|
||||
T operator()(boost::blank const &) const { return def_; }
|
||||
T operator()(bool) const { return def_; }
|
||||
T operator()(int i) const { return static_cast<T>(i); }
|
||||
T operator()(unsigned long long u) const { return static_cast<T>(u); }
|
||||
T operator()(double d) const { return static_cast<T>(d); }
|
||||
T operator()(const std::string& s) const { return lexical_cast_default<T>(s, def_); }
|
||||
T operator()(t_string const &) const { return def_; }
|
||||
|
||||
private:
|
||||
const T def_;
|
||||
};
|
||||
}
|
||||
private:
|
||||
const T def_;
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
int config_attribute_value::to_int(int def) const
|
||||
{
|
||||
|
@ -272,12 +300,13 @@ double config_attribute_value::to_double(double def) const
|
|||
}
|
||||
|
||||
/// Visitor for converting a variant to a string.
|
||||
class config_attribute_value::string_visitor
|
||||
: public boost::static_visitor<std::string>
|
||||
class config_attribute_value::string_visitor : public boost::static_visitor<std::string>
|
||||
{
|
||||
const std::string default_;
|
||||
|
||||
public:
|
||||
string_visitor(const std::string& fallback) : default_(fallback) {}
|
||||
|
||||
std::string operator()(const boost::blank &) const { return default_; }
|
||||
std::string operator()(const yes_no & b) const { return b.str(); }
|
||||
std::string operator()(const true_false & b) const { return b.str(); }
|
||||
|
@ -295,7 +324,10 @@ std::string config_attribute_value::str(const std::string& fallback) const
|
|||
|
||||
t_string config_attribute_value::t_str() const
|
||||
{
|
||||
if (const t_string *p = boost::get<const t_string>(&value_)) return *p;
|
||||
if(const t_string* p = boost::get<const t_string>(&value_)) {
|
||||
return *p;
|
||||
}
|
||||
|
||||
return str();
|
||||
}
|
||||
|
||||
|
@ -312,28 +344,45 @@ bool config_attribute_value::blank() const
|
|||
*/
|
||||
bool config_attribute_value::empty() const
|
||||
{
|
||||
if (boost::get<const boost::blank>(&value_)) return true;
|
||||
if (const std::string *p = boost::get<const std::string>(&value_)) return p->empty();
|
||||
if(boost::get<const boost::blank>(&value_)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(const std::string* p = boost::get<const std::string>(&value_)) {
|
||||
return p->empty();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Visitor handling equality checks.
|
||||
class config_attribute_value::equality_visitor
|
||||
: public boost::static_visitor<bool>
|
||||
class config_attribute_value::equality_visitor : public boost::static_visitor<bool>
|
||||
{
|
||||
public:
|
||||
// Most generic: not equal.
|
||||
template <typename T, typename U>
|
||||
bool operator()(const T &, const U &) const { return false; }
|
||||
template<typename T, typename U>
|
||||
bool operator()(const T&, const U&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same types are comparable and might be equal.
|
||||
template <typename T>
|
||||
bool operator()(const T & lhs, const T & rhs) const { return lhs == rhs; }
|
||||
template<typename T>
|
||||
bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
// Boolean values can be compared.
|
||||
bool operator()(const true_false & lhs, const yes_no & rhs) const { return bool(lhs) == bool(rhs); }
|
||||
bool operator()(const yes_no & lhs, const true_false & rhs) const { return bool(lhs) == bool(rhs); }
|
||||
bool operator()(const true_false& lhs, const yes_no& rhs) const
|
||||
{
|
||||
return bool(lhs) == bool(rhs);
|
||||
}
|
||||
|
||||
bool operator()(const yes_no& lhs, const true_false& rhs) const
|
||||
{
|
||||
return bool(lhs) == bool(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -341,7 +390,7 @@ public:
|
|||
* Exception: Boolean synonyms can be equal ("yes" == "true").
|
||||
* Note: Blanks have no string representation, so do not equal "" (an empty string).
|
||||
*/
|
||||
bool config_attribute_value::operator==(const config_attribute_value &other) const
|
||||
bool config_attribute_value::operator==(const config_attribute_value& other) const
|
||||
{
|
||||
return boost::apply_visitor(equality_visitor(), value_, other.value_);
|
||||
}
|
||||
|
@ -352,7 +401,7 @@ bool config_attribute_value::operator==(const config_attribute_value &other) con
|
|||
* Note: Blanks have no string representation, so do not equal "" (an empty string).
|
||||
* Also note that translatable string are never equal to non translatable strings.
|
||||
*/
|
||||
bool config_attribute_value::equals(const std::string &str) const
|
||||
bool config_attribute_value::equals(const std::string& str) const
|
||||
{
|
||||
config_attribute_value v;
|
||||
v = str;
|
||||
|
@ -363,7 +412,7 @@ bool config_attribute_value::equals(const std::string &str) const
|
|||
// that's why we don't use it.
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const config_attribute_value &v)
|
||||
std::ostream& operator<<(std::ostream& os, const config_attribute_value& v)
|
||||
{
|
||||
// Simple implementation, but defined out-of-line because of the templating
|
||||
// involved.
|
||||
|
|
Loading…
Add table
Reference in a new issue