xlnt/source/value.cpp

338 lines
6.5 KiB
C++

#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);
}
value::value(const value &v)
{
type_ = v.type_;
numeric_value_ = v.numeric_value_;
string_value_ = v.string_value_;
}
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;
}
value &value::operator=(int i)
{
return *this = value(i);
}
bool value::is(type t) const
{
return type_ == t;
}
template<>
std::string value::get() const
{
if(type_ == type::string)
{
return string_value_;
}
throw std::runtime_error("not a string");
}
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