Branch data TLA Line data Source code
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 <detail/xlnt_config_impl.hpp>
7 : :
8 : : #include <string>
9 : :
10 : : namespace xlnt {
11 : : namespace detail {
12 : :
13 : : /// parsing assumptions used by the following functions
14 : : /// - on entry, the start element for the element has been consumed by parser->next
15 : : /// - on exit, the closing element has been consumed by parser->next
16 : : /// using these assumptions, the following functions DO NOT use parser->peek (SLOW!!!)
17 : : /// probable further gains from not building an attribute map and using the attribute events instead as the impl just iterates the map
18 : :
19 : : /// 'r' == cell reference e.g. 'A1'
20 : : /// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-oe376/db11a912-b1cb-4dff-b46d-9bedfd10cef0
21 : : ///
22 : : /// a lightweight version of xlnt::cell_reference with no extre functionality (absolute/relative, ...)
23 : : /// many thousands are created during (de)serialisation, so even minor overhead is noticable
24 : : struct Cell_Reference
25 : : {
26 : : // the obvious ctor
27 :CBC 2035 : explicit Cell_Reference(xlnt::row_t row_arg, xlnt::column_t::index_t column_arg) noexcept
28 : 2035 : : row(row_arg), column(column_arg)
29 : : {
30 : 2035 : }
31 : :
32 : : // the common case. row # is already known during parsing (from parent <row> element)
33 : : // just need to evaluate the column
34 : 2035 : explicit Cell_Reference(xlnt::row_t row_arg, const std::string &reference) noexcept
35 : 2035 : : row(row_arg)
36 : : {
37 : : // only three characters allowed for the column
38 : : // assumption:
39 : : // - regex pattern match: [A-Z]{1,3}\d{1,7}
40 : 2035 : const char *iter = reference.c_str();
41 : 2035 : int temp = *iter - 'A' + 1; // 'A' == 1
42 : 2035 : ++iter;
43 [ - + ]: 2035 : if (*iter >= 'A') // second char
44 : : {
45 :UBC 0 : temp *= 26; // LHS values are more significant
46 : 0 : temp += *iter - 'A' + 1; // 'A' == 1
47 : 0 : ++iter;
48 [ # # ]: 0 : if (*iter >= 'A') // third char
49 : : {
50 : 0 : temp *= 26; // LHS values are more significant
51 : 0 : temp += *iter - 'A' + 1; // 'A' == 1
52 : : }
53 : : }
54 :CBC 2035 : column = static_cast<xlnt::column_t::index_t>(temp);
55 : 2035 : }
56 : :
57 : : // for sorting purposes
58 : : bool operator<(const Cell_Reference &rhs)
59 : : {
60 : : // row first, serialisation is done by row then column
61 : : if (row < rhs.row)
62 : : {
63 : : return true;
64 : : }
65 : : else if (rhs.row < row)
66 : : {
67 : : return false;
68 : : }
69 : : // same row, column comparison
70 : : return column < rhs.column;
71 : : }
72 : :
73 : : xlnt::row_t row; // range:[1, 1048576]
74 : : xlnt::column_t::index_t column; // range:["A", "ZZZ"] -> [1, 26^3] -> [1, 17576]
75 : : };
76 : :
77 : : // <c> inside <row> element
78 : : // https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cell?view=openxml-2.8.1
79 : : struct Cell
80 : : {
81 : : // sort cells by location, row first
82 : : bool operator<(const Cell &rhs)
83 : : {
84 : : return ref < rhs.ref;
85 : : }
86 : :
87 : : bool is_phonetic = false; // 'ph'
88 : : xlnt::cell_type type = xlnt::cell_type::number; // 't'
89 : : int cell_metadata_idx = -1; // 'cm'
90 : : int style_index = -1; // 's'
91 : : Cell_Reference ref{0, 0}; // 'r'
92 : : std::string value; // <v> OR <is>
93 : : std::string formula_string; // <f>
94 : : };
95 : :
96 : : // for printing to file.
97 : : // This matches the output format of excel irrespective of current locale
98 : : XLNT_API_INTERNAL std::string serialise(double d);
99 : :
100 : : // Parses a string to a double-precision floating-point number. Optionally, num_characters_parsed can point
101 : : // to a variable where the number of parsed characters will be stored.
102 : : XLNT_API_INTERNAL double deserialise(const std::string &s, size_t *num_characters_parsed = nullptr);
103 : :
104 : : // Parses a string to a double-precision floating-point number. Optionally, end can point
105 : : // to a pointer where the character after the last successfully parsed character will be stored.
106 : : XLNT_API_INTERNAL double deserialise(const char *s, const char **end = nullptr);
107 : :
108 : : } // namespace detail
109 : : } // namespace xlnt
110 : : #endif
|