summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2022-06-06 19:48:03 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2022-06-06 21:32:38 -0400
commit8ec42c299640fc7793f04f2e8b013233a32cbe03 (patch)
tree433d0c0a6427daae58e6dba9e3d77d22a9e5a365
parent2a6263ff4bcb195d7e9c398f5644511b43801730 (diff)
downloadorcus-8ec42c299640fc7793f04f2e8b013233a32cbe03.tar.gz
Add import_xf sub-interface and use it in xlsx
-rw-r--r--include/orcus/spreadsheet/factory.hpp25
-rw-r--r--include/orcus/spreadsheet/import_interface_styles.hpp37
-rw-r--r--src/liborcus/spreadsheet_interface.cpp2
-rw-r--r--src/liborcus/xlsx_context.cpp198
-rw-r--r--src/liborcus/xlsx_context.hpp2
-rw-r--r--src/spreadsheet/factory_styles.cpp112
6 files changed, 297 insertions, 79 deletions
diff --git a/include/orcus/spreadsheet/factory.hpp b/include/orcus/spreadsheet/factory.hpp
index 8078fa6b..9ec2f882 100644
--- a/include/orcus/spreadsheet/factory.hpp
+++ b/include/orcus/spreadsheet/factory.hpp
@@ -79,6 +79,7 @@ public:
virtual iface::import_border_style* get_border_style() override;
virtual iface::import_cell_protection* get_cell_protection() override;
virtual iface::import_number_format* get_number_format() override;
+ virtual iface::import_xf* get_xf(xf_category_t cat) override;
virtual void set_font_count(size_t n) override;
virtual void set_fill_count(size_t n) override;
@@ -210,6 +211,30 @@ public:
void reset();
};
+class ORCUS_SPM_DLLPUBLIC import_xf : public iface::import_xf
+{
+ struct impl;
+ std::unique_ptr<impl> mp_impl;
+
+public:
+ import_xf() = delete;
+ import_xf(styles& _styles_model, string_pool& sp);
+ virtual ~import_xf() override;
+
+ virtual void set_font(size_t index) override;
+ virtual void set_fill(size_t index) override;
+ virtual void set_border(size_t index) override;
+ virtual void set_protection(size_t index) override;
+ virtual void set_number_format(size_t index) override;
+ virtual void set_style_xf(size_t index) override;
+ virtual void set_apply_alignment(bool b) override;
+ virtual void set_horizontal_alignment(hor_alignment_t align) override;
+ virtual void set_vertical_alignment(ver_alignment_t align) override;
+ virtual size_t commit() override;
+
+ void reset(xf_category_t cat);
+};
+
class ORCUS_SPM_DLLPUBLIC export_factory : public iface::export_factory
{
struct impl;
diff --git a/include/orcus/spreadsheet/import_interface_styles.hpp b/include/orcus/spreadsheet/import_interface_styles.hpp
index 0ae60323..6509673a 100644
--- a/include/orcus/spreadsheet/import_interface_styles.hpp
+++ b/include/orcus/spreadsheet/import_interface_styles.hpp
@@ -24,6 +24,7 @@ class import_fill_style;
class import_border_style;
class import_cell_protection;
class import_number_format;
+class import_xf;
/**
* Interface for styles. Note that because the default style must have an
@@ -94,6 +95,17 @@ public:
virtual import_number_format* get_number_format() = 0;
/**
+ * Return a pointer to the interface instance for importing cell format
+ * (xf) indices that each references different format attributes in their
+ * respective pools. Note that the import_styles implementer <i>must</i>
+ * return a non-null pointer.
+ *
+ * @return pointer to the interface instance for importing cell format (xf)
+ * indices.
+ */
+ virtual import_xf* get_xf(xf_category_t cat) = 0;
+
+ /**
* Set the total number of font styles. This may be called before importing
* any of the font styles. This will give the implementer a chance to
* allocate storage. Note that it may not always be called.
@@ -294,6 +306,31 @@ public:
virtual size_t commit() = 0;
};
+class ORCUS_DLLPUBLIC import_xf
+{
+public:
+ virtual ~import_xf();
+
+ virtual void set_font(size_t index) = 0;
+ virtual void set_fill(size_t index) = 0;
+ virtual void set_border(size_t index) = 0;
+ virtual void set_protection(size_t index) = 0;
+ virtual void set_number_format(size_t index) = 0;
+
+ /**
+ * Set the index into the cell style record to specify a named cell style it
+ * uses as its basis.
+ *
+ * @param index index into the cell style record it uses as its basis.
+ */
+ virtual void set_style_xf(size_t index) = 0;
+ virtual void set_apply_alignment(bool b) = 0;
+ virtual void set_horizontal_alignment(hor_alignment_t align) = 0;
+ virtual void set_vertical_alignment(ver_alignment_t align) = 0;
+
+ virtual size_t commit() = 0;
+};
+
}}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_interface.cpp b/src/liborcus/spreadsheet_interface.cpp
index 2ffbb855..91775f04 100644
--- a/src/liborcus/spreadsheet_interface.cpp
+++ b/src/liborcus/spreadsheet_interface.cpp
@@ -35,6 +35,8 @@ import_cell_protection::~import_cell_protection() {}
import_number_format::~import_number_format() {}
+import_xf::~import_xf() {}
+
import_sheet_properties::~import_sheet_properties() {}
import_named_expression::~import_named_expression() {}
diff --git a/src/liborcus/xlsx_context.cpp b/src/liborcus/xlsx_context.cpp
index bfbdb696..9496a7f9 100644
--- a/src/liborcus/xlsx_context.cpp
+++ b/src/liborcus/xlsx_context.cpp
@@ -400,65 +400,6 @@ public:
}
};
-class xf_attr_parser
-{
- spreadsheet::iface::import_styles& m_styles;
-public:
- xf_attr_parser(spreadsheet::iface::import_styles& styles) :
- m_styles(styles) {}
-
- void operator() (const xml_token_attr_t& attr)
- {
- switch (attr.name)
- {
- case XML_borderId:
- {
- size_t n = to_long(attr.value);
- m_styles.set_xf_border(n);
- }
- break;
- case XML_fillId:
- {
- size_t n = to_long(attr.value);
- m_styles.set_xf_fill(n);
- }
- break;
- case XML_fontId:
- {
- size_t n = to_long(attr.value);
- m_styles.set_xf_font(n);
- }
- break;
- case XML_numFmtId:
- {
- size_t n = to_long(attr.value);
- m_styles.set_xf_number_format(n);
- }
- break;
- case XML_xfId:
- {
- size_t n = to_long(attr.value);
- m_styles.set_xf_style_xf(n);
- }
- break;
- case XML_applyBorder:
- break;
- case XML_applyFill:
- break;
- case XML_applyFont:
- break;
- case XML_applyNumberFormat:
- break;
- case XML_applyAlignment:
- {
- bool b = to_long(attr.value) != 0;
- m_styles.set_xf_apply_alignment(b);
- }
- break;
- }
- }
-};
-
class cell_alignment_attr_parser
{
spreadsheet::hor_alignment_t m_hor_align;
@@ -828,6 +769,7 @@ void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const x
mp_styles->set_xf_count(ss::xf_category_t::cell_style, n);
}
m_cell_style_xf = true;
+ mp_xf = mp_styles->get_xf(ss::xf_category_t::cell_style);
break;
}
case XML_cellXfs:
@@ -842,6 +784,7 @@ void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const x
mp_styles->set_xf_count(ss::xf_category_t::cell, n);
}
m_cell_style_xf = false;
+ mp_xf = mp_styles->get_xf(ss::xf_category_t::cell);
break;
}
case XML_dxfs:
@@ -855,6 +798,7 @@ void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const x
size_t n = strtoul(ps.data(), nullptr, 10);
mp_styles->set_xf_count(ss::xf_category_t::differential, n);
}
+ mp_xf = mp_styles->get_xf(ss::xf_category_t::differential);
break;
}
case XML_cellStyles:
@@ -878,17 +822,72 @@ void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const x
}
case XML_xf:
{
+ assert(mp_xf);
+
// Actual cell format attributes (for some reason) abbreviated to
// 'xf'. Used both by cells and cell styles.
- xml_elem_stack_t allowed;
- allowed.push_back(xml_elem_stack_t::value_type(NS_ooxml_xlsx, XML_cellXfs));
- allowed.push_back(xml_elem_stack_t::value_type(NS_ooxml_xlsx, XML_cellStyleXfs));
- xml_element_expected(parent, allowed);
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_cellXfs },
+ { NS_ooxml_xlsx, XML_cellStyleXfs },
+ };
+ xml_element_expected(parent, expected);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_borderId:
+ {
+ size_t n = to_long(attr.value);
+ mp_xf->set_border(n);
+ break;
+ }
+ case XML_fillId:
+ {
+ size_t n = to_long(attr.value);
+ mp_xf->set_fill(n);
+ break;
+ }
+ case XML_fontId:
+ {
+ size_t n = to_long(attr.value);
+ mp_xf->set_font(n);
+ break;
+ }
+ case XML_numFmtId:
+ {
+ size_t n = to_long(attr.value);
+ mp_xf->set_number_format(n);
+ break;
+ }
+ case XML_xfId:
+ {
+ size_t n = to_long(attr.value);
+ mp_xf->set_style_xf(n);
+ break;
+ }
+ case XML_applyBorder:
+ break;
+ case XML_applyFill:
+ break;
+ case XML_applyFont:
+ break;
+ case XML_applyNumberFormat:
+ break;
+ case XML_applyAlignment:
+ {
+ bool b = to_long(attr.value) != 0;
+ mp_xf->set_apply_alignment(b);
+ break;
+ }
+ }
+ }
- for_each(attrs.begin(), attrs.end(), xf_attr_parser(*mp_styles));
break;
}
case XML_dxf:
+ // TODO: Pick up dxf record. Technically dxf is a sub set of xf,
+ // but for now we use xf for dxf.
break;
case XML_protection:
{
@@ -925,14 +924,56 @@ void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const x
}
case XML_alignment:
{
- xml_elem_stack_t expected_elements;
- expected_elements.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_xf));
- expected_elements.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_dxf));
- xml_element_expected(parent, expected_elements);
- cell_alignment_attr_parser func;
- func = for_each(attrs.begin(), attrs.end(), func);
- mp_styles->set_xf_horizontal_alignment(func.get_hor_align());
- mp_styles->set_xf_vertical_alignment(func.get_ver_align());
+ assert(mp_xf);
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_xf },
+ { NS_ooxml_xlsx, XML_dxf },
+ };
+ xml_element_expected(parent, expected);
+
+ // NB: default vertical alignment is 'bottom'.
+ ss::hor_alignment_t hor_align = ss::hor_alignment_t::unknown;
+ ss::ver_alignment_t ver_align = ss::ver_alignment_t::bottom;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_horizontal:
+ {
+ if (attr.value == "center")
+ hor_align = ss::hor_alignment_t::center;
+ else if (attr.value == "right")
+ hor_align = ss::hor_alignment_t::right;
+ else if (attr.value == "left")
+ hor_align = ss::hor_alignment_t::left;
+ else if (attr.value == "justify")
+ hor_align = ss::hor_alignment_t::justified;
+ else if (attr.value == "distributed")
+ hor_align = ss::hor_alignment_t::distributed;
+ break;
+ }
+ case XML_vertical:
+ {
+ if (attr.value == "top")
+ ver_align = ss::ver_alignment_t::top;
+ else if (attr.value == "center")
+ ver_align = ss::ver_alignment_t::middle;
+ else if (attr.value == "bottom")
+ ver_align = ss::ver_alignment_t::bottom;
+ else if (attr.value == "justify")
+ ver_align = ss::ver_alignment_t::justified;
+ else if (attr.value == "distributed")
+ ver_align = ss::ver_alignment_t::distributed;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ mp_xf->set_horizontal_alignment(hor_align);
+ mp_xf->set_vertical_alignment(ver_align);
break;
}
case XML_numFmts:
@@ -986,14 +1027,15 @@ bool xlsx_styles_context::end_element(xmlns_id_t ns, xml_token_t name)
case XML_cellStyle:
mp_styles->commit_cell_style();
break;
- case XML_xf:
- if (m_cell_style_xf)
- mp_styles->commit_cell_style_xf();
- else
- mp_styles->commit_cell_xf();
+ case XML_cellStyleXfs:
+ case XML_cellXfs:
+ case XML_dxfs:
+ mp_xf = nullptr;
break;
+ case XML_xf:
case XML_dxf:
- mp_styles->commit_dxf();
+ assert(mp_xf);
+ mp_xf->commit();
break;
case XML_protection:
{
diff --git a/src/liborcus/xlsx_context.hpp b/src/liborcus/xlsx_context.hpp
index 30615d06..75c56a4b 100644
--- a/src/liborcus/xlsx_context.hpp
+++ b/src/liborcus/xlsx_context.hpp
@@ -26,6 +26,7 @@ namespace spreadsheet { namespace iface {
class import_border_style;
class import_cell_protection;
class import_number_format;
+ class import_xf;
}}
/**
@@ -86,6 +87,7 @@ private:
spreadsheet::iface::import_border_style* mp_border = nullptr;
spreadsheet::iface::import_cell_protection* mp_protection = nullptr;
spreadsheet::iface::import_number_format* mp_numfmt = nullptr;
+ spreadsheet::iface::import_xf* mp_xf = nullptr;
string_pool m_pool;
bool m_diagonal_up;
diff --git a/src/spreadsheet/factory_styles.cpp b/src/spreadsheet/factory_styles.cpp
index 773091e4..2249fb60 100644
--- a/src/spreadsheet/factory_styles.cpp
+++ b/src/spreadsheet/factory_styles.cpp
@@ -37,6 +37,7 @@ struct import_styles::impl
import_border_style border_style;
import_cell_protection cell_protection;
import_number_format number_format;
+ import_xf xf;
cell_format_t cur_cell_format;
cell_style_t cur_cell_style;
@@ -48,7 +49,8 @@ struct import_styles::impl
fill_style(_styles_model, sp),
border_style(_styles_model, sp),
cell_protection(_styles_model, sp),
- number_format(_styles_model, sp)
+ number_format(_styles_model, sp),
+ xf(_styles_model, sp)
{}
};
@@ -87,6 +89,12 @@ iface::import_number_format* import_styles::get_number_format()
return &mp_impl->number_format;
}
+iface::import_xf* import_styles::get_xf(xf_category_t cat)
+{
+ mp_impl->xf.reset(cat);
+ return &mp_impl->xf;
+}
+
void import_styles::set_font_count(size_t n)
{
mp_impl->styles_model.reserve_font_store(n);
@@ -625,6 +633,108 @@ void import_number_format::reset()
mp_impl->cur_numfmt_active.reset();
}
+struct import_xf::impl
+{
+ styles& styles_model;
+ string_pool& str_pool;
+
+ cell_format_t cur_cell_format;
+ xf_category_t xf_category = xf_category_t::unknown;
+
+ impl(styles& _styles_model, string_pool& sp) :
+ styles_model(_styles_model), str_pool(sp) {}
+};
+
+import_xf::import_xf(styles& _styles_model, string_pool& sp) :
+ mp_impl(std::make_unique<impl>(_styles_model, sp))
+{
+}
+
+import_xf::~import_xf()
+{
+}
+
+void import_xf::set_font(size_t index)
+{
+ mp_impl->cur_cell_format.font = index;
+}
+
+void import_xf::set_fill(size_t index)
+{
+ mp_impl->cur_cell_format.fill = index;
+}
+
+void import_xf::set_border(size_t index)
+{
+ mp_impl->cur_cell_format.border = index;
+
+ // TODO : we need to decide whether to have interface methods for these
+ // apply_foo attributes. For now there is only one, for alignment.
+ mp_impl->cur_cell_format.apply_border = index > 0;
+}
+
+void import_xf::set_protection(size_t index)
+{
+ mp_impl->cur_cell_format.protection = index;
+}
+
+void import_xf::set_number_format(size_t index)
+{
+ mp_impl->cur_cell_format.number_format = index;
+}
+
+void import_xf::set_style_xf(size_t index)
+{
+ mp_impl->cur_cell_format.style_xf = index;
+}
+
+void import_xf::set_apply_alignment(bool b)
+{
+ mp_impl->cur_cell_format.apply_alignment = b;
+}
+
+void import_xf::set_horizontal_alignment(hor_alignment_t align)
+{
+ mp_impl->cur_cell_format.hor_align = align;
+}
+
+void import_xf::set_vertical_alignment(ver_alignment_t align)
+{
+ mp_impl->cur_cell_format.ver_align = align;
+}
+
+size_t import_xf::commit()
+{
+ size_t xf_id = 0;
+
+ switch (mp_impl->xf_category)
+ {
+ case xf_category_t::cell:
+ xf_id = mp_impl->styles_model.append_cell_format(mp_impl->cur_cell_format);
+ break;
+ case xf_category_t::cell_style:
+ xf_id = mp_impl->styles_model.append_cell_style_format(mp_impl->cur_cell_format);
+ break;
+ case xf_category_t::differential:
+ xf_id = mp_impl->styles_model.append_diff_cell_format(mp_impl->cur_cell_format);
+ break;
+ case xf_category_t::unknown:
+ throw std::logic_error("unknown cell format category");
+ }
+
+ mp_impl->cur_cell_format.reset();
+ return xf_id;
+}
+
+void import_xf::reset(xf_category_t cat)
+{
+ if (cat == xf_category_t::unknown)
+ throw std::invalid_argument("The specified category is 'unknown'.");
+
+ mp_impl->cur_cell_format.reset();
+ mp_impl->xf_category = cat;
+}
+
}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */