-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
locale aware double->string conversions #467
Changes from 7 commits
e8e29e9
1069c17
9136d21
63484f8
dfb8f15
d30e705
556d335
9d9d5de
504fed3
f1042c5
6c5a5a5
06801f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#ifndef XLNT_DETAIL_SERIALISATION_HELPERS_HPP | ||
#define XLNT_DETAIL_SERIALISATION_HELPERS_HPP | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was moved out of xlsx_consumer.cpp as a bit of cleanup from #421 |
||
|
||
#include <xlnt/cell/cell_type.hpp> | ||
#include <xlnt/cell/index_types.hpp> | ||
#include <string> | ||
|
||
namespace xlnt { | ||
namespace detail { | ||
|
||
/// parsing assumptions used by the following functions | ||
/// - on entry, the start element for the element has been consumed by parser->next | ||
/// - on exit, the closing element has been consumed by parser->next | ||
/// using these assumptions, the following functions DO NOT use parser->peek (SLOW!!!) | ||
/// probable further gains from not building an attribute map and using the attribute events instead as the impl just iterates the map | ||
|
||
/// 'r' == cell reference e.g. 'A1' | ||
/// https://docs.microsoft.com/en-us/openspecs/office_standards/ms-oe376/db11a912-b1cb-4dff-b46d-9bedfd10cef0 | ||
/// | ||
/// a lightweight version of xlnt::cell_reference with no extre functionality (absolute/relative, ...) | ||
/// many thousands are created during (de)serialisation, so even minor overhead is noticable | ||
struct Cell_Reference | ||
{ | ||
// the obvious ctor | ||
explicit Cell_Reference(xlnt::row_t row_arg, xlnt::column_t::index_t column_arg) noexcept | ||
: row(row_arg), column(column_arg) | ||
{ | ||
} | ||
|
||
// the common case. row # is already known during parsing (from parent <row> element) | ||
// just need to evaluate the column | ||
explicit Cell_Reference(xlnt::row_t row_arg, const std::string &reference) noexcept | ||
: row(row_arg) | ||
{ | ||
// only three characters allowed for the column | ||
// assumption: | ||
// - regex pattern match: [A-Z]{1,3}\d{1,7} | ||
const char *iter = reference.c_str(); | ||
int temp = *iter - 'A' + 1; // 'A' == 1 | ||
++iter; | ||
if (*iter >= 'A') // second char | ||
{ | ||
temp *= 26; // LHS values are more significant | ||
temp += *iter - 'A' + 1; // 'A' == 1 | ||
++iter; | ||
if (*iter >= 'A') // third char | ||
{ | ||
temp *= 26; // LHS values are more significant | ||
temp += *iter - 'A' + 1; // 'A' == 1 | ||
} | ||
} | ||
column = static_cast<xlnt::column_t::index_t>(temp); | ||
} | ||
|
||
// for sorting purposes | ||
bool operator<(const Cell_Reference &rhs) | ||
{ | ||
// row first, serialisation is done by row then column | ||
if (row < rhs.row) | ||
{ | ||
return true; | ||
} | ||
else if (rhs.row < row) | ||
{ | ||
return false; | ||
} | ||
// same row, column comparison | ||
return column < rhs.column; | ||
} | ||
|
||
xlnt::row_t row; // range:[1, 1048576] | ||
xlnt::column_t::index_t column; // range:["A", "ZZZ"] -> [1, 26^3] -> [1, 17576] | ||
}; | ||
|
||
// <c> inside <row> element | ||
// https://docs.microsoft.com/en-us/dotnet/api/documentformat.openxml.spreadsheet.cell?view=openxml-2.8.1 | ||
struct Cell | ||
{ | ||
// sort cells by location, row first | ||
bool operator<(const Cell &rhs) | ||
{ | ||
return ref < rhs.ref; | ||
} | ||
|
||
bool is_phonetic = false; // 'ph' | ||
xlnt::cell_type type = xlnt::cell_type::number; // 't' | ||
int cell_metatdata_idx = -1; // 'cm' | ||
int style_index = -1; // 's' | ||
Cell_Reference ref{0, 0}; // 'r' | ||
std::string value; // <v> OR <is> | ||
std::string formula_string; // <f> | ||
}; | ||
|
||
} // namespace detail | ||
} // namespace xlnt | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change here allows deserialise to be used anywhere std::strtod was used. Matching the char** param is however not possible due to the temporary buffer used when locale conversion is required. In the one case this was required for, the number of characters converted was what was being checked anyway.