2014-07-26 04:39:25 +08:00
|
|
|
#include "cell/value.hpp"
|
|
|
|
#include "common/datetime.hpp"
|
|
|
|
|
|
|
|
namespace xlnt {
|
|
|
|
|
|
|
|
value value::error(const std::string &error_string)
|
|
|
|
{
|
|
|
|
value v(error_string);
|
|
|
|
v.type_ = type::error;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value() : type_(type::null), numeric_value_(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(value &&v)
|
|
|
|
{
|
|
|
|
swap(*this, v);
|
|
|
|
}
|
|
|
|
|
2014-07-27 04:19:15 +08:00
|
|
|
value::value(const value &v)
|
|
|
|
{
|
|
|
|
type_ = v.type_;
|
|
|
|
numeric_value_ = v.numeric_value_;
|
|
|
|
string_value_ = v.string_value_;
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
value::value(bool b) : type_(type::boolean), numeric_value_(b ? 1 : 0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(int i) : type_(type::numeric), numeric_value_(i)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(double d) : type_(type::numeric), numeric_value_(d)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(int64_t i) : type_(type::numeric), numeric_value_((long double)i)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(const char *s) : value(std::string(s))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value::value(const std::string &s) : type_(type::string), string_value_(s)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
value &value::operator=(value other)
|
|
|
|
{
|
|
|
|
swap(*this, other);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-07-27 04:19:15 +08:00
|
|
|
value &value::operator=(int i)
|
|
|
|
{
|
|
|
|
return *this = value(i);
|
|
|
|
}
|
|
|
|
|
2014-07-26 04:39:25 +08:00
|
|
|
bool value::is(type t) const
|
|
|
|
{
|
|
|
|
return type_ == t;
|
|
|
|
}
|
2014-07-27 04:19:15 +08:00
|
|
|
|
|
|
|
template<>
|
|
|
|
std::string value::get() const
|
|
|
|
{
|
|
|
|
if(type_ == type::string)
|
|
|
|
{
|
|
|
|
return string_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw std::runtime_error("not a string");
|
|
|
|
}
|
2014-07-26 04:39:25 +08:00
|
|
|
|
|
|
|
template<>
|
|
|
|
double value::as() const
|
|
|
|
{
|
|
|
|
switch(type_)
|
|
|
|
{
|
|
|
|
case type::boolean:
|
|
|
|
case type::numeric:
|
|
|
|
return (double)numeric_value_;
|
|
|
|
case type::string:
|
|
|
|
return std::stod(string_value_);
|
|
|
|
case type::error:
|
|
|
|
throw std::runtime_error("invalid");
|
|
|
|
case type::null:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int value::as() const
|
|
|
|
{
|
|
|
|
switch(type_)
|
|
|
|
{
|
|
|
|
case type::boolean:
|
|
|
|
case type::numeric:
|
|
|
|
return (int)numeric_value_;
|
|
|
|
case type::string:
|
|
|
|
return std::stoi(string_value_);
|
|
|
|
case type::error:
|
|
|
|
throw std::runtime_error("invalid");
|
|
|
|
case type::null:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
int64_t value::as() const
|
|
|
|
{
|
|
|
|
switch(type_)
|
|
|
|
{
|
|
|
|
case type::boolean:
|
|
|
|
case type::numeric:
|
|
|
|
return (int64_t)numeric_value_;
|
|
|
|
case type::string:
|
|
|
|
return std::stoi(string_value_);
|
|
|
|
case type::error:
|
|
|
|
throw std::runtime_error("invalid");
|
|
|
|
case type::null:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
bool value::as() const
|
|
|
|
{
|
|
|
|
switch(type_)
|
|
|
|
{
|
|
|
|
case type::boolean:
|
|
|
|
case type::numeric:
|
|
|
|
return numeric_value_ != 0;
|
|
|
|
case type::string:
|
|
|
|
return !string_value_.empty();
|
|
|
|
case type::error:
|
|
|
|
throw std::runtime_error("invalid");
|
|
|
|
case type::null:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::is_integral() const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && (int64_t)numeric_value_ == numeric_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
std::string value::as() const
|
|
|
|
{
|
|
|
|
return to_string();
|
|
|
|
}
|
|
|
|
|
|
|
|
value value::null()
|
|
|
|
{
|
|
|
|
return value();
|
|
|
|
}
|
|
|
|
|
|
|
|
value::type value::get_type() const
|
|
|
|
{
|
|
|
|
return type_;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string value::to_string() const
|
|
|
|
{
|
|
|
|
switch(type_)
|
|
|
|
{
|
|
|
|
case type::boolean:
|
|
|
|
return numeric_value_ != 0 ? "1" : "0";
|
|
|
|
case type::numeric:
|
|
|
|
return std::to_string(numeric_value_);
|
|
|
|
case type::string:
|
|
|
|
case type::error:
|
|
|
|
return string_value_;
|
|
|
|
case type::null:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(bool value) const
|
|
|
|
{
|
|
|
|
return type_ == type::boolean && (numeric_value_ != 0) == value;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(int comparand) const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && numeric_value_ == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(double comparand) const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && numeric_value_ == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const std::string &comparand) const
|
|
|
|
{
|
|
|
|
if(type_ == type::string)
|
|
|
|
{
|
|
|
|
return string_value_ == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const char *comparand) const
|
|
|
|
{
|
|
|
|
return *this == std::string(comparand);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const time &comparand) const
|
|
|
|
{
|
|
|
|
if(type_ != type::numeric)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return time::from_number(numeric_value_) == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const date &comparand) const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && comparand.to_number(calendar::windows_1900) == numeric_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const datetime &comparand) const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && comparand.to_number(calendar::windows_1900) == numeric_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const timedelta &comparand) const
|
|
|
|
{
|
|
|
|
return type_ == type::numeric && comparand.to_number() == numeric_value_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool value::operator==(const value &v) const
|
|
|
|
{
|
|
|
|
if(type_ != v.type_) return false;
|
|
|
|
if(type_ == type::string || type_ == type::error) return string_value_ == v.string_value_;
|
|
|
|
if(type_ == type::numeric || type_ == type::boolean) return numeric_value_ == v.numeric_value_;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
value &value::operator=(const time &value)
|
|
|
|
{
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->numeric_value = value.to_number();
|
|
|
|
d_->is_date_ = true;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
value &value::operator=(const date &value)
|
|
|
|
{
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
auto base_year = worksheet(d_->parent_).get_parent().get_properties().excel_base_date;
|
|
|
|
d_->numeric_value = value.to_number(base_year);
|
|
|
|
d_->is_date_ = true;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
value &value::operator=(const datetime &value)
|
|
|
|
{
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
auto base_year = worksheet(d_->parent_).get_parent().get_properties().excel_base_date;
|
|
|
|
d_->numeric_value = value.to_number(base_year);
|
|
|
|
d_->is_date_ = true;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
value &value::operator=(const timedelta &value)
|
|
|
|
{
|
|
|
|
d_->type_ = type::numeric;
|
|
|
|
d_->numeric_value = value.to_number();
|
|
|
|
d_->is_date_ = true;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool operator==(bool comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(int comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const char *comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const std::string &comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const time &comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const date &comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const datetime &comparand, const xlnt::value &value)
|
|
|
|
{
|
|
|
|
return value == comparand;
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(value &left, value &right)
|
|
|
|
{
|
|
|
|
using std::swap;
|
|
|
|
swap(left.type_, right.type_);
|
|
|
|
swap(left.string_value_, right.string_value_);
|
|
|
|
swap(left.numeric_value_, right.numeric_value_);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace xlnt
|