#include #include #include #include #include namespace xlnt { std::size_t cell_reference_hash::operator()(const cell_reference &k) const { return k.get_row() * constants::MaxColumn().index + k.get_column_index().index; } cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolute_row) { column_absolute(absolute_column); row_absolute(absolute_row); return *this; } cell_reference::cell_reference() : cell_reference(1, 1) { } cell_reference::cell_reference(const string &string) { auto split = split_reference(string, absolute_column_, absolute_row_); set_column(split.first); set_row(split.second); } cell_reference::cell_reference(const char *reference_string) : cell_reference(string(reference_string)) { } cell_reference::cell_reference(const string &column, row_t row) : cell_reference(column_t(column), row) { } cell_reference::cell_reference(column_t column_index, row_t row) : column_(column_index), row_(row), absolute_row_(false), absolute_column_(false) { if (row_ == 0 || !(row_ <= constants::MaxRow()) || column_ == 0 || !(column_ <= constants::MaxColumn())) { throw cell_coordinates_exception(column_, row_); } } range_reference cell_reference::operator, (const xlnt::cell_reference &other) const { return range_reference(*this, other); } string cell_reference::to_string() const { string string_representation; if (absolute_column_) { string_representation.append("$"); } string_representation.append(column_.column_string()); if (absolute_row_) { string_representation.append("$"); } string_representation.append(string::from(row_)); return string_representation; } range_reference cell_reference::to_range() const { return range_reference(column_, row_, column_, row_); } std::pair cell_reference::split_reference(const string &reference_string, bool &absolute_column, bool &absolute_row) { absolute_column = false; absolute_row = false; auto is_alpha = [](string::code_point c) { return (c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z'); }; auto upper_ref_string = reference_string.to_upper(); auto iter = upper_ref_string.begin(); auto end = upper_ref_string.end(); while(iter != end && (is_alpha(*iter) || *iter == U'$')) { ++iter; } string column_string(upper_ref_string.begin(), iter); if (column_string.length() > 1 && column_string.front() == '$') { absolute_column = true; column_string.erase(0); } if (column_string.length() > 1 && column_string.back() == '$') { absolute_row = true; column_string.erase(column_string.length() - 1); } string row_string(iter, end); auto is_digit = [](string::code_point c) { return (c >= U'0' && c <= U'9'); }; for(auto c : row_string) { if(!is_digit(c)) { throw cell_coordinates_exception(reference_string); } } if (column_string.length() == 0 || row_string.length() == 0) { throw cell_coordinates_exception(reference_string); } return { column_string, row_string.to() }; } cell_reference cell_reference::make_offset(int column_offset, int row_offset) const { //TODO: check for overflow/underflow return cell_reference(static_cast(static_cast(column_.index) + column_offset), static_cast(static_cast(row_) + row_offset)); } bool cell_reference::operator==(const cell_reference &comparand) const { return comparand.column_ == column_ && comparand.row_ == row_ && absolute_column_ == comparand.absolute_column_ && absolute_row_ == comparand.absolute_row_; } bool cell_reference::operator<(const cell_reference &other) { if (row_ != other.row_) { return row_ < other.row_; } return column_ < other.column_; } bool cell_reference::operator>(const cell_reference &other) { if (row_ != other.row_) { return row_ > other.row_; } return column_ > other.column_; } bool cell_reference::operator<=(const cell_reference &other) { if (row_ != other.row_) { return row_ < other.row_; } return column_ <= other.column_; } bool cell_reference::operator>=(const cell_reference &other) { if (row_ != other.row_) { return row_ > other.row_; } return column_ >= other.column_; } } // namespace xlnt