1 // Copyright (c) 2014-2020 Thomas Fussell 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE 20 // 21 // @license: http://www.opensource.org/licenses/mit-license.php 22 // @author: see AUTHORS file 23 24 #pragma once 25 26 #include <algorithm> 27 #include <cstdint> 28 #include <string> 29 30 #include <xlnt/xlnt_config.hpp> 31 32 // We might want to change these types for various optimizations in the future 33 // so use typedefs. 34 35 namespace xlnt { 36 37 /// <summary> 38 /// All rows should be referred to by an instance of this type. 39 /// </summary> 40 using row_t = std::uint32_t; 41 42 /// <summary> 43 /// Columns can be referred to as a string A,B,...Z,AA,AB,..,ZZ,AAA,...,ZZZ 44 /// or as a 1-indexed index. This class encapsulates both of these forms of 45 /// column referencing and allows for conversions between them. 46 /// </summary> 47 class XLNT_API column_t 48 { 49 public: 50 /// <summary> 51 /// Alias declaration for the internal numeric type of this column. 52 /// </summary> 53 using index_t = std::uint32_t; 54 55 /// <summary> 56 /// Convert a column letter into a column number (e.g. B -> 2) 57 /// </summary> 58 /// <remarks> 59 /// Excel only supports 1 - 3 letter column names from A->ZZZ, so we 60 /// restrict our column names to 1 - 3 characters, each in the range A - Z. 61 /// Strings outside this range and malformed strings will throw column_string_index_exception. 62 /// </remarks> 63 static index_t column_index_from_string(const std::string &column_string); 64 65 /// <summary> 66 /// Convert a column number into a column letter (3 -> 'C') 67 /// </summary> 68 /// <remarks> 69 /// Right shift the column, column_index, by 26 to find column letters in reverse 70 /// order. These indices are 1-based, and can be converted to ASCII 71 /// ordinals by adding 64. 72 /// </remarks> 73 static std::string column_string_from_index(index_t column_index); 74 75 /// <summary> 76 /// Default constructor. The column points to the "A" column. 77 /// </summary> 78 column_t(); 79 80 /// <summary> 81 /// Constructs a column from a number. 82 /// </summary> 83 column_t(index_t column_index); 84 85 /// <summary> 86 /// Constructs a column from a string. 87 /// </summary> 88 column_t(const std::string &column_string); 89 90 /// <summary> 91 /// Constructs a column from a string. 92 /// </summary> 93 column_t(const char *column_string); 94 95 /// <summary> 96 /// Returns a string representation of this column index. 97 /// </summary> 98 std::string column_string() const; 99 100 /// <summary> 101 /// Sets this column to be equal to rhs and return reference to self. 102 /// </summary> 103 column_t &operator=(const std::string &rhs); 104 105 /// <summary> 106 /// Sets this column to be equal to rhs and return reference to self. 107 /// </summary> 108 column_t &operator=(const char *rhs); 109 110 /// <summary> 111 /// Returns true if this column refers to the same column as other. 112 /// </summary> 113 bool operator==(const column_t &other) const; 114 115 /// <summary> 116 /// Returns true if this column doesn't refer to the same column as other. 117 /// </summary> 118 bool operator!=(const column_t &other) const; 119 120 /// <summary> 121 /// Returns true if this column refers to the same column as other. 122 /// </summary> 123 bool operator==(int other) const; 124 125 /// <summary> 126 /// Returns true if this column refers to the same column as other. 127 /// </summary> 128 bool operator==(index_t other) const; 129 130 /// <summary> 131 /// Returns true if this column refers to the same column as other. 132 /// </summary> 133 bool operator==(const std::string &other) const; 134 135 /// <summary> 136 /// Returns true if this column refers to the same column as other. 137 /// </summary> 138 bool operator==(const char *other) const; 139 140 /// <summary> 141 /// Returns true if this column doesn't refer to the same column as other. 142 /// </summary> 143 bool operator!=(int other) const; 144 145 /// <summary> 146 /// Returns true if this column doesn't refer to the same column as other. 147 /// </summary> 148 bool operator!=(index_t other) const; 149 150 /// <summary> 151 /// Returns true if this column doesn't refer to the same column as other. 152 /// </summary> 153 bool operator!=(const std::string &other) const; 154 155 /// <summary> 156 /// Returns true if this column doesn't refer to the same column as other. 157 /// </summary> 158 bool operator!=(const char *other) const; 159 160 /// <summary> 161 /// Returns true if other is to the right of this column. 162 /// </summary> 163 bool operator>(const column_t &other) const; 164 165 /// <summary> 166 /// Returns true if other is to the right of or equal to this column. 167 /// </summary> 168 bool operator>=(const column_t &other) const; 169 170 /// <summary> 171 /// Returns true if other is to the left of this column. 172 /// </summary> 173 bool operator<(const column_t &other) const; 174 175 /// <summary> 176 /// Returns true if other is to the left of or equal to this column. 177 /// </summary> 178 bool operator<=(const column_t &other) const; 179 180 /// <summary> 181 /// Returns true if other is to the right of this column. 182 /// </summary> 183 bool operator>(const column_t::index_t &other) const; 184 185 /// <summary> 186 /// Returns true if other is to the right of or equal to this column. 187 /// </summary> 188 bool operator>=(const column_t::index_t &other) const; 189 190 /// <summary> 191 /// Returns true if other is to the left of this column. 192 /// </summary> 193 bool operator<(const column_t::index_t &other) const; 194 195 /// <summary> 196 /// Returns true if other is to the left of or equal to this column. 197 /// </summary> 198 bool operator<=(const column_t::index_t &other) const; 199 200 /// <summary> 201 /// Pre-increments this column, making it point to the column one to the right and returning a reference to it. 202 /// </summary> 203 column_t &operator++(); 204 205 /// <summary> 206 /// Pre-deccrements this column, making it point to the column one to the left and returning a reference to it. 207 /// </summary> 208 column_t &operator--(); 209 210 /// <summary> 211 /// Post-increments this column, making it point to the column one to the right and returning the old column. 212 /// </summary> 213 column_t operator++(int); 214 215 /// <summary> 216 /// Post-decrements this column, making it point to the column one to the left and returning the old column. 217 /// </summary> 218 column_t operator--(int); 219 220 /// <summary> 221 /// Returns the result of adding rhs to this column. 222 /// </summary> 223 friend XLNT_API column_t operator+(column_t lhs, const column_t &rhs); 224 225 /// <summary> 226 /// Returns the result of subtracing lhs by rhs column. 227 /// </summary> 228 friend XLNT_API column_t operator-(column_t lhs, const column_t &rhs); 229 230 /// <summary> 231 /// Adds rhs to this column and returns a reference to this column. 232 /// </summary> 233 column_t &operator+=(const column_t &rhs); 234 235 /// <summary> 236 /// Subtracts rhs from this column and returns a reference to this column. 237 /// </summary> 238 column_t &operator-=(const column_t &rhs); 239 240 /// <summary> 241 /// Returns true if other is to the right of this column. 242 /// </summary> 243 friend XLNT_API bool operator>(const column_t::index_t &left, const column_t &right); 244 245 /// <summary> 246 /// Returns true if other is to the right of or equal to this column. 247 /// </summary> 248 friend XLNT_API bool operator>=(const column_t::index_t &left, const column_t &right); 249 250 /// <summary> 251 /// Returns true if other is to the left of this column. 252 /// </summary> 253 friend XLNT_API bool operator<(const column_t::index_t &left, const column_t &right); 254 255 /// <summary> 256 /// Returns true if other is to the left of or equal to this column. 257 /// </summary> 258 friend XLNT_API bool operator<=(const column_t::index_t &left, const column_t &right); 259 260 /// <summary> 261 /// Swaps the columns that left and right refer to. 262 /// </summary> 263 friend XLNT_API void swap(column_t &left, column_t &right); 264 265 /// <summary> 266 /// Internal numeric value of this column index. 267 /// </summary> 268 index_t index; 269 }; 270 271 enum class row_or_col_t : int 272 { 273 row, 274 column 275 }; 276 277 /// <summary> 278 /// Functor for hashing a column. 279 /// Allows for use of std::unordered_set<column_t, column_hash> and similar. 280 /// </summary> 281 struct XLNT_API column_hash 282 { 283 /// <summary> 284 /// Returns the result of hashing column k. 285 /// </summary> 286 std::size_t operator()(const column_t &k) const; 287 }; 288 289 } // namespace xlnt 290 291 namespace std { 292 293 /// <summary> 294 /// Template specialization to allow xlnt::column_t to be used as a key in a std container. 295 /// </summary> 296 template <> 297 struct hash<xlnt::column_t> 298 { 299 /// <summary> 300 /// Returns the result of hashing column k. 301 /// </summary> operator ()std::hash302 size_t operator()(const xlnt::column_t &k) const 303 { 304 static xlnt::column_hash hasher; 305 return hasher(k); 306 } 307 }; 308 309 } // namespace std 310