mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
optimize hot code paths
This commit is contained in:
parent
bbdace8b44
commit
716a81a19f
|
@ -60,18 +60,14 @@ namespace {
|
||||||
|
|
||||||
xml::qname &qn(const std::string &namespace_, const std::string &name)
|
xml::qname &qn(const std::string &namespace_, const std::string &name)
|
||||||
{
|
{
|
||||||
static auto &memo = *new std::unordered_map<std::string, std::unordered_map<std::string, xml::qname>>();
|
using qname_map = std::unordered_map<std::string, xml::qname>;
|
||||||
|
static auto &memo = *new std::unordered_map<std::string, qname_map>();
|
||||||
if (!memo.count(namespace_))
|
|
||||||
{
|
|
||||||
memo[namespace_] = std::unordered_map<std::string, xml::qname>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &ns_memo = memo[namespace_];
|
auto &ns_memo = memo[namespace_];
|
||||||
|
|
||||||
if (!ns_memo.count(name))
|
if (ns_memo.find(name) == ns_memo.end())
|
||||||
{
|
{
|
||||||
ns_memo[name] = xml::qname(xlnt::constants::ns(namespace_), name);
|
return ns_memo.emplace(name, xml::qname(xlnt::constants::ns(namespace_), name)).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns_memo[name];
|
return ns_memo[name];
|
||||||
|
@ -248,13 +244,24 @@ cell xlsx_consumer::read_cell()
|
||||||
expect_end_element(current_element);
|
expect_end_element(current_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect_end_element(cell_el);
|
expect_end_element(qn("spreadsheetml", "c"));
|
||||||
|
|
||||||
if (has_formula && !has_shared_formula)
|
if (has_formula && !has_shared_formula)
|
||||||
{
|
{
|
||||||
cell.formula(formula_value_string);
|
cell.formula(formula_value_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::istringstream number_converter;
|
||||||
|
number_converter.imbue(std::locale("C"));
|
||||||
|
|
||||||
|
auto stold = [&number_converter](const std::string &s)
|
||||||
|
{
|
||||||
|
number_converter.str(s);
|
||||||
|
long double result;
|
||||||
|
number_converter >> result;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
if (has_value)
|
if (has_value)
|
||||||
{
|
{
|
||||||
if (type == "str")
|
if (type == "str")
|
||||||
|
@ -269,7 +276,7 @@ cell xlsx_consumer::read_cell()
|
||||||
}
|
}
|
||||||
else if (type == "s")
|
else if (type == "s")
|
||||||
{
|
{
|
||||||
cell.d_->value_numeric_ = std::stold(value_string);
|
cell.d_->value_numeric_ = stold(value_string);
|
||||||
cell.data_type(cell::type::shared_string);
|
cell.data_type(cell::type::shared_string);
|
||||||
}
|
}
|
||||||
else if (type == "b") // boolean
|
else if (type == "b") // boolean
|
||||||
|
@ -278,7 +285,7 @@ cell xlsx_consumer::read_cell()
|
||||||
}
|
}
|
||||||
else if (type == "n") // numeric
|
else if (type == "n") // numeric
|
||||||
{
|
{
|
||||||
cell.value(std::stold(value_string));
|
cell.value(stold(value_string));
|
||||||
}
|
}
|
||||||
else if (!value_string.empty() && value_string[0] == '#')
|
else if (!value_string.empty() && value_string[0] == '#')
|
||||||
{
|
{
|
||||||
|
@ -332,7 +339,6 @@ std::string xlsx_consumer::read_worksheet_begin(const std::string &rel_id)
|
||||||
|
|
||||||
expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet
|
expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet
|
||||||
skip_attributes({ qn("mc", "Ignorable") });
|
skip_attributes({ qn("mc", "Ignorable") });
|
||||||
read_namespaces();
|
|
||||||
|
|
||||||
while (in_element(qn("spreadsheetml", "worksheet")))
|
while (in_element(qn("spreadsheetml", "worksheet")))
|
||||||
{
|
{
|
||||||
|
@ -546,6 +552,17 @@ void xlsx_consumer::read_worksheet_sheetdata()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::istringstream number_converter;
|
||||||
|
number_converter.imbue(std::locale("C"));
|
||||||
|
|
||||||
|
auto stold = [&number_converter](const std::string &s)
|
||||||
|
{
|
||||||
|
number_converter.str(s);
|
||||||
|
long double result;
|
||||||
|
number_converter >> result;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
while (in_element(qn("spreadsheetml", "sheetData")))
|
while (in_element(qn("spreadsheetml", "sheetData")))
|
||||||
{
|
{
|
||||||
|
@ -648,7 +665,7 @@ void xlsx_consumer::read_worksheet_sheetdata()
|
||||||
}
|
}
|
||||||
else if (type == "s")
|
else if (type == "s")
|
||||||
{
|
{
|
||||||
cell.d_->value_numeric_ = std::stold(value_string);
|
cell.d_->value_numeric_ = stold(value_string);
|
||||||
cell.data_type(cell::type::shared_string);
|
cell.data_type(cell::type::shared_string);
|
||||||
}
|
}
|
||||||
else if (type == "b") // boolean
|
else if (type == "b") // boolean
|
||||||
|
@ -657,7 +674,7 @@ void xlsx_consumer::read_worksheet_sheetdata()
|
||||||
}
|
}
|
||||||
else if (type == "n") // numeric
|
else if (type == "n") // numeric
|
||||||
{
|
{
|
||||||
cell.value(std::stold(value_string));
|
cell.value(stold(value_string));
|
||||||
}
|
}
|
||||||
else if (!value_string.empty() && value_string[0] == '#')
|
else if (!value_string.empty() && value_string[0] == '#')
|
||||||
{
|
{
|
||||||
|
@ -1347,7 +1364,6 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
|
||||||
|
|
||||||
expect_start_element(qn("workbook", "workbook"), xml::content::complex);
|
expect_start_element(qn("workbook", "workbook"), xml::content::complex);
|
||||||
skip_attribute(qn("mc", "Ignorable"));
|
skip_attribute(qn("mc", "Ignorable"));
|
||||||
read_namespaces();
|
|
||||||
|
|
||||||
while (in_element(qn("workbook", "workbook")))
|
while (in_element(qn("workbook", "workbook")))
|
||||||
{
|
{
|
||||||
|
@ -1672,7 +1688,6 @@ void xlsx_consumer::read_stylesheet()
|
||||||
|
|
||||||
expect_start_element(qn("spreadsheetml", "styleSheet"), xml::content::complex);
|
expect_start_element(qn("spreadsheetml", "styleSheet"), xml::content::complex);
|
||||||
skip_attributes({qn("mc", "Ignorable")});
|
skip_attributes({qn("mc", "Ignorable")});
|
||||||
read_namespaces();
|
|
||||||
|
|
||||||
std::vector<std::pair<style_impl, std::size_t>> styles;
|
std::vector<std::pair<style_impl, std::size_t>> styles;
|
||||||
std::vector<std::pair<format_impl, std::size_t>> format_records;
|
std::vector<std::pair<format_impl, std::size_t>> format_records;
|
||||||
|
@ -2503,7 +2518,6 @@ void xlsx_consumer::skip_remaining_content(const xml::qname &name)
|
||||||
// start by assuming we've already parsed the opening tag
|
// start by assuming we've already parsed the opening tag
|
||||||
|
|
||||||
skip_attributes();
|
skip_attributes();
|
||||||
read_namespaces();
|
|
||||||
read_text();
|
read_text();
|
||||||
|
|
||||||
// continue until the closing tag is reached
|
// continue until the closing tag is reached
|
||||||
|
@ -2516,24 +2530,6 @@ void xlsx_consumer::skip_remaining_content(const xml::qname &name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> xlsx_consumer::read_namespaces()
|
|
||||||
{
|
|
||||||
std::vector<std::string> namespaces;
|
|
||||||
|
|
||||||
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
|
|
||||||
{
|
|
||||||
parser().next_expect(xml::parser::event_type::start_namespace_decl);
|
|
||||||
namespaces.push_back(parser().namespace_());
|
|
||||||
|
|
||||||
if (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
||||||
{
|
|
||||||
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return namespaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool xlsx_consumer::in_element(const xml::qname &name)
|
bool xlsx_consumer::in_element(const xml::qname &name)
|
||||||
{
|
{
|
||||||
return parser().peek() != xml::parser::event_type::end_element
|
return parser().peek() != xml::parser::event_type::end_element
|
||||||
|
@ -2565,12 +2561,6 @@ void xlsx_consumer::expect_start_element(const xml::qname &name, xml::content co
|
||||||
void xlsx_consumer::expect_end_element(const xml::qname &name)
|
void xlsx_consumer::expect_end_element(const xml::qname &name)
|
||||||
{
|
{
|
||||||
parser().next_expect(xml::parser::event_type::end_element, name);
|
parser().next_expect(xml::parser::event_type::end_element, name);
|
||||||
|
|
||||||
while (parser().peek() == xml::parser::event_type::end_namespace_decl)
|
|
||||||
{
|
|
||||||
parser().next_expect(xml::parser::event_type::end_namespace_decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
stack_.pop_back();
|
stack_.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,12 +357,6 @@ private:
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool in_element(const xml::qname &name);
|
bool in_element(const xml::qname &name);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles all start and end namespace events from the current parser
|
|
||||||
/// and returns a vector of strings containing the URL for each namespace.
|
|
||||||
/// </summary>
|
|
||||||
std::vector<std::string> read_namespaces();
|
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -352,22 +352,20 @@ void worksheet::unfreeze_panes()
|
||||||
|
|
||||||
cell worksheet::cell(const cell_reference &reference)
|
cell worksheet::cell(const cell_reference &reference)
|
||||||
{
|
{
|
||||||
if (d_->cell_map_.find(reference.row()) == d_->cell_map_.end())
|
|
||||||
{
|
|
||||||
d_->cell_map_[reference.row()] = std::unordered_map<column_t, detail::cell_impl>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &row = d_->cell_map_[reference.row()];
|
auto &row = d_->cell_map_[reference.row()];
|
||||||
|
auto match = row.find(reference.column_index());
|
||||||
|
|
||||||
if (row.find(reference.column_index()) == row.end())
|
if (match == row.end())
|
||||||
{
|
{
|
||||||
auto &impl = row[reference.column_index()] = detail::cell_impl();
|
match = row.emplace(reference.column_index(), detail::cell_impl()).first;
|
||||||
|
auto &impl = match->second;
|
||||||
|
|
||||||
impl.parent_ = d_;
|
impl.parent_ = d_;
|
||||||
impl.column_ = reference.column_index();
|
impl.column_ = reference.column_index();
|
||||||
impl.row_ = reference.row();
|
impl.row_ = reference.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
return xlnt::cell(&row[reference.column_index()]);
|
return xlnt::cell(&match->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cell worksheet::cell(const cell_reference &reference) const
|
const cell worksheet::cell(const cell_reference &reference) const
|
||||||
|
|
Loading…
Reference in New Issue
Block a user