1 #ifndef XLNT_DETAIL_SERIALISATION_HELPERS_HPP 2 #define XLNT_DETAIL_SERIALISATION_HELPERS_HPP 3 4 #include <xlnt/cell/cell_type.hpp> 5 #include <xlnt/cell/index_types.hpp> 6 #include <string> 7 8 namespace xlnt { 9 namespace detail { 10 11 /// parsing assumptions used by the following functions 12 /// - on entry, the start element for the element has been consumed by parser->next 13 /// - on exit, the closing element has been consumed by parser->next 14 /// using these assumptions, the following functions DO NOT use parser->peek (SLOW!!!) 15 /// probable further gains from not building an attribute map and using the attribute events instead as the impl just iterates the map 16 17 /// 'r' == cell reference e.g. 'A1' 18 /// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-oe376/db11a912-b1cb-4dff-b46d-9bedfd10cef0 19 /// 20 /// a lightweight version of xlnt::cell_reference with no extre functionality (absolute/relative, ...) 21 /// many thousands are created during (de)serialisation, so even minor overhead is noticable 22 struct Cell_Reference 23 { 24 // the obvious ctor Cell_Referencexlnt::detail::Cell_Reference25 explicit Cell_Reference(xlnt::row_t row_arg, xlnt::column_t::index_t column_arg) noexcept 26 : row(row_arg), column(column_arg) 27 { 28 } 29 30 // the common case. row # is already known during parsing (from parent <row> element) 31 // just need to evaluate the column Cell_Referencexlnt::detail::Cell_Reference32 explicit Cell_Reference(xlnt::row_t row_arg, const std::string &reference) noexcept 33 : row(row_arg) 34 { 35 // only three characters allowed for the column 36 // assumption: 37 // - regex pattern match: [A-Z]{1,3}\d{1,7} 38 const char *iter = reference.c_str(); 39 int temp = *iter - 'A' + 1; // 'A' == 1 40 ++iter; 41 if (*iter >= 'A') // second char 42 { 43 temp *= 26; // LHS values are more significant 44 temp += *iter - 'A' + 1; // 'A' == 1 45 ++iter; 46 if (*iter >= 'A') // third char 47 { 48 temp *= 26; // LHS values are more significant 49 temp += *iter - 'A' + 1; // 'A' == 1 50 } 51 } 52 column = static_cast<xlnt::column_t::index_t>(temp); 53 } 54 55 // for sorting purposes operator <xlnt::detail::Cell_Reference56 bool operator<(const Cell_Reference &rhs) 57 { 58 // row first, serialisation is done by row then column 59 if (row < rhs.row) 60 { 61 return true; 62 } 63 else if (rhs.row < row) 64 { 65 return false; 66 } 67 // same row, column comparison 68 return column < rhs.column; 69 } 70 71 xlnt::row_t row; // range:[1, 1048576] 72 xlnt::column_t::index_t column; // range:["A", "ZZZ"] -> [1, 26^3] -> [1, 17576] 73 }; 74 75 // <c> inside <row> element 76 // https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cell?view=openxml-2.8.1 77 struct Cell 78 { 79 // sort cells by location, row first operator <xlnt::detail::Cell80 bool operator<(const Cell &rhs) 81 { 82 return ref < rhs.ref; 83 } 84 85 bool is_phonetic = false; // 'ph' 86 xlnt::cell_type type = xlnt::cell_type::number; // 't' 87 int cell_metatdata_idx = -1; // 'cm' 88 int style_index = -1; // 's' 89 Cell_Reference ref{0, 0}; // 'r' 90 std::string value; // <v> OR <is> 91 std::string formula_string; // <f> 92 }; 93 94 } // namespace detail 95 } // namespace xlnt 96 #endif