serialisation_helpers.hpp 3.2 KB

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