summaryrefslogtreecommitdiffstats
path: root/src/liborcus
diff options
context:
space:
mode:
Diffstat (limited to 'src/liborcus')
-rw-r--r--src/liborcus/Makefile.am590
-rw-r--r--src/liborcus/Makefile.in4283
-rw-r--r--src/liborcus/common_test.cpp245
-rw-r--r--src/liborcus/config.cpp54
-rw-r--r--src/liborcus/constants.inl.in4
-rw-r--r--src/liborcus/css_document_tree.cpp647
-rw-r--r--src/liborcus/css_document_tree_test.cpp690
-rw-r--r--src/liborcus/css_selector.cpp214
-rw-r--r--src/liborcus/detection_result.cpp20
-rw-r--r--src/liborcus/detection_result.hpp26
-rw-r--r--src/liborcus/dom_tree.cpp741
-rw-r--r--src/liborcus/dom_tree_test.cpp123
-rw-r--r--src/liborcus/format_detection.cpp135
-rw-r--r--src/liborcus/formula_result.cpp120
-rw-r--r--src/liborcus/formula_result.hpp72
-rw-r--r--src/liborcus/gnumeric_cell_context.cpp377
-rw-r--r--src/liborcus/gnumeric_cell_context.hpp85
-rw-r--r--src/liborcus/gnumeric_cell_context_test.cpp386
-rw-r--r--src/liborcus/gnumeric_context.cpp453
-rw-r--r--src/liborcus/gnumeric_context.hpp67
-rw-r--r--src/liborcus/gnumeric_detection_handler.cpp83
-rw-r--r--src/liborcus/gnumeric_detection_handler.hpp31
-rw-r--r--src/liborcus/gnumeric_filter_context.cpp256
-rw-r--r--src/liborcus/gnumeric_filter_context.hpp54
-rw-r--r--src/liborcus/gnumeric_handler.cpp32
-rw-r--r--src/liborcus/gnumeric_handler.hpp36
-rw-r--r--src/liborcus/gnumeric_names_context.cpp110
-rw-r--r--src/liborcus/gnumeric_names_context.hpp49
-rw-r--r--src/liborcus/gnumeric_namespace_types.cpp38
-rw-r--r--src/liborcus/gnumeric_namespace_types.hpp26
-rw-r--r--src/liborcus/gnumeric_sheet_context.cpp819
-rw-r--r--src/liborcus/gnumeric_sheet_context.hpp112
-rw-r--r--src/liborcus/gnumeric_sheet_context_test.cpp119
-rw-r--r--src/liborcus/gnumeric_styles_context.cpp342
-rw-r--r--src/liborcus/gnumeric_styles_context.hpp59
-rw-r--r--src/liborcus/gnumeric_token_constants.hpp21
-rw-r--r--src/liborcus/gnumeric_token_constants.inl258
-rw-r--r--src/liborcus/gnumeric_tokens.cpp20
-rw-r--r--src/liborcus/gnumeric_tokens.hpp23
-rw-r--r--src/liborcus/gnumeric_tokens.inl263
-rw-r--r--src/liborcus/gnumeric_types.cpp174
-rw-r--r--src/liborcus/gnumeric_types.hpp149
-rw-r--r--src/liborcus/gnumeric_value_format_parser.cpp131
-rw-r--r--src/liborcus/gnumeric_value_format_parser.hpp46
-rw-r--r--src/liborcus/impl_utils.hpp18
-rw-r--r--src/liborcus/info.cpp31
-rw-r--r--src/liborcus/interface.cpp37
-rw-r--r--src/liborcus/json_document_tree.cpp1777
-rw-r--r--src/liborcus/json_document_tree_test.cpp862
-rw-r--r--src/liborcus/json_map_tree.cpp786
-rw-r--r--src/liborcus/json_map_tree.hpp197
-rw-r--r--src/liborcus/json_map_tree_test.cpp130
-rw-r--r--src/liborcus/json_structure_mapper.cpp77
-rw-r--r--src/liborcus/json_structure_mapper.hpp37
-rw-r--r--src/liborcus/json_structure_tree.cpp720
-rw-r--r--src/liborcus/json_structure_tree_test.cpp201
-rw-r--r--src/liborcus/json_util.cpp27
-rw-r--r--src/liborcus/json_util.hpp21
-rw-r--r--src/liborcus/measurement.cpp214
-rw-r--r--src/liborcus/number_utils.cpp74
-rw-r--r--src/liborcus/number_utils.hpp22
-rw-r--r--src/liborcus/odf_document_styles_context.cpp73
-rw-r--r--src/liborcus/odf_document_styles_context.hpp50
-rw-r--r--src/liborcus/odf_helper.cpp260
-rw-r--r--src/liborcus/odf_helper.hpp55
-rw-r--r--src/liborcus/odf_helper_test.cpp51
-rw-r--r--src/liborcus/odf_namespace_types.cpp12
-rw-r--r--src/liborcus/odf_namespace_types.hpp16
-rw-r--r--src/liborcus/odf_namespace_types_cpp.inl63
-rw-r--r--src/liborcus/odf_namespace_types_hpp.inl31
-rw-r--r--src/liborcus/odf_number_format_context.cpp1126
-rw-r--r--src/liborcus/odf_number_format_context.hpp180
-rw-r--r--src/liborcus/odf_para_context.cpp165
-rw-r--r--src/liborcus/odf_para_context.hpp62
-rw-r--r--src/liborcus/odf_style_context.cpp774
-rw-r--r--src/liborcus/odf_style_context.hpp51
-rw-r--r--src/liborcus/odf_styles.cpp110
-rw-r--r--src/liborcus/odf_styles.hpp127
-rw-r--r--src/liborcus/odf_styles_context.cpp403
-rw-r--r--src/liborcus/odf_styles_context.hpp70
-rw-r--r--src/liborcus/odf_token_constants.hpp21
-rw-r--r--src/liborcus/odf_token_constants.inl2280
-rw-r--r--src/liborcus/odf_tokens.cpp23
-rw-r--r--src/liborcus/odf_tokens.hpp23
-rw-r--r--src/liborcus/odf_tokens.inl2285
-rw-r--r--src/liborcus/ods_content_xml_context.cpp900
-rw-r--r--src/liborcus/ods_content_xml_context.hpp138
-rw-r--r--src/liborcus/ods_dde_links_context.cpp49
-rw-r--r--src/liborcus/ods_dde_links_context.hpp42
-rw-r--r--src/liborcus/ods_session_data.cpp42
-rw-r--r--src/liborcus/ods_session_data.hpp82
-rw-r--r--src/liborcus/ooxml_content_types.cpp74
-rw-r--r--src/liborcus/ooxml_content_types.hpp49
-rw-r--r--src/liborcus/ooxml_global.cpp97
-rw-r--r--src/liborcus/ooxml_global.hpp48
-rw-r--r--src/liborcus/ooxml_namespace_types.cpp52
-rw-r--r--src/liborcus/ooxml_namespace_types.hpp44
-rw-r--r--src/liborcus/ooxml_schemas.cpp70
-rw-r--r--src/liborcus/ooxml_schemas.hpp47
-rw-r--r--src/liborcus/ooxml_token_constants.hpp21
-rw-r--r--src/liborcus/ooxml_token_constants.inl3519
-rw-r--r--src/liborcus/ooxml_tokens.cpp29
-rw-r--r--src/liborcus/ooxml_tokens.hpp21
-rw-r--r--src/liborcus/ooxml_tokens.inl3524
-rw-r--r--src/liborcus/ooxml_types.cpp27
-rw-r--r--src/liborcus/ooxml_types.hpp73
-rw-r--r--src/liborcus/opc_context.cpp310
-rw-r--r--src/liborcus/opc_context.hpp90
-rw-r--r--src/liborcus/opc_reader.cpp306
-rw-r--r--src/liborcus/opc_reader.hpp127
-rw-r--r--src/liborcus/opc_token_constants.hpp20
-rw-r--r--src/liborcus/opc_token_constants.inl31
-rw-r--r--src/liborcus/opc_tokens.inl36
-rw-r--r--src/liborcus/orcus_csv.cpp196
-rw-r--r--src/liborcus/orcus_gnumeric.cpp163
-rw-r--r--src/liborcus/orcus_import_ods.cpp51
-rw-r--r--src/liborcus/orcus_import_xlsx.cpp51
-rw-r--r--src/liborcus/orcus_json.cpp513
-rw-r--r--src/liborcus/orcus_ods.cpp230
-rw-r--r--src/liborcus/orcus_parquet.cpp547
-rw-r--r--src/liborcus/orcus_xls_xml.cpp134
-rw-r--r--src/liborcus/orcus_xlsx.cpp824
-rw-r--r--src/liborcus/orcus_xml.cpp702
-rw-r--r--src/liborcus/orcus_xml_impl.cpp22
-rw-r--r--src/liborcus/orcus_xml_impl.hpp51
-rw-r--r--src/liborcus/orcus_xml_map_def.cpp299
-rw-r--r--src/liborcus/session_context.cpp30
-rw-r--r--src/liborcus/session_context.hpp58
-rw-r--r--src/liborcus/spreadsheet_iface_util.cpp53
-rw-r--r--src/liborcus/spreadsheet_iface_util.hpp36
-rw-r--r--src/liborcus/spreadsheet_impl_types.cpp50
-rw-r--r--src/liborcus/spreadsheet_impl_types.hpp39
-rw-r--r--src/liborcus/spreadsheet_interface.cpp159
-rw-r--r--src/liborcus/spreadsheet_types.cpp763
-rw-r--r--src/liborcus/string_helper.cpp40
-rw-r--r--src/liborcus/string_helper.hpp21
-rw-r--r--src/liborcus/xls_xml_context.cpp2396
-rw-r--r--src/liborcus/xls_xml_context.hpp334
-rw-r--r--src/liborcus/xls_xml_detection_handler.cpp113
-rw-r--r--src/liborcus/xls_xml_detection_handler.hpp31
-rw-r--r--src/liborcus/xls_xml_handler.cpp22
-rw-r--r--src/liborcus/xls_xml_handler.hpp35
-rw-r--r--src/liborcus/xls_xml_namespace_types.cpp32
-rw-r--r--src/liborcus/xls_xml_namespace_types.hpp28
-rw-r--r--src/liborcus/xls_xml_token_constants.hpp20
-rw-r--r--src/liborcus/xls_xml_token_constants.inl992
-rw-r--r--src/liborcus/xls_xml_tokens.cpp21
-rw-r--r--src/liborcus/xls_xml_tokens.hpp20
-rw-r--r--src/liborcus/xls_xml_tokens.inl997
-rw-r--r--src/liborcus/xlsx_autofilter_context.cpp140
-rw-r--r--src/liborcus/xlsx_autofilter_context.hpp64
-rw-r--r--src/liborcus/xlsx_conditional_format_context.cpp878
-rw-r--r--src/liborcus/xlsx_conditional_format_context.hpp68
-rw-r--r--src/liborcus/xlsx_drawing_context.cpp173
-rw-r--r--src/liborcus/xlsx_drawing_context.hpp48
-rw-r--r--src/liborcus/xlsx_handler.cpp76
-rw-r--r--src/liborcus/xlsx_handler.hpp91
-rw-r--r--src/liborcus/xlsx_helper.cpp33
-rw-r--r--src/liborcus/xlsx_helper.hpp18
-rw-r--r--src/liborcus/xlsx_pivot_context.cpp1734
-rw-r--r--src/liborcus/xlsx_pivot_context.hpp118
-rw-r--r--src/liborcus/xlsx_revision_context.cpp578
-rw-r--r--src/liborcus/xlsx_revision_context.hpp53
-rw-r--r--src/liborcus/xlsx_session_data.cpp47
-rw-r--r--src/liborcus/xlsx_session_data.hpp92
-rw-r--r--src/liborcus/xlsx_shared_strings_context.cpp253
-rw-r--r--src/liborcus/xlsx_shared_strings_context.hpp48
-rw-r--r--src/liborcus/xlsx_sheet_context.cpp943
-rw-r--r--src/liborcus/xlsx_sheet_context.hpp141
-rw-r--r--src/liborcus/xlsx_sheet_context_test.cpp281
-rw-r--r--src/liborcus/xlsx_styles_context.cpp1055
-rw-r--r--src/liborcus/xlsx_styles_context.hpp86
-rw-r--r--src/liborcus/xlsx_table_context.cpp319
-rw-r--r--src/liborcus/xlsx_table_context.hpp52
-rw-r--r--src/liborcus/xlsx_types.cpp116
-rw-r--r--src/liborcus/xlsx_types.hpp93
-rw-r--r--src/liborcus/xlsx_workbook_context.cpp253
-rw-r--r--src/liborcus/xlsx_workbook_context.hpp65
-rw-r--r--src/liborcus/xml_context_base.cpp348
-rw-r--r--src/liborcus/xml_context_base.hpp192
-rw-r--r--src/liborcus/xml_context_global.cpp106
-rw-r--r--src/liborcus/xml_context_global.hpp71
-rw-r--r--src/liborcus/xml_element_types.cpp19
-rw-r--r--src/liborcus/xml_element_types.hpp30
-rw-r--r--src/liborcus/xml_element_validator.cpp60
-rw-r--r--src/liborcus/xml_element_validator.hpp50
-rw-r--r--src/liborcus/xml_empty_context.cpp44
-rw-r--r--src/liborcus/xml_empty_context.hpp39
-rw-r--r--src/liborcus/xml_map_tree.cpp772
-rw-r--r--src/liborcus/xml_map_tree.hpp316
-rw-r--r--src/liborcus/xml_map_tree_test.cpp274
-rw-r--r--src/liborcus/xml_simple_stream_handler.cpp54
-rw-r--r--src/liborcus/xml_simple_stream_handler.hpp40
-rw-r--r--src/liborcus/xml_stream_handler.cpp139
-rw-r--r--src/liborcus/xml_stream_handler.hpp66
-rw-r--r--src/liborcus/xml_stream_parser.cpp96
-rw-r--r--src/liborcus/xml_stream_parser.hpp84
-rw-r--r--src/liborcus/xml_structure_mapper.cpp84
-rw-r--r--src/liborcus/xml_structure_mapper.hpp40
-rw-r--r--src/liborcus/xml_structure_tree.cpp625
-rw-r--r--src/liborcus/xml_structure_tree_test.cpp286
-rw-r--r--src/liborcus/xml_util.cpp70
-rw-r--r--src/liborcus/xml_util.hpp43
-rw-r--r--src/liborcus/xpath_parser.cpp90
-rw-r--r--src/liborcus/xpath_parser.hpp49
-rw-r--r--src/liborcus/xpath_parser_test.cpp74
-rw-r--r--src/liborcus/yaml_document_tree.cpp856
-rw-r--r--src/liborcus/yaml_document_tree_test.cpp642
208 files changed, 59641 insertions, 0 deletions
diff --git a/src/liborcus/Makefile.am b/src/liborcus/Makefile.am
new file mode 100644
index 0000000..4f42193
--- /dev/null
+++ b/src/liborcus/Makefile.am
@@ -0,0 +1,590 @@
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/include \
+ -I./include $(BOOST_CPPFLAGS)
+
+EXTRA_PROGRAMS = \
+ css-document-tree-test \
+ json-document-tree-test \
+ yaml-document-tree-test \
+ xml-map-tree-test \
+ common-test \
+ dom-tree-test \
+ json-structure-tree-test \
+ json-map-tree-test \
+ xml-structure-tree-test \
+ xpath-parser-test
+
+TESTS =
+
+EXTRA_DIST = \
+ xml_element_types.hpp
+
+if HAVE_STATIC_LIB
+AM_CPPFLAGS += -D__ORCUS_STATIC_LIB=1
+else
+AM_CPPFLAGS += -D__ORCUS_BUILDING_DLL=1
+endif
+
+if HAVE_FILESYSTEM
+AM_CPPFLAGS += "-DHAVE_FILESYSTEM=1"
+endif
+
+if HAVE_EXPERIMENTAL_FILESYSTEM
+AM_CPPFLAGS += "-DHAVE_EXPERIMENTAL_FILESYSTEM=1"
+endif
+
+liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS = \
+ $(ZLIB_CFLAGS)
+
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS = \
+ -no-undefined $(BOOST_SYSTEM_LDFLAGS)
+
+liborcus_@ORCUS_API_VERSION@_la_LIBADD = \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(ZLIB_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS += -lstdc++fs
+else
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS += $(BOOST_FILESYSTEM_LDFLAGS)
+liborcus_@ORCUS_API_VERSION@_la_LIBADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+AM_CPPFLAGS += -DSRCDIR=\""$(top_srcdir)"\"
+
+lib_LTLIBRARIES = liborcus-@ORCUS_API_VERSION@.la
+liborcus_@ORCUS_API_VERSION@_la_SOURCES = \
+ config.cpp \
+ css_document_tree.cpp \
+ css_selector.cpp \
+ detection_result.hpp \
+ detection_result.cpp \
+ dom_tree.cpp \
+ format_detection.cpp \
+ formula_result.hpp \
+ formula_result.cpp \
+ impl_utils.hpp \
+ info.cpp \
+ interface.cpp \
+ json_document_tree.cpp \
+ json_map_tree.hpp \
+ json_map_tree.cpp \
+ json_structure_mapper.hpp \
+ json_structure_mapper.cpp \
+ json_structure_tree.cpp \
+ json_util.hpp \
+ json_util.cpp \
+ spreadsheet_interface.cpp \
+ orcus_csv.cpp \
+ orcus_json.cpp \
+ orcus_xml.cpp \
+ orcus_xml_impl.hpp \
+ orcus_xml_impl.cpp \
+ orcus_xml_map_def.cpp \
+ measurement.cpp \
+ number_utils.cpp \
+ number_utils.hpp \
+ xml_context_base.hpp \
+ xml_context_base.cpp \
+ xml_context_global.hpp \
+ xml_context_global.cpp \
+ xml_element_types.cpp \
+ xml_element_validator.hpp \
+ xml_element_validator.cpp \
+ xml_empty_context.hpp \
+ xml_empty_context.cpp \
+ xml_map_tree.hpp \
+ xml_map_tree.cpp \
+ xml_stream_handler.hpp \
+ xml_stream_handler.cpp \
+ xml_stream_parser.hpp \
+ xml_stream_parser.cpp \
+ xml_simple_stream_handler.hpp \
+ xml_simple_stream_handler.cpp \
+ xml_structure_mapper.hpp \
+ xml_structure_mapper.cpp \
+ xml_structure_tree.cpp \
+ xml_util.hpp \
+ xml_util.cpp \
+ xpath_parser.cpp \
+ yaml_document_tree.cpp \
+ ooxml_namespace_types.cpp \
+ ooxml_namespace_types.hpp \
+ odf_namespace_types.hpp \
+ odf_namespace_types_hpp.inl \
+ odf_namespace_types.cpp \
+ odf_namespace_types_cpp.inl \
+ gnumeric_namespace_types.hpp \
+ gnumeric_namespace_types.cpp \
+ xls_xml_namespace_types.hpp \
+ xls_xml_namespace_types.cpp \
+ session_context.hpp \
+ session_context.cpp \
+ spreadsheet_impl_types.hpp \
+ spreadsheet_impl_types.cpp \
+ spreadsheet_types.cpp \
+ spreadsheet_iface_util.hpp \
+ spreadsheet_iface_util.cpp \
+ string_helper.hpp \
+ string_helper.cpp
+
+if WITH_XLSX_FILTER
+
+EXTRA_PROGRAMS += \
+ xlsx-sheet-context-test
+
+liborcus_@ORCUS_API_VERSION@_la_SOURCES += \
+ ooxml_content_types.cpp \
+ ooxml_content_types.hpp \
+ ooxml_global.cpp \
+ ooxml_global.hpp \
+ ooxml_schemas.cpp \
+ ooxml_schemas.hpp \
+ ooxml_token_constants.hpp \
+ ooxml_token_constants.inl \
+ ooxml_tokens.cpp \
+ ooxml_tokens.hpp \
+ ooxml_tokens.inl \
+ ooxml_types.hpp \
+ ooxml_types.cpp \
+ opc_context.cpp \
+ opc_context.hpp \
+ opc_reader.cpp \
+ opc_reader.hpp \
+ opc_reader.hpp \
+ opc_token_constants.hpp \
+ opc_token_constants.inl \
+ opc_tokens.inl \
+ orcus_xlsx.cpp \
+ orcus_import_xlsx.cpp \
+ xlsx_shared_strings_context.cpp \
+ xlsx_shared_strings_context.hpp \
+ xlsx_drawing_context.hpp \
+ xlsx_drawing_context.cpp \
+ xlsx_handler.cpp \
+ xlsx_handler.hpp \
+ xlsx_helper.cpp \
+ xlsx_helper.hpp \
+ xlsx_session_data.hpp \
+ xlsx_session_data.cpp \
+ xlsx_revision_context.cpp \
+ xlsx_revision_context.hpp \
+ xlsx_pivot_context.cpp \
+ xlsx_pivot_context.hpp \
+ xlsx_sheet_context.cpp \
+ xlsx_sheet_context.hpp \
+ xlsx_styles_context.cpp \
+ xlsx_styles_context.hpp \
+ xlsx_conditional_format_context.cpp \
+ xlsx_conditional_format_context.hpp \
+ xlsx_table_context.cpp \
+ xlsx_table_context.hpp \
+ xlsx_autofilter_context.cpp \
+ xlsx_autofilter_context.hpp \
+ xlsx_types.hpp \
+ xlsx_types.cpp \
+ xlsx_workbook_context.cpp \
+ xlsx_workbook_context.hpp
+
+# xlsx-sheet-context-test
+
+xlsx_sheet_context_test_SOURCES = \
+ formula_result.cpp \
+ ooxml_global.cpp \
+ ooxml_namespace_types.cpp \
+ ooxml_schemas.cpp \
+ ooxml_tokens.cpp \
+ ooxml_types.cpp \
+ session_context.cpp \
+ spreadsheet_interface.cpp \
+ xlsx_autofilter_context.cpp \
+ xlsx_conditional_format_context.cpp \
+ xlsx_helper.cpp \
+ xlsx_session_data.cpp \
+ xlsx_sheet_context.cpp \
+ xlsx_sheet_context_test.cpp \
+ xlsx_types.cpp \
+ xml_context_base.cpp \
+ xml_context_global.cpp \
+ xml_element_types.cpp \
+ xml_element_validator.cpp \
+ xml_empty_context.cpp \
+ xml_util.cpp
+
+xlsx_sheet_context_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a
+
+xlsx_sheet_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+TESTS += \
+ xlsx-sheet-context-test
+
+endif # WITH_XLSX_FILTER
+
+if WITH_XLS_XML_FILTER
+
+liborcus_@ORCUS_API_VERSION@_la_SOURCES += \
+ xls_xml_tokens.hpp \
+ xls_xml_tokens.inl \
+ xls_xml_tokens.cpp \
+ xls_xml_token_constants.hpp \
+ xls_xml_token_constants.inl \
+ orcus_xls_xml.cpp \
+ xls_xml_detection_handler.hpp \
+ xls_xml_detection_handler.cpp \
+ xls_xml_handler.hpp \
+ xls_xml_handler.cpp \
+ xls_xml_context.hpp \
+ xls_xml_context.cpp
+
+endif # WITH_XLS_XML_FILTER
+
+if WITH_ODS_FILTER
+
+liborcus_@ORCUS_API_VERSION@_la_SOURCES += \
+ odf_document_styles_context.hpp \
+ odf_document_styles_context.cpp \
+ odf_para_context.hpp \
+ odf_para_context.cpp \
+ odf_styles.hpp \
+ odf_styles.cpp \
+ odf_styles_context.hpp \
+ odf_styles_context.cpp \
+ odf_style_context.hpp \
+ odf_style_context.cpp \
+ odf_number_format_context.hpp \
+ odf_number_format_context.cpp \
+ odf_token_constants.hpp \
+ odf_token_constants.inl \
+ odf_tokens.hpp \
+ odf_tokens.inl \
+ odf_tokens.cpp \
+ ods_content_xml_context.hpp \
+ ods_content_xml_context.cpp \
+ ods_dde_links_context.hpp \
+ ods_dde_links_context.cpp \
+ ods_session_data.hpp \
+ ods_session_data.cpp \
+ odf_helper.hpp \
+ odf_helper.cpp \
+ orcus_ods.cpp \
+ orcus_import_ods.cpp
+
+# odf-helper-test
+
+EXTRA_PROGRAMS += \
+ odf-helper-test
+
+odf_helper_test_SOURCES = \
+ odf_helper.cpp \
+ string_helper.cpp \
+ odf_helper_test.cpp
+
+odf_helper_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+odf_helper_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+TESTS += \
+ odf-helper-test
+
+endif # WITH_ODS_FILTER
+
+if WITH_GNUMERIC_FILTER
+
+liborcus_@ORCUS_API_VERSION@_la_SOURCES += \
+ gnumeric_cell_context.cpp \
+ gnumeric_cell_context.hpp \
+ gnumeric_context.cpp \
+ gnumeric_context.hpp \
+ gnumeric_detection_handler.cpp \
+ gnumeric_detection_handler.hpp \
+ gnumeric_filter_context.cpp \
+ gnumeric_filter_context.hpp \
+ gnumeric_handler.cpp \
+ gnumeric_handler.hpp \
+ gnumeric_names_context.cpp \
+ gnumeric_names_context.hpp \
+ gnumeric_sheet_context.cpp \
+ gnumeric_sheet_context.hpp \
+ gnumeric_styles_context.cpp \
+ gnumeric_styles_context.hpp \
+ gnumeric_token_constants.hpp \
+ gnumeric_token_constants.inl \
+ gnumeric_tokens.cpp \
+ gnumeric_tokens.hpp \
+ gnumeric_tokens.inl \
+ gnumeric_types.cpp \
+ gnumeric_types.hpp \
+ gnumeric_value_format_parser.cpp \
+ gnumeric_value_format_parser.hpp \
+ orcus_gnumeric.cpp
+
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS += \
+ $(BOOST_IOSTREAMS_LDFLAGS)
+
+liborcus_@ORCUS_API_VERSION@_la_LIBADD += \
+ $(BOOST_IOSTREAMS_LIBS)
+
+# gnumeric-cell-context-test
+
+EXTRA_PROGRAMS += \
+ gnumeric-cell-context-test \
+ gnumeric-sheet-context-test
+
+gnumeric_cell_context_test_SOURCES = \
+ number_utils.cpp \
+ session_context.cpp \
+ gnumeric_cell_context_test.cpp \
+ gnumeric_cell_context.cpp \
+ gnumeric_value_format_parser.cpp \
+ xml_context_base.cpp \
+ xml_element_types.cpp \
+ xml_element_validator.cpp \
+ xml_empty_context.cpp \
+ xml_util.cpp \
+ gnumeric_namespace_types.cpp \
+ gnumeric_tokens.cpp \
+ gnumeric_types.cpp \
+ odf_namespace_types.cpp \
+ spreadsheet_interface.cpp
+
+gnumeric_cell_context_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a
+
+orcus_gnumeric_cell_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+TESTS += gnumeric-cell-context-test
+
+# gnumeric-sheet-context-test
+
+gnumeric_sheet_context_test_SOURCES = \
+ session_context.cpp \
+ gnumeric_sheet_context_test.cpp \
+ gnumeric_sheet_context.cpp \
+ gnumeric_names_context.cpp \
+ gnumeric_cell_context.cpp \
+ gnumeric_filter_context.cpp \
+ gnumeric_styles_context.cpp \
+ gnumeric_value_format_parser.cpp \
+ gnumeric_types.cpp \
+ number_utils.cpp \
+ xml_context_base.cpp \
+ xml_element_types.cpp \
+ xml_element_validator.cpp \
+ xml_empty_context.cpp \
+ xml_util.cpp \
+ gnumeric_namespace_types.cpp \
+ gnumeric_tokens.cpp \
+ odf_namespace_types.cpp \
+ spreadsheet_interface.cpp \
+ string_helper.cpp
+
+gnumeric_sheet_context_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a
+
+gnumeric_sheet_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+TESTS += gnumeric-sheet-context-test
+
+endif # WITH_GNUMERIC_FILTER
+
+if WITH_PARQUET_FILTER
+
+liborcus_@ORCUS_API_VERSION@_la_SOURCES += \
+ orcus_parquet.cpp
+
+liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS += \
+ $(PARQUET_CFLAGS)
+
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS += \
+ $(PARQUET_LDFLAGS)
+
+liborcus_@ORCUS_API_VERSION@_la_LIBADD += \
+ $(PARQUET_LIBS)
+
+endif # WITH_PARQUET_FILTER
+
+# css-document-tree-test
+
+css_document_tree_test_SOURCES = \
+ css_document_tree.cpp \
+ css_document_tree_test.cpp
+
+css_document_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+css_document_tree_test_LDADD += -lstdc++fs
+else
+css_document_tree_test_LDADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+# json-document-tree-test
+
+json_document_tree_test_SOURCES = \
+ json_document_tree.cpp \
+ json_util.cpp \
+ json_document_tree_test.cpp
+
+json_document_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a \
+ $(BOOST_SYSTEM_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+json_document_tree_test_LDADD += -lstdc++fs
+else
+json_document_tree_test_LDADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+json_document_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# yaml-document-tree-test
+
+yaml_document_tree_test_SOURCES = \
+ yaml_document_tree.cpp \
+ json_util.cpp \
+ yaml_document_tree_test.cpp
+
+yaml_document_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+yaml_document_tree_test_LDADD += -lstdc++fs
+else
+yaml_document_tree_test_LDADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+yaml_document_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# xml-map-tree-test
+
+xml_map_tree_test_SOURCES = \
+ xml_map_tree.cpp \
+ xml_map_tree.hpp \
+ xpath_parser.hpp \
+ xpath_parser.cpp \
+ spreadsheet_impl_types.hpp \
+ spreadsheet_impl_types.cpp \
+ xml_map_tree_test.cpp
+
+xml_map_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a \
+ $(BOOST_SYSTEM_LIBS)
+
+# xml-structure-tree-test
+
+xml_structure_tree_test_SOURCES = \
+ string_helper.cpp \
+ xml_structure_tree.cpp \
+ xml_structure_mapper.cpp \
+ xml_structure_tree_test.cpp
+
+xml_structure_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+xml_structure_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+xml_structure_tree_test_LDADD += -lstdc++fs
+else
+xml_structure_tree_test_LDADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+# common-test
+
+common_test_SOURCES = \
+ common_test.cpp
+
+common_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+# dom-tree-test
+
+dom_tree_test_SOURCES = dom_tree_test.cpp
+dom_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+# json-structure-tree-test
+
+json_structure_tree_test_SOURCES = json_structure_tree_test.cpp
+json_structure_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+if !HAVE_FILESYSTEM
+if HAVE_EXPERIMENTAL_FILESYSTEM
+json_structure_tree_test_LDADD += -lstdc++fs
+else
+json_structure_tree_test_LDADD += $(BOOST_FILESYSTEM_LIBS)
+endif
+endif
+
+# json-map-tree-test
+
+json_map_tree_test_SOURCES = json_map_tree_test.cpp \
+ json_map_tree.cpp \
+ spreadsheet_impl_types.cpp
+json_map_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+# xpath-parser-test
+
+xpath_parser_test_SOURCES = \
+ xpath_parser_test.cpp \
+ xpath_parser.cpp
+xpath_parser_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+TESTS += \
+ css-document-tree-test \
+ json-document-tree-test \
+ yaml-document-tree-test \
+ xml-map-tree-test \
+ common-test \
+ dom-tree-test \
+ json-structure-tree-test \
+ json-map-tree-test \
+ xml-structure-tree-test \
+ xpath-parser-test
+
+distclean-local:
+ rm -rf $(TESTS)
+
+@VALGRIND_CHECK_RULES@
diff --git a/src/liborcus/Makefile.in b/src/liborcus/Makefile.in
new file mode 100644
index 0000000..2b75863
--- /dev/null
+++ b/src/liborcus/Makefile.in
@@ -0,0 +1,4283 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+EXTRA_PROGRAMS = css-document-tree-test$(EXEEXT) \
+ json-document-tree-test$(EXEEXT) \
+ yaml-document-tree-test$(EXEEXT) xml-map-tree-test$(EXEEXT) \
+ common-test$(EXEEXT) dom-tree-test$(EXEEXT) \
+ json-structure-tree-test$(EXEEXT) json-map-tree-test$(EXEEXT) \
+ xml-structure-tree-test$(EXEEXT) xpath-parser-test$(EXEEXT) \
+ $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
+TESTS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
+ css-document-tree-test$(EXEEXT) \
+ json-document-tree-test$(EXEEXT) \
+ yaml-document-tree-test$(EXEEXT) xml-map-tree-test$(EXEEXT) \
+ common-test$(EXEEXT) dom-tree-test$(EXEEXT) \
+ json-structure-tree-test$(EXEEXT) json-map-tree-test$(EXEEXT) \
+ xml-structure-tree-test$(EXEEXT) xpath-parser-test$(EXEEXT)
+@HAVE_STATIC_LIB_TRUE@am__append_1 = -D__ORCUS_STATIC_LIB=1
+@HAVE_STATIC_LIB_FALSE@am__append_2 = -D__ORCUS_BUILDING_DLL=1
+@HAVE_FILESYSTEM_TRUE@am__append_3 = "-DHAVE_FILESYSTEM=1"
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@am__append_4 = "-DHAVE_EXPERIMENTAL_FILESYSTEM=1"
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_5 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_6 = $(BOOST_FILESYSTEM_LDFLAGS)
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_7 = $(BOOST_FILESYSTEM_LIBS)
+@WITH_XLSX_FILTER_TRUE@am__append_8 = \
+@WITH_XLSX_FILTER_TRUE@ xlsx-sheet-context-test
+
+@WITH_XLSX_FILTER_TRUE@am__append_9 = \
+@WITH_XLSX_FILTER_TRUE@ ooxml_content_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_content_types.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_global.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_global.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_schemas.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_schemas.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_token_constants.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_token_constants.inl \
+@WITH_XLSX_FILTER_TRUE@ ooxml_tokens.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_tokens.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_tokens.inl \
+@WITH_XLSX_FILTER_TRUE@ ooxml_types.hpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ opc_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ opc_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ opc_reader.cpp \
+@WITH_XLSX_FILTER_TRUE@ opc_reader.hpp \
+@WITH_XLSX_FILTER_TRUE@ opc_reader.hpp \
+@WITH_XLSX_FILTER_TRUE@ opc_token_constants.hpp \
+@WITH_XLSX_FILTER_TRUE@ opc_token_constants.inl \
+@WITH_XLSX_FILTER_TRUE@ opc_tokens.inl \
+@WITH_XLSX_FILTER_TRUE@ orcus_xlsx.cpp \
+@WITH_XLSX_FILTER_TRUE@ orcus_import_xlsx.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_shared_strings_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_shared_strings_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_drawing_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_drawing_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_handler.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_handler.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_helper.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_helper.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_session_data.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_session_data.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_revision_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_revision_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_pivot_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_pivot_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_styles_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_styles_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_conditional_format_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_conditional_format_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_table_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_table_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_autofilter_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_autofilter_context.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_types.hpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_workbook_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_workbook_context.hpp
+
+@WITH_XLSX_FILTER_TRUE@am__append_10 = \
+@WITH_XLSX_FILTER_TRUE@ xlsx-sheet-context-test
+
+@WITH_XLS_XML_FILTER_TRUE@am__append_11 = \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_tokens.hpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_tokens.inl \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_tokens.cpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_token_constants.hpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_token_constants.inl \
+@WITH_XLS_XML_FILTER_TRUE@ orcus_xls_xml.cpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_detection_handler.hpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_detection_handler.cpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_handler.hpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_handler.cpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_context.hpp \
+@WITH_XLS_XML_FILTER_TRUE@ xls_xml_context.cpp
+
+@WITH_ODS_FILTER_TRUE@am__append_12 = \
+@WITH_ODS_FILTER_TRUE@ odf_document_styles_context.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_document_styles_context.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_para_context.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_para_context.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_styles.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_styles.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_styles_context.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_styles_context.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_style_context.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_style_context.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_number_format_context.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_number_format_context.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_token_constants.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_token_constants.inl \
+@WITH_ODS_FILTER_TRUE@ odf_tokens.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_tokens.inl \
+@WITH_ODS_FILTER_TRUE@ odf_tokens.cpp \
+@WITH_ODS_FILTER_TRUE@ ods_content_xml_context.hpp \
+@WITH_ODS_FILTER_TRUE@ ods_content_xml_context.cpp \
+@WITH_ODS_FILTER_TRUE@ ods_dde_links_context.hpp \
+@WITH_ODS_FILTER_TRUE@ ods_dde_links_context.cpp \
+@WITH_ODS_FILTER_TRUE@ ods_session_data.hpp \
+@WITH_ODS_FILTER_TRUE@ ods_session_data.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_helper.hpp \
+@WITH_ODS_FILTER_TRUE@ odf_helper.cpp \
+@WITH_ODS_FILTER_TRUE@ orcus_ods.cpp \
+@WITH_ODS_FILTER_TRUE@ orcus_import_ods.cpp
+
+
+# odf-helper-test
+@WITH_ODS_FILTER_TRUE@am__append_13 = \
+@WITH_ODS_FILTER_TRUE@ odf-helper-test
+
+@WITH_ODS_FILTER_TRUE@am__append_14 = \
+@WITH_ODS_FILTER_TRUE@ odf-helper-test
+
+@WITH_GNUMERIC_FILTER_TRUE@am__append_15 = \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_detection_handler.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_detection_handler.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_filter_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_filter_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_handler.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_handler.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_names_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_names_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_styles_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_styles_context.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_token_constants.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_token_constants.inl \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.inl \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_types.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_value_format_parser.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_value_format_parser.hpp \
+@WITH_GNUMERIC_FILTER_TRUE@ orcus_gnumeric.cpp
+
+@WITH_GNUMERIC_FILTER_TRUE@am__append_16 = \
+@WITH_GNUMERIC_FILTER_TRUE@ $(BOOST_IOSTREAMS_LDFLAGS)
+
+@WITH_GNUMERIC_FILTER_TRUE@am__append_17 = \
+@WITH_GNUMERIC_FILTER_TRUE@ $(BOOST_IOSTREAMS_LIBS)
+
+
+# gnumeric-cell-context-test
+@WITH_GNUMERIC_FILTER_TRUE@am__append_18 = \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric-cell-context-test \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric-sheet-context-test
+
+@WITH_GNUMERIC_FILTER_TRUE@am__append_19 = gnumeric-cell-context-test \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric-sheet-context-test
+@WITH_PARQUET_FILTER_TRUE@am__append_20 = \
+@WITH_PARQUET_FILTER_TRUE@ orcus_parquet.cpp
+
+@WITH_PARQUET_FILTER_TRUE@am__append_21 = \
+@WITH_PARQUET_FILTER_TRUE@ $(PARQUET_CFLAGS)
+
+@WITH_PARQUET_FILTER_TRUE@am__append_22 = \
+@WITH_PARQUET_FILTER_TRUE@ $(PARQUET_LDFLAGS)
+
+@WITH_PARQUET_FILTER_TRUE@am__append_23 = \
+@WITH_PARQUET_FILTER_TRUE@ $(PARQUET_LIBS)
+
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_24 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_25 = $(BOOST_FILESYSTEM_LIBS)
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_26 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_27 = $(BOOST_FILESYSTEM_LIBS)
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_28 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_29 = $(BOOST_FILESYSTEM_LIBS)
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_30 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_31 = $(BOOST_FILESYSTEM_LIBS)
+@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_32 = -lstdc++fs
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_33 = $(BOOST_FILESYSTEM_LIBS)
+subdir = src/liborcus
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \
+ $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = constants.inl
+CONFIG_CLEAN_VPATH_FILES =
+@WITH_XLSX_FILTER_TRUE@am__EXEEXT_1 = \
+@WITH_XLSX_FILTER_TRUE@ xlsx-sheet-context-test$(EXEEXT)
+@WITH_ODS_FILTER_TRUE@am__EXEEXT_2 = odf-helper-test$(EXEEXT)
+@WITH_GNUMERIC_FILTER_TRUE@am__EXEEXT_3 = gnumeric-cell-context-test$(EXEEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric-sheet-context-test$(EXEEXT)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@WITH_GNUMERIC_FILTER_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@WITH_PARQUET_FILTER_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+liborcus_@ORCUS_API_VERSION@_la_DEPENDENCIES = \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \
+ $(am__DEPENDENCIES_4)
+am__liborcus_@ORCUS_API_VERSION@_la_SOURCES_DIST = config.cpp \
+ css_document_tree.cpp css_selector.cpp detection_result.hpp \
+ detection_result.cpp dom_tree.cpp format_detection.cpp \
+ formula_result.hpp formula_result.cpp impl_utils.hpp info.cpp \
+ interface.cpp json_document_tree.cpp json_map_tree.hpp \
+ json_map_tree.cpp json_structure_mapper.hpp \
+ json_structure_mapper.cpp json_structure_tree.cpp \
+ json_util.hpp json_util.cpp spreadsheet_interface.cpp \
+ orcus_csv.cpp orcus_json.cpp orcus_xml.cpp orcus_xml_impl.hpp \
+ orcus_xml_impl.cpp orcus_xml_map_def.cpp measurement.cpp \
+ number_utils.cpp number_utils.hpp xml_context_base.hpp \
+ xml_context_base.cpp xml_context_global.hpp \
+ xml_context_global.cpp xml_element_types.cpp \
+ xml_element_validator.hpp xml_element_validator.cpp \
+ xml_empty_context.hpp xml_empty_context.cpp xml_map_tree.hpp \
+ xml_map_tree.cpp xml_stream_handler.hpp xml_stream_handler.cpp \
+ xml_stream_parser.hpp xml_stream_parser.cpp \
+ xml_simple_stream_handler.hpp xml_simple_stream_handler.cpp \
+ xml_structure_mapper.hpp xml_structure_mapper.cpp \
+ xml_structure_tree.cpp xml_util.hpp xml_util.cpp \
+ xpath_parser.cpp yaml_document_tree.cpp \
+ ooxml_namespace_types.cpp ooxml_namespace_types.hpp \
+ odf_namespace_types.hpp odf_namespace_types_hpp.inl \
+ odf_namespace_types.cpp odf_namespace_types_cpp.inl \
+ gnumeric_namespace_types.hpp gnumeric_namespace_types.cpp \
+ xls_xml_namespace_types.hpp xls_xml_namespace_types.cpp \
+ session_context.hpp session_context.cpp \
+ spreadsheet_impl_types.hpp spreadsheet_impl_types.cpp \
+ spreadsheet_types.cpp spreadsheet_iface_util.hpp \
+ spreadsheet_iface_util.cpp string_helper.hpp string_helper.cpp \
+ ooxml_content_types.cpp ooxml_content_types.hpp \
+ ooxml_global.cpp ooxml_global.hpp ooxml_schemas.cpp \
+ ooxml_schemas.hpp ooxml_token_constants.hpp \
+ ooxml_token_constants.inl ooxml_tokens.cpp ooxml_tokens.hpp \
+ ooxml_tokens.inl ooxml_types.hpp ooxml_types.cpp \
+ opc_context.cpp opc_context.hpp opc_reader.cpp opc_reader.hpp \
+ opc_token_constants.hpp opc_token_constants.inl opc_tokens.inl \
+ orcus_xlsx.cpp orcus_import_xlsx.cpp \
+ xlsx_shared_strings_context.cpp \
+ xlsx_shared_strings_context.hpp xlsx_drawing_context.hpp \
+ xlsx_drawing_context.cpp xlsx_handler.cpp xlsx_handler.hpp \
+ xlsx_helper.cpp xlsx_helper.hpp xlsx_session_data.hpp \
+ xlsx_session_data.cpp xlsx_revision_context.cpp \
+ xlsx_revision_context.hpp xlsx_pivot_context.cpp \
+ xlsx_pivot_context.hpp xlsx_sheet_context.cpp \
+ xlsx_sheet_context.hpp xlsx_styles_context.cpp \
+ xlsx_styles_context.hpp xlsx_conditional_format_context.cpp \
+ xlsx_conditional_format_context.hpp xlsx_table_context.cpp \
+ xlsx_table_context.hpp xlsx_autofilter_context.cpp \
+ xlsx_autofilter_context.hpp xlsx_types.hpp xlsx_types.cpp \
+ xlsx_workbook_context.cpp xlsx_workbook_context.hpp \
+ xls_xml_tokens.hpp xls_xml_tokens.inl xls_xml_tokens.cpp \
+ xls_xml_token_constants.hpp xls_xml_token_constants.inl \
+ orcus_xls_xml.cpp xls_xml_detection_handler.hpp \
+ xls_xml_detection_handler.cpp xls_xml_handler.hpp \
+ xls_xml_handler.cpp xls_xml_context.hpp xls_xml_context.cpp \
+ odf_document_styles_context.hpp \
+ odf_document_styles_context.cpp odf_para_context.hpp \
+ odf_para_context.cpp odf_styles.hpp odf_styles.cpp \
+ odf_styles_context.hpp odf_styles_context.cpp \
+ odf_style_context.hpp odf_style_context.cpp \
+ odf_number_format_context.hpp odf_number_format_context.cpp \
+ odf_token_constants.hpp odf_token_constants.inl odf_tokens.hpp \
+ odf_tokens.inl odf_tokens.cpp ods_content_xml_context.hpp \
+ ods_content_xml_context.cpp ods_dde_links_context.hpp \
+ ods_dde_links_context.cpp ods_session_data.hpp \
+ ods_session_data.cpp odf_helper.hpp odf_helper.cpp \
+ orcus_ods.cpp orcus_import_ods.cpp gnumeric_cell_context.cpp \
+ gnumeric_cell_context.hpp gnumeric_context.cpp \
+ gnumeric_context.hpp gnumeric_detection_handler.cpp \
+ gnumeric_detection_handler.hpp gnumeric_filter_context.cpp \
+ gnumeric_filter_context.hpp gnumeric_handler.cpp \
+ gnumeric_handler.hpp gnumeric_names_context.cpp \
+ gnumeric_names_context.hpp gnumeric_sheet_context.cpp \
+ gnumeric_sheet_context.hpp gnumeric_styles_context.cpp \
+ gnumeric_styles_context.hpp gnumeric_token_constants.hpp \
+ gnumeric_token_constants.inl gnumeric_tokens.cpp \
+ gnumeric_tokens.hpp gnumeric_tokens.inl gnumeric_types.cpp \
+ gnumeric_types.hpp gnumeric_value_format_parser.cpp \
+ gnumeric_value_format_parser.hpp orcus_gnumeric.cpp \
+ orcus_parquet.cpp
+@WITH_XLSX_FILTER_TRUE@am__objects_1 = liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-opc_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo \
+@WITH_XLSX_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo
+@WITH_XLS_XML_FILTER_TRUE@am__objects_2 = liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo \
+@WITH_XLS_XML_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo \
+@WITH_XLS_XML_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo \
+@WITH_XLS_XML_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo \
+@WITH_XLS_XML_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo
+@WITH_ODS_FILTER_TRUE@am__objects_3 = liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo \
+@WITH_ODS_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo
+@WITH_GNUMERIC_FILTER_TRUE@am__objects_4 = liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo
+@WITH_PARQUET_FILTER_TRUE@am__objects_5 = liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo
+am_liborcus_@ORCUS_API_VERSION@_la_OBJECTS = \
+ liborcus_@ORCUS_API_VERSION@_la-config.lo \
+ liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-css_selector.lo \
+ liborcus_@ORCUS_API_VERSION@_la-detection_result.lo \
+ liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-format_detection.lo \
+ liborcus_@ORCUS_API_VERSION@_la-formula_result.lo \
+ liborcus_@ORCUS_API_VERSION@_la-info.lo \
+ liborcus_@ORCUS_API_VERSION@_la-interface.lo \
+ liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo \
+ liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-json_util.lo \
+ liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo \
+ liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo \
+ liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo \
+ liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo \
+ liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo \
+ liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo \
+ liborcus_@ORCUS_API_VERSION@_la-measurement.lo \
+ liborcus_@ORCUS_API_VERSION@_la-number_utils.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xml_util.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo \
+ liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo \
+ liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-session_context.lo \
+ liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo \
+ liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo \
+ liborcus_@ORCUS_API_VERSION@_la-string_helper.lo \
+ $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+ $(am__objects_4) $(am__objects_5)
+liborcus_@ORCUS_API_VERSION@_la_OBJECTS = \
+ $(am_liborcus_@ORCUS_API_VERSION@_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+liborcus_@ORCUS_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) \
+ $(liborcus_@ORCUS_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@
+am_common_test_OBJECTS = common_test.$(OBJEXT)
+common_test_OBJECTS = $(am_common_test_OBJECTS)
+common_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+am_css_document_tree_test_OBJECTS = css_document_tree.$(OBJEXT) \
+ css_document_tree_test.$(OBJEXT)
+css_document_tree_test_OBJECTS = $(am_css_document_tree_test_OBJECTS)
+css_document_tree_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+am_dom_tree_test_OBJECTS = dom_tree_test.$(OBJEXT)
+dom_tree_test_OBJECTS = $(am_dom_tree_test_OBJECTS)
+dom_tree_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+am__gnumeric_cell_context_test_SOURCES_DIST = number_utils.cpp \
+ session_context.cpp gnumeric_cell_context_test.cpp \
+ gnumeric_cell_context.cpp gnumeric_value_format_parser.cpp \
+ xml_context_base.cpp xml_element_types.cpp \
+ xml_element_validator.cpp xml_empty_context.cpp xml_util.cpp \
+ gnumeric_namespace_types.cpp gnumeric_tokens.cpp \
+ gnumeric_types.cpp odf_namespace_types.cpp \
+ spreadsheet_interface.cpp
+@WITH_GNUMERIC_FILTER_TRUE@am_gnumeric_cell_context_test_OBJECTS = \
+@WITH_GNUMERIC_FILTER_TRUE@ number_utils.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ session_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context_test.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_value_format_parser.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_context_base.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_validator.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_empty_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_util.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_namespace_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ odf_namespace_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ spreadsheet_interface.$(OBJEXT)
+gnumeric_cell_context_test_OBJECTS = \
+ $(am_gnumeric_cell_context_test_OBJECTS)
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_cell_context_test_DEPENDENCIES = \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../test/liborcus-test.a
+am__gnumeric_sheet_context_test_SOURCES_DIST = session_context.cpp \
+ gnumeric_sheet_context_test.cpp gnumeric_sheet_context.cpp \
+ gnumeric_names_context.cpp gnumeric_cell_context.cpp \
+ gnumeric_filter_context.cpp gnumeric_styles_context.cpp \
+ gnumeric_value_format_parser.cpp gnumeric_types.cpp \
+ number_utils.cpp xml_context_base.cpp xml_element_types.cpp \
+ xml_element_validator.cpp xml_empty_context.cpp xml_util.cpp \
+ gnumeric_namespace_types.cpp gnumeric_tokens.cpp \
+ odf_namespace_types.cpp spreadsheet_interface.cpp \
+ string_helper.cpp
+@WITH_GNUMERIC_FILTER_TRUE@am_gnumeric_sheet_context_test_OBJECTS = gnumeric_sheet_context_test-session_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_sheet_context_test.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_sheet_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_names_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_cell_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_filter_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_styles_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_value_format_parser.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-number_utils.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-xml_context_base.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-xml_element_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-xml_element_validator.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-xml_empty_context.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-xml_util.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_namespace_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-gnumeric_tokens.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-odf_namespace_types.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-spreadsheet_interface.$(OBJEXT) \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test-string_helper.$(OBJEXT)
+gnumeric_sheet_context_test_OBJECTS = \
+ $(am_gnumeric_sheet_context_test_OBJECTS)
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_sheet_context_test_DEPENDENCIES = \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../test/liborcus-test.a
+am_json_document_tree_test_OBJECTS = \
+ json_document_tree_test-json_document_tree.$(OBJEXT) \
+ json_document_tree_test-json_util.$(OBJEXT) \
+ json_document_tree_test-json_document_tree_test.$(OBJEXT)
+json_document_tree_test_OBJECTS = \
+ $(am_json_document_tree_test_OBJECTS)
+json_document_tree_test_DEPENDENCIES = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am_json_map_tree_test_OBJECTS = json_map_tree_test.$(OBJEXT) \
+ json_map_tree.$(OBJEXT) spreadsheet_impl_types.$(OBJEXT)
+json_map_tree_test_OBJECTS = $(am_json_map_tree_test_OBJECTS)
+json_map_tree_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1)
+am_json_structure_tree_test_OBJECTS = \
+ json_structure_tree_test.$(OBJEXT)
+json_structure_tree_test_OBJECTS = \
+ $(am_json_structure_tree_test_OBJECTS)
+json_structure_tree_test_DEPENDENCIES = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+am__odf_helper_test_SOURCES_DIST = odf_helper.cpp string_helper.cpp \
+ odf_helper_test.cpp
+@WITH_ODS_FILTER_TRUE@am_odf_helper_test_OBJECTS = \
+@WITH_ODS_FILTER_TRUE@ odf_helper_test-odf_helper.$(OBJEXT) \
+@WITH_ODS_FILTER_TRUE@ odf_helper_test-string_helper.$(OBJEXT) \
+@WITH_ODS_FILTER_TRUE@ odf_helper_test-odf_helper_test.$(OBJEXT)
+odf_helper_test_OBJECTS = $(am_odf_helper_test_OBJECTS)
+@WITH_ODS_FILTER_TRUE@odf_helper_test_DEPENDENCIES = \
+@WITH_ODS_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_ODS_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+am__xlsx_sheet_context_test_SOURCES_DIST = formula_result.cpp \
+ ooxml_global.cpp ooxml_namespace_types.cpp ooxml_schemas.cpp \
+ ooxml_tokens.cpp ooxml_types.cpp session_context.cpp \
+ spreadsheet_interface.cpp xlsx_autofilter_context.cpp \
+ xlsx_conditional_format_context.cpp xlsx_helper.cpp \
+ xlsx_session_data.cpp xlsx_sheet_context.cpp \
+ xlsx_sheet_context_test.cpp xlsx_types.cpp \
+ xml_context_base.cpp xml_context_global.cpp \
+ xml_element_types.cpp xml_element_validator.cpp \
+ xml_empty_context.cpp xml_util.cpp
+@WITH_XLSX_FILTER_TRUE@am_xlsx_sheet_context_test_OBJECTS = xlsx_sheet_context_test-formula_result.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-ooxml_global.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-ooxml_namespace_types.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-ooxml_schemas.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-ooxml_tokens.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-ooxml_types.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-session_context.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-spreadsheet_interface.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_autofilter_context.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_conditional_format_context.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_helper.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_session_data.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_sheet_context.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_sheet_context_test.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xlsx_types.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_context_base.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_context_global.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_element_types.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_element_validator.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_empty_context.$(OBJEXT) \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test-xml_util.$(OBJEXT)
+xlsx_sheet_context_test_OBJECTS = \
+ $(am_xlsx_sheet_context_test_OBJECTS)
+@WITH_XLSX_FILTER_TRUE@xlsx_sheet_context_test_DEPENDENCIES = \
+@WITH_XLSX_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_XLSX_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_XLSX_FILTER_TRUE@ ../test/liborcus-test.a
+am_xml_map_tree_test_OBJECTS = xml_map_tree.$(OBJEXT) \
+ xpath_parser.$(OBJEXT) spreadsheet_impl_types.$(OBJEXT) \
+ xml_map_tree_test.$(OBJEXT)
+xml_map_tree_test_OBJECTS = $(am_xml_map_tree_test_OBJECTS)
+xml_map_tree_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a $(am__DEPENDENCIES_1)
+am_xml_structure_tree_test_OBJECTS = \
+ xml_structure_tree_test-string_helper.$(OBJEXT) \
+ xml_structure_tree_test-xml_structure_tree.$(OBJEXT) \
+ xml_structure_tree_test-xml_structure_mapper.$(OBJEXT) \
+ xml_structure_tree_test-xml_structure_tree_test.$(OBJEXT)
+xml_structure_tree_test_OBJECTS = \
+ $(am_xml_structure_tree_test_OBJECTS)
+xml_structure_tree_test_DEPENDENCIES = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+am_xpath_parser_test_OBJECTS = xpath_parser_test.$(OBJEXT) \
+ xpath_parser.$(OBJEXT)
+xpath_parser_test_OBJECTS = $(am_xpath_parser_test_OBJECTS)
+xpath_parser_test_DEPENDENCIES = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1)
+am_yaml_document_tree_test_OBJECTS = \
+ yaml_document_tree_test-yaml_document_tree.$(OBJEXT) \
+ yaml_document_tree_test-json_util.$(OBJEXT) \
+ yaml_document_tree_test-yaml_document_tree_test.$(OBJEXT)
+yaml_document_tree_test_OBJECTS = \
+ $(am_yaml_document_tree_test_OBJECTS)
+yaml_document_tree_test_DEPENDENCIES = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_2)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/common_test.Po \
+ ./$(DEPDIR)/css_document_tree.Po \
+ ./$(DEPDIR)/css_document_tree_test.Po \
+ ./$(DEPDIR)/dom_tree_test.Po \
+ ./$(DEPDIR)/gnumeric_cell_context.Po \
+ ./$(DEPDIR)/gnumeric_cell_context_test.Po \
+ ./$(DEPDIR)/gnumeric_namespace_types.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-session_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po \
+ ./$(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po \
+ ./$(DEPDIR)/gnumeric_tokens.Po ./$(DEPDIR)/gnumeric_types.Po \
+ ./$(DEPDIR)/gnumeric_value_format_parser.Po \
+ ./$(DEPDIR)/json_document_tree_test-json_document_tree.Po \
+ ./$(DEPDIR)/json_document_tree_test-json_document_tree_test.Po \
+ ./$(DEPDIR)/json_document_tree_test-json_util.Po \
+ ./$(DEPDIR)/json_map_tree.Po ./$(DEPDIR)/json_map_tree_test.Po \
+ ./$(DEPDIR)/json_structure_tree_test.Po \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Plo \
+ ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Plo \
+ ./$(DEPDIR)/number_utils.Po \
+ ./$(DEPDIR)/odf_helper_test-odf_helper.Po \
+ ./$(DEPDIR)/odf_helper_test-odf_helper_test.Po \
+ ./$(DEPDIR)/odf_helper_test-string_helper.Po \
+ ./$(DEPDIR)/odf_namespace_types.Po \
+ ./$(DEPDIR)/session_context.Po \
+ ./$(DEPDIR)/spreadsheet_impl_types.Po \
+ ./$(DEPDIR)/spreadsheet_interface.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-formula_result.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-session_context.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po \
+ ./$(DEPDIR)/xlsx_sheet_context_test-xml_util.Po \
+ ./$(DEPDIR)/xml_context_base.Po \
+ ./$(DEPDIR)/xml_element_types.Po \
+ ./$(DEPDIR)/xml_element_validator.Po \
+ ./$(DEPDIR)/xml_empty_context.Po ./$(DEPDIR)/xml_map_tree.Po \
+ ./$(DEPDIR)/xml_map_tree_test.Po \
+ ./$(DEPDIR)/xml_structure_tree_test-string_helper.Po \
+ ./$(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po \
+ ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po \
+ ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po \
+ ./$(DEPDIR)/xml_util.Po ./$(DEPDIR)/xpath_parser.Po \
+ ./$(DEPDIR)/xpath_parser_test.Po \
+ ./$(DEPDIR)/yaml_document_tree_test-json_util.Po \
+ ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po \
+ ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(liborcus_@ORCUS_API_VERSION@_la_SOURCES) \
+ $(common_test_SOURCES) $(css_document_tree_test_SOURCES) \
+ $(dom_tree_test_SOURCES) $(gnumeric_cell_context_test_SOURCES) \
+ $(gnumeric_sheet_context_test_SOURCES) \
+ $(json_document_tree_test_SOURCES) \
+ $(json_map_tree_test_SOURCES) \
+ $(json_structure_tree_test_SOURCES) $(odf_helper_test_SOURCES) \
+ $(xlsx_sheet_context_test_SOURCES) \
+ $(xml_map_tree_test_SOURCES) \
+ $(xml_structure_tree_test_SOURCES) \
+ $(xpath_parser_test_SOURCES) \
+ $(yaml_document_tree_test_SOURCES)
+DIST_SOURCES = $(am__liborcus_@ORCUS_API_VERSION@_la_SOURCES_DIST) \
+ $(common_test_SOURCES) $(css_document_tree_test_SOURCES) \
+ $(dom_tree_test_SOURCES) \
+ $(am__gnumeric_cell_context_test_SOURCES_DIST) \
+ $(am__gnumeric_sheet_context_test_SOURCES_DIST) \
+ $(json_document_tree_test_SOURCES) \
+ $(json_map_tree_test_SOURCES) \
+ $(json_structure_tree_test_SOURCES) \
+ $(am__odf_helper_test_SOURCES_DIST) \
+ $(am__xlsx_sheet_context_test_SOURCES_DIST) \
+ $(xml_map_tree_test_SOURCES) \
+ $(xml_structure_tree_test_SOURCES) \
+ $(xpath_parser_test_SOURCES) \
+ $(yaml_document_tree_test_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__extra_recursive_targets = check-valgrind-recursive \
+ check-valgrind-memcheck-recursive \
+ check-valgrind-helgrind-recursive check-valgrind-drd-recursive \
+ check-valgrind-sgcheck-recursive
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/constants.inl.in \
+ $(top_srcdir)/depcomp $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
+BOOST_DATE_TIME_LDFLAGS = @BOOST_DATE_TIME_LDFLAGS@
+BOOST_DATE_TIME_LDPATH = @BOOST_DATE_TIME_LDPATH@
+BOOST_DATE_TIME_LIBS = @BOOST_DATE_TIME_LIBS@
+BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@
+BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@
+BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@
+BOOST_IOSTREAMS_LDFLAGS = @BOOST_IOSTREAMS_LDFLAGS@
+BOOST_IOSTREAMS_LDPATH = @BOOST_IOSTREAMS_LDPATH@
+BOOST_IOSTREAMS_LIBS = @BOOST_IOSTREAMS_LIBS@
+BOOST_LDPATH = @BOOST_LDPATH@
+BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@
+BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@
+BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@
+BOOST_ROOT = @BOOST_ROOT@
+BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@
+BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@
+BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@
+ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@
+ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@
+ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_CXX17 = @HAVE_CXX17@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IXION_REQUIRED_API_VERSION = @IXION_REQUIRED_API_VERSION@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBIXION_CFLAGS = @LIBIXION_CFLAGS@
+LIBIXION_LIBS = @LIBIXION_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MDDS_CFLAGS = @MDDS_CFLAGS@
+MDDS_LIBS = @MDDS_LIBS@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORCUS_API_VERSION = @ORCUS_API_VERSION@
+ORCUS_MAJOR_VERSION = @ORCUS_MAJOR_VERSION@
+ORCUS_MICRO_VERSION = @ORCUS_MICRO_VERSION@
+ORCUS_MINOR_VERSION = @ORCUS_MINOR_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PARQUET_CFLAGS = @PARQUET_CFLAGS@
+PARQUET_LIBS = @PARQUET_LIBS@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POW_LIB = @POW_LIB@
+PYTHON = @PYTHON@
+PYTHON_CFLAGS = @PYTHON_CFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_LIBS = @PYTHON_LIBS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VALGRIND = @VALGRIND@
+VALGRIND_ENABLED = @VALGRIND_ENABLED@
+VERSION = @VERSION@
+ZLIB_CFLAGS = @ZLIB_CFLAGS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+valgrind_enabled_tools = @valgrind_enabled_tools@
+valgrind_tools = @valgrind_tools@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/include \
+ -I./include $(BOOST_CPPFLAGS) $(am__append_1) $(am__append_2) \
+ $(am__append_3) $(am__append_4) -DSRCDIR=\""$(top_srcdir)"\"
+EXTRA_DIST = \
+ xml_element_types.hpp
+
+liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS = $(ZLIB_CFLAGS) \
+ $(am__append_21)
+liborcus_@ORCUS_API_VERSION@_la_LDFLAGS = -no-undefined \
+ $(BOOST_SYSTEM_LDFLAGS) $(am__append_5) $(am__append_6) \
+ $(am__append_16) $(am__append_22)
+liborcus_@ORCUS_API_VERSION@_la_LIBADD = \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(ZLIB_LIBS) $(am__append_7) \
+ $(am__append_17) $(am__append_23)
+lib_LTLIBRARIES = liborcus-@ORCUS_API_VERSION@.la
+liborcus_@ORCUS_API_VERSION@_la_SOURCES = config.cpp \
+ css_document_tree.cpp css_selector.cpp detection_result.hpp \
+ detection_result.cpp dom_tree.cpp format_detection.cpp \
+ formula_result.hpp formula_result.cpp impl_utils.hpp info.cpp \
+ interface.cpp json_document_tree.cpp json_map_tree.hpp \
+ json_map_tree.cpp json_structure_mapper.hpp \
+ json_structure_mapper.cpp json_structure_tree.cpp \
+ json_util.hpp json_util.cpp spreadsheet_interface.cpp \
+ orcus_csv.cpp orcus_json.cpp orcus_xml.cpp orcus_xml_impl.hpp \
+ orcus_xml_impl.cpp orcus_xml_map_def.cpp measurement.cpp \
+ number_utils.cpp number_utils.hpp xml_context_base.hpp \
+ xml_context_base.cpp xml_context_global.hpp \
+ xml_context_global.cpp xml_element_types.cpp \
+ xml_element_validator.hpp xml_element_validator.cpp \
+ xml_empty_context.hpp xml_empty_context.cpp xml_map_tree.hpp \
+ xml_map_tree.cpp xml_stream_handler.hpp xml_stream_handler.cpp \
+ xml_stream_parser.hpp xml_stream_parser.cpp \
+ xml_simple_stream_handler.hpp xml_simple_stream_handler.cpp \
+ xml_structure_mapper.hpp xml_structure_mapper.cpp \
+ xml_structure_tree.cpp xml_util.hpp xml_util.cpp \
+ xpath_parser.cpp yaml_document_tree.cpp \
+ ooxml_namespace_types.cpp ooxml_namespace_types.hpp \
+ odf_namespace_types.hpp odf_namespace_types_hpp.inl \
+ odf_namespace_types.cpp odf_namespace_types_cpp.inl \
+ gnumeric_namespace_types.hpp gnumeric_namespace_types.cpp \
+ xls_xml_namespace_types.hpp xls_xml_namespace_types.cpp \
+ session_context.hpp session_context.cpp \
+ spreadsheet_impl_types.hpp spreadsheet_impl_types.cpp \
+ spreadsheet_types.cpp spreadsheet_iface_util.hpp \
+ spreadsheet_iface_util.cpp string_helper.hpp string_helper.cpp \
+ $(am__append_9) $(am__append_11) $(am__append_12) \
+ $(am__append_15) $(am__append_20)
+
+# xlsx-sheet-context-test
+@WITH_XLSX_FILTER_TRUE@xlsx_sheet_context_test_SOURCES = \
+@WITH_XLSX_FILTER_TRUE@ formula_result.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_global.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_namespace_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_schemas.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_tokens.cpp \
+@WITH_XLSX_FILTER_TRUE@ ooxml_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ session_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ spreadsheet_interface.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_autofilter_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_conditional_format_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_helper.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_session_data.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_sheet_context_test.cpp \
+@WITH_XLSX_FILTER_TRUE@ xlsx_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_context_base.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_context_global.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_element_types.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_element_validator.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_empty_context.cpp \
+@WITH_XLSX_FILTER_TRUE@ xml_util.cpp
+
+@WITH_XLSX_FILTER_TRUE@xlsx_sheet_context_test_LDADD = \
+@WITH_XLSX_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_XLSX_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_XLSX_FILTER_TRUE@ ../test/liborcus-test.a
+
+@WITH_XLSX_FILTER_TRUE@xlsx_sheet_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+@WITH_ODS_FILTER_TRUE@odf_helper_test_SOURCES = \
+@WITH_ODS_FILTER_TRUE@ odf_helper.cpp \
+@WITH_ODS_FILTER_TRUE@ string_helper.cpp \
+@WITH_ODS_FILTER_TRUE@ odf_helper_test.cpp
+
+@WITH_ODS_FILTER_TRUE@odf_helper_test_LDADD = \
+@WITH_ODS_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_ODS_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+@WITH_ODS_FILTER_TRUE@odf_helper_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_cell_context_test_SOURCES = \
+@WITH_GNUMERIC_FILTER_TRUE@ number_utils.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ session_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context_test.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_value_format_parser.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_context_base.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_validator.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_empty_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_util.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_namespace_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ odf_namespace_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ spreadsheet_interface.cpp
+
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_cell_context_test_LDADD = \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../test/liborcus-test.a
+
+@WITH_GNUMERIC_FILTER_TRUE@orcus_gnumeric_cell_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# gnumeric-sheet-context-test
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_sheet_context_test_SOURCES = \
+@WITH_GNUMERIC_FILTER_TRUE@ session_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context_test.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_sheet_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_names_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_cell_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_filter_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_styles_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_value_format_parser.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ number_utils.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_context_base.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_element_validator.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_empty_context.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ xml_util.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_namespace_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ gnumeric_tokens.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ odf_namespace_types.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ spreadsheet_interface.cpp \
+@WITH_GNUMERIC_FILTER_TRUE@ string_helper.cpp
+
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_sheet_context_test_LDADD = \
+@WITH_GNUMERIC_FILTER_TRUE@ liborcus-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+@WITH_GNUMERIC_FILTER_TRUE@ ../test/liborcus-test.a
+
+@WITH_GNUMERIC_FILTER_TRUE@gnumeric_sheet_context_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# css-document-tree-test
+css_document_tree_test_SOURCES = \
+ css_document_tree.cpp \
+ css_document_tree_test.cpp
+
+css_document_tree_test_LDADD = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(am__append_24) $(am__append_25)
+
+# json-document-tree-test
+json_document_tree_test_SOURCES = \
+ json_document_tree.cpp \
+ json_util.cpp \
+ json_document_tree_test.cpp
+
+json_document_tree_test_LDADD = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a $(BOOST_SYSTEM_LIBS) $(am__append_26) \
+ $(am__append_27)
+json_document_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# yaml-document-tree-test
+yaml_document_tree_test_SOURCES = \
+ yaml_document_tree.cpp \
+ json_util.cpp \
+ yaml_document_tree_test.cpp
+
+yaml_document_tree_test_LDADD = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(am__append_28) $(am__append_29)
+yaml_document_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+
+# xml-map-tree-test
+xml_map_tree_test_SOURCES = \
+ xml_map_tree.cpp \
+ xml_map_tree.hpp \
+ xpath_parser.hpp \
+ xpath_parser.cpp \
+ spreadsheet_impl_types.hpp \
+ spreadsheet_impl_types.cpp \
+ xml_map_tree_test.cpp
+
+xml_map_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ ../test/liborcus-test.a \
+ $(BOOST_SYSTEM_LIBS)
+
+
+# xml-structure-tree-test
+xml_structure_tree_test_SOURCES = \
+ string_helper.cpp \
+ xml_structure_tree.cpp \
+ xml_structure_mapper.cpp \
+ xml_structure_tree_test.cpp
+
+xml_structure_tree_test_CPPFLAGS = -I$(top_builddir)/lib/liborcus/liborcus.la $(AM_CPPFLAGS)
+xml_structure_tree_test_LDADD = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(am__append_30) $(am__append_31)
+
+# common-test
+common_test_SOURCES = \
+ common_test.cpp
+
+common_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+
+# dom-tree-test
+dom_tree_test_SOURCES = dom_tree_test.cpp
+dom_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la
+
+
+# json-structure-tree-test
+json_structure_tree_test_SOURCES = json_structure_tree_test.cpp
+json_structure_tree_test_LDADD = liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS) $(am__append_32) $(am__append_33)
+
+# json-map-tree-test
+json_map_tree_test_SOURCES = json_map_tree_test.cpp \
+ json_map_tree.cpp \
+ spreadsheet_impl_types.cpp
+
+json_map_tree_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+
+# xpath-parser-test
+xpath_parser_test_SOURCES = \
+ xpath_parser_test.cpp \
+ xpath_parser.cpp
+
+xpath_parser_test_LDADD = \
+ liborcus-@ORCUS_API_VERSION@.la \
+ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \
+ $(BOOST_SYSTEM_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/liborcus/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/liborcus/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+constants.inl: $(top_builddir)/config.status $(srcdir)/constants.inl.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+liborcus-@ORCUS_API_VERSION@.la: $(liborcus_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_@ORCUS_API_VERSION@_la_DEPENDENCIES) $(EXTRA_liborcus_@ORCUS_API_VERSION@_la_DEPENDENCIES)
+ $(AM_V_CXXLD)$(liborcus_@ORCUS_API_VERSION@_la_LINK) -rpath $(libdir) $(liborcus_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_@ORCUS_API_VERSION@_la_LIBADD) $(LIBS)
+
+common-test$(EXEEXT): $(common_test_OBJECTS) $(common_test_DEPENDENCIES) $(EXTRA_common_test_DEPENDENCIES)
+ @rm -f common-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(common_test_OBJECTS) $(common_test_LDADD) $(LIBS)
+
+css-document-tree-test$(EXEEXT): $(css_document_tree_test_OBJECTS) $(css_document_tree_test_DEPENDENCIES) $(EXTRA_css_document_tree_test_DEPENDENCIES)
+ @rm -f css-document-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(css_document_tree_test_OBJECTS) $(css_document_tree_test_LDADD) $(LIBS)
+
+dom-tree-test$(EXEEXT): $(dom_tree_test_OBJECTS) $(dom_tree_test_DEPENDENCIES) $(EXTRA_dom_tree_test_DEPENDENCIES)
+ @rm -f dom-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(dom_tree_test_OBJECTS) $(dom_tree_test_LDADD) $(LIBS)
+
+gnumeric-cell-context-test$(EXEEXT): $(gnumeric_cell_context_test_OBJECTS) $(gnumeric_cell_context_test_DEPENDENCIES) $(EXTRA_gnumeric_cell_context_test_DEPENDENCIES)
+ @rm -f gnumeric-cell-context-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(gnumeric_cell_context_test_OBJECTS) $(gnumeric_cell_context_test_LDADD) $(LIBS)
+
+gnumeric-sheet-context-test$(EXEEXT): $(gnumeric_sheet_context_test_OBJECTS) $(gnumeric_sheet_context_test_DEPENDENCIES) $(EXTRA_gnumeric_sheet_context_test_DEPENDENCIES)
+ @rm -f gnumeric-sheet-context-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(gnumeric_sheet_context_test_OBJECTS) $(gnumeric_sheet_context_test_LDADD) $(LIBS)
+
+json-document-tree-test$(EXEEXT): $(json_document_tree_test_OBJECTS) $(json_document_tree_test_DEPENDENCIES) $(EXTRA_json_document_tree_test_DEPENDENCIES)
+ @rm -f json-document-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(json_document_tree_test_OBJECTS) $(json_document_tree_test_LDADD) $(LIBS)
+
+json-map-tree-test$(EXEEXT): $(json_map_tree_test_OBJECTS) $(json_map_tree_test_DEPENDENCIES) $(EXTRA_json_map_tree_test_DEPENDENCIES)
+ @rm -f json-map-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(json_map_tree_test_OBJECTS) $(json_map_tree_test_LDADD) $(LIBS)
+
+json-structure-tree-test$(EXEEXT): $(json_structure_tree_test_OBJECTS) $(json_structure_tree_test_DEPENDENCIES) $(EXTRA_json_structure_tree_test_DEPENDENCIES)
+ @rm -f json-structure-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(json_structure_tree_test_OBJECTS) $(json_structure_tree_test_LDADD) $(LIBS)
+
+odf-helper-test$(EXEEXT): $(odf_helper_test_OBJECTS) $(odf_helper_test_DEPENDENCIES) $(EXTRA_odf_helper_test_DEPENDENCIES)
+ @rm -f odf-helper-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(odf_helper_test_OBJECTS) $(odf_helper_test_LDADD) $(LIBS)
+
+xlsx-sheet-context-test$(EXEEXT): $(xlsx_sheet_context_test_OBJECTS) $(xlsx_sheet_context_test_DEPENDENCIES) $(EXTRA_xlsx_sheet_context_test_DEPENDENCIES)
+ @rm -f xlsx-sheet-context-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(xlsx_sheet_context_test_OBJECTS) $(xlsx_sheet_context_test_LDADD) $(LIBS)
+
+xml-map-tree-test$(EXEEXT): $(xml_map_tree_test_OBJECTS) $(xml_map_tree_test_DEPENDENCIES) $(EXTRA_xml_map_tree_test_DEPENDENCIES)
+ @rm -f xml-map-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(xml_map_tree_test_OBJECTS) $(xml_map_tree_test_LDADD) $(LIBS)
+
+xml-structure-tree-test$(EXEEXT): $(xml_structure_tree_test_OBJECTS) $(xml_structure_tree_test_DEPENDENCIES) $(EXTRA_xml_structure_tree_test_DEPENDENCIES)
+ @rm -f xml-structure-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(xml_structure_tree_test_OBJECTS) $(xml_structure_tree_test_LDADD) $(LIBS)
+
+xpath-parser-test$(EXEEXT): $(xpath_parser_test_OBJECTS) $(xpath_parser_test_DEPENDENCIES) $(EXTRA_xpath_parser_test_DEPENDENCIES)
+ @rm -f xpath-parser-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(xpath_parser_test_OBJECTS) $(xpath_parser_test_LDADD) $(LIBS)
+
+yaml-document-tree-test$(EXEEXT): $(yaml_document_tree_test_OBJECTS) $(yaml_document_tree_test_DEPENDENCIES) $(EXTRA_yaml_document_tree_test_DEPENDENCIES)
+ @rm -f yaml-document-tree-test$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(yaml_document_tree_test_OBJECTS) $(yaml_document_tree_test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/css_document_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/css_document_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dom_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_cell_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_cell_context_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_namespace_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-session_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_tokens.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnumeric_value_format_parser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_document_tree_test-json_document_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_document_tree_test-json_document_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_document_tree_test-json_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_map_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_map_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_structure_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/number_utils.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odf_helper_test-odf_helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odf_helper_test-odf_helper_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odf_helper_test-string_helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odf_namespace_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spreadsheet_impl_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spreadsheet_interface.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-formula_result.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-session_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xlsx_sheet_context_test-xml_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_context_base.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_element_types.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_element_validator.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_empty_context.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_map_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_map_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_structure_tree_test-string_helper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath_parser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xpath_parser_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yaml_document_tree_test-json_util.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+liborcus_@ORCUS_API_VERSION@_la-config.lo: config.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-config.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-config.lo `test -f 'config.cpp' || echo '$(srcdir)/'`config.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='config.cpp' object='liborcus_@ORCUS_API_VERSION@_la-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-config.lo `test -f 'config.cpp' || echo '$(srcdir)/'`config.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo: css_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo `test -f 'css_document_tree.cpp' || echo '$(srcdir)/'`css_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='css_document_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-css_document_tree.lo `test -f 'css_document_tree.cpp' || echo '$(srcdir)/'`css_document_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-css_selector.lo: css_selector.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-css_selector.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-css_selector.lo `test -f 'css_selector.cpp' || echo '$(srcdir)/'`css_selector.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='css_selector.cpp' object='liborcus_@ORCUS_API_VERSION@_la-css_selector.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-css_selector.lo `test -f 'css_selector.cpp' || echo '$(srcdir)/'`css_selector.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-detection_result.lo: detection_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-detection_result.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-detection_result.lo `test -f 'detection_result.cpp' || echo '$(srcdir)/'`detection_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='detection_result.cpp' object='liborcus_@ORCUS_API_VERSION@_la-detection_result.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-detection_result.lo `test -f 'detection_result.cpp' || echo '$(srcdir)/'`detection_result.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo: dom_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo `test -f 'dom_tree.cpp' || echo '$(srcdir)/'`dom_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dom_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-dom_tree.lo `test -f 'dom_tree.cpp' || echo '$(srcdir)/'`dom_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-format_detection.lo: format_detection.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-format_detection.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-format_detection.lo `test -f 'format_detection.cpp' || echo '$(srcdir)/'`format_detection.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='format_detection.cpp' object='liborcus_@ORCUS_API_VERSION@_la-format_detection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-format_detection.lo `test -f 'format_detection.cpp' || echo '$(srcdir)/'`format_detection.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-formula_result.lo: formula_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-formula_result.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-formula_result.lo `test -f 'formula_result.cpp' || echo '$(srcdir)/'`formula_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='formula_result.cpp' object='liborcus_@ORCUS_API_VERSION@_la-formula_result.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-formula_result.lo `test -f 'formula_result.cpp' || echo '$(srcdir)/'`formula_result.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-info.lo: info.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-info.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-info.lo `test -f 'info.cpp' || echo '$(srcdir)/'`info.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='info.cpp' object='liborcus_@ORCUS_API_VERSION@_la-info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-info.lo `test -f 'info.cpp' || echo '$(srcdir)/'`info.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-interface.lo: interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-interface.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-interface.lo `test -f 'interface.cpp' || echo '$(srcdir)/'`interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='interface.cpp' object='liborcus_@ORCUS_API_VERSION@_la-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-interface.lo `test -f 'interface.cpp' || echo '$(srcdir)/'`interface.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo: json_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo `test -f 'json_document_tree.cpp' || echo '$(srcdir)/'`json_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_document_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-json_document_tree.lo `test -f 'json_document_tree.cpp' || echo '$(srcdir)/'`json_document_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo: json_map_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo `test -f 'json_map_tree.cpp' || echo '$(srcdir)/'`json_map_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_map_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-json_map_tree.lo `test -f 'json_map_tree.cpp' || echo '$(srcdir)/'`json_map_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo: json_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo `test -f 'json_structure_mapper.cpp' || echo '$(srcdir)/'`json_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_structure_mapper.cpp' object='liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.lo `test -f 'json_structure_mapper.cpp' || echo '$(srcdir)/'`json_structure_mapper.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo: json_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo `test -f 'json_structure_tree.cpp' || echo '$(srcdir)/'`json_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_structure_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.lo `test -f 'json_structure_tree.cpp' || echo '$(srcdir)/'`json_structure_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-json_util.lo: json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-json_util.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-json_util.lo `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_util.cpp' object='liborcus_@ORCUS_API_VERSION@_la-json_util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-json_util.lo `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo: spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_interface.cpp' object='liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.lo `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo: orcus_csv.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo `test -f 'orcus_csv.cpp' || echo '$(srcdir)/'`orcus_csv.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_csv.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_csv.lo `test -f 'orcus_csv.cpp' || echo '$(srcdir)/'`orcus_csv.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo: orcus_json.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo `test -f 'orcus_json.cpp' || echo '$(srcdir)/'`orcus_json.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_json.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_json.lo `test -f 'orcus_json.cpp' || echo '$(srcdir)/'`orcus_json.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo: orcus_xml.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo `test -f 'orcus_xml.cpp' || echo '$(srcdir)/'`orcus_xml.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_xml.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml.lo `test -f 'orcus_xml.cpp' || echo '$(srcdir)/'`orcus_xml.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo: orcus_xml_impl.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo `test -f 'orcus_xml_impl.cpp' || echo '$(srcdir)/'`orcus_xml_impl.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_xml_impl.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.lo `test -f 'orcus_xml_impl.cpp' || echo '$(srcdir)/'`orcus_xml_impl.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo: orcus_xml_map_def.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo `test -f 'orcus_xml_map_def.cpp' || echo '$(srcdir)/'`orcus_xml_map_def.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_xml_map_def.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.lo `test -f 'orcus_xml_map_def.cpp' || echo '$(srcdir)/'`orcus_xml_map_def.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-measurement.lo: measurement.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-measurement.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-measurement.lo `test -f 'measurement.cpp' || echo '$(srcdir)/'`measurement.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='measurement.cpp' object='liborcus_@ORCUS_API_VERSION@_la-measurement.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-measurement.lo `test -f 'measurement.cpp' || echo '$(srcdir)/'`measurement.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-number_utils.lo: number_utils.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-number_utils.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-number_utils.lo `test -f 'number_utils.cpp' || echo '$(srcdir)/'`number_utils.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='number_utils.cpp' object='liborcus_@ORCUS_API_VERSION@_la-number_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-number_utils.lo `test -f 'number_utils.cpp' || echo '$(srcdir)/'`number_utils.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo: xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_base.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_context_base.lo `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo: xml_context_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo `test -f 'xml_context_global.cpp' || echo '$(srcdir)/'`xml_context_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_global.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_context_global.lo `test -f 'xml_context_global.cpp' || echo '$(srcdir)/'`xml_context_global.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo: xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_element_types.lo `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo: xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_validator.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.lo `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo: xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_empty_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.lo `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo: xml_map_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo `test -f 'xml_map_tree.cpp' || echo '$(srcdir)/'`xml_map_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_map_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.lo `test -f 'xml_map_tree.cpp' || echo '$(srcdir)/'`xml_map_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo: xml_stream_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo `test -f 'xml_stream_handler.cpp' || echo '$(srcdir)/'`xml_stream_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_stream_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.lo `test -f 'xml_stream_handler.cpp' || echo '$(srcdir)/'`xml_stream_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo: xml_stream_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo `test -f 'xml_stream_parser.cpp' || echo '$(srcdir)/'`xml_stream_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_stream_parser.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.lo `test -f 'xml_stream_parser.cpp' || echo '$(srcdir)/'`xml_stream_parser.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo: xml_simple_stream_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo `test -f 'xml_simple_stream_handler.cpp' || echo '$(srcdir)/'`xml_simple_stream_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_simple_stream_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.lo `test -f 'xml_simple_stream_handler.cpp' || echo '$(srcdir)/'`xml_simple_stream_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo: xml_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo `test -f 'xml_structure_mapper.cpp' || echo '$(srcdir)/'`xml_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_mapper.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.lo `test -f 'xml_structure_mapper.cpp' || echo '$(srcdir)/'`xml_structure_mapper.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo: xml_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo `test -f 'xml_structure_tree.cpp' || echo '$(srcdir)/'`xml_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.lo `test -f 'xml_structure_tree.cpp' || echo '$(srcdir)/'`xml_structure_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xml_util.lo: xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xml_util.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xml_util.lo `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_util.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xml_util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xml_util.lo `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo: xpath_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo `test -f 'xpath_parser.cpp' || echo '$(srcdir)/'`xpath_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xpath_parser.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xpath_parser.lo `test -f 'xpath_parser.cpp' || echo '$(srcdir)/'`xpath_parser.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo: yaml_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo `test -f 'yaml_document_tree.cpp' || echo '$(srcdir)/'`yaml_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_document_tree.cpp' object='liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.lo `test -f 'yaml_document_tree.cpp' || echo '$(srcdir)/'`yaml_document_tree.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo: ooxml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo `test -f 'ooxml_namespace_types.cpp' || echo '$(srcdir)/'`ooxml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_namespace_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.lo `test -f 'ooxml_namespace_types.cpp' || echo '$(srcdir)/'`ooxml_namespace_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo: odf_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo `test -f 'odf_namespace_types.cpp' || echo '$(srcdir)/'`odf_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_namespace_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.lo `test -f 'odf_namespace_types.cpp' || echo '$(srcdir)/'`odf_namespace_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo: gnumeric_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo `test -f 'gnumeric_namespace_types.cpp' || echo '$(srcdir)/'`gnumeric_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_namespace_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.lo `test -f 'gnumeric_namespace_types.cpp' || echo '$(srcdir)/'`gnumeric_namespace_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo: xls_xml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo `test -f 'xls_xml_namespace_types.cpp' || echo '$(srcdir)/'`xls_xml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xls_xml_namespace_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.lo `test -f 'xls_xml_namespace_types.cpp' || echo '$(srcdir)/'`xls_xml_namespace_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-session_context.lo: session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-session_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-session_context.lo `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-session_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-session_context.lo `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo: spreadsheet_impl_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo `test -f 'spreadsheet_impl_types.cpp' || echo '$(srcdir)/'`spreadsheet_impl_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_impl_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.lo `test -f 'spreadsheet_impl_types.cpp' || echo '$(srcdir)/'`spreadsheet_impl_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo: spreadsheet_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo `test -f 'spreadsheet_types.cpp' || echo '$(srcdir)/'`spreadsheet_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.lo `test -f 'spreadsheet_types.cpp' || echo '$(srcdir)/'`spreadsheet_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo: spreadsheet_iface_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo `test -f 'spreadsheet_iface_util.cpp' || echo '$(srcdir)/'`spreadsheet_iface_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_iface_util.cpp' object='liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.lo `test -f 'spreadsheet_iface_util.cpp' || echo '$(srcdir)/'`spreadsheet_iface_util.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-string_helper.lo: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-string_helper.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-string_helper.lo `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='liborcus_@ORCUS_API_VERSION@_la-string_helper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-string_helper.lo `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo: ooxml_content_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo `test -f 'ooxml_content_types.cpp' || echo '$(srcdir)/'`ooxml_content_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_content_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.lo `test -f 'ooxml_content_types.cpp' || echo '$(srcdir)/'`ooxml_content_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo: ooxml_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo `test -f 'ooxml_global.cpp' || echo '$(srcdir)/'`ooxml_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_global.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_global.lo `test -f 'ooxml_global.cpp' || echo '$(srcdir)/'`ooxml_global.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo: ooxml_schemas.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo `test -f 'ooxml_schemas.cpp' || echo '$(srcdir)/'`ooxml_schemas.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_schemas.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.lo `test -f 'ooxml_schemas.cpp' || echo '$(srcdir)/'`ooxml_schemas.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo: ooxml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo `test -f 'ooxml_tokens.cpp' || echo '$(srcdir)/'`ooxml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_tokens.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.lo `test -f 'ooxml_tokens.cpp' || echo '$(srcdir)/'`ooxml_tokens.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo: ooxml_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo `test -f 'ooxml_types.cpp' || echo '$(srcdir)/'`ooxml_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ooxml_types.lo `test -f 'ooxml_types.cpp' || echo '$(srcdir)/'`ooxml_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-opc_context.lo: opc_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-opc_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-opc_context.lo `test -f 'opc_context.cpp' || echo '$(srcdir)/'`opc_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='opc_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-opc_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-opc_context.lo `test -f 'opc_context.cpp' || echo '$(srcdir)/'`opc_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo: opc_reader.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo `test -f 'opc_reader.cpp' || echo '$(srcdir)/'`opc_reader.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='opc_reader.cpp' object='liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-opc_reader.lo `test -f 'opc_reader.cpp' || echo '$(srcdir)/'`opc_reader.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo: orcus_xlsx.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo `test -f 'orcus_xlsx.cpp' || echo '$(srcdir)/'`orcus_xlsx.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_xlsx.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.lo `test -f 'orcus_xlsx.cpp' || echo '$(srcdir)/'`orcus_xlsx.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo: orcus_import_xlsx.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo `test -f 'orcus_import_xlsx.cpp' || echo '$(srcdir)/'`orcus_import_xlsx.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_import_xlsx.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.lo `test -f 'orcus_import_xlsx.cpp' || echo '$(srcdir)/'`orcus_import_xlsx.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo: xlsx_shared_strings_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo `test -f 'xlsx_shared_strings_context.cpp' || echo '$(srcdir)/'`xlsx_shared_strings_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_shared_strings_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.lo `test -f 'xlsx_shared_strings_context.cpp' || echo '$(srcdir)/'`xlsx_shared_strings_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo: xlsx_drawing_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo `test -f 'xlsx_drawing_context.cpp' || echo '$(srcdir)/'`xlsx_drawing_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_drawing_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.lo `test -f 'xlsx_drawing_context.cpp' || echo '$(srcdir)/'`xlsx_drawing_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo: xlsx_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo `test -f 'xlsx_handler.cpp' || echo '$(srcdir)/'`xlsx_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.lo `test -f 'xlsx_handler.cpp' || echo '$(srcdir)/'`xlsx_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo: xlsx_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo `test -f 'xlsx_helper.cpp' || echo '$(srcdir)/'`xlsx_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_helper.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.lo `test -f 'xlsx_helper.cpp' || echo '$(srcdir)/'`xlsx_helper.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo: xlsx_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo `test -f 'xlsx_session_data.cpp' || echo '$(srcdir)/'`xlsx_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_session_data.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.lo `test -f 'xlsx_session_data.cpp' || echo '$(srcdir)/'`xlsx_session_data.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo: xlsx_revision_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo `test -f 'xlsx_revision_context.cpp' || echo '$(srcdir)/'`xlsx_revision_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_revision_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.lo `test -f 'xlsx_revision_context.cpp' || echo '$(srcdir)/'`xlsx_revision_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo: xlsx_pivot_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo `test -f 'xlsx_pivot_context.cpp' || echo '$(srcdir)/'`xlsx_pivot_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_pivot_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.lo `test -f 'xlsx_pivot_context.cpp' || echo '$(srcdir)/'`xlsx_pivot_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo: xlsx_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo `test -f 'xlsx_sheet_context.cpp' || echo '$(srcdir)/'`xlsx_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_sheet_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.lo `test -f 'xlsx_sheet_context.cpp' || echo '$(srcdir)/'`xlsx_sheet_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo: xlsx_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo `test -f 'xlsx_styles_context.cpp' || echo '$(srcdir)/'`xlsx_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_styles_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.lo `test -f 'xlsx_styles_context.cpp' || echo '$(srcdir)/'`xlsx_styles_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo: xlsx_conditional_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo `test -f 'xlsx_conditional_format_context.cpp' || echo '$(srcdir)/'`xlsx_conditional_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_conditional_format_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.lo `test -f 'xlsx_conditional_format_context.cpp' || echo '$(srcdir)/'`xlsx_conditional_format_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo: xlsx_table_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo `test -f 'xlsx_table_context.cpp' || echo '$(srcdir)/'`xlsx_table_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_table_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.lo `test -f 'xlsx_table_context.cpp' || echo '$(srcdir)/'`xlsx_table_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo: xlsx_autofilter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo `test -f 'xlsx_autofilter_context.cpp' || echo '$(srcdir)/'`xlsx_autofilter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_autofilter_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.lo `test -f 'xlsx_autofilter_context.cpp' || echo '$(srcdir)/'`xlsx_autofilter_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo: xlsx_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo `test -f 'xlsx_types.cpp' || echo '$(srcdir)/'`xlsx_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_types.lo `test -f 'xlsx_types.cpp' || echo '$(srcdir)/'`xlsx_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo: xlsx_workbook_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo `test -f 'xlsx_workbook_context.cpp' || echo '$(srcdir)/'`xlsx_workbook_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_workbook_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.lo `test -f 'xlsx_workbook_context.cpp' || echo '$(srcdir)/'`xlsx_workbook_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo: xls_xml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo `test -f 'xls_xml_tokens.cpp' || echo '$(srcdir)/'`xls_xml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xls_xml_tokens.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.lo `test -f 'xls_xml_tokens.cpp' || echo '$(srcdir)/'`xls_xml_tokens.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo: orcus_xls_xml.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo `test -f 'orcus_xls_xml.cpp' || echo '$(srcdir)/'`orcus_xls_xml.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_xls_xml.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.lo `test -f 'orcus_xls_xml.cpp' || echo '$(srcdir)/'`orcus_xls_xml.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo: xls_xml_detection_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo `test -f 'xls_xml_detection_handler.cpp' || echo '$(srcdir)/'`xls_xml_detection_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xls_xml_detection_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.lo `test -f 'xls_xml_detection_handler.cpp' || echo '$(srcdir)/'`xls_xml_detection_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo: xls_xml_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo `test -f 'xls_xml_handler.cpp' || echo '$(srcdir)/'`xls_xml_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xls_xml_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.lo `test -f 'xls_xml_handler.cpp' || echo '$(srcdir)/'`xls_xml_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo: xls_xml_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo `test -f 'xls_xml_context.cpp' || echo '$(srcdir)/'`xls_xml_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xls_xml_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.lo `test -f 'xls_xml_context.cpp' || echo '$(srcdir)/'`xls_xml_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo: odf_document_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo `test -f 'odf_document_styles_context.cpp' || echo '$(srcdir)/'`odf_document_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_document_styles_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.lo `test -f 'odf_document_styles_context.cpp' || echo '$(srcdir)/'`odf_document_styles_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo: odf_para_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo `test -f 'odf_para_context.cpp' || echo '$(srcdir)/'`odf_para_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_para_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_para_context.lo `test -f 'odf_para_context.cpp' || echo '$(srcdir)/'`odf_para_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo: odf_styles.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo `test -f 'odf_styles.cpp' || echo '$(srcdir)/'`odf_styles.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_styles.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_styles.lo `test -f 'odf_styles.cpp' || echo '$(srcdir)/'`odf_styles.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo: odf_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo `test -f 'odf_styles_context.cpp' || echo '$(srcdir)/'`odf_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_styles_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.lo `test -f 'odf_styles_context.cpp' || echo '$(srcdir)/'`odf_styles_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo: odf_style_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo `test -f 'odf_style_context.cpp' || echo '$(srcdir)/'`odf_style_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_style_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_style_context.lo `test -f 'odf_style_context.cpp' || echo '$(srcdir)/'`odf_style_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo: odf_number_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo `test -f 'odf_number_format_context.cpp' || echo '$(srcdir)/'`odf_number_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_number_format_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.lo `test -f 'odf_number_format_context.cpp' || echo '$(srcdir)/'`odf_number_format_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo: odf_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo `test -f 'odf_tokens.cpp' || echo '$(srcdir)/'`odf_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_tokens.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_tokens.lo `test -f 'odf_tokens.cpp' || echo '$(srcdir)/'`odf_tokens.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo: ods_content_xml_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo `test -f 'ods_content_xml_context.cpp' || echo '$(srcdir)/'`ods_content_xml_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ods_content_xml_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.lo `test -f 'ods_content_xml_context.cpp' || echo '$(srcdir)/'`ods_content_xml_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo: ods_dde_links_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo `test -f 'ods_dde_links_context.cpp' || echo '$(srcdir)/'`ods_dde_links_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ods_dde_links_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.lo `test -f 'ods_dde_links_context.cpp' || echo '$(srcdir)/'`ods_dde_links_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo: ods_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo `test -f 'ods_session_data.cpp' || echo '$(srcdir)/'`ods_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ods_session_data.cpp' object='liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-ods_session_data.lo `test -f 'ods_session_data.cpp' || echo '$(srcdir)/'`ods_session_data.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo: odf_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo `test -f 'odf_helper.cpp' || echo '$(srcdir)/'`odf_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_helper.cpp' object='liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-odf_helper.lo `test -f 'odf_helper.cpp' || echo '$(srcdir)/'`odf_helper.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo: orcus_ods.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo `test -f 'orcus_ods.cpp' || echo '$(srcdir)/'`orcus_ods.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_ods.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_ods.lo `test -f 'orcus_ods.cpp' || echo '$(srcdir)/'`orcus_ods.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo: orcus_import_ods.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo `test -f 'orcus_import_ods.cpp' || echo '$(srcdir)/'`orcus_import_ods.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_import_ods.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.lo `test -f 'orcus_import_ods.cpp' || echo '$(srcdir)/'`orcus_import_ods.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo: gnumeric_cell_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo `test -f 'gnumeric_cell_context.cpp' || echo '$(srcdir)/'`gnumeric_cell_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_cell_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.lo `test -f 'gnumeric_cell_context.cpp' || echo '$(srcdir)/'`gnumeric_cell_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo: gnumeric_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo `test -f 'gnumeric_context.cpp' || echo '$(srcdir)/'`gnumeric_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.lo `test -f 'gnumeric_context.cpp' || echo '$(srcdir)/'`gnumeric_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo: gnumeric_detection_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo `test -f 'gnumeric_detection_handler.cpp' || echo '$(srcdir)/'`gnumeric_detection_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_detection_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.lo `test -f 'gnumeric_detection_handler.cpp' || echo '$(srcdir)/'`gnumeric_detection_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo: gnumeric_filter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo `test -f 'gnumeric_filter_context.cpp' || echo '$(srcdir)/'`gnumeric_filter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_filter_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.lo `test -f 'gnumeric_filter_context.cpp' || echo '$(srcdir)/'`gnumeric_filter_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo: gnumeric_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo `test -f 'gnumeric_handler.cpp' || echo '$(srcdir)/'`gnumeric_handler.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_handler.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.lo `test -f 'gnumeric_handler.cpp' || echo '$(srcdir)/'`gnumeric_handler.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo: gnumeric_names_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo `test -f 'gnumeric_names_context.cpp' || echo '$(srcdir)/'`gnumeric_names_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_names_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.lo `test -f 'gnumeric_names_context.cpp' || echo '$(srcdir)/'`gnumeric_names_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo: gnumeric_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo `test -f 'gnumeric_sheet_context.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_sheet_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.lo `test -f 'gnumeric_sheet_context.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo: gnumeric_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo `test -f 'gnumeric_styles_context.cpp' || echo '$(srcdir)/'`gnumeric_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_styles_context.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.lo `test -f 'gnumeric_styles_context.cpp' || echo '$(srcdir)/'`gnumeric_styles_context.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo: gnumeric_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo `test -f 'gnumeric_tokens.cpp' || echo '$(srcdir)/'`gnumeric_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_tokens.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.lo `test -f 'gnumeric_tokens.cpp' || echo '$(srcdir)/'`gnumeric_tokens.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo: gnumeric_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo `test -f 'gnumeric_types.cpp' || echo '$(srcdir)/'`gnumeric_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_types.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.lo `test -f 'gnumeric_types.cpp' || echo '$(srcdir)/'`gnumeric_types.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo: gnumeric_value_format_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo `test -f 'gnumeric_value_format_parser.cpp' || echo '$(srcdir)/'`gnumeric_value_format_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_value_format_parser.cpp' object='liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.lo `test -f 'gnumeric_value_format_parser.cpp' || echo '$(srcdir)/'`gnumeric_value_format_parser.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo: orcus_gnumeric.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo `test -f 'orcus_gnumeric.cpp' || echo '$(srcdir)/'`orcus_gnumeric.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_gnumeric.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.lo `test -f 'orcus_gnumeric.cpp' || echo '$(srcdir)/'`orcus_gnumeric.cpp
+
+liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo: orcus_parquet.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -MT liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo -MD -MP -MF $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Tpo -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo `test -f 'orcus_parquet.cpp' || echo '$(srcdir)/'`orcus_parquet.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Tpo $(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='orcus_parquet.cpp' object='liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liborcus_@ORCUS_API_VERSION@_la_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.lo `test -f 'orcus_parquet.cpp' || echo '$(srcdir)/'`orcus_parquet.cpp
+
+gnumeric_sheet_context_test-session_context.o: session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-session_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-session_context.Tpo -c -o gnumeric_sheet_context_test-session_context.o `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-session_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-session_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_context.cpp' object='gnumeric_sheet_context_test-session_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-session_context.o `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+
+gnumeric_sheet_context_test-session_context.obj: session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-session_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-session_context.Tpo -c -o gnumeric_sheet_context_test-session_context.obj `if test -f 'session_context.cpp'; then $(CYGPATH_W) 'session_context.cpp'; else $(CYGPATH_W) '$(srcdir)/session_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-session_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-session_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_context.cpp' object='gnumeric_sheet_context_test-session_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-session_context.obj `if test -f 'session_context.cpp'; then $(CYGPATH_W) 'session_context.cpp'; else $(CYGPATH_W) '$(srcdir)/session_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_sheet_context_test.o: gnumeric_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_sheet_context_test.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Tpo -c -o gnumeric_sheet_context_test-gnumeric_sheet_context_test.o `test -f 'gnumeric_sheet_context_test.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_sheet_context_test.cpp' object='gnumeric_sheet_context_test-gnumeric_sheet_context_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_sheet_context_test.o `test -f 'gnumeric_sheet_context_test.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context_test.cpp
+
+gnumeric_sheet_context_test-gnumeric_sheet_context_test.obj: gnumeric_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_sheet_context_test.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Tpo -c -o gnumeric_sheet_context_test-gnumeric_sheet_context_test.obj `if test -f 'gnumeric_sheet_context_test.cpp'; then $(CYGPATH_W) 'gnumeric_sheet_context_test.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_sheet_context_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_sheet_context_test.cpp' object='gnumeric_sheet_context_test-gnumeric_sheet_context_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_sheet_context_test.obj `if test -f 'gnumeric_sheet_context_test.cpp'; then $(CYGPATH_W) 'gnumeric_sheet_context_test.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_sheet_context_test.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_sheet_context.o: gnumeric_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_sheet_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_sheet_context.o `test -f 'gnumeric_sheet_context.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_sheet_context.cpp' object='gnumeric_sheet_context_test-gnumeric_sheet_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_sheet_context.o `test -f 'gnumeric_sheet_context.cpp' || echo '$(srcdir)/'`gnumeric_sheet_context.cpp
+
+gnumeric_sheet_context_test-gnumeric_sheet_context.obj: gnumeric_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_sheet_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_sheet_context.obj `if test -f 'gnumeric_sheet_context.cpp'; then $(CYGPATH_W) 'gnumeric_sheet_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_sheet_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_sheet_context.cpp' object='gnumeric_sheet_context_test-gnumeric_sheet_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_sheet_context.obj `if test -f 'gnumeric_sheet_context.cpp'; then $(CYGPATH_W) 'gnumeric_sheet_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_sheet_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_names_context.o: gnumeric_names_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_names_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_names_context.o `test -f 'gnumeric_names_context.cpp' || echo '$(srcdir)/'`gnumeric_names_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_names_context.cpp' object='gnumeric_sheet_context_test-gnumeric_names_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_names_context.o `test -f 'gnumeric_names_context.cpp' || echo '$(srcdir)/'`gnumeric_names_context.cpp
+
+gnumeric_sheet_context_test-gnumeric_names_context.obj: gnumeric_names_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_names_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_names_context.obj `if test -f 'gnumeric_names_context.cpp'; then $(CYGPATH_W) 'gnumeric_names_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_names_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_names_context.cpp' object='gnumeric_sheet_context_test-gnumeric_names_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_names_context.obj `if test -f 'gnumeric_names_context.cpp'; then $(CYGPATH_W) 'gnumeric_names_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_names_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_cell_context.o: gnumeric_cell_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_cell_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_cell_context.o `test -f 'gnumeric_cell_context.cpp' || echo '$(srcdir)/'`gnumeric_cell_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_cell_context.cpp' object='gnumeric_sheet_context_test-gnumeric_cell_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_cell_context.o `test -f 'gnumeric_cell_context.cpp' || echo '$(srcdir)/'`gnumeric_cell_context.cpp
+
+gnumeric_sheet_context_test-gnumeric_cell_context.obj: gnumeric_cell_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_cell_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_cell_context.obj `if test -f 'gnumeric_cell_context.cpp'; then $(CYGPATH_W) 'gnumeric_cell_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_cell_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_cell_context.cpp' object='gnumeric_sheet_context_test-gnumeric_cell_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_cell_context.obj `if test -f 'gnumeric_cell_context.cpp'; then $(CYGPATH_W) 'gnumeric_cell_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_cell_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_filter_context.o: gnumeric_filter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_filter_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_filter_context.o `test -f 'gnumeric_filter_context.cpp' || echo '$(srcdir)/'`gnumeric_filter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_filter_context.cpp' object='gnumeric_sheet_context_test-gnumeric_filter_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_filter_context.o `test -f 'gnumeric_filter_context.cpp' || echo '$(srcdir)/'`gnumeric_filter_context.cpp
+
+gnumeric_sheet_context_test-gnumeric_filter_context.obj: gnumeric_filter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_filter_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_filter_context.obj `if test -f 'gnumeric_filter_context.cpp'; then $(CYGPATH_W) 'gnumeric_filter_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_filter_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_filter_context.cpp' object='gnumeric_sheet_context_test-gnumeric_filter_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_filter_context.obj `if test -f 'gnumeric_filter_context.cpp'; then $(CYGPATH_W) 'gnumeric_filter_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_filter_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_styles_context.o: gnumeric_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_styles_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_styles_context.o `test -f 'gnumeric_styles_context.cpp' || echo '$(srcdir)/'`gnumeric_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_styles_context.cpp' object='gnumeric_sheet_context_test-gnumeric_styles_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_styles_context.o `test -f 'gnumeric_styles_context.cpp' || echo '$(srcdir)/'`gnumeric_styles_context.cpp
+
+gnumeric_sheet_context_test-gnumeric_styles_context.obj: gnumeric_styles_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_styles_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Tpo -c -o gnumeric_sheet_context_test-gnumeric_styles_context.obj `if test -f 'gnumeric_styles_context.cpp'; then $(CYGPATH_W) 'gnumeric_styles_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_styles_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_styles_context.cpp' object='gnumeric_sheet_context_test-gnumeric_styles_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_styles_context.obj `if test -f 'gnumeric_styles_context.cpp'; then $(CYGPATH_W) 'gnumeric_styles_context.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_styles_context.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_value_format_parser.o: gnumeric_value_format_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_value_format_parser.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Tpo -c -o gnumeric_sheet_context_test-gnumeric_value_format_parser.o `test -f 'gnumeric_value_format_parser.cpp' || echo '$(srcdir)/'`gnumeric_value_format_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_value_format_parser.cpp' object='gnumeric_sheet_context_test-gnumeric_value_format_parser.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_value_format_parser.o `test -f 'gnumeric_value_format_parser.cpp' || echo '$(srcdir)/'`gnumeric_value_format_parser.cpp
+
+gnumeric_sheet_context_test-gnumeric_value_format_parser.obj: gnumeric_value_format_parser.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_value_format_parser.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Tpo -c -o gnumeric_sheet_context_test-gnumeric_value_format_parser.obj `if test -f 'gnumeric_value_format_parser.cpp'; then $(CYGPATH_W) 'gnumeric_value_format_parser.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_value_format_parser.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_value_format_parser.cpp' object='gnumeric_sheet_context_test-gnumeric_value_format_parser.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_value_format_parser.obj `if test -f 'gnumeric_value_format_parser.cpp'; then $(CYGPATH_W) 'gnumeric_value_format_parser.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_value_format_parser.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_types.o: gnumeric_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_types.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Tpo -c -o gnumeric_sheet_context_test-gnumeric_types.o `test -f 'gnumeric_types.cpp' || echo '$(srcdir)/'`gnumeric_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_types.cpp' object='gnumeric_sheet_context_test-gnumeric_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_types.o `test -f 'gnumeric_types.cpp' || echo '$(srcdir)/'`gnumeric_types.cpp
+
+gnumeric_sheet_context_test-gnumeric_types.obj: gnumeric_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_types.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Tpo -c -o gnumeric_sheet_context_test-gnumeric_types.obj `if test -f 'gnumeric_types.cpp'; then $(CYGPATH_W) 'gnumeric_types.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_types.cpp' object='gnumeric_sheet_context_test-gnumeric_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_types.obj `if test -f 'gnumeric_types.cpp'; then $(CYGPATH_W) 'gnumeric_types.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_types.cpp'; fi`
+
+gnumeric_sheet_context_test-number_utils.o: number_utils.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-number_utils.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Tpo -c -o gnumeric_sheet_context_test-number_utils.o `test -f 'number_utils.cpp' || echo '$(srcdir)/'`number_utils.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Tpo $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='number_utils.cpp' object='gnumeric_sheet_context_test-number_utils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-number_utils.o `test -f 'number_utils.cpp' || echo '$(srcdir)/'`number_utils.cpp
+
+gnumeric_sheet_context_test-number_utils.obj: number_utils.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-number_utils.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Tpo -c -o gnumeric_sheet_context_test-number_utils.obj `if test -f 'number_utils.cpp'; then $(CYGPATH_W) 'number_utils.cpp'; else $(CYGPATH_W) '$(srcdir)/number_utils.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Tpo $(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='number_utils.cpp' object='gnumeric_sheet_context_test-number_utils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-number_utils.obj `if test -f 'number_utils.cpp'; then $(CYGPATH_W) 'number_utils.cpp'; else $(CYGPATH_W) '$(srcdir)/number_utils.cpp'; fi`
+
+gnumeric_sheet_context_test-xml_context_base.o: xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_context_base.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Tpo -c -o gnumeric_sheet_context_test-xml_context_base.o `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_base.cpp' object='gnumeric_sheet_context_test-xml_context_base.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_context_base.o `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+
+gnumeric_sheet_context_test-xml_context_base.obj: xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_context_base.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Tpo -c -o gnumeric_sheet_context_test-xml_context_base.obj `if test -f 'xml_context_base.cpp'; then $(CYGPATH_W) 'xml_context_base.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_base.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_base.cpp' object='gnumeric_sheet_context_test-xml_context_base.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_context_base.obj `if test -f 'xml_context_base.cpp'; then $(CYGPATH_W) 'xml_context_base.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_base.cpp'; fi`
+
+gnumeric_sheet_context_test-xml_element_types.o: xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_element_types.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Tpo -c -o gnumeric_sheet_context_test-xml_element_types.o `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_types.cpp' object='gnumeric_sheet_context_test-xml_element_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_element_types.o `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+
+gnumeric_sheet_context_test-xml_element_types.obj: xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_element_types.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Tpo -c -o gnumeric_sheet_context_test-xml_element_types.obj `if test -f 'xml_element_types.cpp'; then $(CYGPATH_W) 'xml_element_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_types.cpp' object='gnumeric_sheet_context_test-xml_element_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_element_types.obj `if test -f 'xml_element_types.cpp'; then $(CYGPATH_W) 'xml_element_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_types.cpp'; fi`
+
+gnumeric_sheet_context_test-xml_element_validator.o: xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_element_validator.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Tpo -c -o gnumeric_sheet_context_test-xml_element_validator.o `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_validator.cpp' object='gnumeric_sheet_context_test-xml_element_validator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_element_validator.o `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+
+gnumeric_sheet_context_test-xml_element_validator.obj: xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_element_validator.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Tpo -c -o gnumeric_sheet_context_test-xml_element_validator.obj `if test -f 'xml_element_validator.cpp'; then $(CYGPATH_W) 'xml_element_validator.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_validator.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_validator.cpp' object='gnumeric_sheet_context_test-xml_element_validator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_element_validator.obj `if test -f 'xml_element_validator.cpp'; then $(CYGPATH_W) 'xml_element_validator.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_validator.cpp'; fi`
+
+gnumeric_sheet_context_test-xml_empty_context.o: xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_empty_context.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Tpo -c -o gnumeric_sheet_context_test-xml_empty_context.o `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_empty_context.cpp' object='gnumeric_sheet_context_test-xml_empty_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_empty_context.o `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+
+gnumeric_sheet_context_test-xml_empty_context.obj: xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_empty_context.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Tpo -c -o gnumeric_sheet_context_test-xml_empty_context.obj `if test -f 'xml_empty_context.cpp'; then $(CYGPATH_W) 'xml_empty_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_empty_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_empty_context.cpp' object='gnumeric_sheet_context_test-xml_empty_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_empty_context.obj `if test -f 'xml_empty_context.cpp'; then $(CYGPATH_W) 'xml_empty_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_empty_context.cpp'; fi`
+
+gnumeric_sheet_context_test-xml_util.o: xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_util.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Tpo -c -o gnumeric_sheet_context_test-xml_util.o `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_util.cpp' object='gnumeric_sheet_context_test-xml_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_util.o `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+
+gnumeric_sheet_context_test-xml_util.obj: xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-xml_util.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Tpo -c -o gnumeric_sheet_context_test-xml_util.obj `if test -f 'xml_util.cpp'; then $(CYGPATH_W) 'xml_util.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_util.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Tpo $(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_util.cpp' object='gnumeric_sheet_context_test-xml_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-xml_util.obj `if test -f 'xml_util.cpp'; then $(CYGPATH_W) 'xml_util.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_util.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_namespace_types.o: gnumeric_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_namespace_types.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Tpo -c -o gnumeric_sheet_context_test-gnumeric_namespace_types.o `test -f 'gnumeric_namespace_types.cpp' || echo '$(srcdir)/'`gnumeric_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_namespace_types.cpp' object='gnumeric_sheet_context_test-gnumeric_namespace_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_namespace_types.o `test -f 'gnumeric_namespace_types.cpp' || echo '$(srcdir)/'`gnumeric_namespace_types.cpp
+
+gnumeric_sheet_context_test-gnumeric_namespace_types.obj: gnumeric_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_namespace_types.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Tpo -c -o gnumeric_sheet_context_test-gnumeric_namespace_types.obj `if test -f 'gnumeric_namespace_types.cpp'; then $(CYGPATH_W) 'gnumeric_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_namespace_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_namespace_types.cpp' object='gnumeric_sheet_context_test-gnumeric_namespace_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_namespace_types.obj `if test -f 'gnumeric_namespace_types.cpp'; then $(CYGPATH_W) 'gnumeric_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_namespace_types.cpp'; fi`
+
+gnumeric_sheet_context_test-gnumeric_tokens.o: gnumeric_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_tokens.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Tpo -c -o gnumeric_sheet_context_test-gnumeric_tokens.o `test -f 'gnumeric_tokens.cpp' || echo '$(srcdir)/'`gnumeric_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_tokens.cpp' object='gnumeric_sheet_context_test-gnumeric_tokens.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_tokens.o `test -f 'gnumeric_tokens.cpp' || echo '$(srcdir)/'`gnumeric_tokens.cpp
+
+gnumeric_sheet_context_test-gnumeric_tokens.obj: gnumeric_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-gnumeric_tokens.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Tpo -c -o gnumeric_sheet_context_test-gnumeric_tokens.obj `if test -f 'gnumeric_tokens.cpp'; then $(CYGPATH_W) 'gnumeric_tokens.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_tokens.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Tpo $(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='gnumeric_tokens.cpp' object='gnumeric_sheet_context_test-gnumeric_tokens.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-gnumeric_tokens.obj `if test -f 'gnumeric_tokens.cpp'; then $(CYGPATH_W) 'gnumeric_tokens.cpp'; else $(CYGPATH_W) '$(srcdir)/gnumeric_tokens.cpp'; fi`
+
+gnumeric_sheet_context_test-odf_namespace_types.o: odf_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-odf_namespace_types.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Tpo -c -o gnumeric_sheet_context_test-odf_namespace_types.o `test -f 'odf_namespace_types.cpp' || echo '$(srcdir)/'`odf_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_namespace_types.cpp' object='gnumeric_sheet_context_test-odf_namespace_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-odf_namespace_types.o `test -f 'odf_namespace_types.cpp' || echo '$(srcdir)/'`odf_namespace_types.cpp
+
+gnumeric_sheet_context_test-odf_namespace_types.obj: odf_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-odf_namespace_types.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Tpo -c -o gnumeric_sheet_context_test-odf_namespace_types.obj `if test -f 'odf_namespace_types.cpp'; then $(CYGPATH_W) 'odf_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_namespace_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Tpo $(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_namespace_types.cpp' object='gnumeric_sheet_context_test-odf_namespace_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-odf_namespace_types.obj `if test -f 'odf_namespace_types.cpp'; then $(CYGPATH_W) 'odf_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_namespace_types.cpp'; fi`
+
+gnumeric_sheet_context_test-spreadsheet_interface.o: spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-spreadsheet_interface.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Tpo -c -o gnumeric_sheet_context_test-spreadsheet_interface.o `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Tpo $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_interface.cpp' object='gnumeric_sheet_context_test-spreadsheet_interface.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-spreadsheet_interface.o `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+
+gnumeric_sheet_context_test-spreadsheet_interface.obj: spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-spreadsheet_interface.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Tpo -c -o gnumeric_sheet_context_test-spreadsheet_interface.obj `if test -f 'spreadsheet_interface.cpp'; then $(CYGPATH_W) 'spreadsheet_interface.cpp'; else $(CYGPATH_W) '$(srcdir)/spreadsheet_interface.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Tpo $(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_interface.cpp' object='gnumeric_sheet_context_test-spreadsheet_interface.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-spreadsheet_interface.obj `if test -f 'spreadsheet_interface.cpp'; then $(CYGPATH_W) 'spreadsheet_interface.cpp'; else $(CYGPATH_W) '$(srcdir)/spreadsheet_interface.cpp'; fi`
+
+gnumeric_sheet_context_test-string_helper.o: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-string_helper.o -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Tpo -c -o gnumeric_sheet_context_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Tpo $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='gnumeric_sheet_context_test-string_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+
+gnumeric_sheet_context_test-string_helper.obj: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT gnumeric_sheet_context_test-string_helper.obj -MD -MP -MF $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Tpo -c -o gnumeric_sheet_context_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Tpo $(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='gnumeric_sheet_context_test-string_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnumeric_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o gnumeric_sheet_context_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+
+json_document_tree_test-json_document_tree.o: json_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_document_tree.o -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_document_tree.Tpo -c -o json_document_tree_test-json_document_tree.o `test -f 'json_document_tree.cpp' || echo '$(srcdir)/'`json_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_document_tree.Tpo $(DEPDIR)/json_document_tree_test-json_document_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_document_tree.cpp' object='json_document_tree_test-json_document_tree.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_document_tree.o `test -f 'json_document_tree.cpp' || echo '$(srcdir)/'`json_document_tree.cpp
+
+json_document_tree_test-json_document_tree.obj: json_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_document_tree.obj -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_document_tree.Tpo -c -o json_document_tree_test-json_document_tree.obj `if test -f 'json_document_tree.cpp'; then $(CYGPATH_W) 'json_document_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/json_document_tree.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_document_tree.Tpo $(DEPDIR)/json_document_tree_test-json_document_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_document_tree.cpp' object='json_document_tree_test-json_document_tree.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_document_tree.obj `if test -f 'json_document_tree.cpp'; then $(CYGPATH_W) 'json_document_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/json_document_tree.cpp'; fi`
+
+json_document_tree_test-json_util.o: json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_util.o -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_util.Tpo -c -o json_document_tree_test-json_util.o `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_util.Tpo $(DEPDIR)/json_document_tree_test-json_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_util.cpp' object='json_document_tree_test-json_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_util.o `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+
+json_document_tree_test-json_util.obj: json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_util.obj -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_util.Tpo -c -o json_document_tree_test-json_util.obj `if test -f 'json_util.cpp'; then $(CYGPATH_W) 'json_util.cpp'; else $(CYGPATH_W) '$(srcdir)/json_util.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_util.Tpo $(DEPDIR)/json_document_tree_test-json_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_util.cpp' object='json_document_tree_test-json_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_util.obj `if test -f 'json_util.cpp'; then $(CYGPATH_W) 'json_util.cpp'; else $(CYGPATH_W) '$(srcdir)/json_util.cpp'; fi`
+
+json_document_tree_test-json_document_tree_test.o: json_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_document_tree_test.o -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_document_tree_test.Tpo -c -o json_document_tree_test-json_document_tree_test.o `test -f 'json_document_tree_test.cpp' || echo '$(srcdir)/'`json_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_document_tree_test.Tpo $(DEPDIR)/json_document_tree_test-json_document_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_document_tree_test.cpp' object='json_document_tree_test-json_document_tree_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_document_tree_test.o `test -f 'json_document_tree_test.cpp' || echo '$(srcdir)/'`json_document_tree_test.cpp
+
+json_document_tree_test-json_document_tree_test.obj: json_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT json_document_tree_test-json_document_tree_test.obj -MD -MP -MF $(DEPDIR)/json_document_tree_test-json_document_tree_test.Tpo -c -o json_document_tree_test-json_document_tree_test.obj `if test -f 'json_document_tree_test.cpp'; then $(CYGPATH_W) 'json_document_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/json_document_tree_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/json_document_tree_test-json_document_tree_test.Tpo $(DEPDIR)/json_document_tree_test-json_document_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_document_tree_test.cpp' object='json_document_tree_test-json_document_tree_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(json_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o json_document_tree_test-json_document_tree_test.obj `if test -f 'json_document_tree_test.cpp'; then $(CYGPATH_W) 'json_document_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/json_document_tree_test.cpp'; fi`
+
+odf_helper_test-odf_helper.o: odf_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-odf_helper.o -MD -MP -MF $(DEPDIR)/odf_helper_test-odf_helper.Tpo -c -o odf_helper_test-odf_helper.o `test -f 'odf_helper.cpp' || echo '$(srcdir)/'`odf_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-odf_helper.Tpo $(DEPDIR)/odf_helper_test-odf_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_helper.cpp' object='odf_helper_test-odf_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-odf_helper.o `test -f 'odf_helper.cpp' || echo '$(srcdir)/'`odf_helper.cpp
+
+odf_helper_test-odf_helper.obj: odf_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-odf_helper.obj -MD -MP -MF $(DEPDIR)/odf_helper_test-odf_helper.Tpo -c -o odf_helper_test-odf_helper.obj `if test -f 'odf_helper.cpp'; then $(CYGPATH_W) 'odf_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_helper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-odf_helper.Tpo $(DEPDIR)/odf_helper_test-odf_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_helper.cpp' object='odf_helper_test-odf_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-odf_helper.obj `if test -f 'odf_helper.cpp'; then $(CYGPATH_W) 'odf_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_helper.cpp'; fi`
+
+odf_helper_test-string_helper.o: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-string_helper.o -MD -MP -MF $(DEPDIR)/odf_helper_test-string_helper.Tpo -c -o odf_helper_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-string_helper.Tpo $(DEPDIR)/odf_helper_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='odf_helper_test-string_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+
+odf_helper_test-string_helper.obj: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-string_helper.obj -MD -MP -MF $(DEPDIR)/odf_helper_test-string_helper.Tpo -c -o odf_helper_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-string_helper.Tpo $(DEPDIR)/odf_helper_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='odf_helper_test-string_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+
+odf_helper_test-odf_helper_test.o: odf_helper_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-odf_helper_test.o -MD -MP -MF $(DEPDIR)/odf_helper_test-odf_helper_test.Tpo -c -o odf_helper_test-odf_helper_test.o `test -f 'odf_helper_test.cpp' || echo '$(srcdir)/'`odf_helper_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-odf_helper_test.Tpo $(DEPDIR)/odf_helper_test-odf_helper_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_helper_test.cpp' object='odf_helper_test-odf_helper_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-odf_helper_test.o `test -f 'odf_helper_test.cpp' || echo '$(srcdir)/'`odf_helper_test.cpp
+
+odf_helper_test-odf_helper_test.obj: odf_helper_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT odf_helper_test-odf_helper_test.obj -MD -MP -MF $(DEPDIR)/odf_helper_test-odf_helper_test.Tpo -c -o odf_helper_test-odf_helper_test.obj `if test -f 'odf_helper_test.cpp'; then $(CYGPATH_W) 'odf_helper_test.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_helper_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/odf_helper_test-odf_helper_test.Tpo $(DEPDIR)/odf_helper_test-odf_helper_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='odf_helper_test.cpp' object='odf_helper_test-odf_helper_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(odf_helper_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o odf_helper_test-odf_helper_test.obj `if test -f 'odf_helper_test.cpp'; then $(CYGPATH_W) 'odf_helper_test.cpp'; else $(CYGPATH_W) '$(srcdir)/odf_helper_test.cpp'; fi`
+
+xlsx_sheet_context_test-formula_result.o: formula_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-formula_result.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-formula_result.Tpo -c -o xlsx_sheet_context_test-formula_result.o `test -f 'formula_result.cpp' || echo '$(srcdir)/'`formula_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-formula_result.Tpo $(DEPDIR)/xlsx_sheet_context_test-formula_result.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='formula_result.cpp' object='xlsx_sheet_context_test-formula_result.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-formula_result.o `test -f 'formula_result.cpp' || echo '$(srcdir)/'`formula_result.cpp
+
+xlsx_sheet_context_test-formula_result.obj: formula_result.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-formula_result.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-formula_result.Tpo -c -o xlsx_sheet_context_test-formula_result.obj `if test -f 'formula_result.cpp'; then $(CYGPATH_W) 'formula_result.cpp'; else $(CYGPATH_W) '$(srcdir)/formula_result.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-formula_result.Tpo $(DEPDIR)/xlsx_sheet_context_test-formula_result.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='formula_result.cpp' object='xlsx_sheet_context_test-formula_result.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-formula_result.obj `if test -f 'formula_result.cpp'; then $(CYGPATH_W) 'formula_result.cpp'; else $(CYGPATH_W) '$(srcdir)/formula_result.cpp'; fi`
+
+xlsx_sheet_context_test-ooxml_global.o: ooxml_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_global.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Tpo -c -o xlsx_sheet_context_test-ooxml_global.o `test -f 'ooxml_global.cpp' || echo '$(srcdir)/'`ooxml_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_global.cpp' object='xlsx_sheet_context_test-ooxml_global.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_global.o `test -f 'ooxml_global.cpp' || echo '$(srcdir)/'`ooxml_global.cpp
+
+xlsx_sheet_context_test-ooxml_global.obj: ooxml_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_global.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Tpo -c -o xlsx_sheet_context_test-ooxml_global.obj `if test -f 'ooxml_global.cpp'; then $(CYGPATH_W) 'ooxml_global.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_global.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_global.cpp' object='xlsx_sheet_context_test-ooxml_global.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_global.obj `if test -f 'ooxml_global.cpp'; then $(CYGPATH_W) 'ooxml_global.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_global.cpp'; fi`
+
+xlsx_sheet_context_test-ooxml_namespace_types.o: ooxml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_namespace_types.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Tpo -c -o xlsx_sheet_context_test-ooxml_namespace_types.o `test -f 'ooxml_namespace_types.cpp' || echo '$(srcdir)/'`ooxml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_namespace_types.cpp' object='xlsx_sheet_context_test-ooxml_namespace_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_namespace_types.o `test -f 'ooxml_namespace_types.cpp' || echo '$(srcdir)/'`ooxml_namespace_types.cpp
+
+xlsx_sheet_context_test-ooxml_namespace_types.obj: ooxml_namespace_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_namespace_types.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Tpo -c -o xlsx_sheet_context_test-ooxml_namespace_types.obj `if test -f 'ooxml_namespace_types.cpp'; then $(CYGPATH_W) 'ooxml_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_namespace_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_namespace_types.cpp' object='xlsx_sheet_context_test-ooxml_namespace_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_namespace_types.obj `if test -f 'ooxml_namespace_types.cpp'; then $(CYGPATH_W) 'ooxml_namespace_types.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_namespace_types.cpp'; fi`
+
+xlsx_sheet_context_test-ooxml_schemas.o: ooxml_schemas.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_schemas.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Tpo -c -o xlsx_sheet_context_test-ooxml_schemas.o `test -f 'ooxml_schemas.cpp' || echo '$(srcdir)/'`ooxml_schemas.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_schemas.cpp' object='xlsx_sheet_context_test-ooxml_schemas.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_schemas.o `test -f 'ooxml_schemas.cpp' || echo '$(srcdir)/'`ooxml_schemas.cpp
+
+xlsx_sheet_context_test-ooxml_schemas.obj: ooxml_schemas.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_schemas.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Tpo -c -o xlsx_sheet_context_test-ooxml_schemas.obj `if test -f 'ooxml_schemas.cpp'; then $(CYGPATH_W) 'ooxml_schemas.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_schemas.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_schemas.cpp' object='xlsx_sheet_context_test-ooxml_schemas.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_schemas.obj `if test -f 'ooxml_schemas.cpp'; then $(CYGPATH_W) 'ooxml_schemas.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_schemas.cpp'; fi`
+
+xlsx_sheet_context_test-ooxml_tokens.o: ooxml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_tokens.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Tpo -c -o xlsx_sheet_context_test-ooxml_tokens.o `test -f 'ooxml_tokens.cpp' || echo '$(srcdir)/'`ooxml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_tokens.cpp' object='xlsx_sheet_context_test-ooxml_tokens.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_tokens.o `test -f 'ooxml_tokens.cpp' || echo '$(srcdir)/'`ooxml_tokens.cpp
+
+xlsx_sheet_context_test-ooxml_tokens.obj: ooxml_tokens.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_tokens.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Tpo -c -o xlsx_sheet_context_test-ooxml_tokens.obj `if test -f 'ooxml_tokens.cpp'; then $(CYGPATH_W) 'ooxml_tokens.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_tokens.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_tokens.cpp' object='xlsx_sheet_context_test-ooxml_tokens.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_tokens.obj `if test -f 'ooxml_tokens.cpp'; then $(CYGPATH_W) 'ooxml_tokens.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_tokens.cpp'; fi`
+
+xlsx_sheet_context_test-ooxml_types.o: ooxml_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_types.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Tpo -c -o xlsx_sheet_context_test-ooxml_types.o `test -f 'ooxml_types.cpp' || echo '$(srcdir)/'`ooxml_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_types.cpp' object='xlsx_sheet_context_test-ooxml_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_types.o `test -f 'ooxml_types.cpp' || echo '$(srcdir)/'`ooxml_types.cpp
+
+xlsx_sheet_context_test-ooxml_types.obj: ooxml_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-ooxml_types.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Tpo -c -o xlsx_sheet_context_test-ooxml_types.obj `if test -f 'ooxml_types.cpp'; then $(CYGPATH_W) 'ooxml_types.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ooxml_types.cpp' object='xlsx_sheet_context_test-ooxml_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-ooxml_types.obj `if test -f 'ooxml_types.cpp'; then $(CYGPATH_W) 'ooxml_types.cpp'; else $(CYGPATH_W) '$(srcdir)/ooxml_types.cpp'; fi`
+
+xlsx_sheet_context_test-session_context.o: session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-session_context.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-session_context.Tpo -c -o xlsx_sheet_context_test-session_context.o `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-session_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-session_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_context.cpp' object='xlsx_sheet_context_test-session_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-session_context.o `test -f 'session_context.cpp' || echo '$(srcdir)/'`session_context.cpp
+
+xlsx_sheet_context_test-session_context.obj: session_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-session_context.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-session_context.Tpo -c -o xlsx_sheet_context_test-session_context.obj `if test -f 'session_context.cpp'; then $(CYGPATH_W) 'session_context.cpp'; else $(CYGPATH_W) '$(srcdir)/session_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-session_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-session_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='session_context.cpp' object='xlsx_sheet_context_test-session_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-session_context.obj `if test -f 'session_context.cpp'; then $(CYGPATH_W) 'session_context.cpp'; else $(CYGPATH_W) '$(srcdir)/session_context.cpp'; fi`
+
+xlsx_sheet_context_test-spreadsheet_interface.o: spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-spreadsheet_interface.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Tpo -c -o xlsx_sheet_context_test-spreadsheet_interface.o `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Tpo $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_interface.cpp' object='xlsx_sheet_context_test-spreadsheet_interface.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-spreadsheet_interface.o `test -f 'spreadsheet_interface.cpp' || echo '$(srcdir)/'`spreadsheet_interface.cpp
+
+xlsx_sheet_context_test-spreadsheet_interface.obj: spreadsheet_interface.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-spreadsheet_interface.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Tpo -c -o xlsx_sheet_context_test-spreadsheet_interface.obj `if test -f 'spreadsheet_interface.cpp'; then $(CYGPATH_W) 'spreadsheet_interface.cpp'; else $(CYGPATH_W) '$(srcdir)/spreadsheet_interface.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Tpo $(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='spreadsheet_interface.cpp' object='xlsx_sheet_context_test-spreadsheet_interface.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-spreadsheet_interface.obj `if test -f 'spreadsheet_interface.cpp'; then $(CYGPATH_W) 'spreadsheet_interface.cpp'; else $(CYGPATH_W) '$(srcdir)/spreadsheet_interface.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_autofilter_context.o: xlsx_autofilter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_autofilter_context.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Tpo -c -o xlsx_sheet_context_test-xlsx_autofilter_context.o `test -f 'xlsx_autofilter_context.cpp' || echo '$(srcdir)/'`xlsx_autofilter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_autofilter_context.cpp' object='xlsx_sheet_context_test-xlsx_autofilter_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_autofilter_context.o `test -f 'xlsx_autofilter_context.cpp' || echo '$(srcdir)/'`xlsx_autofilter_context.cpp
+
+xlsx_sheet_context_test-xlsx_autofilter_context.obj: xlsx_autofilter_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_autofilter_context.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Tpo -c -o xlsx_sheet_context_test-xlsx_autofilter_context.obj `if test -f 'xlsx_autofilter_context.cpp'; then $(CYGPATH_W) 'xlsx_autofilter_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_autofilter_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_autofilter_context.cpp' object='xlsx_sheet_context_test-xlsx_autofilter_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_autofilter_context.obj `if test -f 'xlsx_autofilter_context.cpp'; then $(CYGPATH_W) 'xlsx_autofilter_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_autofilter_context.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_conditional_format_context.o: xlsx_conditional_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_conditional_format_context.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Tpo -c -o xlsx_sheet_context_test-xlsx_conditional_format_context.o `test -f 'xlsx_conditional_format_context.cpp' || echo '$(srcdir)/'`xlsx_conditional_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_conditional_format_context.cpp' object='xlsx_sheet_context_test-xlsx_conditional_format_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_conditional_format_context.o `test -f 'xlsx_conditional_format_context.cpp' || echo '$(srcdir)/'`xlsx_conditional_format_context.cpp
+
+xlsx_sheet_context_test-xlsx_conditional_format_context.obj: xlsx_conditional_format_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_conditional_format_context.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Tpo -c -o xlsx_sheet_context_test-xlsx_conditional_format_context.obj `if test -f 'xlsx_conditional_format_context.cpp'; then $(CYGPATH_W) 'xlsx_conditional_format_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_conditional_format_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_conditional_format_context.cpp' object='xlsx_sheet_context_test-xlsx_conditional_format_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_conditional_format_context.obj `if test -f 'xlsx_conditional_format_context.cpp'; then $(CYGPATH_W) 'xlsx_conditional_format_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_conditional_format_context.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_helper.o: xlsx_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_helper.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Tpo -c -o xlsx_sheet_context_test-xlsx_helper.o `test -f 'xlsx_helper.cpp' || echo '$(srcdir)/'`xlsx_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_helper.cpp' object='xlsx_sheet_context_test-xlsx_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_helper.o `test -f 'xlsx_helper.cpp' || echo '$(srcdir)/'`xlsx_helper.cpp
+
+xlsx_sheet_context_test-xlsx_helper.obj: xlsx_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_helper.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Tpo -c -o xlsx_sheet_context_test-xlsx_helper.obj `if test -f 'xlsx_helper.cpp'; then $(CYGPATH_W) 'xlsx_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_helper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_helper.cpp' object='xlsx_sheet_context_test-xlsx_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_helper.obj `if test -f 'xlsx_helper.cpp'; then $(CYGPATH_W) 'xlsx_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_helper.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_session_data.o: xlsx_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_session_data.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Tpo -c -o xlsx_sheet_context_test-xlsx_session_data.o `test -f 'xlsx_session_data.cpp' || echo '$(srcdir)/'`xlsx_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_session_data.cpp' object='xlsx_sheet_context_test-xlsx_session_data.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_session_data.o `test -f 'xlsx_session_data.cpp' || echo '$(srcdir)/'`xlsx_session_data.cpp
+
+xlsx_sheet_context_test-xlsx_session_data.obj: xlsx_session_data.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_session_data.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Tpo -c -o xlsx_sheet_context_test-xlsx_session_data.obj `if test -f 'xlsx_session_data.cpp'; then $(CYGPATH_W) 'xlsx_session_data.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_session_data.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_session_data.cpp' object='xlsx_sheet_context_test-xlsx_session_data.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_session_data.obj `if test -f 'xlsx_session_data.cpp'; then $(CYGPATH_W) 'xlsx_session_data.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_session_data.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_sheet_context.o: xlsx_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_sheet_context.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Tpo -c -o xlsx_sheet_context_test-xlsx_sheet_context.o `test -f 'xlsx_sheet_context.cpp' || echo '$(srcdir)/'`xlsx_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_sheet_context.cpp' object='xlsx_sheet_context_test-xlsx_sheet_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_sheet_context.o `test -f 'xlsx_sheet_context.cpp' || echo '$(srcdir)/'`xlsx_sheet_context.cpp
+
+xlsx_sheet_context_test-xlsx_sheet_context.obj: xlsx_sheet_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_sheet_context.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Tpo -c -o xlsx_sheet_context_test-xlsx_sheet_context.obj `if test -f 'xlsx_sheet_context.cpp'; then $(CYGPATH_W) 'xlsx_sheet_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_sheet_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_sheet_context.cpp' object='xlsx_sheet_context_test-xlsx_sheet_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_sheet_context.obj `if test -f 'xlsx_sheet_context.cpp'; then $(CYGPATH_W) 'xlsx_sheet_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_sheet_context.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_sheet_context_test.o: xlsx_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_sheet_context_test.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Tpo -c -o xlsx_sheet_context_test-xlsx_sheet_context_test.o `test -f 'xlsx_sheet_context_test.cpp' || echo '$(srcdir)/'`xlsx_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_sheet_context_test.cpp' object='xlsx_sheet_context_test-xlsx_sheet_context_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_sheet_context_test.o `test -f 'xlsx_sheet_context_test.cpp' || echo '$(srcdir)/'`xlsx_sheet_context_test.cpp
+
+xlsx_sheet_context_test-xlsx_sheet_context_test.obj: xlsx_sheet_context_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_sheet_context_test.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Tpo -c -o xlsx_sheet_context_test-xlsx_sheet_context_test.obj `if test -f 'xlsx_sheet_context_test.cpp'; then $(CYGPATH_W) 'xlsx_sheet_context_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_sheet_context_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_sheet_context_test.cpp' object='xlsx_sheet_context_test-xlsx_sheet_context_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_sheet_context_test.obj `if test -f 'xlsx_sheet_context_test.cpp'; then $(CYGPATH_W) 'xlsx_sheet_context_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_sheet_context_test.cpp'; fi`
+
+xlsx_sheet_context_test-xlsx_types.o: xlsx_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_types.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Tpo -c -o xlsx_sheet_context_test-xlsx_types.o `test -f 'xlsx_types.cpp' || echo '$(srcdir)/'`xlsx_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_types.cpp' object='xlsx_sheet_context_test-xlsx_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_types.o `test -f 'xlsx_types.cpp' || echo '$(srcdir)/'`xlsx_types.cpp
+
+xlsx_sheet_context_test-xlsx_types.obj: xlsx_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xlsx_types.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Tpo -c -o xlsx_sheet_context_test-xlsx_types.obj `if test -f 'xlsx_types.cpp'; then $(CYGPATH_W) 'xlsx_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xlsx_types.cpp' object='xlsx_sheet_context_test-xlsx_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xlsx_types.obj `if test -f 'xlsx_types.cpp'; then $(CYGPATH_W) 'xlsx_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xlsx_types.cpp'; fi`
+
+xlsx_sheet_context_test-xml_context_base.o: xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_context_base.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Tpo -c -o xlsx_sheet_context_test-xml_context_base.o `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_base.cpp' object='xlsx_sheet_context_test-xml_context_base.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_context_base.o `test -f 'xml_context_base.cpp' || echo '$(srcdir)/'`xml_context_base.cpp
+
+xlsx_sheet_context_test-xml_context_base.obj: xml_context_base.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_context_base.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Tpo -c -o xlsx_sheet_context_test-xml_context_base.obj `if test -f 'xml_context_base.cpp'; then $(CYGPATH_W) 'xml_context_base.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_base.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_base.cpp' object='xlsx_sheet_context_test-xml_context_base.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_context_base.obj `if test -f 'xml_context_base.cpp'; then $(CYGPATH_W) 'xml_context_base.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_base.cpp'; fi`
+
+xlsx_sheet_context_test-xml_context_global.o: xml_context_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_context_global.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Tpo -c -o xlsx_sheet_context_test-xml_context_global.o `test -f 'xml_context_global.cpp' || echo '$(srcdir)/'`xml_context_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_global.cpp' object='xlsx_sheet_context_test-xml_context_global.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_context_global.o `test -f 'xml_context_global.cpp' || echo '$(srcdir)/'`xml_context_global.cpp
+
+xlsx_sheet_context_test-xml_context_global.obj: xml_context_global.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_context_global.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Tpo -c -o xlsx_sheet_context_test-xml_context_global.obj `if test -f 'xml_context_global.cpp'; then $(CYGPATH_W) 'xml_context_global.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_global.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_context_global.cpp' object='xlsx_sheet_context_test-xml_context_global.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_context_global.obj `if test -f 'xml_context_global.cpp'; then $(CYGPATH_W) 'xml_context_global.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_context_global.cpp'; fi`
+
+xlsx_sheet_context_test-xml_element_types.o: xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_element_types.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Tpo -c -o xlsx_sheet_context_test-xml_element_types.o `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_types.cpp' object='xlsx_sheet_context_test-xml_element_types.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_element_types.o `test -f 'xml_element_types.cpp' || echo '$(srcdir)/'`xml_element_types.cpp
+
+xlsx_sheet_context_test-xml_element_types.obj: xml_element_types.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_element_types.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Tpo -c -o xlsx_sheet_context_test-xml_element_types.obj `if test -f 'xml_element_types.cpp'; then $(CYGPATH_W) 'xml_element_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_types.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_types.cpp' object='xlsx_sheet_context_test-xml_element_types.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_element_types.obj `if test -f 'xml_element_types.cpp'; then $(CYGPATH_W) 'xml_element_types.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_types.cpp'; fi`
+
+xlsx_sheet_context_test-xml_element_validator.o: xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_element_validator.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Tpo -c -o xlsx_sheet_context_test-xml_element_validator.o `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_validator.cpp' object='xlsx_sheet_context_test-xml_element_validator.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_element_validator.o `test -f 'xml_element_validator.cpp' || echo '$(srcdir)/'`xml_element_validator.cpp
+
+xlsx_sheet_context_test-xml_element_validator.obj: xml_element_validator.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_element_validator.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Tpo -c -o xlsx_sheet_context_test-xml_element_validator.obj `if test -f 'xml_element_validator.cpp'; then $(CYGPATH_W) 'xml_element_validator.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_validator.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_element_validator.cpp' object='xlsx_sheet_context_test-xml_element_validator.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_element_validator.obj `if test -f 'xml_element_validator.cpp'; then $(CYGPATH_W) 'xml_element_validator.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_element_validator.cpp'; fi`
+
+xlsx_sheet_context_test-xml_empty_context.o: xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_empty_context.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Tpo -c -o xlsx_sheet_context_test-xml_empty_context.o `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_empty_context.cpp' object='xlsx_sheet_context_test-xml_empty_context.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_empty_context.o `test -f 'xml_empty_context.cpp' || echo '$(srcdir)/'`xml_empty_context.cpp
+
+xlsx_sheet_context_test-xml_empty_context.obj: xml_empty_context.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_empty_context.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Tpo -c -o xlsx_sheet_context_test-xml_empty_context.obj `if test -f 'xml_empty_context.cpp'; then $(CYGPATH_W) 'xml_empty_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_empty_context.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_empty_context.cpp' object='xlsx_sheet_context_test-xml_empty_context.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_empty_context.obj `if test -f 'xml_empty_context.cpp'; then $(CYGPATH_W) 'xml_empty_context.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_empty_context.cpp'; fi`
+
+xlsx_sheet_context_test-xml_util.o: xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_util.o -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_util.Tpo -c -o xlsx_sheet_context_test-xml_util.o `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_util.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_util.cpp' object='xlsx_sheet_context_test-xml_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_util.o `test -f 'xml_util.cpp' || echo '$(srcdir)/'`xml_util.cpp
+
+xlsx_sheet_context_test-xml_util.obj: xml_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xlsx_sheet_context_test-xml_util.obj -MD -MP -MF $(DEPDIR)/xlsx_sheet_context_test-xml_util.Tpo -c -o xlsx_sheet_context_test-xml_util.obj `if test -f 'xml_util.cpp'; then $(CYGPATH_W) 'xml_util.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_util.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xlsx_sheet_context_test-xml_util.Tpo $(DEPDIR)/xlsx_sheet_context_test-xml_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_util.cpp' object='xlsx_sheet_context_test-xml_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xlsx_sheet_context_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xlsx_sheet_context_test-xml_util.obj `if test -f 'xml_util.cpp'; then $(CYGPATH_W) 'xml_util.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_util.cpp'; fi`
+
+xml_structure_tree_test-string_helper.o: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-string_helper.o -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-string_helper.Tpo -c -o xml_structure_tree_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-string_helper.Tpo $(DEPDIR)/xml_structure_tree_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='xml_structure_tree_test-string_helper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-string_helper.o `test -f 'string_helper.cpp' || echo '$(srcdir)/'`string_helper.cpp
+
+xml_structure_tree_test-string_helper.obj: string_helper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-string_helper.obj -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-string_helper.Tpo -c -o xml_structure_tree_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-string_helper.Tpo $(DEPDIR)/xml_structure_tree_test-string_helper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='string_helper.cpp' object='xml_structure_tree_test-string_helper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-string_helper.obj `if test -f 'string_helper.cpp'; then $(CYGPATH_W) 'string_helper.cpp'; else $(CYGPATH_W) '$(srcdir)/string_helper.cpp'; fi`
+
+xml_structure_tree_test-xml_structure_tree.o: xml_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_tree.o -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Tpo -c -o xml_structure_tree_test-xml_structure_tree.o `test -f 'xml_structure_tree.cpp' || echo '$(srcdir)/'`xml_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_tree.cpp' object='xml_structure_tree_test-xml_structure_tree.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_tree.o `test -f 'xml_structure_tree.cpp' || echo '$(srcdir)/'`xml_structure_tree.cpp
+
+xml_structure_tree_test-xml_structure_tree.obj: xml_structure_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_tree.obj -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Tpo -c -o xml_structure_tree_test-xml_structure_tree.obj `if test -f 'xml_structure_tree.cpp'; then $(CYGPATH_W) 'xml_structure_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_tree.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_tree.cpp' object='xml_structure_tree_test-xml_structure_tree.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_tree.obj `if test -f 'xml_structure_tree.cpp'; then $(CYGPATH_W) 'xml_structure_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_tree.cpp'; fi`
+
+xml_structure_tree_test-xml_structure_mapper.o: xml_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_mapper.o -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Tpo -c -o xml_structure_tree_test-xml_structure_mapper.o `test -f 'xml_structure_mapper.cpp' || echo '$(srcdir)/'`xml_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_mapper.cpp' object='xml_structure_tree_test-xml_structure_mapper.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_mapper.o `test -f 'xml_structure_mapper.cpp' || echo '$(srcdir)/'`xml_structure_mapper.cpp
+
+xml_structure_tree_test-xml_structure_mapper.obj: xml_structure_mapper.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_mapper.obj -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Tpo -c -o xml_structure_tree_test-xml_structure_mapper.obj `if test -f 'xml_structure_mapper.cpp'; then $(CYGPATH_W) 'xml_structure_mapper.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_mapper.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_mapper.cpp' object='xml_structure_tree_test-xml_structure_mapper.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_mapper.obj `if test -f 'xml_structure_mapper.cpp'; then $(CYGPATH_W) 'xml_structure_mapper.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_mapper.cpp'; fi`
+
+xml_structure_tree_test-xml_structure_tree_test.o: xml_structure_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_tree_test.o -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Tpo -c -o xml_structure_tree_test-xml_structure_tree_test.o `test -f 'xml_structure_tree_test.cpp' || echo '$(srcdir)/'`xml_structure_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_tree_test.cpp' object='xml_structure_tree_test-xml_structure_tree_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_tree_test.o `test -f 'xml_structure_tree_test.cpp' || echo '$(srcdir)/'`xml_structure_tree_test.cpp
+
+xml_structure_tree_test-xml_structure_tree_test.obj: xml_structure_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xml_structure_tree_test-xml_structure_tree_test.obj -MD -MP -MF $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Tpo -c -o xml_structure_tree_test-xml_structure_tree_test.obj `if test -f 'xml_structure_tree_test.cpp'; then $(CYGPATH_W) 'xml_structure_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_tree_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Tpo $(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='xml_structure_tree_test.cpp' object='xml_structure_tree_test-xml_structure_tree_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_structure_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o xml_structure_tree_test-xml_structure_tree_test.obj `if test -f 'xml_structure_tree_test.cpp'; then $(CYGPATH_W) 'xml_structure_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/xml_structure_tree_test.cpp'; fi`
+
+yaml_document_tree_test-yaml_document_tree.o: yaml_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-yaml_document_tree.o -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Tpo -c -o yaml_document_tree_test-yaml_document_tree.o `test -f 'yaml_document_tree.cpp' || echo '$(srcdir)/'`yaml_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Tpo $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_document_tree.cpp' object='yaml_document_tree_test-yaml_document_tree.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-yaml_document_tree.o `test -f 'yaml_document_tree.cpp' || echo '$(srcdir)/'`yaml_document_tree.cpp
+
+yaml_document_tree_test-yaml_document_tree.obj: yaml_document_tree.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-yaml_document_tree.obj -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Tpo -c -o yaml_document_tree_test-yaml_document_tree.obj `if test -f 'yaml_document_tree.cpp'; then $(CYGPATH_W) 'yaml_document_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_document_tree.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Tpo $(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_document_tree.cpp' object='yaml_document_tree_test-yaml_document_tree.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-yaml_document_tree.obj `if test -f 'yaml_document_tree.cpp'; then $(CYGPATH_W) 'yaml_document_tree.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_document_tree.cpp'; fi`
+
+yaml_document_tree_test-json_util.o: json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-json_util.o -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-json_util.Tpo -c -o yaml_document_tree_test-json_util.o `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-json_util.Tpo $(DEPDIR)/yaml_document_tree_test-json_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_util.cpp' object='yaml_document_tree_test-json_util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-json_util.o `test -f 'json_util.cpp' || echo '$(srcdir)/'`json_util.cpp
+
+yaml_document_tree_test-json_util.obj: json_util.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-json_util.obj -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-json_util.Tpo -c -o yaml_document_tree_test-json_util.obj `if test -f 'json_util.cpp'; then $(CYGPATH_W) 'json_util.cpp'; else $(CYGPATH_W) '$(srcdir)/json_util.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-json_util.Tpo $(DEPDIR)/yaml_document_tree_test-json_util.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_util.cpp' object='yaml_document_tree_test-json_util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-json_util.obj `if test -f 'json_util.cpp'; then $(CYGPATH_W) 'json_util.cpp'; else $(CYGPATH_W) '$(srcdir)/json_util.cpp'; fi`
+
+yaml_document_tree_test-yaml_document_tree_test.o: yaml_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-yaml_document_tree_test.o -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Tpo -c -o yaml_document_tree_test-yaml_document_tree_test.o `test -f 'yaml_document_tree_test.cpp' || echo '$(srcdir)/'`yaml_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Tpo $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_document_tree_test.cpp' object='yaml_document_tree_test-yaml_document_tree_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-yaml_document_tree_test.o `test -f 'yaml_document_tree_test.cpp' || echo '$(srcdir)/'`yaml_document_tree_test.cpp
+
+yaml_document_tree_test-yaml_document_tree_test.obj: yaml_document_tree_test.cpp
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT yaml_document_tree_test-yaml_document_tree_test.obj -MD -MP -MF $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Tpo -c -o yaml_document_tree_test-yaml_document_tree_test.obj `if test -f 'yaml_document_tree_test.cpp'; then $(CYGPATH_W) 'yaml_document_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_document_tree_test.cpp'; fi`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Tpo $(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='yaml_document_tree_test.cpp' object='yaml_document_tree_test-yaml_document_tree_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(yaml_document_tree_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o yaml_document_tree_test-yaml_document_tree_test.obj `if test -f 'yaml_document_tree_test.cpp'; then $(CYGPATH_W) 'yaml_document_tree_test.cpp'; else $(CYGPATH_W) '$(srcdir)/yaml_document_tree_test.cpp'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+check-valgrind-local:
+check-valgrind-memcheck-local:
+check-valgrind-helgrind-local:
+check-valgrind-drd-local:
+check-valgrind-sgcheck-local:
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+xlsx-sheet-context-test.log: xlsx-sheet-context-test$(EXEEXT)
+ @p='xlsx-sheet-context-test$(EXEEXT)'; \
+ b='xlsx-sheet-context-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+odf-helper-test.log: odf-helper-test$(EXEEXT)
+ @p='odf-helper-test$(EXEEXT)'; \
+ b='odf-helper-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+gnumeric-cell-context-test.log: gnumeric-cell-context-test$(EXEEXT)
+ @p='gnumeric-cell-context-test$(EXEEXT)'; \
+ b='gnumeric-cell-context-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+gnumeric-sheet-context-test.log: gnumeric-sheet-context-test$(EXEEXT)
+ @p='gnumeric-sheet-context-test$(EXEEXT)'; \
+ b='gnumeric-sheet-context-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+css-document-tree-test.log: css-document-tree-test$(EXEEXT)
+ @p='css-document-tree-test$(EXEEXT)'; \
+ b='css-document-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+json-document-tree-test.log: json-document-tree-test$(EXEEXT)
+ @p='json-document-tree-test$(EXEEXT)'; \
+ b='json-document-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+yaml-document-tree-test.log: yaml-document-tree-test$(EXEEXT)
+ @p='yaml-document-tree-test$(EXEEXT)'; \
+ b='yaml-document-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xml-map-tree-test.log: xml-map-tree-test$(EXEEXT)
+ @p='xml-map-tree-test$(EXEEXT)'; \
+ b='xml-map-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+common-test.log: common-test$(EXEEXT)
+ @p='common-test$(EXEEXT)'; \
+ b='common-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+dom-tree-test.log: dom-tree-test$(EXEEXT)
+ @p='dom-tree-test$(EXEEXT)'; \
+ b='dom-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+json-structure-tree-test.log: json-structure-tree-test$(EXEEXT)
+ @p='json-structure-tree-test$(EXEEXT)'; \
+ b='json-structure-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+json-map-tree-test.log: json-map-tree-test$(EXEEXT)
+ @p='json-map-tree-test$(EXEEXT)'; \
+ b='json-map-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xml-structure-tree-test.log: xml-structure-tree-test$(EXEEXT)
+ @p='xml-structure-tree-test$(EXEEXT)'; \
+ b='xml-structure-tree-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+xpath-parser-test.log: xpath-parser-test$(EXEEXT)
+ @p='xpath-parser-test$(EXEEXT)'; \
+ b='xpath-parser-test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+install-EXTRAPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+check-valgrind: check-valgrind-am
+
+check-valgrind-am: check-valgrind-local
+
+check-valgrind-drd: check-valgrind-drd-am
+
+check-valgrind-drd-am: check-valgrind-drd-local
+
+check-valgrind-helgrind: check-valgrind-helgrind-am
+
+check-valgrind-helgrind-am: check-valgrind-helgrind-local
+
+check-valgrind-memcheck: check-valgrind-memcheck-am
+
+check-valgrind-memcheck-am: check-valgrind-memcheck-local
+
+check-valgrind-sgcheck: check-valgrind-sgcheck-am
+
+check-valgrind-sgcheck-am: check-valgrind-sgcheck-local
+
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/common_test.Po
+ -rm -f ./$(DEPDIR)/css_document_tree.Po
+ -rm -f ./$(DEPDIR)/css_document_tree_test.Po
+ -rm -f ./$(DEPDIR)/dom_tree_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_cell_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_cell_context_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-session_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po
+ -rm -f ./$(DEPDIR)/gnumeric_tokens.Po
+ -rm -f ./$(DEPDIR)/gnumeric_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_value_format_parser.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_document_tree.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_document_tree_test.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_util.Po
+ -rm -f ./$(DEPDIR)/json_map_tree.Po
+ -rm -f ./$(DEPDIR)/json_map_tree_test.Po
+ -rm -f ./$(DEPDIR)/json_structure_tree_test.Po
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Plo
+ -rm -f ./$(DEPDIR)/number_utils.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-odf_helper.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-odf_helper_test.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/odf_namespace_types.Po
+ -rm -f ./$(DEPDIR)/session_context.Po
+ -rm -f ./$(DEPDIR)/spreadsheet_impl_types.Po
+ -rm -f ./$(DEPDIR)/spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-formula_result.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-session_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_util.Po
+ -rm -f ./$(DEPDIR)/xml_context_base.Po
+ -rm -f ./$(DEPDIR)/xml_element_types.Po
+ -rm -f ./$(DEPDIR)/xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/xml_map_tree.Po
+ -rm -f ./$(DEPDIR)/xml_map_tree_test.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po
+ -rm -f ./$(DEPDIR)/xml_util.Po
+ -rm -f ./$(DEPDIR)/xpath_parser.Po
+ -rm -f ./$(DEPDIR)/xpath_parser_test.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-json_util.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-local distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/common_test.Po
+ -rm -f ./$(DEPDIR)/css_document_tree.Po
+ -rm -f ./$(DEPDIR)/css_document_tree_test.Po
+ -rm -f ./$(DEPDIR)/dom_tree_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_cell_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_cell_context_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_cell_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_filter_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_names_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_sheet_context_test.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_styles_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_tokens.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-gnumeric_value_format_parser.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-number_utils.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-odf_namespace_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-session_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_context_base.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/gnumeric_sheet_context_test-xml_util.Po
+ -rm -f ./$(DEPDIR)/gnumeric_tokens.Po
+ -rm -f ./$(DEPDIR)/gnumeric_types.Po
+ -rm -f ./$(DEPDIR)/gnumeric_value_format_parser.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_document_tree.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_document_tree_test.Po
+ -rm -f ./$(DEPDIR)/json_document_tree_test-json_util.Po
+ -rm -f ./$(DEPDIR)/json_map_tree.Po
+ -rm -f ./$(DEPDIR)/json_map_tree_test.Po
+ -rm -f ./$(DEPDIR)/json_structure_tree_test.Po
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-config.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_document_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-css_selector.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-detection_result.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-dom_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-format_detection.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-formula_result.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_cell_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_detection_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_filter_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_names_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_sheet_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-gnumeric_value_format_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-info.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-interface.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_document_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_map_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_mapper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_structure_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-json_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-measurement.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-number_utils.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_document_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_number_format_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_para_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_style_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-odf_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_content_xml_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_dde_links_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ods_session_data.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_content_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_global.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_schemas.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-ooxml_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-opc_reader.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_csv.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_gnumeric.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_ods.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_import_xlsx.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_json.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_ods.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_parquet.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xls_xml.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xlsx.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_impl.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-orcus_xml_map_def.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-session_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_iface_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_impl_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_interface.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-spreadsheet_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-string_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_detection_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_namespace_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xls_xml_tokens.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_autofilter_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_conditional_format_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_drawing_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_helper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_pivot_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_revision_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_session_data.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_shared_strings_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_sheet_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_styles_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_table_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xlsx_workbook_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_base.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_context_global.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_types.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_element_validator.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_empty_context.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_map_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_simple_stream_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_handler.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_stream_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_mapper.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_structure_tree.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xml_util.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-xpath_parser.Plo
+ -rm -f ./$(DEPDIR)/liborcus_@ORCUS_API_VERSION@_la-yaml_document_tree.Plo
+ -rm -f ./$(DEPDIR)/number_utils.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-odf_helper.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-odf_helper_test.Po
+ -rm -f ./$(DEPDIR)/odf_helper_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/odf_namespace_types.Po
+ -rm -f ./$(DEPDIR)/session_context.Po
+ -rm -f ./$(DEPDIR)/spreadsheet_impl_types.Po
+ -rm -f ./$(DEPDIR)/spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-formula_result.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_global.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_namespace_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_schemas.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_tokens.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-ooxml_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-session_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-spreadsheet_interface.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_autofilter_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_conditional_format_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_helper.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_session_data.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_sheet_context_test.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xlsx_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_base.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_context_global.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_types.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/xlsx_sheet_context_test-xml_util.Po
+ -rm -f ./$(DEPDIR)/xml_context_base.Po
+ -rm -f ./$(DEPDIR)/xml_element_types.Po
+ -rm -f ./$(DEPDIR)/xml_element_validator.Po
+ -rm -f ./$(DEPDIR)/xml_empty_context.Po
+ -rm -f ./$(DEPDIR)/xml_map_tree.Po
+ -rm -f ./$(DEPDIR)/xml_map_tree_test.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-string_helper.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_mapper.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree.Po
+ -rm -f ./$(DEPDIR)/xml_structure_tree_test-xml_structure_tree_test.Po
+ -rm -f ./$(DEPDIR)/xml_util.Po
+ -rm -f ./$(DEPDIR)/xpath_parser.Po
+ -rm -f ./$(DEPDIR)/xpath_parser_test.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-json_util.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree.Po
+ -rm -f ./$(DEPDIR)/yaml_document_tree_test-yaml_document_tree_test.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am check-valgrind-am check-valgrind-drd-am \
+ check-valgrind-drd-local check-valgrind-helgrind-am \
+ check-valgrind-helgrind-local check-valgrind-local \
+ check-valgrind-memcheck-am check-valgrind-memcheck-local \
+ check-valgrind-sgcheck-am check-valgrind-sgcheck-local clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-local distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-libLTLIBRARIES \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \
+ uninstall uninstall-am uninstall-libLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+distclean-local:
+ rm -rf $(TESTS)
+
+@VALGRIND_CHECK_RULES@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/liborcus/common_test.cpp b/src/liborcus/common_test.cpp
new file mode 100644
index 0000000..8e4f4c7
--- /dev/null
+++ b/src/liborcus/common_test.cpp
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/measurement.hpp>
+#include <orcus/spreadsheet/types.hpp>
+
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <cmath>
+
+using namespace std;
+using namespace orcus;
+
+void test_date_time_conversion()
+{
+ struct {
+ const char* str;
+ int year;
+ int month;
+ int day;
+ int hour;
+ int minute;
+ double second;
+ } tests[] = {
+ { "2011-02-12", 2011, 2, 12, 0, 0, 0.0 },
+ { "1934-12-23T21:34:56.69", 1934, 12, 23, 21, 34, 56.69 },
+ };
+
+ for (size_t i = 0, n = sizeof(tests)/sizeof(tests[0]); i < n; ++i)
+ {
+ std::string_view str(tests[i].str);
+ date_time_t ret = date_time_t::from_chars(str);
+ cout << "original: " << str << endl;
+ cout << "converted: year=" << ret.year << ", month=" << ret.month << ", day="
+ << ret.day << ", hour=" << ret.hour << ", minute=" << ret.minute << ", second=" << ret.second << endl;
+ assert(ret.year == tests[i].year);
+ assert(ret.month == tests[i].month);
+ assert(ret.day == tests[i].day);
+ assert(ret.hour == tests[i].hour);
+ assert(ret.minute == tests[i].minute);
+ assert(ret.second == tests[i].second);
+ }
+}
+
+string to_string(length_unit_t unit)
+{
+ switch (unit)
+ {
+ case length_unit_t::centimeter:
+ return "centimeter";
+ case length_unit_t::inch:
+ return "inch";
+ case length_unit_t::point:
+ return "point";
+ case length_unit_t::twip:
+ return "twip";
+ case length_unit_t::unknown:
+ default:
+ ;
+ }
+ return "unknown";
+}
+
+void test_measurement_conversion()
+{
+ struct {
+ const char* str;
+ double expected;
+ size_t decimals;
+ length_unit_t unit;
+ } tests[] = {
+ { "12.34", 12.34, 2, length_unit_t::unknown },
+ { "35", 35, 0, length_unit_t::unknown },
+ { "0.69825", 0.69825, 5, length_unit_t::unknown },
+ { ".1592", 0.1592, 4, length_unit_t::unknown },
+ { "5", 5.0, 0, length_unit_t::unknown },
+ { "-3", -3.0, 0, length_unit_t::unknown },
+ { "-3.456", -3.456, 3, length_unit_t::unknown },
+ { "-.987", -0.987, 3, length_unit_t::unknown },
+ { "-100.987.", -100.987, 3, length_unit_t::unknown }, // Second decimal point should stop the parsing.
+
+ { "12.345in", 12.345, 3, length_unit_t::inch },
+ { "120.30001cm", 120.30001, 5, length_unit_t::centimeter },
+ { "3.12mm", 3.12, 2, length_unit_t::millimeter },
+ { "32.681pt", 32.681, 2, length_unit_t::point },
+ { "0.1234px", 0.1234, 4, length_unit_t::pixel },
+ };
+
+ for (size_t i = 0, n = sizeof(tests)/sizeof(tests[0]); i < n; ++i)
+ {
+ length_t ret = to_length(tests[i].str);
+ cout << "original: '" << tests[i].str << "', converted: " << ret.value
+ << " (" << to_string(ret.unit) << "), expected: "
+ << tests[i].expected << " (" << to_string(tests[i].unit) << ")" << endl;
+
+ // Check for double-precision equality without the rounding error.
+ double factor = 1.0;
+ for (size_t j = 0; j < tests[i].decimals; ++j)
+ factor *= 10.0;
+
+ double converted = round(ret.value * factor);
+ double expected = round(tests[i].expected * factor);
+ assert(converted == expected);
+
+ assert(ret.unit == tests[i].unit);
+ }
+}
+
+void test_measurement_conversion_2()
+{
+ struct check
+ {
+ length_unit_t from;
+ length_unit_t to;
+ double original;
+ double expected;
+ };
+
+ std::vector<check> checks =
+ {
+ { length_unit_t::millimeter, length_unit_t::twip, 254.0, 14400.0 },
+ };
+
+ for (const check& c : checks)
+ {
+ // without volatile, sometimes the following assert evaluates to false on 32-bit debian platforms.
+ volatile double observed = convert(c.original, c.from, c.to);
+ assert(observed == c.expected);
+ }
+}
+
+void test_string2number_conversion()
+{
+ struct {
+ const char* str;
+ double expected;
+ size_t decimals;
+ size_t end_pos;
+ } tests[] = {
+ { "1.2", 1.2, 1, 3 },
+ { "1.2a", 1.2, 1, 3 },
+ { "1.2.", 1.2, 1, 3 },
+ { "1.3456", 1.3456, 4, 6 },
+ { "-10.345", -10.345, 3, 7 },
+ { "-10.345-", -10.345, 3, 7 },
+ { "1.2E-2", 1.2E-2, 3, 6 },
+ { "1.26E+3", 1.26E+3, 1, 7 },
+ };
+
+ for (size_t i = 0, n = sizeof(tests)/sizeof(tests[0]); i < n; ++i)
+ {
+ const char* p = tests[i].str;
+ const char* p_parse_ended = nullptr;
+ double converted = to_double(p, &p_parse_ended);
+ cout << "original: '" << tests[i].str << "', converted: " << converted
+ << ", expected: " << tests[i].expected << endl;
+
+ // Check for double-precision equality without the rounding error.
+ double factor = 1.0;
+ for (size_t j = 0; j < tests[i].decimals; ++j)
+ factor *= 10.0;
+
+ converted = round(converted * factor);
+ double expected = round(tests[i].expected * factor);
+ assert(converted == expected);
+
+ // Check the end parse position.
+ const char* pos_expected = p + tests[i].end_pos;
+ assert(pos_expected == p_parse_ended);
+ }
+}
+
+void test_string2long_conversion()
+{
+ struct {
+ const char* str;
+ long expected;
+ size_t end_pos;
+ } tests[] = {
+ { "1", 1, 1 },
+ { "12", 12, 2 },
+ { "13.4", 13, 2 },
+ { "-23", -23, 3 },
+ { "678abc", 678, 3 },
+ };
+
+ for (size_t i = 0, n = sizeof(tests)/sizeof(tests[0]); i < n; ++i)
+ {
+ const char* p = tests[i].str;
+ const char* p_parse_ended = nullptr;
+ long converted = to_long(p, &p_parse_ended);
+ cout << "original: '" << tests[i].str << "', converted: " << converted
+ << ", expected: " << tests[i].expected << endl;
+
+ assert(converted == tests[i].expected);
+
+ // Check the end parse position.
+ const char* pos_expected = p + tests[i].end_pos;
+ assert(pos_expected == p_parse_ended);
+ }
+}
+
+void test_spreadsheet_types()
+{
+ std::vector<spreadsheet::error_value_t> values =
+ {
+ spreadsheet::error_value_t::div0,
+ spreadsheet::error_value_t::na,
+ spreadsheet::error_value_t::name,
+ spreadsheet::error_value_t::null,
+ spreadsheet::error_value_t::num,
+ spreadsheet::error_value_t::ref,
+ spreadsheet::error_value_t::value
+ };
+
+ for (spreadsheet::error_value_t ev : values)
+ {
+ // Round-trip each enum value.
+ std::ostringstream os;
+ os << ev;
+ std::string s = os.str();
+ auto converted = spreadsheet::to_error_value_enum(s);
+ assert(converted == ev);
+ }
+}
+
+int main()
+{
+ test_date_time_conversion();
+ test_measurement_conversion();
+ test_measurement_conversion_2();
+ test_string2number_conversion();
+ test_string2long_conversion();
+ test_spreadsheet_types();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/config.cpp b/src/liborcus/config.cpp
new file mode 100644
index 0000000..9195e02
--- /dev/null
+++ b/src/liborcus/config.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/config.hpp"
+
+namespace orcus {
+
+config::config(format_t input) :
+ input_format(input),
+ debug(false),
+ structure_check(true)
+{
+ // Initialize format-specific config settings below.
+
+ switch (input_format)
+ {
+ case format_t::csv:
+ {
+ csv_config csv;
+ csv.header_row_size = 0;
+ csv.split_to_multiple_sheets = false;
+ data = csv;
+ break;
+ }
+ case format_t::gnumeric:
+ case format_t::ods:
+ case format_t::xls_xml:
+ case format_t::xlsx:
+ case format_t::unknown:
+ default:
+ ;
+ }
+}
+
+json_config::json_config() :
+ output_format(dump_format_t::none),
+ preserve_object_order(true),
+ resolve_references(false),
+ persistent_string_values(true) {}
+
+json_config::~json_config() {}
+
+yaml_config::yaml_config() :
+ output_format(output_format_type::none) {}
+
+yaml_config::~yaml_config() {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/constants.inl.in b/src/liborcus/constants.inl.in
new file mode 100644
index 0000000..da93f77
--- /dev/null
+++ b/src/liborcus/constants.inl.in
@@ -0,0 +1,4 @@
+
+#define ORCUS_MAJOR_VERSION @ORCUS_MAJOR_VERSION@
+#define ORCUS_MINOR_VERSION @ORCUS_MINOR_VERSION@
+#define ORCUS_MICRO_VERSION @ORCUS_MICRO_VERSION@
diff --git a/src/liborcus/css_document_tree.cpp b/src/liborcus/css_document_tree.cpp
new file mode 100644
index 0000000..6960084
--- /dev/null
+++ b/src/liborcus/css_document_tree.cpp
@@ -0,0 +1,647 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/css_document_tree.hpp>
+#include <orcus/css_parser.hpp>
+#include <orcus/string_pool.hpp>
+
+#define ORCUS_DEBUG_CSS_DOCTREE 0
+
+#include <iostream>
+#include <unordered_map>
+#include <map>
+#include <algorithm>
+#include <iterator>
+#include <string_view>
+
+namespace orcus {
+
+namespace {
+
+struct selector_type
+{
+ css_selector_t selector;
+ css::pseudo_element_t pseudo_element;
+};
+
+class parser_handler
+{
+ css_document_tree& m_doc;
+ std::vector<selector_type> m_cur_selector_group;
+ css_properties_t m_cur_properties;
+ std::string_view m_cur_prop_name;
+ std::vector<css_property_value_t> m_cur_prop_values;
+ css_selector_t m_cur_selector; /// current selector
+ css_simple_selector_t m_cur_simple_selector;
+ css::pseudo_element_t m_cur_pseudo_element;
+ css::combinator_t m_cur_combinator;
+ bool m_in_prop:1;
+public:
+ parser_handler(css_document_tree& doc) :
+ m_doc(doc),
+ m_cur_pseudo_element(0),
+ m_cur_combinator(css::combinator_t::descendant),
+ m_in_prop(false) {}
+
+ void at_rule_name(std::string_view name)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "@" << name;
+#else
+ (void)name;
+#endif
+ }
+
+ void simple_selector_type(std::string_view type)
+ {
+ m_cur_simple_selector.name = type;
+ }
+
+ void simple_selector_class(std::string_view cls)
+ {
+ m_cur_simple_selector.classes.insert(cls);
+ }
+
+ void simple_selector_pseudo_element(css::pseudo_element_t pe)
+ {
+ // Only the one applied to the last simple selector is valid.
+ m_cur_pseudo_element |= pe;
+ }
+
+ void simple_selector_pseudo_class(css::pseudo_class_t pc)
+ {
+ m_cur_simple_selector.pseudo_classes |= pc;
+ }
+
+ void simple_selector_id(std::string_view id)
+ {
+ m_cur_simple_selector.id = id;
+ }
+
+ void end_simple_selector()
+ {
+ if (m_cur_selector.first.empty())
+ m_cur_selector.first = m_cur_simple_selector;
+ else
+ {
+ css_chained_simple_selector_t css;
+ css.combinator = m_cur_combinator;
+ css.simple_selector = m_cur_simple_selector;
+ m_cur_selector.chained.push_back(css);
+ }
+
+ m_cur_simple_selector.clear();
+ }
+
+ void end_selector()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << m_cur_selector << "|";
+#endif
+ selector_type sel;
+ sel.selector = m_cur_selector;
+ sel.pseudo_element = m_cur_pseudo_element;
+ m_cur_selector_group.push_back(sel);
+ m_cur_selector.clear();
+ m_cur_pseudo_element = 0;
+ }
+
+ void combinator(css::combinator_t combinator)
+ {
+ m_cur_combinator = combinator;
+ }
+
+ void property_name(std::string_view name)
+ {
+ m_cur_prop_name = name;
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << name << ":";
+#endif
+ }
+
+ void value(std::string_view s)
+ {
+ m_cur_prop_values.push_back(s);
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << " '" << s << "'";
+#endif
+ }
+
+ void rgb(uint8_t red, uint8_t green, uint8_t blue)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << " rgb(" << (int)red << ',' << (int)green << ',' << (int)blue << ')';
+#endif
+ css_property_value_t val;
+ val.type = css::property_value_t::rgb;
+ val.value = css::rgba_color_t{red, green, blue, 0.0};
+ m_cur_prop_values.push_back(val);
+ }
+
+ void rgba(uint8_t red, uint8_t green, uint8_t blue, double alpha)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << " rgba(" << (int)red << ',' << (int)green << ',' << (int)blue << ',' << alpha << ')';
+#endif
+ css_property_value_t val;
+ val.type = css::property_value_t::rgba;
+ val.value = css::rgba_color_t{red, green, blue, alpha};
+ m_cur_prop_values.push_back(val);
+ }
+
+ void hsl(uint8_t hue, uint8_t sat, uint8_t light)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "hsl(" << (int)hue << ',' << (int)sat << ',' << (int)light << ')';
+#endif
+ css_property_value_t val;
+ val.type = css::property_value_t::hsl;
+ val.value = css::hsla_color_t{hue, sat, light, 0.0};
+ m_cur_prop_values.push_back(val);
+ }
+
+ void hsla(uint8_t hue, uint8_t sat, uint8_t light, double alpha)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "hsla(" << (int)hue << ',' << (int)sat << ',' << (int)light << ',' << alpha << ')';
+#endif
+ css_property_value_t val;
+ val.type = css::property_value_t::hsla;
+ val.value = css::hsla_color_t{hue, sat, light, alpha};
+ m_cur_prop_values.push_back(val);
+ }
+
+ void url(std::string_view url)
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << " url(" << url << ")";
+#endif
+ css_property_value_t val;
+ val.type = orcus::css::property_value_t::url;
+ val.value = url;
+ m_cur_prop_values.push_back(val);
+ }
+
+ void begin_parse()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "========" << endl;
+#endif
+ }
+
+ void end_parse()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "========" << endl;
+#endif
+ }
+
+ void begin_block()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << endl << "{" << endl;
+#endif
+ m_in_prop = true;
+ }
+
+ void end_block()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << "}" << endl;
+#endif
+ m_in_prop = false;
+
+ // Push the property set and selector group to the document tree.
+
+ std::vector<selector_type>::iterator it = m_cur_selector_group.begin(), ite = m_cur_selector_group.end();
+ for (; it != ite; ++it)
+ m_doc.insert_properties(it->selector, it->pseudo_element, m_cur_properties);
+
+ m_cur_selector_group.clear();
+ m_cur_properties.clear();
+ }
+
+ void begin_property()
+ {
+#if ORCUS_DEBUG_CSS_DOCTREE
+ if (m_in_prop)
+ cout << " ";
+ cout << "* ";
+#endif
+ }
+
+ void end_property()
+ {
+ m_cur_properties.insert(
+ css_properties_t::value_type(m_cur_prop_name, m_cur_prop_values));
+ m_cur_prop_name = std::string_view{};
+ m_cur_prop_values.clear();
+#if ORCUS_DEBUG_CSS_DOCTREE
+ cout << endl;
+#endif
+ }
+};
+
+struct simple_selector_node;
+
+typedef std::unordered_map<
+ css_simple_selector_t, simple_selector_node, css_simple_selector_t::hash> simple_selectors_type;
+
+typedef std::map<css::combinator_t, simple_selectors_type> combinators_type;
+
+struct simple_selector_node
+{
+ css_pseudo_element_properties_t properties;
+ combinators_type children;
+};
+
+css_simple_selector_t intern(string_pool& sp, const css_simple_selector_t& sel)
+{
+ css_simple_selector_t interned;
+
+ if (!sel.name.empty())
+ interned.name = sp.intern(sel.name).first;
+ if (!sel.id.empty())
+ interned.id = sp.intern(sel.id).first;
+
+ css_simple_selector_t::classes_type::const_iterator it = sel.classes.begin(), ite = sel.classes.end();
+ for (; it != ite; ++it)
+ interned.classes.insert(sp.intern(*it).first);
+
+ interned.pseudo_classes = sel.pseudo_classes;
+
+ return interned;
+}
+
+css_selector_t intern(string_pool& sp, const css_selector_t& sel)
+{
+ css_selector_t interned;
+ interned.first = intern(sp, sel.first);
+
+ css_selector_t::chained_type::const_iterator it = sel.chained.begin(), ite = sel.chained.end();
+ for (; it != ite; ++it)
+ {
+ const css_chained_simple_selector_t& cs = *it;
+ css_chained_simple_selector_t cs_interned;
+ cs_interned.combinator = cs.combinator;
+ cs_interned.simple_selector = intern(sp, cs.simple_selector);
+ interned.chained.push_back(cs_interned);
+ }
+
+ return interned;
+}
+
+class intern_inserter
+{
+ string_pool& m_sp;
+ std::vector<css_property_value_t>& m_dest;
+public:
+ intern_inserter(string_pool& sp, std::vector<css_property_value_t>& dest) :
+ m_sp(sp), m_dest(dest) {}
+
+ void operator() (const css_property_value_t& v) const
+ {
+ switch (v.type)
+ {
+ case css::property_value_t::string:
+ case css::property_value_t::url:
+ {
+ // String value needs interning.
+ css_property_value_t interned = v;
+ auto s = std::get<std::string_view>(v.value);
+ interned.value = m_sp.intern(s).first;
+ m_dest.push_back(interned);
+ break;
+ }
+ default:
+ m_dest.push_back(v);
+ }
+ }
+};
+
+void store_properties(
+ string_pool& sp, css_pseudo_element_properties_t& store,
+ css::pseudo_element_t pseudo_flags, const css_properties_t& props)
+{
+ css_pseudo_element_properties_t::iterator it_store = store.find(pseudo_flags);
+ if (it_store == store.end())
+ {
+ // No storage for this pseudo flag value. Create a new one.
+ std::pair<css_pseudo_element_properties_t::iterator, bool> r =
+ store.insert(
+ css_pseudo_element_properties_t::value_type(
+ pseudo_flags, css_properties_t()));
+ if (!r.second)
+ // insertion failed.
+ return;
+
+ it_store = r.first;
+ }
+
+ css_properties_t& prop_store = it_store->second;
+
+ css_properties_t::const_iterator it = props.begin(), ite = props.end();
+ for (; it != ite; ++it)
+ {
+ std::string_view key = sp.intern(it->first).first;
+ std::vector<css_property_value_t> vals;
+ for_each(it->second.begin(), it->second.end(), intern_inserter(sp, vals));
+ prop_store[key] = vals;
+ }
+}
+
+simple_selector_node* get_or_create_simple_selector_node(
+ simple_selectors_type& store, const css_simple_selector_t& ss)
+{
+ simple_selectors_type::iterator it = store.find(ss);
+ if (it == store.end())
+ {
+ // Insert this root selector.
+ std::pair<simple_selectors_type::iterator, bool> r =
+ store.insert(
+ simple_selectors_type::value_type(
+ ss, simple_selector_node()));
+
+ if (!r.second)
+ // Insertion failed.
+ return nullptr;
+
+ it = r.first;
+ }
+
+ return &it->second;
+}
+
+const simple_selector_node* get_simple_selector_node(
+ const simple_selectors_type& store, const css_simple_selector_t& ss)
+{
+ simple_selectors_type::const_iterator it = store.find(ss);
+ return it == store.end() ? nullptr : &it->second;
+}
+
+simple_selectors_type* get_or_create_simple_selectors_type(
+ combinators_type& store, css::combinator_t combinator)
+{
+ combinators_type::iterator it = store.find(combinator);
+ if (it == store.end())
+ {
+ // Insert new combinator.
+ std::pair<combinators_type::iterator, bool> r =
+ store.insert(
+ combinators_type::value_type(
+ combinator, simple_selectors_type()));
+ if (!r.second)
+ // Insertion failed.
+ return nullptr;
+
+ it = r.first;
+ }
+
+ return &it->second;
+}
+
+const simple_selectors_type* get_simple_selectors_type(
+ const combinators_type& store, css::combinator_t combinator)
+{
+ combinators_type::const_iterator it = store.find(combinator);
+ return it == store.end() ? nullptr : &it->second;
+}
+
+void dump_pseudo_elements(css::pseudo_element_t elem)
+{
+ if (!elem)
+ return;
+
+ if (elem & css::pseudo_element_after)
+ std::cout << "::after";
+ if (elem & css::pseudo_element_before)
+ std::cout << "::before";
+ if (elem & css::pseudo_element_first_letter)
+ std::cout << "::first-letter";
+ if (elem & css::pseudo_element_first_line)
+ std::cout << "::first-line";
+ if (elem & css::pseudo_element_selection)
+ std::cout << "::selection";
+ if (elem & css::pseudo_element_backdrop)
+ std::cout << "::backdrop";
+}
+
+void dump_properties(const css_properties_t& props)
+{
+ std::cout << '{' << std::endl;
+ css_properties_t::const_iterator it = props.begin(), ite = props.end();
+ for (; it != ite; ++it)
+ {
+ std::cout << " * " << it->first << ": ";
+ const std::vector<css_property_value_t>& vals = it->second;
+ std::copy(vals.begin(), vals.end(), std::ostream_iterator<css_property_value_t>(std::cout, " "));
+ std::cout << ';' << std::endl;
+ }
+ std::cout << '}' << std::endl;
+}
+
+void dump_all_properties(const css_selector_t& selector, const css_pseudo_element_properties_t& properties)
+{
+ css_pseudo_element_properties_t::const_iterator it_prop = properties.begin(), ite_prop = properties.end();
+ for (; it_prop != ite_prop; ++it_prop)
+ {
+ const css_properties_t& prop = it_prop->second;
+ if (prop.empty())
+ continue;
+
+ std::cout << selector;
+ dump_pseudo_elements(it_prop->first);
+ std::cout << std::endl;
+ dump_properties(prop);
+ }
+}
+
+void dump_chained_recursive(
+ css_selector_t& selector, css::combinator_t op, const simple_selectors_type& ss)
+{
+ simple_selectors_type::const_iterator it_ss = ss.begin(), ite_ss = ss.end();
+ for (; it_ss != ite_ss; ++it_ss)
+ {
+ css_chained_simple_selector_t chained_ss;
+ chained_ss.combinator = op;
+ chained_ss.simple_selector = it_ss->first;
+ selector.chained.push_back(chained_ss);
+
+ const simple_selector_node& node = it_ss->second;
+ dump_all_properties(selector, node.properties);
+
+ combinators_type::const_iterator it_comb = node.children.begin(), ite_comb = node.children.end();
+ for (; it_comb != ite_comb; ++it_comb)
+ dump_chained_recursive(selector, it_comb->first, it_comb->second);
+
+ selector.chained.pop_back();
+ }
+}
+
+const css_pseudo_element_properties_t* get_properties_map(
+ const simple_selectors_type& root, const css_selector_t& selector)
+{
+ const simple_selector_node* node = get_simple_selector_node(root, selector.first);
+ if (!node)
+ return nullptr;
+
+ if (!selector.chained.empty())
+ {
+ // Follow the chain to find the right node to store new properties.
+ css_selector_t::chained_type::const_iterator it_chain = selector.chained.begin();
+ css_selector_t::chained_type::const_iterator ite_chain = selector.chained.end();
+ const combinators_type* combos = &node->children;
+ for (; it_chain != ite_chain; ++it_chain)
+ {
+ const css_chained_simple_selector_t& css = *it_chain;
+ const simple_selectors_type* ss = get_simple_selectors_type(*combos, css.combinator);
+ if (!ss)
+ return nullptr;
+
+ node = get_simple_selector_node(*ss, css.simple_selector);
+ if (!node)
+ return nullptr;
+
+ combos = &node->children;
+ }
+ }
+
+ assert(node);
+ return &node->properties;
+}
+
+}
+
+css_document_tree::insertion_error::insertion_error(const std::string& msg) :
+ general_error(msg) {}
+
+struct css_document_tree::impl
+{
+ string_pool m_string_pool;
+ simple_selectors_type m_root;
+};
+
+css_document_tree::css_document_tree() : mp_impl(std::make_unique<impl>())
+{
+}
+
+css_document_tree::css_document_tree(css_document_tree&& other) :
+ mp_impl(std::move(other.mp_impl))
+{
+ other.mp_impl = std::make_unique<impl>();
+}
+
+css_document_tree::~css_document_tree() = default;
+
+css_document_tree& css_document_tree::operator=(css_document_tree&& other)
+{
+ css_document_tree tmp(std::move(other));
+ swap(tmp);
+
+ return *this;
+}
+
+void css_document_tree::load(std::string_view stream)
+{
+ if (stream.empty())
+ return;
+
+ parser_handler handler(*this);
+ css_parser<parser_handler> parser(stream, handler);
+ parser.parse();
+}
+
+void css_document_tree::insert_properties(
+ const css_selector_t& selector,
+ css::pseudo_element_t pseudo_elem,
+ const css_properties_t& props)
+{
+ if (props.empty())
+ return;
+
+ css_selector_t selector_interned = intern(mp_impl->m_string_pool, selector);
+
+ // See if the root selector already exists.
+ simple_selector_node* node =
+ get_or_create_simple_selector_node(mp_impl->m_root, selector_interned.first);
+
+ if (!node)
+ throw insertion_error("failed to find or create the root simple selector node.");
+
+ if (!selector_interned.chained.empty())
+ {
+ // Follow the chain to find the right node to store new properties.
+ css_selector_t::chained_type::iterator it_chain = selector_interned.chained.begin();
+ css_selector_t::chained_type::iterator ite_chain = selector_interned.chained.end();
+ combinators_type* combos = &node->children;
+ for (; it_chain != ite_chain; ++it_chain)
+ {
+ css_chained_simple_selector_t& css = *it_chain;
+ simple_selectors_type* ss = get_or_create_simple_selectors_type(*combos, css.combinator);
+ if (!ss)
+ throw insertion_error("failed to find or create the simple selectors type by combinator.");
+
+ node = get_or_create_simple_selector_node(*ss, css.simple_selector);
+ if (!node)
+ throw insertion_error("failed to find or create the simple selector node.");
+
+ combos = &node->children;
+ }
+ }
+
+ // We found the right node to store the properties.
+ assert(node);
+ store_properties(mp_impl->m_string_pool, node->properties, pseudo_elem, props);
+}
+
+const css_properties_t* css_document_tree::get_properties(
+ const css_selector_t& selector, css::pseudo_element_t pseudo_elem) const
+{
+ const css_pseudo_element_properties_t* prop_map = get_properties_map(mp_impl->m_root, selector);
+ if (!prop_map)
+ return nullptr;
+
+ css_pseudo_element_properties_t::const_iterator it = prop_map->find(pseudo_elem);
+ if (it == prop_map->end())
+ return nullptr;
+
+ return &it->second;
+}
+
+const css_pseudo_element_properties_t*
+css_document_tree::get_all_properties(const css_selector_t& selector) const
+{
+ return get_properties_map(mp_impl->m_root, selector);
+}
+
+void css_document_tree::dump() const
+{
+ css_selector_t selector;
+
+ const simple_selectors_type& ss = mp_impl->m_root;
+ simple_selectors_type::const_iterator it_ss = ss.begin(), ite_ss = ss.end();
+ for (; it_ss != ite_ss; ++it_ss)
+ {
+ selector.first = it_ss->first;
+
+ const simple_selector_node& node = it_ss->second;
+ dump_all_properties(selector, node.properties);
+
+ combinators_type::const_iterator it_comb = node.children.begin(), ite_comb = node.children.end();
+ for (; it_comb != ite_comb; ++it_comb)
+ dump_chained_recursive(selector, it_comb->first, it_comb->second);
+ }
+}
+
+void css_document_tree::swap(css_document_tree& other) noexcept
+{
+ mp_impl.swap(other.mp_impl);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/css_document_tree_test.cpp b/src/liborcus/css_document_tree_test.cpp
new file mode 100644
index 0000000..085ae14
--- /dev/null
+++ b/src/liborcus/css_document_tree_test.cpp
@@ -0,0 +1,690 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/css_document_tree.hpp>
+#include <orcus/css_types.hpp>
+#include <orcus/css_parser_base.hpp>
+#include <orcus/stream.hpp>
+
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <iterator>
+
+#include "filesystem_env.hpp"
+
+using namespace orcus;
+
+bool check_prop(const css_properties_t& props, std::string_view key, std::string_view val)
+{
+ css_properties_t::const_iterator it = props.find(key);
+ if (it == props.end())
+ {
+ std::cout << "property '" << key << "' not found" << std::endl;
+ return false;
+ }
+
+ // Chain all property values into a single string delimited by a " ".
+ const std::vector<css_property_value_t>& vals = it->second;
+ std::ostringstream os;
+ if (vals.size() > 1)
+ {
+ auto it_end = vals.end();
+ std::advance(it_end, -1);
+ std::copy(vals.begin(), it_end, std::ostream_iterator<css_property_value_t>(os, " "));
+ }
+ os << vals.back();
+
+ std::string val_stored = os.str();
+ if (val != val_stored)
+ {
+ std::cout << "property '" << key << "' is expected to have value '"
+ << val << "' but '" << val_stored << "' is found." << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+using check_properties_type = std::vector<std::pair<std::string, std::string>>;
+
+bool check_props(const css_properties_t& props, check_properties_type expected)
+{
+ bool pass = true;
+
+ for (const auto& [key, value] : expected)
+ {
+ bool res = check_prop(props, key, value);
+ if (!res)
+ pass = false;
+ }
+
+ return pass;
+}
+
+css_document_tree load_document(const fs::path& path)
+{
+ std::cout << path << std::endl;
+ file_content content(path.string());
+ css_document_tree doc;
+ doc.load(content.str());
+
+ return doc;
+}
+
+void test_css_invalids()
+{
+ // Get all yaml files in this directory.
+ fs::path dirpath(SRCDIR"/test/css/invalids/");
+ fs::directory_iterator it_end;
+
+ size_t file_count = 0;
+
+ for (fs::directory_iterator it(dirpath); it != it_end; ++it)
+ {
+ fs::path path = it->path();
+ if (!fs::is_regular_file(path))
+ continue;
+
+ if (path.extension().string() != ".css")
+ continue;
+
+ std::cout << "parsing invalid file " << path.filename().string() << "..." << std::endl;
+
+ ++file_count;
+
+ file_content content(path.string().data());
+ css_document_tree doc;
+
+ try
+ {
+ doc.load(content.str());
+ assert(!"css::parse_error was not thrown, but expected to be.");
+ }
+ catch (const parse_error&)
+ {
+ // This is expected.
+ }
+ }
+
+ assert(file_count > 0);
+}
+
+void test_css_simple_selector_equality()
+{
+ css_simple_selector_t left;
+ css_simple_selector_t right;
+ assert(left == right);
+
+ left.classes.insert("one");
+ assert(left != right);
+ right.classes.insert("one");
+ assert(left == right);
+
+ left.classes.insert("two");
+ assert(left != right);
+ right.classes.insert("two");
+ assert(left == right);
+
+ left.classes.insert("three");
+ assert(left != right);
+ right.classes.insert("three");
+ assert(left == right);
+}
+
+void test_css_empty()
+{
+ fs::path path = SRCDIR"/test/css/empty.css";
+ std::cout << path << std::endl;
+
+ file_content content(path.string());
+ css_document_tree doc;
+ doc.load(content.str());
+}
+
+void test_css_parse_basic1()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic1.css");
+
+ css_selector_t selector;
+ selector.first.name = "table";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "width", "auto"));
+ assert(check_prop(*props, "height", "500px"));
+
+ selector.first.name = "td";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "color", "gray"));
+ assert(check_prop(*props, "background-color", "yellow"));
+
+ // This selector doesn't exist in the document tree.
+ selector.first.name = "tr";
+ props = doc.get_properties(selector, 0);
+ assert(!props);
+}
+
+void test_css_parse_basic2()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic2.css");
+
+ css_selector_t selector;
+ selector.first.name = "div";
+ selector.first.classes.insert("foo");
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "border", "solid 1px"));
+
+ selector.clear();
+ selector.first.classes.insert("warning");
+
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "background-color", "red"));
+ assert(check_prop(*props, "font-weight", "900"));
+}
+
+void test_css_parse_basic3()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic3.css");
+
+ css_selector_t selector;
+ selector.first.name = "html";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "height", "100%"));
+
+ selector.first.name = "body";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "height", "100%"));
+
+ {
+ // h1, h2, h3 and h4 all have identical set of properties.
+ const char* names[] = { "h1", "h2", "h3", "h4" };
+ std::size_t n = std::size(names);
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ selector.first.name = names[i];
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "font-variant", "small-caps"));
+ assert(check_prop(*props, "padding", "2.5em"));
+ }
+ }
+}
+
+void test_css_parse_basic4()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic4.css");
+
+ css_selector_t selector;
+ selector.first.name = "h1";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "margin", "0.5in"));
+
+ selector.first.name = "h2";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "line-height", "3cm"));
+
+ selector.first.name = "h3";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "word-spacing", "4mm"));
+
+ selector.first.name = "h4";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "font-size", "1pc"));
+
+ selector.first.name = "p";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "font-size", "12px"));
+}
+
+void test_css_parse_basic5()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic5.css");
+
+ css_selector_t selector;
+ selector.first.classes.insert("info");
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "word-spacing", "normal"));
+}
+
+void test_css_parse_basic6()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic6.css");
+
+ css_selector_t selector;
+ selector.first.name = "h1";
+ selector.first.id = "chapter1";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "text-align", "center"));
+
+ selector.first.id = "z98y";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "letter-spacing", "0.5em"));
+
+ selector.clear();
+ selector.first.id = "id_global";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "margin", "10px"));
+}
+
+void test_css_parse_basic7()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic7.css");
+
+ css_selector_t selector;
+ selector.first.classes.insert("one");
+ selector.first.classes.insert("two");
+ selector.first.classes.insert("three");
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "blue"));
+
+ selector.first.classes.clear();
+ selector.first.classes.insert("one");
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "aqua"));
+
+ selector.first.classes.clear();
+ selector.first.classes.insert("two");
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "azure"));
+
+ selector.first.classes.insert("one"); // one two
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "brown"));
+
+ selector.first.clear();
+ selector.first.name = "span";
+ selector.first.classes.insert("button");
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "border", "solid 1px gray"));
+
+ selector.first.classes.insert("selected"); // button selected
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "border", "solid 4px red"));
+}
+
+void test_css_parse_basic8()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic8.css");
+
+ css_selector_t selector;
+ selector.first.classes.insert("ribbon");
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "#5BC8F7"));
+
+ props = doc.get_properties(selector, css::pseudo_element_after);
+ assert(props);
+ assert(props->size() == 4);
+ assert(check_prop(*props, "content", "Look at this orange box."));
+ assert(check_prop(*props, "background-color", "#FFBA10"));
+ assert(check_prop(*props, "border-color", "black"));
+ assert(check_prop(*props, "border-style", "dotted"));
+
+ props = doc.get_properties(selector, css::pseudo_element_before);
+ assert(!props); // it doesn't exist for this pseudo element.
+
+ props = doc.get_properties(
+ selector,
+ css::pseudo_element_after|css::pseudo_element_selection);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "content", "Selected orange box."));
+
+ // Get all properties for all pseudo element flag combos.
+ const css_pseudo_element_properties_t* all_props = doc.get_all_properties(selector);
+ assert(all_props);
+ assert(all_props->size() == 3);
+
+ // Check the properties for no pseudo element flag.
+ css_pseudo_element_properties_t::const_iterator it = all_props->find(0);
+ assert(it != all_props->end());
+ props = &it->second;
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "#5BC8F7"));
+
+ // ::after pseudo element
+ it = all_props->find(css::pseudo_element_after);
+ assert(it != all_props->end());
+ props = &it->second;
+ assert(props->size() == 4);
+ assert(check_prop(*props, "content", "Look at this orange box."));
+ assert(check_prop(*props, "background-color", "#FFBA10"));
+ assert(check_prop(*props, "border-color", "black"));
+ assert(check_prop(*props, "border-style", "dotted"));
+
+ // ::after::selection pseudo element pair.
+ it = all_props->find(css::pseudo_element_after|css::pseudo_element_selection);
+ assert(it != all_props->end());
+ props = &it->second;
+ assert(check_prop(*props, "content", "Selected orange box."));
+}
+
+void test_css_parse_basic9()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic9.css");
+
+ css_selector_t selector;
+ selector.first.name = "a";
+ selector.first.pseudo_classes = css::pseudo_class_link;
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "#FF0000"));
+
+ selector.first.pseudo_classes = css::pseudo_class_visited;
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "#00FF00"));
+
+ selector.first.pseudo_classes = css::pseudo_class_hover;
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "#FF00FF"));
+
+ selector.first.pseudo_classes = css::pseudo_class_active;
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "color", "#0000FF"));
+}
+
+void test_css_parse_basic10()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic10.css");
+
+ css_selector_t selector;
+ selector.first.classes.insert("foo");
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "background-color", "rgb(12,230,222)"));
+ assert(check_prop(*props, "border", "solid 5px rgba(30,12,0,0.79)"));
+}
+
+void test_css_parse_basic11()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic11.css");
+
+ css_selector_t selector;
+ selector.first.classes.insert("callout");
+
+ const css_properties_t* props = doc.get_properties(selector, css::pseudo_element_before);
+ assert(props);
+ assert(props->size() == 5);
+ assert(check_prop(*props, "content", ""));
+ assert(check_prop(*props, "width", "0px"));
+ assert(check_prop(*props, "height", "0px"));
+ assert(check_prop(*props, "border", "0.8em solid transparent"));
+ assert(check_prop(*props, "position", "absolute"));
+}
+
+void test_css_parse_basic12()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic12.css");
+
+ css_selector_t selector;
+ selector.first.name = "div";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-image", "url(https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png)"));
+
+ selector.first.name = "p";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-image", "none"));
+
+ selector.first.name = "div";
+ selector.first.classes.insert("img1");
+
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-image", "url(http://www.rabiakhan.com/Gallery/background.jpg)"));
+
+ selector.first.classes.clear();
+ selector.first.classes.insert("img2");
+
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-image", "url(http://www.tgraphic.com/userimages/Gallery/Backgrounds/TGraphic_com-Full-Wallpapers-Backgrounds_Colorful_C_1920_33.jpg)"));
+}
+
+void test_css_parse_basic13()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic13.css");
+
+ css_selector_t selector;
+ selector.first.id = "p1";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsl(120,100,50)"));
+
+ selector.first.id = "p2";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsl(120,100,75)"));
+
+ selector.first.id = "p3";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsl(120,100,25)"));
+
+ selector.first.id = "p4";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsl(120,60,70)"));
+}
+
+void test_css_parse_basic14()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/basic14.css");
+
+ css_selector_t selector;
+ selector.first.id = "p1";
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsla(120,100,50,0.3)"));
+
+ selector.first.id = "p2";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsla(120,100,75,0.3)"));
+
+ selector.first.id = "p3";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsla(120,100,25,0.3)"));
+
+ selector.first.id = "p4";
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "hsla(120,60,70,0.3)"));
+}
+
+void test_css_parse_chained1()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/chained1.css");
+
+ css_selector_t selector;
+ selector.first.name = "div";
+ css_simple_selector_t ss;
+ ss.name = "p";
+ selector.chained.push_back(ss);
+
+ // div p
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "yellow"));
+
+ // div > p
+ selector.chained.back().combinator = css::combinator_t::direct_child;
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "blue"));
+
+ // div + p
+ selector.chained.back().combinator = css::combinator_t::next_sibling;
+ props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 1);
+ assert(check_prop(*props, "background-color", "red"));
+}
+
+void test_css_parse_chained2()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/chained2.css");
+
+ // Build selector '#id1 table.data td'.
+ css_selector_t selector;
+ selector.first.id = "id1";
+
+ css_simple_selector_t ss;
+ ss.name = "table";
+ ss.classes.insert("data");
+ selector.chained.push_back(ss);
+
+ ss.clear();
+ ss.name = "td";
+ selector.chained.push_back(ss);
+
+ const css_properties_t* props = doc.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 2);
+ assert(check_prop(*props, "background-color", "aquamarine"));
+ assert(check_prop(*props, "border", "solid 2px"));
+}
+
+void test_css_parse_utf8_1()
+{
+ css_document_tree doc = load_document(SRCDIR"/test/css/utf8-1.css");
+
+ css_document_tree doc2;
+ doc2 = std::move(doc); // test the move assignment operator.
+
+ css_selector_t selector;
+ selector.first.classes.insert("style17");
+
+ const css_properties_t* props = doc2.get_properties(selector, 0);
+ assert(props);
+ assert(props->size() == 11);
+
+ check_properties_type expected = {
+ { "mso-pattern", "auto none" },
+ { "background", "#EDEDED" },
+ { "mso-style-name", "20% - 强调文字颜色 3" },
+ { "color", "#000000" },
+ { "font-size", "11.0pt" },
+ { "font-weight", "400" },
+ { "font-style", "normal" },
+ { "font-family", "宋体" },
+ { "text-decoration", "none" },
+ { "mso-generic-font-family", "auto" },
+ { "mso-font-charset", "0" },
+ };
+
+ assert(check_props(*props, expected));
+}
+
+int main()
+{
+ test_css_invalids();
+ test_css_simple_selector_equality();
+ test_css_empty();
+ test_css_parse_basic1();
+ test_css_parse_basic2();
+ test_css_parse_basic3();
+ test_css_parse_basic4();
+ test_css_parse_basic5();
+ test_css_parse_basic6();
+ test_css_parse_basic7();
+ test_css_parse_basic8();
+ test_css_parse_basic9();
+ test_css_parse_basic10();
+ test_css_parse_basic11();
+ test_css_parse_basic12();
+ test_css_parse_basic13();
+ test_css_parse_basic14();
+ test_css_parse_chained1();
+ test_css_parse_chained2();
+ test_css_parse_utf8_1();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/css_selector.cpp b/src/liborcus/css_selector.cpp
new file mode 100644
index 0000000..b7b63f3
--- /dev/null
+++ b/src/liborcus/css_selector.cpp
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/css_selector.hpp"
+
+namespace orcus {
+
+css_simple_selector_t::css_simple_selector_t() :
+ pseudo_classes(0) {}
+
+void css_simple_selector_t::clear()
+{
+ name = std::string_view{};
+ id = std::string_view{};
+ classes.clear();
+ pseudo_classes = 0;
+}
+
+bool css_simple_selector_t::empty() const
+{
+ return name.empty() && id.empty() && classes.empty() && !pseudo_classes;
+}
+
+bool css_simple_selector_t::operator== (const css_simple_selector_t& r) const
+{
+ if (name != r.name)
+ return false;
+
+ if (id != r.id)
+ return false;
+
+ if (classes != r.classes)
+ return false;
+
+ return pseudo_classes == r.pseudo_classes;
+}
+
+bool css_simple_selector_t::operator!= (const css_simple_selector_t& r) const
+{
+ return !operator==(r);
+}
+
+size_t css_simple_selector_t::hash::operator() (const css_simple_selector_t& ss) const
+{
+ std::hash<std::string_view> h;
+
+ size_t val = h(ss.name);
+ val += h(ss.id);
+
+ for (std::string_view s : ss.classes)
+ val += h(s);
+
+ val += ss.pseudo_classes;
+
+ return val;
+}
+
+bool css_chained_simple_selector_t::operator== (const css_chained_simple_selector_t& r) const
+{
+ return combinator == r.combinator && simple_selector == r.simple_selector;
+}
+
+css_chained_simple_selector_t::css_chained_simple_selector_t() :
+ combinator(css::combinator_t::descendant) {}
+
+css_chained_simple_selector_t::css_chained_simple_selector_t(const css_simple_selector_t& ss) :
+ combinator(css::combinator_t::descendant), simple_selector(ss) {}
+
+css_chained_simple_selector_t::css_chained_simple_selector_t(
+ css::combinator_t op, const css_simple_selector_t& ss) :
+ combinator(op), simple_selector(ss) {}
+
+void css_selector_t::clear()
+{
+ first.clear();
+ chained.clear();
+}
+
+bool css_selector_t::operator== (const css_selector_t& r) const
+{
+ return first == r.first && chained == r.chained;
+}
+
+css_property_value_t::css_property_value_t() :
+ type(css::property_value_t::none), value{std::string_view{}} {}
+
+css_property_value_t::css_property_value_t(const css_property_value_t& r) :
+ type(r.type), value(r.value)
+{
+}
+
+css_property_value_t::css_property_value_t(std::string_view _str) :
+ type(css::property_value_t::string), value(_str) {}
+
+css_property_value_t& css_property_value_t::operator= (const css_property_value_t& r)
+{
+ type = r.type;
+ value = r.value;
+ return *this;
+}
+
+void css_property_value_t::swap(css_property_value_t& r)
+{
+ std::swap(type, r.type);
+ std::swap(value, r.value);
+}
+
+std::ostream& operator<< (std::ostream& os, const css_simple_selector_t& v)
+{
+ os << v.name;
+ css_simple_selector_t::classes_type::const_iterator it = v.classes.begin(), ite = v.classes.end();
+ for (; it != ite; ++it)
+ os << '.' << *it;
+ if (!v.id.empty())
+ os << '#' << v.id;
+ if (v.pseudo_classes)
+ os << css::pseudo_class_to_string(v.pseudo_classes);
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const css_selector_t& v)
+{
+ os << v.first;
+ css_selector_t::chained_type::const_iterator it = v.chained.begin(), ite = v.chained.end();
+ for (; it != ite; ++it)
+ {
+ const css_chained_simple_selector_t& css = *it;
+ os << ' ';
+ switch (css.combinator)
+ {
+ case css::combinator_t::direct_child:
+ os << "> ";
+ break;
+ case css::combinator_t::next_sibling:
+ os << "+ ";
+ break;
+ case css::combinator_t::descendant:
+ default:
+ ;
+ }
+ os << css.simple_selector;
+ }
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const css_property_value_t& v)
+{
+ const char* sep = ",";
+
+ switch (v.type)
+ {
+ case css::property_value_t::hsl:
+ {
+ auto c = std::get<css::hsla_color_t>(v.value);
+ os << "hsl("
+ << (int)c.hue << sep
+ << (int)c.saturation << sep
+ << (int)c.lightness
+ << ")";
+ break;
+ }
+ case css::property_value_t::hsla:
+ {
+ auto c = std::get<css::hsla_color_t>(v.value);
+ os << "hsla("
+ << (int)c.hue << sep
+ << (int)c.saturation << sep
+ << (int)c.lightness << sep
+ << c.alpha
+ << ")";
+ break;
+ }
+ case css::property_value_t::rgb:
+ {
+ auto c = std::get<css::rgba_color_t>(v.value);
+ os << "rgb("
+ << (int)c.red << sep
+ << (int)c.green << sep
+ << (int)c.blue
+ << ")";
+ break;
+ }
+ case css::property_value_t::rgba:
+ {
+ auto c = std::get<css::rgba_color_t>(v.value);
+ os << "rgba("
+ << (int)c.red << sep
+ << (int)c.green << sep
+ << (int)c.blue << sep
+ << c.alpha
+ << ")";
+ break;
+ }
+ case css::property_value_t::string:
+ os << std::get<std::string_view>(v.value);
+ break;
+ case css::property_value_t::url:
+ os << "url(" << std::get<std::string_view>(v.value) << ")";
+ break;
+ case css::property_value_t::none:
+ default:
+ ;
+ }
+
+ return os;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/detection_result.cpp b/src/liborcus/detection_result.cpp
new file mode 100644
index 0000000..b49f645
--- /dev/null
+++ b/src/liborcus/detection_result.cpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "detection_result.hpp"
+
+namespace orcus {
+
+detection_result::detection_result(bool result) : m_result(result) {}
+
+bool detection_result::get_result() const
+{
+ return m_result;
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/detection_result.hpp b/src/liborcus/detection_result.hpp
new file mode 100644
index 0000000..bb87941
--- /dev/null
+++ b/src/liborcus/detection_result.hpp
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_DETECTION_RESULT_HPP
+#define ORCUS_DETECTION_RESULT_HPP
+
+namespace orcus {
+
+class detection_result
+{
+ bool m_result;
+
+public:
+ detection_result(bool result);
+
+ bool get_result() const;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/dom_tree.cpp b/src/liborcus/dom_tree.cpp
new file mode 100644
index 0000000..9e7a764
--- /dev/null
+++ b/src/liborcus/dom_tree.cpp
@@ -0,0 +1,741 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/dom_tree.hpp>
+#include <orcus/exception.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <orcus/sax_ns_parser.hpp>
+#include <orcus/string_pool.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <cassert>
+#include <unordered_map>
+#include <vector>
+#include <algorithm>
+#include <deque>
+
+namespace orcus {
+
+namespace dom {
+
+namespace {
+
+/**
+ * Escape certain characters with backslash (\).
+ */
+void escape(std::ostream& os, std::string_view val)
+{
+ if (val.empty())
+ return;
+
+ const char* p = val.data();
+ const char* p_end = p + val.size();
+ for (; p != p_end; ++p)
+ {
+ if (*p == '"')
+ os << "\\\"";
+ else if (*p == '\\')
+ os << "\\\\";
+ else
+ os << *p;
+ }
+}
+
+struct attr
+{
+ dom::entity_name name;
+ std::string_view value;
+
+ attr(xmlns_id_t _ns, std::string_view _name, std::string_view _value);
+};
+
+struct entity_name_hash
+{
+ std::size_t operator()(const entity_name& v) const
+ {
+ return std::hash<std::string_view>{}(v.name) ^ reinterpret_cast<std::size_t>(v.ns);
+ }
+};
+
+using attrs_type = std::vector<attr>;
+using attr_map_type = std::unordered_map<entity_name, size_t, entity_name_hash>;
+
+struct declaration
+{
+ attrs_type attrs;
+ attr_map_type attr_map;
+};
+
+enum class node_type { element, content };
+
+struct element;
+
+struct node
+{
+ const element* parent;
+ node_type type;
+
+ node(node_type _type) : parent(nullptr), type(_type) {}
+
+ virtual ~node() = 0;
+ virtual void print(std::ostream& os, const xmlns_context& cxt) const = 0;
+};
+
+typedef std::vector<std::unique_ptr<node>> nodes_type;
+
+struct element : public node
+{
+ entity_name name;
+ attrs_type attrs;
+ attr_map_type attr_map;
+ nodes_type child_nodes;
+ std::vector<size_t> child_elem_positions;
+
+ element() = delete;
+ element(xmlns_id_t _ns, std::string_view _name);
+ virtual void print(std::ostream& os, const xmlns_context& cxt) const;
+ virtual ~element();
+};
+
+struct content : public node
+{
+ std::string_view value;
+
+ content(std::string_view _value);
+ virtual void print(std::ostream& os, const xmlns_context& cxt) const;
+ virtual ~content();
+};
+
+void print(std::ostream& os, const entity_name& name, const xmlns_context& cxt)
+{
+ if (name.ns)
+ {
+ size_t index = cxt.get_index(name.ns);
+ if (index != INDEX_NOT_FOUND)
+ os << "ns" << index << ':';
+ }
+ os << name.name;
+}
+
+void print(std::ostream& os, const attr& at, const xmlns_context& cxt)
+{
+ dom::print(os, at.name, cxt);
+ os << "=\"";
+ escape(os, at.value);
+ os << '"';
+}
+
+attr::attr(xmlns_id_t _ns, std::string_view _name, std::string_view _value) :
+ name(_ns, _name), value(_value) {}
+
+node::~node() {}
+
+element::element(xmlns_id_t _ns, std::string_view _name) :
+ node(node_type::element), name(_ns, _name) {}
+
+void element::print(std::ostream& os, const xmlns_context& cxt) const
+{
+ dom::print(os, name, cxt);
+}
+
+element::~element() = default;
+
+content::content(std::string_view _value) : node(node_type::content), value(_value) {}
+
+void content::print(std::ostream& os, const xmlns_context& /*cxt*/) const
+{
+ os << '"';
+ escape(os, value);
+ os << '"';
+}
+
+content::~content() = default;
+
+} // anonymous namespace
+
+entity_name::entity_name() : ns(XMLNS_UNKNOWN_ID) {}
+
+entity_name::entity_name(std::string_view _name) :
+ ns(XMLNS_UNKNOWN_ID), name(_name) {}
+
+entity_name::entity_name(xmlns_id_t _ns, std::string_view _name) :
+ ns(_ns), name(_name) {}
+
+bool entity_name::operator== (const entity_name& other) const
+{
+ return ns == other.ns && name == other.name;
+}
+
+bool entity_name::operator!= (const entity_name& other) const
+{
+ return !operator==(other);
+}
+
+struct const_node::impl
+{
+ node_t type;
+
+ union
+ {
+ const dom::declaration* decl;
+ const dom::element* elem;
+
+ struct
+ {
+ const char* p;
+ size_t n;
+
+ } str;
+
+ } value;
+
+ impl() : type(node_t::unset) {}
+
+ impl(const impl& other) : type(other.type)
+ {
+ switch (type)
+ {
+ case node_t::declaration:
+ value.decl = other.value.decl;
+ break;
+ case node_t::element:
+ value.elem = other.value.elem;
+ break;
+ case node_t::unset:
+ default:
+ ;
+ }
+ }
+
+ impl(const dom::element* _elem) : type(node_t::element)
+ {
+ value.elem = _elem;
+ }
+
+ impl(const dom::declaration* _decl) : type(node_t::declaration)
+ {
+ value.decl = _decl;
+ }
+};
+
+const_node::const_node(std::unique_ptr<impl>&& _impl) : mp_impl(std::move(_impl)) {}
+const_node::const_node() : mp_impl(std::make_unique<impl>()) {}
+const_node::const_node(const const_node& other) : mp_impl(std::make_unique<impl>(*other.mp_impl)) {}
+const_node::const_node(const_node&& other) : mp_impl(std::move(other.mp_impl)) {}
+const_node::~const_node() {}
+
+node_t const_node::type() const
+{
+ return mp_impl->type;
+}
+
+size_t const_node::child_count() const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::element:
+ {
+ const dom::element* p = mp_impl->value.elem;
+ return p->child_elem_positions.size();
+ }
+ default:
+ ;
+ }
+
+ return 0;
+}
+
+const_node const_node::child(size_t index) const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::element:
+ {
+ const dom::element* p = mp_impl->value.elem;
+
+ size_t elem_pos = p->child_elem_positions.at(index);
+ assert(elem_pos < p->child_nodes.size());
+
+ const dom::node* child_node = p->child_nodes[elem_pos].get();
+ assert(child_node->type == node_type::element);
+
+ auto v = std::make_unique<impl>(static_cast<const dom::element*>(child_node));
+ return const_node(std::move(v));
+ }
+ default:
+ ;
+ }
+ return const_node();
+}
+
+entity_name const_node::name() const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::element:
+ {
+ const dom::element* p = mp_impl->value.elem;
+ return p->name;
+ }
+ default:
+ ;
+ }
+
+ return entity_name();
+}
+
+std::string_view const_node::attribute(const entity_name& name) const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::element:
+ {
+ const dom::element* p = mp_impl->value.elem;
+ auto it = p->attr_map.find(name);
+ if (it == p->attr_map.end())
+ break;
+
+ size_t pos = it->second;
+ assert(pos < p->attrs.size());
+ return p->attrs[pos].value;
+ }
+ default:
+ ;
+ }
+
+ return std::string_view();
+}
+
+std::string_view const_node::attribute(std::string_view name) const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::declaration:
+ {
+ const dom::declaration* p = mp_impl->value.decl;
+ auto it = p->attr_map.find(name);
+ if (it == p->attr_map.end())
+ return std::string_view();
+
+ size_t pos = it->second;
+ assert(pos < p->attrs.size());
+ return p->attrs[pos].value;
+ }
+ default:
+ ;
+ }
+
+ return attribute(entity_name(name));
+}
+
+size_t const_node::attribute_count() const
+{
+ switch (mp_impl->type)
+ {
+ case node_t::declaration:
+ {
+ const dom::declaration* p = mp_impl->value.decl;
+ return p->attrs.size();
+ }
+ case node_t::element:
+ {
+ const dom::element* p = mp_impl->value.elem;
+ return p->attrs.size();
+ }
+ default:
+ ;
+ }
+ return 0;
+}
+
+const_node const_node::parent() const
+{
+ if (mp_impl->type != node_t::element)
+ return const_node();
+
+ const dom::element* p = mp_impl->value.elem->parent;
+ if (!p)
+ return const_node();
+
+ auto v = std::make_unique<impl>(p);
+ return const_node(std::move(v));
+}
+
+void const_node::swap(const_node& other)
+{
+ mp_impl.swap(other.mp_impl);
+}
+
+const_node& const_node::operator= (const const_node& other)
+{
+ const_node tmp(other);
+ swap(tmp);
+ return *this;
+}
+
+bool const_node::operator== (const const_node& other) const
+{
+ if (mp_impl->type != other.mp_impl->type)
+ return false;
+
+ switch (mp_impl->type)
+ {
+ case node_t::unset:
+ return true;
+ case node_t::declaration:
+ return mp_impl->value.decl == other.mp_impl->value.decl;
+ case node_t::element:
+ return mp_impl->value.elem == other.mp_impl->value.elem;
+ default:
+ ;
+ }
+
+ return false;
+}
+
+bool const_node::operator!= (const const_node& other) const
+{
+ return !operator==(other);
+}
+
+/**
+ * This impl class also serves as the handler for the sax_ns_parser.
+ */
+struct document_tree::impl
+{
+ typedef std::vector<dom::element*> element_stack_type;
+ typedef std::unordered_map<std::string_view, dom::declaration> declarations_type;
+
+ xmlns_context& m_ns_cxt;
+ string_pool m_pool;
+
+ std::unique_ptr<sax::doctype_declaration> m_doctype;
+
+ std::string_view m_cur_decl_name;
+ declarations_type m_decls;
+ dom::attrs_type m_doc_attrs;
+ dom::attrs_type m_cur_attrs;
+ dom::attr_map_type m_cur_attr_map;
+ element_stack_type m_elem_stack;
+ std::unique_ptr<dom::element> m_root;
+
+ impl(xmlns_context& cxt) : m_ns_cxt(cxt) {}
+
+ void start_declaration(std::string_view name)
+ {
+ m_cur_decl_name = name;
+ }
+
+ void end_declaration(std::string_view name);
+ void start_element(const sax_ns_parser_element& elem);
+ void end_element(const sax_ns_parser_element& elem);
+ void characters(std::string_view val, bool transient);
+ void doctype(const sax::doctype_declaration& dtd);
+
+ void attribute(std::string_view name, std::string_view val)
+ {
+ set_attribute(XMLNS_UNKNOWN_ID, name, val);
+ }
+
+ void attribute(const sax_ns_parser_attribute& attr)
+ {
+ set_attribute(attr.ns, attr.name, attr.value);
+ }
+
+ void set_attribute(xmlns_id_t ns, std::string_view name, std::string_view val);
+};
+
+void document_tree::impl::end_declaration(std::string_view name)
+{
+ assert(m_cur_decl_name == name);
+
+ dom::declaration decl;
+ decl.attrs.swap(m_cur_attrs);
+ decl.attr_map.swap(m_cur_attr_map);
+
+ declarations_type::iterator it = m_decls.find(name);
+ if (it == m_decls.end())
+ {
+ // Insert a new entry for this name.
+ std::pair<declarations_type::iterator,bool> r =
+ m_decls.insert(
+ declarations_type::value_type(
+ m_pool.intern(name).first, std::move(decl)));
+
+ if (!r.second)
+ // Insertion failed.
+ throw general_error("dom_tree::end_declaration: failed to insert a new declaration entry.");
+ }
+ else
+ it->second = std::move(decl);
+}
+
+void document_tree::impl::start_element(const sax_ns_parser_element& elem)
+{
+ xmlns_id_t ns = elem.ns;
+ std::string_view name = elem.name;
+
+ // These strings must be persistent.
+ std::string_view name_safe = m_pool.intern(name).first;
+
+ dom::element* p = nullptr;
+ if (!m_root)
+ {
+ // This must be the root element!
+ m_root = std::make_unique<dom::element>(ns, name_safe);
+ m_elem_stack.push_back(m_root.get());
+ p = m_elem_stack.back();
+ p->attrs.swap(m_cur_attrs);
+ p->attr_map.swap(m_cur_attr_map);
+ return;
+ }
+
+ // Append new element as a child element of the current element.
+ p = m_elem_stack.back();
+
+ size_t elem_pos = p->child_nodes.size();
+ p->child_elem_positions.push_back(elem_pos);
+
+ p->child_nodes.push_back(std::make_unique<dom::element>(ns, name_safe));
+ const dom::element* parent = p;
+ p = static_cast<dom::element*>(p->child_nodes.back().get());
+ p->parent = parent;
+ p->attrs.swap(m_cur_attrs);
+ p->attr_map.swap(m_cur_attr_map);
+
+ m_elem_stack.push_back(p);
+}
+
+void document_tree::impl::end_element(const sax_ns_parser_element& elem)
+{
+ xmlns_id_t ns = elem.ns;
+ std::string_view name = elem.name;
+
+ const dom::element* p = m_elem_stack.back();
+ if (p->name.ns != ns || p->name.name != name)
+ throw general_error("non-matching end element.");
+
+ m_elem_stack.pop_back();
+}
+
+void document_tree::impl::characters(std::string_view val, bool /*transient*/)
+{
+ if (m_elem_stack.empty())
+ // No root element has been encountered. Ignore this.
+ return;
+
+ std::string_view val2 = trim(val);
+ if (val2.empty())
+ return;
+
+ dom::element* p = m_elem_stack.back();
+ val2 = m_pool.intern(val2).first; // Make sure the string is persistent.
+ auto child = std::make_unique<dom::content>(val2);
+ child->parent = p;
+ p->child_nodes.push_back(std::move(child));
+}
+
+void document_tree::impl::set_attribute(xmlns_id_t ns, std::string_view name, std::string_view val)
+{
+ // These strings must be persistent.
+ std::string_view name2 = m_pool.intern(name).first;
+ std::string_view val2 = m_pool.intern(val).first;
+
+ size_t pos = m_cur_attrs.size();
+ m_cur_attrs.push_back(dom::attr(ns, name2, val2));
+ m_cur_attr_map.insert({dom::entity_name(ns, name2), pos});
+}
+
+void document_tree::impl::doctype(const sax::doctype_declaration& dtd)
+{
+ m_doctype = std::make_unique<sax::doctype_declaration>(dtd); // make a copy.
+
+ sax::doctype_declaration& this_dtd = *m_doctype;
+ string_pool& pool = m_pool;
+
+ // Intern the strings.
+ this_dtd.root_element = pool.intern(dtd.root_element).first;
+ this_dtd.fpi = pool.intern(dtd.fpi).first;
+ this_dtd.uri = pool.intern(dtd.uri).first;
+}
+
+document_tree::document_tree(xmlns_context& cxt) :
+ mp_impl(std::make_unique<impl>(cxt)) {}
+
+document_tree::document_tree(document_tree&& other) :
+ mp_impl(std::move(other.mp_impl))
+{
+ other.mp_impl = std::make_unique<impl>(mp_impl->m_ns_cxt);
+}
+
+document_tree::~document_tree() {}
+
+void document_tree::load(std::string_view strm)
+{
+ sax_ns_parser<impl> parser(strm, mp_impl->m_ns_cxt, *mp_impl);
+ parser.parse();
+}
+
+dom::const_node document_tree::root() const
+{
+ const dom::element* p = mp_impl->m_root.get();
+ auto v = std::make_unique<const_node::impl>(p);
+ return dom::const_node(std::move(v));
+}
+
+dom::const_node document_tree::declaration(std::string_view name) const
+{
+ impl::declarations_type::const_iterator it = mp_impl->m_decls.find(name);
+ if (it == mp_impl->m_decls.end())
+ return dom::const_node();
+
+ const dom::declaration* decl = &it->second;
+ auto v = std::make_unique<dom::const_node::impl>(decl);
+ return dom::const_node(std::move(v));
+}
+
+void document_tree::swap(document_tree& other)
+{
+ mp_impl.swap(other.mp_impl);
+}
+
+const sax::doctype_declaration* document_tree::get_doctype() const
+{
+ return mp_impl->m_doctype.get();
+}
+
+namespace {
+
+struct scope
+{
+ typedef std::vector<const dom::node*> nodes_type;
+ std::string name;
+ nodes_type nodes;
+ nodes_type::const_iterator current_pos;
+
+ scope(const scope&) = delete;
+ scope& operator=(const scope&) = delete;
+
+ scope(const std::string& _name, dom::node* _node) :
+ name(_name)
+ {
+ nodes.push_back(_node);
+ current_pos = nodes.begin();
+ }
+
+ scope(const std::string& _name) : name(_name) {}
+};
+
+typedef std::deque<scope> scopes_type;
+
+void print_scope(std::ostream& os, const scopes_type& scopes)
+{
+ if (scopes.empty())
+ throw general_error("scope stack shouldn't be empty while dumping tree.");
+
+ // Skip the first scope which is root.
+ scopes_type::const_iterator it = scopes.begin(), it_end = scopes.end();
+ for (++it; it != it_end; ++it)
+ os << "/" << it->name;
+}
+
+}
+
+void document_tree::dump_compact(std::ostream& os) const
+{
+ if (!mp_impl->m_root)
+ return;
+
+ // Dump namespaces first.
+ mp_impl->m_ns_cxt.dump(os);
+
+ scopes_type scopes;
+
+ scopes.emplace_back(std::string(), mp_impl->m_root.get());
+ while (!scopes.empty())
+ {
+ bool new_scope = false;
+
+ // Iterate through all elements in the current scope.
+ scope& cur_scope = scopes.back();
+ for (; cur_scope.current_pos != cur_scope.nodes.end(); ++cur_scope.current_pos)
+ {
+ const dom::node* this_node = *cur_scope.current_pos;
+ assert(this_node);
+ print_scope(os, scopes);
+ if (this_node->type == dom::node_type::content)
+ {
+ // This is a text content.
+ this_node->print(os, mp_impl->m_ns_cxt);
+ os << std::endl;
+ continue;
+ }
+
+ assert(this_node->type == dom::node_type::element);
+ const dom::element* elem = static_cast<const dom::element*>(this_node);
+ os << "/";
+ elem->print(os, mp_impl->m_ns_cxt);
+ os << std::endl;
+
+ {
+ // Dump attributes.
+ dom::attrs_type attrs = elem->attrs;
+ std::sort(attrs.begin(), attrs.end(),
+ [](const dom::attr& left, const dom::attr& right) -> bool
+ {
+ return left.name.name < right.name.name;
+ }
+ );
+
+ for (const dom::attr& a : attrs)
+ {
+ print_scope(os, scopes);
+ os << "/";
+ elem->print(os, mp_impl->m_ns_cxt);
+ os << "@";
+ dom::print(os, a, mp_impl->m_ns_cxt);
+ os << std::endl;
+ }
+ }
+
+ if (elem->child_nodes.empty())
+ continue;
+
+ // This element has child nodes. Push a new scope and populate it
+ // with all child elements, but skip content nodes.
+ scope::nodes_type nodes;
+ for (const std::unique_ptr<dom::node>& p : elem->child_nodes)
+ nodes.push_back(p.get());
+
+ assert(!nodes.empty());
+
+ // Push a new scope, and restart the loop with the new scope.
+ ++cur_scope.current_pos;
+ std::ostringstream elem_name;
+ elem->print(elem_name, mp_impl->m_ns_cxt);
+ scopes.emplace_back(elem_name.str());
+ scope& child_scope = scopes.back();
+ child_scope.nodes.swap(nodes);
+ child_scope.current_pos = child_scope.nodes.begin();
+
+ new_scope = true;
+ break;
+ }
+
+ if (new_scope)
+ continue;
+
+ scopes.pop_back();
+ }
+}
+
+} // namespace dom
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/dom_tree_test.cpp b/src/liborcus/dom_tree_test.cpp
new file mode 100644
index 0000000..5ce5418
--- /dev/null
+++ b/src/liborcus/dom_tree_test.cpp
@@ -0,0 +1,123 @@
+
+#include <orcus/dom_tree.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <cassert>
+#include <iostream>
+
+using namespace orcus::dom;
+
+struct doctree
+{
+ orcus::xmlns_repository repo;
+ orcus::xmlns_context cxt;
+ orcus::dom::document_tree tree;
+
+ doctree(std::string_view content) : repo(), cxt(repo.create_context()), tree(cxt)
+ {
+ tree.load(content);
+ }
+};
+
+std::unique_ptr<doctree> load_document_tree(std::string_view content)
+{
+ std::unique_ptr<doctree> ret = std::make_unique<doctree>(content);
+ return ret;
+}
+
+std::unique_ptr<doctree> load_document_tree_from_file(const char* filepath)
+{
+ orcus::file_content content(filepath);
+ return load_document_tree(content.str());
+}
+
+void test_encoded_attr()
+{
+ std::string content = "<?xml version=\"1.0\"?><root attr=\"&amp;;\"/>";
+ auto doctree = load_document_tree(content);
+ const_node root = doctree->tree.root();
+ doctree->tree.dump_compact(std::cout);
+ std::cout << __FILE__ << "#" << __LINE__ << " (:test_encoded_attr): " << root.attribute("attr") << std::endl;
+ assert(root.attribute("attr") == "&;");
+}
+
+void test_declaration()
+{
+ auto doctree = load_document_tree_from_file(SRCDIR"/test/xml/osm/street-in-aizu.osm");
+
+ const_node decl = doctree->tree.declaration("xml");
+ assert(decl.type() == node_t::declaration);
+ assert(decl.attribute("version") == "1.0");
+ assert(decl.attribute("encoding") == "UTF-8");
+
+ const_node copied = decl;
+ assert(copied == decl);
+}
+
+void test_attributes()
+{
+ auto doctree = load_document_tree_from_file(SRCDIR"/test/xml/osm/street-in-aizu.osm");
+
+ const_node root = doctree->tree.root();
+ assert(root.name() == entity_name("osm"));
+ assert(root.type() == node_t::element);
+ assert(root.attribute("version") == "0.6");
+ assert(root.attribute("generator") == "CGImap 0.6.1 (1984 thorn-02.openstreetmap.org)");
+ assert(root.attribute("copyright") == "OpenStreetMap and contributors");
+ assert(root.attribute("attribution") == "http://www.openstreetmap.org/copyright");
+ assert(root.attribute("license") == "http://opendatacommons.org/licenses/odbl/1-0/");
+ assert(root.attribute("no-such-attribute").empty());
+ assert(root.attribute_count() == 5);
+}
+
+void test_element_hierarchy()
+{
+ auto doctree = load_document_tree_from_file(SRCDIR"/test/xml/osm/street-in-aizu.osm");
+
+ const_node root = doctree->tree.root();
+ assert(root.name() == entity_name("osm"));
+ assert(root.child_count() > 0);
+ assert(root.parent().type() == node_t::unset);
+
+ const_node elem = root.child(0);
+ assert(elem != root);
+ assert(elem.type() == node_t::element);
+ assert(elem.name() == entity_name("bounds"));
+ assert(elem.attribute("minlat") == "37.4793300");
+ assert(elem.attribute("minlon") == "139.9158300");
+ assert(elem.attribute("maxlat") == "37.4798000");
+ assert(elem.attribute("maxlon") == "139.9162300");
+ assert(elem.attribute_count() == 4);
+ assert(elem.child_count() == 0);
+ assert(elem.parent() == root);
+
+ const_node copied_elem = elem;
+ assert(copied_elem == elem);
+
+ elem = root.child(5);
+ assert(elem.name() == entity_name("node"));
+ assert(elem.attribute("user") == "jun_meguro");
+ assert(elem.child_count() == 1);
+ elem = elem.child(0);
+ assert(elem.name() == entity_name("tag"));
+ assert(elem.attribute("k") == "highway");
+ assert(elem.attribute("v") == "crossing");
+
+ // Make sure the number of child elements are accurate.
+ size_t n_elems = root.child_count();
+ for (size_t i = 0; i < n_elems; ++i)
+ {
+ auto child = root.child(i);
+ assert(child.type() == node_t::element);
+ }
+}
+
+int main()
+{
+ test_encoded_attr();
+ test_declaration();
+ test_attributes();
+ test_element_hierarchy();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/liborcus/format_detection.cpp b/src/liborcus/format_detection.cpp
new file mode 100644
index 0000000..e685362
--- /dev/null
+++ b/src/liborcus/format_detection.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifdef __ORCUS_ODS
+#define ODS_ENABLED 1
+#else
+#define ODS_ENABLED 0
+#endif
+
+#ifdef __ORCUS_XLSX
+#define XLSX_ENABLED 1
+#else
+#define XLSX_ENABLED 0
+#endif
+
+#ifdef __ORCUS_GNUMERIC
+#define GNUMERIC_ENABLED 1
+#else
+#define GNUMERIC_ENABLED 0
+#endif
+
+#ifdef __ORCUS_XLS_XML
+#define XLS_XML_ENABLED 1
+#else
+#define XLS_XML_ENABLED 0
+#endif
+
+#ifdef __ORCUS_PARQUET
+#define PARQUET_ENABLED 1
+#else
+#define PARQUET_ENABLED 0
+#endif
+
+#include <orcus/format_detection.hpp>
+#include <orcus/orcus_csv.hpp>
+
+#if ODS_ENABLED
+#include <orcus/orcus_ods.hpp>
+#endif
+#if XLSX_ENABLED
+#include <orcus/orcus_xlsx.hpp>
+#endif
+#if GNUMERIC_ENABLED
+#include <orcus/orcus_gnumeric.hpp>
+#endif
+#if XLS_XML_ENABLED
+#include <orcus/orcus_xls_xml.hpp>
+#endif
+#if PARQUET_ENABLED
+#include <orcus/orcus_parquet.hpp>
+#endif
+
+#include <stdexcept>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+format_t detect(std::string_view strm) try
+{
+ const auto* p = reinterpret_cast<const unsigned char*>(strm.data());
+
+#if ODS_ENABLED
+ if (orcus_ods::detect(p, strm.size()))
+ return format_t::ods;
+#endif
+#if XLSX_ENABLED
+ if (orcus_xlsx::detect(p, strm.size()))
+ return format_t::xlsx;
+#endif
+#if GNUMERIC_ENABLED
+ if (orcus_gnumeric::detect(p, strm.size()))
+ return format_t::gnumeric;
+#endif
+#if XLS_XML_ENABLED
+ if (orcus_xls_xml::detect(p, strm.size()))
+ return format_t::xls_xml;
+#endif
+#if PARQUET_ENABLED
+ if (orcus_parquet::detect(p, strm.size()))
+ return format_t::parquet;
+#endif
+
+ return format_t::unknown;
+}
+catch (const std::exception&)
+{
+ return format_t::unknown;
+}
+catch (...)
+{
+ return format_t::unknown;
+}
+
+std::shared_ptr<iface::import_filter> create_filter(format_t type, ss::iface::import_factory* factory)
+{
+ if (!factory)
+ throw std::invalid_argument("pointer to import factory instance must not be null");
+ switch (type)
+ {
+#if ODS_ENABLED
+ case format_t::ods:
+ return std::allocate_shared<orcus_ods>(std::allocator<orcus_ods>{}, factory);
+#endif
+#if XLSX_ENABLED
+ case format_t::xlsx:
+ return std::allocate_shared<orcus_xlsx>(std::allocator<orcus_xlsx>{}, factory);
+#endif
+#if GNUMERIC_ENABLED
+ case format_t::gnumeric:
+ return std::allocate_shared<orcus_gnumeric>(std::allocator<orcus_gnumeric>{}, factory);
+#endif
+#if XLS_XML_ENABLED
+ case format_t::xls_xml:
+ return std::allocate_shared<orcus_xls_xml>(std::allocator<orcus_xls_xml>{}, factory);
+#endif
+#if PARQUET_ENABLED
+ case format_t::parquet:
+ return std::allocate_shared<orcus_parquet>(std::allocator<orcus_parquet>{}, factory);
+#endif
+ case format_t::csv:
+ return std::allocate_shared<orcus_csv>(std::allocator<orcus_csv>{}, factory);
+ case format_t::unknown:
+ default:;
+ }
+ return {};
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/formula_result.cpp b/src/liborcus/formula_result.cpp
new file mode 100644
index 0000000..bdde523
--- /dev/null
+++ b/src/liborcus/formula_result.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "formula_result.hpp"
+
+#include <ostream>
+
+namespace orcus {
+
+formula_result::formula_result() : type(result_type::empty) {}
+formula_result::formula_result(const formula_result& r) :
+ type(r.type)
+{
+ switch (type)
+ {
+ case result_type::numeric:
+ value_numeric = r.value_numeric;
+ break;
+ case result_type::boolean:
+ value_boolean = r.value_boolean;
+ break;
+ case result_type::string:
+ value_string.p = r.value_string.p;
+ value_string.n = r.value_string.n;
+ break;
+ case result_type::empty:
+ default:
+ ;
+ }
+}
+
+formula_result::formula_result(double v) : type(result_type::numeric), value_numeric(v) {}
+formula_result::formula_result(const char* p, size_t n) :
+ type(result_type::string)
+{
+ value_string.p = p;
+ value_string.n = n;
+}
+
+formula_result::formula_result(bool b) : type(result_type::boolean), value_boolean(b) {}
+
+size_t range_formula_results::to_array_pos(size_t row, size_t col) const
+{
+ return row * m_cols + col;
+}
+
+range_formula_results::range_formula_results(size_t rows, size_t cols) :
+ m_store(rows*cols), m_rows(rows), m_cols(cols) {}
+
+void range_formula_results::set(size_t row, size_t col, const formula_result& v)
+{
+ size_t pos = to_array_pos(row, col);
+ m_store[pos] = v;
+}
+
+const formula_result& range_formula_results::get(size_t row, size_t col) const
+{
+ size_t pos = to_array_pos(row, col);
+ return m_store[pos];
+}
+
+size_t range_formula_results::row_size() const
+{
+ return m_rows;
+}
+
+size_t range_formula_results::col_size() const
+{
+ return m_cols;
+}
+
+std::ostream& operator<< (std::ostream& os, const formula_result& v)
+{
+ switch (v.type)
+ {
+ case formula_result::result_type::numeric:
+ os << v.value_numeric;
+ break;
+ case formula_result::result_type::boolean:
+ os << v.value_boolean;
+ break;
+ case formula_result::result_type::string:
+ os << std::string_view(v.value_string.p, v.value_string.n);
+ break;
+ case formula_result::result_type::empty:
+ break;
+ }
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const orcus::range_formula_results& res)
+{
+ os << "{ ";
+ size_t col_pos = 0;
+ for (const formula_result& v : res.m_store)
+ {
+ if (col_pos == res.m_cols)
+ {
+ os << " | ";
+ col_pos = 0;
+ }
+ else if (col_pos > 0)
+ os << ", ";
+
+ os << v;
+ ++col_pos;
+ }
+
+ os << " }";
+
+ return os;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/formula_result.hpp b/src/liborcus/formula_result.hpp
new file mode 100644
index 0000000..14665b3
--- /dev/null
+++ b/src/liborcus/formula_result.hpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_FORMULA_RESULT_HPP
+#define INCLUDED_ORCUS_FORMULA_RESULT_HPP
+
+#include <vector>
+#include <cstdlib>
+#include <iosfwd>
+
+namespace orcus {
+
+/**
+ * Stores cached formula result. Note that when the result is of string
+ * type, it only stores a pointer to the string buffer but the instance of
+ * this class does not own the buffer.
+ */
+struct formula_result
+{
+ enum class result_type { empty, numeric, string, boolean };
+
+ result_type type;
+
+ union
+ {
+ double value_numeric;
+ bool value_boolean;
+ struct { const char* p; size_t n; } value_string;
+ };
+
+ formula_result();
+ formula_result(const formula_result& r);
+ formula_result(double v);
+ formula_result(const char* p, size_t n);
+ formula_result(bool b);
+};
+
+class range_formula_results
+{
+ friend std::ostream& operator<< (std::ostream&, const range_formula_results&);
+
+ std::vector<formula_result> m_store;
+ size_t m_rows;
+ size_t m_cols;
+
+ size_t to_array_pos(size_t row, size_t col) const;
+
+public:
+ range_formula_results() = delete;
+ range_formula_results(const range_formula_results&) = delete;
+ range_formula_results(size_t rows, size_t cols);
+
+ void set(size_t row, size_t col, const formula_result& v);
+ const formula_result& get(size_t row, size_t col) const;
+
+ size_t row_size() const;
+ size_t col_size() const;
+};
+
+std::ostream& operator<< (std::ostream& os, const formula_result& v);
+std::ostream& operator<< (std::ostream& os, const orcus::range_formula_results& res);
+
+}
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_cell_context.cpp b/src/liborcus/gnumeric_cell_context.cpp
new file mode 100644
index 0000000..07b82bc
--- /dev/null
+++ b/src/liborcus/gnumeric_cell_context.cpp
@@ -0,0 +1,377 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_cell_context.hpp"
+#include "gnumeric_value_format_parser.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/measurement.hpp>
+
+#include <fstream>
+#include <algorithm>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+gnumeric_cell_context::gnumeric_cell_context(
+ session_context& session_cxt, const tokens& tokens, ss::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory),
+ mp_sheet(nullptr)
+{
+}
+
+gnumeric_cell_context::~gnumeric_cell_context() = default;
+
+void gnumeric_cell_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Cell:
+ start_cell(attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool gnumeric_cell_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Cell:
+ end_cell();
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void gnumeric_cell_context::characters(std::string_view str, bool transient)
+{
+ m_chars = str;
+ if (transient)
+ m_chars = intern(m_chars);
+}
+
+void gnumeric_cell_context::reset(ss::iface::import_sheet* sheet)
+{
+ m_cell_data.reset();
+ m_chars = std::string_view{};
+ mp_sheet = sheet;
+ m_pool.clear();
+}
+
+void gnumeric_cell_context::start_cell(const xml_token_attrs_t& attrs)
+{
+ m_cell_data = cell_data{};
+ m_cell_data->type = cell_type_formula;
+ m_format_segments.clear();
+
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Row:
+ m_cell_data->row = to_long(attr.value);
+ break;
+ case XML_Col:
+ m_cell_data->col = to_long(attr.value);
+ break;
+ case XML_ValueType:
+ {
+ auto v = to_long(attr.value);
+ m_cell_data->type = cell_type_value;
+ m_cell_data->value_type = static_cast<gnumeric_value_type>(v);
+ break;
+ }
+ case XML_ValueFormat:
+ {
+ auto v = attr.value;
+ if (attr.transient)
+ v = m_pool.intern(v).first;
+
+ gnumeric_value_format_parser parser(v);
+
+ try
+ {
+ parser.parse();
+ }
+ catch (const parse_error& e)
+ {
+ std::ostringstream os;
+ os << "failed to parse a value format string: '" << v << "' (reason=" << e.what() << ")";
+ warn(os.str());
+ break;
+ }
+
+ m_format_segments = parser.pop_segments();
+ break;
+ }
+ case XML_ExprID:
+ m_cell_data->shared_formula_id = to_long(attr.value);
+ m_cell_data->type = cell_type_shared_formula;
+ break;
+ case XML_Rows:
+ m_cell_data->type = cell_type_value;
+ m_cell_data->value_type = vt_array;
+ m_cell_data->array_rows = to_long(attr.value);
+ break;
+ case XML_Cols:
+ m_cell_data->type = cell_type_value;
+ m_cell_data->value_type = vt_array;
+ m_cell_data->array_cols = to_long(attr.value);
+ break;
+ }
+ }
+}
+
+void gnumeric_cell_context::end_cell()
+{
+ if (!m_cell_data)
+ return;
+
+ if (!mp_sheet)
+ return;
+
+ ss::col_t col = m_cell_data->col;
+ ss::row_t row = m_cell_data->row;
+
+ switch (m_cell_data->type)
+ {
+ case cell_type_value:
+ {
+ if (!m_cell_data->value_type)
+ break;
+
+ switch (*m_cell_data->value_type)
+ {
+ case vt_boolean:
+ {
+ bool val = to_bool(m_chars);
+ mp_sheet->set_bool(row, col, val);
+ break;
+ }
+ case vt_float:
+ {
+ double val = to_double(m_chars);
+ mp_sheet->set_value(row, col, val);
+ break;
+ }
+ case vt_string:
+ {
+ push_string(row, col);
+ break;
+ }
+ case vt_array:
+ {
+ ss::range_t range;
+ range.first.column = col;
+ range.first.row = row;
+ range.last.column = col + m_cell_data->array_cols - 1;
+ range.last.row = row + m_cell_data->array_rows - 1;
+
+ ss::iface::import_array_formula* af = mp_sheet->get_array_formula();
+ if (!af)
+ break;
+
+ if (m_chars.empty() || m_chars[0] != '=')
+ // formula string should start with a '='
+ break;
+
+ af->set_range(range);
+ af->set_formula(ss::formula_grammar_t::gnumeric, m_chars.substr(1));
+ af->commit();
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os << "unhandled cell value type (" << *m_cell_data->value_type << ")";
+ warn(os.str());
+ }
+ }
+ break;
+ }
+ case cell_type_formula:
+ {
+ ss::iface::import_formula* xformula = mp_sheet->get_formula();
+ if (!xformula)
+ break;
+
+ if (m_chars.empty() || m_chars[0] != '=')
+ // formula string should start with a '='
+ break;
+
+ xformula->set_position(row, col);
+ xformula->set_formula(ss::formula_grammar_t::gnumeric, m_chars.substr(1));
+ xformula->commit();
+ break;
+ }
+ case cell_type_shared_formula:
+ {
+ ss::iface::import_formula* xformula = mp_sheet->get_formula();
+ if (!xformula)
+ break;
+
+ xformula->set_position(row, col);
+
+ if (!m_chars.empty() && m_chars[0] == '=')
+ xformula->set_formula(ss::formula_grammar_t::gnumeric, m_chars.substr(1));
+
+ xformula->set_shared_formula_index(m_cell_data->shared_formula_id);
+ xformula->commit();
+ break;
+ }
+ case cell_type_unknown:
+ {
+ std::ostringstream os;
+ os << "cell type is unknown (row=" << row << "; col=" << col << ")";
+ warn(os.str());
+ break;
+ }
+ }
+
+ m_cell_data.reset();
+}
+
+void gnumeric_cell_context::push_string(ss::row_t row, ss::col_t col)
+{
+ ss::iface::import_shared_strings* shared_strings = mp_factory->get_shared_strings();
+ if (!shared_strings)
+ return;
+
+ if (m_format_segments.empty())
+ {
+ // unformatted text
+ std::size_t sid = shared_strings->add(m_chars);
+ mp_sheet->set_string(row, col, sid);
+ return;
+ }
+
+ for (const auto& [start, end] : build_format_segment_ranges())
+ {
+ assert(start < end);
+
+ auto t = m_chars.substr(start, end - start);
+
+ // TODO: use segment tree to eliminate this inner loop
+ for (const gnumeric_value_format_segment& vfs : m_format_segments)
+ {
+ if (vfs.value.empty())
+ continue;
+
+ if (start < vfs.start || vfs.end < end)
+ continue;
+
+ // we have format information
+ switch (vfs.type)
+ {
+ case gnumeric_value_format_type::bold:
+ {
+ bool v = to_bool(vfs.value);
+ shared_strings->set_segment_bold(v);
+ break;
+ }
+ case gnumeric_value_format_type::italic:
+ {
+ bool v = to_bool(vfs.value);
+ shared_strings->set_segment_italic(v);
+ break;
+ }
+ case gnumeric_value_format_type::color:
+ {
+ // [red]x[green]x[blue]
+ auto color = parse_gnumeric_rgb_8x(vfs.value);
+ if (color)
+ shared_strings->set_segment_font_color(255, color->red, color->green, color->blue);
+ break;
+ }
+ case gnumeric_value_format_type::family:
+ {
+ if (!vfs.value.empty())
+ shared_strings->set_segment_font_name(vfs.value);
+ break;
+ }
+ case gnumeric_value_format_type::size:
+ {
+ const char* p_end = nullptr;
+ double v = to_double(vfs.value, &p_end);
+ if (p_end > vfs.value.data())
+ {
+ // font size here is stored in 1024ths of a point, likely coming from Pango
+ v /= 1024.0;
+ shared_strings->set_segment_font_size(v);
+ }
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os << "unsupported format segment type (" << int(vfs.type) << ")";
+ warn(os.str());
+ }
+ }
+ }
+
+ shared_strings->append_segment(t);
+ }
+
+ std::size_t sid = shared_strings->commit_segments();
+ mp_sheet->set_string(row, col, sid);
+}
+
+std::vector<std::pair<std::size_t, std::size_t>> gnumeric_cell_context::build_format_segment_ranges() const
+{
+ if (m_format_segments.empty())
+ return {};
+
+ std::vector<std::size_t> pts;
+ pts.push_back(0);
+ pts.push_back(m_chars.size());
+ for (const auto& seg : m_format_segments)
+ {
+ pts.push_back(seg.start);
+ pts.push_back(seg.end);
+ }
+
+ std::sort(pts.begin(), pts.end());
+ auto last = std::unique(pts.begin(), pts.end());
+ pts.erase(last, pts.end());
+ assert(pts.size() > 2u);
+
+ std::vector<std::pair<std::size_t, std::size_t>> ranges;
+
+ auto it = pts.begin();
+ auto start = *it;
+ for (++it; it != pts.end(); ++it)
+ {
+ auto end = *it;
+ ranges.emplace_back(start, end);
+ start = end;
+ }
+
+ return ranges;
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_cell_context.hpp b/src/liborcus/gnumeric_cell_context.hpp
new file mode 100644
index 0000000..b3c5f85
--- /dev/null
+++ b/src/liborcus/gnumeric_cell_context.hpp
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_GNUMERIC_CELL_CONTEXT_HPP
+#define INCLUDED_ORCUS_GNUMERIC_CELL_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "gnumeric_types.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+#include <orcus/string_pool.hpp>
+
+#include <mdds/flat_segment_tree.hpp>
+
+#include <optional>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+
+}}
+
+struct gnumeric_cell_data;
+
+class gnumeric_cell_context : public xml_context_base
+{
+ enum cell_type
+ {
+ cell_type_unknown,
+ cell_type_value,
+ cell_type_formula,
+ cell_type_shared_formula,
+ };
+
+ struct cell_data
+ {
+ cell_type type = cell_type_unknown;
+ std::optional<gnumeric_value_type> value_type;
+ spreadsheet::row_t row = 0;
+ spreadsheet::col_t col = 0;
+ spreadsheet::row_t array_rows = 0;
+ spreadsheet::col_t array_cols = 0;
+ std::size_t shared_formula_id = 0;
+ };
+
+public:
+ gnumeric_cell_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+ virtual ~gnumeric_cell_context() override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset(spreadsheet::iface::import_sheet* sheet);
+
+private:
+ void start_cell(const xml_token_attrs_t& attrs);
+ void end_cell();
+ void push_string(spreadsheet::row_t row, spreadsheet::col_t col);
+
+ std::vector<std::pair<std::size_t, std::size_t>> build_format_segment_ranges() const;
+
+private:
+ spreadsheet::iface::import_factory* mp_factory;
+ spreadsheet::iface::import_sheet* mp_sheet;
+
+ std::vector<gnumeric_value_format_segment> m_format_segments;
+ std::optional<cell_data> m_cell_data;
+ std::string_view m_chars;
+ string_pool m_pool;
+};
+
+} // namespace orcus
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_cell_context_test.cpp b/src/liborcus/gnumeric_cell_context_test.cpp
new file mode 100644
index 0000000..80d612c
--- /dev/null
+++ b/src/liborcus/gnumeric_cell_context_test.cpp
@@ -0,0 +1,386 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_cell_context.hpp"
+#include "gnumeric_tokens.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "mock_spreadsheet.hpp"
+#include "session_context.hpp"
+#include <orcus/types.hpp>
+
+#include <iostream>
+#include <string>
+#include <cstdlib>
+
+using namespace orcus;
+using namespace std;
+using namespace orcus::spreadsheet;
+using namespace orcus::spreadsheet::mock;
+
+namespace {
+
+class mock_array_formula : public import_array_formula
+{
+public:
+ virtual void set_range(const range_t& range) override
+ {
+ assert(range.first.row == 19);
+ assert(range.first.column == 111);
+ assert(range.last.row == 20);
+ assert(range.last.column == 113);
+ }
+
+ virtual void set_formula(formula_grammar_t grammar, std::string_view formula) override
+ {
+ assert(grammar == formula_grammar_t::gnumeric);
+ assert(formula == "arrayFormula");
+ }
+
+ virtual void set_result_bool(row_t, col_t, bool) override
+ {
+ }
+
+ virtual void set_result_empty(row_t, col_t) override
+ {
+ }
+
+ virtual void set_result_string(row_t, col_t, std::string_view) override
+ {
+ }
+
+ virtual void set_result_value(row_t, col_t, double) override
+ {
+ }
+
+ virtual void commit() override
+ {
+ }
+};
+
+class mock_formula : public import_formula
+{
+public:
+ virtual void set_position(row_t row, col_t col) override
+ {
+ assert(row == 9);
+ assert(col == 11);
+ }
+
+ virtual void set_formula(formula_grammar_t grammar, std::string_view formula) override
+ {
+ assert(grammar == formula_grammar_t::gnumeric);
+ assert(formula == "formula");
+ }
+
+ virtual void set_shared_formula_index(size_t) override
+ {
+ }
+
+ virtual void set_result_bool(bool) override
+ {
+ }
+
+ virtual void set_result_empty() override
+ {
+ }
+
+ virtual void set_result_string(std::string_view) override
+ {
+ }
+
+ virtual void set_result_value(double) override
+ {
+ }
+
+ virtual void commit() override
+ {
+ }
+};
+
+class mock_sheet : public import_sheet
+{
+ mock_formula m_formula;
+ mock_array_formula m_array_formula;
+public:
+ virtual void set_value(row_t row, col_t col, double val) override
+ {
+ assert(row == 1);
+ assert(col == 2);
+ assert(val == 5.0);
+ }
+
+ virtual void set_bool(row_t row, col_t col, bool val) override
+ {
+ assert(row == 31);
+ assert(col == 32);
+ assert(val == true);
+ }
+
+ virtual void set_string(row_t row, col_t col, string_id_t id) override
+ {
+ assert(row == 10);
+ assert(col == 321);
+ assert(id == 2);
+ }
+
+ virtual iface::import_array_formula* get_array_formula() override
+ {
+ return &m_array_formula;
+ }
+
+ virtual iface::import_formula* get_formula() override
+ {
+ return &m_formula;
+ }
+};
+
+class mock_shared_strings : public import_shared_strings
+{
+public:
+ virtual size_t add(std::string_view s) override
+ {
+ assert(s.size() == 14);
+ assert(s == "14 char string");
+ return 2;
+ }
+};
+
+class mock_factory : public import_factory
+{
+public:
+ virtual iface::import_shared_strings* get_shared_strings()
+ {
+ return &m_shared_strings;
+ }
+
+private:
+ mock_shared_strings m_shared_strings;
+};
+
+void test_cell_value()
+{
+ mock_sheet sheet;
+ import_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "1", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "2", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_ValueType, "40", false));
+ context.start_element(ns, elem, attrs);
+ context.characters("5", false);
+ context.end_element(ns, elem);
+}
+
+void test_cell_bool()
+{
+ mock_sheet sheet;
+ import_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "31", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "32", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_ValueType, "20", false));
+ context.start_element(ns, elem, attrs);
+ context.characters("TRUE", false);
+ context.end_element(ns, elem);
+}
+
+void test_cell_string()
+{
+ mock_sheet sheet;
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "10", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "321", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_ValueType, "60", false));
+ context.start_element(ns, elem, attrs);
+ context.characters("14 char string", false);
+ context.end_element(ns, elem);
+}
+
+void test_shared_formula_with_string()
+{
+ class mock_formula_local : public import_formula
+ {
+ public:
+ void set_position(row_t row, col_t col) override
+ {
+ assert(row == 5);
+ assert(col == 15);
+ }
+
+ void set_formula(formula_grammar_t grammar, std::string_view formula) override
+ {
+ assert(grammar == formula_grammar_t::gnumeric);
+ assert(formula == "basicFormulaString");
+ }
+
+ void set_shared_formula_index(size_t index) override
+ {
+ assert(index == 2);
+ }
+
+ void commit() override
+ {
+ }
+ };
+
+ class mock_sheet_local : public import_sheet
+ {
+ mock_formula_local m_formula;
+ public:
+ virtual iface::import_formula* get_formula()
+ {
+ return &m_formula;
+ }
+ };
+
+ mock_sheet_local sheet;
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "5", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "15", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_ExprID, "2", false));
+
+ context.start_element(ns, elem, attrs);
+ context.characters("=basicFormulaString", false);
+ context.end_element(ns, elem);
+}
+
+void test_shared_formula_without_string()
+{
+ class mock_formula_local : public import_formula
+ {
+ public:
+ void set_position(row_t row, col_t col) override
+ {
+ assert(row == 6);
+ assert(col == 16);
+ }
+
+ void set_shared_formula_index(size_t index) override
+ {
+ assert(index == 3);
+ }
+
+ void commit() override
+ {
+ }
+ };
+
+ class mock_sheet_local : public import_sheet
+ {
+ mock_formula_local m_formula;
+ public:
+ virtual iface::import_formula* get_formula()
+ {
+ return &m_formula;
+ }
+ };
+
+ mock_sheet_local sheet;
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "6", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "16", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_ExprID, "3", false));
+
+ context.start_element(ns, elem, attrs);
+ context.end_element(ns, elem);
+}
+
+void test_cell_formula()
+{
+ mock_sheet sheet;
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "9", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "11", false));
+ context.start_element(ns, elem, attrs);
+ context.characters("=formula", false);
+ context.end_element(ns, elem);
+}
+
+void test_cell_array_formula()
+{
+ mock_sheet sheet;
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_cell_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(&sheet);
+
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t elem = XML_Cell;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Row, "19", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Col, "111", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Rows, "2", false));
+ attrs.push_back(xml_token_attr_t(NS_gnumeric_gnm, XML_Cols, "3", false));
+ context.start_element(ns, elem, attrs);
+ context.characters("arrayFormula", false);
+ context.end_element(ns, elem);
+}
+
+}
+
+int main()
+{
+ test_cell_value();
+ test_cell_bool();
+ test_cell_string();
+ test_shared_formula_with_string();
+ test_shared_formula_without_string();
+ test_cell_formula();
+ test_cell_array_formula();
+
+ return EXIT_SUCCESS;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_context.cpp b/src/liborcus/gnumeric_context.cpp
new file mode 100644
index 0000000..33c8d44
--- /dev/null
+++ b/src/liborcus/gnumeric_context.cpp
@@ -0,0 +1,453 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_context.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_sheet_context.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+
+#include <fstream>
+#include <algorithm>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+std::size_t import_font_style(ss::iface::import_styles& istyles, const gnumeric_style& style)
+{
+ ss::iface::import_font_style* ifont = istyles.start_font_style();
+ ENSURE_INTERFACE(ifont, import_font_style);
+
+ if (style.font_name)
+ ifont->set_name(*style.font_name);
+
+ if (style.font_unit)
+ ifont->set_size(*style.font_unit);
+
+ if (style.bold)
+ ifont->set_bold(*style.bold);
+
+ if (style.italic)
+ ifont->set_italic(*style.italic);
+
+ if (style.underline)
+ {
+ if (*style.underline)
+ ifont->set_underline(ss::underline_t::single_line);
+ else
+ ifont->set_underline(ss::underline_t::none);
+ }
+
+ if (style.strikethrough)
+ {
+ if (*style.strikethrough)
+ {
+ ifont->set_strikethrough_style(ss::strikethrough_style_t::solid);
+ ifont->set_strikethrough_type(ss::strikethrough_type_t::single_type);
+ ifont->set_strikethrough_width(ss::strikethrough_width_t::width_auto);
+ }
+ else
+ {
+ ifont->set_strikethrough_style(ss::strikethrough_style_t::none);
+ ifont->set_strikethrough_type(ss::strikethrough_type_t::none);
+ }
+ }
+
+ if (style.fore)
+ ifont->set_color(255, style.fore->red, style.fore->green, style.fore->blue);
+
+ return ifont->commit();
+}
+
+std::optional<std::size_t> import_fill_style(
+ ss::iface::import_styles& istyles, const gnumeric_style& style)
+{
+ if (style.pattern == ss::fill_pattern_t::none)
+ return {};
+
+ ss::iface::import_fill_style* ifill = istyles.start_fill_style();
+ ENSURE_INTERFACE(ifill, import_fill_style);
+
+ ifill->set_pattern_type(style.pattern);
+
+ if (style.back)
+ ifill->set_fg_color(
+ 255,
+ style.back->red,
+ style.back->green,
+ style.back->blue);
+
+ if (style.pattern_color)
+ ifill->set_bg_color(
+ 255,
+ style.pattern_color->red,
+ style.pattern_color->green,
+ style.pattern_color->blue);
+
+ return ifill->commit();
+}
+
+std::optional<std::size_t> import_border_styles(
+ ss::iface::import_styles& istyles, const gnumeric_style& style)
+{
+ ss::iface::import_border_style* iborder = istyles.start_border_style();
+ ENSURE_INTERFACE(iborder, import_border_style);
+
+ auto func_import_border = [&iborder](ss::border_direction_t dir, const gnumeric_style::border_type& border)
+ {
+ bool has_style = false;
+
+ if (border.style)
+ {
+ iborder->set_style(dir, to_standard_type(*border.style));
+ has_style = true;
+ }
+
+ if (border.color)
+ {
+ iborder->set_color(
+ dir, 255, border.color->red, border.color->green, border.color->blue);
+ has_style = true;
+ }
+
+ return has_style;
+ };
+
+ bool has_style = false;
+
+ if (func_import_border(ss::border_direction_t::top, style.border_top))
+ has_style = true;
+
+ if (func_import_border(ss::border_direction_t::bottom, style.border_bottom))
+ has_style = true;
+
+ if (func_import_border(ss::border_direction_t::left, style.border_left))
+ has_style = true;
+
+ if (func_import_border(ss::border_direction_t::right, style.border_right))
+ has_style = true;
+
+ if (func_import_border(ss::border_direction_t::diagonal_bl_tr, style.border_bl_tr))
+ has_style = true;
+
+ if (func_import_border(ss::border_direction_t::diagonal_tl_br, style.border_br_tl))
+ has_style = true;
+
+ if (!has_style)
+ return {};
+
+ return iborder->commit();
+}
+
+std::optional<std::size_t> import_number_format(
+ ss::iface::import_styles& istyles, const gnumeric_style& style)
+{
+ if (!style.number_format)
+ return {};
+
+ ss::iface::import_number_format* inumfmt = istyles.start_number_format();
+ ENSURE_INTERFACE(inumfmt, import_number_format);
+
+ inumfmt->set_code(*style.number_format);
+ return inumfmt->commit();
+}
+
+} // anonymous namespace
+
+gnumeric_content_xml_context::gnumeric_content_xml_context(
+ session_context& session_cxt, const tokens& tokens, spreadsheet::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory),
+ m_sheet_pos(0),
+ m_cxt_names(session_cxt, tokens, factory),
+ m_cxt_sheet(session_cxt, tokens, factory)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_gnumeric_gnm, XML_Workbook }, // root element
+ { NS_gnumeric_gnm, XML_SheetNameIndex, NS_gnumeric_gnm, XML_SheetName },
+ { NS_gnumeric_gnm, XML_Sheets, NS_gnumeric_gnm, XML_Sheet },
+ { NS_gnumeric_gnm, XML_Workbook, NS_gnumeric_gnm, XML_Names },
+ { NS_gnumeric_gnm, XML_Workbook, NS_gnumeric_gnm, XML_SheetNameIndex },
+ { NS_gnumeric_gnm, XML_Workbook, NS_gnumeric_gnm, XML_Sheets },
+ };
+
+ init_element_validator(rules, std::size(rules));
+
+ register_child(&m_cxt_names);
+ register_child(&m_cxt_sheet);
+}
+
+gnumeric_content_xml_context::~gnumeric_content_xml_context() = default;
+
+xml_context_base* gnumeric_content_xml_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Sheet:
+ {
+ m_cxt_sheet.reset(m_sheet_pos++);
+ return &m_cxt_sheet;
+ }
+ case XML_Names:
+ {
+ m_cxt_names.reset();
+ return &m_cxt_names;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+void gnumeric_content_xml_context::end_child_context(
+ xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Sheet:
+ {
+ assert(child == &m_cxt_sheet);
+ end_sheet();
+ break;
+ }
+ case XML_Names:
+ {
+ assert(child == &m_cxt_names);
+ end_names();
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_content_xml_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& /*attrs*/)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_SheetNameIndex:
+ m_sheet_pos = 0;
+ break;
+ case XML_SheetName:
+ break;
+ case XML_Sheets:
+ m_sheet_pos = 0;
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool gnumeric_content_xml_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Sheets:
+ end_sheets();
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void gnumeric_content_xml_context::characters(std::string_view str, bool /*transient*/)
+{
+ if (str.empty())
+ return;
+
+ const auto [ns, name] = get_current_element();
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_SheetName:
+ {
+ auto* p = mp_factory->append_sheet(m_sheet_pos++, str);
+ if (!p)
+ {
+ std::ostringstream os;
+ os << "failed to append a new sheet named '" << str << "'";
+ warn(os.str());
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_content_xml_context::end_names()
+{
+ ss::iface::import_named_expression* named_exp = mp_factory->get_named_expression();
+ if (!named_exp)
+ return;
+
+ for (const auto& name : m_cxt_names.get_names())
+ {
+ try
+ {
+ named_exp->set_base_position(name.position);
+ named_exp->set_named_expression(name.name, name.value);
+ named_exp->commit();
+ }
+ catch (const std::exception& e)
+ {
+ std::ostringstream os;
+ os << "failed to commit a named expression named '" << name.name
+ << "': (reason='" << e.what() << "'; value='" << name.value << "')";
+ warn(os.str());
+ }
+ }
+}
+
+void gnumeric_content_xml_context::end_sheet()
+{
+ m_styles.push_back(m_cxt_sheet.pop_styles());
+}
+
+void gnumeric_content_xml_context::end_sheets()
+{
+ import_styles();
+}
+
+void gnumeric_content_xml_context::import_styles()
+{
+ ss::iface::import_styles* istyles = mp_factory->get_styles();
+ if (!istyles)
+ return;
+
+ std::size_t xf_count = 1; // one for the default style
+ for (const auto& sheet_styles : m_styles)
+ xf_count += sheet_styles.size();
+
+ istyles->set_xf_count(ss::xf_category_t::cell, xf_count);
+
+ import_default_styles(istyles);
+ import_cell_styles(istyles);
+}
+
+void gnumeric_content_xml_context::import_default_styles(ss::iface::import_styles* istyles)
+{
+ assert(istyles);
+
+ ss::iface::import_font_style* ifont = istyles->start_font_style();
+ ENSURE_INTERFACE(ifont, imort_font_style);
+ std::size_t id = ifont->commit();
+ assert(id == 0);
+
+ ss::iface::import_fill_style* ifill = istyles->start_fill_style();
+ ENSURE_INTERFACE(ifill, imort_fill_style);
+ id = ifill->commit();
+ assert(id == 0);
+
+ ss::iface::import_border_style* iborder = istyles->start_border_style();
+ ENSURE_INTERFACE(iborder, imort_border_style);
+ id = iborder->commit();
+ assert(id == 0);
+
+ ss::iface::import_cell_protection* iprotection = istyles->start_cell_protection();
+ ENSURE_INTERFACE(iprotection, imort_cell_protection);
+ id = iprotection->commit();
+ assert(id == 0);
+
+ ss::iface::import_number_format* inumfmt = istyles->start_number_format();
+ ENSURE_INTERFACE(inumfmt, import_number_format);
+ id = inumfmt->commit();
+ assert(id == 0);
+
+ ss::iface::import_xf* ixf = istyles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(ixf, import_xf);
+ id = ixf->commit();
+ assert(id == 0);
+
+ ss::iface::import_cell_style* xstyle = istyles->start_cell_style();
+ ENSURE_INTERFACE(xstyle, import_cell_style);
+ xstyle->set_xf(0);
+ xstyle->commit();
+}
+
+void gnumeric_content_xml_context::import_cell_styles(ss::iface::import_styles* istyles)
+{
+ assert(istyles);
+
+ for (const auto& sheet_styles : m_styles)
+ {
+ for (const gnumeric_style& style : sheet_styles)
+ {
+ assert(style.valid()); // should be validated before insertion
+
+ ss::iface::import_sheet* isheet = mp_factory->get_sheet(style.sheet);
+ if (!isheet)
+ continue;
+
+ std::size_t id_font = import_font_style(*istyles, style);
+ auto id_fill = import_fill_style(*istyles, style);
+ auto id_border = import_border_styles(*istyles, style);
+ auto id_numfmt = import_number_format(*istyles, style);
+
+ ss::iface::import_xf* ixf = istyles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(ixf, import_xf);
+
+ ixf->set_font(id_font);
+
+ if (id_fill)
+ ixf->set_fill(*id_fill);
+
+ if (id_border)
+ ixf->set_border(*id_border);
+
+ if (id_numfmt)
+ ixf->set_number_format(*id_numfmt);
+
+ bool apply_alignment =
+ style.hor_align != ss::hor_alignment_t::unknown ||
+ style.ver_align != ss::ver_alignment_t::unknown ||
+ style.wrap_text;
+
+ ixf->set_apply_alignment(apply_alignment);
+
+ if (style.hor_align != ss::hor_alignment_t::unknown)
+ ixf->set_horizontal_alignment(style.hor_align);
+
+ if (style.ver_align != ss::ver_alignment_t::unknown)
+ ixf->set_vertical_alignment(style.ver_align);
+
+ if (style.wrap_text)
+ ixf->set_wrap_text(*style.wrap_text);
+
+ std::size_t xfid = ixf->commit();
+ isheet->set_format(
+ style.region.first.row, style.region.first.column,
+ style.region.last.row, style.region.last.column,
+ xfid);
+ }
+ }
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_context.hpp b/src/liborcus/gnumeric_context.hpp
new file mode 100644
index 0000000..f6d066c
--- /dev/null
+++ b/src/liborcus/gnumeric_context.hpp
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_GNUMERICCONTEXT_HPP
+#define INCLUDED_ORCUS_GNUMERICCONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "gnumeric_sheet_context.hpp"
+#include "gnumeric_names_context.hpp"
+#include "gnumeric_types.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+#include <vector>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+class import_styles;
+
+}}
+
+class gnumeric_content_xml_context : public xml_context_base
+{
+public:
+ gnumeric_content_xml_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+
+ virtual ~gnumeric_content_xml_context() override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+private:
+ void end_names();
+ void end_sheet();
+ void end_sheets();
+
+ void import_styles();
+ void import_default_styles(spreadsheet::iface::import_styles* istyles);
+ void import_cell_styles(spreadsheet::iface::import_styles* istyles);
+
+private:
+ spreadsheet::iface::import_factory* mp_factory;
+ spreadsheet::sheet_t m_sheet_pos;
+
+ gnumeric_names_context m_cxt_names;
+ gnumeric_sheet_context m_cxt_sheet;
+
+ std::vector<std::vector<gnumeric_style>> m_styles;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_detection_handler.cpp b/src/liborcus/gnumeric_detection_handler.cpp
new file mode 100644
index 0000000..1f0606e
--- /dev/null
+++ b/src/liborcus/gnumeric_detection_handler.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_detection_handler.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "xml_context_base.hpp"
+#include "detection_result.hpp"
+
+namespace orcus {
+
+namespace {
+
+/**
+ * Check the xml structure up to the first <gnm:Sheet> element. If all the
+ * structure check passes up to that point, we call it "detected".
+ */
+class gnumeric_detection_context : public xml_context_base
+{
+public:
+ gnumeric_detection_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens) {}
+
+ virtual xml_context_base* create_child_context(xmlns_id_t, xml_token_t) { return nullptr; }
+ virtual void characters(std::string_view, bool) {}
+ virtual void end_child_context(xmlns_id_t, xml_token_t, xml_context_base*) {}
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& /*attrs*/)
+ {
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Workbook:
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ break;
+ case XML_Version:
+ case XML_Attributes:
+ case XML_Calculation:
+ case XML_SheetNameIndex:
+ case XML_Geometry:
+ case XML_Sheets:
+ xml_element_expected(parent, NS_gnumeric_gnm, XML_Workbook);
+ break;
+ case XML_Attribute:
+ xml_element_expected(parent, NS_gnumeric_gnm, XML_Attributes);
+ break;
+ case XML_SheetName:
+ xml_element_expected(parent, NS_gnumeric_gnm, XML_SheetNameIndex);
+ break;
+ case XML_Sheet:
+ xml_element_expected(parent, NS_gnumeric_gnm, XML_Sheets);
+ throw detection_result(true);
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name)
+ {
+ return pop_stack(ns, name);
+ }
+};
+
+}
+
+gnumeric_detection_handler::gnumeric_detection_handler(session_context& session_cxt, const tokens& t) :
+ xml_stream_handler(session_cxt, t, std::make_unique<gnumeric_detection_context>(session_cxt, t)) {}
+
+gnumeric_detection_handler::~gnumeric_detection_handler() {}
+
+void gnumeric_detection_handler::start_document() {}
+void gnumeric_detection_handler::end_document() {}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_detection_handler.hpp b/src/liborcus/gnumeric_detection_handler.hpp
new file mode 100644
index 0000000..e7644a3
--- /dev/null
+++ b/src/liborcus/gnumeric_detection_handler.hpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_GNUMERIC_DETECTION_HANDLER_HPP
+#define ORCUS_GNUMERIC_DETECTION_HANDLER_HPP
+
+#include "xml_stream_handler.hpp"
+
+namespace orcus {
+
+struct session_context;
+class tokens;
+
+class gnumeric_detection_handler : public xml_stream_handler
+{
+public:
+ gnumeric_detection_handler(session_context& session_cxt, const tokens& t);
+ virtual ~gnumeric_detection_handler();
+
+ virtual void start_document();
+ virtual void end_document();
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_filter_context.cpp b/src/liborcus/gnumeric_filter_context.cpp
new file mode 100644
index 0000000..f15d2a0
--- /dev/null
+++ b/src/liborcus/gnumeric_filter_context.cpp
@@ -0,0 +1,256 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_filter_context.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/measurement.hpp>
+
+#include <iostream>
+#include <optional>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+enum gnumeric_filter_field_op_t
+{
+ filter_equal,
+ filter_greaterThan,
+ filter_lessThan,
+ filter_greaterThanEqual,
+ filter_lessThanEqual,
+ filter_notEqual,
+ filter_op_invalid
+};
+
+enum gnumeric_filter_field_type_t
+{
+ filter_expr,
+ filter_blanks,
+ filter_nonblanks,
+ filter_type_invalid
+};
+
+} // anonymous namespace
+
+gnumeric_filter_context::gnumeric_filter_context(
+ session_context& session_cxt, const tokens& tokens,
+ ss::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_gnumeric_gnm, XML_Filter }, // root element
+ { NS_gnumeric_gnm, XML_Filter, NS_gnumeric_gnm, XML_Field },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+gnumeric_filter_context::~gnumeric_filter_context() = default;
+
+void gnumeric_filter_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Filter:
+ {
+ start_filter(attrs);
+ break;
+ }
+ case XML_Field:
+ {
+ start_field(attrs);
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool gnumeric_filter_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Filter:
+ end_filter();
+ break;
+ case XML_Field:
+ end_field();
+ break;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void gnumeric_filter_context::reset(spreadsheet::iface::import_sheet* sheet)
+{
+ mp_sheet = sheet;
+ mp_auto_filter = nullptr;
+}
+
+void gnumeric_filter_context::start_filter(const xml_token_attrs_t& attrs)
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_reference_resolver* resolver =
+ mp_factory->get_reference_resolver(ss::formula_ref_context_t::global);
+
+ if (!resolver)
+ return;
+
+ mp_auto_filter = mp_sheet->get_auto_filter();
+ if (!mp_auto_filter)
+ return;
+
+ std::optional<spreadsheet::range_t> area;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Area:
+ area = to_rc_range(resolver->resolve_range(attr.value));
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (!area)
+ {
+ mp_auto_filter = nullptr;
+ return;
+ }
+
+ mp_auto_filter->set_range(*area);
+}
+
+void gnumeric_filter_context::start_field(const xml_token_attrs_t& attrs)
+{
+ if (!mp_auto_filter)
+ return;
+
+ gnumeric_filter_field_type_t filter_field_type = filter_type_invalid;
+ gnumeric_filter_field_op_t filter_op = filter_op_invalid;
+
+ ss::col_t col = -1;
+ std::string_view filter_value_type;
+ std::string_view filter_value;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Index:
+ {
+ col = to_long(attr.value.data());
+ break;
+ }
+ case XML_Type:
+ {
+ if (attr.value == "expr")
+ filter_field_type = filter_expr;
+ else if (attr.value == "blanks")
+ filter_field_type = filter_blanks;
+ else if (attr.value == "nonblanks")
+ filter_field_type = filter_nonblanks;
+ break;
+ }
+ case XML_Op0:
+ {
+ if (attr.value == "eq")
+ filter_op = filter_equal;
+ else if (attr.value == "gt")
+ filter_op = filter_greaterThan;
+ else if (attr.value == "lt")
+ filter_op = filter_lessThan;
+ else if (attr.value == "gte")
+ filter_op = filter_greaterThanEqual;
+ else if (attr.value == "lte")
+ filter_op = filter_lessThanEqual;
+ else if (attr.value == "ne")
+ filter_op = filter_notEqual;
+ break;
+ }
+ case XML_Value0:
+ {
+ filter_value_type = attr.value;
+ break;
+ }
+ case XML_ValueType0:
+ {
+ filter_value = attr.value;
+ break;
+ }
+ }
+ }
+
+ if (col < 0)
+ return;
+
+ mp_auto_filter->set_column(col);
+
+ switch (filter_field_type)
+ {
+ case filter_expr:
+ {
+ // only equal supported in API yet
+ if (filter_op != filter_equal)
+ return;
+
+ // import condition for integer (30), double(40) and string (60)
+ if (filter_value_type == "30" ||
+ filter_value_type == "40" ||
+ filter_value_type == "60" )
+ {
+ mp_auto_filter->append_column_match_value(filter_value);
+ }
+ break;
+ }
+ case filter_blanks:
+ break;
+ case filter_nonblanks:
+ break;
+ case filter_type_invalid:
+ break;
+ }
+}
+
+void gnumeric_filter_context::end_filter()
+{
+ if (mp_auto_filter)
+ mp_auto_filter->commit();
+}
+
+void gnumeric_filter_context::end_field()
+{
+ if (mp_auto_filter)
+ mp_auto_filter->commit_column();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_filter_context.hpp b/src/liborcus/gnumeric_filter_context.hpp
new file mode 100644
index 0000000..b8c794b
--- /dev/null
+++ b/src/liborcus/gnumeric_filter_context.hpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+class import_auto_filter;
+
+}}
+
+class gnumeric_filter_context : public xml_context_base
+{
+public:
+ gnumeric_filter_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+ virtual ~gnumeric_filter_context() override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ void reset(spreadsheet::iface::import_sheet* sheet);
+
+private:
+ void start_filter(const xml_token_attrs_t& attrs);
+ void start_field(const xml_token_attrs_t& attrs);
+
+ void end_filter();
+ void end_field();
+
+
+private:
+ spreadsheet::iface::import_factory* mp_factory = nullptr;
+ spreadsheet::iface::import_sheet* mp_sheet = nullptr;
+ spreadsheet::iface::import_auto_filter* mp_auto_filter = nullptr;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_handler.cpp b/src/liborcus/gnumeric_handler.cpp
new file mode 100644
index 0000000..67e428f
--- /dev/null
+++ b/src/liborcus/gnumeric_handler.cpp
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_handler.hpp"
+#include "gnumeric_context.hpp"
+
+namespace orcus {
+
+gnumeric_content_xml_handler::gnumeric_content_xml_handler(
+ session_context& session_cxt, const tokens& t, spreadsheet::iface::import_factory* factory) :
+ xml_stream_handler(session_cxt, t, std::make_unique<gnumeric_content_xml_context>(session_cxt, t, factory))
+{
+}
+
+gnumeric_content_xml_handler::~gnumeric_content_xml_handler()
+{
+}
+
+void gnumeric_content_xml_handler::start_document()
+{
+}
+
+void gnumeric_content_xml_handler::end_document()
+{
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_handler.hpp b/src/liborcus/gnumeric_handler.hpp
new file mode 100644
index 0000000..1c389c3
--- /dev/null
+++ b/src/liborcus/gnumeric_handler.hpp
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_GNUMERICHANDLER_HPP__
+#define __ORCUS_GNUMERICHANDLER_HPP__
+
+#include "xml_stream_handler.hpp"
+
+namespace orcus {
+
+struct session_context;
+class tokens;
+
+namespace spreadsheet { namespace iface { class import_factory; }}
+
+/**
+ * Handler for parsing the content.xml part.
+ */
+class gnumeric_content_xml_handler : public xml_stream_handler
+{
+public:
+ gnumeric_content_xml_handler(session_context& session_cxt, const tokens& t, spreadsheet::iface::import_factory* factory);
+ virtual ~gnumeric_content_xml_handler();
+
+ virtual void start_document();
+ virtual void end_document();
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_names_context.cpp b/src/liborcus/gnumeric_names_context.cpp
new file mode 100644
index 0000000..9c008af
--- /dev/null
+++ b/src/liborcus/gnumeric_names_context.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_names_context.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+
+#include <iostream>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+gnumeric_names_context::gnumeric_names_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_gnumeric_gnm, XML_Names }, // root element
+ { NS_gnumeric_gnm, XML_Names, NS_gnumeric_gnm, XML_Name },
+ { NS_gnumeric_gnm, XML_Name, NS_gnumeric_gnm, XML_name },
+ { NS_gnumeric_gnm, XML_Name, NS_gnumeric_gnm, XML_value },
+ { NS_gnumeric_gnm, XML_Name, NS_gnumeric_gnm, XML_position },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+gnumeric_names_context::~gnumeric_names_context() = default;
+
+void gnumeric_names_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& /*attrs*/)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Name:
+ m_current_name.reset();
+ break;
+ }
+ }
+}
+
+bool gnumeric_names_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Name:
+ m_named_exps.push_back(m_current_name);
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void gnumeric_names_context::characters(std::string_view str, bool transient)
+{
+ const auto [ns, name] = get_current_element();
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_name:
+ m_current_name.name = transient ? intern(str) : str;
+ break;
+ case XML_value:
+ m_current_name.value = transient ? intern(str) : str;
+ break;
+ case XML_position:
+ {
+ ss::iface::import_reference_resolver* resolver =
+ mp_factory->get_reference_resolver(ss::formula_ref_context_t::global);
+
+ if (resolver)
+ m_current_name.position = resolver->resolve_address(str);
+
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_names_context::reset()
+{
+ m_named_exps.clear();
+}
+
+const std::vector<gnumeric_named_exp>& gnumeric_names_context::get_names() const
+{
+ return m_named_exps;
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_names_context.hpp b/src/liborcus/gnumeric_names_context.hpp
new file mode 100644
index 0000000..1fb0416
--- /dev/null
+++ b/src/liborcus/gnumeric_names_context.hpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+#include "gnumeric_types.hpp"
+
+#include <vector>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+
+}}
+
+class gnumeric_names_context : public xml_context_base
+{
+public:
+ gnumeric_names_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+
+ virtual ~gnumeric_names_context() override;
+
+ virtual void start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ const std::vector<gnumeric_named_exp>& get_names() const;
+
+private:
+ spreadsheet::iface::import_factory* mp_factory = nullptr;
+ std::vector<gnumeric_named_exp> m_named_exps;
+ gnumeric_named_exp m_current_name;
+};
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_namespace_types.cpp b/src/liborcus/gnumeric_namespace_types.cpp
new file mode 100644
index 0000000..1ff0ec9
--- /dev/null
+++ b/src/liborcus/gnumeric_namespace_types.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_namespace_types.hpp"
+#include "odf_namespace_types.hpp"
+
+namespace orcus {
+
+const xmlns_id_t NS_gnumeric_dc = "http://purl.org/dc/elements/1.1/";
+const xmlns_id_t NS_gnumeric_gnm = "http://www.gnumeric.org/v10.dtd";
+const xmlns_id_t NS_gnumeric_ooo = "http://openoffice.org/2004/office";
+const xmlns_id_t NS_gnumeric_xlink = "http://www.w3.org/1999/xlink";
+const xmlns_id_t NS_gnumeric_xsi = "http://www.w3.org/2001/XMLSchema-instance";
+
+namespace {
+
+xmlns_id_t gnumeric_ns[] = {
+ NS_gnumeric_dc,
+ NS_gnumeric_gnm,
+ NS_gnumeric_ooo,
+ NS_gnumeric_xlink,
+ NS_gnumeric_xsi,
+
+ NS_odf_meta,
+ NS_odf_office,
+ nullptr
+};
+
+}
+
+const xmlns_id_t* NS_gnumeric_all = gnumeric_ns;
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_namespace_types.hpp b/src/liborcus/gnumeric_namespace_types.hpp
new file mode 100644
index 0000000..2d6b7ab
--- /dev/null
+++ b/src/liborcus/gnumeric_namespace_types.hpp
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_GNUMERIC_NAMESPACE_TYPES_HPP__
+#define __ORCUS_GNUMERIC_NAMESPACE_TYPES_HPP__
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+extern const xmlns_id_t NS_gnumeric_dc;
+extern const xmlns_id_t NS_gnumeric_gnm;
+extern const xmlns_id_t NS_gnumeric_ooo;
+extern const xmlns_id_t NS_gnumeric_xlink;
+extern const xmlns_id_t NS_gnumeric_xsi;
+
+extern const xmlns_id_t* NS_gnumeric_all;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_sheet_context.cpp b/src/liborcus/gnumeric_sheet_context.cpp
new file mode 100644
index 0000000..aecca4c
--- /dev/null
+++ b/src/liborcus/gnumeric_sheet_context.cpp
@@ -0,0 +1,819 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_sheet_context.hpp"
+#include "gnumeric_cell_context.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+#include <orcus/measurement.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+ss::condition_operator_t get_condition_operator(int val)
+{
+ switch (val)
+ {
+ case 0:
+ return ss::condition_operator_t::between;
+ case 1:
+ return ss::condition_operator_t::not_between;
+ case 2:
+ return ss::condition_operator_t::equal;
+ case 3:
+ return ss::condition_operator_t::not_equal;
+ case 4:
+ return ss::condition_operator_t::greater;
+ case 5:
+ return ss::condition_operator_t::less;
+ case 6:
+ return ss::condition_operator_t::greater_equal;
+ case 7:
+ return ss::condition_operator_t::less_equal;
+ case 8:
+ return ss::condition_operator_t::expression;
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ break;
+ case 16:
+ return ss::condition_operator_t::contains;
+ case 17:
+ return ss::condition_operator_t::not_contains;
+ case 18:
+ return ss::condition_operator_t::begins_with;
+ case 19:
+ break;
+ case 20:
+ return ss::condition_operator_t::ends_with;
+ case 21:
+ break;
+ case 22:
+ return ss::condition_operator_t::contains_error;
+ case 23:
+ return ss::condition_operator_t::contains_no_error;
+ default:
+ break;
+ }
+ return ss::condition_operator_t::unknown;
+}
+
+} // anonymous namespace
+
+gnumeric_sheet_context::gnumeric_sheet_context(
+ session_context& session_cxt, const tokens& tokens, ss::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory),
+ m_cxt_cell(session_cxt, tokens, factory),
+ m_cxt_filter(session_cxt, tokens, factory),
+ m_cxt_names(session_cxt, tokens, factory),
+ m_cxt_styles(session_cxt, tokens, factory)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_gnumeric_gnm, XML_Sheet }, // root element
+ { NS_gnumeric_gnm, XML_Cells, NS_gnumeric_gnm, XML_Cell },
+ { NS_gnumeric_gnm, XML_Cols, NS_gnumeric_gnm, XML_ColInfo },
+ { NS_gnumeric_gnm, XML_MergedRegions, NS_gnumeric_gnm, XML_Merge },
+ { NS_gnumeric_gnm, XML_Rows, NS_gnumeric_gnm, XML_RowInfo },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Cells },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Cols },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Filters },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_MergedRegions },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Name },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Names },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Rows },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Selections },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_SheetLayout },
+ { NS_gnumeric_gnm, XML_Sheet, NS_gnumeric_gnm, XML_Styles },
+ };
+
+ init_element_validator(rules, std::size(rules));
+
+ register_child(&m_cxt_cell);
+ register_child(&m_cxt_filter);
+ register_child(&m_cxt_names);
+ register_child(&m_cxt_styles);
+}
+
+gnumeric_sheet_context::~gnumeric_sheet_context() = default;
+
+xml_context_base* gnumeric_sheet_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Cells:
+ {
+ m_cxt_cell.reset(mp_sheet);
+ return &m_cxt_cell;
+ }
+ case XML_Filter:
+ {
+ m_cxt_filter.reset(mp_sheet);
+ return &m_cxt_filter;
+ }
+ case XML_Names:
+ {
+ m_cxt_names.reset();
+ return &m_cxt_names;
+ }
+ case XML_Styles:
+ {
+ m_cxt_styles.reset(m_sheet);
+ return &m_cxt_styles;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+void gnumeric_sheet_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Names:
+ {
+ assert(child == &m_cxt_names);
+ end_names();
+ break;
+ }
+ case XML_Styles:
+ {
+ assert(child == &m_cxt_styles);
+ end_styles();
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_sheet_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Font:
+ start_font(attrs);
+ break;
+ case XML_Merge:
+ m_merge_area = std::string_view{};
+ break;
+ case XML_Name:
+ start_name(attrs);
+ break;
+ case XML_Style:
+ start_style(attrs);
+ break;
+ case XML_StyleRegion:
+ start_style_region(attrs);
+ break;
+ case XML_ColInfo:
+ start_col(attrs);
+ break;
+ case XML_RowInfo:
+ start_row(attrs);
+ break;
+ case XML_Condition:
+ {
+ if (!m_region_data->contains_conditional_format)
+ {
+ m_region_data->contains_conditional_format = true;
+ end_style(false);
+ }
+ start_condition(attrs);
+ break;
+ }
+ case XML_Expression0:
+ case XML_Expression1:
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool gnumeric_sheet_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch(name)
+ {
+ case XML_Font:
+ end_font();
+ break;
+ case XML_Merge:
+ end_merge();
+ break;
+ case XML_Name:
+ end_name();
+ break;
+ case XML_Style:
+ {
+ xml_token_pair_t parent = get_parent_element();
+ if (parent.second == XML_Condition)
+ {
+ end_style(true);
+ }
+ else
+ {
+ // The conditional format entry contains a mandatory style element
+ // Therefore when we have a conditional format the end_style method
+ // is already called in start_element of the XML_Condition case.
+ if (!m_region_data->contains_conditional_format)
+ {
+ end_style(false);
+ }
+ }
+ break;
+ }
+ case XML_StyleRegion:
+ end_style_region();
+ break;
+ case XML_Condition:
+ end_condition();
+ break;
+ case XML_Expression0:
+ case XML_Expression1:
+ end_expression();
+ break;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void gnumeric_sheet_context::characters(std::string_view str, bool transient)
+{
+ const auto [ns, name] = get_current_element();
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Merge:
+ {
+ m_merge_area = transient ? intern(str) : str;
+ break;
+ }
+ case XML_Name:
+ {
+ m_name = transient ? intern(str) : str;
+ break;
+ }
+ default:
+ m_chars = transient ? intern(str) : str;
+ }
+ }
+ else
+ {
+ m_chars = transient ? intern(str) : str;
+ }
+}
+
+void gnumeric_sheet_context::reset(ss::sheet_t sheet)
+{
+ mp_sheet = nullptr;
+ mp_xf = nullptr;
+ m_sheet = sheet;
+
+ m_region_data.reset();
+
+ m_front_color.red = 0;
+ m_front_color.green = 0;
+ m_front_color.blue = 0;
+
+ m_chars = std::string_view{};
+ m_name = std::string_view{};
+ m_merge_area = std::string_view{};
+}
+
+std::vector<gnumeric_style> gnumeric_sheet_context::pop_styles()
+{
+ return std::move(m_styles);
+}
+
+void gnumeric_sheet_context::start_font(const xml_token_attrs_t& attrs)
+{
+ auto* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ auto* font_style = styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Unit:
+ {
+ double n = atoi(attr.value.data());
+ font_style->set_size(n);
+ break;
+ }
+ case XML_Bold:
+ {
+ bool b = atoi(attr.value.data()) != 0;
+ font_style->set_bold(b);
+ break;
+ }
+ case XML_Italic:
+ {
+ bool b = atoi(attr.value.data()) != 0;
+ font_style->set_italic(b);
+ break;
+ }
+ case XML_Underline:
+ {
+ int n = atoi(attr.value.data());
+ switch (n)
+ {
+ case 0:
+ font_style->set_underline(ss::underline_t::none);
+ break;
+ case 1:
+ font_style->set_underline(ss::underline_t::single_line);
+ break;
+ case 2:
+ font_style->set_underline(ss::underline_t::double_line);
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_sheet_context::start_col(const xml_token_attrs_t& attrs)
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_sheet_properties* sheet_props = mp_sheet->get_sheet_properties();
+ if (!sheet_props)
+ return;
+
+ long col = 0;
+ long col_span = 1;
+ double col_width = 0.0;
+ bool col_hidden = false;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_No:
+ {
+ col = to_long(attr.value);
+ break;
+ }
+ case XML_Unit:
+ {
+ col_width = to_double(attr.value);
+ break;
+ }
+ case XML_Count:
+ {
+ col_span = to_long(attr.value);
+ break;
+ }
+ case XML_Hidden:
+ {
+ col_hidden = to_bool(attr.value);
+ break;
+ }
+ }
+ }
+
+ sheet_props->set_column_width(col, col_span, col_width, length_unit_t::point);
+ sheet_props->set_column_hidden(col, col_span, col_hidden);
+}
+
+void gnumeric_sheet_context::start_row(const xml_token_attrs_t& attrs)
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_sheet_properties* sheet_props = mp_sheet->get_sheet_properties();
+ if (!sheet_props)
+ return;
+
+ long row = 0;
+ long row_span = 1;
+ double row_height = 0.0;
+ bool row_hidden = false;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_No:
+ {
+ row = to_long(attr.value);
+ break;
+ }
+ case XML_Unit:
+ {
+ row_height = to_double(attr.value);
+ break;
+ }
+ case XML_Count:
+ {
+ row_span = to_long(attr.value);
+ break;
+ }
+ case XML_Hidden:
+ {
+ row_hidden = to_bool(attr.value);
+ break;
+ }
+ }
+ }
+
+ for (long i = 0; i < row_span; ++i)
+ {
+ sheet_props->set_row_height(row + i, row_height, length_unit_t::point);
+ sheet_props->set_row_hidden(row + i, row_hidden);
+ }
+}
+
+void gnumeric_sheet_context::start_style(const xml_token_attrs_t& attrs)
+{
+ auto* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ auto* fill_style = styles->start_fill_style();
+ ENSURE_INTERFACE(fill_style, import_fill_style);
+
+ auto* cell_protection = styles->start_cell_protection();
+ ENSURE_INTERFACE(cell_protection, import_cell_protection);
+
+ auto* number_format = styles->start_number_format();
+ ENSURE_INTERFACE(number_format, import_number_format);
+
+ mp_xf = styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(mp_xf, import_xf);
+
+ bool fill_set = false;
+ bool protection_set = false;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Fore:
+ {
+ auto color = parse_gnumeric_rgb(attr.value);
+ if (!color)
+ break;
+
+ fill_style->set_fg_color(255, color->red, color->green, color->blue);
+ fill_set = true;
+ m_front_color = *color;
+ break;
+ }
+ case XML_Back:
+ {
+ auto color = parse_gnumeric_rgb(attr.value);
+ if (!color)
+ break;
+
+ fill_style->set_bg_color(255, color->red, color->green, color->blue);
+ fill_set = true;
+ break;
+ }
+ case XML_Hidden:
+ {
+ bool b = atoi(attr.value.data());
+ cell_protection->set_hidden(b);
+
+ protection_set = true;
+ break;
+ }
+ case XML_Locked:
+ {
+ bool b = atoi(attr.value.data());
+ cell_protection->set_locked(b);
+
+ protection_set = true;
+ break;
+ }
+ case XML_Format:
+ {
+ if (attr.value != "General")
+ {
+ number_format->set_code(attr.value);
+ std::size_t index = number_format->commit();
+ mp_xf->set_number_format(index);
+ }
+ break;
+ }
+ case XML_HAlign:
+ {
+ ss::hor_alignment_t hor_alignment = ss::hor_alignment_t::unknown;
+ if (attr.value == "GNM_HALIGN_CENTER")
+ hor_alignment = ss::hor_alignment_t::center;
+ else if (attr.value == "GNM_HALIGN_RIGHT")
+ hor_alignment = ss::hor_alignment_t::right;
+ else if (attr.value == "GNM_HALIGN_LEFT")
+ hor_alignment = ss::hor_alignment_t::left;
+ else if (attr.value == "GNM_HALIGN_JUSTIFY")
+ hor_alignment = ss::hor_alignment_t::justified;
+ else if (attr.value == "GNM_HALIGN_DISTRIBUTED")
+ hor_alignment = ss::hor_alignment_t::distributed;
+ else if (attr.value == "GNM_HALIGN_FILL")
+ hor_alignment = ss::hor_alignment_t::filled;
+
+ if (hor_alignment != ss::hor_alignment_t::unknown)
+ mp_xf->set_apply_alignment(true);
+ mp_xf->set_horizontal_alignment(hor_alignment);
+ break;
+ }
+ case XML_VAlign:
+ {
+ ss::ver_alignment_t ver_alignment = ss::ver_alignment_t::unknown;
+ if (attr.value == "GNM_VALIGN_BOTTOM")
+ ver_alignment = ss::ver_alignment_t::bottom;
+ else if (attr.value == "GNM_VALIGN_TOP")
+ ver_alignment = ss::ver_alignment_t::top;
+ else if (attr.value == "GNM_VALIGN_CENTER")
+ ver_alignment = ss::ver_alignment_t::middle;
+ else if (attr.value == "GNM_VALIGN_JUSTIFY")
+ ver_alignment = ss::ver_alignment_t::justified;
+ else if (attr.value == "GNM_VALIGN_DISTRIBUTED")
+ ver_alignment = ss::ver_alignment_t::distributed;
+
+ if (ver_alignment != ss::ver_alignment_t::unknown)
+ mp_xf->set_apply_alignment(true);
+ mp_xf->set_vertical_alignment(ver_alignment);
+ break;
+ }
+ }
+ }
+
+ if (fill_set)
+ {
+ size_t fill_id = fill_style->commit();
+ mp_xf->set_fill(fill_id);
+ }
+ if (protection_set)
+ {
+ size_t protection_id = cell_protection->commit();
+ mp_xf->set_protection(protection_id);
+ }
+}
+
+void gnumeric_sheet_context::start_style_region(const xml_token_attrs_t& attrs)
+{
+ m_region_data = style_region{};
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_startCol:
+ {
+ size_t n = atoi(attr.value.data());
+ m_region_data->start_col = n;
+ break;
+ }
+ case XML_startRow:
+ {
+ size_t n = atoi(attr.value.data());
+ m_region_data->start_row = n;
+ break;
+ }
+ case XML_endCol:
+ {
+ size_t n = atoi(attr.value.data());
+ m_region_data->end_col = n;
+ break;
+ }
+ case XML_endRow:
+ {
+ size_t n = atoi(attr.value.data());
+ m_region_data->end_row = n;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+}
+
+void gnumeric_sheet_context::start_condition(const xml_token_attrs_t& attrs)
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_conditional_format* cond_format =
+ mp_sheet->get_conditional_format();
+
+ if (!cond_format)
+ return;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Operator:
+ {
+ int val = atoi(attr.value.data());
+ ss::condition_operator_t op = get_condition_operator(val);
+ cond_format->set_operator(op);
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_sheet_context::start_name(const xml_token_attrs_t& /*attrs*/)
+{
+ m_name = std::string_view{};
+}
+
+void gnumeric_sheet_context::end_font()
+{
+ ss::iface::import_styles* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ auto* font_style = styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ font_style->set_color(0, m_front_color.red, m_front_color.green, m_front_color.blue);
+ font_style->set_name(m_chars);
+ size_t font_id = font_style->commit();
+
+ assert(mp_xf);
+ mp_xf->set_font(font_id);
+}
+
+void gnumeric_sheet_context::end_style(bool conditional_format)
+{
+ ss::iface::import_styles* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ assert(mp_xf);
+ size_t xf_id = mp_xf->commit();
+ if (!conditional_format)
+ {
+ m_region_data->xf_id = xf_id;
+ }
+ else if (mp_sheet)
+ {
+ ss::iface::import_conditional_format* cond_format =
+ mp_sheet->get_conditional_format();
+ if (cond_format)
+ {
+ cond_format->set_xf_id(xf_id);
+ }
+ }
+}
+
+void gnumeric_sheet_context::end_style_region()
+{
+ if (!mp_sheet)
+ return;
+
+ mp_sheet->set_format(m_region_data->start_row, m_region_data->start_col,
+ m_region_data->end_row, m_region_data->end_col, m_region_data->xf_id);
+
+ if (m_region_data->contains_conditional_format)
+ {
+ ss::iface::import_conditional_format* cond_format =
+ mp_sheet->get_conditional_format();
+ if (cond_format)
+ {
+ cond_format->set_range(m_region_data->start_row, m_region_data->start_col,
+ m_region_data->end_row, m_region_data->end_col);
+ cond_format->commit_format();
+ }
+ }
+ m_region_data.reset();
+}
+
+void gnumeric_sheet_context::end_condition()
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_conditional_format* cond_format =
+ mp_sheet->get_conditional_format();
+ if (cond_format)
+ {
+ cond_format->commit_entry();
+ }
+}
+
+void gnumeric_sheet_context::end_expression()
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_conditional_format* cond_format =
+ mp_sheet->get_conditional_format();
+ if (cond_format)
+ {
+ cond_format->set_formula(m_chars);
+ cond_format->commit_condition();
+ }
+}
+
+void gnumeric_sheet_context::end_merge()
+{
+ if (!mp_sheet || m_merge_area.empty())
+ return;
+
+ auto* sp = mp_sheet->get_sheet_properties();
+ if (!sp)
+ return;
+
+ auto* resolver = mp_factory->get_reference_resolver(ss::formula_ref_context_t::global);
+ if (!resolver)
+ return;
+
+ try
+ {
+ ss::range_t range = to_rc_range(resolver->resolve_range(m_merge_area));
+ sp->set_merge_cell_range(range);
+ }
+ catch (const invalid_arg_error& e)
+ {
+ std::ostringstream os;
+ os << "failed to parse a merged area '" << m_merge_area << "': " << e.what();
+ warn(os.str());
+ }
+}
+
+void gnumeric_sheet_context::end_name()
+{
+ if (m_name.empty())
+ return;
+
+ mp_sheet = mp_factory->get_sheet(m_name);
+ m_name = std::string_view{};
+}
+
+void gnumeric_sheet_context::end_names()
+{
+ if (!mp_sheet)
+ return;
+
+ ss::iface::import_named_expression* named_exp = mp_sheet->get_named_expression();
+ if (!named_exp)
+ return;
+
+ for (const auto& name : m_cxt_names.get_names())
+ {
+ try
+ {
+ named_exp->set_base_position(name.position);
+ named_exp->set_named_expression(name.name, name.value);
+ named_exp->commit();
+ }
+ catch (const std::exception& e)
+ {
+ std::ostringstream os;
+ os << "failed to commit a named expression named '" << name.name
+ << "': (reason='" << e.what() << "'; value='" << name.value << "')";
+ warn(os.str());
+ }
+ }
+}
+
+void gnumeric_sheet_context::end_styles()
+{
+ m_styles = m_cxt_styles.pop_styles();
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_sheet_context.hpp b/src/liborcus/gnumeric_sheet_context.hpp
new file mode 100644
index 0000000..70b8f89
--- /dev/null
+++ b/src/liborcus/gnumeric_sheet_context.hpp
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_GNUMERIC_SHEET_CONTEXT_HPP
+#define INCLUDED_ORCUS_GNUMERIC_SHEET_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "gnumeric_cell_context.hpp"
+#include "gnumeric_filter_context.hpp"
+#include "gnumeric_names_context.hpp"
+#include "gnumeric_styles_context.hpp"
+#include "gnumeric_types.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+#include <memory>
+#include <optional>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+class import_auto_filter;
+class import_xf;
+
+}}
+
+class gnumeric_sheet_context : public xml_context_base
+{
+ struct style_region
+ {
+ spreadsheet::row_t start_row = 0;
+ spreadsheet::row_t end_row = 0;
+ spreadsheet::col_t start_col = 0;
+ spreadsheet::col_t end_col = 0;
+
+ std::size_t xf_id = 0;
+ bool contains_conditional_format = false;
+ };
+
+public:
+ gnumeric_sheet_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+
+ virtual ~gnumeric_sheet_context() override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset(spreadsheet::sheet_t sheet);
+
+ std::vector<gnumeric_style> pop_styles();
+
+private:
+ void start_style_region(const xml_token_attrs_t& attrs);
+ void start_style(const xml_token_attrs_t& attrs);
+ void start_font(const xml_token_attrs_t& attrs);
+ void start_col(const xml_token_attrs_t& attrs);
+ void start_row(const xml_token_attrs_t& attrs);
+ void start_condition(const xml_token_attrs_t& attrs);
+ void start_name(const xml_token_attrs_t& attrs);
+
+ void end_style(bool conditional_format);
+ void end_font();
+ void end_style_region();
+ void end_condition();
+ void end_expression();
+ void end_merge();
+ void end_name();
+ void end_names();
+ void end_styles();
+
+private:
+ spreadsheet::iface::import_factory* mp_factory = nullptr;
+ spreadsheet::iface::import_sheet* mp_sheet = nullptr;
+ spreadsheet::iface::import_xf* mp_xf = nullptr;
+ spreadsheet::sheet_t m_sheet = -1;
+
+ std::optional<style_region> m_region_data;
+
+ spreadsheet::color_rgb_t m_front_color;
+
+ /**
+ * Used for temporary storage of characters
+ */
+ std::string_view m_chars;
+ std::string_view m_name;
+ std::string_view m_merge_area;
+
+ gnumeric_cell_context m_cxt_cell;
+ gnumeric_filter_context m_cxt_filter;
+ gnumeric_names_context m_cxt_names;
+ gnumeric_styles_context m_cxt_styles;
+
+ std::vector<gnumeric_style> m_styles;
+};
+
+} // namespace orcus
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_sheet_context_test.cpp b/src/liborcus/gnumeric_sheet_context_test.cpp
new file mode 100644
index 0000000..685357d
--- /dev/null
+++ b/src/liborcus/gnumeric_sheet_context_test.cpp
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_sheet_context.hpp"
+#include "gnumeric_tokens.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "mock_spreadsheet.hpp"
+#include "session_context.hpp"
+#include "orcus/types.hpp"
+
+#include <iostream>
+#include <string>
+#include <cstdlib>
+
+using namespace orcus;
+using namespace std;
+using namespace orcus::spreadsheet;
+using namespace orcus::spreadsheet::mock;
+
+class mock_sheet_properties : public import_sheet_properties
+{
+public:
+ virtual void set_column_width(col_t col, col_t col_span, double size, length_unit_t unit)
+ {
+ assert(col == 2);
+ assert(col_span == 1);
+ assert(size == 37.3);
+ assert(unit == length_unit_t::point);
+ }
+
+ virtual void set_column_hidden(col_t, col_t, bool)
+ {
+ }
+
+ virtual void set_row_height(row_t row, double size, length_unit_t unit)
+ {
+ assert(row == 4);
+ assert(size == 7.3);
+ assert(unit == length_unit_t::point);
+ }
+
+ virtual void set_row_hidden(row_t, bool)
+ {
+ }
+};
+
+class mock_sheet : public import_sheet
+{
+public:
+ virtual iface::import_sheet_properties* get_sheet_properties()
+ {
+ return &m_mock_properties;
+ }
+
+ virtual range_size_t get_sheet_size() const
+ {
+ range_size_t ret;
+ ret.rows = ret.columns = 0;
+ return ret;
+ }
+
+private:
+ mock_sheet_properties m_mock_properties;
+};
+
+class mock_factory : public import_factory
+{
+public:
+ virtual iface::import_sheet* get_sheet(std::string_view) override
+ {
+ return &m_mock_sheet;
+ }
+
+private:
+ mock_sheet m_mock_sheet;
+};
+
+void test_column_width()
+{
+ mock_factory factory;
+ session_context cxt;
+
+ orcus::gnumeric_sheet_context context(cxt, orcus::gnumeric_tokens, &factory);
+ context.reset(0);
+ orcus::xmlns_id_t ns = NS_gnumeric_gnm;
+ orcus::xml_token_t parent = XML_Sheet;
+ orcus::xml_token_attrs_t parent_attr;
+ context.start_element(ns, parent, parent_attr);
+ {
+ orcus::xml_token_t elem = XML_Name;
+ orcus::xml_token_attrs_t attrs;
+ context.start_element(ns, elem, attrs);
+ context.characters("test", false);
+ context.end_element(ns, elem);
+ }
+ {
+ orcus::xml_token_t elem = XML_ColInfo;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(ns, XML_No, "2", false));
+ attrs.push_back(xml_token_attr_t(ns, XML_Unit, "37.3", false));
+ attrs.push_back(xml_token_attr_t(ns, XML_Unit, "37.3", false));
+ context.start_element(ns, elem, attrs);
+ context.end_element(ns, elem);
+ }
+ context.end_element(ns, parent);
+}
+
+int main()
+{
+ test_column_width();
+
+ return EXIT_SUCCESS;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_styles_context.cpp b/src/liborcus/gnumeric_styles_context.cpp
new file mode 100644
index 0000000..b2c6058
--- /dev/null
+++ b/src/liborcus/gnumeric_styles_context.cpp
@@ -0,0 +1,342 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_styles_context.hpp"
+#include "gnumeric_token_constants.hpp"
+#include "gnumeric_namespace_types.hpp"
+
+#include <orcus/measurement.hpp>
+#include <mdds/sorted_string_map.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace hor_align {
+
+using map_type = mdds::sorted_string_map<ss::hor_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "GNM_HALIGN_CENTER", ss::hor_alignment_t::center },
+ { "GNM_HALIGN_DISTRIBUTED", ss::hor_alignment_t::distributed },
+ { "GNM_HALIGN_GENERAL", ss::hor_alignment_t::unknown },
+ { "GNM_HALIGN_JUSTIFY", ss::hor_alignment_t::justified },
+ { "GNM_HALIGN_LEFT", ss::hor_alignment_t::left },
+ { "GNM_HALIGN_RIGHT", ss::hor_alignment_t::right },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::hor_alignment_t::unknown);
+ return mt;
+}
+
+} // namespace hor_align
+
+namespace ver_align {
+
+using map_type = mdds::sorted_string_map<ss::ver_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "GNM_VALIGN_BOTTOM", ss::ver_alignment_t::bottom },
+ { "GNM_VALIGN_CENTER", ss::ver_alignment_t::middle },
+ { "GNM_VALIGN_DISTRIBUTED", ss::ver_alignment_t::distributed },
+ { "GNM_VALIGN_JUSTIFY", ss::ver_alignment_t::justified },
+ { "GNM_VALIGN_TOP", ss::ver_alignment_t::top },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::ver_alignment_t::unknown);
+ return mt;
+}
+
+} // namespace ver_align
+
+ss::fill_pattern_t to_fill_pattern(std::size_t v)
+{
+ constexpr ss::fill_pattern_t patterns[] = {
+ ss::fill_pattern_t::none,
+ ss::fill_pattern_t::solid,
+ // TODO: add more as we establish more mapping rules
+ };
+
+ return (v < std::size(patterns)) ? patterns[v] : ss::fill_pattern_t::none;
+}
+
+gnumeric_style::border_type parse_border_attributes(const xml_token_attrs_t& attrs)
+{
+ gnumeric_style::border_type ret;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == XMLNS_UNKNOWN_ID)
+ {
+ switch (attr.name)
+ {
+ case XML_Style:
+ {
+ const char* p_end = nullptr;
+ long v = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ ret.style = static_cast<gnumeric_border_type>(v);
+ break;
+ }
+ case XML_Color:
+ {
+ ret.color = parse_gnumeric_rgb(attr.value);
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+} // anonymous namespace
+
+gnumeric_styles_context::gnumeric_styles_context(
+ session_context& session_cxt, const tokens& tokens,
+ ss::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_gnumeric_gnm, XML_Styles }, // root element
+ { NS_gnumeric_gnm, XML_Style, NS_gnumeric_gnm, XML_Font },
+ { NS_gnumeric_gnm, XML_Style, NS_gnumeric_gnm, XML_StyleBorder },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Bottom },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Diagonal },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Left },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Rev_Diagonal },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Right },
+ { NS_gnumeric_gnm, XML_StyleBorder, NS_gnumeric_gnm, XML_Top },
+ { NS_gnumeric_gnm, XML_StyleRegion, NS_gnumeric_gnm, XML_Style },
+ { NS_gnumeric_gnm, XML_Styles, NS_gnumeric_gnm, XML_StyleRegion },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+gnumeric_styles_context::~gnumeric_styles_context() = default;
+
+void gnumeric_styles_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_StyleRegion:
+ start_style_region(attrs);
+ break;
+ case XML_StyleBorder:
+ break;
+ case XML_Style:
+ start_style(attrs);
+ break;
+ case XML_Top:
+ {
+ m_current_style.border_top = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Bottom:
+ {
+ m_current_style.border_bottom = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Left:
+ {
+ m_current_style.border_left = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Right:
+ {
+ m_current_style.border_right = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Diagonal:
+ {
+ m_current_style.border_bl_tr = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Rev_Diagonal:
+ {
+ m_current_style.border_br_tl = parse_border_attributes(attrs);
+ break;
+ }
+ case XML_Font:
+ start_font(attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool gnumeric_styles_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_StyleRegion:
+ end_style_region();
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void gnumeric_styles_context::characters(std::string_view str, bool transient)
+{
+ const auto [ns, name] = get_current_element();
+
+ if (ns == NS_gnumeric_gnm)
+ {
+ switch (name)
+ {
+ case XML_Font:
+ {
+ if (transient)
+ str = intern(str);
+ m_current_style.font_name = str;
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_styles_context::reset(ss::sheet_t sheet)
+{
+ m_sheet = sheet;
+ m_styles.clear();
+ m_current_style = gnumeric_style{};
+}
+
+std::vector<gnumeric_style> gnumeric_styles_context::pop_styles()
+{
+ return std::move(m_styles);
+}
+
+void gnumeric_styles_context::start_style_region(const std::vector<xml_token_attr_t>& attrs)
+{
+ m_current_style = gnumeric_style{};
+ m_current_style.sheet = m_sheet;
+
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_startCol:
+ m_current_style.region.first.column = to_long(attr.value);
+ break;
+ case XML_startRow:
+ m_current_style.region.first.row = to_long(attr.value);
+ break;
+ case XML_endCol:
+ m_current_style.region.last.column = to_long(attr.value);
+ break;
+ case XML_endRow:
+ m_current_style.region.last.row = to_long(attr.value);
+ break;
+ }
+ }
+}
+
+void gnumeric_styles_context::start_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_HAlign:
+ m_current_style.hor_align = hor_align::get().find(attr.value);
+ break;
+ case XML_VAlign:
+ m_current_style.ver_align = ver_align::get().find(attr.value);
+ break;
+ case XML_WrapText:
+ m_current_style.wrap_text = to_bool(attr.value);
+ break;
+ case XML_Fore:
+ m_current_style.fore = parse_gnumeric_rgb(attr.value);
+ break;
+ case XML_Back:
+ m_current_style.back = parse_gnumeric_rgb(attr.value);
+ break;
+ case XML_PatternColor:
+ m_current_style.pattern_color = parse_gnumeric_rgb(attr.value);
+ break;
+ case XML_Shade:
+ m_current_style.pattern = to_fill_pattern(to_long(attr.value));
+ break;
+ case XML_Format:
+ {
+ auto v = attr.transient ? intern(attr.value) : attr.value;
+ m_current_style.number_format = v;
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_styles_context::start_font(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_Unit:
+ {
+ const char* p_end = nullptr;
+ double v = to_double(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ m_current_style.font_unit = v;
+ break;
+ }
+ case XML_Bold:
+ m_current_style.bold = to_bool(attr.value);
+ break;
+ case XML_Italic:
+ m_current_style.italic = to_bool(attr.value);
+ break;
+ case XML_Underline:
+ m_current_style.underline = to_bool(attr.value);
+ break;
+ case XML_StrikeThrough:
+ m_current_style.strikethrough = to_bool(attr.value);
+ break;
+ case XML_Script:
+ {
+ auto v = to_long(attr.value);
+ m_current_style.script = static_cast<gnumeric_script_type>(v);
+ break;
+ }
+ }
+ }
+}
+
+void gnumeric_styles_context::end_style_region()
+{
+ if (m_current_style.valid())
+ m_styles.push_back(m_current_style);
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_styles_context.hpp b/src/liborcus/gnumeric_styles_context.hpp
new file mode 100644
index 0000000..1675b48
--- /dev/null
+++ b/src/liborcus/gnumeric_styles_context.hpp
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+#include "gnumeric_types.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+
+}}
+
+class gnumeric_styles_context : public xml_context_base
+{
+public:
+ gnumeric_styles_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory* factory);
+ virtual ~gnumeric_styles_context() override;
+
+ virtual void start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset(spreadsheet::sheet_t sheet);
+
+ std::vector<gnumeric_style> pop_styles();
+
+private:
+ void start_style_region(const std::vector<xml_token_attr_t>& attrs);
+ void start_style(const std::vector<xml_token_attr_t>& attrs);
+ void start_font(const std::vector<xml_token_attr_t>& attrs);
+
+ void end_style_region();
+
+private:
+ spreadsheet::iface::import_factory* mp_factory = nullptr;
+ spreadsheet::sheet_t m_sheet = -1;
+
+ std::vector<gnumeric_style> m_styles;
+ gnumeric_style m_current_style;
+};
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_token_constants.hpp b/src/liborcus/gnumeric_token_constants.hpp
new file mode 100644
index 0000000..7e94fb5
--- /dev/null
+++ b/src/liborcus/gnumeric_token_constants.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_GNUMERIC_TOKEN_CONSTANTS_HPP__
+#define __ORCUS_GNUMERIC_TOKEN_CONSTANTS_HPP__
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+#include "gnumeric_token_constants.inl"
+
+}
+
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_token_constants.inl b/src/liborcus/gnumeric_token_constants.inl
new file mode 100644
index 0000000..4043f22
--- /dev/null
+++ b/src/liborcus/gnumeric_token_constants.inl
@@ -0,0 +1,258 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const xml_token_t XML_AllowBlank = 1;
+const xml_token_t XML_AnswerR = 2;
+const xml_token_t XML_Area = 3;
+const xml_token_t XML_ArrowShapeA = 4;
+const xml_token_t XML_ArrowShapeB = 5;
+const xml_token_t XML_ArrowShapeC = 6;
+const xml_token_t XML_Attribute = 7;
+const xml_token_t XML_Attributes = 8;
+const xml_token_t XML_Author = 9;
+const xml_token_t XML_AutoScale = 10;
+const xml_token_t XML_Back = 11;
+const xml_token_t XML_Bold = 12;
+const xml_token_t XML_Bottom = 13;
+const xml_token_t XML_Calculation = 14;
+const xml_token_t XML_Cell = 15;
+const xml_token_t XML_CellComment = 16;
+const xml_token_t XML_Cells = 17;
+const xml_token_t XML_CellsStr = 18;
+const xml_token_t XML_Col = 19;
+const xml_token_t XML_ColInfo = 20;
+const xml_token_t XML_Collapsed = 21;
+const xml_token_t XML_Color = 22;
+const xml_token_t XML_Cols = 23;
+const xml_token_t XML_Comment = 24;
+const xml_token_t XML_Condition = 25;
+const xml_token_t XML_Constr = 26;
+const xml_token_t XML_Content = 27;
+const xml_token_t XML_Count = 28;
+const xml_token_t XML_CursorCol = 29;
+const xml_token_t XML_CursorRow = 30;
+const xml_token_t XML_DateConvention = 31;
+const xml_token_t XML_DefaultSizePts = 32;
+const xml_token_t XML_Diagonal = 33;
+const xml_token_t XML_Direction = 34;
+const xml_token_t XML_Discr = 35;
+const xml_token_t XML_DisplayFormulas = 36;
+const xml_token_t XML_DisplayOutlines = 37;
+const xml_token_t XML_EnableIteration = 38;
+const xml_token_t XML_Epoch = 39;
+const xml_token_t XML_ExprConvention = 40;
+const xml_token_t XML_ExprID = 41;
+const xml_token_t XML_Expression0 = 42;
+const xml_token_t XML_Expression1 = 43;
+const xml_token_t XML_Field = 44;
+const xml_token_t XML_FillColor = 45;
+const xml_token_t XML_Filter = 46;
+const xml_token_t XML_Filters = 47;
+const xml_token_t XML_FloatDigits = 48;
+const xml_token_t XML_FloatRadix = 49;
+const xml_token_t XML_Font = 50;
+const xml_token_t XML_Footer = 51;
+const xml_token_t XML_Fore = 52;
+const xml_token_t XML_Format = 53;
+const xml_token_t XML_FreezePanes = 54;
+const xml_token_t XML_FrozenTopLeft = 55;
+const xml_token_t XML_Full = 56;
+const xml_token_t XML_Geometry = 57;
+const xml_token_t XML_GogObject = 58;
+const xml_token_t XML_GridColor = 59;
+const xml_token_t XML_HAlign = 60;
+const xml_token_t XML_HardSize = 61;
+const xml_token_t XML_Header = 62;
+const xml_token_t XML_Height = 63;
+const xml_token_t XML_Hidden = 64;
+const xml_token_t XML_HideColHeader = 65;
+const xml_token_t XML_HideGrid = 66;
+const xml_token_t XML_HideRowHeader = 67;
+const xml_token_t XML_HideZero = 68;
+const xml_token_t XML_HyperLink = 69;
+const xml_token_t XML_Inc = 70;
+const xml_token_t XML_Indent = 71;
+const xml_token_t XML_Index = 72;
+const xml_token_t XML_Input = 73;
+const xml_token_t XML_InputMessage = 74;
+const xml_token_t XML_Inputs = 75;
+const xml_token_t XML_Italic = 76;
+const xml_token_t XML_IterationTolerance = 77;
+const xml_token_t XML_Label = 78;
+const xml_token_t XML_LabelFormat = 79;
+const xml_token_t XML_Lcol = 80;
+const xml_token_t XML_Left = 81;
+const xml_token_t XML_LimitsR = 82;
+const xml_token_t XML_Locked = 83;
+const xml_token_t XML_Lrow = 84;
+const xml_token_t XML_Major = 85;
+const xml_token_t XML_ManualRecalc = 86;
+const xml_token_t XML_MarginA = 87;
+const xml_token_t XML_MarginB = 88;
+const xml_token_t XML_Margins = 89;
+const xml_token_t XML_Max = 90;
+const xml_token_t XML_MaxCol = 91;
+const xml_token_t XML_MaxIter = 92;
+const xml_token_t XML_MaxIterations = 93;
+const xml_token_t XML_MaxRow = 94;
+const xml_token_t XML_MaxTime = 95;
+const xml_token_t XML_Merge = 96;
+const xml_token_t XML_MergedRegions = 97;
+const xml_token_t XML_Message = 98;
+const xml_token_t XML_Middle = 99;
+const xml_token_t XML_Min = 100;
+const xml_token_t XML_Minor = 101;
+const xml_token_t XML_ModelType = 102;
+const xml_token_t XML_Name = 103;
+const xml_token_t XML_Names = 104;
+const xml_token_t XML_No = 105;
+const xml_token_t XML_NonNeg = 106;
+const xml_token_t XML_ObjectAnchorType = 107;
+const xml_token_t XML_ObjectBound = 108;
+const xml_token_t XML_ObjectOffset = 109;
+const xml_token_t XML_Objects = 110;
+const xml_token_t XML_Op0 = 111;
+const xml_token_t XML_Op1 = 112;
+const xml_token_t XML_Operator = 113;
+const xml_token_t XML_Orient = 114;
+const xml_token_t XML_OutlineColor = 115;
+const xml_token_t XML_OutlineLevel = 116;
+const xml_token_t XML_OutlineSymbolsBelow = 117;
+const xml_token_t XML_OutlineSymbolsRight = 118;
+const xml_token_t XML_Output = 119;
+const xml_token_t XML_Page = 120;
+const xml_token_t XML_PatternColor = 121;
+const xml_token_t XML_PerformR = 122;
+const xml_token_t XML_Points = 123;
+const xml_token_t XML_PrefUnit = 124;
+const xml_token_t XML_Print = 125;
+const xml_token_t XML_PrintInformation = 126;
+const xml_token_t XML_ProblemType = 127;
+const xml_token_t XML_ProgramR = 128;
+const xml_token_t XML_Protected = 129;
+const xml_token_t XML_RTL_Layout = 130;
+const xml_token_t XML_Rcol = 131;
+const xml_token_t XML_Rev_Diagonal = 132;
+const xml_token_t XML_Right = 133;
+const xml_token_t XML_Rotation = 134;
+const xml_token_t XML_Row = 135;
+const xml_token_t XML_RowInfo = 136;
+const xml_token_t XML_Rows = 137;
+const xml_token_t XML_Rrow = 138;
+const xml_token_t XML_Scale = 139;
+const xml_token_t XML_Scenario = 140;
+const xml_token_t XML_Scenarios = 141;
+const xml_token_t XML_Script = 142;
+const xml_token_t XML_SelectedTab = 143;
+const xml_token_t XML_Selection = 144;
+const xml_token_t XML_Selections = 145;
+const xml_token_t XML_SensitivityR = 146;
+const xml_token_t XML_Shade = 147;
+const xml_token_t XML_Sheet = 148;
+const xml_token_t XML_SheetLayout = 149;
+const xml_token_t XML_SheetName = 150;
+const xml_token_t XML_SheetNameIndex = 151;
+const xml_token_t XML_SheetObjectBonobo = 152;
+const xml_token_t XML_SheetObjectFilled = 153;
+const xml_token_t XML_SheetObjectGraph = 154;
+const xml_token_t XML_SheetObjectImage = 155;
+const xml_token_t XML_SheetWidgetButton = 156;
+const xml_token_t XML_SheetWidgetCheckbox = 157;
+const xml_token_t XML_SheetWidgetCombo = 158;
+const xml_token_t XML_SheetWidgetFrame = 159;
+const xml_token_t XML_SheetWidgetLabel = 160;
+const xml_token_t XML_SheetWidgetList = 161;
+const xml_token_t XML_SheetWidgetScrollbar = 162;
+const xml_token_t XML_SheetWidgetSlider = 163;
+const xml_token_t XML_SheetWidgetSpinbutton = 164;
+const xml_token_t XML_SheetWidgetToggleButton = 165;
+const xml_token_t XML_Sheets = 166;
+const xml_token_t XML_ShowIter = 167;
+const xml_token_t XML_ShrinkToFit = 168;
+const xml_token_t XML_Solver = 169;
+const xml_token_t XML_StrikeThrough = 170;
+const xml_token_t XML_Style = 171;
+const xml_token_t XML_StyleBorder = 172;
+const xml_token_t XML_StyleRegion = 173;
+const xml_token_t XML_Styles = 174;
+const xml_token_t XML_TabColor = 175;
+const xml_token_t XML_TabTextColor = 176;
+const xml_token_t XML_TargetCol = 177;
+const xml_token_t XML_TargetRow = 178;
+const xml_token_t XML_Text = 179;
+const xml_token_t XML_TextFormat = 180;
+const xml_token_t XML_Title = 181;
+const xml_token_t XML_Top = 182;
+const xml_token_t XML_TopLeft = 183;
+const xml_token_t XML_Type = 184;
+const xml_token_t XML_UIData = 185;
+const xml_token_t XML_Underline = 186;
+const xml_token_t XML_UnfrozenTopLeft = 187;
+const xml_token_t XML_Unit = 188;
+const xml_token_t XML_UseDropdown = 189;
+const xml_token_t XML_VAlign = 190;
+const xml_token_t XML_Validation = 191;
+const xml_token_t XML_Value = 192;
+const xml_token_t XML_Value0 = 193;
+const xml_token_t XML_Value1 = 194;
+const xml_token_t XML_ValueFormat = 195;
+const xml_token_t XML_ValueType = 196;
+const xml_token_t XML_ValueType0 = 197;
+const xml_token_t XML_ValueType1 = 198;
+const xml_token_t XML_Version = 199;
+const xml_token_t XML_Visibility = 200;
+const xml_token_t XML_Width = 201;
+const xml_token_t XML_Workbook = 202;
+const xml_token_t XML_WrapText = 203;
+const xml_token_t XML_Zoom = 204;
+const xml_token_t XML_bottom = 205;
+const xml_token_t XML_break = 206;
+const xml_token_t XML_cols = 207;
+const xml_token_t XML_count = 208;
+const xml_token_t XML_crop_bottom = 209;
+const xml_token_t XML_crop_left = 210;
+const xml_token_t XML_crop_right = 211;
+const xml_token_t XML_crop_top = 212;
+const xml_token_t XML_data = 213;
+const xml_token_t XML_dimension = 214;
+const xml_token_t XML_do_not_print = 215;
+const xml_token_t XML_draft = 216;
+const xml_token_t XML_endCol = 217;
+const xml_token_t XML_endRow = 218;
+const xml_token_t XML_even_if_only_styles = 219;
+const xml_token_t XML_footer = 220;
+const xml_token_t XML_grid = 221;
+const xml_token_t XML_hPageBreaks = 222;
+const xml_token_t XML_hcenter = 223;
+const xml_token_t XML_header = 224;
+const xml_token_t XML_id = 225;
+const xml_token_t XML_image_type = 226;
+const xml_token_t XML_items = 227;
+const xml_token_t XML_left = 228;
+const xml_token_t XML_monochrome = 229;
+const xml_token_t XML_name = 230;
+const xml_token_t XML_order = 231;
+const xml_token_t XML_orientation = 232;
+const xml_token_t XML_paper = 233;
+const xml_token_t XML_percentage = 234;
+const xml_token_t XML_pos = 235;
+const xml_token_t XML_position = 236;
+const xml_token_t XML_print_to_uri = 237;
+const xml_token_t XML_print_range = 238;
+const xml_token_t XML_property = 239;
+const xml_token_t XML_repeat_left = 240;
+const xml_token_t XML_repeat_top = 241;
+const xml_token_t XML_right = 242;
+const xml_token_t XML_role = 243;
+const xml_token_t XML_rows = 244;
+const xml_token_t XML_size_bytes = 245;
+const xml_token_t XML_startCol = 246;
+const xml_token_t XML_startRow = 247;
+const xml_token_t XML_target = 248;
+const xml_token_t XML_tip = 249;
+const xml_token_t XML_titles = 250;
+const xml_token_t XML_top = 251;
+const xml_token_t XML_type = 252;
+const xml_token_t XML_vPageBreaks = 253;
+const xml_token_t XML_value = 254;
+const xml_token_t XML_vcenter = 255;
+
diff --git a/src/liborcus/gnumeric_tokens.cpp b/src/liborcus/gnumeric_tokens.cpp
new file mode 100644
index 0000000..99eaa1d
--- /dev/null
+++ b/src/liborcus/gnumeric_tokens.cpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_tokens.hpp"
+
+namespace orcus {
+
+namespace {
+
+#include "gnumeric_tokens.inl"
+
+}
+
+tokens gnumeric_tokens = tokens(token_names, token_name_count);
+
+}/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_tokens.hpp b/src/liborcus/gnumeric_tokens.hpp
new file mode 100644
index 0000000..2ce6016
--- /dev/null
+++ b/src/liborcus/gnumeric_tokens.hpp
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_GNUMERIC_TOKENS_HPP__
+#define __ORCUS_GNUMERIC_TOKENS_HPP__
+
+#include "orcus/tokens.hpp"
+
+namespace orcus {
+
+/**
+ * Singleton instance containing all GNUMERIC tokens.
+ */
+extern tokens gnumeric_tokens;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_tokens.inl b/src/liborcus/gnumeric_tokens.inl
new file mode 100644
index 0000000..297065b
--- /dev/null
+++ b/src/liborcus/gnumeric_tokens.inl
@@ -0,0 +1,263 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const char* token_names[] = {
+ "??", // 0
+ "AllowBlank", // 1
+ "AnswerR", // 2
+ "Area", // 3
+ "ArrowShapeA", // 4
+ "ArrowShapeB", // 5
+ "ArrowShapeC", // 6
+ "Attribute", // 7
+ "Attributes", // 8
+ "Author", // 9
+ "AutoScale", // 10
+ "Back", // 11
+ "Bold", // 12
+ "Bottom", // 13
+ "Calculation", // 14
+ "Cell", // 15
+ "CellComment", // 16
+ "Cells", // 17
+ "CellsStr", // 18
+ "Col", // 19
+ "ColInfo", // 20
+ "Collapsed", // 21
+ "Color", // 22
+ "Cols", // 23
+ "Comment", // 24
+ "Condition", // 25
+ "Constr", // 26
+ "Content", // 27
+ "Count", // 28
+ "CursorCol", // 29
+ "CursorRow", // 30
+ "DateConvention", // 31
+ "DefaultSizePts", // 32
+ "Diagonal", // 33
+ "Direction", // 34
+ "Discr", // 35
+ "DisplayFormulas", // 36
+ "DisplayOutlines", // 37
+ "EnableIteration", // 38
+ "Epoch", // 39
+ "ExprConvention", // 40
+ "ExprID", // 41
+ "Expression0", // 42
+ "Expression1", // 43
+ "Field", // 44
+ "FillColor", // 45
+ "Filter", // 46
+ "Filters", // 47
+ "FloatDigits", // 48
+ "FloatRadix", // 49
+ "Font", // 50
+ "Footer", // 51
+ "Fore", // 52
+ "Format", // 53
+ "FreezePanes", // 54
+ "FrozenTopLeft", // 55
+ "Full", // 56
+ "Geometry", // 57
+ "GogObject", // 58
+ "GridColor", // 59
+ "HAlign", // 60
+ "HardSize", // 61
+ "Header", // 62
+ "Height", // 63
+ "Hidden", // 64
+ "HideColHeader", // 65
+ "HideGrid", // 66
+ "HideRowHeader", // 67
+ "HideZero", // 68
+ "HyperLink", // 69
+ "Inc", // 70
+ "Indent", // 71
+ "Index", // 72
+ "Input", // 73
+ "InputMessage", // 74
+ "Inputs", // 75
+ "Italic", // 76
+ "IterationTolerance", // 77
+ "Label", // 78
+ "LabelFormat", // 79
+ "Lcol", // 80
+ "Left", // 81
+ "LimitsR", // 82
+ "Locked", // 83
+ "Lrow", // 84
+ "Major", // 85
+ "ManualRecalc", // 86
+ "MarginA", // 87
+ "MarginB", // 88
+ "Margins", // 89
+ "Max", // 90
+ "MaxCol", // 91
+ "MaxIter", // 92
+ "MaxIterations", // 93
+ "MaxRow", // 94
+ "MaxTime", // 95
+ "Merge", // 96
+ "MergedRegions", // 97
+ "Message", // 98
+ "Middle", // 99
+ "Min", // 100
+ "Minor", // 101
+ "ModelType", // 102
+ "Name", // 103
+ "Names", // 104
+ "No", // 105
+ "NonNeg", // 106
+ "ObjectAnchorType", // 107
+ "ObjectBound", // 108
+ "ObjectOffset", // 109
+ "Objects", // 110
+ "Op0", // 111
+ "Op1", // 112
+ "Operator", // 113
+ "Orient", // 114
+ "OutlineColor", // 115
+ "OutlineLevel", // 116
+ "OutlineSymbolsBelow", // 117
+ "OutlineSymbolsRight", // 118
+ "Output", // 119
+ "Page", // 120
+ "PatternColor", // 121
+ "PerformR", // 122
+ "Points", // 123
+ "PrefUnit", // 124
+ "Print", // 125
+ "PrintInformation", // 126
+ "ProblemType", // 127
+ "ProgramR", // 128
+ "Protected", // 129
+ "RTL_Layout", // 130
+ "Rcol", // 131
+ "Rev-Diagonal", // 132
+ "Right", // 133
+ "Rotation", // 134
+ "Row", // 135
+ "RowInfo", // 136
+ "Rows", // 137
+ "Rrow", // 138
+ "Scale", // 139
+ "Scenario", // 140
+ "Scenarios", // 141
+ "Script", // 142
+ "SelectedTab", // 143
+ "Selection", // 144
+ "Selections", // 145
+ "SensitivityR", // 146
+ "Shade", // 147
+ "Sheet", // 148
+ "SheetLayout", // 149
+ "SheetName", // 150
+ "SheetNameIndex", // 151
+ "SheetObjectBonobo", // 152
+ "SheetObjectFilled", // 153
+ "SheetObjectGraph", // 154
+ "SheetObjectImage", // 155
+ "SheetWidgetButton", // 156
+ "SheetWidgetCheckbox", // 157
+ "SheetWidgetCombo", // 158
+ "SheetWidgetFrame", // 159
+ "SheetWidgetLabel", // 160
+ "SheetWidgetList", // 161
+ "SheetWidgetScrollbar", // 162
+ "SheetWidgetSlider", // 163
+ "SheetWidgetSpinbutton", // 164
+ "SheetWidgetToggleButton", // 165
+ "Sheets", // 166
+ "ShowIter", // 167
+ "ShrinkToFit", // 168
+ "Solver", // 169
+ "StrikeThrough", // 170
+ "Style", // 171
+ "StyleBorder", // 172
+ "StyleRegion", // 173
+ "Styles", // 174
+ "TabColor", // 175
+ "TabTextColor", // 176
+ "TargetCol", // 177
+ "TargetRow", // 178
+ "Text", // 179
+ "TextFormat", // 180
+ "Title", // 181
+ "Top", // 182
+ "TopLeft", // 183
+ "Type", // 184
+ "UIData", // 185
+ "Underline", // 186
+ "UnfrozenTopLeft", // 187
+ "Unit", // 188
+ "UseDropdown", // 189
+ "VAlign", // 190
+ "Validation", // 191
+ "Value", // 192
+ "Value0", // 193
+ "Value1", // 194
+ "ValueFormat", // 195
+ "ValueType", // 196
+ "ValueType0", // 197
+ "ValueType1", // 198
+ "Version", // 199
+ "Visibility", // 200
+ "Width", // 201
+ "Workbook", // 202
+ "WrapText", // 203
+ "Zoom", // 204
+ "bottom", // 205
+ "break", // 206
+ "cols", // 207
+ "count", // 208
+ "crop-bottom", // 209
+ "crop-left", // 210
+ "crop-right", // 211
+ "crop-top", // 212
+ "data", // 213
+ "dimension", // 214
+ "do_not_print", // 215
+ "draft", // 216
+ "endCol", // 217
+ "endRow", // 218
+ "even_if_only_styles", // 219
+ "footer", // 220
+ "grid", // 221
+ "hPageBreaks", // 222
+ "hcenter", // 223
+ "header", // 224
+ "id", // 225
+ "image-type", // 226
+ "items", // 227
+ "left", // 228
+ "monochrome", // 229
+ "name", // 230
+ "order", // 231
+ "orientation", // 232
+ "paper", // 233
+ "percentage", // 234
+ "pos", // 235
+ "position", // 236
+ "print-to-uri", // 237
+ "print_range", // 238
+ "property", // 239
+ "repeat_left", // 240
+ "repeat_top", // 241
+ "right", // 242
+ "role", // 243
+ "rows", // 244
+ "size-bytes", // 245
+ "startCol", // 246
+ "startRow", // 247
+ "target", // 248
+ "tip", // 249
+ "titles", // 250
+ "top", // 251
+ "type", // 252
+ "vPageBreaks", // 253
+ "value", // 254
+ "vcenter" // 255
+};
+
+size_t token_name_count = 256;
+
diff --git a/src/liborcus/gnumeric_types.cpp b/src/liborcus/gnumeric_types.cpp
new file mode 100644
index 0000000..c02627a
--- /dev/null
+++ b/src/liborcus/gnumeric_types.cpp
@@ -0,0 +1,174 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_types.hpp"
+#include "number_utils.hpp"
+
+#include <mdds/sorted_string_map.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace value_format_type {
+
+using map_type = mdds::sorted_string_map<gnumeric_value_format_type, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "bold", gnumeric_value_format_type::bold },
+ { "color", gnumeric_value_format_type::color },
+ { "family", gnumeric_value_format_type::family },
+ { "italic", gnumeric_value_format_type::italic },
+ { "size", gnumeric_value_format_type::size },
+ { "strikethrough", gnumeric_value_format_type::strikethrough },
+ { "subscript", gnumeric_value_format_type::subscript },
+ { "superscript", gnumeric_value_format_type::superscript },
+ { "underline", gnumeric_value_format_type::underline },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), gnumeric_value_format_type::unknown);
+ return mt;
+}
+
+} // namespace value_format_type
+
+ss::border_style_t to_standard_type(gnumeric_border_type v)
+{
+ switch (v)
+ {
+ case gnumeric_border_type::border_none:
+ return ss::border_style_t::none;
+ case gnumeric_border_type::border_thin:
+ return ss::border_style_t::thin;
+ case gnumeric_border_type::border_medium:
+ return ss::border_style_t::medium;
+ case gnumeric_border_type::border_dashed:
+ return ss::border_style_t::dashed;
+ case gnumeric_border_type::border_dotted:
+ return ss::border_style_t::dotted;
+ case gnumeric_border_type::border_thick:
+ return ss::border_style_t::thick;
+ case gnumeric_border_type::border_double:
+ return ss::border_style_t::double_border;
+ case gnumeric_border_type::border_hair:
+ return ss::border_style_t::hair;
+ case gnumeric_border_type::border_medium_dash:
+ return ss::border_style_t::medium_dashed;
+ case gnumeric_border_type::border_dash_dot:
+ return ss::border_style_t::dash_dot;
+ case gnumeric_border_type::border_medium_dash_dot:
+ return ss::border_style_t::medium_dash_dot;
+ case gnumeric_border_type::border_dash_dot_dot:
+ return ss::border_style_t::dash_dot_dot;
+ case gnumeric_border_type::border_medium_dash_dot_dot:
+ return ss::border_style_t::medium_dash_dot_dot;
+ case gnumeric_border_type::border_slanted_dash_dot:
+ return ss::border_style_t::slant_dash_dot;
+ }
+
+ return ss::border_style_t::unknown;
+}
+
+gnumeric_value_format_type to_gnumeric_value_format_type(std::string_view s)
+{
+ return value_format_type::get().find(s);
+}
+
+void gnumeric_named_exp::reset()
+{
+ name = std::string_view{};
+ value = std::string_view{};
+ position = {0, 0, 0};
+}
+
+bool gnumeric_style::valid() const
+{
+ if (sheet < 0)
+ return false;
+
+ if (region.first.column < 0 || region.first.row < 0 || region.last.column < 0 || region.last.row < 0)
+ return false;
+
+ return true;
+}
+
+std::optional<spreadsheet::color_rgb_t> parse_gnumeric_rgb(std::string_view v)
+{
+ ss::color_rgb_t color;
+
+ auto pos = v.find(':');
+ if (pos == v.npos)
+ return {};
+
+ std::string_view seg = v.substr(0, pos);
+
+ std::optional<std::uint16_t> elem = hex_to_uint16(seg);
+ if (!elem)
+ return {};
+
+ color.red = *elem >> 8; // 16-bit to 8-bit
+ v = v.substr(pos + 1);
+ pos = v.find(':');
+ if (pos == v.npos)
+ return {};
+
+ seg = v.substr(0, pos);
+ elem = hex_to_uint16(seg);
+ if (!elem)
+ return {};
+
+ color.green = *elem >> 8;
+ v = v.substr(pos + 1);
+ elem = hex_to_uint16(v);
+ if (!elem)
+ return {};
+
+ color.blue = *elem >> 8;
+ return color;
+}
+
+std::optional<spreadsheet::color_rgb_t> parse_gnumeric_rgb_8x(std::string_view v)
+{
+ ss::color_rgb_t color;
+
+ auto pos = v.find('x');
+ if (pos == v.npos)
+ return {};
+
+ std::string_view seg = v.substr(0, pos);
+
+ std::optional<std::uint16_t> elem = hex_to_uint8(seg);
+ if (!elem)
+ return {};
+
+ color.red = *elem;
+ v = v.substr(pos + 1);
+ pos = v.find('x');
+ if (pos == v.npos)
+ return {};
+
+ seg = v.substr(0, pos);
+ elem = hex_to_uint8(seg);
+ if (!elem)
+ return {};
+
+ color.green = *elem;
+ v = v.substr(pos + 1);
+ elem = hex_to_uint8(v);
+ if (!elem)
+ return {};
+
+ color.blue = *elem;
+ return color;
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_types.hpp b/src/liborcus/gnumeric_types.hpp
new file mode 100644
index 0000000..1d8b928
--- /dev/null
+++ b/src/liborcus/gnumeric_types.hpp
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <orcus/spreadsheet/types.hpp>
+
+#include <string_view>
+#include <optional>
+
+namespace orcus {
+
+/**
+ * Values are as specified in the Gnumeric source code.
+ */
+enum gnumeric_value_type
+{
+ vt_empty = 10,
+ vt_boolean = 20,
+ vt_float = 40,
+ vt_error = 50,
+ vt_string = 60,
+ vt_cellrange = 70,
+ vt_array = 80
+};
+
+/**
+ * Values are as specified in the Gnumeric source code (see
+ * GnmStyleBorderType).
+ */
+enum class gnumeric_border_type
+{
+ border_none = 0x0,
+ border_thin = 0x1,
+ border_medium = 0x2,
+ border_dashed = 0x3,
+ border_dotted = 0x4,
+ border_thick = 0x5,
+ border_double = 0x6,
+ border_hair = 0x7,
+ border_medium_dash = 0x8,
+ border_dash_dot = 0x9,
+ border_medium_dash_dot = 0xA,
+ border_dash_dot_dot = 0xB,
+ border_medium_dash_dot_dot = 0xC,
+ border_slanted_dash_dot = 0xD,
+};
+
+spreadsheet::border_style_t to_standard_type(gnumeric_border_type v);
+
+enum class gnumeric_value_format_type
+{
+ unknown,
+ bold,
+ color,
+ family,
+ italic,
+ size,
+ strikethrough,
+ subscript,
+ superscript,
+ underline,
+};
+
+gnumeric_value_format_type to_gnumeric_value_format_type(std::string_view s);
+
+struct gnumeric_value_format_segment
+{
+ gnumeric_value_format_type type = gnumeric_value_format_type::unknown;
+ std::string_view value;
+ std::size_t start = 0;
+ std::size_t end = 0;
+};
+
+enum gnumeric_script_type
+{
+ gnm_script_none = 0,
+ gnm_script_super = 1,
+ gnm_script_sub = -1
+};
+
+struct gnumeric_named_exp
+{
+ std::string_view name;
+ std::string_view value;
+ spreadsheet::src_address_t position = {0, 0, 0};
+
+ void reset();
+};
+
+struct gnumeric_style
+{
+ struct border_type
+ {
+ std::optional<gnumeric_border_type> style;
+ std::optional<spreadsheet::color_rgb_t> color;
+ };
+
+ spreadsheet::sheet_t sheet = -1;
+ spreadsheet::range_t region = {{-1, -1}, {-1, -1}};
+ spreadsheet::hor_alignment_t hor_align = spreadsheet::hor_alignment_t::unknown;
+ spreadsheet::ver_alignment_t ver_align = spreadsheet::ver_alignment_t::unknown;
+
+ std::optional<std::string_view> font_name;
+ std::optional<double> font_unit;
+
+ std::optional<bool> wrap_text;
+ std::optional<bool> bold;
+ std::optional<bool> italic;
+ std::optional<bool> underline;
+ std::optional<bool> strikethrough;
+ std::optional<gnumeric_script_type> script; // TODO : not supported yet
+
+ std::optional<spreadsheet::color_rgb_t> fore;
+ std::optional<spreadsheet::color_rgb_t> back;
+ std::optional<spreadsheet::color_rgb_t> pattern_color;
+ spreadsheet::fill_pattern_t pattern = spreadsheet::fill_pattern_t::none;
+
+ std::optional<std::string_view> number_format;
+
+ border_type border_top;
+ border_type border_bottom;
+ border_type border_left;
+ border_type border_right;
+ border_type border_bl_tr; // bottom-left to top-right (diagonal)
+ border_type border_br_tl; // top-left to bottom-right (rev-diagonal)
+
+ bool valid() const;
+};
+
+/**
+ * Parse an RGB color encoded as 'RRRR:GGGG:BBBB', each element being a 16-bit
+ * hex value.
+ */
+std::optional<spreadsheet::color_rgb_t> parse_gnumeric_rgb(std::string_view v);
+
+/**
+ * Parse an RGB color encoded as 'RRxGGxBB', each element being an 8-bit hex
+ * value.
+ */
+std::optional<spreadsheet::color_rgb_t> parse_gnumeric_rgb_8x(std::string_view v);
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_value_format_parser.cpp b/src/liborcus/gnumeric_value_format_parser.cpp
new file mode 100644
index 0000000..014068e
--- /dev/null
+++ b/src/liborcus/gnumeric_value_format_parser.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "gnumeric_value_format_parser.hpp"
+#include <orcus/exception.hpp>
+#include <orcus/measurement.hpp>
+
+#include <cassert>
+#include <sstream>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+using boost::numeric_cast;
+
+namespace orcus {
+
+std::size_t gnumeric_value_format_parser::get_pos() const
+{
+ return std::distance(m_head, m_cur);
+}
+
+void gnumeric_value_format_parser::segment()
+{
+ // segment: [type=value:start:end]
+
+ assert(*m_cur == '[');
+ const char* p0 = nullptr;
+ std::size_t pos = 0;
+
+ gnumeric_value_format_segment seg;
+
+ for (++m_cur; m_cur != m_end; ++m_cur)
+ {
+ if (!p0)
+ p0 = m_cur;
+
+ switch (*m_cur)
+ {
+ case ']':
+ {
+ if (pos != 2)
+ throw parse_error("value format segment is not formatted properly", get_pos());
+
+ auto n = std::distance(p0, m_cur);
+ std::string_view s{p0, numeric_cast<std::size_t>(n)};
+ if (s.empty())
+ throw parse_error("segment value is empty", get_pos());
+
+ seg.end = to_long(s);
+ m_segments.push_back(std::move(seg));
+ return;
+ }
+ case '=':
+ {
+ auto n = std::distance(p0, m_cur);
+ std::string_view s{p0, numeric_cast<std::size_t>(n)};
+ seg.type = to_gnumeric_value_format_type(s);
+ if (seg.type == gnumeric_value_format_type::unknown)
+ {
+ std::ostringstream os;
+ os << "invalid value format type '" << s << "'";
+ throw parse_error(os.str(), get_pos());
+ }
+
+ p0 = nullptr;
+ break;
+ }
+ case ':':
+ {
+ auto n = std::distance(p0, m_cur);
+ std::string_view s{p0, numeric_cast<std::size_t>(n)};
+
+ switch (pos)
+ {
+ case 0:
+ seg.value = s;
+ break;
+ case 1:
+ seg.start = to_long(s);
+ break;
+ default:
+ throw parse_error("too many value partitions", get_pos());
+ }
+
+ p0 = nullptr;
+ ++pos;
+ break;
+ }
+ }
+ }
+
+ throw parse_error("']' was never reached", get_pos());
+}
+
+gnumeric_value_format_parser::gnumeric_value_format_parser(std::string_view format) :
+ m_head(format.data()), m_cur(m_head), m_end(m_head + format.size())
+{
+}
+
+void gnumeric_value_format_parser::parse()
+{
+ if (m_cur == m_end)
+ return;
+
+ // @[segment][segment][segment]...
+
+ if (*m_cur++ != '@')
+ throw parse_error("first character must be '@'", get_pos());
+
+ for (; m_cur != m_end; ++m_cur)
+ {
+ if (*m_cur != '[')
+ throw parse_error("'[' was expected", get_pos());
+
+ segment();
+ assert(*m_cur == ']');
+ }
+}
+
+std::vector<gnumeric_value_format_segment> gnumeric_value_format_parser::pop_segments()
+{
+ return std::move(m_segments);
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/gnumeric_value_format_parser.hpp b/src/liborcus/gnumeric_value_format_parser.hpp
new file mode 100644
index 0000000..83cc6dd
--- /dev/null
+++ b/src/liborcus/gnumeric_value_format_parser.hpp
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <string_view>
+#include <vector>
+
+#include "gnumeric_types.hpp"
+
+namespace orcus {
+
+class gnumeric_value_format_parser
+{
+ const char* m_head = nullptr;
+ const char* m_cur = nullptr;
+ const char* m_end = nullptr;
+
+ std::vector<gnumeric_value_format_segment> m_segments;
+
+private:
+ std::size_t get_pos() const;
+
+ void segment();
+
+public:
+ /**
+ * Constructor.
+ *
+ * @param format Format string containing one or more format segments. Make
+ * sure the source of this string is persisent!
+ */
+ gnumeric_value_format_parser(std::string_view format);
+
+ void parse();
+
+ std::vector<gnumeric_value_format_segment> pop_segments();
+};
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/impl_utils.hpp b/src/liborcus/impl_utils.hpp
new file mode 100644
index 0000000..9b8cd2e
--- /dev/null
+++ b/src/liborcus/impl_utils.hpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#define ENSURE_INTERFACE(PTR, NAME) \
+ do \
+ { \
+ if (!PTR) \
+ throw orcus::interface_error( \
+ "implementer must provide a concrete instance of " #NAME "."); \
+ } while (false)
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/info.cpp b/src/liborcus/info.cpp
new file mode 100644
index 0000000..ae571f5
--- /dev/null
+++ b/src/liborcus/info.cpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/info.hpp"
+
+#include "constants.inl"
+
+namespace orcus {
+
+int get_version_major()
+{
+ return ORCUS_MAJOR_VERSION;
+}
+
+int get_version_minor()
+{
+ return ORCUS_MINOR_VERSION;
+}
+
+int get_version_micro()
+{
+ return ORCUS_MICRO_VERSION;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/interface.cpp b/src/liborcus/interface.cpp
new file mode 100644
index 0000000..2b743a2
--- /dev/null
+++ b/src/liborcus/interface.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/interface.hpp"
+#include "orcus/config.hpp"
+
+namespace orcus { namespace iface {
+
+struct import_filter::impl
+{
+ orcus::config m_config;
+
+ impl(format_t input) : m_config(input) {}
+};
+
+import_filter::import_filter(format_t input) : mp_impl(std::make_unique<impl>(input)) {}
+
+import_filter::~import_filter() = default;
+
+void import_filter::set_config(const config& v)
+{
+ mp_impl->m_config = v;
+}
+
+const config& import_filter::get_config() const
+{
+ return mp_impl->m_config;
+}
+
+document_dumper::~document_dumper() = default;
+
+}}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_document_tree.cpp b/src/liborcus/json_document_tree.cpp
new file mode 100644
index 0000000..009aa08
--- /dev/null
+++ b/src/liborcus/json_document_tree.cpp
@@ -0,0 +1,1777 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/json_document_tree.hpp>
+#include <orcus/json_parser.hpp>
+#include <orcus/config.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/string_pool.hpp>
+
+#include "json_util.hpp"
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <sstream>
+#include <string_view>
+#include <limits>
+#include <iostream>
+#include <deque>
+
+#include <boost/current_function.hpp>
+#include <boost/pool/object_pool.hpp>
+
+#include "filesystem_env.hpp"
+
+namespace orcus { namespace json {
+
+namespace {
+
+struct json_value_object;
+struct json_value_array;
+
+}
+
+struct document_resource
+{
+ string_pool str_pool;
+ boost::object_pool<json_value> obj_pool;
+ boost::object_pool<json_value_object> obj_pool_jvo;
+ boost::object_pool<json_value_array> obj_pool_jva;
+};
+
+namespace detail {
+
+enum class node_t : int
+{
+ // These must have the same values as their public counterparts.
+ unset = static_cast<int>(json::node_t::unset),
+ string = static_cast<int>(json::node_t::string),
+ number = static_cast<int>(json::node_t::number),
+ object = static_cast<int>(json::node_t::object),
+ array = static_cast<int>(json::node_t::array),
+ boolean_true = static_cast<int>(json::node_t::boolean_true),
+ boolean_false = static_cast<int>(json::node_t::boolean_false),
+ null = static_cast<int>(json::node_t::null),
+
+ /**
+ * Value that represents a single key-value pair. This is an internal
+ * only type, and only to be used in the initializer.
+ */
+ key_value = 10,
+
+ /**
+ * Implicit array initialized with a {} instead of explicit array().
+ */
+ array_implicit = 11,
+};
+
+std::ostream& operator<< (std::ostream& os, node_t nt)
+{
+ static const char* unknown = "???";
+
+ static std::vector<const char*> values =
+ {
+ "unset", // 0
+ "string", // 1
+ "number", // 2
+ "object", // 3
+ "array", // 4
+ "boolean_true", // 5
+ "boolean_false", // 6
+ "null", // 7
+ unknown, // 8
+ unknown, // 9
+ "key_value", // 10
+ "array_implicit", // 11
+ };
+
+ size_t nt_value = size_t(nt);
+
+ if (nt_value < values.size())
+ os << values[nt_value];
+ else
+ os << unknown;
+
+ return os;
+}
+
+}
+
+document_error::document_error(const std::string& msg) :
+ general_error("json::document_error", msg) {}
+
+document_error::~document_error() = default;
+
+key_value_error::key_value_error(const std::string& msg) :
+ document_error(msg) {}
+
+key_value_error::~key_value_error() = default;
+
+struct json_value final
+{
+ detail::node_t type;
+ json_value* parent;
+
+ union
+ {
+ double numeric;
+
+ struct
+ {
+ const char* p;
+ size_t n;
+
+ } str;
+
+ struct
+ {
+ const char* key;
+ size_t n_key;
+ json_value* value;
+
+ } kvp; // key-value pair
+
+ json_value_object* object;
+ json_value_array* array;
+
+ } value;
+
+ json_value(const json_value&) = delete;
+ json_value& operator= (const json_value&) = delete;
+
+ json_value() : type(detail::node_t::unset), parent(nullptr) {}
+ json_value(detail::node_t _type) : type(_type), parent(nullptr) {}
+ ~json_value() {}
+};
+
+namespace {
+
+const char* tab = " ";
+const char quote = '"';
+
+const xmlns_id_t NS_orcus_json_xml = "http://schemas.kohei.us/orcus/2015/json";
+
+struct json_value_array
+{
+ std::vector<json_value*> value_array;
+};
+
+struct json_value_object
+{
+ using object_type = std::unordered_map<std::string_view, json_value*>;
+
+ std::vector<std::string_view> key_order;
+ object_type value_object;
+
+ bool has_ref;
+
+ json_value_object() : has_ref(false) {}
+
+ void swap(json_value_object& src)
+ {
+ key_order.swap(src.key_order);
+ value_object.swap(src.value_object);
+ }
+};
+
+void dump_repeat(std::ostringstream& os, const char* s, int repeat)
+{
+ for (int i = 0; i < repeat; ++i)
+ os << s;
+}
+
+void dump_item(
+ std::ostringstream& os, const std::string_view* key, const json_value* val,
+ int level, bool sep);
+
+void dump_value(std::ostringstream& os, const json_value* v, int level, const std::string_view* key = nullptr)
+{
+ dump_repeat(os, tab, level);
+
+ if (key)
+ os << quote << *key << quote << ": ";
+
+ switch (v->type)
+ {
+ case detail::node_t::array:
+ {
+ auto& vals = v->value.array->value_array;
+ os << "[" << std::endl;
+ size_t n = vals.size();
+ size_t pos = 0;
+ for (auto it = vals.begin(), ite = vals.end(); it != ite; ++it, ++pos)
+ dump_item(os, nullptr, *it, level, pos < (n-1));
+
+ dump_repeat(os, tab, level);
+ os << "]";
+ }
+ break;
+ case detail::node_t::boolean_false:
+ os << "false";
+ break;
+ case detail::node_t::boolean_true:
+ os << "true";
+ break;
+ case detail::node_t::null:
+ os << "null";
+ break;
+ case detail::node_t::number:
+ os << v->value.numeric;
+ break;
+ case detail::node_t::object:
+ {
+ const std::vector<std::string_view>& key_order = v->value.object->key_order;
+ auto& vals = v->value.object->value_object;
+ os << "{" << std::endl;
+ size_t n = vals.size();
+
+ if (key_order.empty())
+ {
+ // Dump object's children unordered.
+ size_t pos = 0;
+ for (auto it = vals.begin(), ite = vals.end(); it != ite; ++it, ++pos)
+ {
+ std::string_view this_key = it->first;
+ auto& this_val = it->second;
+
+ dump_item(os, &this_key, this_val, level, pos < (n-1));
+ }
+ }
+ else
+ {
+ // Dump them based on key's original ordering.
+ size_t pos = 0;
+ for (auto it = key_order.begin(), ite = key_order.end(); it != ite; ++it, ++pos)
+ {
+ std::string_view this_key = *it;
+ auto val_pos = vals.find(this_key);
+ assert(val_pos != vals.end());
+
+ dump_item(os, &this_key, val_pos->second, level, pos < (n-1));
+ }
+ }
+
+ dump_repeat(os, tab, level);
+ os << "}";
+ }
+ break;
+ case detail::node_t::string:
+ json::dump_string(
+ os,
+ std::string(v->value.str.p, v->value.str.n));
+ break;
+ case detail::node_t::unset:
+ default:
+ ;
+ }
+}
+
+void dump_item(
+ std::ostringstream& os, const std::string_view* key, const json_value* val,
+ int level, bool sep)
+{
+ dump_value(os, val, level+1, key);
+ if (sep)
+ os << ",";
+ os << std::endl;
+}
+
+std::string dump_json_tree(const json_value* root)
+{
+ if (root->type == detail::node_t::unset)
+ return std::string();
+
+ std::ostringstream os;
+ dump_value(os, root, 0);
+ return os.str();
+}
+
+void dump_string_xml(std::ostringstream& os, std::string_view s)
+{
+ const char* p = s.data();
+ const char* p_end = p + s.size();
+ for (; p != p_end; ++p)
+ {
+ char c = *p;
+ switch (c)
+ {
+ case '"':
+ os << "&quot;";
+ break;
+ case '<':
+ os << "&lt;";
+ break;
+ case '>':
+ os << "&gt;";
+ break;
+ case '&':
+ os << "&amp;";
+ break;
+ case '\'':
+ os << "&apos;";
+ break;
+ default:
+ os << c;
+ }
+ }
+}
+
+void dump_object_item_xml(
+ std::ostringstream& os, std::string_view key, const json_value* val, int level);
+
+void dump_value_xml(std::ostringstream& os, const json_value* v, int level)
+{
+ switch (v->type)
+ {
+ case detail::node_t::array:
+ {
+ os << "<array";
+ if (level == 0)
+ os << " xmlns=\"" << NS_orcus_json_xml << "\"";
+ os << ">";
+
+ auto& vals = v->value.array->value_array;
+
+ for (auto it = vals.begin(), ite = vals.end(); it != ite; ++it)
+ {
+ os << "<item>";
+ dump_value_xml(os, *it, level+1);
+ os << "</item>";
+ }
+
+ os << "</array>";
+ }
+ break;
+ case detail::node_t::boolean_false:
+ os << "<false/>";
+ break;
+ case detail::node_t::boolean_true:
+ os << "<true/>";
+ break;
+ case detail::node_t::null:
+ os << "<null/>";
+ break;
+ case detail::node_t::number:
+ os << "<number value=\"";
+ os << v->value.numeric;
+ os << "\"/>";
+ break;
+ case detail::node_t::object:
+ {
+ os << "<object";
+ if (level == 0)
+ os << " xmlns=\"" << NS_orcus_json_xml << "\"";
+ os << ">";
+
+ const json_value_object& jvo = *v->value.object;
+ auto& key_order = jvo.key_order;
+ auto& vals = jvo.value_object;
+
+ if (key_order.empty())
+ {
+ // Dump object's children unordered.
+ for (auto it = vals.begin(), ite = vals.end(); it != ite; ++it)
+ {
+ auto& key = it->first;
+ auto& val = it->second;
+ dump_object_item_xml(os, key, val, level);
+ }
+ }
+ else
+ {
+ // Dump them based on key's original ordering.
+ for (auto it = key_order.begin(), ite = key_order.end(); it != ite; ++it)
+ {
+ auto& key = *it;
+ auto val_pos = vals.find(key);
+ assert(val_pos != vals.end());
+
+ dump_object_item_xml(os, key, val_pos->second, level);
+ }
+ }
+
+ os << "</object>";
+ }
+ break;
+ case detail::node_t::string:
+ os << "<string value=\"";
+ dump_string_xml(os, std::string_view(v->value.str.p, v->value.str.n));
+ os << "\"/>";
+ break;
+ case detail::node_t::unset:
+ default:
+ ;
+ }
+}
+
+class yaml_dumper
+{
+ enum class write_type { unspecified, indent, linebreak, value };
+
+ std::size_t m_indent_length = 0;
+ write_type m_last_write = write_type::unspecified;
+
+ void reset()
+ {
+ m_indent_length = 0;
+ m_last_write = write_type::unspecified;
+ }
+
+ static bool needs_quote(std::string_view s)
+ {
+ char c_prev = 0;
+
+ for (char c : s)
+ {
+ switch (c)
+ {
+ case '#':
+ return true;
+ case ' ':
+ if (c_prev == ':')
+ return true;
+ }
+
+ c_prev = c;
+ }
+
+ return false;
+ }
+
+public:
+ std::string dump(const json_value* root)
+ {
+ if (!root || root->type == detail::node_t::unset)
+ return std::string();
+
+ reset();
+
+ std::ostringstream os;
+ os << "---" << std::endl;
+ write_value(os, root);
+ return os.str();
+ }
+
+private:
+ void write_indent(std::ostringstream& os)
+ {
+ m_last_write = write_type::indent;
+
+ for (std::size_t i = 0; i < m_indent_length; ++i)
+ os << ' ';
+ }
+
+ void write_linebreak(std::ostringstream& os)
+ {
+ if (m_last_write == write_type::linebreak)
+ return;
+
+ m_last_write = write_type::linebreak;
+ os << std::endl;
+ }
+
+ void write_string(std::ostringstream& os, std::string_view s)
+ {
+ bool quote_value = needs_quote(s);
+
+ if (quote_value)
+ os << '"';
+
+ os << s;
+
+ if (quote_value)
+ os << '"';
+ }
+
+ void write_value(std::ostringstream& os, const json_value* v)
+ {
+ m_last_write = write_type::value;
+ detail::node_t parent_type = v->parent ? v->parent->type : detail::node_t::unset;
+
+ switch (v->type)
+ {
+ case detail::node_t::array:
+ {
+ if (parent_type != detail::node_t::unset)
+ write_linebreak(os);
+
+ for (const json_value* cv : v->value.array->value_array)
+ {
+ write_indent(os);
+ os << "- ";
+ m_indent_length += 2;
+ write_value(os, cv);
+ m_indent_length -= 2;
+ write_linebreak(os);
+ }
+ break;
+ }
+ case detail::node_t::boolean_false:
+ os << "false";
+ break;
+ case detail::node_t::boolean_true:
+ os << "true";
+ break;
+ case detail::node_t::null:
+ os << "null";
+ break;
+ case detail::node_t::number:
+ {
+ os << v->value.numeric;
+ break;
+ }
+ case detail::node_t::object:
+ {
+ const json_value_object& jvo = *v->value.object;
+ const std::vector<std::string_view>& key_order = jvo.key_order;
+ const json_value_object::object_type& vals = jvo.value_object;
+
+ std::deque<std::tuple<std::string_view, const json_value*>> key_values;
+
+ if (key_order.empty())
+ {
+ // Dump object's children unordered.
+ for (const auto& val : vals)
+ key_values.emplace_back(val.first, val.second);
+ }
+ else
+ {
+ // Dump them based on key's original ordering.
+ for (std::string_view key : key_order)
+ {
+ auto val_pos = vals.find(key);
+ assert(val_pos != vals.end());
+ key_values.emplace_back(key, val_pos->second);
+ }
+ }
+
+ if (key_values.empty())
+ break;
+
+ auto write_key_value = [this, &os](std::string_view key, const json_value* value)
+ {
+ std::size_t indent_add = 2;
+ write_string(os, key);
+ os << ": ";
+ m_indent_length += indent_add;
+ write_value(os, value);
+ m_indent_length -= indent_add;
+ write_linebreak(os);
+ };
+
+ if (parent_type == detail::node_t::array)
+ {
+ // Parent is an array. Continue on the "bullet" line.
+ write_key_value(std::get<0>(key_values[0]), std::get<1>(key_values[0]));
+ key_values.pop_front();
+ }
+ else if (parent_type != detail::node_t::unset)
+ write_linebreak(os);
+
+ for (auto& [key, value] : key_values)
+ {
+ write_indent(os);
+ write_key_value(key, value);
+ }
+
+ break;
+ }
+ case detail::node_t::string:
+ {
+ write_string(os, {v->value.str.p, v->value.str.n});
+ break;
+ }
+ case detail::node_t::unset:
+ default:
+ ;
+ }
+ }
+};
+
+void dump_object_item_xml(
+ std::ostringstream& os, std::string_view key, const json_value* val, int level)
+{
+ os << "<item name=\"";
+ dump_string_xml(os, key);
+ os << "\">";
+ dump_value_xml(os, val, level+1);
+ os << "</item>";
+}
+
+std::string dump_xml_tree(const json_value* root)
+{
+ if (root->type == detail::node_t::unset)
+ return std::string();
+
+ std::ostringstream os;
+ os << "<?xml version=\"1.0\"?>" << std::endl;
+ dump_value_xml(os, root, 0);
+ os << std::endl;
+ return os.str();
+}
+
+struct parser_stack
+{
+ std::string_view key;
+ json_value* node;
+
+ parser_stack(json_value* _node) : node(_node) {}
+};
+
+struct external_ref
+{
+ std::string_view path;
+ json_value_object* dest;
+
+ external_ref(std::string_view _path, json_value_object* _dest) :
+ path(_path), dest(_dest) {}
+};
+
+class parser_handler
+{
+ json_value* m_root;
+ const json_config& m_config;
+
+ std::vector<parser_stack> m_stack;
+ std::vector<external_ref> m_external_refs;
+
+ document_resource& m_res;
+
+ json_value* push_value(json_value* value)
+ {
+ assert(!m_stack.empty());
+ parser_stack& cur = m_stack.back();
+
+ switch (cur.node->type)
+ {
+ case detail::node_t::array:
+ {
+ json_value_array* jva = cur.node->value.array;
+ value->parent = cur.node;
+ jva->value_array.push_back(value);
+ return jva->value_array.back();
+ }
+ case detail::node_t::object:
+ {
+ std::string_view key = cur.key;
+ json_value_object* jvo = cur.node->value.object;
+ value->parent = cur.node;
+
+ if (m_config.resolve_references &&
+ key == "$ref" && value->type == detail::node_t::string)
+ {
+ std::string_view sv(value->value.str.p, value->value.str.n);
+ if (!jvo->has_ref && !sv.empty() && sv[0] != '#')
+ {
+ // Store the external reference path and the destination
+ // object for later processing.
+ m_external_refs.emplace_back(sv, jvo);
+ jvo->has_ref = true;
+ }
+ }
+
+ if (m_config.preserve_object_order)
+ jvo->key_order.push_back(key);
+
+ auto r = jvo->value_object.insert(std::make_pair(key, value));
+
+ if (!r.second)
+ throw document_error("adding the same key twice");
+
+ return r.first->second;
+ }
+ default:
+ break;
+ }
+
+ std::ostringstream os;
+ os << BOOST_CURRENT_FUNCTION << ": unstackable JSON value type.";
+ throw document_error(os.str());
+ }
+
+public:
+ parser_handler(const json_config& config, document_resource& res) :
+ m_root(nullptr), m_config(config), m_res(res) {}
+
+ void begin_parse()
+ {
+ m_root = nullptr;
+ }
+
+ void end_parse()
+ {
+ }
+
+ void begin_array()
+ {
+ if (m_root)
+ {
+ json_value* jv = m_res.obj_pool.construct(detail::node_t::array);
+ jv->value.array = m_res.obj_pool_jva.construct();
+ jv = push_value(jv);
+ assert(jv && jv->type == detail::node_t::array);
+ m_stack.push_back(parser_stack(jv));
+ }
+ else
+ {
+ m_root = m_res.obj_pool.construct(detail::node_t::array);
+ m_root->value.array = m_res.obj_pool_jva.construct();
+ m_stack.push_back(parser_stack(m_root));
+ }
+ }
+
+ void end_array()
+ {
+ assert(!m_stack.empty());
+ m_stack.pop_back();
+ }
+
+ void begin_object()
+ {
+ if (m_root)
+ {
+ json_value* jv = m_res.obj_pool.construct(detail::node_t::object);
+ jv->value.object = m_res.obj_pool_jvo.construct();
+ jv = push_value(jv);
+ assert(jv && jv->type == detail::node_t::object);
+ m_stack.push_back(parser_stack(jv));
+ }
+ else
+ {
+ m_root = m_res.obj_pool.construct(detail::node_t::object);
+ m_root->value.object = m_res.obj_pool_jvo.construct();
+ m_stack.push_back(parser_stack(m_root));
+ }
+ }
+
+ void object_key(std::string_view key, bool transient)
+ {
+ parser_stack& cur = m_stack.back();
+ cur.key = key;
+ if (m_config.persistent_string_values || transient)
+ // The tree manages the life cycle of this string value.
+ cur.key = m_res.str_pool.intern(cur.key).first;
+ }
+
+ void end_object()
+ {
+ assert(!m_stack.empty());
+ m_stack.pop_back();
+ }
+
+ void boolean_true()
+ {
+ push_value(m_res.obj_pool.construct(detail::node_t::boolean_true));
+ }
+
+ void boolean_false()
+ {
+ push_value(m_res.obj_pool.construct(detail::node_t::boolean_false));
+ }
+
+ void null()
+ {
+ push_value(m_res.obj_pool.construct(detail::node_t::null));
+ }
+
+ void string(std::string_view s, bool transient)
+ {
+ if (m_config.persistent_string_values || transient)
+ // The tree manages the life cycle of this string value.
+ s = m_res.str_pool.intern(s).first;
+
+ json_value* jv = m_res.obj_pool.construct(detail::node_t::string);
+ jv->value.str.p = s.data();
+ jv->value.str.n = s.size();
+ push_value(jv);
+ }
+
+ void number(double val)
+ {
+ json_value* jv = m_res.obj_pool.construct(detail::node_t::number);
+ jv->value.numeric = val;
+ push_value(jv);
+ }
+
+ json_value* get_root()
+ {
+ return m_root;
+ }
+
+ const std::vector<external_ref>& get_external_refs() const
+ {
+ return m_external_refs;
+ }
+};
+
+} // anonymous namespace
+
+struct const_node::impl
+{
+ const document_tree* m_doc;
+ json_value* m_node;
+
+ impl(const document_tree* doc, json_value* jv) : m_doc(doc), m_node(jv) {}
+ impl(const impl& other) : m_doc(other.m_doc), m_node(other.m_node) {}
+};
+
+const_node::const_node(const document_tree* doc, json_value* jv) : mp_impl(std::make_unique<impl>(doc, jv)) {}
+const_node::const_node(std::unique_ptr<impl>&& p) : mp_impl(std::move(p)) {}
+const_node::const_node(const const_node& other) : mp_impl(std::make_unique<impl>(*other.mp_impl)) {}
+const_node::const_node(const_node&& rhs) : mp_impl(std::move(rhs.mp_impl)) {}
+const_node::~const_node() {}
+
+const_node& const_node::operator=(const const_node& other)
+{
+ if (this == &other)
+ return *this;
+
+ const_node tmp(other);
+ mp_impl.swap(tmp.mp_impl);
+ return *this;
+}
+
+const_node& const_node::operator=(const_node&& other)
+{
+ if (this == &other)
+ return *this;
+
+ mp_impl = std::move(other.mp_impl);
+ return *this;
+}
+
+uintptr_t const_node::identity() const
+{
+ return reinterpret_cast<uintptr_t>(mp_impl->m_node);
+}
+
+const_node_iterator const_node::begin() const
+{
+ if (mp_impl->m_node->type != detail::node_t::array)
+ throw document_error("const_node::begin: this method only supports array nodes.");
+
+ return const_node_iterator(mp_impl->m_doc, *this, true);
+}
+
+const_node_iterator const_node::end() const
+{
+ if (mp_impl->m_node->type != detail::node_t::array)
+ throw document_error("const_node::end: this method only supports array nodes.");
+
+ return const_node_iterator(mp_impl->m_doc, *this, false);
+}
+
+node_t const_node::type() const
+{
+ // Convert it back to the public enum type.
+ return static_cast<node_t>(mp_impl->m_node->type);
+}
+
+size_t const_node::child_count() const
+{
+ switch (mp_impl->m_node->type)
+ {
+ case detail::node_t::object:
+ return mp_impl->m_node->value.object->value_object.size();
+ case detail::node_t::array:
+ return mp_impl->m_node->value.array->value_array.size();
+ case detail::node_t::string:
+ case detail::node_t::number:
+ case detail::node_t::boolean_true:
+ case detail::node_t::boolean_false:
+ case detail::node_t::null:
+ case detail::node_t::unset:
+ default:
+ ;
+ }
+ return 0;
+}
+
+std::vector<std::string_view> const_node::keys() const
+{
+ if (mp_impl->m_node->type != detail::node_t::object)
+ throw document_error("node::keys: this node is not of object type.");
+
+ const json_value_object* jvo = mp_impl->m_node->value.object;
+ if (!jvo->key_order.empty())
+ // Prefer to use key_order when it's populated.
+ return jvo->key_order;
+
+ std::vector<std::string_view> keys;
+
+ for (const auto& n : jvo->value_object)
+ keys.push_back(n.first);
+
+ return keys;
+}
+
+std::string_view const_node::key(size_t index) const
+{
+ if (mp_impl->m_node->type != detail::node_t::object)
+ throw document_error("node::key: this node is not of object type.");
+
+ const json_value_object* jvo = mp_impl->m_node->value.object;
+ if (index >= jvo->key_order.size())
+ throw std::out_of_range("node::key: index is out-of-range.");
+
+ return jvo->key_order[index];
+}
+
+bool const_node::has_key(std::string_view key) const
+{
+ if (mp_impl->m_node->type != detail::node_t::object)
+ return false;
+
+ const json_value_object* jvo = mp_impl->m_node->value.object;
+ const json_value_object::object_type& children = jvo->value_object;
+
+ return children.count(key) != 0;
+}
+
+const_node const_node::child(size_t index) const
+{
+ switch (mp_impl->m_node->type)
+ {
+ case detail::node_t::object:
+ {
+ // This works only when the key order is preserved.
+ const json_value_object* jvo = mp_impl->m_node->value.object;
+ if (index >= jvo->key_order.size())
+ throw std::out_of_range("node::child: index is out-of-range");
+
+ std::string_view key = jvo->key_order[index];
+ auto it = jvo->value_object.find(key);
+ assert(it != jvo->value_object.end());
+ return const_node(mp_impl->m_doc, it->second);
+ }
+ break;
+ case detail::node_t::array:
+ {
+ const json_value_array* jva = mp_impl->m_node->value.array;
+ if (index >= jva->value_array.size())
+ throw std::out_of_range("node::child: index is out-of-range");
+
+ return const_node(mp_impl->m_doc, jva->value_array[index]);
+ }
+ break;
+ case detail::node_t::string:
+ case detail::node_t::number:
+ case detail::node_t::boolean_true:
+ case detail::node_t::boolean_false:
+ case detail::node_t::null:
+ case detail::node_t::unset:
+ default:
+ throw document_error("node::child: this node cannot have child nodes.");
+ }
+}
+
+const_node const_node::child(std::string_view key) const
+{
+ if (mp_impl->m_node->type != detail::node_t::object)
+ throw document_error("node::child: this node is not of object type.");
+
+ const json_value_object* jvo = mp_impl->m_node->value.object;
+ auto it = jvo->value_object.find(key);
+ if (it == jvo->value_object.end())
+ {
+ std::ostringstream os;
+ os << "node::child: this object does not have a key labeled '" << key << "'";
+ throw document_error(os.str());
+ }
+
+ return const_node(mp_impl->m_doc, it->second);
+}
+
+const_node const_node::parent() const
+{
+ if (!mp_impl->m_node->parent)
+ throw document_error("node::parent: this node has no parent.");
+
+ return const_node(mp_impl->m_doc, mp_impl->m_node->parent);
+}
+
+const_node const_node::back() const
+{
+ if (mp_impl->m_node->type != detail::node_t::array)
+ throw document_error("const_node::child: this node is not of array type.");
+
+ const json_value_array* jva = mp_impl->m_node->value.array;
+ if (jva->value_array.empty())
+ throw document_error("const_node::child: this node has no children.");
+
+ return const_node(mp_impl->m_doc, jva->value_array.back());
+}
+
+std::string_view const_node::string_value() const
+{
+ if (mp_impl->m_node->type != detail::node_t::string)
+ throw document_error("node::key: current node is not of string type.");
+
+ return std::string_view(mp_impl->m_node->value.str.p, mp_impl->m_node->value.str.n);
+}
+
+double const_node::numeric_value() const
+{
+ if (mp_impl->m_node->type != detail::node_t::number)
+ throw document_error("node::key: current node is not of numeric type.");
+
+ return mp_impl->m_node->value.numeric;
+}
+
+node::node(const document_tree* doc, json_value* jv) : const_node(doc, jv) {}
+node::node(const_node&& rhs) : const_node(std::move(rhs)) {}
+node::node(const node& other) : const_node(other) {}
+node::node(node&& rhs) : const_node(rhs) {}
+node::~node() {}
+
+node& node::operator=(const node& other)
+{
+ if (this == &other)
+ return *this;
+
+ node tmp(other);
+ mp_impl.swap(tmp.mp_impl);
+ return *this;
+}
+
+node& node::operator=(const detail::init::node& v)
+{
+ document_resource& res =
+ const_cast<document_resource&>(mp_impl->m_doc->get_resource());
+
+ v.store_to_node(res, mp_impl->m_node);
+
+ return *this;
+}
+
+node node::operator[](std::string_view key)
+{
+ if (mp_impl->m_node->type != detail::node_t::object)
+ throw document_error("node::operator[]: the node must be of object type.");
+
+ json_value_object* jvo = const_cast<json_value_object*>(mp_impl->m_node->value.object);
+ auto it = jvo->value_object.find(key);
+ if (it == jvo->value_object.end())
+ {
+ // This object doesn't have the specified key. Create a new empty node
+ // on the fly.
+ document_resource& res =
+ const_cast<document_resource&>(mp_impl->m_doc->get_resource());
+ json_value* jv = res.obj_pool.construct(detail::node_t::unset);
+ jv->parent = mp_impl->m_node;
+ auto r = jvo->value_object.insert(std::make_pair(key, jv));
+ it = r.first;
+ }
+
+ return node(mp_impl->m_doc, it->second);
+}
+
+node node::child(size_t index)
+{
+ const_node cn = const_node::child(index);
+ return node(std::move(cn));
+}
+
+node node::child(std::string_view key)
+{
+ const_node cn = const_node::child(key);
+ return node(std::move(cn));
+}
+
+node node::parent()
+{
+ const_node cn = const_node::parent();
+ return node(std::move(cn));
+}
+
+node node::back()
+{
+ const_node cn = const_node::back();
+ return node(std::move(cn));
+}
+
+void node::push_back(const detail::init::node& v)
+{
+ if (mp_impl->m_node->type != detail::node_t::array)
+ {
+ std::ostringstream os;
+ os << "node::push_back: the node must be of array type, but the value of this node type is '" << mp_impl->m_node->type << "'.";
+ throw document_error(os.str());
+ }
+
+ json_value_array* jva = mp_impl->m_node->value.array;
+ const document_resource& res = mp_impl->m_doc->get_resource();
+ jva->value_array.push_back(v.to_json_value(const_cast<document_resource&>(res)));
+}
+
+struct const_node_iterator::impl
+{
+ const document_tree* m_doc;
+ std::vector<json_value*>::const_iterator m_pos;
+ std::vector<json_value*>::const_iterator m_end;
+ const_node m_current_node;
+
+ impl() : m_doc(nullptr), m_current_node(nullptr, nullptr) {}
+
+ impl(const impl& other) :
+ m_doc(other.m_doc),
+ m_pos(other.m_pos),
+ m_end(other.m_end),
+ m_current_node(other.m_current_node) {}
+
+ impl(const document_tree* doc, const const_node& v, bool begin) :
+ m_doc(doc), m_current_node(nullptr, nullptr)
+ {
+ const json_value_array* jva = v.mp_impl->m_node->value.array;
+ m_pos = begin ? jva->value_array.cbegin() : jva->value_array.cend();
+ m_end = jva->value_array.cend();
+
+ if (m_pos != m_end)
+ m_current_node = const_node(m_doc, *m_pos);
+ }
+
+ void update_current()
+ {
+ m_current_node = const_node(m_doc, m_pos == m_end ? nullptr : *m_pos);
+ }
+};
+
+const_node_iterator::const_node_iterator() :
+ mp_impl(std::make_unique<impl>()) {}
+
+const_node_iterator::const_node_iterator(const const_node_iterator& other) :
+ mp_impl(std::make_unique<impl>(*other.mp_impl)) {}
+
+const_node_iterator::const_node_iterator(const document_tree* doc, const const_node& v, bool begin) :
+ mp_impl(std::make_unique<impl>(doc, v, begin)) {}
+
+const_node_iterator::~const_node_iterator() {}
+
+const const_node& const_node_iterator::operator*() const
+{
+ return mp_impl->m_current_node;
+}
+
+const const_node* const_node_iterator::operator->() const
+{
+ return &mp_impl->m_current_node;
+}
+
+const_node_iterator& const_node_iterator::operator++()
+{
+ ++mp_impl->m_pos;
+ mp_impl->update_current();
+ return *this;
+}
+
+const_node_iterator const_node_iterator::operator++(int)
+{
+ const_node_iterator tmp(*this);
+ ++mp_impl->m_pos;
+ mp_impl->update_current();
+ return tmp;
+}
+
+const_node_iterator& const_node_iterator::operator--()
+{
+ --mp_impl->m_pos;
+ mp_impl->update_current();
+ return *this;
+}
+
+const_node_iterator const_node_iterator::operator--(int)
+{
+ const_node_iterator tmp(*this);
+ --mp_impl->m_pos;
+ mp_impl->update_current();
+ return tmp;
+}
+
+bool const_node_iterator::operator== (const const_node_iterator& other) const
+{
+ return mp_impl->m_pos == other.mp_impl->m_pos && mp_impl->m_end == other.mp_impl->m_end;
+}
+
+bool const_node_iterator::operator!= (const const_node_iterator& other) const
+{
+ return !operator==(other);
+}
+
+const_node_iterator& const_node_iterator::operator= (const const_node_iterator& other)
+{
+ mp_impl->m_doc = other.mp_impl->m_doc;
+ mp_impl->m_pos = other.mp_impl->m_pos;
+ mp_impl->m_end = other.mp_impl->m_end;
+ mp_impl->update_current();
+
+ return *this;
+}
+
+array::array() {}
+array::array(array&& other) : m_vs(std::move(other.m_vs)) {}
+array::array(std::initializer_list<detail::init::node> vs)
+{
+ for (const detail::init::node& v : vs)
+ m_vs.push_back(std::move(const_cast<detail::init::node&>(v)));
+}
+
+array::~array() {}
+
+object::object() {}
+object::object(object&& /*other*/) {}
+object::~object() {}
+
+namespace {
+
+json_value* aggregate_nodes(document_resource& res, std::vector<json_value*> nodes, bool object)
+{
+ bool preserve_object_order = true;
+
+ if (object)
+ {
+ json_value* jv = res.obj_pool.construct(detail::node_t::object);
+ jv->value.object = res.obj_pool_jvo.construct();
+ json_value_object* jvo = jv->value.object;
+
+ for (json_value* const_node : nodes)
+ {
+ if (const_node->type != detail::node_t::key_value)
+ throw document_error("key-value pair was expected.");
+
+ auto& kvp = const_node->value.kvp;
+
+ if (preserve_object_order)
+ jvo->key_order.emplace_back(kvp.key, kvp.n_key);
+
+ kvp.value->parent = jv;
+ auto r = jvo->value_object.insert(
+ std::make_pair(std::string_view(kvp.key, kvp.n_key), kvp.value));
+
+ if (!r.second)
+ throw document_error("adding the same key twice");
+ }
+
+ return jv;
+ }
+
+ json_value* jv = res.obj_pool.construct(detail::node_t::array);
+ jv->value.array = res.obj_pool_jva.construct();
+ json_value_array* jva = jv->value.array;
+
+ for (json_value* const_node : nodes)
+ {
+ if (const_node->type == detail::node_t::key_value)
+ throw document_error("key-value pair was not expected.");
+
+ const_node->parent = jv;
+ jva->value_array.push_back(const_node);
+ }
+
+ return jv;
+}
+
+void aggregate_nodes_to_object(
+ document_resource& res, std::vector<json_value*> nodes, json_value* parent)
+{
+ bool preserve_object_order = true;
+
+ json_value_object* jvo = res.obj_pool_jvo.construct();
+ parent->value.object = jvo;
+
+ for (json_value* const_node : nodes)
+ {
+ if (const_node->type != detail::node_t::key_value)
+ throw document_error("key-value pair was expected.");
+
+ auto& kvp = const_node->value.kvp;
+
+ if (preserve_object_order)
+ jvo->key_order.emplace_back(kvp.key, kvp.n_key);
+
+ kvp.value->parent = parent;
+ auto r = jvo->value_object.insert(
+ std::make_pair(std::string_view(kvp.key, kvp.n_key), kvp.value));
+
+ if (!r.second)
+ throw document_error("adding the same key twice");
+ }
+}
+
+void aggregate_nodes_to_array(
+ document_resource& res, std::vector<json_value*> nodes, json_value* parent)
+{
+ json_value_array* jva = res.obj_pool_jva.construct();
+ parent->value.array = jva;
+
+ for (json_value* const_node : nodes)
+ {
+ if (const_node->type == detail::node_t::key_value)
+ throw document_error("key-value pair was not expected.");
+
+ const_node->parent = parent;
+ jva->value_array.push_back(const_node);
+ }
+}
+
+#ifndef NDEBUG
+
+/**
+ * Verify that the parent pointers stored in the child objects point to
+ * their real parent object.
+ */
+void verify_parent_pointers(const json_value* jv, bool object)
+{
+ if (object)
+ {
+ json_value_object* jvo = jv->value.object;
+ for (const auto& child : jvo->value_object)
+ {
+ const json_value& cv = *child.second;
+ assert(cv.parent == jv);
+ }
+ }
+ else
+ {
+ json_value_array* jva = jv->value.array;
+ for (const auto& child : jva->value_array)
+ {
+ const json_value& cv = *child;
+ assert(cv.parent == jv);
+ }
+ }
+}
+
+#endif
+
+} // anonymous namespace
+
+namespace detail { namespace init {
+
+struct node::impl
+{
+ detail::node_t m_type;
+
+ union
+ {
+ double m_value_number;
+ const char* m_value_string;
+ };
+
+ std::vector<detail::init::node> m_value_array;
+
+ impl() : m_type(detail::node_t::unset) {}
+ impl(double v) : m_type(detail::node_t::number), m_value_number(v) {}
+ impl(int v) : m_type(detail::node_t::number), m_value_number(v) {}
+ impl(bool b) : m_type(b ? detail::node_t::boolean_true : detail::node_t::boolean_false) {}
+ impl(decltype(nullptr)) : m_type(detail::node_t::null) {}
+ impl(const char* p) : m_type(detail::node_t::string), m_value_string(p) {}
+ impl(const std::string& s) : m_type(detail::node_t::string), m_value_string(s.data()) {}
+
+ impl(std::initializer_list<detail::init::node> vs) :
+ m_type(detail::node_t::array_implicit)
+ {
+ for (const detail::init::node& v : vs)
+ m_value_array.push_back(std::move(const_cast<detail::init::node&>(v)));
+
+ // If the list has two elements, and the first element is of type string,
+ // we treat this as object's key-value pair.
+
+ if (m_value_array.size() != 2)
+ return;
+
+ const detail::init::node& v0 = *m_value_array.begin();
+ if (v0.mp_impl->m_type == detail::node_t::string)
+ m_type = detail::node_t::key_value;
+ }
+
+ impl(json::array array) :
+ m_type(detail::node_t::array),
+ m_value_array(std::move(array.m_vs))
+ {}
+
+ impl(json::object /*obj*/) :
+ m_type(detail::node_t::object) {}
+};
+
+node::node(double v) : mp_impl(std::make_unique<impl>(v)) {}
+node::node(int v) : mp_impl(std::make_unique<impl>(v)) {}
+node::node(bool b) : mp_impl(std::make_unique<impl>(b)) {}
+node::node(std::nullptr_t) : mp_impl(std::make_unique<impl>(nullptr)) {}
+node::node(const char* p) : mp_impl(std::make_unique<impl>(p)) {}
+node::node(const std::string& s) : mp_impl(std::make_unique<impl>(s)) {}
+node::node(std::initializer_list<detail::init::node> vs) : mp_impl(std::make_unique<impl>(std::move(vs))) {}
+node::node(json::array array) : mp_impl(std::make_unique<impl>(std::move(array))) {}
+node::node(json::object obj) : mp_impl(std::make_unique<impl>(std::move(obj))) {}
+
+node::node(node&& other) : mp_impl(std::move(other.mp_impl)) {}
+node::~node() {}
+
+json::node_t node::type() const
+{
+ return static_cast<json::node_t>(mp_impl->m_type);
+}
+
+json_value* node::to_json_value(document_resource& res) const
+{
+ json_value* jv = nullptr;
+
+ switch (mp_impl->m_type)
+ {
+ case detail::node_t::key_value:
+ {
+ assert(mp_impl->m_value_array.size() == 2);
+ auto it = mp_impl->m_value_array.begin();
+ const detail::init::node& key_node = *it;
+ assert(key_node.mp_impl->m_type == detail::node_t::string);
+ std::string_view key = res.str_pool.intern(key_node.mp_impl->m_value_string).first;
+ ++it;
+ json_value* value = it->to_json_value(res);
+ if (value->type == detail::node_t::key_value)
+ throw key_value_error("nested key-value pairs are not allowed.");
+
+ ++it;
+ assert(it == mp_impl->m_value_array.end());
+
+ jv = res.obj_pool.construct(mp_impl->m_type);
+ jv->value.kvp.key = key.data();
+ jv->value.kvp.n_key = key.size();
+ jv->value.kvp.value = value;
+ break;
+ }
+ case detail::node_t::array:
+ {
+ std::vector<json_value*> nodes;
+ for (const detail::init::node& v2 : mp_impl->m_value_array)
+ {
+ json_value* r = v2.to_json_value(res);
+ nodes.push_back(r);
+ }
+
+ jv = aggregate_nodes(res, std::move(nodes), false);
+#ifndef NDEBUG
+ verify_parent_pointers(jv, false);
+#endif
+ break;
+ }
+ case detail::node_t::array_implicit:
+ {
+ std::vector<json_value*> nodes;
+ bool object = !mp_impl->m_value_array.empty();
+ for (const detail::init::node& v2 : mp_impl->m_value_array)
+ {
+ json_value* r = v2.to_json_value(res);
+ if (r->type != detail::node_t::key_value)
+ object = false;
+ nodes.push_back(r);
+ }
+
+ jv = aggregate_nodes(res, std::move(nodes), object);
+#ifndef NDEBUG
+ verify_parent_pointers(jv, object);
+#endif
+ break;
+ }
+ case detail::node_t::object:
+ {
+ // Currently only empty object instance is allowed.
+ assert(mp_impl->m_value_array.size() == 0);
+ jv = res.obj_pool.construct(mp_impl->m_type);
+ jv->value.object = res.obj_pool_jvo.construct();
+ break;
+ }
+ case detail::node_t::string:
+ {
+ std::string_view s = res.str_pool.intern(mp_impl->m_value_string).first;
+ jv = res.obj_pool.construct(mp_impl->m_type);
+ jv->value.str.p = s.data();
+ jv->value.str.n = s.size();
+ break;
+ }
+ case detail::node_t::number:
+ jv = res.obj_pool.construct(mp_impl->m_type);
+ jv->value.numeric = mp_impl->m_value_number;
+ break;
+ case detail::node_t::boolean_true:
+ case detail::node_t::boolean_false:
+ case detail::node_t::null:
+ jv = res.obj_pool.construct(mp_impl->m_type);
+ break;
+ case detail::node_t::unset:
+ default:
+ {
+ std::ostringstream os;
+ os << "unknown node type (type=" << int(mp_impl->m_type) << ")";
+ throw document_error(os.str());
+ }
+ }
+
+ return jv;
+}
+
+void node::store_to_node(document_resource& res, json_value* parent) const
+{
+ parent->type = mp_impl->m_type;
+
+ switch (mp_impl->m_type)
+ {
+ case detail::node_t::unset:
+ throw document_error("node type is unset.");
+ case detail::node_t::string:
+ {
+ std::string_view s = res.str_pool.intern(mp_impl->m_value_string).first;
+ parent->value.str.p = s.data();
+ parent->value.str.n = s.size();
+ break;
+ }
+ case detail::node_t::number:
+ parent->value.numeric = mp_impl->m_value_number;
+ break;
+ case detail::node_t::object:
+ {
+ // Currently only empty object instance is allowed.
+ assert(mp_impl->m_value_array.size() == 0);
+ parent->value.object = res.obj_pool_jvo.construct();
+ break;
+ }
+ case detail::node_t::array_implicit:
+ {
+ std::vector<json_value*> nodes;
+ bool object = true;
+ for (const detail::init::node& v2 : mp_impl->m_value_array)
+ {
+ json_value* r = v2.to_json_value(res);
+ if (r->type != detail::node_t::key_value)
+ object = false;
+ nodes.push_back(r);
+ }
+
+ if (object)
+ {
+ parent->type = detail::node_t::object;
+ aggregate_nodes_to_object(res, std::move(nodes), parent);
+ }
+ else
+ {
+ parent->type = detail::node_t::array;
+ aggregate_nodes_to_array(res, std::move(nodes), parent);
+ }
+
+ break;
+ }
+ case detail::node_t::array:
+ {
+ std::vector<json_value*> nodes;
+ for (const detail::init::node& v2 : mp_impl->m_value_array)
+ {
+ json_value* r = v2.to_json_value(res);
+ nodes.push_back(r);
+ }
+
+ aggregate_nodes_to_array(res, std::move(nodes), parent);
+ break;
+ }
+ case detail::node_t::boolean_true:
+ case detail::node_t::boolean_false:
+ case detail::node_t::null:
+ break;
+ case detail::node_t::key_value:
+ // fall-through
+ default:
+ {
+ std::ostringstream os;
+ os << "unknown node type (" << (int)mp_impl->m_type << ")";
+ throw document_error(os.str());
+ }
+ }
+}
+
+}} // namespace detail::init
+
+struct document_tree::impl
+{
+ json::json_value* m_root;
+ std::unique_ptr<document_resource> m_own_res;
+ document_resource& m_res;
+
+ impl() : m_root(nullptr), m_own_res(std::make_unique<document_resource>()), m_res(*m_own_res) {}
+ impl(document_resource& res) : m_root(nullptr), m_res(res) {}
+};
+
+const document_resource& document_tree::get_resource() const
+{
+ return mp_impl->m_res;
+}
+
+document_tree::document_tree() : mp_impl(std::make_unique<impl>()) {}
+document_tree::document_tree(document_tree&& other) : mp_impl(std::move(other.mp_impl)) {}
+document_tree::document_tree(document_resource& res) : mp_impl(std::make_unique<impl>(res)) {}
+
+document_tree::document_tree(std::initializer_list<detail::init::node> vs) :
+ mp_impl(std::make_unique<impl>())
+{
+ std::vector<json_value*> nodes;
+ bool object = true;
+ for (const detail::init::node& v : vs)
+ {
+ json_value* r = v.to_json_value(mp_impl->m_res);
+ if (r->type != detail::node_t::key_value)
+ object = false;
+ nodes.push_back(r);
+ }
+
+ mp_impl->m_root = aggregate_nodes(mp_impl->m_res, std::move(nodes), object);
+}
+
+document_tree::document_tree(array vs) : mp_impl(std::make_unique<impl>())
+{
+ json_value_array* jva = mp_impl->m_res.obj_pool_jva.construct();
+ mp_impl->m_root = mp_impl->m_res.obj_pool.construct(detail::node_t::array);
+ mp_impl->m_root->value.array = jva;
+
+ for (const detail::init::node& v : vs.m_vs)
+ {
+ json_value* r = v.to_json_value(mp_impl->m_res);
+ jva->value_array.push_back(r);
+ }
+}
+
+document_tree::document_tree(object /*obj*/) : mp_impl(std::make_unique<impl>())
+{
+ mp_impl->m_root = mp_impl->m_res.obj_pool.construct(detail::node_t::object);
+ mp_impl->m_root->value.object = mp_impl->m_res.obj_pool_jvo.construct();
+}
+
+document_tree::~document_tree() {}
+
+document_tree& document_tree::operator= (std::initializer_list<detail::init::node> vs)
+{
+ document_tree tmp(std::move(vs));
+ swap(tmp);
+ return *this;
+}
+
+document_tree& document_tree::operator= (array vs)
+{
+ document_tree tmp(std::move(vs));
+ swap(tmp);
+ return *this;
+}
+
+document_tree& document_tree::operator= (object obj)
+{
+ document_tree tmp(std::move(obj));
+ swap(tmp);
+ return *this;
+}
+
+void document_tree::load(std::string_view stream, const json_config& config)
+{
+ json::parser_handler hdl(config, mp_impl->m_res);
+ json_parser<json::parser_handler> parser(stream, hdl);
+ parser.parse();
+ mp_impl->m_root = hdl.get_root();
+
+ auto& external_refs = hdl.get_external_refs();
+
+ json_config ext_config = config;
+ // The stream will get destroyed after each parsing of an external json file.
+ ext_config.persistent_string_values = true;
+
+ fs::path parent_dir = config.input_path;
+ parent_dir = parent_dir.parent_path();
+ for (auto it = external_refs.begin(), ite = external_refs.end(); it != ite; ++it)
+ {
+ fs::path extfile = std::string{it->path};
+ fs::path extpath = parent_dir;
+ extpath /= extfile;
+
+ // Get the stream content from the path.
+ file_content ext_content(extpath.string().data());
+
+ ext_config.input_path = extpath.string();
+ document_tree doc(mp_impl->m_res);
+ try
+ {
+ doc.load(ext_content.str(), ext_config);
+ }
+ catch (const parse_error& e)
+ {
+ std::ostringstream os;
+ os << "Error while parsing " << extpath.string() << std::endl;
+ os << create_parse_error_output(ext_content.str(), e.offset()) << std::endl;
+ os << e.what();
+
+ // Re-throw as general_error to avoid getting caught as parse
+ // error by the parent caller.
+ throw general_error(os.str());
+ }
+
+ json::json_value* root = doc.mp_impl->m_root;
+ if (root->type == detail::node_t::object)
+ {
+ json::json_value_object* jvo_src = root->value.object;
+ json::json_value_object* jvo_dest = it->dest;
+ if (jvo_dest->value_object.size() == 1)
+ {
+ // Swap with the referenced object only when the destination
+ // has one child value i.e. it only has '$ref'.
+ jvo_dest->swap(*jvo_src);
+ jvo_dest->has_ref = false;
+ }
+ }
+ }
+}
+
+json::const_node document_tree::get_document_root() const
+{
+ json::json_value* p = mp_impl->m_root;
+ if (!p)
+ throw document_error("document tree is empty");
+
+ return json::const_node(this, p);
+}
+
+json::node document_tree::get_document_root()
+{
+ json::json_value* p = mp_impl->m_root;
+ if (!p)
+ throw document_error("document tree is empty");
+
+ return json::node(this, p);
+}
+
+std::string document_tree::dump() const
+{
+ if (!mp_impl->m_root)
+ return std::string();
+
+ return json::dump_json_tree(mp_impl->m_root);
+}
+
+std::string document_tree::dump_xml() const
+{
+ if (!mp_impl->m_root)
+ return std::string();
+
+ return json::dump_xml_tree(mp_impl->m_root);
+}
+
+std::string document_tree::dump_yaml() const
+{
+ json::yaml_dumper dumper;
+ return dumper.dump(mp_impl->m_root);
+}
+
+void document_tree::swap(document_tree& other)
+{
+ std::swap(mp_impl, other.mp_impl);
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_document_tree_test.cpp b/src/liborcus/json_document_tree_test.cpp
new file mode 100644
index 0000000..3ab6876
--- /dev/null
+++ b/src/liborcus/json_document_tree_test.cpp
@@ -0,0 +1,862 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "test_global.hpp"
+
+#include <orcus/stream.hpp>
+#include <orcus/json_document_tree.hpp>
+#include <orcus/json_parser_base.hpp>
+#include <orcus/config.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <orcus/dom_tree.hpp>
+
+#include "filesystem_env.hpp"
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <cmath>
+#include <cstring>
+
+using namespace orcus;
+
+fs::path json_test_dirs[] = {
+ SRCDIR"/test/json/basic1",
+ SRCDIR"/test/json/basic2",
+ SRCDIR"/test/json/basic3",
+ SRCDIR"/test/json/basic4",
+ SRCDIR"/test/json/empty-array-1",
+ SRCDIR"/test/json/empty-array-2",
+ SRCDIR"/test/json/empty-array-3",
+ SRCDIR"/test/json/nested1",
+ SRCDIR"/test/json/nested2",
+ SRCDIR"/test/json/swagger",
+ SRCDIR"/test/json/to-yaml-1",
+};
+
+fs::path json_test_refs_dirs[] = {
+ SRCDIR"/test/json/refs1",
+};
+
+bool string_expected(const json::const_node& node, const char* expected)
+{
+ if (node.type() != json::node_t::string)
+ return false;
+
+ if (node.string_value() == expected)
+ return true;
+
+ std::cerr << "expected='" << expected << "', actual='" << node.string_value() << "'" << std::endl;
+ return false;
+}
+
+bool number_expected(
+ const json::const_node& node, double expected,
+ double decimal = 0.0, double exponent = 0.0)
+{
+ if (node.type() != json::node_t::number)
+ return false;
+
+ double actual = node.numeric_value();
+ if (!decimal || !exponent)
+ return actual == expected;
+
+ // Remove the exponent component.
+ actual /= std::pow(10.0, exponent);
+ expected /= std::pow(10.0, exponent);
+
+ // Only compare down to the specified decimal place.
+ actual *= std::pow(10.0, decimal);
+ expected *= std::pow(10.0, decimal);
+
+ actual = std::round(actual);
+ expected = std::round(expected);
+
+ if (actual == expected)
+ return true;
+
+ std::cerr << "expected=" << expected << ", actual=" << actual << std::endl;
+ return false;
+}
+
+std::string dump_check_content(const json::document_tree& doc)
+{
+ std::string xml_strm = doc.dump_xml();
+ assert(!xml_strm.empty());
+
+ xmlns_repository repo;
+ xmlns_context cxt = repo.create_context();
+ dom::document_tree dom(cxt);
+ dom.load(xml_strm);
+
+ std::ostringstream os;
+ dom.dump_compact(os);
+ return os.str();
+}
+
+bool compare_check_contents(const file_content& expected, const std::string& actual)
+{
+ std::string_view _expected(expected.data(), expected.size());
+ std::string_view _actual(actual.data(), actual.size());
+ _expected = trim(_expected);
+ _actual = trim(_actual);
+
+ if (_expected != _actual)
+ {
+ std::size_t pos = locate_first_different_char(_expected, _actual);
+ std::cout << create_parse_error_output(_expected, pos) << std::endl;
+ std::cout << create_parse_error_output(_actual, pos) << std::endl;
+ }
+
+ return _expected == _actual;
+}
+
+void verify_input(json_config& test_config, const fs::path& basedir)
+{
+ fs::path json_file = basedir / "input.json";
+ test_config.input_path = json_file.string();
+
+ std::cout << "* verify input: " << json_file << std::endl;
+
+ file_content content(json_file.string());
+ json::document_tree doc;
+ doc.load(content.str(), test_config);
+
+ fs::path check_file = basedir / "check.txt";
+ file_content check_master(check_file.string());
+ std::string check_doc = dump_check_content(doc);
+
+ bool result = compare_check_contents(check_master, check_doc);
+ assert(result);
+
+ if (fs::path outpath = basedir / "output.yaml"; fs::is_regular_file(outpath))
+ {
+ // Test the yaml output.
+ std::cout << " * yaml output: " << outpath << std::endl;
+
+ file_content expected(outpath.string());
+ std::string actual = doc.dump_yaml();
+
+ test::verify_content(__FILE__, __LINE__, expected.str(), actual);
+ }
+}
+
+void test_json_parse()
+{
+ json_config test_config;
+
+ for (std::size_t i = 0; i < std::size(json_test_dirs); ++i)
+ {
+ fs::path basedir = json_test_dirs[i];
+ verify_input(test_config, basedir);
+ }
+}
+
+void test_json_resolve_refs()
+{
+ json_config test_config;
+ test_config.resolve_references = true;
+
+ for (size_t i = 0; i < std::size(json_test_refs_dirs); ++i)
+ {
+ fs::path basedir = json_test_refs_dirs[i];
+ verify_input(test_config, basedir);
+ }
+}
+
+void test_json_parse_empty()
+{
+ json_config test_config;
+
+ const char* tests[] = {
+ "{}",
+ "[]",
+ "{\"key1\": {}, \"key2\": {}}"
+ };
+
+ for (size_t i = 0; i < std::size(tests); ++i)
+ {
+ const char* test = tests[i];
+ std::cout << "JSON stream: '" << test << "' (" << std::strlen(test) << ")" << std::endl;
+ json::document_tree doc;
+ try
+ {
+ doc.load(test, test_config);
+ }
+ catch (const parse_error& e)
+ {
+ std::cout << create_parse_error_output(test, e.offset()) << std::endl;
+ std::cout << e.what() << std::endl;
+ assert(false);
+ }
+ }
+}
+
+void test_json_parse_invalid()
+{
+ json_config test_config;
+
+ const char* invalids[] = {
+ "[foo]",
+ "[qwerty]",
+ "[1,2] null",
+ "{\"key\" 1: 12}",
+ "[1,,2]",
+ "\"key\": {\"inner\": 12}"
+ };
+
+ for (std::size_t i = 0; i < std::size(invalids); ++i)
+ {
+ const char* invalid_json = invalids[i];
+ json::document_tree doc;
+ try
+ {
+ doc.load(invalid_json, test_config);
+ std::cerr << "Invalid JSON expression is parsed as valid: '" << invalid_json << "'" << std::endl;
+ assert(false);
+ }
+ catch (const parse_error& e)
+ {
+ // works as expected.
+ std::cout << "invalid expression tested: " << invalid_json << std::endl;
+ std::cout << "error message received: " << e.what() << std::endl;
+ }
+ }
+}
+
+std::unique_ptr<json::document_tree> get_doc_tree(const char* filepath)
+{
+ json_config test_config;
+
+ std::cout << filepath << std::endl;
+ file_content content(filepath);
+ std::cout << "--- original" << std::endl;
+ std::cout << content.str() << std::endl;
+
+ auto doc = std::make_unique<json::document_tree>();
+ doc->load(content.str(), test_config);
+
+ return doc;
+}
+
+void dump_and_load(
+ const json::document_tree& doc, const std::function<void(json::const_node)>& test_func)
+{
+ json::document_tree doc2;
+ std::string dumped = doc.dump();
+ std::cout << "--- dumped" << std::endl;
+ std::cout << dumped << std::endl;
+ doc2.load(dumped, json_config());
+ json::const_node node = doc2.get_document_root();
+ test_func(node);
+}
+
+void test_json_traverse_basic1()
+{
+ auto test_func = [](json::const_node node)
+ {
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+ assert(node.child(0).type() == json::node_t::boolean_true);
+ assert(node.child(1).type() == json::node_t::boolean_false);
+ assert(node.child(2).type() == json::node_t::null);
+
+ // Move to child node and move back.
+ json::const_node node2 = node.child(0).parent();
+ assert(node.identity() == node2.identity());
+ };
+
+ const char* filepath = SRCDIR"/test/json/basic1/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_traverse_basic2()
+{
+ auto test_func = [](json::const_node node)
+ {
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 14);
+
+ assert(string_expected(node.child(0), "I am string"));
+ assert(string_expected(node.child(1), "me too"));
+ assert(string_expected(node.child(2), ""));
+ assert(string_expected(node.child(3), "\\"));
+ assert(string_expected(node.child(4), "/"));
+ assert(string_expected(node.child(5), "\\b"));
+ assert(string_expected(node.child(6), "\\f"));
+ assert(string_expected(node.child(7), "\\n"));
+ assert(string_expected(node.child(8), "\\r"));
+ assert(string_expected(node.child(9), "\\t"));
+ assert(string_expected(node.child(10), "\"quoted\""));
+ assert(string_expected(node.child(11), "http://www.google.com"));
+ assert(string_expected(node.child(12), "one \\n two \\n three"));
+ assert(string_expected(node.child(13), "front segment 'single quote' and \"double quote\" end segment"));
+ };
+
+ const char* filepath = SRCDIR"/test/json/basic2/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_traverse_basic3()
+{
+ auto test_func = [](json::const_node node)
+ {
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 9);
+
+ assert(number_expected(node.child(0), 0.0));
+ assert(number_expected(node.child(1), 1.0));
+ assert(number_expected(node.child(2), 2.0));
+ assert(number_expected(node.child(3), 15.0));
+ assert(number_expected(node.child(4), 12.34));
+ assert(number_expected(node.child(5), -0.12));
+ assert(number_expected(node.child(6), 1.2e+22, 1.0, 22.0));
+ assert(number_expected(node.child(7), 1.11e-7, 2.0, -7.0));
+ assert(number_expected(node.child(8), 11E2));
+ };
+
+ const char* filepath = SRCDIR"/test/json/basic3/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_traverse_basic4()
+{
+ auto test_func = [](json::const_node node)
+ {
+ assert(node.type() == json::node_t::object);
+ auto keys = node.keys();
+ assert(keys.size() == 3);
+ for (auto it = keys.begin(), ite = keys.end(); it != ite; ++it)
+ {
+ std::string_view key = *it;
+ json::const_node child = node.child(key);
+ if (key == "int")
+ assert(number_expected(child, 12.0));
+ else if (key == "float")
+ assert(number_expected(child, 0.125));
+ else if (key == "string")
+ assert(string_expected(child, "blah..."));
+ else
+ assert(!"unexpected key");
+ }
+ };
+
+ const char* filepath = SRCDIR"/test/json/basic4/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_traverse_nested1()
+{
+ auto test_func = [](json::const_node node)
+ {
+ uintptr_t root_id = node.identity();
+
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 1);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+
+ assert(number_expected(node.child(0), 1.0));
+ assert(number_expected(node.child(1), 2.0));
+ assert(number_expected(node.child(2), 3.0));
+
+ node = node.parent();
+ assert(node.identity() == root_id);
+ };
+
+ const char* filepath = SRCDIR"/test/json/nested1/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_traverse_nested2()
+{
+ auto test_func = [](json::const_node node)
+ {
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::object);
+ assert(number_expected(node.child("value"), 1.0));
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == json::node_t::object);
+ assert(number_expected(node.child("value"), 2.0));
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == json::node_t::object);
+ assert(number_expected(node.child("value"), 3.0));
+ node = node.parent();
+ };
+
+ const char* filepath = SRCDIR"/test/json/nested2/input.json";
+ std::unique_ptr<json::document_tree> doc = get_doc_tree(filepath);
+ json::const_node node = doc->get_document_root();
+ test_func(node);
+ dump_and_load(*doc, test_func);
+}
+
+void test_json_init_list_flat1()
+{
+ json::document_tree doc = { 1.0, 2.0, 3.0, 4.0 };
+ json::const_node node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 4);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 1.0);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 2.0);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 3.0);
+ node = node.parent();
+
+ node = node.child(3);
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 4.0);
+ node = node.parent();
+
+ // Use iterators.
+ auto it = node.begin();
+ assert(it->type() == json::node_t::number);
+ assert(it->numeric_value() == 1.0);
+ ++it;
+ assert(it->type() == json::node_t::number);
+ assert(it->numeric_value() == 2.0);
+ auto test = it++; // post increment
+ assert(test->numeric_value() == 2.0);
+ assert(it->type() == json::node_t::number);
+ assert(it->numeric_value() == 3.0);
+ test = ++it; // pre increment
+ assert(test->numeric_value() == 4.0);
+ ++it;
+ assert(it == node.end());
+ --it;
+ assert(it->numeric_value() == 4.0);
+ test = it--;
+ assert(test->numeric_value() == 4.0);
+ assert(it->numeric_value() == 3.0);
+
+ doc = { nullptr };
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 1);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::null);
+
+ doc = { true, false };
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::boolean_true);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == json::node_t::boolean_false);
+ node = node.parent();
+
+ doc = { "A", "B", "C" };
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "A");
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "B");
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "C");
+}
+
+void test_json_init_list_nested1()
+{
+ json::document_tree doc = {
+ { true, false, nullptr },
+ { 1.1, 2.2, "text" }
+ };
+
+ json::const_node node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+ assert(node.child(0).type() == json::node_t::boolean_true);
+ assert(node.child(1).type() == json::node_t::boolean_false);
+ assert(node.child(2).type() == json::node_t::null);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+ assert(node.child(0).type() == json::node_t::number);
+ assert(node.child(0).numeric_value() == 1.1);
+ assert(node.child(1).type() == json::node_t::number);
+ assert(node.child(1).numeric_value() == 2.2);
+ assert(node.child(2).type() == json::node_t::string);
+ assert(node.child(2).string_value() == "text");
+}
+
+void test_json_init_list_object1()
+{
+ json::document_tree doc = {
+ { "key1", 1.2 },
+ { "key2", "some text" },
+ };
+
+ json::const_node node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 2);
+ assert(node.key(0) == "key1");
+ assert(node.key(1) == "key2");
+
+ node = node.child("key1");
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 1.2);
+ node = node.parent();
+
+ node = node.child("key2");
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "some text");
+}
+
+void test_json_init_list_object2()
+{
+ // nested objects.
+ json::document_tree doc = {
+ { "parent1",
+ {
+ { "child1", true },
+ { "child2", false },
+ { "child3", 123.4 },
+ }
+ },
+ { "parent2", "not-nested" },
+ };
+
+ json::const_node node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 2);
+ assert(node.key(0) == "parent1");
+ assert(node.key(1) == "parent2");
+
+ node = node.child("parent1");
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 3);
+ assert(node.key(0) == "child1");
+ assert(node.key(1) == "child2");
+ assert(node.key(2) == "child3");
+
+ assert(node.child("child1").type() == json::node_t::boolean_true);
+ assert(node.child("child2").type() == json::node_t::boolean_false);
+ assert(node.child("child3").type() == json::node_t::number);
+ assert(node.child("child3").numeric_value() == 123.4);
+
+ node = node.parent();
+
+ node = node.child("parent2");
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "not-nested");
+}
+
+void test_json_init_list_explicit_array()
+{
+ try
+ {
+ // This structure is too ambiguous and cannot be implicitly
+ // determined.
+ json::document_tree doc = {
+ { "array", { "one", 987.0 } }
+ };
+ assert(!"key_value_error was not thrown");
+ }
+ catch (const json::key_value_error&)
+ {
+ // expected.
+ }
+
+ // Explicitly define an array instead.
+ json::document_tree doc = {
+ { "array", json::array({ "one", 987.0 }) }
+ };
+
+ json::node node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 1);
+ assert(node.key(0) == "array");
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2);
+ assert(node.child(0).string_value() == "one");
+ assert(node.child(1).numeric_value() == 987.0);
+
+ doc = json::array({1, 2, 3});
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+ assert(node.child(0).numeric_value() == 1.0);
+ assert(node.child(1).numeric_value() == 2.0);
+ assert(node.child(2).numeric_value() == 3.0);
+
+ node.push_back(4);
+ node.push_back(5);
+ assert(node.child_count() == 5);
+ assert(node.child(3).numeric_value() == 4.0);
+ assert(node.child(4).numeric_value() == 5.0);
+
+ // empty JSON with array root.
+ json::document_tree doc2 = json::array();
+ node = doc2.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 0);
+
+ // Assigning a non-const node to a const one should work.
+ json::const_node cnode = node;
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 0);
+}
+
+void test_json_init_list_explicit_object()
+{
+ json::document_tree doc = json::object();
+ json::node node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 0);
+
+ // Initialize with an array of 3 empty objects.
+ doc = {
+ json::object(),
+ json::object(),
+ json::object()
+ };
+
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+
+ for (size_t i = 0; i < 3; ++i)
+ {
+ node = node.child(i);
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 0);
+ node = node.parent();
+ }
+}
+
+void test_json_init_root_object_add_child()
+{
+ json::document_tree doc = json::object();
+ json::node node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 0);
+
+ node["child1"] = 1.0;
+
+ assert(node.child_count() == 1);
+
+ node = node.child("child1");
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 1.0);
+
+ node = node.parent();
+ node["child2"] = "foo";
+
+ assert(node.child_count() == 2);
+
+ node = node.child("child2");
+ assert(node.type() == json::node_t::string);
+ assert(node.string_value() == "foo");
+
+ node = node.parent();
+
+ // Access to child via [] operator.
+ node = node["child1"];
+ assert(node.type() == json::node_t::number);
+ assert(node.numeric_value() == 1.0);
+
+ node = node.parent();
+ node["child3"] = { true, false };
+
+ node = node.child("child3");
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2);
+
+ node = node.child(0);
+ assert(node.type() == json::node_t::boolean_true);
+
+ // Move up to the parent array.
+ node = node.parent();
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2);
+
+ // Move down to the other child node.
+ node = node.child(1);
+ assert(node.type() == json::node_t::boolean_false);
+
+ // Move up to the root node.
+ node = node.parent().parent();
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 3);
+
+ node["child1"] = true; // overwrite an existing node.
+ node = node.child("child1");
+ assert(node.type() == json::node_t::boolean_true);
+
+ // direct assignment.
+ node = false;
+ assert(node.type() == json::node_t::boolean_false);
+
+ node = node.parent().child("child1"); // make sure the link is still intact.
+ assert(node.type() == json::node_t::boolean_false);
+
+ node = node.parent();
+ node["null-child"] = nullptr;
+
+ node = node.child("null-child");
+ assert(node.type() == json::node_t::null);
+
+ node = node.parent();
+ node["object-child"] = json::object();
+
+ node = node.child("object-child");
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 0);
+
+ node["array"] = json::array({true, false, nullptr});
+
+ node = node.child("array");
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 3);
+
+ node = node.parent();
+ node["nested-object"] =
+ {
+ { "key1", "foo" },
+ { "key2", 12.34 }
+ };
+
+ node = node.child("nested-object");
+ assert(node.type() == json::node_t::object);
+ assert(node.child_count() == 2);
+ assert(node.child("key1").string_value() == "foo");
+ assert(node.child("key2").numeric_value() == 12.34);
+}
+
+void test_json_init_empty_array()
+{
+ json::document_tree doc = json::array();
+ json::node node = doc.get_document_root();
+ assert(node.type() == json::node_t::array);
+
+ doc = {
+ { "key1", json::array({true, false}) },
+ { "key2", json::array() } // empty array
+ };
+
+ node = doc.get_document_root();
+ assert(node.type() == json::node_t::object);
+ node = node["key1"];
+ assert(node.type() == json::node_t::array);
+ node = node.parent()["key2"];
+ assert(node.type() == json::node_t::array);
+}
+
+void test_json_dynamic_object_keys()
+{
+ json::document_tree doc = json::object();
+ json::node root = doc.get_document_root();
+
+ /* {"test": [1.2, 1.3]} */
+ auto node = root["test"];
+ node = json::array();
+ node.push_back(1.2);
+ node.push_back(1.3);
+
+ // Dump the doc as a string and reload it.
+ doc.load(doc.dump(), json_config());
+ root = doc.get_document_root();
+ assert(root.type() == json::node_t::object);
+ node = root["test"];
+ assert(node.type() == json::node_t::array);
+ assert(node.child_count() == 2u);
+ assert(node.child(0).numeric_value() == 1.2);
+ assert(node.child(1).numeric_value() == 1.3);
+}
+
+int main()
+{
+ try
+ {
+ test_json_parse();
+ test_json_resolve_refs();
+ test_json_parse_empty();
+ test_json_parse_invalid();
+ test_json_traverse_basic1();
+ test_json_traverse_basic2();
+ test_json_traverse_basic3();
+ test_json_traverse_basic4();
+ test_json_traverse_nested1();
+ test_json_traverse_nested2();
+
+ test_json_init_list_flat1();
+ test_json_init_list_nested1();
+ test_json_init_list_object1();
+ test_json_init_list_object2();
+ test_json_init_list_explicit_array();
+ test_json_init_list_explicit_object();
+ test_json_init_root_object_add_child();
+ test_json_init_empty_array();
+ test_json_dynamic_object_keys();
+ }
+ catch (const orcus::general_error& e)
+ {
+ std::cerr << e.what() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_map_tree.cpp b/src/liborcus/json_map_tree.cpp
new file mode 100644
index 0000000..294e782
--- /dev/null
+++ b/src/liborcus/json_map_tree.cpp
@@ -0,0 +1,786 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "json_map_tree.hpp"
+#include "orcus/measurement.hpp"
+
+#include <iostream>
+#include <sstream>
+
+namespace orcus {
+
+constexpr json_map_tree::child_position_type json_map_tree::node_child_default_position;
+
+namespace {
+
+void throw_path_error(const char* file, int line, std::string_view path)
+{
+ std::ostringstream os;
+ os << file << "#" << line << ": failed to link this path '" << path << "'";
+ throw json_map_tree::path_error(os.str());
+}
+
+enum class json_path_token_t { unknown, array_pos, object_key, end };
+
+struct json_path_token_value_t
+{
+ json_path_token_t type = json_path_token_t::unknown;
+
+ union
+ {
+ json_map_tree::child_position_type array_pos = json_map_tree::node_child_default_position;
+
+ struct
+ {
+ const char* p;
+ size_t n;
+
+ } str;
+
+ } value;
+
+ json_path_token_value_t(json_path_token_t _type) : type(_type) {}
+
+ json_path_token_value_t(json_map_tree::child_position_type array_pos): type(json_path_token_t::array_pos)
+ {
+ value.array_pos = array_pos;
+ }
+
+ json_path_token_value_t(const char* p, size_t n) : type(json_path_token_t::object_key)
+ {
+ value.str.p = p;
+ value.str.n = n;
+ }
+};
+
+std::string_view get_last_object_key(const std::vector<json_path_token_value_t>& stack)
+{
+ if (stack.size() < 2)
+ return std::string_view{};
+
+ auto it = stack.rbegin();
+ ++it;
+ const json_path_token_value_t& t2 = *it;
+ if (t2.type != json_path_token_t::object_key)
+ return std::string_view{};
+
+ return std::string_view{t2.value.str.p, t2.value.str.n};
+}
+
+class json_path_parser
+{
+ const char* mp_cur;
+ const char* mp_end;
+
+public:
+
+ json_path_parser(std::string_view path) :
+ mp_cur(path.data()),
+ mp_end(mp_cur + path.size())
+ {
+ assert(!path.empty());
+ assert(path[0] == '$');
+ ++mp_cur; // skip the first '$'.
+ }
+
+ json_path_token_value_t next()
+ {
+ if (mp_cur == mp_end)
+ return json_path_token_t::end;
+
+ if (*mp_cur == '[')
+ return next_pos();
+
+ return json_path_token_t::unknown;
+ }
+
+ json_path_token_value_t next_object_key()
+ {
+ assert(*mp_cur == '\'');
+ ++mp_cur;
+ const char* p_head = mp_cur;
+
+ for (; mp_cur != mp_end && *mp_cur != '\''; ++mp_cur)
+ {
+ // Skip until we reach the closing quote.
+ }
+
+ if (*mp_cur != '\'')
+ return json_path_token_t::unknown;
+
+ size_t n = std::distance(p_head, mp_cur);
+
+ ++mp_cur; // Skip the quote.
+ if (*mp_cur != ']')
+ return json_path_token_t::unknown;
+
+ ++mp_cur; // Skip the ']'.
+
+ return json_path_token_value_t(p_head, n);
+ }
+
+ json_path_token_value_t next_pos()
+ {
+ assert(*mp_cur == '[');
+ ++mp_cur; // Skip the '['.
+
+ if (mp_cur == mp_end)
+ return json_path_token_t::unknown;
+
+ if (*mp_cur == '\'')
+ return next_object_key();
+
+ const char* p_head = mp_cur;
+
+ for (; mp_cur != mp_end; ++mp_cur)
+ {
+ if (*mp_cur != ']')
+ continue;
+
+ if (p_head == mp_cur)
+ {
+ // empty brackets.
+ ++mp_cur;
+ return json_map_tree::node_child_default_position;
+ }
+
+ const char* p_parse_ended = nullptr;
+ std::size_t n = mp_cur - p_head;
+ long pos = to_long({p_head, n}, &p_parse_ended);
+
+ if (p_parse_ended != mp_cur)
+ // Parsing failed.
+ break;
+
+ if (pos < 0)
+ // array position cannot be negative.
+ break;
+
+ ++mp_cur; // skip the ']'.
+ return pos;
+ }
+
+ return json_path_token_t::unknown;
+ }
+};
+
+} // anonymous namespace
+
+json_map_tree::path_error::path_error(const std::string& msg) :
+ general_error(msg) {}
+
+json_map_tree::cell_reference_type::cell_reference_type(const cell_position_t& _pos) :
+ pos(_pos) {}
+
+json_map_tree::range_reference_type::range_reference_type(const cell_position_t& _pos) :
+ pos(_pos), row_position(0), row_header(false) {}
+
+json_map_tree::node::node() {}
+json_map_tree::node::node(node&& other) :
+ type(other.type)
+{
+ value.children = nullptr;
+
+ switch (type)
+ {
+ case map_node_type::array:
+ value.children = other.value.children;
+ other.value.children = nullptr;
+ break;
+ case map_node_type::cell_ref:
+ value.cell_ref = other.value.cell_ref;
+ other.value.cell_ref = nullptr;
+ break;
+ case map_node_type::range_field_ref:
+ value.range_field_ref = other.value.range_field_ref;
+ other.value.range_field_ref = nullptr;
+ default:
+ ;
+ }
+
+ other.type = map_node_type::unknown;
+
+ row_group = other.row_group;
+ other.row_group = nullptr;
+
+ anchored_fields = std::move(other.anchored_fields);
+}
+
+json_map_tree::node& json_map_tree::node::get_or_create_child_node(child_position_type pos)
+{
+ node_children_type& children = *value.children;
+
+ auto it = children.lower_bound(pos); // get the first position where pos <= k is true.
+
+ if (it == children.end() || children.key_comp()(pos, it->first))
+ {
+ // Insert a new array child node of unspecified type at the specified position.
+ it = children.insert(
+ it, node_children_type::value_type(pos, node()));
+ }
+
+ assert(it->first == pos);
+ return it->second;
+}
+
+json_map_tree::walker::scope::scope(node* _p) : p(_p), array_position(0) {}
+
+json_map_tree::walker::walker(const json_map_tree& parent) : m_parent(parent) {}
+
+json_map_tree::node* json_map_tree::walker::push_node(input_node_type nt)
+{
+ if (!m_unlinked_stack.empty())
+ {
+ // We're still in the unlinked region.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ if (m_stack.empty())
+ {
+ if (!m_parent.m_root)
+ {
+ // Tree is empty.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ node* p = m_parent.m_root.get();
+
+ if (!is_equivalent(nt, p->type))
+ {
+ // Different node type.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ m_stack.push_back(p);
+ return m_stack.back().p;
+ }
+
+ scope& cur_scope = m_stack.back();
+
+ switch (cur_scope.p->type)
+ {
+ case json_map_tree::map_node_type::array:
+ {
+ node_children_type& node_children = *cur_scope.p->value.children;
+
+ auto it = node_children.find(cur_scope.array_position++);
+ if (it == node_children.end())
+ it = node_children.find(json_map_tree::node_child_default_position);
+
+ if (it == node_children.end())
+ {
+ // This array node has no children.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ node* p = &it->second;
+
+ if (!is_equivalent(nt, p->type))
+ {
+ // Different node type.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ m_stack.push_back(p);
+ return m_stack.back().p;
+ }
+ case json_map_tree::map_node_type::object:
+ {
+ node_children_type& node_children = *cur_scope.p->value.children;
+ auto it = node_children.find(cur_scope.array_position);
+ if (it == node_children.end())
+ {
+ // The currently specified key does not exist in this object.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ node* p = &it->second;
+
+ if (!is_equivalent(nt, p->type))
+ {
+ // Different node type.
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+ }
+
+ m_stack.push_back(p);
+ return m_stack.back().p;
+ }
+ default:
+ ;
+ }
+
+ m_unlinked_stack.push_back(nt);
+ return nullptr;
+}
+
+json_map_tree::node* json_map_tree::walker::pop_node(input_node_type nt)
+{
+ if (!m_unlinked_stack.empty())
+ {
+ // We're in the unlinked region. Pop a node from the unlinked stack.
+ if (m_unlinked_stack.back() != nt)
+ throw general_error("Closing node is of different type than the opening node in the unlinked node stack.");
+
+ m_unlinked_stack.pop_back();
+
+ if (!m_unlinked_stack.empty())
+ // We are still in the unlinked region.
+ return nullptr;
+
+ return m_stack.empty() ? nullptr : m_stack.back().p;
+ }
+
+ if (m_stack.empty())
+ throw general_error("A node was popped while the stack was empty.");
+
+ if (!is_equivalent(nt, m_stack.back().p->type))
+ throw general_error("Closing node is of different type than the opening node in the linked node stack.");
+
+ m_stack.pop_back();
+ return m_stack.empty() ? nullptr : m_stack.back().p;
+}
+
+void json_map_tree::walker::set_object_key(const char* p, size_t n)
+{
+ if (!m_unlinked_stack.empty())
+ return;
+
+ if (m_stack.empty())
+ return;
+
+ scope& cur_scope = m_stack.back();
+ if (cur_scope.p->type != map_node_type::object)
+ return;
+
+ std::string_view pooled = m_parent.m_str_pool.intern({p, n}).first;
+ cur_scope.array_position = reinterpret_cast<child_position_type>(pooled.data());
+}
+
+json_map_tree::json_map_tree() {}
+json_map_tree::~json_map_tree() {}
+
+json_map_tree::walker json_map_tree::get_tree_walker() const
+{
+ return walker(*this);
+}
+
+void json_map_tree::set_cell_link(std::string_view path, const cell_position_t& pos)
+{
+ path_stack_type stack = get_or_create_destination_node(path);
+ if (stack.node_stack.empty())
+ return;
+
+ node* p = stack.node_stack.back();
+ if (p->type != map_node_type::unknown)
+ {
+ std::ostringstream os;
+ os << "this path is not linkable: '" << path << '\'';
+ throw path_error(os.str());
+ }
+
+ p->type = map_node_type::cell_ref;
+ p->value.cell_ref = m_cell_ref_pool.construct(pos);
+
+ // Ensure that this tree owns the instance of the string.
+ p->value.cell_ref->pos.sheet = m_str_pool.intern(p->value.cell_ref->pos.sheet).first;
+}
+
+const json_map_tree::node* json_map_tree::get_link(std::string_view path) const
+{
+ return get_destination_node(path);
+}
+
+void json_map_tree::start_range(const cell_position_t& pos, bool row_header)
+{
+ m_current_range.pos = pos;
+ m_current_range.fields.clear();
+ m_current_range.row_groups.clear();
+ m_current_range.row_header = row_header;
+}
+
+void json_map_tree::append_field_link(std::string_view path, std::string_view label)
+{
+ m_current_range.fields.emplace_back(path, label);
+}
+
+void json_map_tree::set_range_row_group(std::string_view path)
+{
+ m_current_range.row_groups.push_back(path);
+}
+
+void json_map_tree::commit_range()
+{
+ range_reference_type* ref = &get_range_reference(m_current_range.pos);
+ ref->row_header = m_current_range.row_header;
+ spreadsheet::col_t column_pos = 0;
+
+ for (std::string_view path : m_current_range.row_groups)
+ {
+ path_stack_type stack = get_or_create_destination_node(path);
+ if (stack.node_stack.empty())
+ throw_path_error(__FILE__, __LINE__, path);
+
+ stack.node_stack.back()->row_group = ref;
+ }
+
+ long unlabeled_field_count = 0;
+
+ for (const auto& field : m_current_range.fields)
+ {
+ std::string_view path = field.first;
+ std::string_view label = field.second;
+
+ path_stack_type stack = get_or_create_destination_node(path);
+ if (stack.node_stack.empty() || stack.node_stack.back()->type != map_node_type::unknown)
+ throw_path_error(__FILE__, __LINE__, path);
+
+ node* p = stack.node_stack.back();
+ p->type = map_node_type::range_field_ref;
+ p->value.range_field_ref = m_range_field_ref_pool.construct();
+ p->value.range_field_ref->column_pos = column_pos++;
+ p->value.range_field_ref->ref = ref;
+
+ if (!label.empty())
+ {
+ // A custom label is specified. This one takes precedence.
+ p->value.range_field_ref->label = m_str_pool.intern(label).first;
+ }
+ else if (stack.dest_key.empty())
+ {
+ // This field is probably associated with an array.
+ std::ostringstream os;
+ os << "field " << unlabeled_field_count++;
+ p->value.range_field_ref->label = m_str_pool.intern(os.str()).first;
+ }
+ else
+ // This field is associated with an object key. Use its key as the label.
+ p->value.range_field_ref->label = m_str_pool.intern(stack.dest_key).first;
+
+ ref->fields.push_back(p->value.range_field_ref);
+
+ // Find the first row group node ancountered going up from the field
+ // node, and anchor itself to it.
+ for (auto it = stack.node_stack.rbegin(); it != stack.node_stack.rend(); ++it)
+ {
+ node* anchor_node = *it;
+ if (anchor_node->row_group)
+ {
+ anchor_node->anchored_fields.push_back(p);
+ break;
+ }
+ }
+ }
+}
+
+json_map_tree::range_ref_store_type& json_map_tree::get_range_references()
+{
+ return m_range_refs;
+}
+
+json_map_tree::range_reference_type& json_map_tree::get_range_reference(const cell_position_t& pos)
+{
+ auto it = m_range_refs.lower_bound(pos);
+ if (it == m_range_refs.end() || m_range_refs.key_comp()(m_current_range.pos, it->first))
+ {
+ // Ensure that we own the sheet name instance before storing it.
+ m_current_range.pos.sheet = m_str_pool.intern(m_current_range.pos.sheet).first;
+
+ it = m_range_refs.insert(
+ it, range_ref_store_type::value_type(
+ m_current_range.pos, range_reference_type(m_current_range.pos)));
+ }
+
+ return it->second;
+}
+
+const json_map_tree::node* json_map_tree::get_destination_node(std::string_view path) const
+{
+ if (!m_root)
+ // The tree is empty.
+ return nullptr;
+
+ if (path.empty() || path[0] != '$')
+ // A valid path must begin with a '$'.
+ return nullptr;
+
+ json_path_parser parser(path);
+ const node* cur_node = m_root.get();
+
+ for (json_path_token_value_t t = parser.next(); t.type != json_path_token_t::unknown; t = parser.next())
+ {
+ switch (t.type)
+ {
+ case json_path_token_t::array_pos:
+ {
+ if (cur_node->type != map_node_type::array)
+ return nullptr;
+
+ auto it = cur_node->value.children->find(t.value.array_pos);
+ if (it == cur_node->value.children->end())
+ return nullptr;
+
+ cur_node = &it->second;
+ break;
+ }
+ case json_path_token_t::object_key:
+ {
+ if (cur_node->type != map_node_type::object)
+ return nullptr;
+
+ child_position_type pos = to_key_position(t.value.str.p, t.value.str.n);
+
+ auto it = cur_node->value.children->find(pos);
+ if (it == cur_node->value.children->end())
+ return nullptr;
+
+ cur_node = &it->second;
+ break;
+ }
+ case json_path_token_t::end:
+ return cur_node;
+ case json_path_token_t::unknown:
+ default:
+ // Something has gone wrong. Bail out.
+ break;
+ }
+ }
+
+ // If this code path reaches here, something has gone wrong.
+ return nullptr;
+}
+
+json_map_tree::path_stack_type json_map_tree::get_or_create_destination_node(std::string_view path)
+{
+ path_stack_type stack;
+
+ if (path.empty() || path[0] != '$')
+ // A valid path must begin with a '$'.
+ return stack;
+
+ json_path_parser parser(path);
+ json_path_token_value_t t = parser.next();
+
+ std::vector<json_path_token_value_t> token_stack;
+ token_stack.push_back(t);
+
+ switch (t.type)
+ {
+ case json_path_token_t::array_pos:
+ {
+ // Insert or re-use an array node and its child at specified position.
+
+ if (m_root)
+ {
+ if (m_root->type == map_node_type::unknown)
+ {
+ m_root->type = map_node_type::array;
+ m_root->value.children = m_node_children_pool.construct();
+ }
+
+ if (m_root->type != map_node_type::array)
+ throw path_error("root node was expected to be of type array, but is not.");
+ }
+ else
+ {
+ m_root = std::make_unique<node>();
+ m_root->type = map_node_type::array;
+ m_root->value.children = m_node_children_pool.construct();
+ }
+
+ stack.node_stack.push_back(m_root.get());
+ node* p = &stack.node_stack.back()->get_or_create_child_node(t.value.array_pos);
+ stack.node_stack.push_back(p);
+ break;
+ }
+ case json_path_token_t::object_key:
+ {
+ if (m_root)
+ {
+ if (m_root->type == map_node_type::unknown)
+ {
+ m_root->type = map_node_type::object;
+ m_root->value.children = m_node_children_pool.construct();
+ }
+
+ if (m_root->type != map_node_type::object)
+ throw path_error("root node was expected to be of type array, but is not.");
+ }
+ else
+ {
+ m_root = std::make_unique<node>();
+ m_root->type = map_node_type::object;
+ m_root->value.children = m_node_children_pool.construct();
+ }
+
+ stack.node_stack.push_back(m_root.get());
+ child_position_type pos = to_key_position(t.value.str.p, t.value.str.n);
+ node* p = &stack.node_stack.back()->get_or_create_child_node(pos);
+ stack.node_stack.push_back(p);
+ break;
+ }
+ case json_path_token_t::end:
+ {
+ if (!m_root)
+ {
+ m_root = std::make_unique<node>();
+ m_root->type = map_node_type::unknown;
+ }
+
+ stack.node_stack.push_back(m_root.get());
+ return stack;
+ }
+ default:
+ // Something has gone wrong. Bail out.
+ stack.node_stack.clear();
+ return stack;
+ }
+
+ for (t = parser.next(); t.type != json_path_token_t::unknown; t = parser.next())
+ {
+ token_stack.push_back(t);
+ node* cur_node = stack.node_stack.back();
+
+ switch (t.type)
+ {
+ case json_path_token_t::array_pos:
+ {
+ switch (cur_node->type)
+ {
+ case map_node_type::array:
+ // Do nothing.
+ break;
+ case map_node_type::unknown:
+ // Turn this node into an array node.
+ cur_node->type = map_node_type::array;
+ cur_node->value.children = m_node_children_pool.construct();
+ break;
+ default:
+ throw_path_error(__FILE__, __LINE__, path);
+ }
+ node* p = &stack.node_stack.back()->get_or_create_child_node(t.value.array_pos);
+ stack.node_stack.push_back(p);
+ break;
+ }
+ case json_path_token_t::object_key:
+ {
+ switch (cur_node->type)
+ {
+ case map_node_type::object:
+ // Do nothing.
+ break;
+ case map_node_type::unknown:
+ // Turn this node into an object node.
+ cur_node->type = map_node_type::object;
+ cur_node->value.children = m_node_children_pool.construct();
+ break;
+ default:
+ throw_path_error(__FILE__, __LINE__, path);
+ }
+
+ // For an object children, we use the memory address of a
+ // pooled key string as its position.
+ child_position_type pos = to_key_position(t.value.str.p, t.value.str.n);
+ node* p = &stack.node_stack.back()->get_or_create_child_node(pos);
+ stack.node_stack.push_back(p);
+ break;
+ }
+ case json_path_token_t::end:
+ {
+ assert(token_stack.size() >= 2);
+ stack.dest_key = get_last_object_key(token_stack);
+
+ return stack;
+ }
+ case json_path_token_t::unknown:
+ default:
+ // Something has gone wrong. Bail out.
+ break;
+ }
+ }
+
+ // If this code path reaches here, something has gone wrong.
+ stack.node_stack.clear();
+ return stack;
+}
+
+json_map_tree::child_position_type json_map_tree::to_key_position(const char* p, size_t n) const
+{
+ std::string_view pooled_key = m_str_pool.intern({p, n}).first;
+ child_position_type pos = reinterpret_cast<child_position_type>(pooled_key.data());
+ return pos;
+}
+
+bool json_map_tree::is_equivalent(input_node_type input_node, map_node_type map_node)
+{
+ uint8_t left = (0x0F & uint8_t(input_node));
+ uint8_t right = (0x0F & uint8_t(map_node));
+ return left == right;
+}
+
+std::ostream& operator<< (std::ostream& os, json_map_tree::input_node_type nt)
+{
+ os << "(input-node-type: ";
+
+ switch (nt)
+ {
+ case json_map_tree::input_node_type::array:
+ os << "array";
+ break;
+ case json_map_tree::input_node_type::object:
+ os << "object";
+ break;
+ case json_map_tree::input_node_type::value:
+ os << "value";
+ break;
+ case json_map_tree::input_node_type::unknown:
+ os << "unknown";
+ break;
+ }
+
+ os << ')';
+
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, json_map_tree::map_node_type nt)
+{
+ os << "(map-node-type: ";
+
+ switch (nt)
+ {
+ case json_map_tree::map_node_type::array:
+ os << "array";
+ break;
+ case json_map_tree::map_node_type::cell_ref:
+ os << "cell-ref";
+ break;
+ case json_map_tree::map_node_type::object:
+ os << "object";
+ break;
+ case json_map_tree::map_node_type::range_field_ref:
+ os << "range-field-ref";
+ break;
+ case json_map_tree::map_node_type::unknown:
+ os << "unknown";
+ break;
+ }
+
+ os << ')';
+
+ return os;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_map_tree.hpp b/src/liborcus/json_map_tree.hpp
new file mode 100644
index 0000000..9470af0
--- /dev/null
+++ b/src/liborcus/json_map_tree.hpp
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "spreadsheet_impl_types.hpp"
+#include "orcus/string_pool.hpp"
+#include "orcus/exception.hpp"
+
+#include <boost/pool/object_pool.hpp>
+#include <memory>
+#include <map>
+#include <vector>
+#include <iosfwd>
+
+namespace orcus {
+
+using spreadsheet::detail::cell_position_t;
+
+class json_map_tree
+{
+public:
+ using child_position_type = std::uintptr_t;
+
+ static constexpr child_position_type node_child_default_position = -1;
+
+ /**
+ * Error indicating improper path.
+ */
+ class path_error : public general_error
+ {
+ public:
+ path_error(const std::string& msg);
+ };
+
+ struct node;
+ struct range_reference_type;
+ using node_children_type = std::map<child_position_type, node>;
+ using range_ref_store_type = std::map<cell_position_t, range_reference_type>;
+
+ /** Types of nodes in the json input tree. */
+ enum class input_node_type { unknown = 0x00, array = 0x01, object = 0x02, value = 0x04 };
+
+ /**
+ * Types of nodes in the map tree. The lower 4-bits specify the input
+ * node type which are kept in sync with the input_node_type values. The
+ * next 4-bits specify the link type.
+ */
+ enum class map_node_type { unknown = 0x00, array = 0x01, object = 0x02, cell_ref = 0x14, range_field_ref = 0x24 };
+
+ struct cell_reference_type
+ {
+ cell_position_t pos;
+
+ cell_reference_type(const cell_position_t& _pos);
+ };
+
+ struct range_field_reference_type;
+
+ struct range_reference_type
+ {
+ cell_position_t pos;
+ std::vector<const range_field_reference_type*> fields;
+ spreadsheet::row_t row_position;
+ bool row_header;
+
+ range_reference_type(const cell_position_t& _pos);
+ };
+
+ /** Represents a field within a range reference. */
+ struct range_field_reference_type
+ {
+ range_reference_type* ref;
+ spreadsheet::col_t column_pos;
+ std::string_view label;
+ };
+
+ struct node
+ {
+ map_node_type type = map_node_type::unknown;
+
+ union
+ {
+ node_children_type* children = nullptr;
+ cell_reference_type* cell_ref;
+ range_field_reference_type* range_field_ref;
+
+ } value;
+
+ /**
+ * The node is a row-group node (node that defines a row boundary)
+ * if this value is set to a non-null value. If this is not null, it
+ * points to the range_reference instance it belongs to.
+ */
+ range_reference_type* row_group = nullptr;
+
+ std::vector<node*> anchored_fields;
+
+ node(const node&) = delete;
+ node& operator=(const node&) = delete;
+
+ node();
+ node(node&& other);
+
+ node& get_or_create_child_node(child_position_type pos);
+ };
+
+ class walker
+ {
+ friend class json_map_tree;
+
+ struct scope
+ {
+ node* p;
+ child_position_type array_position;
+
+ scope(node* _p);
+ };
+
+ using stack_type = std::vector<scope>;
+ using unlinked_stack_type = std::vector<input_node_type>;
+
+ const json_map_tree& m_parent;
+ stack_type m_stack;
+ unlinked_stack_type m_unlinked_stack;
+
+ walker(const json_map_tree& parent);
+ public:
+
+ node* push_node(input_node_type nt);
+ node* pop_node(input_node_type nt);
+
+ void set_object_key(const char* p, size_t n);
+ };
+
+ json_map_tree();
+ ~json_map_tree();
+
+ walker get_tree_walker() const;
+
+ void set_cell_link(std::string_view path, const cell_position_t& pos);
+
+ const node* get_link(std::string_view path) const;
+
+ void start_range(const cell_position_t& pos, bool row_header);
+ void append_field_link(std::string_view path, std::string_view label);
+ void set_range_row_group(std::string_view path);
+ void commit_range();
+
+ range_ref_store_type& get_range_references();
+
+private:
+ range_reference_type& get_range_reference(const cell_position_t& pos);
+
+ const node* get_destination_node(std::string_view path) const;
+
+ struct path_stack_type
+ {
+ std::vector<node*> node_stack;
+ std::string_view dest_key; //< object key associated with the destination value (if applicable)
+ };
+
+ path_stack_type get_or_create_destination_node(std::string_view path);
+
+ child_position_type to_key_position(const char* p, size_t n) const;
+
+ static bool is_equivalent(input_node_type input_node, map_node_type map_node);
+
+private:
+ boost::object_pool<node_children_type> m_node_children_pool;
+ boost::object_pool<cell_reference_type> m_cell_ref_pool;
+ boost::object_pool<range_field_reference_type> m_range_field_ref_pool;
+
+ mutable string_pool m_str_pool;
+
+ std::unique_ptr<node> m_root;
+
+ range_ref_store_type m_range_refs;
+
+ struct
+ {
+ cell_position_t pos;
+ std::vector<std::pair<std::string_view, std::string_view>> fields; // path, label
+ std::vector<std::string_view> row_groups;
+ bool row_header;
+
+ } m_current_range;
+};
+
+std::ostream& operator<< (std::ostream& os, json_map_tree::input_node_type nt);
+std::ostream& operator<< (std::ostream& os, json_map_tree::map_node_type nt);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_map_tree_test.cpp b/src/liborcus/json_map_tree_test.cpp
new file mode 100644
index 0000000..6100bd9
--- /dev/null
+++ b/src/liborcus/json_map_tree_test.cpp
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "json_map_tree.hpp"
+
+#include <cassert>
+#include <iostream>
+
+using namespace orcus;
+using namespace std;
+
+void test_link_array_values()
+{
+ json_map_tree tree;
+
+ cell_position_t pos("sheet", 0, 0);
+
+ tree.set_cell_link("$[0]", pos);
+ pos.row = 1;
+ tree.set_cell_link("$[][0]", pos);
+
+ const json_map_tree::node* p = tree.get_link("$[0]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::cell_ref);
+ assert(p->value.cell_ref->pos == cell_position_t("sheet", 0, 0));
+
+ p = tree.get_link("$[][0]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::cell_ref);
+ assert(p->value.cell_ref->pos == cell_position_t("sheet", 1, 0));
+}
+
+void test_link_object_values()
+{
+ struct entry
+ {
+ const char* path;
+ cell_position_t pos;
+ };
+
+ std::vector<entry> entries =
+ {
+ { "$[]['id']", cell_position_t("sheet", 2, 3) },
+ { "$[]['name']", cell_position_t("sheet", 2, 4) },
+ { "$[]['address']", cell_position_t("sheet", 2, 5) },
+ };
+
+ json_map_tree tree;
+
+ for (const entry& e : entries)
+ tree.set_cell_link(e.path, e.pos);
+
+ for (const entry& e : entries)
+ {
+ const json_map_tree::node* p = tree.get_link(e.path);
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::cell_ref);
+ assert(e.pos == p->value.cell_ref->pos);
+ }
+}
+
+void test_link_object_root()
+{
+ json_map_tree tree;
+
+ const char* path = "$['root'][2]";
+ cell_position_t pos("sheet", 3, 4);
+ tree.set_cell_link(path, pos);
+
+ const json_map_tree::node* p = tree.get_link(path);
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::cell_ref);
+ assert(p->value.cell_ref->pos == pos);
+}
+
+void test_link_range_fields()
+{
+ json_map_tree tree;
+
+ cell_position_t pos("sheet", 1, 2);
+
+ tree.start_range(pos, false);
+ tree.append_field_link("$[][0]", std::string_view{});
+ tree.append_field_link("$[][1]", std::string_view{});
+ tree.append_field_link("$[][2]", std::string_view{});
+ tree.set_range_row_group("$[]");
+ tree.commit_range();
+
+ const json_map_tree::node* p = tree.get_link("$[][0]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::range_field_ref);
+ assert(p->value.range_field_ref->column_pos == 0);
+
+ p = tree.get_link("$[][1]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::range_field_ref);
+ assert(p->value.range_field_ref->column_pos == 1);
+
+ p = tree.get_link("$[][2]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::range_field_ref);
+ assert(p->value.range_field_ref->column_pos == 2);
+
+ // Check the range reference data itself.
+ const json_map_tree::range_reference_type* ref = p->value.range_field_ref->ref;
+ assert(ref->fields.size() == 3);
+ assert(ref->pos == pos);
+
+ // Make sure the row group is set.
+ p = tree.get_link("$[]");
+ assert(p);
+ assert(p->type == json_map_tree::map_node_type::array);
+ assert(p->row_group == ref);
+}
+
+int main()
+{
+ test_link_array_values();
+ test_link_object_values();
+ test_link_object_root();
+ test_link_range_fields();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_structure_mapper.cpp b/src/liborcus/json_structure_mapper.cpp
new file mode 100644
index 0000000..09a9e97
--- /dev/null
+++ b/src/liborcus/json_structure_mapper.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "json_structure_mapper.hpp"
+
+#include <algorithm>
+#include <sstream>
+#include <cassert>
+
+namespace orcus { namespace json { namespace detail {
+
+structure_mapper::structure_mapper(structure_tree::range_handler_type rh, const json::structure_tree::walker& walker) :
+ m_walker(walker),
+ m_range_handler(std::move(rh)),
+ m_repeat_count(0) {}
+
+void structure_mapper::run()
+{
+ reset();
+ traverse(0);
+}
+
+void structure_mapper::reset()
+{
+ m_walker.root();
+ m_current_range.paths.clear();
+ m_current_range.row_groups.clear();
+ m_repeat_count = 0;
+}
+
+void structure_mapper::push_range()
+{
+ m_range_handler(std::move(m_current_range));
+
+ m_current_range.paths.clear();
+ m_current_range.row_groups.clear();
+}
+
+void structure_mapper::traverse(size_t /*pos*/)
+{
+ json::structure_tree::node_properties node = m_walker.get_node();
+
+ if (node.repeat)
+ {
+ ++m_repeat_count;
+ m_current_range.row_groups.push_back(m_walker.build_row_group_path());
+ }
+
+ if (m_repeat_count && node.type == json::structure_tree::node_type::value)
+ {
+ for (std::string path : m_walker.build_field_paths())
+ m_current_range.paths.push_back(std::move(path));
+ }
+
+ for (size_t i = 0, n = m_walker.child_count(); i < n; ++i)
+ {
+ m_walker.descend(i);
+ traverse(i);
+ m_walker.ascend();
+ }
+
+ if (node.repeat)
+ {
+ --m_repeat_count;
+
+ if (!m_repeat_count)
+ push_range();
+ }
+}
+
+}}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_structure_mapper.hpp b/src/liborcus/json_structure_mapper.hpp
new file mode 100644
index 0000000..6dfdd08
--- /dev/null
+++ b/src/liborcus/json_structure_mapper.hpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/json_structure_tree.hpp"
+
+#include <vector>
+#include <functional>
+
+namespace orcus { namespace json { namespace detail {
+
+class structure_mapper
+{
+public:
+ structure_mapper(json::structure_tree::range_handler_type rh, const json::structure_tree::walker& walker);
+
+ void run();
+
+private:
+ void reset();
+ void push_range();
+ void traverse(size_t pos);
+
+private:
+ json::structure_tree::walker m_walker;
+ json::structure_tree::range_handler_type m_range_handler;
+ size_t m_repeat_count;
+ json::table_range_t m_current_range;
+
+};
+
+}}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_structure_tree.cpp b/src/liborcus/json_structure_tree.cpp
new file mode 100644
index 0000000..862b4de
--- /dev/null
+++ b/src/liborcus/json_structure_tree.cpp
@@ -0,0 +1,720 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/json_structure_tree.hpp>
+#include <orcus/json_parser.hpp>
+#include <orcus/string_pool.hpp>
+
+#include "json_structure_mapper.hpp"
+
+#include <vector>
+#include <memory>
+#include <algorithm>
+#include <map>
+#include <functional>
+
+#include <boost/pool/object_pool.hpp>
+
+namespace orcus { namespace json {
+
+namespace {
+
+struct structure_node;
+
+using node_children_type = std::vector<structure_node*>;
+using node_type = structure_tree::node_type;
+using array_positions_type = std::map<int32_t, bool>;
+
+/**
+ * Only pick those array positions that are marked "valid" - the associated
+ * boolean value is true.
+ */
+std::vector<int32_t> to_valid_array_positions(const array_positions_type& array_positions)
+{
+ std::vector<int32_t> aps;
+
+ for (const auto& e : array_positions)
+ {
+ if (e.second)
+ aps.push_back(e.first);
+ }
+
+ return aps;
+}
+
+/**
+ * Represents a node inside a JSON structure tree.
+ */
+struct structure_node
+{
+ bool repeat = false;
+
+ node_type type = node_type::unknown;
+
+ node_children_type children;
+
+ /**
+ * The number of child nodes in the source data tree, not to be confused
+ * with the number of child nodes in the structure tree.
+ */
+ int32_t child_count = 0;
+
+ std::string_view name; //< value of a key for a object key node.
+
+ /**
+ * For a value node that is an immediate child of an array node, these
+ * positions are the positions of the parent array that values always
+ * occur in the source data tree.
+ */
+ array_positions_type array_positions;
+
+ structure_node(node_type _type) : type(_type) {}
+
+ bool operator== (const structure_node& other) const
+ {
+ if (type != other.type)
+ return false;
+
+ if (type != node_type::object_key)
+ return true;
+
+ return name == other.name;
+ }
+
+ bool operator< (const structure_node& other) const
+ {
+ if (type != other.type)
+ return type < other.type;
+
+ if (name != other.name)
+ return name < other.name;
+
+ return true;
+ }
+};
+
+struct parse_scope
+{
+ structure_node& node;
+
+ int32_t child_count = 0;
+
+ parse_scope(structure_node& _node) : node(_node) {}
+};
+
+using parse_scopes_type = std::vector<parse_scope>;
+
+/**
+ * Represents a scope during structure tree traversal.
+ */
+struct scope
+{
+ const structure_node& node;
+ node_children_type::const_iterator current_pos;
+
+ scope(const structure_node& _node) :
+ node(_node),
+ current_pos(node.children.begin()) {}
+};
+
+using scope_stack_type = std::vector<scope>;
+
+void print_scope(std::ostream& os, const scope& s)
+{
+ switch (s.node.type)
+ {
+ case node_type::array:
+ os << "array";
+ break;
+ case node_type::object:
+ os << "object";
+ break;
+ case node_type::object_key:
+ os << "['" << s.node.name << "']";
+ break;
+ default:
+ os << "???";
+ }
+
+ if (s.node.repeat)
+ os << "(*)";
+
+ if (s.node.type == node_type::array && s.node.child_count)
+ os << '[' << s.node.child_count << ']';
+}
+
+void print_scopes(std::ostream& os, const scope_stack_type& scopes)
+{
+ auto it = scopes.cbegin();
+ auto ite = scopes.cend();
+
+ os << '$';
+ print_scope(os, *it);
+
+ for (++it; it != ite; ++it)
+ {
+ if (it->node.type != node_type::object_key)
+ os << '.';
+ print_scope(os, *it);
+ }
+}
+
+structure_tree::node_properties to_node_properties(const structure_node& sn)
+{
+ structure_tree::node_properties np;
+ np.type = sn.type;
+ np.repeat = sn.repeat;
+ return np;
+}
+
+} // anonymous namespace
+
+struct structure_tree::impl
+{
+ boost::object_pool<structure_node> m_node_store;
+ structure_node* m_root;
+ parse_scopes_type m_stack;
+ string_pool m_pool;
+
+ impl() : m_root(nullptr) {}
+ ~impl() {}
+
+ void begin_parse() {}
+
+ void end_parse() {}
+
+ void begin_array()
+ {
+ push_stack(node_type::array);
+ }
+
+ void end_array()
+ {
+ pop_stack();
+ }
+
+ void begin_object()
+ {
+ push_stack(node_type::object);
+ }
+
+ void object_key(std::string_view key, bool transient)
+ {
+ structure_node node(node_type::object_key);
+ node.name = key;
+
+ if (transient)
+ node.name = m_pool.intern(node.name).first;
+
+ push_stack(node);
+ }
+
+ void end_object()
+ {
+ pop_stack();
+ }
+
+ void boolean_true()
+ {
+ push_value();
+ }
+
+ void boolean_false()
+ {
+ push_value();
+ }
+
+ void null()
+ {
+ push_value();
+ }
+
+ void string(std::string_view /*val*/, bool /*transient*/)
+ {
+ push_value();
+ }
+
+ void number(double /*val*/)
+ {
+ push_value();
+ }
+
+ void normalize_tree()
+ {
+ if (!m_root)
+ return;
+
+ std::function<void(structure_node&)> descend = [&descend](structure_node& node)
+ {
+ if (node.children.empty())
+ return;
+
+ // Sort all children.
+ std::sort(node.children.begin(), node.children.end(),
+ [](const structure_node* left, const structure_node* right) -> bool
+ {
+ return *left < *right;
+ }
+ );
+
+ for (structure_node* child : node.children)
+ descend(*child);
+ };
+
+ descend(*m_root);
+ }
+
+ void dump_compact(std::ostream& os) const
+ {
+ if (!m_root)
+ return;
+
+ scope_stack_type scopes;
+ scopes.emplace_back(*m_root);
+
+ while (!scopes.empty())
+ {
+ scope& cur_scope = scopes.back();
+
+ bool new_scope = false;
+
+ for (; cur_scope.current_pos != cur_scope.node.children.end(); ++cur_scope.current_pos)
+ {
+ const structure_node& cur_node = **cur_scope.current_pos;
+
+ if (cur_node.type == node_type::value)
+ {
+ assert(cur_node.children.empty());
+
+ // Print all its parent scopes.
+ print_scopes(os, scopes);
+
+ // Print the value node at the end.
+ os << ".value";
+
+ // Print array positions if applicable.
+ std::vector<int32_t> aps = to_valid_array_positions(cur_node.array_positions);
+
+ if (!aps.empty())
+ {
+ os << '[';
+ auto it = aps.cbegin();
+ os << *it;
+ for (++it; it != aps.cend(); ++it)
+ os << ',' << *it;
+ os << ']';
+ }
+
+ os << std::endl;
+ continue;
+ }
+
+ if (cur_node.children.empty())
+ continue;
+
+ // This node has child nodes. Push a new scope and trigger a new inner loop.
+
+ ++cur_scope.current_pos; // Don't forget to move to the next sibling for when we return to this scope.
+ scopes.emplace_back(cur_node);
+ new_scope = true;
+ break;
+ }
+
+ if (new_scope)
+ continue;
+
+ scopes.pop_back();
+ }
+ }
+
+private:
+
+ parse_scope& get_current_scope()
+ {
+ assert(!m_stack.empty());
+ return m_stack.back();
+ }
+
+ bool is_node_repeatable(const structure_node& node) const
+ {
+ const structure_node& cur = m_stack.back().node;
+
+ if (cur.type != node_type::array)
+ return false;
+
+ return node.type == node_type::array || node.type == node_type::object;
+ }
+
+ void push_stack(const structure_node& node)
+ {
+ if (!m_root)
+ {
+ // This is the very first node.
+ assert(node.type != node_type::object_key);
+ m_root = m_node_store.construct(node.type);
+ m_stack.emplace_back(*m_root);
+ return;
+ }
+
+ parse_scope& cur_scope = get_current_scope();
+ structure_node& cur_node = cur_scope.node;
+
+ // Record the position of this new child in case the parent is an
+ // array and the new node is a value node.
+
+ int32_t array_pos = -1;
+
+ if (cur_node.type == node_type::array)
+ {
+ array_pos = cur_scope.child_count;
+
+ if (node.type != node_type::value)
+ {
+ // See if this array has a child value node.
+ auto it = std::find_if(
+ cur_node.children.begin(), cur_node.children.end(),
+ [](const structure_node* p) -> bool { return p->type == node_type::value; }
+ );
+
+ if (it != cur_node.children.end())
+ {
+ // It has a child value node. See if this value node has
+ // this array position recorded. If yes, turn it off
+ // since this position is not always a value.
+ array_positions_type& aps = (*it)->array_positions;
+ auto it_array_pos = aps.find(array_pos);
+ if (it_array_pos != aps.end())
+ it_array_pos->second = false;
+ }
+
+ array_pos = -1;
+ }
+ }
+
+ ++cur_scope.child_count;
+
+ {
+ // See if the current node has a child node of the specified type.
+ auto it = std::find_if(cur_node.children.begin(), cur_node.children.end(),
+ [&node](const structure_node* p) -> bool
+ {
+ return *p == node;
+ }
+ );
+
+ if (it == cur_node.children.end())
+ {
+ // current node doesn't have a child of specified type. Add one.
+ cur_node.children.push_back(m_node_store.construct(node));
+ m_stack.emplace_back(*cur_node.children.back());
+ }
+ else
+ {
+ // current node does have a child of specified type.
+ bool repeat = is_node_repeatable(node);
+ structure_node& child = **it;
+ child.repeat = repeat;
+ m_stack.emplace_back(child);
+ }
+ }
+
+ if (array_pos >= 0)
+ {
+ array_positions_type& aps = m_stack.back().node.array_positions;
+ int32_t min_pos = aps.empty() ? 0 : aps.begin()->first;
+ if (array_pos >= min_pos)
+ {
+ auto it = aps.lower_bound(array_pos);
+
+ if (it == aps.end() || aps.key_comp()(array_pos, it->first))
+ {
+ // Insert a new array child node of unspecified type at the specified position.
+ aps.insert(
+ it, array_positions_type::value_type(array_pos, true));
+ }
+ }
+ }
+ }
+
+ void push_value()
+ {
+ push_stack(node_type::value);
+ pop_stack();
+ }
+
+ void pop_stack()
+ {
+ parse_scope& cur_scope = get_current_scope();
+ structure_node& cur_node = cur_scope.node;
+ if (cur_scope.child_count > cur_node.child_count)
+ cur_node.child_count = cur_scope.child_count;
+
+ m_stack.pop_back();
+
+ if (!m_stack.empty() && get_current_scope().node.type == node_type::object_key)
+ // Object key is a special non-leaf node that can only have one child.
+ m_stack.pop_back();
+ }
+};
+
+struct structure_tree::walker::impl
+{
+ using stack_type = std::vector<const structure_node*>;
+
+ const structure_tree::impl* parent_impl;
+
+ stack_type stack;
+
+ impl() : parent_impl(nullptr) {}
+
+ impl(const structure_tree::impl* _parent_impl) : parent_impl(_parent_impl) {}
+
+ impl(const structure_tree::walker::impl& other) :
+ parent_impl(other.parent_impl) {}
+
+ void check_tree()
+ {
+ if (!parent_impl)
+ throw json_structure_error(
+ "This walker is not associated with any json_structure_tree instance.");
+
+ if (!parent_impl->m_root)
+ throw json_structure_error("Empty tree.");
+ }
+
+ void check_stack()
+ {
+ check_tree();
+
+ if (stack.empty())
+ throw json_structure_error(
+ "Walker stack is empty. Most likely caused by not calling root() to start the traversal.");
+ }
+};
+
+structure_tree::walker::walker() : mp_impl(std::make_unique<impl>()) {}
+structure_tree::walker::walker(const walker& other) : mp_impl(std::make_unique<impl>(*other.mp_impl)) {}
+structure_tree::walker::walker(const structure_tree::impl* parent_impl) : mp_impl(std::make_unique<impl>(parent_impl)) {}
+structure_tree::walker::~walker() {}
+
+void structure_tree::walker::root()
+{
+ mp_impl->check_tree();
+
+ mp_impl->stack.clear();
+ mp_impl->stack.push_back(mp_impl->parent_impl->m_root);
+}
+
+void structure_tree::walker::descend(size_t child_pos)
+{
+ mp_impl->check_stack();
+ assert(!mp_impl->stack.empty());
+
+ const structure_node* p = mp_impl->stack.back();
+ assert(p);
+
+ if (child_pos >= p->children.size())
+ {
+ std::ostringstream os;
+ os << "Specified child position of " << child_pos << " exceeds the child count of " << p->children.size() << '.';
+ throw json_structure_error(os.str());
+ }
+
+ p = p->children[child_pos];
+ assert(p);
+ mp_impl->stack.push_back(p);
+}
+
+void structure_tree::walker::ascend()
+{
+ mp_impl->check_stack();
+ assert(!mp_impl->stack.empty());
+
+ if (mp_impl->stack.size() == 1u)
+ throw json_structure_error("You cannot ascend from the root node.");
+
+ mp_impl->stack.pop_back();
+}
+
+size_t structure_tree::walker::child_count() const
+{
+ mp_impl->check_stack();
+ assert(!mp_impl->stack.empty());
+
+ const structure_node* p = mp_impl->stack.back();
+ return p->children.size();
+}
+
+structure_tree::node_properties structure_tree::walker::get_node() const
+{
+ mp_impl->check_stack();
+ assert(!mp_impl->stack.empty());
+
+ const structure_node* p = mp_impl->stack.back();
+ assert(p);
+ return to_node_properties(*p);
+}
+
+std::vector<std::string> structure_tree::walker::build_field_paths() const
+{
+ mp_impl->check_stack();
+ assert(!mp_impl->stack.empty());
+
+ if (mp_impl->stack.empty() || mp_impl->stack.back()->type != node_type::value)
+ throw json_structure_error("You can only build field paths to value node.");
+
+ std::ostringstream os;
+ os << '$';
+
+ auto it = mp_impl->stack.cbegin(), ite = mp_impl->stack.cend();
+
+ const structure_node* p = nullptr;
+ const structure_node* p_prev = *it;
+
+ for (++it; it != ite; ++it, p_prev = p)
+ {
+ p = *it;
+
+ switch (p_prev->type)
+ {
+ case structure_tree::node_type::array:
+ if (p->type != structure_tree::node_type::value)
+ os << "[]";
+ break;
+ case structure_tree::node_type::object_key:
+ os << "['" << p_prev->name << "']";
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (p_prev->type == structure_tree::node_type::value && !p->array_positions.empty())
+ {
+ // non-empty array positions implies that the parent is an array.
+ std::vector<int32_t> aps = to_valid_array_positions(p->array_positions);
+ if (!aps.empty())
+ {
+ std::vector<std::string> ret;
+ std::string base = os.str();
+ for (int32_t ap : aps)
+ {
+ std::ostringstream path;
+ path << base << '[' << ap << ']';
+ ret.push_back(path.str());
+ }
+
+ return ret;
+ }
+ }
+
+ return std::vector<std::string>(1u, os.str());
+}
+
+std::string structure_tree::walker::build_row_group_path() const
+{
+ mp_impl->check_stack();
+
+ if (mp_impl->stack.size() < 2u)
+ throw json_structure_error("Current node is root - it doesn't have a parent.");
+
+ if (!mp_impl->stack.back()->repeat)
+ throw json_structure_error(
+ "Current node is not a repeating node. Only the parent node of a repeating node can be a row group.");
+
+ {
+ auto it = mp_impl->stack.crbegin();
+ ++it;
+ if ((*it)->type != structure_tree::node_type::array)
+ throw json_structure_error(
+ "Parent node of the current node is not of array type, but it should be.");
+ }
+
+ std::ostringstream os;
+ os << '$';
+
+ auto it = mp_impl->stack.cbegin(), ite = mp_impl->stack.cend();
+ ite -= 2; // jump to the parent node, and we don't include the last node in the path output.
+
+ for (; it != ite; ++it)
+ {
+ const structure_node* p = *it;
+
+ switch (p->type)
+ {
+ case structure_tree::node_type::array:
+ os << "[]";
+ break;
+ case structure_tree::node_type::object_key:
+ os << "['" << p->name << "']";
+ break;
+ default:
+ ;
+ }
+ }
+
+ return os.str();
+}
+
+structure_tree::structure_tree() : mp_impl(std::make_unique<impl>()) {}
+structure_tree::~structure_tree() {}
+
+void structure_tree::parse(std::string_view stream)
+{
+ json_parser<impl> parser(stream, *mp_impl);
+ parser.parse();
+}
+
+void structure_tree::normalize_tree()
+{
+ mp_impl->normalize_tree();
+}
+
+void structure_tree::dump_compact(std::ostream& os) const
+{
+ mp_impl->dump_compact(os);
+}
+
+structure_tree::walker structure_tree::get_walker() const
+{
+ return walker(mp_impl.get());
+}
+
+void structure_tree::process_ranges(range_handler_type rh) const
+{
+ detail::structure_mapper mapper(rh, get_walker());
+ mapper.run();
+}
+
+std::ostream& operator<< (std::ostream& os, structure_tree::node_type nt)
+{
+
+ switch (nt)
+ {
+ case structure_tree::node_type::array:
+ os << "structure_tree::node_type::array";
+ break;
+ case structure_tree::node_type::object:
+ os << "structure_tree::node_type::object";
+ break;
+ case structure_tree::node_type::object_key:
+ os << "structure_tree::node_type::object_key";
+ break;
+ case structure_tree::node_type::unknown:
+ os << "structure_tree::node_type::unknown";
+ break;
+ case structure_tree::node_type::value:
+ os << "structure_tree::node_type::value";
+ break;
+ }
+
+ return os;
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_structure_tree_test.cpp b/src/liborcus/json_structure_tree_test.cpp
new file mode 100644
index 0000000..60a0598
--- /dev/null
+++ b/src/liborcus/json_structure_tree_test.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/json_structure_tree.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/parser_global.hpp>
+#include "filesystem_env.hpp"
+
+#include <vector>
+#include <sstream>
+#include <cassert>
+#include <unordered_set>
+
+using namespace orcus;
+
+std::vector<const char*> base_dirs = {
+ SRCDIR"/test/json-structure/arrays-in-object/",
+ SRCDIR"/test/json-structure/nested-arrays/",
+ SRCDIR"/test/json-structure/nested-arrays-mixed/",
+ SRCDIR"/test/json-structure/nested-arrays-mixed-2/",
+ SRCDIR"/test/json-structure/repeat-objects/",
+ SRCDIR"/test/json-structure/repeat-objects-2/",
+ SRCDIR"/test/json-structure/multiple-ranges/",
+};
+
+/**
+ * All json contents under this directory have no value nodes. Since the
+ * structure output of a JSON content only dumps value nodes, the output
+ * string should be empty when the source content does not have any value
+ * nodes.
+ */
+void test_no_value_nodes()
+{
+ fs::path base_dir(SRCDIR"/test/json-structure/no-value-nodes");
+
+ for (const fs::path& p : fs::directory_iterator(base_dir))
+ {
+ if (!fs::is_regular_file(p))
+ continue;
+
+ if (p.extension().string() != ".json")
+ continue;
+
+ file_content strm(p.string().data());
+ json::structure_tree tree;
+ tree.parse(strm.str());
+ tree.normalize_tree();
+ std::ostringstream os;
+ tree.dump_compact(os);
+
+ assert(os.str().empty());
+ }
+}
+
+void test_basic()
+{
+ for (const char* base_dir : base_dirs)
+ {
+ std::string filepath(base_dir);
+ filepath.append("input.json");
+
+ file_content strm(filepath.data());
+ assert(!strm.empty());
+ json::structure_tree tree;
+ tree.parse(strm.str());
+ tree.normalize_tree();
+ std::ostringstream os;
+ tree.dump_compact(os);
+ std::string data_content = os.str();
+
+ // Check the dump content against known datum.
+ filepath = base_dir;
+ filepath.append("check.txt");
+ file_content strm_check(filepath.data());
+ assert(!strm_check.empty());
+
+ // They should be identical, plus or minus leading/trailing whitespaces.
+ std::string_view s1(data_content.data(), data_content.size());
+ std::string_view s2 = strm_check.str();
+ assert(trim(s1) == trim(s2));
+ }
+}
+
+void test_automatic_range_detection()
+{
+ using detected_group_type = std::unordered_set<std::string>;
+ using detected_groups_type = std::vector<detected_group_type>;
+
+ struct check
+ {
+ fs::path filepath;
+ detected_groups_type expected_groups;
+ };
+
+ std::vector<check> checks =
+ {
+ {
+ SRCDIR"/test/json-structure/arrays-in-object/input.json",
+ {
+ {
+ "row-group:$['rows']",
+ "path:$['rows'][]['name']",
+ "path:$['rows'][]['age']",
+ "path:$['rows'][]['error']",
+ }
+ }
+ },
+ {
+ SRCDIR"/test/json-structure/repeat-objects/input.json",
+ {
+ {
+ "path:$[]['name']",
+ "path:$[]['age']",
+ "row-group:$",
+ }
+ }
+ },
+ {
+ SRCDIR"/test/json-structure/repeat-objects-2/input.json",
+ {
+ {
+ "path:$[]['name']",
+ "path:$[]['age']",
+ "path:$[]['props']['alpha']",
+ "path:$[]['props']['beta']",
+ "path:$[]['props']['gamma']",
+ "path:$[]['props']['theta']",
+ "row-group:$",
+ }
+ }
+ },
+ {
+ SRCDIR"/test/json-structure/multiple-ranges/input.json",
+ {
+ {
+ "path:$['data'][]['category']",
+ "path:$['data'][]['region']",
+ "path:$['data'][]['records'][]['id']",
+ "path:$['data'][]['records'][]['ref']",
+ "row-group:$['data']",
+ "row-group:$['data'][]['records']",
+ },
+ {
+ "path:$['misc'][][0]",
+ "path:$['misc'][][1]",
+ "path:$['misc'][][2]",
+ "row-group:$['misc']",
+ }
+ }
+ },
+ };
+
+ for (const check& c : checks)
+ {
+ file_content strm(c.filepath.string().data());
+ assert(!strm.empty());
+ json::structure_tree tree;
+ tree.parse(strm.str());
+
+ detected_groups_type observed_groups;
+
+ json::structure_tree::range_handler_type rh = [&observed_groups](json::table_range_t&& range)
+ {
+ detected_group_type observed;
+ for (const std::string& s : range.row_groups)
+ {
+ std::ostringstream os;
+ os << "row-group:" << s;
+ observed.insert(os.str());
+ }
+
+ for (const std::string& s : range.paths)
+ {
+ std::ostringstream os;
+ os << "path:" << s;
+ observed.insert(os.str());
+ }
+
+ observed_groups.push_back(std::move(observed));
+ };
+
+ tree.process_ranges(rh);
+
+ assert(observed_groups == c.expected_groups);
+ }
+}
+
+int main()
+{
+ test_no_value_nodes();
+ test_basic();
+ test_automatic_range_detection();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_util.cpp b/src/liborcus/json_util.cpp
new file mode 100644
index 0000000..b031cbe
--- /dev/null
+++ b/src/liborcus/json_util.cpp
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/json_global.hpp"
+
+#include <sstream>
+
+namespace orcus { namespace json {
+
+namespace {
+
+const char quote = '"';
+
+}
+
+void dump_string(std::ostringstream& os, const std::string& s)
+{
+ os << quote << escape_string(s) << quote;
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/json_util.hpp b/src/liborcus/json_util.hpp
new file mode 100644
index 0000000..00917a2
--- /dev/null
+++ b/src/liborcus/json_util.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_JSON_UTIL_HPP
+#define INCLUDED_ORCUS_JSON_UTIL_HPP
+
+#include <sstream>
+
+namespace orcus { namespace json {
+
+void dump_string(std::ostringstream& os, const std::string& s);
+
+}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/measurement.cpp b/src/liborcus/measurement.cpp
new file mode 100644
index 0000000..f034595
--- /dev/null
+++ b/src/liborcus/measurement.cpp
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/measurement.hpp>
+#include <orcus/exception.hpp>
+#include <orcus/parser_global.hpp>
+
+#include <mdds/sorted_string_map.hpp>
+#include <mdds/global.hpp>
+
+#include <sstream>
+
+namespace orcus {
+
+double to_double(std::string_view s, const char** p_parse_ended)
+{
+ const char* p = s.data();
+ double value;
+ const char* p_last = parse_numeric(p, p + s.size(), value);
+ if (p_parse_ended)
+ *p_parse_ended = p_last;
+
+ return value;
+}
+
+long to_long(std::string_view s, const char** p_parse_ended)
+{
+ long value;
+ const char* p_last = parse_integer(s.data(), s.data() + s.size(), value);
+ if (p_parse_ended)
+ *p_parse_ended = p_last;
+
+ return value;
+}
+
+bool to_bool(std::string_view s)
+{
+ size_t n = s.size();
+ if (n == 1)
+ // Any single char other than '0' is true.
+ return s[0] != '0';
+
+ return s == "true" || s == "TRUE";
+}
+
+namespace {
+
+namespace length {
+
+using map_type = mdds::sorted_string_map<length_unit_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "cm", length_unit_t::centimeter },
+ { "in", length_unit_t::inch },
+ { "mm", length_unit_t::millimeter },
+ { "pt", length_unit_t::point },
+ { "px", length_unit_t::pixel }
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), length_unit_t::unknown);
+ return mt;
+}
+
+} // namespace length
+
+} // anonymous namespace
+
+length_t to_length(std::string_view str)
+{
+ length_t ret;
+ if (str.empty())
+ return ret;
+
+ const char* p = str.data();
+ const char* p_start = p;
+ const char* p_end = p_start + str.size();
+ p = parse_numeric(p, p_end, ret.value);
+
+ std::string_view tail(p, p_end-p);
+ ret.unit = length::get().find(tail);
+
+ return ret;
+}
+
+namespace {
+
+double convert_inch(double value, length_unit_t unit_to)
+{
+ switch (unit_to)
+ {
+ case length_unit_t::twip:
+ // inches to twips : 1 twip = 1/1440 inches
+ return value * 1440.0;
+ default:
+ ;
+ }
+
+ throw general_error("convert_inch: unsupported unit of measurement.");
+}
+
+double convert_point(double value, length_unit_t unit_to)
+{
+ switch (unit_to)
+ {
+ case length_unit_t::twip:
+ // 20 twips = 1 point
+ return value * 20.0;
+ default:
+ ;
+ }
+
+ throw general_error("convert_point: unsupported unit of measurement.");
+}
+
+double convert_centimeter(double value, length_unit_t unit_to)
+{
+ switch (unit_to)
+ {
+ case length_unit_t::twip:
+ // centimeters to twips : 2.54 cm = 1 inch = 1440 twips
+ return value / 2.54 * 1440.0;
+ default:
+ ;
+ }
+
+ throw general_error("convert_centimeter: unsupported unit of measurement.");
+}
+
+double convert_millimeter(double value, length_unit_t unit_to)
+{
+ switch (unit_to)
+ {
+ case length_unit_t::twip:
+ // millimeters to twips : 25.4 mm = 1 inch = 1440 twips
+ return value / 25.4 * 1440.0;
+ default:
+ ;
+ }
+
+ throw general_error("convert_millimeter: unsupported unit of measurement.");
+}
+
+double convert_twip(double value, length_unit_t unit_to)
+{
+ switch (unit_to)
+ {
+ case length_unit_t::inch:
+ // twips to inches : 1 twip = 1/1440 inches
+ return value / 1440.0;
+ case length_unit_t::point:
+ // 1 twip = 1/1440 inches = 72/1440 points = 1/20 points
+ return value / 20.0;
+ default:
+ ;
+ }
+ throw general_error("convert_twip: unsupported unit of measurement.");
+}
+
+/**
+ * Since Excel's column width is based on the maximum digit width of font
+ * used as the "Normal" style font, it's impossible to convert it accurately
+ * without the font information.
+ */
+double convert_xlsx_column_digit(double value, length_unit_t unit_to)
+{
+ // Convert to centimeters first. Here, we'll just assume that a single
+ // digit always equals 1.9 millimeters. TODO: find a better way to convert
+ // this.
+ value *= 0.19;
+ return convert_centimeter(value, unit_to);
+}
+
+}
+
+double convert(double value, length_unit_t unit_from, length_unit_t unit_to)
+{
+ if (value == 0.0)
+ return value;
+
+ switch (unit_from)
+ {
+ case length_unit_t::point:
+ return convert_point(value, unit_to);
+ case length_unit_t::inch:
+ return convert_inch(value, unit_to);
+ case length_unit_t::centimeter:
+ return convert_centimeter(value, unit_to);
+ case length_unit_t::millimeter:
+ return convert_millimeter(value, unit_to);
+ case length_unit_t::twip:
+ return convert_twip(value, unit_to);
+ case length_unit_t::xlsx_column_digit:
+ return convert_xlsx_column_digit(value, unit_to);
+ default:
+ ;
+ }
+
+ std::ostringstream os;
+ os << "convert: unsupported unit of measurement (from "
+ << static_cast<int>(unit_from) << " to "
+ << static_cast<int>(unit_to) << ") (value=" << value << ")";
+ throw general_error(os.str());
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/number_utils.cpp b/src/liborcus/number_utils.cpp
new file mode 100644
index 0000000..8e669ae
--- /dev/null
+++ b/src/liborcus/number_utils.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "number_utils.hpp"
+
+namespace orcus {
+
+namespace {
+
+std::optional<std::uint8_t> char_to_uint8(char c)
+{
+ std::uint8_t v;
+ if ('0' <= c && c <= '9')
+ {
+ v = c - '0';
+ return v;
+ }
+
+ if ('A' <= c && c <= 'F')
+ {
+ v = c - 'A' + 10;
+ return v;
+ }
+
+ if ('a' <= c && c <= 'f')
+ {
+ v = c - 'a' + 10;
+ return v;
+ }
+
+ return {};
+}
+
+template<typename IntT>
+std::optional<IntT> hex_to_uint(std::string_view s)
+{
+ static_assert(std::is_integral_v<IntT>);
+
+ constexpr std::size_t expected_len = sizeof(IntT) * 2u;
+ if (s.size() > expected_len)
+ return {};
+
+ IntT value = 0;
+ for (char c : s)
+ {
+ value = value << 4;
+ auto v = char_to_uint8(c);
+ if (!v)
+ return {};
+ value += *v;
+ }
+
+ return value;
+}
+
+} // anonymous namespace
+
+std::optional<std::uint8_t> hex_to_uint8(std::string_view s)
+{
+ return hex_to_uint<std::uint8_t>(s);
+}
+
+std::optional<std::uint16_t> hex_to_uint16(std::string_view s)
+{
+ return hex_to_uint<std::uint16_t>(s);
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/number_utils.hpp b/src/liborcus/number_utils.hpp
new file mode 100644
index 0000000..acb4c3a
--- /dev/null
+++ b/src/liborcus/number_utils.hpp
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <string_view>
+#include <optional>
+#include <cstdint>
+
+namespace orcus {
+
+std::optional<std::uint8_t> hex_to_uint8(std::string_view s);
+
+std::optional<std::uint16_t> hex_to_uint16(std::string_view s);
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_document_styles_context.cpp b/src/liborcus/odf_document_styles_context.cpp
new file mode 100644
index 0000000..957e55f
--- /dev/null
+++ b/src/liborcus/odf_document_styles_context.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_document_styles_context.hpp"
+#include "odf_token_constants.hpp"
+#include "odf_namespace_types.hpp"
+
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+
+#include <iostream>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+document_styles_context::document_styles_context(session_context& session_cxt, const tokens& tk, odf_styles_map_type& styles_map, ss::iface::import_styles* xstyles) :
+ xml_context_base(session_cxt, tk),
+ m_styles_map(styles_map),
+ mp_styles(xstyles),
+ m_cxt_styles(session_cxt, tk, xstyles)
+{
+ register_child(&m_cxt_styles);
+}
+
+xml_context_base* document_styles_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_office && name == XML_styles)
+ {
+ m_cxt_styles.reset();
+ return &m_cxt_styles;
+ }
+
+ return nullptr;
+}
+
+void document_styles_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_odf_office && name == XML_styles)
+ {
+ assert(child == &m_cxt_styles);
+ auto new_styles = m_cxt_styles.pop_styles();
+ merge(m_styles_map, new_styles);
+ assert(new_styles.empty());
+ }
+}
+
+void document_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ auto parent = push_stack(ns, name);
+ (void)parent;
+
+ (void)attrs;
+
+ warn_unhandled();
+}
+
+bool document_styles_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void document_styles_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_document_styles_context.hpp b/src/liborcus/odf_document_styles_context.hpp
new file mode 100644
index 0000000..4deecb5
--- /dev/null
+++ b/src/liborcus/odf_document_styles_context.hpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+#include "odf_styles.hpp"
+#include "odf_styles_context.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_styles;
+
+}}
+
+/**
+ * Context that handles the <office:document-styles> element scope.
+ *
+ * <office:document-styles> is the root element of styles.xml stream inside an
+ * ODF document.
+ */
+class document_styles_context : public xml_context_base
+{
+public:
+ document_styles_context(
+ session_context& session_cxt, const tokens& tk,
+ odf_styles_map_type& styles_map, spreadsheet::iface::import_styles* xstyles);
+
+ xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+private:
+ odf_styles_map_type& m_styles_map;
+ spreadsheet::iface::import_styles* mp_styles = nullptr;
+
+ styles_context m_cxt_styles;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_helper.cpp b/src/liborcus/odf_helper.cpp
new file mode 100644
index 0000000..7198b74
--- /dev/null
+++ b/src/liborcus/odf_helper.cpp
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_helper.hpp"
+#include "string_helper.hpp"
+#include <orcus/spreadsheet/types.hpp>
+#include <orcus/measurement.hpp>
+#include <mdds/sorted_string_map.hpp>
+#include <mdds/global.hpp>
+#include <orcus/spreadsheet/styles.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace border_style {
+
+using map_type = mdds::sorted_string_map<spreadsheet::border_style_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "dash-dot", spreadsheet::border_style_t::dash_dot },
+ { "dash-dot-dot", spreadsheet::border_style_t::dash_dot_dot },
+ { "dashed", spreadsheet::border_style_t::dashed },
+ { "dotted", spreadsheet::border_style_t::dotted },
+ { "double-thin", spreadsheet::border_style_t::double_thin },
+ { "fine-dashed", spreadsheet::border_style_t::fine_dashed },
+ { "none", spreadsheet::border_style_t::none },
+ { "solid", spreadsheet::border_style_t::solid },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::border_style_t::unknown);
+ return mt;
+}
+
+} // namespace border_style
+
+namespace underline_width {
+
+using map_type = mdds::sorted_string_map<spreadsheet::underline_width_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "auto", ss::underline_width_t::automatic },
+ { "bold", ss::underline_width_t::bold },
+ { "dash", ss::underline_width_t::dash },
+ { "medium", ss::underline_width_t::medium },
+ { "thick", ss::underline_width_t::thick },
+ { "thin", ss::underline_width_t::thin },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::underline_width_t::none);
+ return mt;
+}
+
+} // namespace underline_width
+
+namespace underline_style {
+
+using map_type = mdds::sorted_string_map<ss::underline_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "dash", ss::underline_t::dash },
+ { "dot-dash", ss::underline_t::dot_dash },
+ { "dot-dot-dash", ss::underline_t::dot_dot_dash },
+ { "dotted", ss::underline_t::dotted },
+ { "long-dash", ss::underline_t::long_dash },
+ { "none", ss::underline_t::none },
+ { "solid", ss::underline_t::single_line },
+ { "wave", ss::underline_t::wave }
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), ss::underline_t::none);
+ return mt;
+}
+
+} // namespace underline_style
+
+namespace hor_align {
+
+using map_type = mdds::sorted_string_map<spreadsheet::hor_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "center", spreadsheet::hor_alignment_t::center },
+ { "end", spreadsheet::hor_alignment_t::right },
+ { "justified", spreadsheet::hor_alignment_t::justified },
+ { "start", spreadsheet::hor_alignment_t::left }
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), ss::hor_alignment_t::unknown);
+ return mt;
+}
+
+} // namespace hor_align
+
+namespace ver_align {
+
+using map_type = mdds::sorted_string_map<spreadsheet::ver_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "bottom", spreadsheet::ver_alignment_t::bottom },
+ { "justified", spreadsheet::ver_alignment_t::justified },
+ { "middle", spreadsheet::ver_alignment_t::middle },
+ { "top", spreadsheet::ver_alignment_t::top }
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), ss::ver_alignment_t::unknown);
+ return mt;
+}
+
+} // namespace ver_align
+
+bool is_valid_hex_digit(const char& character, orcus::spreadsheet::color_elem_t& val)
+{
+ if ('0' <= character && character <= '9')
+ {
+ val += character - '0';
+ return true;
+ }
+
+ if ('A' <= character && character <= 'F')
+ {
+ val += character - 'A' + 10;
+ return true;
+ }
+
+ if ('a' <= character && character <= 'f')
+ {
+ val += character - 'a' + 10;
+ return true;
+ }
+
+ return false;
+}
+
+// converts two characters starting at index to a color value
+bool convert_color_digits(std::string_view value, orcus::spreadsheet::color_elem_t& color_val, size_t index)
+{
+ const char& high_val = value[index];
+ color_val = 0;
+ if (!is_valid_hex_digit(high_val, color_val))
+ return false;
+ color_val *= 16;
+ const char& low_val = value[++index];
+ return is_valid_hex_digit(low_val, color_val);
+}
+
+} // anonymous namespace
+
+bool odf::convert_fo_color(
+ std::string_view value,
+ spreadsheet::color_elem_t& red,
+ spreadsheet::color_elem_t& green,
+ spreadsheet::color_elem_t& blue)
+{
+ auto color = convert_fo_color(value);
+ if (!color)
+ return false;
+
+ red = color->red;
+ green = color->green;
+ blue = color->blue;
+ return true;
+}
+
+std::optional<spreadsheet::color_rgb_t> odf::convert_fo_color(std::string_view value)
+{
+ std::optional<spreadsheet::color_rgb_t> ret;
+
+ // first character needs to be '#'
+ if (value.size() != 7)
+ return ret;
+
+ if (value[0] != '#')
+ return ret;
+
+ spreadsheet::color_rgb_t color;
+ if (!convert_color_digits(value, color.red, 1))
+ return ret;
+
+ if (!convert_color_digits(value, color.green, 3))
+ return ret;
+
+ if (!convert_color_digits(value, color.blue, 5))
+ return ret;
+
+ return color;
+}
+
+orcus::odf::border_details_t odf::extract_border_details(std::string_view value)
+{
+ border_details_t border_details;
+
+ auto detail = orcus::string_helper::split_string(value,' ');
+
+ for (const auto& sub_detail : detail)
+ {
+ if (sub_detail[0] == '#')
+ convert_fo_color(sub_detail, border_details.red, border_details.green, border_details.blue);
+ else if (sub_detail[0] >= '0' && sub_detail[0] <='9')
+ border_details.border_width = orcus::to_length(sub_detail);
+ else // This has to be a style
+ border_details.border_style = border_style::get().find(sub_detail);
+ }
+ return border_details;
+}
+
+ss::underline_width_t odf::extract_underline_width(std::string_view value)
+{
+ // TODO: style:text-underline-width also allows:
+ // * percent value
+ // * positive integer
+ // * positive length
+ // As we encounter real-life examples of these values, we should add code to
+ // handle them here. For now, we only handle enumerated values.
+ return underline_width::get().find(value);
+}
+
+orcus::spreadsheet::underline_t odf::extract_underline_style(std::string_view value)
+{
+ return underline_style::get().find(value);
+}
+
+ss::hor_alignment_t odf::extract_hor_alignment_style(std::string_view value)
+{
+ return hor_align::get().find(value);
+}
+
+spreadsheet::ver_alignment_t odf::extract_ver_alignment_style(std::string_view value)
+{
+ return ver_align::get().find(value);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_helper.hpp b/src/liborcus/odf_helper.hpp
new file mode 100644
index 0000000..eb95692
--- /dev/null
+++ b/src/liborcus/odf_helper.hpp
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_ODF_HELPER_HPP
+#define INCLUDED_ORCUS_ODF_HELPER_HPP
+
+#include <orcus/spreadsheet/types.hpp>
+#include <orcus/measurement.hpp>
+#include <orcus/spreadsheet/styles.hpp>
+
+#include <optional>
+
+namespace orcus { namespace odf {
+
+struct border_details_t
+{
+ spreadsheet::border_style_t border_style = spreadsheet::border_style_t::unknown;
+
+ spreadsheet::color_elem_t red = 0;
+ spreadsheet::color_elem_t green = 0;
+ spreadsheet::color_elem_t blue = 0;
+
+ length_t border_width;
+};
+
+bool convert_fo_color(
+ std::string_view value,
+ spreadsheet::color_elem_t& red,
+ spreadsheet::color_elem_t& green,
+ spreadsheet::color_elem_t& blue);
+
+std::optional<spreadsheet::color_rgb_t> convert_fo_color(std::string_view value);
+
+/**
+ * extracts border style, width and colors from a string value.
+ */
+border_details_t extract_border_details(std::string_view value);
+
+spreadsheet::underline_width_t extract_underline_width(std::string_view value);
+
+spreadsheet::underline_t extract_underline_style(std::string_view value);
+
+spreadsheet::hor_alignment_t extract_hor_alignment_style(std::string_view value);
+
+spreadsheet::ver_alignment_t extract_ver_alignment_style(std::string_view value);
+
+}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_helper_test.cpp b/src/liborcus/odf_helper_test.cpp
new file mode 100644
index 0000000..803644c
--- /dev/null
+++ b/src/liborcus/odf_helper_test.cpp
@@ -0,0 +1,51 @@
+#include "odf_helper.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+#include <cassert>
+
+using namespace orcus::spreadsheet;
+
+namespace {
+
+void test_color_conversion(const char* input, bool valid,
+ color_elem_t red_expected, color_elem_t green_expected, color_elem_t blue_expected)
+{
+ color_elem_t red, green, blue;
+ bool valid_result = orcus::odf::convert_fo_color(input, red, green, blue);
+
+ assert(valid == valid_result);
+ if (valid)
+ {
+ assert(red_expected == red);
+ assert(green_expected == green);
+ assert(blue_expected == blue);
+ }
+}
+
+}
+
+int main()
+{
+ struct
+ {
+ const char* input;
+ bool valid;
+ orcus::spreadsheet::color_elem_t red;
+ orcus::spreadsheet::color_elem_t green;
+ orcus::spreadsheet::color_elem_t blue;
+ } data[] = {
+ { "not valid", false, 0, 0, 0},
+ { "#000000", true, 0, 0, 0},
+ { "#0000", false, 0, 0, 0},
+ { "#abcdef", true, 0xab, 0xcd, 0xef},
+ { "#ABCDEF", true, 0xab, 0xcd, 0xef},
+ { "#123456", true, 0x12, 0x34, 0x56}
+ };
+
+ for (size_t i = 0; i < sizeof(data)/sizeof(data[0]); ++i)
+ {
+ test_color_conversion(data[i].input, data[i].valid, data[i].red, data[i].green, data[i].blue);
+ }
+ return 0;
+}
diff --git a/src/liborcus/odf_namespace_types.cpp b/src/liborcus/odf_namespace_types.cpp
new file mode 100644
index 0000000..ae768db
--- /dev/null
+++ b/src/liborcus/odf_namespace_types.cpp
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_namespace_types.hpp"
+
+#include "odf_namespace_types_cpp.inl"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_namespace_types.hpp b/src/liborcus/odf_namespace_types.hpp
new file mode 100644
index 0000000..5dce680
--- /dev/null
+++ b/src/liborcus/odf_namespace_types.hpp
@@ -0,0 +1,16 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_ODF_NAMESPACE_TYPES_HPP__
+#define __ORCUS_ODF_NAMESPACE_TYPES_HPP__
+
+#include "orcus/types.hpp"
+
+#include "odf_namespace_types_hpp.inl"
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_namespace_types_cpp.inl b/src/liborcus/odf_namespace_types_cpp.inl
new file mode 100644
index 0000000..8b0dc1f
--- /dev/null
+++ b/src/liborcus/odf_namespace_types_cpp.inl
@@ -0,0 +1,63 @@
+namespace orcus {
+
+const xmlns_id_t NS_odf_anim = "urn:oasis:names:tc:opendocument:xmlns:animation:1.0";
+const xmlns_id_t NS_odf_chart = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0";
+const xmlns_id_t NS_odf_config = "urn:oasis:names:tc:opendocument:xmlns:config:1.0";
+const xmlns_id_t NS_odf_db = "urn:oasis:names:tc:opendocument:xmlns:database:1.0";
+const xmlns_id_t NS_odf_dc = "http://purl.org/dc/elements/1.1/";
+const xmlns_id_t NS_odf_dr3d = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0";
+const xmlns_id_t NS_odf_draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";
+const xmlns_id_t NS_odf_fo = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0";
+const xmlns_id_t NS_odf_form = "urn:oasis:names:tc:opendocument:xmlns:form:1.0";
+const xmlns_id_t NS_odf_grddl = "http://www.w3.org/2003/g/data-view#";
+const xmlns_id_t NS_odf_math = "http://www.w3.org/1998/Math/MathML";
+const xmlns_id_t NS_odf_meta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0";
+const xmlns_id_t NS_odf_number = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0";
+const xmlns_id_t NS_odf_office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0";
+const xmlns_id_t NS_odf_presentation = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0";
+const xmlns_id_t NS_odf_script = "urn:oasis:names:tc:opendocument:xmlns:script:1.0";
+const xmlns_id_t NS_odf_smil = "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0";
+const xmlns_id_t NS_odf_style = "urn:oasis:names:tc:opendocument:xmlns:style:1.0";
+const xmlns_id_t NS_odf_svg = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0";
+const xmlns_id_t NS_odf_table = "urn:oasis:names:tc:opendocument:xmlns:table:1.0";
+const xmlns_id_t NS_odf_text = "urn:oasis:names:tc:opendocument:xmlns:text:1.0";
+const xmlns_id_t NS_odf_xforms = "http://www.w3.org/2002/xforms";
+const xmlns_id_t NS_odf_xhtml = "http://www.w3.org/1999/xhtml";
+const xmlns_id_t NS_odf_xlink = "http://www.w3.org/1999/xlink";
+
+namespace {
+
+const xmlns_id_t odf_ns[] = {
+ NS_odf_anim,
+ NS_odf_chart,
+ NS_odf_config,
+ NS_odf_db,
+ NS_odf_dc,
+ NS_odf_dr3d,
+ NS_odf_draw,
+ NS_odf_fo,
+ NS_odf_form,
+ NS_odf_grddl,
+ NS_odf_math,
+ NS_odf_meta,
+ NS_odf_number,
+ NS_odf_office,
+ NS_odf_presentation,
+ NS_odf_script,
+ NS_odf_smil,
+ NS_odf_style,
+ NS_odf_svg,
+ NS_odf_table,
+ NS_odf_text,
+ NS_odf_xforms,
+ NS_odf_xhtml,
+ NS_odf_xlink,
+ nullptr
+};
+
+} // anonymous
+
+const xmlns_id_t* NS_odf_all = odf_ns;
+
+}
+
diff --git a/src/liborcus/odf_namespace_types_hpp.inl b/src/liborcus/odf_namespace_types_hpp.inl
new file mode 100644
index 0000000..a80c917
--- /dev/null
+++ b/src/liborcus/odf_namespace_types_hpp.inl
@@ -0,0 +1,31 @@
+namespace orcus {
+
+extern const xmlns_id_t NS_odf_anim;
+extern const xmlns_id_t NS_odf_chart;
+extern const xmlns_id_t NS_odf_config;
+extern const xmlns_id_t NS_odf_db;
+extern const xmlns_id_t NS_odf_dc;
+extern const xmlns_id_t NS_odf_dr3d;
+extern const xmlns_id_t NS_odf_draw;
+extern const xmlns_id_t NS_odf_fo;
+extern const xmlns_id_t NS_odf_form;
+extern const xmlns_id_t NS_odf_grddl;
+extern const xmlns_id_t NS_odf_math;
+extern const xmlns_id_t NS_odf_meta;
+extern const xmlns_id_t NS_odf_number;
+extern const xmlns_id_t NS_odf_office;
+extern const xmlns_id_t NS_odf_presentation;
+extern const xmlns_id_t NS_odf_script;
+extern const xmlns_id_t NS_odf_smil;
+extern const xmlns_id_t NS_odf_style;
+extern const xmlns_id_t NS_odf_svg;
+extern const xmlns_id_t NS_odf_table;
+extern const xmlns_id_t NS_odf_text;
+extern const xmlns_id_t NS_odf_xforms;
+extern const xmlns_id_t NS_odf_xhtml;
+extern const xmlns_id_t NS_odf_xlink;
+
+extern const xmlns_id_t* NS_odf_all;
+
+}
+
diff --git a/src/liborcus/odf_number_format_context.cpp b/src/liborcus/odf_number_format_context.cpp
new file mode 100644
index 0000000..d224a64
--- /dev/null
+++ b/src/liborcus/odf_number_format_context.cpp
@@ -0,0 +1,1126 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_number_format_context.hpp"
+#include "odf_namespace_types.hpp"
+#include "odf_token_constants.hpp"
+#include "odf_helper.hpp"
+#include "ods_session_data.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/measurement.hpp>
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+#include <orcus/spreadsheet/styles.hpp>
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+enum class date_style_type
+{
+ unknown = 0,
+ short_symbol,
+ long_symbol
+};
+
+date_style_type to_date_style(std::string_view s)
+{
+ constexpr std::pair<std::string_view, date_style_type> entries[] = {
+ { "short", date_style_type::short_symbol },
+ { "long", date_style_type::long_symbol },
+ };
+
+ for (const auto& entry : entries)
+ {
+ if (s == entry.first)
+ return entry.second;
+ }
+
+ return date_style_type::unknown;
+}
+
+struct parse_result
+{
+ bool success = true;
+ std::string error_message;
+};
+
+date_style_type parse_attrs_for_date_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_style:
+ return to_date_style(attr.value);
+ }
+ }
+ }
+
+ return date_style_type::unknown;
+}
+
+void parse_element_time_short_long(const std::vector<xml_token_attr_t>& attrs, char c, odf_number_format& style)
+{
+ style.code += c;
+
+ if (parse_attrs_for_date_style(attrs) == date_style_type::long_symbol)
+ style.code += c;
+}
+
+void parse_element_number(const std::vector<xml_token_attr_t>& attrs, odf_number_format& style)
+{
+ bool grouping = false;
+ long decimal_places = 0;
+ long min_integer_digits = 0;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_decimal_places:
+ {
+ decimal_places = to_long(attr.value);
+ break;
+ }
+ case XML_grouping:
+ grouping = to_bool(attr.value);
+ break;
+ case XML_min_integer_digits:
+ min_integer_digits = to_long(attr.value);
+ break;
+ default:;
+ }
+ }
+ }
+
+ if (grouping)
+ {
+ if (min_integer_digits < 4)
+ {
+ style.code += "#,";
+
+ for (long i = 0; i < 3 - min_integer_digits; ++i)
+ style.code += "#";
+
+ for (long i = 0; i < min_integer_digits; ++i)
+ style.code += "0";
+ }
+ else
+ {
+ std::string temporary_code;
+
+ for (long i = 0; i < min_integer_digits; ++i)
+ {
+ if (i % 3 == 0 && i != 0)
+ temporary_code += ",";
+
+ temporary_code += "0";
+ }
+
+ std::reverse(temporary_code.begin(), temporary_code.end());
+ style.code += temporary_code;
+ }
+ }
+ else
+ {
+ if (min_integer_digits == 0)
+ style.code += "#";
+
+ for (long i = 0; i < min_integer_digits; ++i)
+ style.code += "0";
+ }
+
+ if (decimal_places > 0)
+ {
+ style.code += ".";
+ for (long i = 0; i < decimal_places; ++i)
+ style.code += "0";
+ }
+}
+
+void parse_element_text_properties(const std::vector<xml_token_attr_t>& attrs, odf_number_format& style)
+{
+ std::string_view color;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_fo)
+ {
+ switch (attr.name)
+ {
+ case XML_color:
+ {
+ if (attr.value == "#000000")
+ color = "BLACK";
+ if (attr.value == "#ff0000")
+ color = "RED";
+ if (attr.value == "#00ff00")
+ color = "GREEN";
+ if (attr.value == "#0000ff")
+ color = "BLUE";
+ if (attr.value == "#ffff00")
+ color = "YELLOW";
+ if (attr.value == "#00ffff")
+ color = "CYAN";
+ if (attr.value == "#ff00ff")
+ color = "MAGENTA";
+ if (attr.value == "#ffffff")
+ color = "WHITE";
+ }
+ }
+ }
+ }
+
+ if (!color.empty())
+ {
+ std::ostringstream os;
+ os << '[' << color << ']';
+ style.code += os.str();
+ }
+}
+
+parse_result parse_element_map(session_context& cxt, const std::vector<xml_token_attr_t>& attrs, odf_number_format& style)
+{
+ parse_result res;
+
+ std::string_view comp; // comparison operator e.g. <, >, >=, ...
+ std::string_view value; // right-hand value
+ std::string_view style_name; // style name associated with the mapped rule
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_apply_style_name:
+ {
+ style_name = attr.value;
+ break;
+ }
+ case XML_condition:
+ {
+ // value()[comp][rvalue] e.g. 'value()>=0'
+ constexpr std::string_view prefix = "value()";
+
+ // check if the attribute value starts with 'value()'
+ if (attr.value.compare(0, prefix.size(), prefix) == 0)
+ {
+ auto pos_value = attr.value.find_first_not_of("<>=", prefix.size());
+
+ comp = attr.value.substr(prefix.size(), pos_value - prefix.size());
+ value = attr.value.substr(pos_value);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (comp.empty() || value.empty() || style_name.empty())
+ {
+ res.success = false;
+ return res;
+ }
+
+ // fetch the code associated with the mapped rule
+ auto& numfmts = cxt.get_data<ods_session_data>().number_formats;
+ std::string_view code = numfmts.get_code(style_name);
+
+ if (code.empty())
+ {
+ res.success = false;
+ std::ostringstream os;
+ os << "code stored for the number format style named '" << style_name << "' exists, but is empty.";
+ res.error_message = os.str();
+ return res;
+ }
+
+ // prepend the mapped rule to the current code
+ std::ostringstream os;
+ os << '[' << comp << value << ']' << code << ';' << style.code;
+ style.code = os.str();
+
+ return res;
+}
+
+} // anonymous namespace
+
+date_style_context::date_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_date_style }, // root element
+ { NS_odf_number, XML_date_style, NS_odf_number, XML_day },
+ { NS_odf_number, XML_date_style, NS_odf_number, XML_month },
+ { NS_odf_number, XML_date_style, NS_odf_number, XML_text },
+ { NS_odf_number, XML_date_style, NS_odf_number, XML_year },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void date_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_date_style:
+ start_element_date_style(attrs);
+ break;
+ case XML_month:
+ start_element_month(attrs);
+ break;
+ case XML_day:
+ start_element_day(attrs);
+ break;
+ case XML_year:
+ start_element_year(attrs);
+ break;
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool date_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void date_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void date_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> date_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+void date_style_context::start_element_date_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ m_current_style->name = intern(attr);
+ break;
+ }
+ }
+ }
+}
+
+void date_style_context::start_element_month(const std::vector<xml_token_attr_t>& attrs)
+{
+ auto style = date_style_type::unknown;
+ bool textual = false;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_style:
+ style = to_date_style(attr.value);
+ break;
+ case XML_textual:
+ textual = to_bool(attr.value);
+ break;
+ }
+ }
+ }
+
+ m_current_style->code += 'M';
+
+ if (style == date_style_type::long_symbol)
+ m_current_style->code += 'M';
+
+ if (textual)
+ m_current_style->code += 'M';
+
+ if (style == date_style_type::long_symbol && textual)
+ m_current_style->code += 'M';
+}
+
+void date_style_context::start_element_day(const std::vector<xml_token_attr_t>& attrs)
+{
+ m_current_style->code += 'D';
+
+ if (parse_attrs_for_date_style(attrs) == date_style_type::long_symbol)
+ m_current_style->code += 'D';
+}
+
+void date_style_context::start_element_year(const std::vector<xml_token_attr_t>& attrs)
+{
+ m_current_style->code += "YY";
+
+ if (parse_attrs_for_date_style(attrs) == date_style_type::long_symbol)
+ m_current_style->code += "YY";
+}
+
+time_style_context::time_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_time_style }, // root element
+ { NS_odf_number, XML_time_style, NS_odf_number, XML_hours },
+ { NS_odf_number, XML_time_style, NS_odf_number, XML_minutes },
+ { NS_odf_number, XML_time_style, NS_odf_number, XML_seconds },
+ { NS_odf_number, XML_time_style, NS_odf_number, XML_text },
+ { NS_odf_number, XML_time_style, NS_odf_number, XML_am_pm },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void time_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_time_style:
+ start_element_time_style(attrs);
+ break;
+ case XML_hours:
+ parse_element_time_short_long(attrs, 'H', *m_current_style);
+ break;
+ case XML_minutes:
+ parse_element_time_short_long(attrs, 'M', *m_current_style);
+ break;
+ case XML_seconds:
+ start_element_seconds(attrs);
+ break;
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ case XML_am_pm:
+ m_current_style->code += "AM/PM";
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool time_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void time_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void time_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> time_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+void time_style_context::start_element_time_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style && attr.name == XML_name)
+ m_current_style->name = intern(attr);
+ }
+}
+
+void time_style_context::start_element_seconds(const std::vector<xml_token_attr_t>& attrs)
+{
+ auto style = date_style_type::unknown;
+ std::optional<std::size_t> decimal_places;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_style:
+ style = to_date_style(attr.value);
+ break;
+ case XML_decimal_places:
+ decimal_places = to_long(attr.value);
+ break;
+ }
+ }
+ }
+
+ m_current_style->code += 'S';
+
+ if (style == date_style_type::long_symbol)
+ m_current_style->code += 'S';
+
+ if (decimal_places && *decimal_places > 0)
+ m_current_style->code += std::string{"S", *decimal_places};
+}
+
+percentage_style_context::percentage_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_percentage_style }, // root element
+ { NS_odf_number, XML_percentage_style, NS_odf_number, XML_number },
+ { NS_odf_number, XML_percentage_style, NS_odf_number, XML_text },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void percentage_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_percentage_style:
+ {
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style && attr.name == XML_name)
+ m_current_style->name = intern(attr);
+ }
+ break;
+ }
+ case XML_number:
+ {
+ parse_element_number(attrs, *m_current_style);
+ break;
+ }
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool percentage_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void percentage_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void percentage_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> percentage_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+boolean_style_context::boolean_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_boolean_style }, // root element
+ { NS_odf_number, XML_boolean_style, NS_odf_number, XML_boolean },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void boolean_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_boolean_style:
+ {
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style && attr.name == XML_name)
+ m_current_style->name = intern(attr);
+ }
+ break;
+ }
+ case XML_boolean:
+ {
+ m_current_style->code += "BOOLEAN";
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool boolean_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void boolean_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> boolean_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+text_style_context::text_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_text_style }, // root element
+ { NS_odf_number, XML_text_style, NS_odf_number, XML_text },
+ { NS_odf_number, XML_text_style, NS_odf_number, XML_text_content },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void text_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text_style:
+ {
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style && attr.name == XML_name)
+ m_current_style->name = intern(attr);
+ }
+ break;
+ }
+ case XML_text_content:
+ {
+ m_current_style->code += '@';
+ break;
+ }
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool text_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void text_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void text_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> text_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+number_style_context::number_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_number_style }, // root element
+ { NS_odf_number, XML_number_style, NS_odf_number, XML_fraction },
+ { NS_odf_number, XML_number_style, NS_odf_number, XML_number },
+ { NS_odf_number, XML_number_style, NS_odf_number, XML_scientific_number },
+ { NS_odf_number, XML_number_style, NS_odf_number, XML_text },
+ { NS_odf_number, XML_number_style, NS_odf_style, XML_map },
+ { NS_odf_number, XML_number_style, NS_odf_style, XML_text_properties },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void number_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_fraction:
+ start_element_fraction(attrs);
+ break;
+ case XML_number_style:
+ start_element_number_style(attrs);
+ break;
+ case XML_number:
+ parse_element_number(attrs, *m_current_style);
+ break;
+ case XML_scientific_number:
+ start_element_scientific_number(attrs);
+ break;
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_odf_style)
+ {
+ switch (name)
+ {
+ case XML_text_properties:
+ parse_element_text_properties(attrs, *m_current_style);
+ break;
+ case XML_map:
+ {
+ auto res = parse_element_map(get_session_context(), attrs, *m_current_style);
+ if (!res.success && get_config().debug)
+ warn(res.error_message);
+
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool number_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ default:;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void number_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void number_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+ m_text_stream = std::ostringstream{};
+ m_country_code = std::string_view{};
+ m_language = std::string_view{};
+}
+
+std::unique_ptr<odf_number_format> number_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+void number_style_context::start_element_fraction(const std::vector<xml_token_attr_t>& attrs)
+{
+ std::size_t min_integer_digits = 0;
+ std::size_t min_numerator_digits = 0;
+ std::size_t min_denominator_digits = 0;
+
+ std::optional<std::string_view> denominator_value;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_min_integer_digits:
+ min_integer_digits = to_long(attr.value);
+ break;
+ case XML_min_numerator_digits:
+ min_numerator_digits = to_long(attr.value);
+ break;
+ case XML_min_denominator_digits:
+ min_denominator_digits = to_long(attr.value);
+ break;
+ case XML_denominator_value:
+ {
+ denominator_value = attr.value;
+ break;
+ }
+ }
+ }
+ }
+
+ if (min_integer_digits > 0)
+ {
+ m_current_style->code += std::string{"#", min_integer_digits};
+ m_current_style->code += ' ';
+ }
+
+ if (min_numerator_digits > 0)
+ m_current_style->code += std::string{"?", min_numerator_digits};
+
+ m_current_style->code += '/';
+
+ if (denominator_value)
+ m_current_style->code += *denominator_value;
+ else if (min_denominator_digits > 0)
+ m_current_style->code += std::string{"?", min_denominator_digits};
+}
+
+void number_style_context::start_element_number_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const xml_token_attr_t& attr: attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_country:
+ m_country_code = attr.value;
+ break;
+ case XML_language:
+ m_language = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ m_current_style->name = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+}
+
+void number_style_context::start_element_scientific_number(const std::vector<xml_token_attr_t>& attrs)
+{
+ long decimal_places = 0;
+ long min_exponent_digits = 0;
+ long min_integer_digits = 0;
+ bool grouping = false;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_decimal_places:
+ decimal_places = to_long(attr.value);
+ break;
+ case XML_grouping:
+ grouping = to_bool(attr.value);
+ break;
+ case XML_min_exponent_digits:
+ min_exponent_digits = to_long(attr.value);
+ break;
+ case XML_min_integer_digits:
+ min_integer_digits = to_long(attr.value);
+ break;
+ }
+ }
+ }
+
+ if (grouping)
+ {
+ if (min_integer_digits < 4)
+ {
+ m_current_style->code += "#,";
+
+ for (long i = 0; i < 3 - min_integer_digits; ++i)
+ {
+ m_current_style->code += "#";
+ }
+
+ for (long i = 0; i < min_integer_digits; ++i)
+ {
+ m_current_style->code += "0";
+ }
+ }
+ else
+ {
+ std::string temporary_code;
+ for (long i = 0; i < min_integer_digits; ++i)
+ {
+ if (i % 3 == 0 && i != 0)
+ temporary_code += ",";
+
+ temporary_code += "0";
+ }
+
+ std::reverse(temporary_code.begin(), temporary_code.end());
+ m_current_style->code += temporary_code;
+ }
+ }
+ else
+ {
+ if (min_integer_digits == 0)
+ m_current_style->code += "#";
+
+ for (long i = 0; i < min_integer_digits; ++i)
+ m_current_style->code += "0";
+ }
+
+ m_current_style->code += ".";
+
+ for (long i = 0; i < decimal_places; ++i)
+ m_current_style->code += "0";
+
+ m_current_style->code += "E+";
+
+ for (long i = 0; i < min_exponent_digits; ++i)
+ m_current_style->code += "0";
+}
+
+currency_style_context::currency_style_context(session_context& session_cxt, const tokens& tk) :
+ xml_context_base(session_cxt, tk)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_odf_number, XML_currency_style }, // root element
+ { NS_odf_number, XML_currency_style, NS_odf_number, XML_currency_symbol },
+ { NS_odf_number, XML_currency_style, NS_odf_number, XML_number },
+ { NS_odf_number, XML_currency_style, NS_odf_number, XML_text },
+ { NS_odf_number, XML_currency_style, NS_odf_style, XML_map },
+ { NS_odf_number, XML_currency_style, NS_odf_style, XML_text_properties },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+void currency_style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_currency_style:
+ start_element_currency_style(attrs);
+ break;
+ case XML_currency_symbol:
+ m_text_stream = std::ostringstream{};
+ break;
+ case XML_number:
+ parse_element_number(attrs, *m_current_style);
+ break;
+ case XML_text:
+ m_text_stream = std::ostringstream{};
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_odf_style)
+ {
+ switch (name)
+ {
+ case XML_map:
+ {
+ auto res = parse_element_map(get_session_context(), attrs, *m_current_style);
+ if (!res.success && get_config().debug)
+ warn(res.error_message);
+
+ break;
+ }
+ case XML_text_properties:
+ parse_element_text_properties(attrs, *m_current_style);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool currency_style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_currency_symbol:
+ {
+ std::ostringstream os;
+ os << m_current_style->code << "[$" << m_text_stream.str() << ']';
+ m_current_style->code = os.str();
+ break;
+ }
+ case XML_text:
+ m_current_style->code += m_text_stream.str();
+ break;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void currency_style_context::characters(std::string_view str, bool /*transient*/)
+{
+ m_text_stream << str;
+}
+
+void currency_style_context::reset()
+{
+ m_current_style = std::make_unique<odf_number_format>();
+}
+
+std::unique_ptr<odf_number_format> currency_style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+void currency_style_context::start_element_currency_style(const std::vector<xml_token_attr_t>& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ m_current_style->name = intern(attr);
+ break;
+ case XML_volatile:
+ m_current_style->is_volatile = to_bool(attr.value);
+ break;
+ }
+ }
+ else if (attr.ns == NS_odf_number)
+ {
+ switch (attr.name)
+ {
+ case XML_language:
+ m_language = intern(attr);
+ break;
+ case XML_country:
+ m_country_code = intern(attr);
+ break;
+ }
+ }
+ }
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_number_format_context.hpp b/src/liborcus/odf_number_format_context.hpp
new file mode 100644
index 0000000..c91c817
--- /dev/null
+++ b/src/liborcus/odf_number_format_context.hpp
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ODF_NUMBER_FORMATTING_CONTEXT_HPP
+#define ODF_NUMBER_FORMATTING_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "odf_styles.hpp"
+
+#include "orcus/string_pool.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+ class import_styles;
+}}
+
+class date_style_context : public xml_context_base
+{
+public:
+ date_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ void start_element_date_style(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_month(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_day(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_year(const std::vector<xml_token_attr_t>& attrs);
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+};
+
+class time_style_context : public xml_context_base
+{
+public:
+ time_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ void start_element_time_style(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_seconds(const std::vector<xml_token_attr_t>& attrs);
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+};
+
+class percentage_style_context : public xml_context_base
+{
+public:
+ percentage_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+};
+
+class boolean_style_context : public xml_context_base
+{
+public:
+ boolean_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+};
+
+class text_style_context : public xml_context_base
+{
+public:
+ text_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+};
+
+/**
+ * Context for <number:number-style> scope.
+ */
+class number_style_context : public xml_context_base
+{
+public:
+ number_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ void start_element_fraction(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_number_style(const std::vector<xml_token_attr_t>& attrs);
+ void start_element_scientific_number(const std::vector<xml_token_attr_t>& attrs);
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+
+ std::string_view m_country_code; // TODO: handle this
+ std::string_view m_language; // TODO: handle this
+};
+
+/**
+ * Context for <number:currency-style> element scope.
+ */
+class currency_style_context : public xml_context_base
+{
+public:
+ currency_style_context(session_context& session_cxt, const tokens& tk);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+ std::unique_ptr<odf_number_format> pop_style();
+
+private:
+ void start_element_currency_style(const std::vector<xml_token_attr_t>& attrs);
+
+private:
+ std::unique_ptr<odf_number_format> m_current_style;
+ std::ostringstream m_text_stream;
+
+ std::string_view m_country_code; // TODO: handle this
+ std::string_view m_language; // TODO: handle this
+};
+
+} // namespace orcus
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_para_context.cpp b/src/liborcus/odf_para_context.cpp
new file mode 100644
index 0000000..ad4b193
--- /dev/null
+++ b/src/liborcus/odf_para_context.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_para_context.hpp"
+#include "odf_token_constants.hpp"
+#include "odf_namespace_types.hpp"
+#include "xml_context_global.hpp"
+
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/exception.hpp"
+
+#include <iostream>
+#include <cassert>
+
+namespace orcus {
+
+text_para_context::text_para_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_shared_strings* ssb, odf_styles_map_type& styles) :
+ xml_context_base(session_cxt, tokens),
+ mp_sstrings(ssb), m_styles(styles),
+ m_string_index(0), m_has_content(false)
+{
+}
+
+text_para_context::~text_para_context() = default;
+
+xml_context_base* text_para_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void text_para_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+ // not implemented yet.
+}
+
+void text_para_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_odf_text)
+ {
+ switch (name)
+ {
+ case XML_p:
+ // paragraph
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ break;
+ case XML_span:
+ {
+ // text span.
+ xml_element_expected(parent, NS_odf_text, XML_p);
+ flush_segment();
+ std::string_view style_name =
+ for_each(attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_odf_text, XML_style_name)).get_value();
+ m_span_stack.push_back(style_name);
+
+ }
+ break;
+ case XML_s:
+ // control character. ignored for now.
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool text_para_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_text)
+ {
+ switch (name)
+ {
+ case XML_p:
+ {
+ // paragraph
+ flush_segment();
+ if (mp_sstrings)
+ m_string_index = mp_sstrings->commit_segments();
+ }
+ break;
+ case XML_span:
+ {
+ // text span.
+ if (m_span_stack.empty())
+ throw xml_structure_error("</text:span> encountered without matching opening element.");
+
+ flush_segment();
+ m_span_stack.pop_back();
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void text_para_context::characters(std::string_view str, bool transient)
+{
+ if (transient)
+ m_contents.push_back(m_pool.intern(str).first);
+ else
+ m_contents.push_back(str);
+}
+
+void text_para_context::reset()
+{
+ m_string_index = 0;
+ m_has_content = false;
+ m_pool.clear();
+ m_contents.clear();
+}
+
+size_t text_para_context::get_string_index() const
+{
+ return m_string_index;
+}
+
+bool text_para_context::empty() const
+{
+ return !m_has_content;
+}
+
+void text_para_context::flush_segment()
+{
+ if (m_contents.empty())
+ // No content to flush.
+ return;
+
+ m_has_content = true;
+
+ const odf_style* style = nullptr;
+ if (!m_span_stack.empty())
+ {
+ std::string_view style_name = m_span_stack.back();
+ auto it = m_styles.find(style_name);
+ if (it != m_styles.end())
+ style = it->second.get();
+ }
+
+ if (mp_sstrings)
+ {
+ if (style && style->family == style_family_text)
+ {
+ const auto& data = std::get<odf_style::text>(style->data);
+ mp_sstrings->set_segment_font(data.font);
+ }
+
+ for (std::string_view ps : m_contents)
+ mp_sstrings->append_segment(ps);
+ }
+
+ m_contents.clear();
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_para_context.hpp b/src/liborcus/odf_para_context.hpp
new file mode 100644
index 0000000..42bdb7d
--- /dev/null
+++ b/src/liborcus/odf_para_context.hpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_PARACONTEXT_HPP
+#define ORCUS_PARACONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "odf_styles.hpp"
+
+#include "orcus/string_pool.hpp"
+
+#include <vector>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface { class import_shared_strings; }}
+
+/**
+ * This class handles <text:p> contexts.
+ */
+class text_para_context : public xml_context_base
+{
+public:
+ text_para_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_shared_strings* ssb, odf_styles_map_type& styles);
+ virtual ~text_para_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ void reset();
+
+ size_t get_string_index() const;
+ bool empty() const;
+
+private:
+ void flush_segment();
+
+private:
+ spreadsheet::iface::import_shared_strings* mp_sstrings;
+ odf_styles_map_type& m_styles;
+
+ string_pool m_pool;
+ std::vector<std::string_view> m_span_stack; /// stack of text spans.
+ std::vector<std::string_view> m_contents;
+ size_t m_string_index;
+ bool m_has_content;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_style_context.cpp b/src/liborcus/odf_style_context.cpp
new file mode 100644
index 0000000..70953a1
--- /dev/null
+++ b/src/liborcus/odf_style_context.cpp
@@ -0,0 +1,774 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_style_context.hpp"
+#include "impl_utils.hpp"
+#include "odf_namespace_types.hpp"
+#include "odf_token_constants.hpp"
+#include "odf_helper.hpp"
+#include "session_context.hpp"
+#include "ods_session_data.hpp"
+
+#include <mdds/sorted_string_map.hpp>
+
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace style_family {
+
+using map_type = mdds::sorted_string_map<odf_style_family>;
+
+constexpr map_type::entry entries[] =
+{
+ { MDDS_ASCII("graphic"), style_family_graphic },
+ { MDDS_ASCII("paragraph"), style_family_paragraph },
+ { MDDS_ASCII("table"), style_family_table },
+ { MDDS_ASCII("table-cell"), style_family_table_cell },
+ { MDDS_ASCII("table-column"), style_family_table_column },
+ { MDDS_ASCII("table-row"), style_family_table_row },
+ { MDDS_ASCII("text"), style_family_text }
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), style_family_unknown);
+ return mt;
+}
+
+} // namespace style_family
+
+odf_style_family to_style_family(std::string_view val)
+{
+ return style_family::get().find(val.data(), val.size());
+}
+
+std::string_view to_string(odf_style_family family)
+{
+ static constexpr std::string_view unknown_str = "unknown";
+
+ for (const auto& entry : style_family::entries)
+ {
+ if (entry.value == family)
+ return {entry.key, entry.key_length};
+ }
+
+ return unknown_str;
+}
+
+namespace st_style {
+
+typedef mdds::sorted_string_map<ss::strikethrough_style_t> map_type;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { MDDS_ASCII("dash"), ss::strikethrough_style_t::dash },
+ { MDDS_ASCII("dot-dash"), ss::strikethrough_style_t::dot_dash },
+ { MDDS_ASCII("dot-dot-dash"), ss::strikethrough_style_t::dot_dot_dash },
+ { MDDS_ASCII("dotted"), ss::strikethrough_style_t::dotted },
+ { MDDS_ASCII("long-dash"), ss::strikethrough_style_t::long_dash },
+ { MDDS_ASCII("none"), ss::strikethrough_style_t::none },
+ { MDDS_ASCII("solid"), ss::strikethrough_style_t::solid },
+ { MDDS_ASCII("wave"), ss::strikethrough_style_t::wave },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::strikethrough_style_t::none);
+ return mt;
+}
+
+} // namespace st_style
+
+} // anonymous namespace
+
+style_context::style_context(session_context& session_cxt, const tokens& tk, ss::iface::import_styles* iface_styles) :
+ xml_context_base(session_cxt, tk),
+ mp_styles(iface_styles)
+{
+}
+
+void style_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_odf_style)
+ {
+ switch (name)
+ {
+ case XML_style:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+
+ std::string_view style_name;
+ std::string_view display_style_name;
+ std::string_view parent_style_name;
+ std::optional<std::string_view> data_style_name;
+ odf_style_family family = style_family_unknown;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ style_name = intern(attr.value);
+ break;
+ case XML_display_name:
+ display_style_name = intern(attr.value);
+ break;
+ case XML_family:
+ family = to_style_family(attr.value);
+ break;
+ case XML_parent_style_name:
+ parent_style_name = intern(attr.value);
+ break;
+ case XML_data_style_name:
+ data_style_name = attr.value; // no need to intern
+ break;
+ }
+ }
+ }
+
+ m_current_style = std::make_unique<odf_style>(
+ style_name, display_style_name, family, parent_style_name);
+
+ if (data_style_name && family == style_family_table_cell)
+ {
+ const auto& ods_data = get_session_context().get_data<ods_session_data>();
+ const auto& numfmt_name2id = ods_data.number_formats.name2id_map;
+
+ if (auto it = numfmt_name2id.find(*data_style_name); it != numfmt_name2id.end())
+ {
+ // record the number format id associated with the name.
+ auto& data = std::get<odf_style::cell>(m_current_style->data);
+ data.number_format = it->second;
+ }
+ else
+ {
+ if (get_config().debug)
+ {
+ std::ostringstream os;
+ os << "no number style found for the data style name of '" << *data_style_name << "'";
+ warn(os.str());
+ }
+ }
+ }
+ break;
+ }
+ case XML_table_column_properties:
+ {
+ xml_element_expected(parent, NS_odf_style, XML_style);
+ assert(m_current_style->family == style_family_table_column);
+
+ for (const xml_token_attr_t& attr: attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_column_width:
+ {
+ std::get<odf_style::column>(m_current_style->data).width = to_length(attr.value);
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case XML_table_row_properties:
+ {
+ xml_element_expected(parent, NS_odf_style, XML_style);
+ assert(m_current_style->family == style_family_table_row);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_row_height:
+ {
+ auto& data = std::get<odf_style::row>(m_current_style->data);
+ data.height = to_length(attr.value);
+ data.height_set = true;
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case XML_table_properties:
+ xml_element_expected(parent, NS_odf_style, XML_style);
+ break;
+ case XML_paragraph_properties:
+ start_paragraph_properties(parent, attrs);
+ break;
+ case XML_text_properties:
+ start_text_properties(parent, attrs);
+ break;
+ case XML_table_cell_properties:
+ start_table_cell_properties(parent, attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool style_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void style_context::reset()
+{
+ m_current_style.reset();
+}
+
+std::unique_ptr<odf_style> style_context::pop_style()
+{
+ return std::move(m_current_style);
+}
+
+void style_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void style_context::start_paragraph_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_element_expected(parent, NS_odf_style, XML_style);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_fo)
+ {
+ switch (attr.name)
+ {
+ case XML_text_align:
+ {
+ auto v = odf::extract_hor_alignment_style(attr.value);
+
+ switch (m_current_style->family)
+ {
+ case style_family_table_cell:
+ {
+ auto& data = std::get<odf_style::cell>(m_current_style->data);
+ data.hor_align = v;
+ break;
+ }
+ case style_family_paragraph:
+ {
+ auto& data = std::get<odf_style::paragraph>(m_current_style->data);
+ data.hor_align = v;
+ break;
+ }
+ default:
+ {
+ if (get_config().debug)
+ {
+ std::ostringstream os;
+ os << "unhandled fo:text-align attribute (family=" << to_string(m_current_style->family) << ")";
+ warn(os.str());
+ }
+ }
+ }
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ }
+}
+
+void style_context::start_text_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ static const xml_elem_set_t expected = {
+ { NS_odf_style, XML_style },
+ { NS_odf_text, XML_list_level_style_number },
+ { NS_odf_text, XML_list_level_style_bullet },
+ };
+ xml_element_expected(parent, expected);
+
+ if (parent != xml_token_pair_t(NS_odf_style, XML_style))
+ // TODO : handle this properly in the future.
+ return;
+
+ // NB: no need to intern the font names since they are consumed at the end
+ // of this function.
+ std::optional<std::string_view> font_name;
+ std::optional<std::string_view> font_name_asian;
+ std::optional<std::string_view> font_name_complex;
+ std::optional<length_t> font_size;
+ std::optional<length_t> font_size_asian;
+ std::optional<length_t> font_size_complex;
+ std::optional<bool> bold;
+ std::optional<bool> bold_asian;
+ std::optional<bool> bold_complex;
+ std::optional<bool> italic;
+ std::optional<bool> italic_asian;
+ std::optional<bool> italic_complex;
+ std::optional<ss::color_rgb_t> color;
+
+ std::optional<ss::color_rgb_t> underline_color;
+ std::optional<ss::underline_t> underline_style;
+ std::optional<ss::underline_type_t> underline_type;
+ std::optional<ss::underline_width_t> underline_width;
+ std::optional<ss::underline_mode_t> underline_mode;
+
+ std::optional<ss::strikethrough_style_t> strikethrough_style;
+ std::optional<ss::strikethrough_type_t> strikethrough_type;
+ std::optional<ss::strikethrough_width_t> strikethrough_width;
+ std::optional<ss::strikethrough_text_t> strikethrough_text;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_font_name:
+ font_name = attr.value;
+ break;
+ case XML_font_name_asian:
+ font_name_asian = attr.value;
+ break;
+ case XML_font_name_complex:
+ font_name_complex = attr.value;
+ break;
+ case XML_font_size_asian:
+ font_size_asian = to_length(attr.value);
+ break;
+ case XML_font_size_complex:
+ font_size_complex = to_length(attr.value);
+ break;
+ case XML_font_style_asian:
+ italic_asian = attr.value == "italic";
+ break;
+ case XML_font_style_complex:
+ italic_complex = attr.value == "italic";
+ break;
+ case XML_font_weight_asian:
+ bold_asian = attr.value == "bold";
+ break;
+ case XML_font_weight_complex:
+ bold_complex = attr.value == "bold";
+ break;
+ case XML_text_underline_color:
+ if (attr.value != "font-color")
+ underline_color = odf::convert_fo_color(attr.value);
+ break;
+ case XML_text_underline_mode:
+ if (attr.value == "skip-white-space")
+ underline_mode = ss::underline_mode_t::skip_white_space;
+ else
+ underline_mode = ss::underline_mode_t::continuous;
+ break;
+ case XML_text_underline_width:
+ {
+ underline_width = odf::extract_underline_width(attr.value);
+ break;
+ }
+ case XML_text_underline_style:
+ {
+ underline_style = odf::extract_underline_style(attr.value);
+ break;
+ }
+ case XML_text_underline_type:
+ {
+ if (attr.value == "none")
+ underline_type = ss::underline_type_t::none;
+ else if (attr.value == "single")
+ underline_type = ss::underline_type_t::single_type;
+ else if (attr.value == "double")
+ underline_type = ss::underline_type_t::double_type;
+ break;
+ }
+ case XML_text_line_through_style:
+ {
+ strikethrough_style = st_style::get().find(attr.value.data(), attr.value.size());
+ break;
+ }
+ case XML_text_line_through_type:
+ {
+ if (attr.value == "single")
+ strikethrough_type = ss::strikethrough_type_t::single_type;
+ else if (attr.value == "double")
+ strikethrough_type = ss::strikethrough_type_t::double_type;
+ else
+ strikethrough_type = ss::strikethrough_type_t::unknown;
+ break;
+ }
+ case XML_text_line_through_width:
+ {
+ if (attr.value == "bold")
+ strikethrough_width = ss::strikethrough_width_t::bold;
+ else
+ strikethrough_width = ss::strikethrough_width_t::unknown;
+ break;
+ }
+ case XML_text_line_through_text:
+ {
+ if (attr.value == "/")
+ strikethrough_text = ss::strikethrough_text_t::slash;
+ else if (attr.value == "X")
+ strikethrough_text = ss::strikethrough_text_t::cross;
+ else
+ strikethrough_text = ss::strikethrough_text_t::unknown;
+ break;
+ }
+ }
+ }
+ else if (attr.ns == NS_odf_fo)
+ {
+ switch (attr.name)
+ {
+ case XML_font_size:
+ font_size = to_length(attr.value);
+ break;
+ case XML_font_style:
+ italic = attr.value == "italic";
+ break;
+ case XML_font_weight:
+ bold = attr.value == "bold";
+ break;
+ case XML_color:
+ color = odf::convert_fo_color(attr.value);
+ break;
+ }
+ }
+ }
+
+ // Commit the font data.
+ auto* font_style = mp_styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ if (font_name)
+ font_style->set_name(*font_name);
+
+ if (font_name_asian)
+ font_style->set_name_asian(*font_name_asian);
+
+ if (font_name_complex)
+ font_style->set_name_complex(*font_name_complex);
+
+ if (font_size && font_size->unit == length_unit_t::point)
+ font_style->set_size(font_size->value);
+
+ if (font_size_asian && font_size_asian->unit == length_unit_t::point)
+ font_style->set_size_asian(font_size_asian->value);
+
+ if (font_size_complex && font_size_complex->unit == length_unit_t::point)
+ font_style->set_size_complex(font_size_complex->value);
+
+ if (bold)
+ font_style->set_bold(*bold);
+
+ if (bold_asian)
+ font_style->set_bold_asian(*bold_asian);
+
+ if (bold_complex)
+ font_style->set_bold_complex(*bold_complex);
+
+ if (italic)
+ font_style->set_italic(*italic);
+
+ if (italic_asian)
+ font_style->set_italic_asian(*italic_asian);
+
+ if (italic_complex)
+ font_style->set_italic_complex(*italic_complex);
+
+ if (color)
+ font_style->set_color(255, color->red, color->green, color->blue);
+
+ if (underline_color)
+ // Separate underline color is specified.
+ font_style->set_underline_color(255, underline_color->red, underline_color->green, underline_color->blue);
+
+ if (underline_width)
+ font_style->set_underline_width(*underline_width);
+
+ if (underline_style)
+ font_style->set_underline(*underline_style);
+
+ if (underline_type)
+ font_style->set_underline_type(*underline_type);
+
+ if (underline_mode)
+ font_style->set_underline_mode(*underline_mode);
+
+ if (strikethrough_style)
+ font_style->set_strikethrough_style(*strikethrough_style);
+
+ if (strikethrough_type)
+ font_style->set_strikethrough_type(*strikethrough_type);
+
+ if (strikethrough_width)
+ font_style->set_strikethrough_width(*strikethrough_width);
+
+ if (strikethrough_text)
+ font_style->set_strikethrough_text(*strikethrough_text);
+
+ size_t font_id = font_style->commit();
+
+ switch (m_current_style->family)
+ {
+ case style_family_table_cell:
+ {
+ auto& data = std::get<odf_style::cell>(m_current_style->data);
+ data.font = font_id;
+ break;
+ }
+ case style_family_text:
+ {
+ auto& data = std::get<odf_style::text>(m_current_style->data);
+ data.font = font_id;
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void style_context::start_table_cell_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_element_expected(parent, NS_odf_style, XML_style);
+
+ if (m_current_style->family != style_family_table_cell)
+ throw xml_structure_error("expected table_cell family style in cell_properties element");
+
+ if (!mp_styles)
+ return;
+
+ auto& data = std::get<odf_style::cell>(m_current_style->data);
+
+ std::optional<spreadsheet::color_rgb_t> bg_color;
+
+ std::optional<bool> locked;
+ std::optional<bool> hidden;
+ std::optional<bool> formula_hidden;
+ std::optional<bool> print_content;
+
+ bool cell_protection_set = false;
+
+ using border_map_type = std::map<ss::border_direction_t, odf::border_details_t>;
+ border_map_type border_styles;
+
+ ss::ver_alignment_t ver_alignment = ss::ver_alignment_t::unknown;
+ std::optional<bool> wrap_text;
+ std::optional<bool> shrink_to_fit;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_fo)
+ {
+ switch (attr.name)
+ {
+ case XML_background_color:
+ bg_color = odf::convert_fo_color(attr.value);
+ break;
+ case XML_border:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+
+ const ss::border_direction_t dirs[] =
+ {
+ ss::border_direction_t::top,
+ ss::border_direction_t::bottom,
+ ss::border_direction_t::left,
+ ss::border_direction_t::right
+ };
+
+ for (const auto dir : dirs)
+ border_styles.insert_or_assign(dir, border_details);
+
+ break;
+ }
+ case XML_border_top:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::top, border_details);
+ break;
+ }
+ case XML_border_bottom:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::bottom, border_details);
+ break;
+ }
+ case XML_border_left:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::left, border_details);
+ break;
+ }
+ case XML_border_right:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::right, border_details);
+ break;
+ }
+ case XML_diagonal_bl_tr:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::diagonal_bl_tr, border_details);
+ break;
+ }
+ case XML_diagonal_tl_br:
+ {
+ odf::border_details_t border_details = odf::extract_border_details(attr.value);
+ border_styles.insert_or_assign(ss::border_direction_t::diagonal_tl_br, border_details);
+ break;
+ }
+ case XML_wrap_option:
+ {
+ wrap_text = (attr.value == "wrap");
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_odf_style)
+ {
+ switch (attr.name)
+ {
+ case XML_print_content:
+ {
+ cell_protection_set = true;
+ print_content = to_bool(attr.value);
+ break;
+ }
+ case XML_cell_protect:
+ {
+ if (attr.value == "protected")
+ {
+ cell_protection_set = true;
+ locked = true;
+ }
+ else if (attr.value == "hidden-and-protected")
+ {
+ cell_protection_set = true;
+ locked = true;
+ hidden = true;
+ }
+ else if (attr.value == "formula-hidden")
+ {
+ cell_protection_set = true;
+ formula_hidden = true;
+ }
+ else if (attr.value == "protected formula-hidden" || attr.value == "formula-hidden protected")
+ {
+ cell_protection_set = true;
+ formula_hidden = true;
+ locked = true;
+ }
+ else if (attr.value == "none")
+ {
+ cell_protection_set = true;
+ locked = false;
+ hidden = false;
+ formula_hidden = false;
+ }
+ break;
+ }
+ case XML_vertical_align:
+ ver_alignment = odf::extract_ver_alignment_style(attr.value);
+ break;
+ case XML_shrink_to_fit:
+ shrink_to_fit = to_bool(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ std::size_t fill_id = 0;
+ std::size_t border_id = 0;
+ std::size_t cell_protection_id = 0;
+
+ if (bg_color)
+ {
+ auto* fill_style = mp_styles->start_fill_style();
+ ENSURE_INTERFACE(fill_style, import_fill_style);
+
+ fill_style->set_pattern_type(ss::fill_pattern_t::solid);
+ fill_style->set_fg_color(255, bg_color->red, bg_color->green, bg_color->blue);
+ fill_id = fill_style->commit();
+ }
+
+ if (!border_styles.empty())
+ {
+ auto* border_style = mp_styles->start_border_style();
+ ENSURE_INTERFACE(border_style, import_border_style);
+
+ for (const auto& [dir, details] : border_styles)
+ {
+ border_style->set_color(dir, 255, details.red, details.green, details.blue);
+ border_style->set_style(dir, details.border_style);
+ border_style->set_width(dir, details.border_width.value, details.border_width.unit);
+ }
+
+ border_id = border_style->commit();
+ }
+
+ if (cell_protection_set)
+ {
+ auto* cell_protection = mp_styles->start_cell_protection();
+ ENSURE_INTERFACE(cell_protection, import_cell_protection);
+
+ if (hidden)
+ cell_protection->set_hidden(*hidden);
+
+ if (locked)
+ cell_protection->set_locked(*locked);
+
+ if (print_content)
+ cell_protection->set_print_content(*print_content);
+
+ if (formula_hidden)
+ cell_protection->set_formula_hidden(*formula_hidden);
+
+ cell_protection_id = cell_protection->commit();
+ }
+
+ switch (m_current_style->family)
+ {
+ case style_family_table_cell:
+ {
+ data.fill = fill_id;
+ data.border = border_id;
+ data.protection = cell_protection_id;
+ data.ver_align = ver_alignment;
+ data.wrap_text = wrap_text;
+ data.shrink_to_fit = shrink_to_fit;
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_style_context.hpp b/src/liborcus/odf_style_context.hpp
new file mode 100644
index 0000000..4a33948
--- /dev/null
+++ b/src/liborcus/odf_style_context.hpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+#include "odf_styles.hpp"
+
+#include <memory>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+ class import_styles;
+}}
+
+/**
+ * Context for <style:style> element scope.
+ *
+ * This context populates one odf_style instance that represents a single set
+ * of style properties.
+ */
+class style_context : public xml_context_base
+{
+public:
+ style_context(session_context& session_cxt, const tokens& tk, spreadsheet::iface::import_styles* iface_styles);
+
+ void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+ void characters(std::string_view str, bool transient) override;
+ bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ void reset();
+ std::unique_ptr<odf_style> pop_style();
+
+private:
+ void start_paragraph_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_text_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_table_cell_properties(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+
+private:
+ spreadsheet::iface::import_styles* mp_styles = nullptr;
+ std::unique_ptr<odf_style> m_current_style;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_styles.cpp b/src/liborcus/odf_styles.cpp
new file mode 100644
index 0000000..814d468
--- /dev/null
+++ b/src/liborcus/odf_styles.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_styles.hpp"
+
+#include <stdexcept>
+
+namespace orcus {
+
+odf_style::odf_style() : family(style_family_unknown) {}
+odf_style::odf_style(std::string_view _name, std::string_view _display_name, odf_style_family _family, std::string_view parent) :
+ name(_name),
+ display_name(_display_name),
+ family(_family),
+ parent_name(parent)
+{
+ switch (family)
+ {
+ case style_family_table_column:
+ data = column{};
+ break;
+ case style_family_table_row:
+ data = row{};
+ break;
+ case style_family_table_cell:
+ data = cell{};
+ break;
+ case style_family_table:
+ data = table{};
+ break;
+ case style_family_graphic:
+ data = graphic{};
+ break;
+ case style_family_paragraph:
+ data = paragraph{};
+ break;
+ case style_family_text:
+ data = text{};
+ break;
+ case style_family_unknown:
+ throw std::invalid_argument("unkown style family is not allowed");
+ }
+}
+
+odf_style::~odf_style() {}
+
+odf_number_format::odf_number_format(std::string_view _name, bool _is_volatile):
+ name(_name),
+ is_volatile(_is_volatile)
+{
+}
+
+void merge(odf_styles_map_type& dst, odf_styles_map_type& src)
+{
+ for (auto& [name, style] : src)
+ dst.insert_or_assign(name, std::move(style));
+
+ src.clear();
+}
+
+void dump_state(const odf_styles_map_type& styles_map, std::ostream& os)
+{
+ os << "styles picked up:\n";
+
+ auto it = styles_map.begin(), it_end = styles_map.end();
+ for (; it != it_end; ++it)
+ {
+ os << " style: " << it->first << " [ ";
+
+ switch (it->second->family)
+ {
+ case style_family_table_column:
+ {
+ const auto& data = std::get<odf_style::column>(it->second->data);
+ os << "column width: " << data.width.to_string();
+ break;
+ }
+ case style_family_table_row:
+ {
+ const auto& data = std::get<odf_style::row>(it->second->data);
+ os << "row height: " << data.height.to_string();
+ break;
+ }
+ case style_family_table_cell:
+ {
+ const auto& cell = std::get<odf_style::cell>(it->second->data);
+ os << "xf ID: " << cell.xf;
+ break;
+ }
+ case style_family_text:
+ {
+ const auto& data = std::get<odf_style::text>(it->second->data);
+ os << "font ID: " << data.font;
+ break;
+ }
+ default:
+ ;
+ }
+
+ os << " ]\n";
+ }
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_styles.hpp b/src/liborcus/odf_styles.hpp
new file mode 100644
index 0000000..c4e5eaf
--- /dev/null
+++ b/src/liborcus/odf_styles.hpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_ODF_STYLES_HPP
+#define INCLUDED_ORCUS_ODF_STYLES_HPP
+
+#include <orcus/measurement.hpp>
+#include <orcus/spreadsheet/types.hpp>
+
+#include <map>
+#include <memory>
+#include <variant>
+#include <ostream>
+#include <optional>
+
+namespace orcus {
+
+enum odf_style_family
+{
+ style_family_unknown = 0,
+ style_family_table_column,
+ style_family_table_row,
+ style_family_table_cell,
+ style_family_table,
+ style_family_graphic,
+ style_family_paragraph,
+ style_family_text
+};
+
+/**
+ * Each instance of this class represents a single <style:style> entry.
+ */
+struct odf_style
+{
+ struct column
+ {
+ length_t width;
+ };
+
+ struct row
+ {
+ length_t height;
+ bool height_set = false;
+ };
+
+ struct cell
+ {
+ std::size_t font = 0;
+ std::size_t fill = 0;
+ std::size_t border = 0;
+ std::size_t protection = 0;
+ std::size_t xf = 0;
+ std::size_t number_format = 0;
+ spreadsheet::hor_alignment_t hor_align = spreadsheet::hor_alignment_t::unknown;
+ spreadsheet::ver_alignment_t ver_align = spreadsheet::ver_alignment_t::unknown;
+ std::optional<bool> wrap_text;
+ std::optional<bool> shrink_to_fit;
+ };
+
+ struct table
+ {
+ };
+
+ struct graphic
+ {
+ };
+
+ struct paragraph
+ {
+ spreadsheet::hor_alignment_t hor_align = spreadsheet::hor_alignment_t::unknown;
+ };
+
+ struct text
+ {
+ size_t font;
+ };
+
+ using data_type = std::variant<column, row, cell, table, graphic, paragraph, text>;
+
+ std::string_view name;
+ std::string_view display_name;
+ odf_style_family family;
+ std::string_view parent_name;
+
+ data_type data;
+
+ odf_style(const odf_style&) = delete;
+ odf_style& operator=(const odf_style&) = delete;
+
+ odf_style();
+ odf_style(std::string_view _name, std::string_view _display_name, odf_style_family _family, std::string_view parent);
+
+ ~odf_style();
+};
+
+struct odf_number_format
+{
+ std::string_view name;
+ std::string code;
+ bool is_volatile = false;
+
+ odf_number_format() = default;
+ odf_number_format(std::string_view _name, bool _is_volatile);
+};
+
+using odf_styles_map_type = std::map<std::string_view, std::unique_ptr<odf_style>>;
+
+/**
+ * Merge two styles collections into one.
+ *
+ * @param dst destination where all the styles will be stored when the call
+ * returns.
+ * @param src source collection to move all the styles from. After the call
+ * returns this one will be empty.
+ */
+void merge(odf_styles_map_type& dst, odf_styles_map_type& src);
+
+void dump_state(const odf_styles_map_type& styles_map, std::ostream& os);
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_styles_context.cpp b/src/liborcus/odf_styles_context.cpp
new file mode 100644
index 0000000..cf2589d
--- /dev/null
+++ b/src/liborcus/odf_styles_context.cpp
@@ -0,0 +1,403 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_styles_context.hpp"
+#include "odf_namespace_types.hpp"
+#include "odf_token_constants.hpp"
+#include "ods_session_data.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+#include <iostream>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+styles_context::styles_context(
+ session_context& session_cxt, const tokens& tk,
+ spreadsheet::iface::import_styles* iface_styles) :
+ xml_context_base(session_cxt, tk),
+ mp_styles(iface_styles),
+ m_automatic_styles(false),
+ m_cxt_style(session_cxt, tk, mp_styles),
+ m_cxt_number_style(session_cxt, tk),
+ m_cxt_currency_style(session_cxt, tk),
+ m_cxt_boolean_style(session_cxt, tk),
+ m_cxt_text_style(session_cxt, tk),
+ m_cxt_percentage_style(session_cxt, tk),
+ m_cxt_date_style(session_cxt, tk),
+ m_cxt_time_style(session_cxt, tk)
+{
+ register_child(&m_cxt_style);
+ register_child(&m_cxt_number_style);
+ register_child(&m_cxt_currency_style);
+ register_child(&m_cxt_boolean_style);
+ register_child(&m_cxt_text_style);
+ register_child(&m_cxt_percentage_style);
+ register_child(&m_cxt_date_style);
+ register_child(&m_cxt_time_style);
+
+ commit_default_styles();
+}
+
+xml_context_base* styles_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_number_style:
+ {
+ m_cxt_number_style.reset();
+ return &m_cxt_number_style;
+ }
+ case XML_currency_style:
+ {
+ m_cxt_currency_style.reset();
+ return &m_cxt_currency_style;
+ }
+ case XML_boolean_style:
+ {
+ m_cxt_boolean_style.reset();
+ return &m_cxt_boolean_style;
+ }
+ case XML_text_style:
+ {
+ m_cxt_text_style.reset();
+ return &m_cxt_text_style;
+ }
+ case XML_percentage_style:
+ {
+ m_cxt_percentage_style.reset();
+ return &m_cxt_percentage_style;
+ }
+ case XML_date_style:
+ {
+ m_cxt_date_style.reset();
+ return &m_cxt_date_style;
+ }
+ case XML_time_style:
+ {
+ m_cxt_time_style.reset();
+ return &m_cxt_time_style;
+ }
+ }
+ }
+
+ if (ns == NS_odf_style && name == XML_style)
+ {
+ m_cxt_style.reset();
+ return &m_cxt_style;
+ }
+
+ return nullptr;
+}
+
+void styles_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_odf_number)
+ {
+ switch (name)
+ {
+ case XML_number_style:
+ {
+ assert(child == &m_cxt_number_style);
+ push_number_style(m_cxt_number_style.pop_style());
+ break;
+ }
+ case XML_currency_style:
+ {
+ assert(child == &m_cxt_currency_style);
+ push_number_style(m_cxt_currency_style.pop_style());
+ break;
+ }
+ case XML_boolean_style:
+ {
+ assert(child == &m_cxt_boolean_style);
+ push_number_style(m_cxt_boolean_style.pop_style());
+ break;
+ }
+ case XML_text_style:
+ {
+ assert(child == &m_cxt_text_style);
+ push_number_style(m_cxt_text_style.pop_style());
+ break;
+ }
+ case XML_percentage_style:
+ {
+ assert(child == &m_cxt_percentage_style);
+ push_number_style(m_cxt_percentage_style.pop_style());
+ break;
+ }
+ case XML_date_style:
+ {
+ assert(child == &m_cxt_date_style);
+ push_number_style(m_cxt_date_style.pop_style());
+ break;
+ }
+ case XML_time_style:
+ {
+ assert(child == &m_cxt_time_style);
+ push_number_style(m_cxt_time_style.pop_style());
+ break;
+ }
+ default:;
+ }
+ }
+ else if (ns == NS_odf_style && name == XML_style)
+ {
+ assert(child == &m_cxt_style);
+ std::unique_ptr<odf_style> current_style = m_cxt_style.pop_style();
+
+ std::optional<std::size_t> parent_xfid = query_parent_style_xfid(current_style->parent_name);
+
+ if (mp_styles && current_style->family == style_family_table_cell)
+ {
+ auto& cell = std::get<odf_style::cell>(current_style->data);
+
+ if (m_automatic_styles)
+ {
+ // Import it into the direct cell style store
+ auto* xf = mp_styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(xf, import_xf);
+ xf->set_font(cell.font);
+ xf->set_fill(cell.fill);
+ xf->set_border(cell.border);
+ xf->set_protection(cell.protection);
+ xf->set_number_format(cell.number_format);
+
+ if (cell.hor_align != ss::hor_alignment_t::unknown)
+ xf->set_horizontal_alignment(cell.hor_align);
+ if (cell.ver_align != ss::ver_alignment_t::unknown)
+ xf->set_vertical_alignment(cell.ver_align);
+ if (cell.wrap_text)
+ xf->set_wrap_text(*cell.wrap_text);
+ if (cell.shrink_to_fit)
+ xf->set_shrink_to_fit(*cell.shrink_to_fit);
+
+ if (parent_xfid)
+ xf->set_style_xf(*parent_xfid);
+
+ cell.xf = xf->commit();
+ }
+ else
+ {
+ // Import it into the cell style xf store, and reference
+ // its index in the cell style name store.
+ auto* xf = mp_styles->start_xf(ss::xf_category_t::cell_style);
+ ENSURE_INTERFACE(xf, import_xf);
+ xf->set_font(cell.font);
+ xf->set_fill(cell.fill);
+ xf->set_border(cell.border);
+ xf->set_protection(cell.protection);
+ xf->set_number_format(cell.number_format);
+
+ if (cell.hor_align != ss::hor_alignment_t::unknown)
+ xf->set_horizontal_alignment(cell.hor_align);
+ if (cell.ver_align != ss::ver_alignment_t::unknown)
+ xf->set_vertical_alignment(cell.ver_align);
+ if (cell.wrap_text)
+ xf->set_wrap_text(*cell.wrap_text);
+ if (cell.shrink_to_fit)
+ xf->set_shrink_to_fit(*cell.shrink_to_fit);
+
+ if (parent_xfid)
+ xf->set_style_xf(*parent_xfid);
+
+ size_t style_xf_id = xf->commit();
+ cell.xf = style_xf_id;
+
+ auto* cell_style = mp_styles->start_cell_style();
+ ENSURE_INTERFACE(cell_style, import_cell_style);
+
+ if (!current_style->display_name.empty())
+ cell_style->set_display_name(current_style->display_name);
+
+ cell_style->set_name(current_style->name);
+ cell_style->set_xf(style_xf_id);
+ cell_style->set_parent_name(current_style->parent_name);
+ cell_style->commit();
+ }
+ }
+
+ std::string_view style_name = get_session_context().intern(current_style->name);
+ m_styles.emplace(style_name, std::move(current_style));
+ }
+}
+
+void styles_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& /*attrs*/)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_odf_office)
+ {
+ switch (name)
+ {
+ case XML_automatic_styles:
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ m_automatic_styles = true;
+ break;
+ case XML_styles:
+ m_automatic_styles = false;
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool styles_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void styles_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void styles_context::reset()
+{
+ m_styles.clear();
+}
+
+odf_styles_map_type styles_context::pop_styles()
+{
+ return std::move(m_styles);
+}
+
+void styles_context::commit_default_styles()
+{
+ if (!mp_styles)
+ return;
+
+ auto* font_style = mp_styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ auto* fill_style = mp_styles->start_fill_style();
+ ENSURE_INTERFACE(fill_style, import_fill_style);
+
+ auto* border_style = mp_styles->start_border_style();
+ ENSURE_INTERFACE(border_style, import_border_style);
+
+ auto* cell_protection = mp_styles->start_cell_protection();
+ ENSURE_INTERFACE(cell_protection, import_cell_protection);
+
+ auto* number_format = mp_styles->start_number_format();
+ ENSURE_INTERFACE(number_format, import_number_format);
+
+ // Set default styles. Default styles must be associated with an index of 0.
+ // Set empty styles for all style types before importing real styles.
+ font_style->commit();
+ fill_style->commit();
+ border_style->commit();
+ cell_protection->commit();
+ number_format->commit();
+
+ auto* xf = mp_styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(xf, import_xf);
+ xf->commit();
+
+ xf = mp_styles->start_xf(ss::xf_category_t::cell_style);
+ ENSURE_INTERFACE(xf, import_xf);
+ xf->commit();
+
+ auto* cell_style = mp_styles->start_cell_style();
+ ENSURE_INTERFACE(cell_style, import_cell_style);
+ cell_style->commit();
+}
+
+void styles_context::push_number_style(std::unique_ptr<odf_number_format> num_style)
+{
+ if (!mp_styles)
+ return;
+
+ if (num_style->name.empty())
+ {
+ warn("ignoring a number style with empty name.");
+ return;
+ }
+
+ if (num_style->code.empty())
+ {
+ std::ostringstream os;
+ os << "number style named '" << num_style->name << "' has empty code.";
+ warn(os.str());
+ return;
+ }
+
+ auto* number_format = mp_styles->start_number_format();
+ ENSURE_INTERFACE(number_format, import_number_format);
+
+ number_format->set_code(num_style->code);
+ std::size_t id = number_format->commit();
+
+ if (get_config().debug)
+ {
+ std::cerr << "number-style: name='" << num_style->name
+ << "'; code='" << num_style->code
+ << "'; id=" << id << std::endl;
+ }
+
+ auto& sess_cxt = get_session_context();
+ auto& numfmts_store = sess_cxt.get_data<ods_session_data>().number_formats;
+
+ if (auto res = numfmts_store.name2id_map.insert_or_assign(sess_cxt.intern(num_style->name), id); !res.second)
+ {
+ std::ostringstream os;
+ os << "number style named '" << num_style->name << "' has been overwritten.";
+ warn(os.str());
+ }
+
+ if (auto res = numfmts_store.id2code_map.insert_or_assign(id, std::move(num_style->code)); !res.second)
+ {
+ std::ostringstream os;
+ os << "number style associated with the id of " << id << " has been overwritten.";
+ warn(os.str());
+ }
+}
+
+std::optional<std::size_t> styles_context::query_parent_style_xfid(std::string_view parent_name) const
+{
+ std::optional<std::size_t> parent_xfid;
+
+ if (parent_name.empty())
+ return parent_xfid;
+
+ const ods_session_data& ods_data = get_session_context().get_data<ods_session_data>();
+
+ auto it = ods_data.styles_map.find(parent_name);
+ if (it == ods_data.styles_map.end())
+ {
+ // Not found in the session store. Check the current styles map too.
+ auto it2 = m_styles.find(parent_name);
+ if (it2 != m_styles.end())
+ {
+ const odf_style& s = *it2->second;
+ if (s.family == style_family_table_cell)
+ {
+ const odf_style::cell& c = std::get<odf_style::cell>(s.data);
+ parent_xfid = c.xf;
+ }
+ }
+ return parent_xfid;
+ }
+
+ const odf_style& s = *it->second;
+ if (s.family != style_family_table_cell)
+ return parent_xfid;
+
+ const odf_style::cell& c = std::get<odf_style::cell>(s.data);
+ parent_xfid = c.xf;
+
+ return parent_xfid;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_styles_context.hpp b/src/liborcus/odf_styles_context.hpp
new file mode 100644
index 0000000..01b2ac4
--- /dev/null
+++ b/src/liborcus/odf_styles_context.hpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_ODF_STYLES_CONTEXT_HPP
+#define ORCUS_ODF_STYLES_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "odf_styles.hpp"
+#include "odf_style_context.hpp"
+#include "odf_number_format_context.hpp"
+
+#include <unordered_map>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+ class import_styles;
+}}
+
+/**
+ * Context that handles <office:automatic-styles> or <office:styles> scope.
+ */
+class styles_context : public xml_context_base
+{
+public:
+ styles_context(
+ session_context& session_cxt, const tokens& tk, spreadsheet::iface::import_styles* iface_styles);
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset();
+ odf_styles_map_type pop_styles();
+
+private:
+ void commit_default_styles();
+
+ void push_number_style(std::unique_ptr<odf_number_format> num_style);
+
+ std::optional<std::size_t> query_parent_style_xfid(std::string_view parent_name) const;
+
+private:
+ spreadsheet::iface::import_styles* mp_styles;
+ odf_styles_map_type m_styles;
+
+ // an automatic style corresponds to a cell format and not a real style
+ bool m_automatic_styles;
+
+ style_context m_cxt_style;
+ number_style_context m_cxt_number_style;
+ currency_style_context m_cxt_currency_style;
+ boolean_style_context m_cxt_boolean_style;
+ text_style_context m_cxt_text_style;
+ percentage_style_context m_cxt_percentage_style;
+ date_style_context m_cxt_date_style;
+ time_style_context m_cxt_time_style;
+};
+
+} // namespace orcus
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_token_constants.hpp b/src/liborcus/odf_token_constants.hpp
new file mode 100644
index 0000000..71cf64b
--- /dev/null
+++ b/src/liborcus/odf_token_constants.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_ODF_TOKEN_CONSTANTS_HPP__
+#define __ORCUS_ODF_TOKEN_CONSTANTS_HPP__
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+#include "odf_token_constants.inl"
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_token_constants.inl b/src/liborcus/odf_token_constants.inl
new file mode 100644
index 0000000..868e465
--- /dev/null
+++ b/src/liborcus/odf_token_constants.inl
@@ -0,0 +1,2280 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const xml_token_t XML_0 = 1;
+const xml_token_t XML_0deg = 2;
+const xml_token_t XML_0grad = 3;
+const xml_token_t XML_0rad = 4;
+const xml_token_t XML_1 = 5;
+const xml_token_t XML_1_3 = 6;
+const xml_token_t XML_100 = 7;
+const xml_token_t XML_2 = 8;
+const xml_token_t XML_200 = 9;
+const xml_token_t XML_3 = 10;
+const xml_token_t XML_300 = 11;
+const xml_token_t XML_3d = 12;
+const xml_token_t XML_400 = 13;
+const xml_token_t XML_500 = 14;
+const xml_token_t XML_600 = 15;
+const xml_token_t XML_700 = 16;
+const xml_token_t XML_800 = 17;
+const xml_token_t XML_900 = 18;
+const xml_token_t XML_A = 19;
+const xml_token_t XML_I = 20;
+const xml_token_t XML_ROC = 21;
+const xml_token_t XML__blank = 22;
+const xml_token_t XML__parent = 23;
+const xml_token_t XML__self = 24;
+const xml_token_t XML__top = 25;
+const xml_token_t XML_a = 26;
+const xml_token_t XML_about = 27;
+const xml_token_t XML_above = 28;
+const xml_token_t XML_accelerate = 29;
+const xml_token_t XML_accent = 30;
+const xml_token_t XML_accent_height = 31;
+const xml_token_t XML_acceptance_state = 32;
+const xml_token_t XML_accepted = 33;
+const xml_token_t XML_accumulate = 34;
+const xml_token_t XML_action = 35;
+const xml_token_t XML_active = 36;
+const xml_token_t XML_actuate = 37;
+const xml_token_t XML_add_empty_lines = 38;
+const xml_token_t XML_additional_column_statement = 39;
+const xml_token_t XML_additive = 40;
+const xml_token_t XML_address = 41;
+const xml_token_t XML_adjustment = 42;
+const xml_token_t XML_after_previous = 43;
+const xml_token_t XML_algorithm = 44;
+const xml_token_t XML_align = 45;
+const xml_token_t XML_all = 46;
+const xml_token_t XML_allow_deletes = 47;
+const xml_token_t XML_allow_empty_cell = 48;
+const xml_token_t XML_allow_inserts = 49;
+const xml_token_t XML_allow_updates = 50;
+const xml_token_t XML_alpha_numeric = 51;
+const xml_token_t XML_alphabetic = 52;
+const xml_token_t XML_alphabetical_index = 53;
+const xml_token_t XML_alphabetical_index_auto_mark_file = 54;
+const xml_token_t XML_alphabetical_index_entry_template = 55;
+const xml_token_t XML_alphabetical_index_mark = 56;
+const xml_token_t XML_alphabetical_index_mark_end = 57;
+const xml_token_t XML_alphabetical_index_mark_start = 58;
+const xml_token_t XML_alphabetical_index_source = 59;
+const xml_token_t XML_alphabetical_separators = 60;
+const xml_token_t XML_alternate = 61;
+const xml_token_t XML_always = 62;
+const xml_token_t XML_am_pm = 63;
+const xml_token_t XML_ambient_color = 64;
+const xml_token_t XML_anchor_page_number = 65;
+const xml_token_t XML_anchor_type = 66;
+const xml_token_t XML_angle = 67;
+const xml_token_t XML_angle_offset = 68;
+const xml_token_t XML_angled_connector_line = 69;
+const xml_token_t XML_angled_line = 70;
+const xml_token_t XML_anim = 71;
+const xml_token_t XML_animate = 72;
+const xml_token_t XML_animateColor = 73;
+const xml_token_t XML_animateMotion = 74;
+const xml_token_t XML_animateTransform = 75;
+const xml_token_t XML_animation = 76;
+const xml_token_t XML_animation_delay = 77;
+const xml_token_t XML_animation_direction = 78;
+const xml_token_t XML_animation_group = 79;
+const xml_token_t XML_animation_repeat = 80;
+const xml_token_t XML_animation_start_inside = 81;
+const xml_token_t XML_animation_steps = 82;
+const xml_token_t XML_animation_stop_inside = 83;
+const xml_token_t XML_animations = 84;
+const xml_token_t XML_annotation = 85;
+const xml_token_t XML_annotation_end = 86;
+const xml_token_t XML_annotations = 87;
+const xml_token_t XML_annote = 88;
+const xml_token_t XML_appear = 89;
+const xml_token_t XML_append_table_alias_name = 90;
+const xml_token_t XML_applet = 91;
+const xml_token_t XML_application_connection_settings = 92;
+const xml_token_t XML_application_data = 93;
+const xml_token_t XML_apply_command = 94;
+const xml_token_t XML_apply_design_mode = 95;
+const xml_token_t XML_apply_filter = 96;
+const xml_token_t XML_apply_style_name = 97;
+const xml_token_t XML_arc = 98;
+const xml_token_t XML_archive = 99;
+const xml_token_t XML_area = 100;
+const xml_token_t XML_area_circle = 101;
+const xml_token_t XML_area_polygon = 102;
+const xml_token_t XML_area_rectangle = 103;
+const xml_token_t XML_array = 104;
+const xml_token_t XML_arrow_down = 105;
+const xml_token_t XML_arrow_left = 106;
+const xml_token_t XML_arrow_right = 107;
+const xml_token_t XML_arrow_up = 108;
+const xml_token_t XML_article = 109;
+const xml_token_t XML_as_char = 110;
+const xml_token_t XML_as_template = 111;
+const xml_token_t XML_ascending = 112;
+const xml_token_t XML_ascent = 113;
+const xml_token_t XML_asian = 114;
+const xml_token_t XML_asterisk = 115;
+const xml_token_t XML_at_axis = 116;
+const xml_token_t XML_at_labels = 117;
+const xml_token_t XML_at_labels_and_axis = 118;
+const xml_token_t XML_attached_axis = 119;
+const xml_token_t XML_attractive = 120;
+const xml_token_t XML_attributeName = 121;
+const xml_token_t XML_audio = 122;
+const xml_token_t XML_audio_level = 123;
+const xml_token_t XML_author = 124;
+const xml_token_t XML_author_initials = 125;
+const xml_token_t XML_author_name = 126;
+const xml_token_t XML_auto = 127;
+const xml_token_t XML_auto_complete = 128;
+const xml_token_t XML_auto_create_new_frame = 129;
+const xml_token_t XML_auto_grow_height = 130;
+const xml_token_t XML_auto_grow_width = 131;
+const xml_token_t XML_auto_increment = 132;
+const xml_token_t XML_auto_position = 133;
+const xml_token_t XML_auto_reload = 134;
+const xml_token_t XML_auto_size = 135;
+const xml_token_t XML_auto_text_indent = 136;
+const xml_token_t XML_auto_update = 137;
+const xml_token_t XML_autoReverse = 138;
+const xml_token_t XML_automatic = 139;
+const xml_token_t XML_automatic_content = 140;
+const xml_token_t XML_automatic_find_labels = 141;
+const xml_token_t XML_automatic_focus = 142;
+const xml_token_t XML_automatic_order = 143;
+const xml_token_t XML_automatic_styles = 144;
+const xml_token_t XML_automatic_update = 145;
+const xml_token_t XML_average = 146;
+const xml_token_t XML_averaged_abscissa = 147;
+const xml_token_t XML_avoid_overlap = 148;
+const xml_token_t XML_axial = 149;
+const xml_token_t XML_axis = 150;
+const xml_token_t XML_axis_label_position = 151;
+const xml_token_t XML_axis_position = 152;
+const xml_token_t XML_b_spline = 153;
+const xml_token_t XML_back_scale = 154;
+const xml_token_t XML_backface_culling = 155;
+const xml_token_t XML_background = 156;
+const xml_token_t XML_background_color = 157;
+const xml_token_t XML_background_image = 158;
+const xml_token_t XML_background_objects_visible = 159;
+const xml_token_t XML_background_size = 160;
+const xml_token_t XML_background_transparency = 161;
+const xml_token_t XML_background_visible = 162;
+const xml_token_t XML_balanced = 163;
+const xml_token_t XML_base_cell_address = 164;
+const xml_token_t XML_base_dn = 165;
+const xml_token_t XML_base64Binary = 166;
+const xml_token_t XML_baseline = 167;
+const xml_token_t XML_bbox = 168;
+const xml_token_t XML_begin = 169;
+const xml_token_t XML_below = 170;
+const xml_token_t XML_bevel = 171;
+const xml_token_t XML_bibliography = 172;
+const xml_token_t XML_bibliography_configuration = 173;
+const xml_token_t XML_bibliography_data_field = 174;
+const xml_token_t XML_bibliography_entry_template = 175;
+const xml_token_t XML_bibliography_mark = 176;
+const xml_token_t XML_bibliography_source = 177;
+const xml_token_t XML_bibliography_type = 178;
+const xml_token_t XML_biggest = 179;
+const xml_token_t XML_bigint = 180;
+const xml_token_t XML_binary = 181;
+const xml_token_t XML_binary_data = 182;
+const xml_token_t XML_bind = 183;
+const xml_token_t XML_bind_styles_to_content = 184;
+const xml_token_t XML_bit = 185;
+const xml_token_t XML_bitmap = 186;
+const xml_token_t XML_blend = 187;
+const xml_token_t XML_blob = 188;
+const xml_token_t XML_blue = 189;
+const xml_token_t XML_body = 190;
+const xml_token_t XML_bold = 191;
+const xml_token_t XML_book = 192;
+const xml_token_t XML_booklet = 193;
+const xml_token_t XML_bookmark = 194;
+const xml_token_t XML_bookmark_end = 195;
+const xml_token_t XML_bookmark_start = 196;
+const xml_token_t XML_booktitle = 197;
+const xml_token_t XML_boolean = 198;
+const xml_token_t XML_boolean_comparison_mode = 199;
+const xml_token_t XML_boolean_style = 200;
+const xml_token_t XML_boolean_value = 201;
+const xml_token_t XML_border = 202;
+const xml_token_t XML_border_bottom = 203;
+const xml_token_t XML_border_color = 204;
+const xml_token_t XML_border_left = 205;
+const xml_token_t XML_border_line_width = 206;
+const xml_token_t XML_border_line_width_bottom = 207;
+const xml_token_t XML_border_line_width_left = 208;
+const xml_token_t XML_border_line_width_right = 209;
+const xml_token_t XML_border_line_width_top = 210;
+const xml_token_t XML_border_model = 211;
+const xml_token_t XML_border_right = 212;
+const xml_token_t XML_border_top = 213;
+const xml_token_t XML_both = 214;
+const xml_token_t XML_bottom = 215;
+const xml_token_t XML_bottom_end = 216;
+const xml_token_t XML_bottom_left = 217;
+const xml_token_t XML_bottom_right = 218;
+const xml_token_t XML_bottom_start = 219;
+const xml_token_t XML_bound_column = 220;
+const xml_token_t XML_bow_tie = 221;
+const xml_token_t XML_break_after = 222;
+const xml_token_t XML_break_before = 223;
+const xml_token_t XML_buddhist = 224;
+const xml_token_t XML_bullet_char = 225;
+const xml_token_t XML_bullet_relative_size = 226;
+const xml_token_t XML_butt = 227;
+const xml_token_t XML_button = 228;
+const xml_token_t XML_button_type = 229;
+const xml_token_t XML_buttons = 230;
+const xml_token_t XML_by = 231;
+const xml_token_t XML_c = 232;
+const xml_token_t XML_calcMode = 233;
+const xml_token_t XML_calculation_settings = 234;
+const xml_token_t XML_calendar = 235;
+const xml_token_t XML_cap_height = 236;
+const xml_token_t XML_capitalize = 237;
+const xml_token_t XML_capitalize_entries = 238;
+const xml_token_t XML_caption = 239;
+const xml_token_t XML_caption_angle = 240;
+const xml_token_t XML_caption_angle_type = 241;
+const xml_token_t XML_caption_escape = 242;
+const xml_token_t XML_caption_escape_direction = 243;
+const xml_token_t XML_caption_fit_line_length = 244;
+const xml_token_t XML_caption_gap = 245;
+const xml_token_t XML_caption_id = 246;
+const xml_token_t XML_caption_line_length = 247;
+const xml_token_t XML_caption_point_x = 248;
+const xml_token_t XML_caption_point_y = 249;
+const xml_token_t XML_caption_sequence_format = 250;
+const xml_token_t XML_caption_sequence_name = 251;
+const xml_token_t XML_caption_type = 252;
+const xml_token_t XML_cascade = 253;
+const xml_token_t XML_case_sensitive = 254;
+const xml_token_t XML_catalog_name = 255;
+const xml_token_t XML_categories = 256;
+const xml_token_t XML_category_and_value = 257;
+const xml_token_t XML_cell_address = 258;
+const xml_token_t XML_cell_content_change = 259;
+const xml_token_t XML_cell_content_deletion = 260;
+const xml_token_t XML_cell_count = 261;
+const xml_token_t XML_cell_protect = 262;
+const xml_token_t XML_cell_range = 263;
+const xml_token_t XML_cell_range_address = 264;
+const xml_token_t XML_cell_range_source = 265;
+const xml_token_t XML_center = 266;
+const xml_token_t XML_central = 267;
+const xml_token_t XML_chain_next_name = 268;
+const xml_token_t XML_change = 269;
+const xml_token_t XML_change_deletion = 270;
+const xml_token_t XML_change_end = 271;
+const xml_token_t XML_change_id = 272;
+const xml_token_t XML_change_info = 273;
+const xml_token_t XML_change_start = 274;
+const xml_token_t XML_change_track_table_cell = 275;
+const xml_token_t XML_changed_region = 276;
+const xml_token_t XML_chapter = 277;
+const xml_token_t XML_char = 278;
+const xml_token_t XML_character_count = 279;
+const xml_token_t XML_character_set = 280;
+const xml_token_t XML_chart = 281;
+const xml_token_t XML_chart_properties = 282;
+const xml_token_t XML_charts = 283;
+const xml_token_t XML_checkbox = 284;
+const xml_token_t XML_checked = 285;
+const xml_token_t XML_checkerboard = 286;
+const xml_token_t XML_circle = 287;
+const xml_token_t XML_citation_body_style_name = 288;
+const xml_token_t XML_citation_style_name = 289;
+const xml_token_t XML_class = 290;
+const xml_token_t XML_class_id = 291;
+const xml_token_t XML_class_names = 292;
+const xml_token_t XML_clip = 293;
+const xml_token_t XML_clob = 294;
+const xml_token_t XML_clockwise = 295;
+const xml_token_t XML_close = 296;
+const xml_token_t XML_close_back = 297;
+const xml_token_t XML_close_front = 298;
+const xml_token_t XML_close_horizontal = 299;
+const xml_token_t XML_close_vertical = 300;
+const xml_token_t XML_cm = 301;
+const xml_token_t XML_code = 302;
+const xml_token_t XML_collapse = 303;
+const xml_token_t XML_collapsing = 304;
+const xml_token_t XML_color = 305;
+const xml_token_t XML_color_interpolation = 306;
+const xml_token_t XML_color_interpolation_direction = 307;
+const xml_token_t XML_color_inversion = 308;
+const xml_token_t XML_color_mode = 309;
+const xml_token_t XML_column = 310;
+const xml_token_t XML_column_count = 311;
+const xml_token_t XML_column_definition = 312;
+const xml_token_t XML_column_definitions = 313;
+const xml_token_t XML_column_gap = 314;
+const xml_token_t XML_column_mapping = 315;
+const xml_token_t XML_column_name = 316;
+const xml_token_t XML_column_percentage = 317;
+const xml_token_t XML_column_sep = 318;
+const xml_token_t XML_column_width = 319;
+const xml_token_t XML_columns = 320;
+const xml_token_t XML_combine_entries = 321;
+const xml_token_t XML_combine_entries_with_dash = 322;
+const xml_token_t XML_combine_entries_with_pp = 323;
+const xml_token_t XML_combobox = 324;
+const xml_token_t XML_comma_separated = 325;
+const xml_token_t XML_command = 326;
+const xml_token_t XML_command_type = 327;
+const xml_token_t XML_comment = 328;
+const xml_token_t XML_complex = 329;
+const xml_token_t XML_component = 330;
+const xml_token_t XML_component_collection = 331;
+const xml_token_t XML_concave = 332;
+const xml_token_t XML_concentric_gradient_fill_allowed = 333;
+const xml_token_t XML_cond_style_name = 334;
+const xml_token_t XML_condensed = 335;
+const xml_token_t XML_condition = 336;
+const xml_token_t XML_condition_source = 337;
+const xml_token_t XML_condition_source_range_address = 338;
+const xml_token_t XML_conditional_text = 339;
+const xml_token_t XML_cone = 340;
+const xml_token_t XML_conference = 341;
+const xml_token_t XML_config = 342;
+const xml_token_t XML_config_item = 343;
+const xml_token_t XML_config_item_map_entry = 344;
+const xml_token_t XML_config_item_map_indexed = 345;
+const xml_token_t XML_config_item_map_named = 346;
+const xml_token_t XML_config_item_set = 347;
+const xml_token_t XML_connect_bars = 348;
+const xml_token_t XML_connection_data = 349;
+const xml_token_t XML_connection_name = 350;
+const xml_token_t XML_connection_resource = 351;
+const xml_token_t XML_connector = 352;
+const xml_token_t XML_consecutive_numbering = 353;
+const xml_token_t XML_consolidation = 354;
+const xml_token_t XML_constant = 355;
+const xml_token_t XML_contains_error = 356;
+const xml_token_t XML_contains_header = 357;
+const xml_token_t XML_content = 358;
+const xml_token_t XML_content_validation = 359;
+const xml_token_t XML_content_validation_name = 360;
+const xml_token_t XML_content_validations = 361;
+const xml_token_t XML_contextual_spacing = 362;
+const xml_token_t XML_continue = 363;
+const xml_token_t XML_continue_list = 364;
+const xml_token_t XML_continue_numbering = 365;
+const xml_token_t XML_continuous = 366;
+const xml_token_t XML_contour_path = 367;
+const xml_token_t XML_contour_polygon = 368;
+const xml_token_t XML_contrast = 369;
+const xml_token_t XML_control = 370;
+const xml_token_t XML_control_implementation = 371;
+const xml_token_t XML_conversion_mode = 372;
+const xml_token_t XML_convert_empty_to_null = 373;
+const xml_token_t XML_coordinate_region = 374;
+const xml_token_t XML_copy_all = 375;
+const xml_token_t XML_copy_back = 376;
+const xml_token_t XML_copy_formulas = 377;
+const xml_token_t XML_copy_of = 378;
+const xml_token_t XML_copy_outline_levels = 379;
+const xml_token_t XML_copy_results_only = 380;
+const xml_token_t XML_copy_styles = 381;
+const xml_token_t XML_corner_radius = 382;
+const xml_token_t XML_corners = 383;
+const xml_token_t XML_correct = 384;
+const xml_token_t XML_count = 385;
+const xml_token_t XML_count_empty_lines = 386;
+const xml_token_t XML_count_in_text_boxes = 387;
+const xml_token_t XML_counter_clockwise = 388;
+const xml_token_t XML_counterclockwise = 389;
+const xml_token_t XML_countnums = 390;
+const xml_token_t XML_country = 391;
+const xml_token_t XML_country_asian = 392;
+const xml_token_t XML_country_complex = 393;
+const xml_token_t XML_covered_table_cell = 394;
+const xml_token_t XML_creation_date = 395;
+const xml_token_t XML_creation_time = 396;
+const xml_token_t XML_creator = 397;
+const xml_token_t XML_creator_initials = 398;
+const xml_token_t XML_cube = 399;
+const xml_token_t XML_cubic_spline = 400;
+const xml_token_t XML_cuboid = 401;
+const xml_token_t XML_currency = 402;
+const xml_token_t XML_currency_style = 403;
+const xml_token_t XML_currency_symbol = 404;
+const xml_token_t XML_current = 405;
+const xml_token_t XML_current_date = 406;
+const xml_token_t XML_current_selected = 407;
+const xml_token_t XML_current_state = 408;
+const xml_token_t XML_current_value = 409;
+const xml_token_t XML_curve = 410;
+const xml_token_t XML_custom = 411;
+const xml_token_t XML_custom_shape = 412;
+const xml_token_t XML_custom1 = 413;
+const xml_token_t XML_custom2 = 414;
+const xml_token_t XML_custom3 = 415;
+const xml_token_t XML_custom4 = 416;
+const xml_token_t XML_custom5 = 417;
+const xml_token_t XML_cut = 418;
+const xml_token_t XML_cut_offs = 419;
+const xml_token_t XML_cx = 420;
+const xml_token_t XML_cy = 421;
+const xml_token_t XML_cylinder = 422;
+const xml_token_t XML_d = 423;
+const xml_token_t XML_dash = 424;
+const xml_token_t XML_dashed = 425;
+const xml_token_t XML_data = 426;
+const xml_token_t XML_data_cell_range_address = 427;
+const xml_token_t XML_data_field = 428;
+const xml_token_t XML_data_label = 429;
+const xml_token_t XML_data_label_number = 430;
+const xml_token_t XML_data_label_series = 431;
+const xml_token_t XML_data_label_symbol = 432;
+const xml_token_t XML_data_label_text = 433;
+const xml_token_t XML_data_pilot_display_info = 434;
+const xml_token_t XML_data_pilot_field = 435;
+const xml_token_t XML_data_pilot_field_reference = 436;
+const xml_token_t XML_data_pilot_group = 437;
+const xml_token_t XML_data_pilot_group_member = 438;
+const xml_token_t XML_data_pilot_groups = 439;
+const xml_token_t XML_data_pilot_layout_info = 440;
+const xml_token_t XML_data_pilot_level = 441;
+const xml_token_t XML_data_pilot_member = 442;
+const xml_token_t XML_data_pilot_members = 443;
+const xml_token_t XML_data_pilot_sort_info = 444;
+const xml_token_t XML_data_pilot_subtotal = 445;
+const xml_token_t XML_data_pilot_subtotals = 446;
+const xml_token_t XML_data_pilot_table = 447;
+const xml_token_t XML_data_pilot_tables = 448;
+const xml_token_t XML_data_point = 449;
+const xml_token_t XML_data_source = 450;
+const xml_token_t XML_data_source_has_labels = 451;
+const xml_token_t XML_data_source_setting = 452;
+const xml_token_t XML_data_source_setting_is_list = 453;
+const xml_token_t XML_data_source_setting_name = 454;
+const xml_token_t XML_data_source_setting_type = 455;
+const xml_token_t XML_data_source_setting_value = 456;
+const xml_token_t XML_data_source_settings = 457;
+const xml_token_t XML_data_style_name = 458;
+const xml_token_t XML_data_type = 459;
+const xml_token_t XML_database = 460;
+const xml_token_t XML_database_description = 461;
+const xml_token_t XML_database_display = 462;
+const xml_token_t XML_database_name = 463;
+const xml_token_t XML_database_next = 464;
+const xml_token_t XML_database_range = 465;
+const xml_token_t XML_database_ranges = 466;
+const xml_token_t XML_database_row_number = 467;
+const xml_token_t XML_database_row_select = 468;
+const xml_token_t XML_database_source_query = 469;
+const xml_token_t XML_database_source_sql = 470;
+const xml_token_t XML_database_source_table = 471;
+const xml_token_t XML_database_table_name = 472;
+const xml_token_t XML_datasource = 473;
+const xml_token_t XML_datatype = 474;
+const xml_token_t XML_date = 475;
+const xml_token_t XML_date_adjust = 476;
+const xml_token_t XML_date_end = 477;
+const xml_token_t XML_date_start = 478;
+const xml_token_t XML_date_string = 479;
+const xml_token_t XML_date_style = 480;
+const xml_token_t XML_date_time = 481;
+const xml_token_t XML_date_time_decl = 482;
+const xml_token_t XML_date_value = 483;
+const xml_token_t XML_datetime = 484;
+const xml_token_t XML_day = 485;
+const xml_token_t XML_day_of_week = 486;
+const xml_token_t XML_days = 487;
+const xml_token_t XML_db = 488;
+const xml_token_t XML_dc = 489;
+const xml_token_t XML_dde_application = 490;
+const xml_token_t XML_dde_connection = 491;
+const xml_token_t XML_dde_connection_decl = 492;
+const xml_token_t XML_dde_connection_decls = 493;
+const xml_token_t XML_dde_item = 494;
+const xml_token_t XML_dde_link = 495;
+const xml_token_t XML_dde_links = 496;
+const xml_token_t XML_dde_source = 497;
+const xml_token_t XML_dde_topic = 498;
+const xml_token_t XML_decelerate = 499;
+const xml_token_t XML_decimal = 500;
+const xml_token_t XML_decimal_places = 501;
+const xml_token_t XML_decimal_replacement = 502;
+const xml_token_t XML_decorative = 503;
+const xml_token_t XML_deep = 504;
+const xml_token_t XML_default = 505;
+const xml_token_t XML_default_button = 506;
+const xml_token_t XML_default_cell_style_name = 507;
+const xml_token_t XML_default_outline_level = 508;
+const xml_token_t XML_default_page_layout = 509;
+const xml_token_t XML_default_row_style_name = 510;
+const xml_token_t XML_default_style = 511;
+const xml_token_t XML_default_style_name = 512;
+const xml_token_t XML_definition_src = 513;
+const xml_token_t XML_delay = 514;
+const xml_token_t XML_delay_for_repeat = 515;
+const xml_token_t XML_delete_rule = 516;
+const xml_token_t XML_deletion = 517;
+const xml_token_t XML_deletions = 518;
+const xml_token_t XML_delimiter = 519;
+const xml_token_t XML_denominator_value = 520;
+const xml_token_t XML_dependencies = 521;
+const xml_token_t XML_dependency = 522;
+const xml_token_t XML_depth = 523;
+const xml_token_t XML_desc = 524;
+const xml_token_t XML_descending = 525;
+const xml_token_t XML_descent = 526;
+const xml_token_t XML_description = 527;
+const xml_token_t XML_detail_fields = 528;
+const xml_token_t XML_detective = 529;
+const xml_token_t XML_diagonal_bl_tr = 530;
+const xml_token_t XML_diagonal_bl_tr_widths = 531;
+const xml_token_t XML_diagonal_tl_br = 532;
+const xml_token_t XML_diagonal_tl_br_widths = 533;
+const xml_token_t XML_diamond = 534;
+const xml_token_t XML_diffuse_color = 535;
+const xml_token_t XML_dim = 536;
+const xml_token_t XML_dimension = 537;
+const xml_token_t XML_direction = 538;
+const xml_token_t XML_disable = 539;
+const xml_token_t XML_disabled = 540;
+const xml_token_t XML_disc = 541;
+const xml_token_t XML_discrete = 542;
+const xml_token_t XML_display = 543;
+const xml_token_t XML_display_border = 544;
+const xml_token_t XML_display_date_time = 545;
+const xml_token_t XML_display_duplicates = 546;
+const xml_token_t XML_display_equation = 547;
+const xml_token_t XML_display_factor = 548;
+const xml_token_t XML_display_filter_buttons = 549;
+const xml_token_t XML_display_footer = 550;
+const xml_token_t XML_display_header = 551;
+const xml_token_t XML_display_label = 552;
+const xml_token_t XML_display_levels = 553;
+const xml_token_t XML_display_list = 554;
+const xml_token_t XML_display_member_mode = 555;
+const xml_token_t XML_display_name = 556;
+const xml_token_t XML_display_outline_level = 557;
+const xml_token_t XML_display_page_number = 558;
+const xml_token_t XML_display_r_square = 559;
+const xml_token_t XML_dissolve = 560;
+const xml_token_t XML_distance = 561;
+const xml_token_t XML_distance_after_sep = 562;
+const xml_token_t XML_distance_before_sep = 563;
+const xml_token_t XML_distinct = 564;
+const xml_token_t XML_distribute_letter = 565;
+const xml_token_t XML_distribute_space = 566;
+const xml_token_t XML_document = 567;
+const xml_token_t XML_document_content = 568;
+const xml_token_t XML_document_meta = 569;
+const xml_token_t XML_document_settings = 570;
+const xml_token_t XML_document_statistic = 571;
+const xml_token_t XML_document_styles = 572;
+const xml_token_t XML_domain = 573;
+const xml_token_t XML_dont_balance_text_columns = 574;
+const xml_token_t XML_dot = 575;
+const xml_token_t XML_dot_dash = 576;
+const xml_token_t XML_dot_dashed = 577;
+const xml_token_t XML_dot_dot_dash = 578;
+const xml_token_t XML_dots1 = 579;
+const xml_token_t XML_dots1_length = 580;
+const xml_token_t XML_dots2 = 581;
+const xml_token_t XML_dots2_length = 582;
+const xml_token_t XML_dotted = 583;
+const xml_token_t XML_double = 584;
+const xml_token_t XML_double_sided = 585;
+const xml_token_t XML_down = 586;
+const xml_token_t XML_dr3d = 587;
+const xml_token_t XML_draft = 588;
+const xml_token_t XML_draw = 589;
+const xml_token_t XML_draw_aspect = 590;
+const xml_token_t XML_draw_count = 591;
+const xml_token_t XML_drawing = 592;
+const xml_token_t XML_drawing_page = 593;
+const xml_token_t XML_drawing_page_properties = 594;
+const xml_token_t XML_drawings = 595;
+const xml_token_t XML_drill_down_on_double_click = 596;
+const xml_token_t XML_driver_settings = 597;
+const xml_token_t XML_drop_cap = 598;
+const xml_token_t XML_drop_down = 599;
+const xml_token_t XML_dropdown = 600;
+const xml_token_t XML_dur = 601;
+const xml_token_t XML_duration = 602;
+const xml_token_t XML_dynamic = 603;
+const xml_token_t XML_dynamic_spacing = 604;
+const xml_token_t XML_echo_char = 605;
+const xml_token_t XML_edge_rounding = 606;
+const xml_token_t XML_edge_rounding_mode = 607;
+const xml_token_t XML_editable = 608;
+const xml_token_t XML_editing_cycles = 609;
+const xml_token_t XML_editing_duration = 610;
+const xml_token_t XML_edition = 611;
+const xml_token_t XML_editor = 612;
+const xml_token_t XML_effect = 613;
+const xml_token_t XML_ellipse = 614;
+const xml_token_t XML_ellipsoid = 615;
+const xml_token_t XML_email = 616;
+const xml_token_t XML_embed = 617;
+const xml_token_t XML_embedded_number_behavior = 618;
+const xml_token_t XML_embedded_text = 619;
+const xml_token_t XML_embossed = 620;
+const xml_token_t XML_emissive_color = 621;
+const xml_token_t XML_emphasis = 622;
+const xml_token_t XML_enable = 623;
+const xml_token_t XML_enable_sql92_check = 624;
+const xml_token_t XML_enabled = 625;
+const xml_token_t XML_encoding = 626;
+const xml_token_t XML_enctype = 627;
+const xml_token_t XML_end = 628;
+const xml_token_t XML_end_angle = 629;
+const xml_token_t XML_end_cell_address = 630;
+const xml_token_t XML_end_color = 631;
+const xml_token_t XML_end_column = 632;
+const xml_token_t XML_end_glue_point = 633;
+const xml_token_t XML_end_guide = 634;
+const xml_token_t XML_end_indent = 635;
+const xml_token_t XML_end_intensity = 636;
+const xml_token_t XML_end_line_spacing_horizontal = 637;
+const xml_token_t XML_end_line_spacing_vertical = 638;
+const xml_token_t XML_end_position = 639;
+const xml_token_t XML_end_row = 640;
+const xml_token_t XML_end_shape = 641;
+const xml_token_t XML_end_table = 642;
+const xml_token_t XML_end_x = 643;
+const xml_token_t XML_end_y = 644;
+const xml_token_t XML_endless = 645;
+const xml_token_t XML_endnote = 646;
+const xml_token_t XML_endsync = 647;
+const xml_token_t XML_engine = 648;
+const xml_token_t XML_engraved = 649;
+const xml_token_t XML_enhanced_geometry = 650;
+const xml_token_t XML_enhanced_path = 651;
+const xml_token_t XML_entrance = 652;
+const xml_token_t XML_equal_boolean = 653;
+const xml_token_t XML_equal_integer = 654;
+const xml_token_t XML_equal_use_only_zero = 655;
+const xml_token_t XML_equation = 656;
+const xml_token_t XML_era = 657;
+const xml_token_t XML_error_category = 658;
+const xml_token_t XML_error_indicator = 659;
+const xml_token_t XML_error_lower_indicator = 660;
+const xml_token_t XML_error_lower_limit = 661;
+const xml_token_t XML_error_lower_range = 662;
+const xml_token_t XML_error_macro = 663;
+const xml_token_t XML_error_margin = 664;
+const xml_token_t XML_error_message = 665;
+const xml_token_t XML_error_percentage = 666;
+const xml_token_t XML_error_upper_indicator = 667;
+const xml_token_t XML_error_upper_limit = 668;
+const xml_token_t XML_error_upper_range = 669;
+const xml_token_t XML_escape_direction = 670;
+const xml_token_t XML_escape_processing = 671;
+const xml_token_t XML_even_columns = 672;
+const xml_token_t XML_even_rows = 673;
+const xml_token_t XML_evenodd = 674;
+const xml_token_t XML_event_listener = 675;
+const xml_token_t XML_event_listeners = 676;
+const xml_token_t XML_event_name = 677;
+const xml_token_t XML_execute = 678;
+const xml_token_t XML_execute_macro = 679;
+const xml_token_t XML_exit = 680;
+const xml_token_t XML_expanded = 681;
+const xml_token_t XML_exponent_interval = 682;
+const xml_token_t XML_exponential = 683;
+const xml_token_t XML_expression = 684;
+const xml_token_t XML_extension = 685;
+const xml_token_t XML_extra_condensed = 686;
+const xml_token_t XML_extra_expanded = 687;
+const xml_token_t XML_extrude = 688;
+const xml_token_t XML_extrusion = 689;
+const xml_token_t XML_extrusion_allowed = 690;
+const xml_token_t XML_extrusion_brightness = 691;
+const xml_token_t XML_extrusion_color = 692;
+const xml_token_t XML_extrusion_depth = 693;
+const xml_token_t XML_extrusion_diffusion = 694;
+const xml_token_t XML_extrusion_first_light_direction = 695;
+const xml_token_t XML_extrusion_first_light_harsh = 696;
+const xml_token_t XML_extrusion_first_light_level = 697;
+const xml_token_t XML_extrusion_light_face = 698;
+const xml_token_t XML_extrusion_metal = 699;
+const xml_token_t XML_extrusion_number_of_line_segments = 700;
+const xml_token_t XML_extrusion_origin = 701;
+const xml_token_t XML_extrusion_rotation_angle = 702;
+const xml_token_t XML_extrusion_rotation_center = 703;
+const xml_token_t XML_extrusion_second_light_direction = 704;
+const xml_token_t XML_extrusion_second_light_harsh = 705;
+const xml_token_t XML_extrusion_second_light_level = 706;
+const xml_token_t XML_extrusion_shininess = 707;
+const xml_token_t XML_extrusion_skew = 708;
+const xml_token_t XML_extrusion_specularity = 709;
+const xml_token_t XML_extrusion_viewpoint = 710;
+const xml_token_t XML_fade = 711;
+const xml_token_t XML_fade_from_bottom = 712;
+const xml_token_t XML_fade_from_center = 713;
+const xml_token_t XML_fade_from_left = 714;
+const xml_token_t XML_fade_from_lowerleft = 715;
+const xml_token_t XML_fade_from_lowerright = 716;
+const xml_token_t XML_fade_from_right = 717;
+const xml_token_t XML_fade_from_top = 718;
+const xml_token_t XML_fade_from_upperleft = 719;
+const xml_token_t XML_fade_from_upperright = 720;
+const xml_token_t XML_fade_out = 721;
+const xml_token_t XML_fade_to_center = 722;
+const xml_token_t XML_fadeColor = 723;
+const xml_token_t XML_false = 724;
+const xml_token_t XML_family = 725;
+const xml_token_t XML_fast = 726;
+const xml_token_t XML_field = 727;
+const xml_token_t XML_field_name = 728;
+const xml_token_t XML_field_number = 729;
+const xml_token_t XML_file = 730;
+const xml_token_t XML_file_based_database = 731;
+const xml_token_t XML_file_name = 732;
+const xml_token_t XML_fill = 733;
+const xml_token_t XML_fill_character = 734;
+const xml_token_t XML_fill_color = 735;
+const xml_token_t XML_fill_gradient_name = 736;
+const xml_token_t XML_fill_hatch_name = 737;
+const xml_token_t XML_fill_hatch_solid = 738;
+const xml_token_t XML_fill_image = 739;
+const xml_token_t XML_fill_image_height = 740;
+const xml_token_t XML_fill_image_name = 741;
+const xml_token_t XML_fill_image_ref_point = 742;
+const xml_token_t XML_fill_image_ref_point_x = 743;
+const xml_token_t XML_fill_image_ref_point_y = 744;
+const xml_token_t XML_fill_image_width = 745;
+const xml_token_t XML_fill_rule = 746;
+const xml_token_t XML_fillDefault = 747;
+const xml_token_t XML_filter = 748;
+const xml_token_t XML_filter_and = 749;
+const xml_token_t XML_filter_condition = 750;
+const xml_token_t XML_filter_name = 751;
+const xml_token_t XML_filter_options = 752;
+const xml_token_t XML_filter_or = 753;
+const xml_token_t XML_filter_set_item = 754;
+const xml_token_t XML_filter_statement = 755;
+const xml_token_t XML_first = 756;
+const xml_token_t XML_first_column = 757;
+const xml_token_t XML_first_page = 758;
+const xml_token_t XML_first_page_number = 759;
+const xml_token_t XML_first_row = 760;
+const xml_token_t XML_first_row_end_column = 761;
+const xml_token_t XML_first_row_start_column = 762;
+const xml_token_t XML_fit_to_contour = 763;
+const xml_token_t XML_fit_to_size = 764;
+const xml_token_t XML_fix = 765;
+const xml_token_t XML_fixed = 766;
+const xml_token_t XML_fixed_text = 767;
+const xml_token_t XML_flat = 768;
+const xml_token_t XML_float = 769;
+const xml_token_t XML_floating_frame = 770;
+const xml_token_t XML_floor = 771;
+const xml_token_t XML_flow_with_text = 772;
+const xml_token_t XML_fly_away = 773;
+const xml_token_t XML_fo = 774;
+const xml_token_t XML_focal_length = 775;
+const xml_token_t XML_focus_on_click = 776;
+const xml_token_t XML_font_adornments = 777;
+const xml_token_t XML_font_charset = 778;
+const xml_token_t XML_font_charset_asian = 779;
+const xml_token_t XML_font_charset_complex = 780;
+const xml_token_t XML_font_color = 781;
+const xml_token_t XML_font_face = 782;
+const xml_token_t XML_font_face_decls = 783;
+const xml_token_t XML_font_face_format = 784;
+const xml_token_t XML_font_face_name = 785;
+const xml_token_t XML_font_face_src = 786;
+const xml_token_t XML_font_face_uri = 787;
+const xml_token_t XML_font_family = 788;
+const xml_token_t XML_font_family_asian = 789;
+const xml_token_t XML_font_family_complex = 790;
+const xml_token_t XML_font_family_generic = 791;
+const xml_token_t XML_font_family_generic_asian = 792;
+const xml_token_t XML_font_family_generic_complex = 793;
+const xml_token_t XML_font_independent_line_spacing = 794;
+const xml_token_t XML_font_name = 795;
+const xml_token_t XML_font_name_asian = 796;
+const xml_token_t XML_font_name_complex = 797;
+const xml_token_t XML_font_pitch = 798;
+const xml_token_t XML_font_pitch_asian = 799;
+const xml_token_t XML_font_pitch_complex = 800;
+const xml_token_t XML_font_relief = 801;
+const xml_token_t XML_font_size = 802;
+const xml_token_t XML_font_size_asian = 803;
+const xml_token_t XML_font_size_complex = 804;
+const xml_token_t XML_font_size_rel = 805;
+const xml_token_t XML_font_size_rel_asian = 806;
+const xml_token_t XML_font_size_rel_complex = 807;
+const xml_token_t XML_font_stretch = 808;
+const xml_token_t XML_font_style = 809;
+const xml_token_t XML_font_style_asian = 810;
+const xml_token_t XML_font_style_complex = 811;
+const xml_token_t XML_font_style_name = 812;
+const xml_token_t XML_font_style_name_asian = 813;
+const xml_token_t XML_font_style_name_complex = 814;
+const xml_token_t XML_font_variant = 815;
+const xml_token_t XML_font_weight = 816;
+const xml_token_t XML_font_weight_asian = 817;
+const xml_token_t XML_font_weight_complex = 818;
+const xml_token_t XML_footer = 819;
+const xml_token_t XML_footer_decl = 820;
+const xml_token_t XML_footer_first = 821;
+const xml_token_t XML_footer_left = 822;
+const xml_token_t XML_footer_style = 823;
+const xml_token_t XML_footnote = 824;
+const xml_token_t XML_footnote_max_height = 825;
+const xml_token_t XML_footnote_sep = 826;
+const xml_token_t XML_footnotes_position = 827;
+const xml_token_t XML_for = 828;
+const xml_token_t XML_force_manual = 829;
+const xml_token_t XML_forced_exponent_sign = 830;
+const xml_token_t XML_foreground = 831;
+const xml_token_t XML_foreign = 832;
+const xml_token_t XML_form = 833;
+const xml_token_t XML_format_change = 834;
+const xml_token_t XML_format_source = 835;
+const xml_token_t XML_formatted_text = 836;
+const xml_token_t XML_forms = 837;
+const xml_token_t XML_formula = 838;
+const xml_token_t XML_formula_hidden = 839;
+const xml_token_t XML_formulas = 840;
+const xml_token_t XML_forward = 841;
+const xml_token_t XML_fraction = 842;
+const xml_token_t XML_frame = 843;
+const xml_token_t XML_frame_content = 844;
+const xml_token_t XML_frame_count = 845;
+const xml_token_t XML_frame_display_border = 846;
+const xml_token_t XML_frame_display_scrollbar = 847;
+const xml_token_t XML_frame_end_margin = 848;
+const xml_token_t XML_frame_margin_horizontal = 849;
+const xml_token_t XML_frame_margin_vertical = 850;
+const xml_token_t XML_frame_name = 851;
+const xml_token_t XML_frame_start_margin = 852;
+const xml_token_t XML_free = 853;
+const xml_token_t XML_freeze = 854;
+const xml_token_t XML_from = 855;
+const xml_token_t XML_from_another_table = 856;
+const xml_token_t XML_from_bottom = 857;
+const xml_token_t XML_from_center = 858;
+const xml_token_t XML_from_inside = 859;
+const xml_token_t XML_from_left = 860;
+const xml_token_t XML_from_lower_left = 861;
+const xml_token_t XML_from_lower_right = 862;
+const xml_token_t XML_from_right = 863;
+const xml_token_t XML_from_same_table = 864;
+const xml_token_t XML_from_top = 865;
+const xml_token_t XML_from_upper_left = 866;
+const xml_token_t XML_from_upper_right = 867;
+const xml_token_t XML_ft = 868;
+const xml_token_t XML_full = 869;
+const xml_token_t XML_full_screen = 870;
+const xml_token_t XML_function = 871;
+const xml_token_t XML_fx = 872;
+const xml_token_t XML_fy = 873;
+const xml_token_t XML_g = 874;
+const xml_token_t XML_gamma = 875;
+const xml_token_t XML_gap = 876;
+const xml_token_t XML_gap_width = 877;
+const xml_token_t XML_generator = 878;
+const xml_token_t XML_generic_control = 879;
+const xml_token_t XML_gengou = 880;
+const xml_token_t XML_get = 881;
+const xml_token_t XML_global = 882;
+const xml_token_t XML_glue_point = 883;
+const xml_token_t XML_glue_point_leaving_directions = 884;
+const xml_token_t XML_glue_point_type = 885;
+const xml_token_t XML_glue_points = 886;
+const xml_token_t XML_glyph_orientation_vertical = 887;
+const xml_token_t XML_gouraud = 888;
+const xml_token_t XML_gradient = 889;
+const xml_token_t XML_gradient_step_count = 890;
+const xml_token_t XML_gradientTransform = 891;
+const xml_token_t XML_gradientUnits = 892;
+const xml_token_t XML_grand_total = 893;
+const xml_token_t XML_graphic = 894;
+const xml_token_t XML_graphic_properties = 895;
+const xml_token_t XML_grddl = 896;
+const xml_token_t XML_green = 897;
+const xml_token_t XML_gregorian = 898;
+const xml_token_t XML_greyscale = 899;
+const xml_token_t XML_grid = 900;
+const xml_token_t XML_group_bars_per_axis = 901;
+const xml_token_t XML_group_by_field_number = 902;
+const xml_token_t XML_group_id = 903;
+const xml_token_t XML_grouped_by = 904;
+const xml_token_t XML_grouping = 905;
+const xml_token_t XML_guide_distance = 906;
+const xml_token_t XML_guide_overhang = 907;
+const xml_token_t XML_h = 908;
+const xml_token_t XML_handle = 909;
+const xml_token_t XML_handle_mirror_horizontal = 910;
+const xml_token_t XML_handle_mirror_vertical = 911;
+const xml_token_t XML_handle_polar = 912;
+const xml_token_t XML_handle_position = 913;
+const xml_token_t XML_handle_radius_range_maximum = 914;
+const xml_token_t XML_handle_radius_range_minimum = 915;
+const xml_token_t XML_handle_range_x_maximum = 916;
+const xml_token_t XML_handle_range_x_minimum = 917;
+const xml_token_t XML_handle_range_y_maximum = 918;
+const xml_token_t XML_handle_range_y_minimum = 919;
+const xml_token_t XML_handle_switched = 920;
+const xml_token_t XML_handout = 921;
+const xml_token_t XML_handout_master = 922;
+const xml_token_t XML_hanging = 923;
+const xml_token_t XML_hanja = 924;
+const xml_token_t XML_hanja_yoil = 925;
+const xml_token_t XML_has_persistent_data = 926;
+const xml_token_t XML_hatch = 927;
+const xml_token_t XML_header = 928;
+const xml_token_t XML_header_decl = 929;
+const xml_token_t XML_header_first = 930;
+const xml_token_t XML_header_footer_properties = 931;
+const xml_token_t XML_header_left = 932;
+const xml_token_t XML_header_style = 933;
+const xml_token_t XML_headers = 934;
+const xml_token_t XML_height = 935;
+const xml_token_t XML_help_message = 936;
+const xml_token_t XML_hidden = 937;
+const xml_token_t XML_hidden_and_protected = 938;
+const xml_token_t XML_hidden_paragraph = 939;
+const xml_token_t XML_hidden_text = 940;
+const xml_token_t XML_hide = 941;
+const xml_token_t XML_hide_shape = 942;
+const xml_token_t XML_hide_text = 943;
+const xml_token_t XML_high = 944;
+const xml_token_t XML_highlighted_range = 945;
+const xml_token_t XML_hijri = 946;
+const xml_token_t XML_hold = 947;
+const xml_token_t XML_hole_size = 948;
+const xml_token_t XML_horizontal = 949;
+const xml_token_t XML_horizontal_bar = 950;
+const xml_token_t XML_horizontal_checkerboard = 951;
+const xml_token_t XML_horizontal_lines = 952;
+const xml_token_t XML_horizontal_on_even = 953;
+const xml_token_t XML_horizontal_on_odd = 954;
+const xml_token_t XML_horizontal_pos = 955;
+const xml_token_t XML_horizontal_rel = 956;
+const xml_token_t XML_horizontal_segments = 957;
+const xml_token_t XML_horizontal_stripes = 958;
+const xml_token_t XML_hostname = 959;
+const xml_token_t XML_hourglass = 960;
+const xml_token_t XML_hours = 961;
+const xml_token_t XML_howpublished = 962;
+const xml_token_t XML_href = 963;
+const xml_token_t XML_hsl = 964;
+const xml_token_t XML_hyperlink_behaviour = 965;
+const xml_token_t XML_hyphenate = 966;
+const xml_token_t XML_hyphenation_keep = 967;
+const xml_token_t XML_hyphenation_ladder_count = 968;
+const xml_token_t XML_hyphenation_push_char_count = 969;
+const xml_token_t XML_hyphenation_remain_char_count = 970;
+const xml_token_t XML_i = 971;
+const xml_token_t XML_icon = 972;
+const xml_token_t XML_id = 973;
+const xml_token_t XML_identifier = 974;
+const xml_token_t XML_identify_categories = 975;
+const xml_token_t XML_ideograph_alpha = 976;
+const xml_token_t XML_ideographic = 977;
+const xml_token_t XML_ignore = 978;
+const xml_token_t XML_ignore_case = 979;
+const xml_token_t XML_ignore_driver_privileges = 980;
+const xml_token_t XML_ignore_empty_rows = 981;
+const xml_token_t XML_ignore_result = 982;
+const xml_token_t XML_illustration_index = 983;
+const xml_token_t XML_illustration_index_entry_template = 984;
+const xml_token_t XML_illustration_index_source = 985;
+const xml_token_t XML_image = 986;
+const xml_token_t XML_image_align = 987;
+const xml_token_t XML_image_count = 988;
+const xml_token_t XML_image_data = 989;
+const xml_token_t XML_image_frame = 990;
+const xml_token_t XML_image_map = 991;
+const xml_token_t XML_image_opacity = 992;
+const xml_token_t XML_image_position = 993;
+const xml_token_t XML_in = 994;
+const xml_token_t XML_inbook = 995;
+const xml_token_t XML_inch = 996;
+const xml_token_t XML_include_hidden_cells = 997;
+const xml_token_t XML_incollection = 998;
+const xml_token_t XML_increment = 999;
+const xml_token_t XML_indefinite = 1000;
+const xml_token_t XML_index = 1001;
+const xml_token_t XML_index_body = 1002;
+const xml_token_t XML_index_column = 1003;
+const xml_token_t XML_index_columns = 1004;
+const xml_token_t XML_index_entry_bibliography = 1005;
+const xml_token_t XML_index_entry_chapter = 1006;
+const xml_token_t XML_index_entry_link_end = 1007;
+const xml_token_t XML_index_entry_link_start = 1008;
+const xml_token_t XML_index_entry_page_number = 1009;
+const xml_token_t XML_index_entry_span = 1010;
+const xml_token_t XML_index_entry_tab_stop = 1011;
+const xml_token_t XML_index_entry_text = 1012;
+const xml_token_t XML_index_name = 1013;
+const xml_token_t XML_index_scope = 1014;
+const xml_token_t XML_index_source_style = 1015;
+const xml_token_t XML_index_source_styles = 1016;
+const xml_token_t XML_index_title = 1017;
+const xml_token_t XML_index_title_template = 1018;
+const xml_token_t XML_indices = 1019;
+const xml_token_t XML_information = 1020;
+const xml_token_t XML_inherit = 1021;
+const xml_token_t XML_initial_creator = 1022;
+const xml_token_t XML_inner = 1023;
+const xml_token_t XML_inproceedings = 1024;
+const xml_token_t XML_insertion = 1025;
+const xml_token_t XML_insertion_cut_off = 1026;
+const xml_token_t XML_inside = 1027;
+const xml_token_t XML_institution = 1028;
+const xml_token_t XML_int = 1029;
+const xml_token_t XML_integer = 1030;
+const xml_token_t XML_intensity = 1031;
+const xml_token_t XML_interactive_sequence = 1032;
+const xml_token_t XML_interlocking_horizontal_left = 1033;
+const xml_token_t XML_interlocking_horizontal_right = 1034;
+const xml_token_t XML_interlocking_vertical_bottom = 1035;
+const xml_token_t XML_interlocking_vertical_top = 1036;
+const xml_token_t XML_interpolation = 1037;
+const xml_token_t XML_interval_major = 1038;
+const xml_token_t XML_interval_minor_divisor = 1039;
+const xml_token_t XML_into_default_style_data_style = 1040;
+const xml_token_t XML_into_english_number = 1041;
+const xml_token_t XML_inverse = 1042;
+const xml_token_t XML_is_active = 1043;
+const xml_token_t XML_is_ascending = 1044;
+const xml_token_t XML_is_autoincrement = 1045;
+const xml_token_t XML_is_boolean = 1046;
+const xml_token_t XML_is_clustered = 1047;
+const xml_token_t XML_is_data_layout_field = 1048;
+const xml_token_t XML_is_empty_allowed = 1049;
+const xml_token_t XML_is_first_row_header_line = 1050;
+const xml_token_t XML_is_hidden = 1051;
+const xml_token_t XML_is_list_header = 1052;
+const xml_token_t XML_is_nullable = 1053;
+const xml_token_t XML_is_password_required = 1054;
+const xml_token_t XML_is_selection = 1055;
+const xml_token_t XML_is_sub_table = 1056;
+const xml_token_t XML_is_table_name_length_limited = 1057;
+const xml_token_t XML_is_tristate = 1058;
+const xml_token_t XML_is_unique = 1059;
+const xml_token_t XML_isbn = 1060;
+const xml_token_t XML_issn = 1061;
+const xml_token_t XML_italic = 1062;
+const xml_token_t XML_item = 1063;
+const xml_token_t XML_iterate = 1064;
+const xml_token_t XML_iterate_interval = 1065;
+const xml_token_t XML_iterate_type = 1066;
+const xml_token_t XML_iteration = 1067;
+const xml_token_t XML_iterative = 1068;
+const xml_token_t XML_japanese_candle_stick = 1069;
+const xml_token_t XML_jewish = 1070;
+const xml_token_t XML_join_border = 1071;
+const xml_token_t XML_journal = 1072;
+const xml_token_t XML_justify = 1073;
+const xml_token_t XML_justify_single_word = 1074;
+const xml_token_t XML_keep_text = 1075;
+const xml_token_t XML_keep_together = 1076;
+const xml_token_t XML_keep_with_next = 1077;
+const xml_token_t XML_key = 1078;
+const xml_token_t XML_key_column = 1079;
+const xml_token_t XML_key_columns = 1080;
+const xml_token_t XML_key1 = 1081;
+const xml_token_t XML_key1_phonetic = 1082;
+const xml_token_t XML_key2 = 1083;
+const xml_token_t XML_key2_phonetic = 1084;
+const xml_token_t XML_keySplines = 1085;
+const xml_token_t XML_keyTimes = 1086;
+const xml_token_t XML_keys = 1087;
+const xml_token_t XML_keyword = 1088;
+const xml_token_t XML_keywords = 1089;
+const xml_token_t XML_kind = 1090;
+const xml_token_t XML_km = 1091;
+const xml_token_t XML_label = 1092;
+const xml_token_t XML_label_alignment = 1093;
+const xml_token_t XML_label_arrangement = 1094;
+const xml_token_t XML_label_cell_address = 1095;
+const xml_token_t XML_label_cell_range_address = 1096;
+const xml_token_t XML_label_followed_by = 1097;
+const xml_token_t XML_label_position = 1098;
+const xml_token_t XML_label_position_negative = 1099;
+const xml_token_t XML_label_range = 1100;
+const xml_token_t XML_label_ranges = 1101;
+const xml_token_t XML_label_separator = 1102;
+const xml_token_t XML_label_width_and_position = 1103;
+const xml_token_t XML_landscape = 1104;
+const xml_token_t XML_language = 1105;
+const xml_token_t XML_language_asian = 1106;
+const xml_token_t XML_language_complex = 1107;
+const xml_token_t XML_laser = 1108;
+const xml_token_t XML_last = 1109;
+const xml_token_t XML_last_column = 1110;
+const xml_token_t XML_last_column_spanned = 1111;
+const xml_token_t XML_last_page = 1112;
+const xml_token_t XML_last_row = 1113;
+const xml_token_t XML_last_row_end_column = 1114;
+const xml_token_t XML_last_row_spanned = 1115;
+const xml_token_t XML_last_row_start_column = 1116;
+const xml_token_t XML_last_visited_page = 1117;
+const xml_token_t XML_latin = 1118;
+const xml_token_t XML_layer = 1119;
+const xml_token_t XML_layer_set = 1120;
+const xml_token_t XML_layout_grid_base_height = 1121;
+const xml_token_t XML_layout_grid_base_width = 1122;
+const xml_token_t XML_layout_grid_color = 1123;
+const xml_token_t XML_layout_grid_display = 1124;
+const xml_token_t XML_layout_grid_lines = 1125;
+const xml_token_t XML_layout_grid_mode = 1126;
+const xml_token_t XML_layout_grid_print = 1127;
+const xml_token_t XML_layout_grid_ruby_below = 1128;
+const xml_token_t XML_layout_grid_ruby_height = 1129;
+const xml_token_t XML_layout_grid_snap_to = 1130;
+const xml_token_t XML_layout_grid_standard_mode = 1131;
+const xml_token_t XML_layout_mode = 1132;
+const xml_token_t XML_leader_char = 1133;
+const xml_token_t XML_leader_color = 1134;
+const xml_token_t XML_leader_style = 1135;
+const xml_token_t XML_leader_text = 1136;
+const xml_token_t XML_leader_text_style = 1137;
+const xml_token_t XML_leader_type = 1138;
+const xml_token_t XML_leader_width = 1139;
+const xml_token_t XML_leave_gap = 1140;
+const xml_token_t XML_left = 1141;
+const xml_token_t XML_left_outside = 1142;
+const xml_token_t XML_legend = 1143;
+const xml_token_t XML_legend_align = 1144;
+const xml_token_t XML_legend_expansion = 1145;
+const xml_token_t XML_legend_expansion_aspect_ratio = 1146;
+const xml_token_t XML_legend_position = 1147;
+const xml_token_t XML_length = 1148;
+const xml_token_t XML_letter_kerning = 1149;
+const xml_token_t XML_letter_spacing = 1150;
+const xml_token_t XML_letters = 1151;
+const xml_token_t XML_level = 1152;
+const xml_token_t XML_light = 1153;
+const xml_token_t XML_lighting_mode = 1154;
+const xml_token_t XML_line = 1155;
+const xml_token_t XML_line_break = 1156;
+const xml_token_t XML_line_distance = 1157;
+const xml_token_t XML_line_height = 1158;
+const xml_token_t XML_line_height_at_least = 1159;
+const xml_token_t XML_line_number = 1160;
+const xml_token_t XML_line_skew = 1161;
+const xml_token_t XML_line_spacing = 1162;
+const xml_token_t XML_line_style = 1163;
+const xml_token_t XML_linear = 1164;
+const xml_token_t XML_linearGradient = 1165;
+const xml_token_t XML_linenumbering_configuration = 1166;
+const xml_token_t XML_linenumbering_separator = 1167;
+const xml_token_t XML_lines = 1168;
+const xml_token_t XML_link_data_style_to_source = 1169;
+const xml_token_t XML_link_to_source_data = 1170;
+const xml_token_t XML_linked_cell = 1171;
+const xml_token_t XML_list = 1172;
+const xml_token_t XML_list_header = 1173;
+const xml_token_t XML_list_id = 1174;
+const xml_token_t XML_list_item = 1175;
+const xml_token_t XML_list_level = 1176;
+const xml_token_t XML_list_level_label_alignment = 1177;
+const xml_token_t XML_list_level_position_and_space_mode = 1178;
+const xml_token_t XML_list_level_properties = 1179;
+const xml_token_t XML_list_level_style_bullet = 1180;
+const xml_token_t XML_list_level_style_image = 1181;
+const xml_token_t XML_list_level_style_number = 1182;
+const xml_token_t XML_list_linkage_type = 1183;
+const xml_token_t XML_list_property = 1184;
+const xml_token_t XML_list_source = 1185;
+const xml_token_t XML_list_source_type = 1186;
+const xml_token_t XML_list_style = 1187;
+const xml_token_t XML_list_style_name = 1188;
+const xml_token_t XML_list_tab_stop_position = 1189;
+const xml_token_t XML_list_value = 1190;
+const xml_token_t XML_listbox = 1191;
+const xml_token_t XML_listtab = 1192;
+const xml_token_t XML_local_socket = 1193;
+const xml_token_t XML_logarithmic = 1194;
+const xml_token_t XML_login = 1195;
+const xml_token_t XML_login_timeout = 1196;
+const xml_token_t XML_long = 1197;
+const xml_token_t XML_long_dash = 1198;
+const xml_token_t XML_longvarbinary = 1199;
+const xml_token_t XML_longvarchar = 1200;
+const xml_token_t XML_lowercase = 1201;
+const xml_token_t XML_lr = 1202;
+const xml_token_t XML_lr_tb = 1203;
+const xml_token_t XML_ltr = 1204;
+const xml_token_t XML_luminance = 1205;
+const xml_token_t XML_m = 1206;
+const xml_token_t XML_macro_name = 1207;
+const xml_token_t XML_main_entry = 1208;
+const xml_token_t XML_main_entry_style_name = 1209;
+const xml_token_t XML_main_sequence = 1210;
+const xml_token_t XML_major = 1211;
+const xml_token_t XML_manual = 1212;
+const xml_token_t XML_map = 1213;
+const xml_token_t XML_margin = 1214;
+const xml_token_t XML_margin_bottom = 1215;
+const xml_token_t XML_margin_left = 1216;
+const xml_token_t XML_margin_right = 1217;
+const xml_token_t XML_margin_top = 1218;
+const xml_token_t XML_margins = 1219;
+const xml_token_t XML_marked_invalid = 1220;
+const xml_token_t XML_marker = 1221;
+const xml_token_t XML_marker_end = 1222;
+const xml_token_t XML_marker_end_center = 1223;
+const xml_token_t XML_marker_end_width = 1224;
+const xml_token_t XML_marker_start = 1225;
+const xml_token_t XML_marker_start_center = 1226;
+const xml_token_t XML_marker_start_width = 1227;
+const xml_token_t XML_master_element = 1228;
+const xml_token_t XML_master_fields = 1229;
+const xml_token_t XML_master_page = 1230;
+const xml_token_t XML_master_page_name = 1231;
+const xml_token_t XML_master_styles = 1232;
+const xml_token_t XML_mastersthesis = 1233;
+const xml_token_t XML_math = 1234;
+const xml_token_t XML_mathematical = 1235;
+const xml_token_t XML_matrix_covered = 1236;
+const xml_token_t XML_max = 1237;
+const xml_token_t XML_max_denominator_value = 1238;
+const xml_token_t XML_max_edge = 1239;
+const xml_token_t XML_max_height = 1240;
+const xml_token_t XML_max_length = 1241;
+const xml_token_t XML_max_row_count = 1242;
+const xml_token_t XML_max_value = 1243;
+const xml_token_t XML_max_width = 1244;
+const xml_token_t XML_maximum = 1245;
+const xml_token_t XML_maximum_difference = 1246;
+const xml_token_t XML_may_break_between_rows = 1247;
+const xml_token_t XML_may_script = 1248;
+const xml_token_t XML_mean_value = 1249;
+const xml_token_t XML_measure = 1250;
+const xml_token_t XML_measure_align = 1251;
+const xml_token_t XML_measure_vertical_align = 1252;
+const xml_token_t XML_media = 1253;
+const xml_token_t XML_media_call = 1254;
+const xml_token_t XML_media_type = 1255;
+const xml_token_t XML_medium = 1256;
+const xml_token_t XML_melt = 1257;
+const xml_token_t XML_member_count = 1258;
+const xml_token_t XML_member_difference = 1259;
+const xml_token_t XML_member_name = 1260;
+const xml_token_t XML_member_percentage = 1261;
+const xml_token_t XML_member_percentage_difference = 1262;
+const xml_token_t XML_member_type = 1263;
+const xml_token_t XML_message_type = 1264;
+const xml_token_t XML_meta = 1265;
+const xml_token_t XML_meta_field = 1266;
+const xml_token_t XML_method = 1267;
+const xml_token_t XML_mi = 1268;
+const xml_token_t XML_middle = 1269;
+const xml_token_t XML_mime_type = 1270;
+const xml_token_t XML_mimetype = 1271;
+const xml_token_t XML_min = 1272;
+const xml_token_t XML_min_decimal_places = 1273;
+const xml_token_t XML_min_denominator_digits = 1274;
+const xml_token_t XML_min_edge = 1275;
+const xml_token_t XML_min_exponent_digits = 1276;
+const xml_token_t XML_min_height = 1277;
+const xml_token_t XML_min_integer_digits = 1278;
+const xml_token_t XML_min_label_distance = 1279;
+const xml_token_t XML_min_label_width = 1280;
+const xml_token_t XML_min_numerator_digits = 1281;
+const xml_token_t XML_min_row_height = 1282;
+const xml_token_t XML_min_value = 1283;
+const xml_token_t XML_min_width = 1284;
+const xml_token_t XML_minimum = 1285;
+const xml_token_t XML_minor = 1286;
+const xml_token_t XML_minutes = 1287;
+const xml_token_t XML_mirror = 1288;
+const xml_token_t XML_mirror_horizontal = 1289;
+const xml_token_t XML_mirror_vertical = 1290;
+const xml_token_t XML_mirrored = 1291;
+const xml_token_t XML_misc = 1292;
+const xml_token_t XML_miter = 1293;
+const xml_token_t XML_mm = 1294;
+const xml_token_t XML_mode = 1295;
+const xml_token_t XML_model = 1296;
+const xml_token_t XML_modern = 1297;
+const xml_token_t XML_modification_date = 1298;
+const xml_token_t XML_modification_time = 1299;
+const xml_token_t XML_modifiers = 1300;
+const xml_token_t XML_modulate = 1301;
+const xml_token_t XML_mono = 1302;
+const xml_token_t XML_month = 1303;
+const xml_token_t XML_months = 1304;
+const xml_token_t XML_motion_path = 1305;
+const xml_token_t XML_mouse_as_pen = 1306;
+const xml_token_t XML_mouse_visible = 1307;
+const xml_token_t XML_move = 1308;
+const xml_token_t XML_move_from_bottom = 1309;
+const xml_token_t XML_move_from_left = 1310;
+const xml_token_t XML_move_from_lowerleft = 1311;
+const xml_token_t XML_move_from_lowerright = 1312;
+const xml_token_t XML_move_from_right = 1313;
+const xml_token_t XML_move_from_top = 1314;
+const xml_token_t XML_move_from_upperleft = 1315;
+const xml_token_t XML_move_from_upperright = 1316;
+const xml_token_t XML_move_short = 1317;
+const xml_token_t XML_movement = 1318;
+const xml_token_t XML_movement_cut_off = 1319;
+const xml_token_t XML_moving_average = 1320;
+const xml_token_t XML_multi_deletion_spanned = 1321;
+const xml_token_t XML_multi_line = 1322;
+const xml_token_t XML_multiple = 1323;
+const xml_token_t XML_name = 1324;
+const xml_token_t XML_name_and_extension = 1325;
+const xml_token_t XML_named = 1326;
+const xml_token_t XML_named_expression = 1327;
+const xml_token_t XML_named_expressions = 1328;
+const xml_token_t XML_named_range = 1329;
+const xml_token_t XML_named_symbol = 1330;
+const xml_token_t XML_nav_order = 1331;
+const xml_token_t XML_navigation_mode = 1332;
+const xml_token_t XML_near_axis = 1333;
+const xml_token_t XML_near_axis_other_side = 1334;
+const xml_token_t XML_near_origin = 1335;
+const xml_token_t XML_never = 1336;
+const xml_token_t XML_new = 1337;
+const xml_token_t XML_next = 1338;
+const xml_token_t XML_next_page = 1339;
+const xml_token_t XML_next_style_name = 1340;
+const xml_token_t XML_no_action = 1341;
+const xml_token_t XML_no_limit = 1342;
+const xml_token_t XML_no_nulls = 1343;
+const xml_token_t XML_no_repeat = 1344;
+const xml_token_t XML_no_wrap = 1345;
+const xml_token_t XML_node_type = 1346;
+const xml_token_t XML_nohref = 1347;
+const xml_token_t XML_non_primitive = 1348;
+const xml_token_t XML_non_whitespace_character_count = 1349;
+const xml_token_t XML_none = 1350;
+const xml_token_t XML_nonzero = 1351;
+const xml_token_t XML_normal = 1352;
+const xml_token_t XML_normals_direction = 1353;
+const xml_token_t XML_normals_kind = 1354;
+const xml_token_t XML_note = 1355;
+const xml_token_t XML_note_body = 1356;
+const xml_token_t XML_note_citation = 1357;
+const xml_token_t XML_note_class = 1358;
+const xml_token_t XML_note_continuation_notice_backward = 1359;
+const xml_token_t XML_note_continuation_notice_forward = 1360;
+const xml_token_t XML_note_ref = 1361;
+const xml_token_t XML_notes = 1362;
+const xml_token_t XML_notes_configuration = 1363;
+const xml_token_t XML_nothing = 1364;
+const xml_token_t XML_notify_on_update_of_ranges = 1365;
+const xml_token_t XML_null_date = 1366;
+const xml_token_t XML_null_year = 1367;
+const xml_token_t XML_nullable = 1368;
+const xml_token_t XML_num_format = 1369;
+const xml_token_t XML_num_letter_sync = 1370;
+const xml_token_t XML_num_prefix = 1371;
+const xml_token_t XML_num_suffix = 1372;
+const xml_token_t XML_number = 1373;
+const xml_token_t XML_number_all_superior = 1374;
+const xml_token_t XML_number_and_name = 1375;
+const xml_token_t XML_number_columns_repeated = 1376;
+const xml_token_t XML_number_columns_spanned = 1377;
+const xml_token_t XML_number_lines = 1378;
+const xml_token_t XML_number_matrix_columns_spanned = 1379;
+const xml_token_t XML_number_matrix_rows_spanned = 1380;
+const xml_token_t XML_number_no_superior = 1381;
+const xml_token_t XML_number_position = 1382;
+const xml_token_t XML_number_rows_repeated = 1383;
+const xml_token_t XML_number_rows_spanned = 1384;
+const xml_token_t XML_number_style = 1385;
+const xml_token_t XML_number_wrapped_paragraphs = 1386;
+const xml_token_t XML_numbered_entries = 1387;
+const xml_token_t XML_numbered_paragraph = 1388;
+const xml_token_t XML_numeric = 1389;
+const xml_token_t XML_object = 1390;
+const xml_token_t XML_object_count = 1391;
+const xml_token_t XML_object_index = 1392;
+const xml_token_t XML_object_index_entry_template = 1393;
+const xml_token_t XML_object_index_source = 1394;
+const xml_token_t XML_object_name = 1395;
+const xml_token_t XML_object_ole = 1396;
+const xml_token_t XML_objectBoundingBox = 1397;
+const xml_token_t XML_objects = 1398;
+const xml_token_t XML_oblique = 1399;
+const xml_token_t XML_odd_columns = 1400;
+const xml_token_t XML_odd_rows = 1401;
+const xml_token_t XML_office = 1402;
+const xml_token_t XML_offset = 1403;
+const xml_token_t XML_ole_action = 1404;
+const xml_token_t XML_ole_draw_aspect = 1405;
+const xml_token_t XML_ole_object_count = 1406;
+const xml_token_t XML_on_click = 1407;
+const xml_token_t XML_on_update_keep_size = 1408;
+const xml_token_t XML_on_update_keep_styles = 1409;
+const xml_token_t XML_onLoad = 1410;
+const xml_token_t XML_onRequest = 1411;
+const xml_token_t XML_once_concurrent = 1412;
+const xml_token_t XML_once_successive = 1413;
+const xml_token_t XML_opacity = 1414;
+const xml_token_t XML_opacity_name = 1415;
+const xml_token_t XML_open = 1416;
+const xml_token_t XML_open_horizontal = 1417;
+const xml_token_t XML_open_vertical = 1418;
+const xml_token_t XML_operation = 1419;
+const xml_token_t XML_operator = 1420;
+const xml_token_t XML_option = 1421;
+const xml_token_t XML_order = 1422;
+const xml_token_t XML_order_statement = 1423;
+const xml_token_t XML_organizations = 1424;
+const xml_token_t XML_orgchart = 1425;
+const xml_token_t XML_orientation = 1426;
+const xml_token_t XML_origin = 1427;
+const xml_token_t XML_orphans = 1428;
+const xml_token_t XML_other = 1429;
+const xml_token_t XML_out = 1430;
+const xml_token_t XML_outer = 1431;
+const xml_token_t XML_outline = 1432;
+const xml_token_t XML_outline_level = 1433;
+const xml_token_t XML_outline_level_style = 1434;
+const xml_token_t XML_outline_style = 1435;
+const xml_token_t XML_outline_subtotals_bottom = 1436;
+const xml_token_t XML_outline_subtotals_top = 1437;
+const xml_token_t XML_outside = 1438;
+const xml_token_t XML_outside_end = 1439;
+const xml_token_t XML_outside_start = 1440;
+const xml_token_t XML_overflow_behavior = 1441;
+const xml_token_t XML_overlap = 1442;
+const xml_token_t XML_overline_position = 1443;
+const xml_token_t XML_overline_thickness = 1444;
+const xml_token_t XML_p = 1445;
+const xml_token_t XML_paced = 1446;
+const xml_token_t XML_pad = 1447;
+const xml_token_t XML_padding = 1448;
+const xml_token_t XML_padding_bottom = 1449;
+const xml_token_t XML_padding_left = 1450;
+const xml_token_t XML_padding_right = 1451;
+const xml_token_t XML_padding_top = 1452;
+const xml_token_t XML_page = 1453;
+const xml_token_t XML_page_adjust = 1454;
+const xml_token_t XML_page_breaks_on_group_change = 1455;
+const xml_token_t XML_page_content = 1456;
+const xml_token_t XML_page_continuation = 1457;
+const xml_token_t XML_page_count = 1458;
+const xml_token_t XML_page_end_margin = 1459;
+const xml_token_t XML_page_height = 1460;
+const xml_token_t XML_page_layout = 1461;
+const xml_token_t XML_page_layout_name = 1462;
+const xml_token_t XML_page_layout_properties = 1463;
+const xml_token_t XML_page_number = 1464;
+const xml_token_t XML_page_sequence = 1465;
+const xml_token_t XML_page_start_margin = 1466;
+const xml_token_t XML_page_step_size = 1467;
+const xml_token_t XML_page_thumbnail = 1468;
+const xml_token_t XML_page_usage = 1469;
+const xml_token_t XML_page_variable_get = 1470;
+const xml_token_t XML_page_variable_set = 1471;
+const xml_token_t XML_page_width = 1472;
+const xml_token_t XML_pages = 1473;
+const xml_token_t XML_panose_1 = 1474;
+const xml_token_t XML_paper_tray_name = 1475;
+const xml_token_t XML_par = 1476;
+const xml_token_t XML_paragraph = 1477;
+const xml_token_t XML_paragraph_content = 1478;
+const xml_token_t XML_paragraph_count = 1479;
+const xml_token_t XML_paragraph_end_margin = 1480;
+const xml_token_t XML_paragraph_properties = 1481;
+const xml_token_t XML_paragraph_start_margin = 1482;
+const xml_token_t XML_paragraph_style_name = 1483;
+const xml_token_t XML_parallel = 1484;
+const xml_token_t XML_param = 1485;
+const xml_token_t XML_parameter_name_substitution = 1486;
+const xml_token_t XML_parent = 1487;
+const xml_token_t XML_parent_style_name = 1488;
+const xml_token_t XML_parse_sql_statement = 1489;
+const xml_token_t XML_password = 1490;
+const xml_token_t XML_path = 1491;
+const xml_token_t XML_path_id = 1492;
+const xml_token_t XML_path_stretchpoint_x = 1493;
+const xml_token_t XML_path_stretchpoint_y = 1494;
+const xml_token_t XML_pause = 1495;
+const xml_token_t XML_pc = 1496;
+const xml_token_t XML_pending = 1497;
+const xml_token_t XML_percentage = 1498;
+const xml_token_t XML_percentage_data_style_name = 1499;
+const xml_token_t XML_percentage_style = 1500;
+const xml_token_t XML_perspective = 1501;
+const xml_token_t XML_phdthesis = 1502;
+const xml_token_t XML_phong = 1503;
+const xml_token_t XML_pie_offset = 1504;
+const xml_token_t XML_placeholder = 1505;
+const xml_token_t XML_placeholder_type = 1506;
+const xml_token_t XML_placing = 1507;
+const xml_token_t XML_plain_number = 1508;
+const xml_token_t XML_plain_number_and_name = 1509;
+const xml_token_t XML_play = 1510;
+const xml_token_t XML_play_full = 1511;
+const xml_token_t XML_plot_area = 1512;
+const xml_token_t XML_plugin = 1513;
+const xml_token_t XML_plus = 1514;
+const xml_token_t XML_points = 1515;
+const xml_token_t XML_polygon = 1516;
+const xml_token_t XML_polyline = 1517;
+const xml_token_t XML_polynomial = 1518;
+const xml_token_t XML_port = 1519;
+const xml_token_t XML_portrait = 1520;
+const xml_token_t XML_position = 1521;
+const xml_token_t XML_possessive_form = 1522;
+const xml_token_t XML_post = 1523;
+const xml_token_t XML_power = 1524;
+const xml_token_t XML_precision = 1525;
+const xml_token_t XML_precision_as_shown = 1526;
+const xml_token_t XML_prefix = 1527;
+const xml_token_t XML_presentation = 1528;
+const xml_token_t XML_presentation_page_layout = 1529;
+const xml_token_t XML_presentation_page_layout_name = 1530;
+const xml_token_t XML_preset_class = 1531;
+const xml_token_t XML_preset_id = 1532;
+const xml_token_t XML_preset_sub_type = 1533;
+const xml_token_t XML_previous = 1534;
+const xml_token_t XML_previous_page = 1535;
+const xml_token_t XML_primary = 1536;
+const xml_token_t XML_print = 1537;
+const xml_token_t XML_print_content = 1538;
+const xml_token_t XML_print_date = 1539;
+const xml_token_t XML_print_orientation = 1540;
+const xml_token_t XML_print_page_order = 1541;
+const xml_token_t XML_print_range = 1542;
+const xml_token_t XML_print_ranges = 1543;
+const xml_token_t XML_print_time = 1544;
+const xml_token_t XML_print_view = 1545;
+const xml_token_t XML_printable = 1546;
+const xml_token_t XML_printed_by = 1547;
+const xml_token_t XML_printer = 1548;
+const xml_token_t XML_prior = 1549;
+const xml_token_t XML_proceedings = 1550;
+const xml_token_t XML_product = 1551;
+const xml_token_t XML_projection = 1552;
+const xml_token_t XML_properties = 1553;
+const xml_token_t XML_property = 1554;
+const xml_token_t XML_property_name = 1555;
+const xml_token_t XML_protect = 1556;
+const xml_token_t XML_protected = 1557;
+const xml_token_t XML_protection_key = 1558;
+const xml_token_t XML_protection_key_digest_algorithm = 1559;
+const xml_token_t XML_pt = 1560;
+const xml_token_t XML_publisher = 1561;
+const xml_token_t XML_punctuation_wrap = 1562;
+const xml_token_t XML_push = 1563;
+const xml_token_t XML_pyramid = 1564;
+const xml_token_t XML_quarter = 1565;
+const xml_token_t XML_quarters = 1566;
+const xml_token_t XML_queries = 1567;
+const xml_token_t XML_query = 1568;
+const xml_token_t XML_query_collection = 1569;
+const xml_token_t XML_query_name = 1570;
+const xml_token_t XML_r = 1571;
+const xml_token_t XML_radial = 1572;
+const xml_token_t XML_radialGradient = 1573;
+const xml_token_t XML_radio = 1574;
+const xml_token_t XML_random = 1575;
+const xml_token_t XML_range_usable_as = 1576;
+const xml_token_t XML_readonly = 1577;
+const xml_token_t XML_real = 1578;
+const xml_token_t XML_records = 1579;
+const xml_token_t XML_recreate_on_edit = 1580;
+const xml_token_t XML_rect = 1581;
+const xml_token_t XML_rectangle = 1582;
+const xml_token_t XML_rectangular = 1583;
+const xml_token_t XML_red = 1584;
+const xml_token_t XML_ref = 1585;
+const xml_token_t XML_ref_name = 1586;
+const xml_token_t XML_reference_format = 1587;
+const xml_token_t XML_reference_mark = 1588;
+const xml_token_t XML_reference_mark_end = 1589;
+const xml_token_t XML_reference_mark_start = 1590;
+const xml_token_t XML_referenced_table_name = 1591;
+const xml_token_t XML_reflect = 1592;
+const xml_token_t XML_refresh_delay = 1593;
+const xml_token_t XML_region_center = 1594;
+const xml_token_t XML_region_left = 1595;
+const xml_token_t XML_region_right = 1596;
+const xml_token_t XML_register_true = 1597;
+const xml_token_t XML_register_truth_ref_style_name = 1598;
+const xml_token_t XML_regression_curve = 1599;
+const xml_token_t XML_regression_force_intercept = 1600;
+const xml_token_t XML_regression_intercept_value = 1601;
+const xml_token_t XML_regression_max_degree = 1602;
+const xml_token_t XML_regression_moving_type = 1603;
+const xml_token_t XML_regression_name = 1604;
+const xml_token_t XML_regression_period = 1605;
+const xml_token_t XML_regression_type = 1606;
+const xml_token_t XML_regular_polygon = 1607;
+const xml_token_t XML_rejected = 1608;
+const xml_token_t XML_rejecting_change_id = 1609;
+const xml_token_t XML_rel_column_width = 1610;
+const xml_token_t XML_rel_height = 1611;
+const xml_token_t XML_rel_width = 1612;
+const xml_token_t XML_related_column_name = 1613;
+const xml_token_t XML_relative_tab_stop_position = 1614;
+const xml_token_t XML_remove = 1615;
+const xml_token_t XML_remove_dependents = 1616;
+const xml_token_t XML_remove_precedents = 1617;
+const xml_token_t XML_repeat = 1618;
+const xml_token_t XML_repeat_column = 1619;
+const xml_token_t XML_repeat_content = 1620;
+const xml_token_t XML_repeat_row = 1621;
+const xml_token_t XML_repeatCount = 1622;
+const xml_token_t XML_repeatDur = 1623;
+const xml_token_t XML_repeated = 1624;
+const xml_token_t XML_replace = 1625;
+const xml_token_t XML_report_type = 1626;
+const xml_token_t XML_reports = 1627;
+const xml_token_t XML_reset = 1628;
+const xml_token_t XML_restart = 1629;
+const xml_token_t XML_restart_numbering = 1630;
+const xml_token_t XML_restart_on_page = 1631;
+const xml_token_t XML_restartDefault = 1632;
+const xml_token_t XML_restrict = 1633;
+const xml_token_t XML_reverse = 1634;
+const xml_token_t XML_reverse_direction = 1635;
+const xml_token_t XML_rfc_language_tag = 1636;
+const xml_token_t XML_rfc_language_tag_asian = 1637;
+const xml_token_t XML_rfc_language_tag_complex = 1638;
+const xml_token_t XML_rgb = 1639;
+const xml_token_t XML_right = 1640;
+const xml_token_t XML_right_angled_axes = 1641;
+const xml_token_t XML_right_outside = 1642;
+const xml_token_t XML_rl = 1643;
+const xml_token_t XML_rl_tb = 1644;
+const xml_token_t XML_roll_from_bottom = 1645;
+const xml_token_t XML_roll_from_left = 1646;
+const xml_token_t XML_roll_from_right = 1647;
+const xml_token_t XML_roll_from_top = 1648;
+const xml_token_t XML_roman = 1649;
+const xml_token_t XML_rotate = 1650;
+const xml_token_t XML_rotation = 1651;
+const xml_token_t XML_rotation_align = 1652;
+const xml_token_t XML_rotation_angle = 1653;
+const xml_token_t XML_round = 1654;
+const xml_token_t XML_row = 1655;
+const xml_token_t XML_row_count = 1656;
+const xml_token_t XML_row_height = 1657;
+const xml_token_t XML_row_mapping = 1658;
+const xml_token_t XML_row_number = 1659;
+const xml_token_t XML_row_percentage = 1660;
+const xml_token_t XML_row_retrieving_statement = 1661;
+const xml_token_t XML_rows = 1662;
+const xml_token_t XML_ruby = 1663;
+const xml_token_t XML_ruby_align = 1664;
+const xml_token_t XML_ruby_base = 1665;
+const xml_token_t XML_ruby_position = 1666;
+const xml_token_t XML_ruby_properties = 1667;
+const xml_token_t XML_ruby_text = 1668;
+const xml_token_t XML_run_through = 1669;
+const xml_token_t XML_running_total = 1670;
+const xml_token_t XML_rx = 1671;
+const xml_token_t XML_ry = 1672;
+const xml_token_t XML_s = 1673;
+const xml_token_t XML_scale = 1674;
+const xml_token_t XML_scale_min = 1675;
+const xml_token_t XML_scale_text = 1676;
+const xml_token_t XML_scale_to = 1677;
+const xml_token_t XML_scale_to_X = 1678;
+const xml_token_t XML_scale_to_Y = 1679;
+const xml_token_t XML_scale_to_pages = 1680;
+const xml_token_t XML_scenario = 1681;
+const xml_token_t XML_scenario_ranges = 1682;
+const xml_token_t XML_scene = 1683;
+const xml_token_t XML_schema_definition = 1684;
+const xml_token_t XML_schema_name = 1685;
+const xml_token_t XML_school = 1686;
+const xml_token_t XML_scientific_number = 1687;
+const xml_token_t XML_screen = 1688;
+const xml_token_t XML_script = 1689;
+const xml_token_t XML_script_asian = 1690;
+const xml_token_t XML_script_complex = 1691;
+const xml_token_t XML_script_type = 1692;
+const xml_token_t XML_scripts = 1693;
+const xml_token_t XML_scroll = 1694;
+const xml_token_t XML_search_criteria_must_apply_to_whole_cell = 1695;
+const xml_token_t XML_secondary_fill_color = 1696;
+const xml_token_t XML_seconds = 1697;
+const xml_token_t XML_section = 1698;
+const xml_token_t XML_section_name = 1699;
+const xml_token_t XML_section_properties = 1700;
+const xml_token_t XML_section_source = 1701;
+const xml_token_t XML_segments = 1702;
+const xml_token_t XML_select_page = 1703;
+const xml_token_t XML_selected = 1704;
+const xml_token_t XML_selected_page = 1705;
+const xml_token_t XML_selection = 1706;
+const xml_token_t XML_selection_indices = 1707;
+const xml_token_t XML_self = 1708;
+const xml_token_t XML_semi_automatic = 1709;
+const xml_token_t XML_semi_condensed = 1710;
+const xml_token_t XML_semi_expanded = 1711;
+const xml_token_t XML_sender_city = 1712;
+const xml_token_t XML_sender_company = 1713;
+const xml_token_t XML_sender_country = 1714;
+const xml_token_t XML_sender_email = 1715;
+const xml_token_t XML_sender_fax = 1716;
+const xml_token_t XML_sender_firstname = 1717;
+const xml_token_t XML_sender_initials = 1718;
+const xml_token_t XML_sender_lastname = 1719;
+const xml_token_t XML_sender_phone_private = 1720;
+const xml_token_t XML_sender_phone_work = 1721;
+const xml_token_t XML_sender_position = 1722;
+const xml_token_t XML_sender_postal_code = 1723;
+const xml_token_t XML_sender_state_or_province = 1724;
+const xml_token_t XML_sender_street = 1725;
+const xml_token_t XML_sender_title = 1726;
+const xml_token_t XML_sentence_count = 1727;
+const xml_token_t XML_separating = 1728;
+const xml_token_t XML_separation_character = 1729;
+const xml_token_t XML_separator = 1730;
+const xml_token_t XML_seq = 1731;
+const xml_token_t XML_sequence = 1732;
+const xml_token_t XML_sequence_decl = 1733;
+const xml_token_t XML_sequence_decls = 1734;
+const xml_token_t XML_sequence_ref = 1735;
+const xml_token_t XML_series = 1736;
+const xml_token_t XML_series_source = 1737;
+const xml_token_t XML_server_database = 1738;
+const xml_token_t XML_server_map = 1739;
+const xml_token_t XML_set = 1740;
+const xml_token_t XML_set_default = 1741;
+const xml_token_t XML_set_null = 1742;
+const xml_token_t XML_settings = 1743;
+const xml_token_t XML_shade_mode = 1744;
+const xml_token_t XML_shadow = 1745;
+const xml_token_t XML_shadow_color = 1746;
+const xml_token_t XML_shadow_offset_x = 1747;
+const xml_token_t XML_shadow_offset_y = 1748;
+const xml_token_t XML_shadow_opacity = 1749;
+const xml_token_t XML_shadow_slant = 1750;
+const xml_token_t XML_shape = 1751;
+const xml_token_t XML_shape_id = 1752;
+const xml_token_t XML_shapes = 1753;
+const xml_token_t XML_sharpness = 1754;
+const xml_token_t XML_sheet_name = 1755;
+const xml_token_t XML_shininess = 1756;
+const xml_token_t XML_short = 1757;
+const xml_token_t XML_show = 1758;
+const xml_token_t XML_show_deleted = 1759;
+const xml_token_t XML_show_details = 1760;
+const xml_token_t XML_show_empty = 1761;
+const xml_token_t XML_show_end_of_presentation_slide = 1762;
+const xml_token_t XML_show_filter_button = 1763;
+const xml_token_t XML_show_logo = 1764;
+const xml_token_t XML_show_shape = 1765;
+const xml_token_t XML_show_text = 1766;
+const xml_token_t XML_show_unit = 1767;
+const xml_token_t XML_shrink_to_fit = 1768;
+const xml_token_t XML_side_by_side = 1769;
+const xml_token_t XML_simple = 1770;
+const xml_token_t XML_single = 1771;
+const xml_token_t XML_size = 1772;
+const xml_token_t XML_skewX = 1773;
+const xml_token_t XML_skewY = 1774;
+const xml_token_t XML_skip_white_space = 1775;
+const xml_token_t XML_slide = 1776;
+const xml_token_t XML_slope = 1777;
+const xml_token_t XML_slow = 1778;
+const xml_token_t XML_small_caps = 1779;
+const xml_token_t XML_smallint = 1780;
+const xml_token_t XML_smil = 1781;
+const xml_token_t XML_snap_to_layout_grid = 1782;
+const xml_token_t XML_soft_page_break = 1783;
+const xml_token_t XML_solid = 1784;
+const xml_token_t XML_solid_type = 1785;
+const xml_token_t XML_sort = 1786;
+const xml_token_t XML_sort_algorithm = 1787;
+const xml_token_t XML_sort_ascending = 1788;
+const xml_token_t XML_sort_by = 1789;
+const xml_token_t XML_sort_by_position = 1790;
+const xml_token_t XML_sort_by_x_values = 1791;
+const xml_token_t XML_sort_groups = 1792;
+const xml_token_t XML_sort_key = 1793;
+const xml_token_t XML_sort_mode = 1794;
+const xml_token_t XML_sound = 1795;
+const xml_token_t XML_source = 1796;
+const xml_token_t XML_source_cell_range = 1797;
+const xml_token_t XML_source_cell_range_addresses = 1798;
+const xml_token_t XML_source_field_name = 1799;
+const xml_token_t XML_source_name = 1800;
+const xml_token_t XML_source_range_address = 1801;
+const xml_token_t XML_source_service = 1802;
+const xml_token_t XML_space = 1803;
+const xml_token_t XML_space_after = 1804;
+const xml_token_t XML_space_before = 1805;
+const xml_token_t XML_span = 1806;
+const xml_token_t XML_specular = 1807;
+const xml_token_t XML_specular_color = 1808;
+const xml_token_t XML_speed = 1809;
+const xml_token_t XML_sphere = 1810;
+const xml_token_t XML_spin_button = 1811;
+const xml_token_t XML_spiral_inward_left = 1812;
+const xml_token_t XML_spiral_inward_right = 1813;
+const xml_token_t XML_spiral_outward_left = 1814;
+const xml_token_t XML_spiral_outward_right = 1815;
+const xml_token_t XML_spiralin_left = 1816;
+const xml_token_t XML_spiralin_right = 1817;
+const xml_token_t XML_spiralout_left = 1818;
+const xml_token_t XML_spiralout_right = 1819;
+const xml_token_t XML_spline = 1820;
+const xml_token_t XML_spline_order = 1821;
+const xml_token_t XML_spline_resolution = 1822;
+const xml_token_t XML_spreadMethod = 1823;
+const xml_token_t XML_spreadsheet = 1824;
+const xml_token_t XML_sql = 1825;
+const xml_token_t XML_sql_pass_through = 1826;
+const xml_token_t XML_sql_statement = 1827;
+const xml_token_t XML_sqlnull = 1828;
+const xml_token_t XML_square = 1829;
+const xml_token_t XML_stacked = 1830;
+const xml_token_t XML_stagger_even = 1831;
+const xml_token_t XML_stagger_odd = 1832;
+const xml_token_t XML_standard = 1833;
+const xml_token_t XML_standard_deviation = 1834;
+const xml_token_t XML_standard_error = 1835;
+const xml_token_t XML_star = 1836;
+const xml_token_t XML_start = 1837;
+const xml_token_t XML_start_angle = 1838;
+const xml_token_t XML_start_color = 1839;
+const xml_token_t XML_start_column = 1840;
+const xml_token_t XML_start_glue_point = 1841;
+const xml_token_t XML_start_guide = 1842;
+const xml_token_t XML_start_indent = 1843;
+const xml_token_t XML_start_intensity = 1844;
+const xml_token_t XML_start_line_spacing_horizontal = 1845;
+const xml_token_t XML_start_line_spacing_vertical = 1846;
+const xml_token_t XML_start_numbering_at = 1847;
+const xml_token_t XML_start_page = 1848;
+const xml_token_t XML_start_position = 1849;
+const xml_token_t XML_start_row = 1850;
+const xml_token_t XML_start_scale = 1851;
+const xml_token_t XML_start_shape = 1852;
+const xml_token_t XML_start_table = 1853;
+const xml_token_t XML_start_value = 1854;
+const xml_token_t XML_start_with_navigator = 1855;
+const xml_token_t XML_state = 1856;
+const xml_token_t XML_status = 1857;
+const xml_token_t XML_stay_on_top = 1858;
+const xml_token_t XML_stdev = 1859;
+const xml_token_t XML_stdevp = 1860;
+const xml_token_t XML_stemh = 1861;
+const xml_token_t XML_stemv = 1862;
+const xml_token_t XML_step = 1863;
+const xml_token_t XML_step_center_x = 1864;
+const xml_token_t XML_step_center_y = 1865;
+const xml_token_t XML_step_end = 1866;
+const xml_token_t XML_step_size = 1867;
+const xml_token_t XML_step_start = 1868;
+const xml_token_t XML_steps = 1869;
+const xml_token_t XML_stock_gain_marker = 1870;
+const xml_token_t XML_stock_loss_marker = 1871;
+const xml_token_t XML_stock_range_line = 1872;
+const xml_token_t XML_stop = 1873;
+const xml_token_t XML_stop_color = 1874;
+const xml_token_t XML_stop_opacity = 1875;
+const xml_token_t XML_straight_line = 1876;
+const xml_token_t XML_stretch = 1877;
+const xml_token_t XML_stretch_from_bottom = 1878;
+const xml_token_t XML_stretch_from_left = 1879;
+const xml_token_t XML_stretch_from_right = 1880;
+const xml_token_t XML_stretch_from_top = 1881;
+const xml_token_t XML_strict = 1882;
+const xml_token_t XML_strikethrough_position = 1883;
+const xml_token_t XML_strikethrough_thickness = 1884;
+const xml_token_t XML_string = 1885;
+const xml_token_t XML_string_value = 1886;
+const xml_token_t XML_string_value_if_false = 1887;
+const xml_token_t XML_string_value_if_true = 1888;
+const xml_token_t XML_string_value_phonetic = 1889;
+const xml_token_t XML_stripes = 1890;
+const xml_token_t XML_stroke = 1891;
+const xml_token_t XML_stroke_color = 1892;
+const xml_token_t XML_stroke_dash = 1893;
+const xml_token_t XML_stroke_dash_names = 1894;
+const xml_token_t XML_stroke_linecap = 1895;
+const xml_token_t XML_stroke_linejoin = 1896;
+const xml_token_t XML_stroke_opacity = 1897;
+const xml_token_t XML_stroke_width = 1898;
+const xml_token_t XML_struct = 1899;
+const xml_token_t XML_structure_protected = 1900;
+const xml_token_t XML_style = 1901;
+const xml_token_t XML_style_name = 1902;
+const xml_token_t XML_style_override = 1903;
+const xml_token_t XML_styles = 1904;
+const xml_token_t XML_sub = 1905;
+const xml_token_t XML_sub_item = 1906;
+const xml_token_t XML_subject = 1907;
+const xml_token_t XML_submit = 1908;
+const xml_token_t XML_subtitle = 1909;
+const xml_token_t XML_subtotal_field = 1910;
+const xml_token_t XML_subtotal_rule = 1911;
+const xml_token_t XML_subtotal_rules = 1912;
+const xml_token_t XML_subtype = 1913;
+const xml_token_t XML_suffix = 1914;
+const xml_token_t XML_sum = 1915;
+const xml_token_t XML_super = 1916;
+const xml_token_t XML_suppress_version_columns = 1917;
+const xml_token_t XML_svg = 1918;
+const xml_token_t XML_swiss = 1919;
+const xml_token_t XML_syllable_count = 1920;
+const xml_token_t XML_symbol_color = 1921;
+const xml_token_t XML_symbol_height = 1922;
+const xml_token_t XML_symbol_image = 1923;
+const xml_token_t XML_symbol_name = 1924;
+const xml_token_t XML_symbol_type = 1925;
+const xml_token_t XML_symbol_width = 1926;
+const xml_token_t XML_system = 1927;
+const xml_token_t XML_system_driver_settings = 1928;
+const xml_token_t XML_tab = 1929;
+const xml_token_t XML_tab_color = 1930;
+const xml_token_t XML_tab_cycle = 1931;
+const xml_token_t XML_tab_index = 1932;
+const xml_token_t XML_tab_ref = 1933;
+const xml_token_t XML_tab_stop = 1934;
+const xml_token_t XML_tab_stop_distance = 1935;
+const xml_token_t XML_tab_stops = 1936;
+const xml_token_t XML_table = 1937;
+const xml_token_t XML_table_background = 1938;
+const xml_token_t XML_table_cell = 1939;
+const xml_token_t XML_table_cell_properties = 1940;
+const xml_token_t XML_table_centering = 1941;
+const xml_token_t XML_table_column = 1942;
+const xml_token_t XML_table_column_group = 1943;
+const xml_token_t XML_table_column_properties = 1944;
+const xml_token_t XML_table_columns = 1945;
+const xml_token_t XML_table_count = 1946;
+const xml_token_t XML_table_definition = 1947;
+const xml_token_t XML_table_definitions = 1948;
+const xml_token_t XML_table_exclude_filter = 1949;
+const xml_token_t XML_table_fields = 1950;
+const xml_token_t XML_table_filter = 1951;
+const xml_token_t XML_table_filter_pattern = 1952;
+const xml_token_t XML_table_formula = 1953;
+const xml_token_t XML_table_header_columns = 1954;
+const xml_token_t XML_table_header_rows = 1955;
+const xml_token_t XML_table_include_filter = 1956;
+const xml_token_t XML_table_index = 1957;
+const xml_token_t XML_table_index_entry_template = 1958;
+const xml_token_t XML_table_index_source = 1959;
+const xml_token_t XML_table_name = 1960;
+const xml_token_t XML_table_of_content = 1961;
+const xml_token_t XML_table_of_content_entry_template = 1962;
+const xml_token_t XML_table_of_content_source = 1963;
+const xml_token_t XML_table_properties = 1964;
+const xml_token_t XML_table_representation = 1965;
+const xml_token_t XML_table_representations = 1966;
+const xml_token_t XML_table_row = 1967;
+const xml_token_t XML_table_row_group = 1968;
+const xml_token_t XML_table_row_properties = 1969;
+const xml_token_t XML_table_rows = 1970;
+const xml_token_t XML_table_setting = 1971;
+const xml_token_t XML_table_settings = 1972;
+const xml_token_t XML_table_source = 1973;
+const xml_token_t XML_table_template = 1974;
+const xml_token_t XML_table_type = 1975;
+const xml_token_t XML_table_type_filter = 1976;
+const xml_token_t XML_tabular_layout = 1977;
+const xml_token_t XML_target_cell_address = 1978;
+const xml_token_t XML_target_frame = 1979;
+const xml_token_t XML_target_frame_name = 1980;
+const xml_token_t XML_target_range_address = 1981;
+const xml_token_t XML_targetElement = 1982;
+const xml_token_t XML_tb = 1983;
+const xml_token_t XML_tb_lr = 1984;
+const xml_token_t XML_tb_rl = 1985;
+const xml_token_t XML_techreport = 1986;
+const xml_token_t XML_template = 1987;
+const xml_token_t XML_template_name = 1988;
+const xml_token_t XML_text = 1989;
+const xml_token_t XML_text_align = 1990;
+const xml_token_t XML_text_align_last = 1991;
+const xml_token_t XML_text_align_source = 1992;
+const xml_token_t XML_text_areas = 1993;
+const xml_token_t XML_text_autospace = 1994;
+const xml_token_t XML_text_blinking = 1995;
+const xml_token_t XML_text_box = 1996;
+const xml_token_t XML_text_combine = 1997;
+const xml_token_t XML_text_combine_end_char = 1998;
+const xml_token_t XML_text_combine_start_char = 1999;
+const xml_token_t XML_text_content = 2000;
+const xml_token_t XML_text_emphasize = 2001;
+const xml_token_t XML_text_indent = 2002;
+const xml_token_t XML_text_input = 2003;
+const xml_token_t XML_text_line_through_color = 2004;
+const xml_token_t XML_text_line_through_mode = 2005;
+const xml_token_t XML_text_line_through_style = 2006;
+const xml_token_t XML_text_line_through_text = 2007;
+const xml_token_t XML_text_line_through_text_style = 2008;
+const xml_token_t XML_text_line_through_type = 2009;
+const xml_token_t XML_text_line_through_width = 2010;
+const xml_token_t XML_text_outline = 2011;
+const xml_token_t XML_text_overlap = 2012;
+const xml_token_t XML_text_overline_color = 2013;
+const xml_token_t XML_text_overline_mode = 2014;
+const xml_token_t XML_text_overline_style = 2015;
+const xml_token_t XML_text_overline_type = 2016;
+const xml_token_t XML_text_overline_width = 2017;
+const xml_token_t XML_text_path = 2018;
+const xml_token_t XML_text_path_allowed = 2019;
+const xml_token_t XML_text_path_mode = 2020;
+const xml_token_t XML_text_path_same_letter_heights = 2021;
+const xml_token_t XML_text_path_scale = 2022;
+const xml_token_t XML_text_position = 2023;
+const xml_token_t XML_text_properties = 2024;
+const xml_token_t XML_text_rotate_angle = 2025;
+const xml_token_t XML_text_rotation_angle = 2026;
+const xml_token_t XML_text_rotation_scale = 2027;
+const xml_token_t XML_text_scale = 2028;
+const xml_token_t XML_text_shadow = 2029;
+const xml_token_t XML_text_style = 2030;
+const xml_token_t XML_text_style_name = 2031;
+const xml_token_t XML_text_transform = 2032;
+const xml_token_t XML_text_underline_color = 2033;
+const xml_token_t XML_text_underline_mode = 2034;
+const xml_token_t XML_text_underline_style = 2035;
+const xml_token_t XML_text_underline_type = 2036;
+const xml_token_t XML_text_underline_width = 2037;
+const xml_token_t XML_textarea = 2038;
+const xml_token_t XML_textarea_horizontal_align = 2039;
+const xml_token_t XML_textarea_vertical_align = 2040;
+const xml_token_t XML_textual = 2041;
+const xml_token_t XML_texture_filter = 2042;
+const xml_token_t XML_texture_generation_mode_x = 2043;
+const xml_token_t XML_texture_generation_mode_y = 2044;
+const xml_token_t XML_texture_kind = 2045;
+const xml_token_t XML_texture_mode = 2046;
+const xml_token_t XML_thick = 2047;
+const xml_token_t XML_thin = 2048;
+const xml_token_t XML_thousand = 2049;
+const xml_token_t XML_three_dimensional = 2050;
+const xml_token_t XML_thumbnail = 2051;
+const xml_token_t XML_tick_mark_position = 2052;
+const xml_token_t XML_tick_marks_major_inner = 2053;
+const xml_token_t XML_tick_marks_major_outer = 2054;
+const xml_token_t XML_tick_marks_minor_inner = 2055;
+const xml_token_t XML_tick_marks_minor_outer = 2056;
+const xml_token_t XML_tile_repeat_offset = 2057;
+const xml_token_t XML_time = 2058;
+const xml_token_t XML_time_adjust = 2059;
+const xml_token_t XML_time_style = 2060;
+const xml_token_t XML_time_value = 2061;
+const xml_token_t XML_timestmp = 2062;
+const xml_token_t XML_timing_root = 2063;
+const xml_token_t XML_tinyint = 2064;
+const xml_token_t XML_title = 2065;
+const xml_token_t XML_to = 2066;
+const xml_token_t XML_to_another_table = 2067;
+const xml_token_t XML_to_bottom = 2068;
+const xml_token_t XML_to_center = 2069;
+const xml_token_t XML_to_left = 2070;
+const xml_token_t XML_to_lower_left = 2071;
+const xml_token_t XML_to_lower_right = 2072;
+const xml_token_t XML_to_right = 2073;
+const xml_token_t XML_to_top = 2074;
+const xml_token_t XML_to_upper_left = 2075;
+const xml_token_t XML_to_upper_right = 2076;
+const xml_token_t XML_toc_mark = 2077;
+const xml_token_t XML_toc_mark_end = 2078;
+const xml_token_t XML_toc_mark_start = 2079;
+const xml_token_t XML_toggle = 2080;
+const xml_token_t XML_top = 2081;
+const xml_token_t XML_top_end = 2082;
+const xml_token_t XML_top_left = 2083;
+const xml_token_t XML_top_right = 2084;
+const xml_token_t XML_top_start = 2085;
+const xml_token_t XML_total_percentage = 2086;
+const xml_token_t XML_trace_dependents = 2087;
+const xml_token_t XML_trace_errors = 2088;
+const xml_token_t XML_trace_precedents = 2089;
+const xml_token_t XML_track_changes = 2090;
+const xml_token_t XML_tracked_changes = 2091;
+const xml_token_t XML_transform = 2092;
+const xml_token_t XML_transformation = 2093;
+const xml_token_t XML_transition = 2094;
+const xml_token_t XML_transition_on_click = 2095;
+const xml_token_t XML_transition_speed = 2096;
+const xml_token_t XML_transition_style = 2097;
+const xml_token_t XML_transition_type = 2098;
+const xml_token_t XML_transitionFilter = 2099;
+const xml_token_t XML_translate = 2100;
+const xml_token_t XML_transliteration_country = 2101;
+const xml_token_t XML_transliteration_format = 2102;
+const xml_token_t XML_transliteration_language = 2103;
+const xml_token_t XML_transliteration_style = 2104;
+const xml_token_t XML_transparent = 2105;
+const xml_token_t XML_treat_empty_cells = 2106;
+const xml_token_t XML_triple = 2107;
+const xml_token_t XML_true = 2108;
+const xml_token_t XML_truncate_on_overflow = 2109;
+const xml_token_t XML_ttb = 2110;
+const xml_token_t XML_type = 2111;
+const xml_token_t XML_type_name = 2112;
+const xml_token_t XML_ultra_condensed = 2113;
+const xml_token_t XML_ultra_expanded = 2114;
+const xml_token_t XML_unchecked = 2115;
+const xml_token_t XML_uncover_to_bottom = 2116;
+const xml_token_t XML_uncover_to_left = 2117;
+const xml_token_t XML_uncover_to_lowerleft = 2118;
+const xml_token_t XML_uncover_to_lowerright = 2119;
+const xml_token_t XML_uncover_to_right = 2120;
+const xml_token_t XML_uncover_to_top = 2121;
+const xml_token_t XML_uncover_to_upperleft = 2122;
+const xml_token_t XML_uncover_to_upperright = 2123;
+const xml_token_t XML_underline_position = 2124;
+const xml_token_t XML_underline_thickness = 2125;
+const xml_token_t XML_unicode_range = 2126;
+const xml_token_t XML_unique = 2127;
+const xml_token_t XML_unit = 2128;
+const xml_token_t XML_units_per_em = 2129;
+const xml_token_t XML_unknown = 2130;
+const xml_token_t XML_unpublished = 2131;
+const xml_token_t XML_unsorted = 2132;
+const xml_token_t XML_up = 2133;
+const xml_token_t XML_update_rule = 2134;
+const xml_token_t XML_update_table = 2135;
+const xml_token_t XML_uppercase = 2136;
+const xml_token_t XML_url = 2137;
+const xml_token_t XML_use_banding_columns_styles = 2138;
+const xml_token_t XML_use_banding_rows_styles = 2139;
+const xml_token_t XML_use_caption = 2140;
+const xml_token_t XML_use_catalog = 2141;
+const xml_token_t XML_use_chart_objects = 2142;
+const xml_token_t XML_use_date_time_name = 2143;
+const xml_token_t XML_use_draw_objects = 2144;
+const xml_token_t XML_use_first_column_styles = 2145;
+const xml_token_t XML_use_first_row_styles = 2146;
+const xml_token_t XML_use_floating_frames = 2147;
+const xml_token_t XML_use_footer_name = 2148;
+const xml_token_t XML_use_graphics = 2149;
+const xml_token_t XML_use_header_name = 2150;
+const xml_token_t XML_use_index_marks = 2151;
+const xml_token_t XML_use_index_source_styles = 2152;
+const xml_token_t XML_use_keys_as_entries = 2153;
+const xml_token_t XML_use_labels = 2154;
+const xml_token_t XML_use_last_column_styles = 2155;
+const xml_token_t XML_use_last_row_styles = 2156;
+const xml_token_t XML_use_math_objects = 2157;
+const xml_token_t XML_use_objects = 2158;
+const xml_token_t XML_use_optimal_column_width = 2159;
+const xml_token_t XML_use_optimal_row_height = 2160;
+const xml_token_t XML_use_other_objects = 2161;
+const xml_token_t XML_use_outline_level = 2162;
+const xml_token_t XML_use_regular_expressions = 2163;
+const xml_token_t XML_use_soft_page_breaks = 2164;
+const xml_token_t XML_use_spreadsheet_objects = 2165;
+const xml_token_t XML_use_system_user = 2166;
+const xml_token_t XML_use_tables = 2167;
+const xml_token_t XML_use_wildcards = 2168;
+const xml_token_t XML_use_window_font_color = 2169;
+const xml_token_t XML_use_zero = 2170;
+const xml_token_t XML_used_hierarchy = 2171;
+const xml_token_t XML_user_defined = 2172;
+const xml_token_t XML_user_field_decl = 2173;
+const xml_token_t XML_user_field_decls = 2174;
+const xml_token_t XML_user_field_get = 2175;
+const xml_token_t XML_user_field_input = 2176;
+const xml_token_t XML_user_index = 2177;
+const xml_token_t XML_user_index_entry_template = 2178;
+const xml_token_t XML_user_index_mark = 2179;
+const xml_token_t XML_user_index_mark_end = 2180;
+const xml_token_t XML_user_index_mark_start = 2181;
+const xml_token_t XML_user_index_source = 2182;
+const xml_token_t XML_user_name = 2183;
+const xml_token_t XML_user_transformed = 2184;
+const xml_token_t XML_v_alphabetic = 2185;
+const xml_token_t XML_v_hanging = 2186;
+const xml_token_t XML_v_ideographic = 2187;
+const xml_token_t XML_v_mathematical = 2188;
+const xml_token_t XML_validation = 2189;
+const xml_token_t XML_value = 2190;
+const xml_token_t XML_value_and_percentage = 2191;
+const xml_token_t XML_value_list = 2192;
+const xml_token_t XML_value_range = 2193;
+const xml_token_t XML_value_type = 2194;
+const xml_token_t XML_values = 2195;
+const xml_token_t XML_values_cell_range_address = 2196;
+const xml_token_t XML_var = 2197;
+const xml_token_t XML_varbinary = 2198;
+const xml_token_t XML_varchar = 2199;
+const xml_token_t XML_variable = 2200;
+const xml_token_t XML_variable_decl = 2201;
+const xml_token_t XML_variable_decls = 2202;
+const xml_token_t XML_variable_get = 2203;
+const xml_token_t XML_variable_input = 2204;
+const xml_token_t XML_variable_set = 2205;
+const xml_token_t XML_variance = 2206;
+const xml_token_t XML_varp = 2207;
+const xml_token_t XML_verb = 2208;
+const xml_token_t XML_version = 2209;
+const xml_token_t XML_vertical = 2210;
+const xml_token_t XML_vertical_align = 2211;
+const xml_token_t XML_vertical_bar = 2212;
+const xml_token_t XML_vertical_checkerboard = 2213;
+const xml_token_t XML_vertical_lines = 2214;
+const xml_token_t XML_vertical_pos = 2215;
+const xml_token_t XML_vertical_rel = 2216;
+const xml_token_t XML_vertical_segments = 2217;
+const xml_token_t XML_vertical_stripes = 2218;
+const xml_token_t XML_viewBox = 2219;
+const xml_token_t XML_visibility = 2220;
+const xml_token_t XML_visible = 2221;
+const xml_token_t XML_visible_area_height = 2222;
+const xml_token_t XML_visible_area_left = 2223;
+const xml_token_t XML_visible_area_top = 2224;
+const xml_token_t XML_visible_area_width = 2225;
+const xml_token_t XML_visited_style_name = 2226;
+const xml_token_t XML_visual_effect = 2227;
+const xml_token_t XML_void = 2228;
+const xml_token_t XML_volatile = 2229;
+const xml_token_t XML_volume = 2230;
+const xml_token_t XML_vpn = 2231;
+const xml_token_t XML_vrp = 2232;
+const xml_token_t XML_vup = 2233;
+const xml_token_t XML_wall = 2234;
+const xml_token_t XML_warning = 2235;
+const xml_token_t XML_watermark = 2236;
+const xml_token_t XML_wave = 2237;
+const xml_token_t XML_wavyline = 2238;
+const xml_token_t XML_wavyline_from_bottom = 2239;
+const xml_token_t XML_wavyline_from_left = 2240;
+const xml_token_t XML_wavyline_from_right = 2241;
+const xml_token_t XML_wavyline_from_top = 2242;
+const xml_token_t XML_week_of_year = 2243;
+const xml_token_t XML_whenNotActive = 2244;
+const xml_token_t XML_wide = 2245;
+const xml_token_t XML_widows = 2246;
+const xml_token_t XML_width = 2247;
+const xml_token_t XML_widths = 2248;
+const xml_token_t XML_with_previous = 2249;
+const xml_token_t XML_word = 2250;
+const xml_token_t XML_word_count = 2251;
+const xml_token_t XML_wrap = 2252;
+const xml_token_t XML_wrap_contour = 2253;
+const xml_token_t XML_wrap_contour_mode = 2254;
+const xml_token_t XML_wrap_dynamic_threshold = 2255;
+const xml_token_t XML_wrap_influence_on_position = 2256;
+const xml_token_t XML_wrap_option = 2257;
+const xml_token_t XML_writing_mode = 2258;
+const xml_token_t XML_writing_mode_automatic = 2259;
+const xml_token_t XML_www = 2260;
+const xml_token_t XML_x = 2261;
+const xml_token_t XML_x_height = 2262;
+const xml_token_t XML_x1 = 2263;
+const xml_token_t XML_x2 = 2264;
+const xml_token_t XML_xforms = 2265;
+const xml_token_t XML_xforms_list_source = 2266;
+const xml_token_t XML_xforms_submission = 2267;
+const xml_token_t XML_xhtml = 2268;
+const xml_token_t XML_xlink = 2269;
+const xml_token_t XML_xml = 2270;
+const xml_token_t XML_y = 2271;
+const xml_token_t XML_y1 = 2272;
+const xml_token_t XML_y2 = 2273;
+const xml_token_t XML_year = 2274;
+const xml_token_t XML_years = 2275;
+const xml_token_t XML_z = 2276;
+const xml_token_t XML_z_index = 2277;
+const xml_token_t XML_zero_values = 2278;
diff --git a/src/liborcus/odf_tokens.cpp b/src/liborcus/odf_tokens.cpp
new file mode 100644
index 0000000..b20414d
--- /dev/null
+++ b/src/liborcus/odf_tokens.cpp
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "odf_tokens.hpp"
+
+namespace orcus {
+
+namespace {
+
+#include "odf_tokens.inl"
+
+}
+
+tokens odf_tokens = tokens(token_names, token_name_count);
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_tokens.hpp b/src/liborcus/odf_tokens.hpp
new file mode 100644
index 0000000..db1befa
--- /dev/null
+++ b/src/liborcus/odf_tokens.hpp
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_ODF_TOKENS_HPP__
+#define __ORCUS_ODF_TOKENS_HPP__
+
+#include "orcus/tokens.hpp"
+
+namespace orcus {
+
+/**
+ * Singleton instance containing all ODF tokens.
+ */
+extern tokens odf_tokens;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/odf_tokens.inl b/src/liborcus/odf_tokens.inl
new file mode 100644
index 0000000..623c721
--- /dev/null
+++ b/src/liborcus/odf_tokens.inl
@@ -0,0 +1,2285 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const char* token_names[] = {
+ "??", // 0
+ "0", // 1
+ "0deg", // 2
+ "0grad", // 3
+ "0rad", // 4
+ "1", // 5
+ "1.3", // 6
+ "100", // 7
+ "2", // 8
+ "200", // 9
+ "3", // 10
+ "300", // 11
+ "3d", // 12
+ "400", // 13
+ "500", // 14
+ "600", // 15
+ "700", // 16
+ "800", // 17
+ "900", // 18
+ "A", // 19
+ "I", // 20
+ "ROC", // 21
+ "_blank", // 22
+ "_parent", // 23
+ "_self", // 24
+ "_top", // 25
+ "a", // 26
+ "about", // 27
+ "above", // 28
+ "accelerate", // 29
+ "accent", // 30
+ "accent-height", // 31
+ "acceptance-state", // 32
+ "accepted", // 33
+ "accumulate", // 34
+ "action", // 35
+ "active", // 36
+ "actuate", // 37
+ "add-empty-lines", // 38
+ "additional-column-statement", // 39
+ "additive", // 40
+ "address", // 41
+ "adjustment", // 42
+ "after-previous", // 43
+ "algorithm", // 44
+ "align", // 45
+ "all", // 46
+ "allow-deletes", // 47
+ "allow-empty-cell", // 48
+ "allow-inserts", // 49
+ "allow-updates", // 50
+ "alpha-numeric", // 51
+ "alphabetic", // 52
+ "alphabetical-index", // 53
+ "alphabetical-index-auto-mark-file", // 54
+ "alphabetical-index-entry-template", // 55
+ "alphabetical-index-mark", // 56
+ "alphabetical-index-mark-end", // 57
+ "alphabetical-index-mark-start", // 58
+ "alphabetical-index-source", // 59
+ "alphabetical-separators", // 60
+ "alternate", // 61
+ "always", // 62
+ "am-pm", // 63
+ "ambient-color", // 64
+ "anchor-page-number", // 65
+ "anchor-type", // 66
+ "angle", // 67
+ "angle-offset", // 68
+ "angled-connector-line", // 69
+ "angled-line", // 70
+ "anim", // 71
+ "animate", // 72
+ "animateColor", // 73
+ "animateMotion", // 74
+ "animateTransform", // 75
+ "animation", // 76
+ "animation-delay", // 77
+ "animation-direction", // 78
+ "animation-group", // 79
+ "animation-repeat", // 80
+ "animation-start-inside", // 81
+ "animation-steps", // 82
+ "animation-stop-inside", // 83
+ "animations", // 84
+ "annotation", // 85
+ "annotation-end", // 86
+ "annotations", // 87
+ "annote", // 88
+ "appear", // 89
+ "append-table-alias-name", // 90
+ "applet", // 91
+ "application-connection-settings", // 92
+ "application-data", // 93
+ "apply-command", // 94
+ "apply-design-mode", // 95
+ "apply-filter", // 96
+ "apply-style-name", // 97
+ "arc", // 98
+ "archive", // 99
+ "area", // 100
+ "area-circle", // 101
+ "area-polygon", // 102
+ "area-rectangle", // 103
+ "array", // 104
+ "arrow-down", // 105
+ "arrow-left", // 106
+ "arrow-right", // 107
+ "arrow-up", // 108
+ "article", // 109
+ "as-char", // 110
+ "as-template", // 111
+ "ascending", // 112
+ "ascent", // 113
+ "asian", // 114
+ "asterisk", // 115
+ "at-axis", // 116
+ "at-labels", // 117
+ "at-labels-and-axis", // 118
+ "attached-axis", // 119
+ "attractive", // 120
+ "attributeName", // 121
+ "audio", // 122
+ "audio-level", // 123
+ "author", // 124
+ "author-initials", // 125
+ "author-name", // 126
+ "auto", // 127
+ "auto-complete", // 128
+ "auto-create-new-frame", // 129
+ "auto-grow-height", // 130
+ "auto-grow-width", // 131
+ "auto-increment", // 132
+ "auto-position", // 133
+ "auto-reload", // 134
+ "auto-size", // 135
+ "auto-text-indent", // 136
+ "auto-update", // 137
+ "autoReverse", // 138
+ "automatic", // 139
+ "automatic-content", // 140
+ "automatic-find-labels", // 141
+ "automatic-focus", // 142
+ "automatic-order", // 143
+ "automatic-styles", // 144
+ "automatic-update", // 145
+ "average", // 146
+ "averaged-abscissa", // 147
+ "avoid-overlap", // 148
+ "axial", // 149
+ "axis", // 150
+ "axis-label-position", // 151
+ "axis-position", // 152
+ "b-spline", // 153
+ "back-scale", // 154
+ "backface-culling", // 155
+ "background", // 156
+ "background-color", // 157
+ "background-image", // 158
+ "background-objects-visible", // 159
+ "background-size", // 160
+ "background-transparency", // 161
+ "background-visible", // 162
+ "balanced", // 163
+ "base-cell-address", // 164
+ "base-dn", // 165
+ "base64Binary", // 166
+ "baseline", // 167
+ "bbox", // 168
+ "begin", // 169
+ "below", // 170
+ "bevel", // 171
+ "bibliography", // 172
+ "bibliography-configuration", // 173
+ "bibliography-data-field", // 174
+ "bibliography-entry-template", // 175
+ "bibliography-mark", // 176
+ "bibliography-source", // 177
+ "bibliography-type", // 178
+ "biggest", // 179
+ "bigint", // 180
+ "binary", // 181
+ "binary-data", // 182
+ "bind", // 183
+ "bind-styles-to-content", // 184
+ "bit", // 185
+ "bitmap", // 186
+ "blend", // 187
+ "blob", // 188
+ "blue", // 189
+ "body", // 190
+ "bold", // 191
+ "book", // 192
+ "booklet", // 193
+ "bookmark", // 194
+ "bookmark-end", // 195
+ "bookmark-start", // 196
+ "booktitle", // 197
+ "boolean", // 198
+ "boolean-comparison-mode", // 199
+ "boolean-style", // 200
+ "boolean-value", // 201
+ "border", // 202
+ "border-bottom", // 203
+ "border-color", // 204
+ "border-left", // 205
+ "border-line-width", // 206
+ "border-line-width-bottom", // 207
+ "border-line-width-left", // 208
+ "border-line-width-right", // 209
+ "border-line-width-top", // 210
+ "border-model", // 211
+ "border-right", // 212
+ "border-top", // 213
+ "both", // 214
+ "bottom", // 215
+ "bottom-end", // 216
+ "bottom-left", // 217
+ "bottom-right", // 218
+ "bottom-start", // 219
+ "bound-column", // 220
+ "bow-tie", // 221
+ "break-after", // 222
+ "break-before", // 223
+ "buddhist", // 224
+ "bullet-char", // 225
+ "bullet-relative-size", // 226
+ "butt", // 227
+ "button", // 228
+ "button-type", // 229
+ "buttons", // 230
+ "by", // 231
+ "c", // 232
+ "calcMode", // 233
+ "calculation-settings", // 234
+ "calendar", // 235
+ "cap-height", // 236
+ "capitalize", // 237
+ "capitalize-entries", // 238
+ "caption", // 239
+ "caption-angle", // 240
+ "caption-angle-type", // 241
+ "caption-escape", // 242
+ "caption-escape-direction", // 243
+ "caption-fit-line-length", // 244
+ "caption-gap", // 245
+ "caption-id", // 246
+ "caption-line-length", // 247
+ "caption-point-x", // 248
+ "caption-point-y", // 249
+ "caption-sequence-format", // 250
+ "caption-sequence-name", // 251
+ "caption-type", // 252
+ "cascade", // 253
+ "case-sensitive", // 254
+ "catalog-name", // 255
+ "categories", // 256
+ "category-and-value", // 257
+ "cell-address", // 258
+ "cell-content-change", // 259
+ "cell-content-deletion", // 260
+ "cell-count", // 261
+ "cell-protect", // 262
+ "cell-range", // 263
+ "cell-range-address", // 264
+ "cell-range-source", // 265
+ "center", // 266
+ "central", // 267
+ "chain-next-name", // 268
+ "change", // 269
+ "change-deletion", // 270
+ "change-end", // 271
+ "change-id", // 272
+ "change-info", // 273
+ "change-start", // 274
+ "change-track-table-cell", // 275
+ "changed-region", // 276
+ "chapter", // 277
+ "char", // 278
+ "character-count", // 279
+ "character-set", // 280
+ "chart", // 281
+ "chart-properties", // 282
+ "charts", // 283
+ "checkbox", // 284
+ "checked", // 285
+ "checkerboard", // 286
+ "circle", // 287
+ "citation-body-style-name", // 288
+ "citation-style-name", // 289
+ "class", // 290
+ "class-id", // 291
+ "class-names", // 292
+ "clip", // 293
+ "clob", // 294
+ "clockwise", // 295
+ "close", // 296
+ "close-back", // 297
+ "close-front", // 298
+ "close-horizontal", // 299
+ "close-vertical", // 300
+ "cm", // 301
+ "code", // 302
+ "collapse", // 303
+ "collapsing", // 304
+ "color", // 305
+ "color-interpolation", // 306
+ "color-interpolation-direction", // 307
+ "color-inversion", // 308
+ "color-mode", // 309
+ "column", // 310
+ "column-count", // 311
+ "column-definition", // 312
+ "column-definitions", // 313
+ "column-gap", // 314
+ "column-mapping", // 315
+ "column-name", // 316
+ "column-percentage", // 317
+ "column-sep", // 318
+ "column-width", // 319
+ "columns", // 320
+ "combine-entries", // 321
+ "combine-entries-with-dash", // 322
+ "combine-entries-with-pp", // 323
+ "combobox", // 324
+ "comma-separated", // 325
+ "command", // 326
+ "command-type", // 327
+ "comment", // 328
+ "complex", // 329
+ "component", // 330
+ "component-collection", // 331
+ "concave", // 332
+ "concentric-gradient-fill-allowed", // 333
+ "cond-style-name", // 334
+ "condensed", // 335
+ "condition", // 336
+ "condition-source", // 337
+ "condition-source-range-address", // 338
+ "conditional-text", // 339
+ "cone", // 340
+ "conference", // 341
+ "config", // 342
+ "config-item", // 343
+ "config-item-map-entry", // 344
+ "config-item-map-indexed", // 345
+ "config-item-map-named", // 346
+ "config-item-set", // 347
+ "connect-bars", // 348
+ "connection-data", // 349
+ "connection-name", // 350
+ "connection-resource", // 351
+ "connector", // 352
+ "consecutive-numbering", // 353
+ "consolidation", // 354
+ "constant", // 355
+ "contains-error", // 356
+ "contains-header", // 357
+ "content", // 358
+ "content-validation", // 359
+ "content-validation-name", // 360
+ "content-validations", // 361
+ "contextual-spacing", // 362
+ "continue", // 363
+ "continue-list", // 364
+ "continue-numbering", // 365
+ "continuous", // 366
+ "contour-path", // 367
+ "contour-polygon", // 368
+ "contrast", // 369
+ "control", // 370
+ "control-implementation", // 371
+ "conversion-mode", // 372
+ "convert-empty-to-null", // 373
+ "coordinate-region", // 374
+ "copy-all", // 375
+ "copy-back", // 376
+ "copy-formulas", // 377
+ "copy-of", // 378
+ "copy-outline-levels", // 379
+ "copy-results-only", // 380
+ "copy-styles", // 381
+ "corner-radius", // 382
+ "corners", // 383
+ "correct", // 384
+ "count", // 385
+ "count-empty-lines", // 386
+ "count-in-text-boxes", // 387
+ "counter-clockwise", // 388
+ "counterclockwise", // 389
+ "countnums", // 390
+ "country", // 391
+ "country-asian", // 392
+ "country-complex", // 393
+ "covered-table-cell", // 394
+ "creation-date", // 395
+ "creation-time", // 396
+ "creator", // 397
+ "creator-initials", // 398
+ "cube", // 399
+ "cubic-spline", // 400
+ "cuboid", // 401
+ "currency", // 402
+ "currency-style", // 403
+ "currency-symbol", // 404
+ "current", // 405
+ "current-date", // 406
+ "current-selected", // 407
+ "current-state", // 408
+ "current-value", // 409
+ "curve", // 410
+ "custom", // 411
+ "custom-shape", // 412
+ "custom1", // 413
+ "custom2", // 414
+ "custom3", // 415
+ "custom4", // 416
+ "custom5", // 417
+ "cut", // 418
+ "cut-offs", // 419
+ "cx", // 420
+ "cy", // 421
+ "cylinder", // 422
+ "d", // 423
+ "dash", // 424
+ "dashed", // 425
+ "data", // 426
+ "data-cell-range-address", // 427
+ "data-field", // 428
+ "data-label", // 429
+ "data-label-number", // 430
+ "data-label-series", // 431
+ "data-label-symbol", // 432
+ "data-label-text", // 433
+ "data-pilot-display-info", // 434
+ "data-pilot-field", // 435
+ "data-pilot-field-reference", // 436
+ "data-pilot-group", // 437
+ "data-pilot-group-member", // 438
+ "data-pilot-groups", // 439
+ "data-pilot-layout-info", // 440
+ "data-pilot-level", // 441
+ "data-pilot-member", // 442
+ "data-pilot-members", // 443
+ "data-pilot-sort-info", // 444
+ "data-pilot-subtotal", // 445
+ "data-pilot-subtotals", // 446
+ "data-pilot-table", // 447
+ "data-pilot-tables", // 448
+ "data-point", // 449
+ "data-source", // 450
+ "data-source-has-labels", // 451
+ "data-source-setting", // 452
+ "data-source-setting-is-list", // 453
+ "data-source-setting-name", // 454
+ "data-source-setting-type", // 455
+ "data-source-setting-value", // 456
+ "data-source-settings", // 457
+ "data-style-name", // 458
+ "data-type", // 459
+ "database", // 460
+ "database-description", // 461
+ "database-display", // 462
+ "database-name", // 463
+ "database-next", // 464
+ "database-range", // 465
+ "database-ranges", // 466
+ "database-row-number", // 467
+ "database-row-select", // 468
+ "database-source-query", // 469
+ "database-source-sql", // 470
+ "database-source-table", // 471
+ "database-table-name", // 472
+ "datasource", // 473
+ "datatype", // 474
+ "date", // 475
+ "date-adjust", // 476
+ "date-end", // 477
+ "date-start", // 478
+ "date-string", // 479
+ "date-style", // 480
+ "date-time", // 481
+ "date-time-decl", // 482
+ "date-value", // 483
+ "datetime", // 484
+ "day", // 485
+ "day-of-week", // 486
+ "days", // 487
+ "db", // 488
+ "dc", // 489
+ "dde-application", // 490
+ "dde-connection", // 491
+ "dde-connection-decl", // 492
+ "dde-connection-decls", // 493
+ "dde-item", // 494
+ "dde-link", // 495
+ "dde-links", // 496
+ "dde-source", // 497
+ "dde-topic", // 498
+ "decelerate", // 499
+ "decimal", // 500
+ "decimal-places", // 501
+ "decimal-replacement", // 502
+ "decorative", // 503
+ "deep", // 504
+ "default", // 505
+ "default-button", // 506
+ "default-cell-style-name", // 507
+ "default-outline-level", // 508
+ "default-page-layout", // 509
+ "default-row-style-name", // 510
+ "default-style", // 511
+ "default-style-name", // 512
+ "definition-src", // 513
+ "delay", // 514
+ "delay-for-repeat", // 515
+ "delete-rule", // 516
+ "deletion", // 517
+ "deletions", // 518
+ "delimiter", // 519
+ "denominator-value", // 520
+ "dependencies", // 521
+ "dependency", // 522
+ "depth", // 523
+ "desc", // 524
+ "descending", // 525
+ "descent", // 526
+ "description", // 527
+ "detail-fields", // 528
+ "detective", // 529
+ "diagonal-bl-tr", // 530
+ "diagonal-bl-tr-widths", // 531
+ "diagonal-tl-br", // 532
+ "diagonal-tl-br-widths", // 533
+ "diamond", // 534
+ "diffuse-color", // 535
+ "dim", // 536
+ "dimension", // 537
+ "direction", // 538
+ "disable", // 539
+ "disabled", // 540
+ "disc", // 541
+ "discrete", // 542
+ "display", // 543
+ "display-border", // 544
+ "display-date-time", // 545
+ "display-duplicates", // 546
+ "display-equation", // 547
+ "display-factor", // 548
+ "display-filter-buttons", // 549
+ "display-footer", // 550
+ "display-header", // 551
+ "display-label", // 552
+ "display-levels", // 553
+ "display-list", // 554
+ "display-member-mode", // 555
+ "display-name", // 556
+ "display-outline-level", // 557
+ "display-page-number", // 558
+ "display-r-square", // 559
+ "dissolve", // 560
+ "distance", // 561
+ "distance-after-sep", // 562
+ "distance-before-sep", // 563
+ "distinct", // 564
+ "distribute-letter", // 565
+ "distribute-space", // 566
+ "document", // 567
+ "document-content", // 568
+ "document-meta", // 569
+ "document-settings", // 570
+ "document-statistic", // 571
+ "document-styles", // 572
+ "domain", // 573
+ "dont-balance-text-columns", // 574
+ "dot", // 575
+ "dot-dash", // 576
+ "dot-dashed", // 577
+ "dot-dot-dash", // 578
+ "dots1", // 579
+ "dots1-length", // 580
+ "dots2", // 581
+ "dots2-length", // 582
+ "dotted", // 583
+ "double", // 584
+ "double-sided", // 585
+ "down", // 586
+ "dr3d", // 587
+ "draft", // 588
+ "draw", // 589
+ "draw-aspect", // 590
+ "draw-count", // 591
+ "drawing", // 592
+ "drawing-page", // 593
+ "drawing-page-properties", // 594
+ "drawings", // 595
+ "drill-down-on-double-click", // 596
+ "driver-settings", // 597
+ "drop-cap", // 598
+ "drop-down", // 599
+ "dropdown", // 600
+ "dur", // 601
+ "duration", // 602
+ "dynamic", // 603
+ "dynamic-spacing", // 604
+ "echo-char", // 605
+ "edge-rounding", // 606
+ "edge-rounding-mode", // 607
+ "editable", // 608
+ "editing-cycles", // 609
+ "editing-duration", // 610
+ "edition", // 611
+ "editor", // 612
+ "effect", // 613
+ "ellipse", // 614
+ "ellipsoid", // 615
+ "email", // 616
+ "embed", // 617
+ "embedded-number-behavior", // 618
+ "embedded-text", // 619
+ "embossed", // 620
+ "emissive-color", // 621
+ "emphasis", // 622
+ "enable", // 623
+ "enable-sql92-check", // 624
+ "enabled", // 625
+ "encoding", // 626
+ "enctype", // 627
+ "end", // 628
+ "end-angle", // 629
+ "end-cell-address", // 630
+ "end-color", // 631
+ "end-column", // 632
+ "end-glue-point", // 633
+ "end-guide", // 634
+ "end-indent", // 635
+ "end-intensity", // 636
+ "end-line-spacing-horizontal", // 637
+ "end-line-spacing-vertical", // 638
+ "end-position", // 639
+ "end-row", // 640
+ "end-shape", // 641
+ "end-table", // 642
+ "end-x", // 643
+ "end-y", // 644
+ "endless", // 645
+ "endnote", // 646
+ "endsync", // 647
+ "engine", // 648
+ "engraved", // 649
+ "enhanced-geometry", // 650
+ "enhanced-path", // 651
+ "entrance", // 652
+ "equal-boolean", // 653
+ "equal-integer", // 654
+ "equal-use-only-zero", // 655
+ "equation", // 656
+ "era", // 657
+ "error-category", // 658
+ "error-indicator", // 659
+ "error-lower-indicator", // 660
+ "error-lower-limit", // 661
+ "error-lower-range", // 662
+ "error-macro", // 663
+ "error-margin", // 664
+ "error-message", // 665
+ "error-percentage", // 666
+ "error-upper-indicator", // 667
+ "error-upper-limit", // 668
+ "error-upper-range", // 669
+ "escape-direction", // 670
+ "escape-processing", // 671
+ "even-columns", // 672
+ "even-rows", // 673
+ "evenodd", // 674
+ "event-listener", // 675
+ "event-listeners", // 676
+ "event-name", // 677
+ "execute", // 678
+ "execute-macro", // 679
+ "exit", // 680
+ "expanded", // 681
+ "exponent-interval", // 682
+ "exponential", // 683
+ "expression", // 684
+ "extension", // 685
+ "extra-condensed", // 686
+ "extra-expanded", // 687
+ "extrude", // 688
+ "extrusion", // 689
+ "extrusion-allowed", // 690
+ "extrusion-brightness", // 691
+ "extrusion-color", // 692
+ "extrusion-depth", // 693
+ "extrusion-diffusion", // 694
+ "extrusion-first-light-direction", // 695
+ "extrusion-first-light-harsh", // 696
+ "extrusion-first-light-level", // 697
+ "extrusion-light-face", // 698
+ "extrusion-metal", // 699
+ "extrusion-number-of-line-segments", // 700
+ "extrusion-origin", // 701
+ "extrusion-rotation-angle", // 702
+ "extrusion-rotation-center", // 703
+ "extrusion-second-light-direction", // 704
+ "extrusion-second-light-harsh", // 705
+ "extrusion-second-light-level", // 706
+ "extrusion-shininess", // 707
+ "extrusion-skew", // 708
+ "extrusion-specularity", // 709
+ "extrusion-viewpoint", // 710
+ "fade", // 711
+ "fade-from-bottom", // 712
+ "fade-from-center", // 713
+ "fade-from-left", // 714
+ "fade-from-lowerleft", // 715
+ "fade-from-lowerright", // 716
+ "fade-from-right", // 717
+ "fade-from-top", // 718
+ "fade-from-upperleft", // 719
+ "fade-from-upperright", // 720
+ "fade-out", // 721
+ "fade-to-center", // 722
+ "fadeColor", // 723
+ "false", // 724
+ "family", // 725
+ "fast", // 726
+ "field", // 727
+ "field-name", // 728
+ "field-number", // 729
+ "file", // 730
+ "file-based-database", // 731
+ "file-name", // 732
+ "fill", // 733
+ "fill-character", // 734
+ "fill-color", // 735
+ "fill-gradient-name", // 736
+ "fill-hatch-name", // 737
+ "fill-hatch-solid", // 738
+ "fill-image", // 739
+ "fill-image-height", // 740
+ "fill-image-name", // 741
+ "fill-image-ref-point", // 742
+ "fill-image-ref-point-x", // 743
+ "fill-image-ref-point-y", // 744
+ "fill-image-width", // 745
+ "fill-rule", // 746
+ "fillDefault", // 747
+ "filter", // 748
+ "filter-and", // 749
+ "filter-condition", // 750
+ "filter-name", // 751
+ "filter-options", // 752
+ "filter-or", // 753
+ "filter-set-item", // 754
+ "filter-statement", // 755
+ "first", // 756
+ "first-column", // 757
+ "first-page", // 758
+ "first-page-number", // 759
+ "first-row", // 760
+ "first-row-end-column", // 761
+ "first-row-start-column", // 762
+ "fit-to-contour", // 763
+ "fit-to-size", // 764
+ "fix", // 765
+ "fixed", // 766
+ "fixed-text", // 767
+ "flat", // 768
+ "float", // 769
+ "floating-frame", // 770
+ "floor", // 771
+ "flow-with-text", // 772
+ "fly-away", // 773
+ "fo", // 774
+ "focal-length", // 775
+ "focus-on-click", // 776
+ "font-adornments", // 777
+ "font-charset", // 778
+ "font-charset-asian", // 779
+ "font-charset-complex", // 780
+ "font-color", // 781
+ "font-face", // 782
+ "font-face-decls", // 783
+ "font-face-format", // 784
+ "font-face-name", // 785
+ "font-face-src", // 786
+ "font-face-uri", // 787
+ "font-family", // 788
+ "font-family-asian", // 789
+ "font-family-complex", // 790
+ "font-family-generic", // 791
+ "font-family-generic-asian", // 792
+ "font-family-generic-complex", // 793
+ "font-independent-line-spacing", // 794
+ "font-name", // 795
+ "font-name-asian", // 796
+ "font-name-complex", // 797
+ "font-pitch", // 798
+ "font-pitch-asian", // 799
+ "font-pitch-complex", // 800
+ "font-relief", // 801
+ "font-size", // 802
+ "font-size-asian", // 803
+ "font-size-complex", // 804
+ "font-size-rel", // 805
+ "font-size-rel-asian", // 806
+ "font-size-rel-complex", // 807
+ "font-stretch", // 808
+ "font-style", // 809
+ "font-style-asian", // 810
+ "font-style-complex", // 811
+ "font-style-name", // 812
+ "font-style-name-asian", // 813
+ "font-style-name-complex", // 814
+ "font-variant", // 815
+ "font-weight", // 816
+ "font-weight-asian", // 817
+ "font-weight-complex", // 818
+ "footer", // 819
+ "footer-decl", // 820
+ "footer-first", // 821
+ "footer-left", // 822
+ "footer-style", // 823
+ "footnote", // 824
+ "footnote-max-height", // 825
+ "footnote-sep", // 826
+ "footnotes-position", // 827
+ "for", // 828
+ "force-manual", // 829
+ "forced-exponent-sign", // 830
+ "foreground", // 831
+ "foreign", // 832
+ "form", // 833
+ "format-change", // 834
+ "format-source", // 835
+ "formatted-text", // 836
+ "forms", // 837
+ "formula", // 838
+ "formula-hidden", // 839
+ "formulas", // 840
+ "forward", // 841
+ "fraction", // 842
+ "frame", // 843
+ "frame-content", // 844
+ "frame-count", // 845
+ "frame-display-border", // 846
+ "frame-display-scrollbar", // 847
+ "frame-end-margin", // 848
+ "frame-margin-horizontal", // 849
+ "frame-margin-vertical", // 850
+ "frame-name", // 851
+ "frame-start-margin", // 852
+ "free", // 853
+ "freeze", // 854
+ "from", // 855
+ "from-another-table", // 856
+ "from-bottom", // 857
+ "from-center", // 858
+ "from-inside", // 859
+ "from-left", // 860
+ "from-lower-left", // 861
+ "from-lower-right", // 862
+ "from-right", // 863
+ "from-same-table", // 864
+ "from-top", // 865
+ "from-upper-left", // 866
+ "from-upper-right", // 867
+ "ft", // 868
+ "full", // 869
+ "full-screen", // 870
+ "function", // 871
+ "fx", // 872
+ "fy", // 873
+ "g", // 874
+ "gamma", // 875
+ "gap", // 876
+ "gap-width", // 877
+ "generator", // 878
+ "generic-control", // 879
+ "gengou", // 880
+ "get", // 881
+ "global", // 882
+ "glue-point", // 883
+ "glue-point-leaving-directions", // 884
+ "glue-point-type", // 885
+ "glue-points", // 886
+ "glyph-orientation-vertical", // 887
+ "gouraud", // 888
+ "gradient", // 889
+ "gradient-step-count", // 890
+ "gradientTransform", // 891
+ "gradientUnits", // 892
+ "grand-total", // 893
+ "graphic", // 894
+ "graphic-properties", // 895
+ "grddl", // 896
+ "green", // 897
+ "gregorian", // 898
+ "greyscale", // 899
+ "grid", // 900
+ "group-bars-per-axis", // 901
+ "group-by-field-number", // 902
+ "group-id", // 903
+ "grouped-by", // 904
+ "grouping", // 905
+ "guide-distance", // 906
+ "guide-overhang", // 907
+ "h", // 908
+ "handle", // 909
+ "handle-mirror-horizontal", // 910
+ "handle-mirror-vertical", // 911
+ "handle-polar", // 912
+ "handle-position", // 913
+ "handle-radius-range-maximum", // 914
+ "handle-radius-range-minimum", // 915
+ "handle-range-x-maximum", // 916
+ "handle-range-x-minimum", // 917
+ "handle-range-y-maximum", // 918
+ "handle-range-y-minimum", // 919
+ "handle-switched", // 920
+ "handout", // 921
+ "handout-master", // 922
+ "hanging", // 923
+ "hanja", // 924
+ "hanja_yoil", // 925
+ "has-persistent-data", // 926
+ "hatch", // 927
+ "header", // 928
+ "header-decl", // 929
+ "header-first", // 930
+ "header-footer-properties", // 931
+ "header-left", // 932
+ "header-style", // 933
+ "headers", // 934
+ "height", // 935
+ "help-message", // 936
+ "hidden", // 937
+ "hidden-and-protected", // 938
+ "hidden-paragraph", // 939
+ "hidden-text", // 940
+ "hide", // 941
+ "hide-shape", // 942
+ "hide-text", // 943
+ "high", // 944
+ "highlighted-range", // 945
+ "hijri", // 946
+ "hold", // 947
+ "hole-size", // 948
+ "horizontal", // 949
+ "horizontal-bar", // 950
+ "horizontal-checkerboard", // 951
+ "horizontal-lines", // 952
+ "horizontal-on-even", // 953
+ "horizontal-on-odd", // 954
+ "horizontal-pos", // 955
+ "horizontal-rel", // 956
+ "horizontal-segments", // 957
+ "horizontal-stripes", // 958
+ "hostname", // 959
+ "hourglass", // 960
+ "hours", // 961
+ "howpublished", // 962
+ "href", // 963
+ "hsl", // 964
+ "hyperlink-behaviour", // 965
+ "hyphenate", // 966
+ "hyphenation-keep", // 967
+ "hyphenation-ladder-count", // 968
+ "hyphenation-push-char-count", // 969
+ "hyphenation-remain-char-count", // 970
+ "i", // 971
+ "icon", // 972
+ "id", // 973
+ "identifier", // 974
+ "identify-categories", // 975
+ "ideograph-alpha", // 976
+ "ideographic", // 977
+ "ignore", // 978
+ "ignore-case", // 979
+ "ignore-driver-privileges", // 980
+ "ignore-empty-rows", // 981
+ "ignore-result", // 982
+ "illustration-index", // 983
+ "illustration-index-entry-template", // 984
+ "illustration-index-source", // 985
+ "image", // 986
+ "image-align", // 987
+ "image-count", // 988
+ "image-data", // 989
+ "image-frame", // 990
+ "image-map", // 991
+ "image-opacity", // 992
+ "image-position", // 993
+ "in", // 994
+ "inbook", // 995
+ "inch", // 996
+ "include-hidden-cells", // 997
+ "incollection", // 998
+ "increment", // 999
+ "indefinite", // 1000
+ "index", // 1001
+ "index-body", // 1002
+ "index-column", // 1003
+ "index-columns", // 1004
+ "index-entry-bibliography", // 1005
+ "index-entry-chapter", // 1006
+ "index-entry-link-end", // 1007
+ "index-entry-link-start", // 1008
+ "index-entry-page-number", // 1009
+ "index-entry-span", // 1010
+ "index-entry-tab-stop", // 1011
+ "index-entry-text", // 1012
+ "index-name", // 1013
+ "index-scope", // 1014
+ "index-source-style", // 1015
+ "index-source-styles", // 1016
+ "index-title", // 1017
+ "index-title-template", // 1018
+ "indices", // 1019
+ "information", // 1020
+ "inherit", // 1021
+ "initial-creator", // 1022
+ "inner", // 1023
+ "inproceedings", // 1024
+ "insertion", // 1025
+ "insertion-cut-off", // 1026
+ "inside", // 1027
+ "institution", // 1028
+ "int", // 1029
+ "integer", // 1030
+ "intensity", // 1031
+ "interactive-sequence", // 1032
+ "interlocking-horizontal-left", // 1033
+ "interlocking-horizontal-right", // 1034
+ "interlocking-vertical-bottom", // 1035
+ "interlocking-vertical-top", // 1036
+ "interpolation", // 1037
+ "interval-major", // 1038
+ "interval-minor-divisor", // 1039
+ "into-default-style-data-style", // 1040
+ "into-english-number", // 1041
+ "inverse", // 1042
+ "is-active", // 1043
+ "is-ascending", // 1044
+ "is-autoincrement", // 1045
+ "is-boolean", // 1046
+ "is-clustered", // 1047
+ "is-data-layout-field", // 1048
+ "is-empty-allowed", // 1049
+ "is-first-row-header-line", // 1050
+ "is-hidden", // 1051
+ "is-list-header", // 1052
+ "is-nullable", // 1053
+ "is-password-required", // 1054
+ "is-selection", // 1055
+ "is-sub-table", // 1056
+ "is-table-name-length-limited", // 1057
+ "is-tristate", // 1058
+ "is-unique", // 1059
+ "isbn", // 1060
+ "issn", // 1061
+ "italic", // 1062
+ "item", // 1063
+ "iterate", // 1064
+ "iterate-interval", // 1065
+ "iterate-type", // 1066
+ "iteration", // 1067
+ "iterative", // 1068
+ "japanese-candle-stick", // 1069
+ "jewish", // 1070
+ "join-border", // 1071
+ "journal", // 1072
+ "justify", // 1073
+ "justify-single-word", // 1074
+ "keep-text", // 1075
+ "keep-together", // 1076
+ "keep-with-next", // 1077
+ "key", // 1078
+ "key-column", // 1079
+ "key-columns", // 1080
+ "key1", // 1081
+ "key1-phonetic", // 1082
+ "key2", // 1083
+ "key2-phonetic", // 1084
+ "keySplines", // 1085
+ "keyTimes", // 1086
+ "keys", // 1087
+ "keyword", // 1088
+ "keywords", // 1089
+ "kind", // 1090
+ "km", // 1091
+ "label", // 1092
+ "label-alignment", // 1093
+ "label-arrangement", // 1094
+ "label-cell-address", // 1095
+ "label-cell-range-address", // 1096
+ "label-followed-by", // 1097
+ "label-position", // 1098
+ "label-position-negative", // 1099
+ "label-range", // 1100
+ "label-ranges", // 1101
+ "label-separator", // 1102
+ "label-width-and-position", // 1103
+ "landscape", // 1104
+ "language", // 1105
+ "language-asian", // 1106
+ "language-complex", // 1107
+ "laser", // 1108
+ "last", // 1109
+ "last-column", // 1110
+ "last-column-spanned", // 1111
+ "last-page", // 1112
+ "last-row", // 1113
+ "last-row-end-column", // 1114
+ "last-row-spanned", // 1115
+ "last-row-start-column", // 1116
+ "last-visited-page", // 1117
+ "latin", // 1118
+ "layer", // 1119
+ "layer-set", // 1120
+ "layout-grid-base-height", // 1121
+ "layout-grid-base-width", // 1122
+ "layout-grid-color", // 1123
+ "layout-grid-display", // 1124
+ "layout-grid-lines", // 1125
+ "layout-grid-mode", // 1126
+ "layout-grid-print", // 1127
+ "layout-grid-ruby-below", // 1128
+ "layout-grid-ruby-height", // 1129
+ "layout-grid-snap-to", // 1130
+ "layout-grid-standard-mode", // 1131
+ "layout-mode", // 1132
+ "leader-char", // 1133
+ "leader-color", // 1134
+ "leader-style", // 1135
+ "leader-text", // 1136
+ "leader-text-style", // 1137
+ "leader-type", // 1138
+ "leader-width", // 1139
+ "leave-gap", // 1140
+ "left", // 1141
+ "left-outside", // 1142
+ "legend", // 1143
+ "legend-align", // 1144
+ "legend-expansion", // 1145
+ "legend-expansion-aspect-ratio", // 1146
+ "legend-position", // 1147
+ "length", // 1148
+ "letter-kerning", // 1149
+ "letter-spacing", // 1150
+ "letters", // 1151
+ "level", // 1152
+ "light", // 1153
+ "lighting-mode", // 1154
+ "line", // 1155
+ "line-break", // 1156
+ "line-distance", // 1157
+ "line-height", // 1158
+ "line-height-at-least", // 1159
+ "line-number", // 1160
+ "line-skew", // 1161
+ "line-spacing", // 1162
+ "line-style", // 1163
+ "linear", // 1164
+ "linearGradient", // 1165
+ "linenumbering-configuration", // 1166
+ "linenumbering-separator", // 1167
+ "lines", // 1168
+ "link-data-style-to-source", // 1169
+ "link-to-source-data", // 1170
+ "linked-cell", // 1171
+ "list", // 1172
+ "list-header", // 1173
+ "list-id", // 1174
+ "list-item", // 1175
+ "list-level", // 1176
+ "list-level-label-alignment", // 1177
+ "list-level-position-and-space-mode", // 1178
+ "list-level-properties", // 1179
+ "list-level-style-bullet", // 1180
+ "list-level-style-image", // 1181
+ "list-level-style-number", // 1182
+ "list-linkage-type", // 1183
+ "list-property", // 1184
+ "list-source", // 1185
+ "list-source-type", // 1186
+ "list-style", // 1187
+ "list-style-name", // 1188
+ "list-tab-stop-position", // 1189
+ "list-value", // 1190
+ "listbox", // 1191
+ "listtab", // 1192
+ "local-socket", // 1193
+ "logarithmic", // 1194
+ "login", // 1195
+ "login-timeout", // 1196
+ "long", // 1197
+ "long-dash", // 1198
+ "longvarbinary", // 1199
+ "longvarchar", // 1200
+ "lowercase", // 1201
+ "lr", // 1202
+ "lr-tb", // 1203
+ "ltr", // 1204
+ "luminance", // 1205
+ "m", // 1206
+ "macro-name", // 1207
+ "main-entry", // 1208
+ "main-entry-style-name", // 1209
+ "main-sequence", // 1210
+ "major", // 1211
+ "manual", // 1212
+ "map", // 1213
+ "margin", // 1214
+ "margin-bottom", // 1215
+ "margin-left", // 1216
+ "margin-right", // 1217
+ "margin-top", // 1218
+ "margins", // 1219
+ "marked-invalid", // 1220
+ "marker", // 1221
+ "marker-end", // 1222
+ "marker-end-center", // 1223
+ "marker-end-width", // 1224
+ "marker-start", // 1225
+ "marker-start-center", // 1226
+ "marker-start-width", // 1227
+ "master-element", // 1228
+ "master-fields", // 1229
+ "master-page", // 1230
+ "master-page-name", // 1231
+ "master-styles", // 1232
+ "mastersthesis", // 1233
+ "math", // 1234
+ "mathematical", // 1235
+ "matrix-covered", // 1236
+ "max", // 1237
+ "max-denominator-value", // 1238
+ "max-edge", // 1239
+ "max-height", // 1240
+ "max-length", // 1241
+ "max-row-count", // 1242
+ "max-value", // 1243
+ "max-width", // 1244
+ "maximum", // 1245
+ "maximum-difference", // 1246
+ "may-break-between-rows", // 1247
+ "may-script", // 1248
+ "mean-value", // 1249
+ "measure", // 1250
+ "measure-align", // 1251
+ "measure-vertical-align", // 1252
+ "media", // 1253
+ "media-call", // 1254
+ "media-type", // 1255
+ "medium", // 1256
+ "melt", // 1257
+ "member-count", // 1258
+ "member-difference", // 1259
+ "member-name", // 1260
+ "member-percentage", // 1261
+ "member-percentage-difference", // 1262
+ "member-type", // 1263
+ "message-type", // 1264
+ "meta", // 1265
+ "meta-field", // 1266
+ "method", // 1267
+ "mi", // 1268
+ "middle", // 1269
+ "mime-type", // 1270
+ "mimetype", // 1271
+ "min", // 1272
+ "min-decimal-places", // 1273
+ "min-denominator-digits", // 1274
+ "min-edge", // 1275
+ "min-exponent-digits", // 1276
+ "min-height", // 1277
+ "min-integer-digits", // 1278
+ "min-label-distance", // 1279
+ "min-label-width", // 1280
+ "min-numerator-digits", // 1281
+ "min-row-height", // 1282
+ "min-value", // 1283
+ "min-width", // 1284
+ "minimum", // 1285
+ "minor", // 1286
+ "minutes", // 1287
+ "mirror", // 1288
+ "mirror-horizontal", // 1289
+ "mirror-vertical", // 1290
+ "mirrored", // 1291
+ "misc", // 1292
+ "miter", // 1293
+ "mm", // 1294
+ "mode", // 1295
+ "model", // 1296
+ "modern", // 1297
+ "modification-date", // 1298
+ "modification-time", // 1299
+ "modifiers", // 1300
+ "modulate", // 1301
+ "mono", // 1302
+ "month", // 1303
+ "months", // 1304
+ "motion-path", // 1305
+ "mouse-as-pen", // 1306
+ "mouse-visible", // 1307
+ "move", // 1308
+ "move-from-bottom", // 1309
+ "move-from-left", // 1310
+ "move-from-lowerleft", // 1311
+ "move-from-lowerright", // 1312
+ "move-from-right", // 1313
+ "move-from-top", // 1314
+ "move-from-upperleft", // 1315
+ "move-from-upperright", // 1316
+ "move-short", // 1317
+ "movement", // 1318
+ "movement-cut-off", // 1319
+ "moving-average", // 1320
+ "multi-deletion-spanned", // 1321
+ "multi-line", // 1322
+ "multiple", // 1323
+ "name", // 1324
+ "name-and-extension", // 1325
+ "named", // 1326
+ "named-expression", // 1327
+ "named-expressions", // 1328
+ "named-range", // 1329
+ "named-symbol", // 1330
+ "nav-order", // 1331
+ "navigation-mode", // 1332
+ "near-axis", // 1333
+ "near-axis-other-side", // 1334
+ "near-origin", // 1335
+ "never", // 1336
+ "new", // 1337
+ "next", // 1338
+ "next-page", // 1339
+ "next-style-name", // 1340
+ "no-action", // 1341
+ "no-limit", // 1342
+ "no-nulls", // 1343
+ "no-repeat", // 1344
+ "no-wrap", // 1345
+ "node-type", // 1346
+ "nohref", // 1347
+ "non-primitive", // 1348
+ "non-whitespace-character-count", // 1349
+ "none", // 1350
+ "nonzero", // 1351
+ "normal", // 1352
+ "normals-direction", // 1353
+ "normals-kind", // 1354
+ "note", // 1355
+ "note-body", // 1356
+ "note-citation", // 1357
+ "note-class", // 1358
+ "note-continuation-notice-backward", // 1359
+ "note-continuation-notice-forward", // 1360
+ "note-ref", // 1361
+ "notes", // 1362
+ "notes-configuration", // 1363
+ "nothing", // 1364
+ "notify-on-update-of-ranges", // 1365
+ "null-date", // 1366
+ "null-year", // 1367
+ "nullable", // 1368
+ "num-format", // 1369
+ "num-letter-sync", // 1370
+ "num-prefix", // 1371
+ "num-suffix", // 1372
+ "number", // 1373
+ "number-all-superior", // 1374
+ "number-and-name", // 1375
+ "number-columns-repeated", // 1376
+ "number-columns-spanned", // 1377
+ "number-lines", // 1378
+ "number-matrix-columns-spanned", // 1379
+ "number-matrix-rows-spanned", // 1380
+ "number-no-superior", // 1381
+ "number-position", // 1382
+ "number-rows-repeated", // 1383
+ "number-rows-spanned", // 1384
+ "number-style", // 1385
+ "number-wrapped-paragraphs", // 1386
+ "numbered-entries", // 1387
+ "numbered-paragraph", // 1388
+ "numeric", // 1389
+ "object", // 1390
+ "object-count", // 1391
+ "object-index", // 1392
+ "object-index-entry-template", // 1393
+ "object-index-source", // 1394
+ "object-name", // 1395
+ "object-ole", // 1396
+ "objectBoundingBox", // 1397
+ "objects", // 1398
+ "oblique", // 1399
+ "odd-columns", // 1400
+ "odd-rows", // 1401
+ "office", // 1402
+ "offset", // 1403
+ "ole-action", // 1404
+ "ole-draw-aspect", // 1405
+ "ole-object-count", // 1406
+ "on-click", // 1407
+ "on-update-keep-size", // 1408
+ "on-update-keep-styles", // 1409
+ "onLoad", // 1410
+ "onRequest", // 1411
+ "once-concurrent", // 1412
+ "once-successive", // 1413
+ "opacity", // 1414
+ "opacity-name", // 1415
+ "open", // 1416
+ "open-horizontal", // 1417
+ "open-vertical", // 1418
+ "operation", // 1419
+ "operator", // 1420
+ "option", // 1421
+ "order", // 1422
+ "order-statement", // 1423
+ "organizations", // 1424
+ "orgchart", // 1425
+ "orientation", // 1426
+ "origin", // 1427
+ "orphans", // 1428
+ "other", // 1429
+ "out", // 1430
+ "outer", // 1431
+ "outline", // 1432
+ "outline-level", // 1433
+ "outline-level-style", // 1434
+ "outline-style", // 1435
+ "outline-subtotals-bottom", // 1436
+ "outline-subtotals-top", // 1437
+ "outside", // 1438
+ "outside-end", // 1439
+ "outside-start", // 1440
+ "overflow-behavior", // 1441
+ "overlap", // 1442
+ "overline-position", // 1443
+ "overline-thickness", // 1444
+ "p", // 1445
+ "paced", // 1446
+ "pad", // 1447
+ "padding", // 1448
+ "padding-bottom", // 1449
+ "padding-left", // 1450
+ "padding-right", // 1451
+ "padding-top", // 1452
+ "page", // 1453
+ "page-adjust", // 1454
+ "page-breaks-on-group-change", // 1455
+ "page-content", // 1456
+ "page-continuation", // 1457
+ "page-count", // 1458
+ "page-end-margin", // 1459
+ "page-height", // 1460
+ "page-layout", // 1461
+ "page-layout-name", // 1462
+ "page-layout-properties", // 1463
+ "page-number", // 1464
+ "page-sequence", // 1465
+ "page-start-margin", // 1466
+ "page-step-size", // 1467
+ "page-thumbnail", // 1468
+ "page-usage", // 1469
+ "page-variable-get", // 1470
+ "page-variable-set", // 1471
+ "page-width", // 1472
+ "pages", // 1473
+ "panose-1", // 1474
+ "paper-tray-name", // 1475
+ "par", // 1476
+ "paragraph", // 1477
+ "paragraph-content", // 1478
+ "paragraph-count", // 1479
+ "paragraph-end-margin", // 1480
+ "paragraph-properties", // 1481
+ "paragraph-start-margin", // 1482
+ "paragraph-style-name", // 1483
+ "parallel", // 1484
+ "param", // 1485
+ "parameter-name-substitution", // 1486
+ "parent", // 1487
+ "parent-style-name", // 1488
+ "parse-sql-statement", // 1489
+ "password", // 1490
+ "path", // 1491
+ "path-id", // 1492
+ "path-stretchpoint-x", // 1493
+ "path-stretchpoint-y", // 1494
+ "pause", // 1495
+ "pc", // 1496
+ "pending", // 1497
+ "percentage", // 1498
+ "percentage-data-style-name", // 1499
+ "percentage-style", // 1500
+ "perspective", // 1501
+ "phdthesis", // 1502
+ "phong", // 1503
+ "pie-offset", // 1504
+ "placeholder", // 1505
+ "placeholder-type", // 1506
+ "placing", // 1507
+ "plain-number", // 1508
+ "plain-number-and-name", // 1509
+ "play", // 1510
+ "play-full", // 1511
+ "plot-area", // 1512
+ "plugin", // 1513
+ "plus", // 1514
+ "points", // 1515
+ "polygon", // 1516
+ "polyline", // 1517
+ "polynomial", // 1518
+ "port", // 1519
+ "portrait", // 1520
+ "position", // 1521
+ "possessive-form", // 1522
+ "post", // 1523
+ "power", // 1524
+ "precision", // 1525
+ "precision-as-shown", // 1526
+ "prefix", // 1527
+ "presentation", // 1528
+ "presentation-page-layout", // 1529
+ "presentation-page-layout-name", // 1530
+ "preset-class", // 1531
+ "preset-id", // 1532
+ "preset-sub-type", // 1533
+ "previous", // 1534
+ "previous-page", // 1535
+ "primary", // 1536
+ "print", // 1537
+ "print-content", // 1538
+ "print-date", // 1539
+ "print-orientation", // 1540
+ "print-page-order", // 1541
+ "print-range", // 1542
+ "print-ranges", // 1543
+ "print-time", // 1544
+ "print-view", // 1545
+ "printable", // 1546
+ "printed-by", // 1547
+ "printer", // 1548
+ "prior", // 1549
+ "proceedings", // 1550
+ "product", // 1551
+ "projection", // 1552
+ "properties", // 1553
+ "property", // 1554
+ "property-name", // 1555
+ "protect", // 1556
+ "protected", // 1557
+ "protection-key", // 1558
+ "protection-key-digest-algorithm", // 1559
+ "pt", // 1560
+ "publisher", // 1561
+ "punctuation-wrap", // 1562
+ "push", // 1563
+ "pyramid", // 1564
+ "quarter", // 1565
+ "quarters", // 1566
+ "queries", // 1567
+ "query", // 1568
+ "query-collection", // 1569
+ "query-name", // 1570
+ "r", // 1571
+ "radial", // 1572
+ "radialGradient", // 1573
+ "radio", // 1574
+ "random", // 1575
+ "range-usable-as", // 1576
+ "readonly", // 1577
+ "real", // 1578
+ "records", // 1579
+ "recreate-on-edit", // 1580
+ "rect", // 1581
+ "rectangle", // 1582
+ "rectangular", // 1583
+ "red", // 1584
+ "ref", // 1585
+ "ref-name", // 1586
+ "reference-format", // 1587
+ "reference-mark", // 1588
+ "reference-mark-end", // 1589
+ "reference-mark-start", // 1590
+ "referenced-table-name", // 1591
+ "reflect", // 1592
+ "refresh-delay", // 1593
+ "region-center", // 1594
+ "region-left", // 1595
+ "region-right", // 1596
+ "register-true", // 1597
+ "register-truth-ref-style-name", // 1598
+ "regression-curve", // 1599
+ "regression-force-intercept", // 1600
+ "regression-intercept-value", // 1601
+ "regression-max-degree", // 1602
+ "regression-moving-type", // 1603
+ "regression-name", // 1604
+ "regression-period", // 1605
+ "regression-type", // 1606
+ "regular-polygon", // 1607
+ "rejected", // 1608
+ "rejecting-change-id", // 1609
+ "rel-column-width", // 1610
+ "rel-height", // 1611
+ "rel-width", // 1612
+ "related-column-name", // 1613
+ "relative-tab-stop-position", // 1614
+ "remove", // 1615
+ "remove-dependents", // 1616
+ "remove-precedents", // 1617
+ "repeat", // 1618
+ "repeat-column", // 1619
+ "repeat-content", // 1620
+ "repeat-row", // 1621
+ "repeatCount", // 1622
+ "repeatDur", // 1623
+ "repeated", // 1624
+ "replace", // 1625
+ "report-type", // 1626
+ "reports", // 1627
+ "reset", // 1628
+ "restart", // 1629
+ "restart-numbering", // 1630
+ "restart-on-page", // 1631
+ "restartDefault", // 1632
+ "restrict", // 1633
+ "reverse", // 1634
+ "reverse-direction", // 1635
+ "rfc-language-tag", // 1636
+ "rfc-language-tag-asian", // 1637
+ "rfc-language-tag-complex", // 1638
+ "rgb", // 1639
+ "right", // 1640
+ "right-angled-axes", // 1641
+ "right-outside", // 1642
+ "rl", // 1643
+ "rl-tb", // 1644
+ "roll-from-bottom", // 1645
+ "roll-from-left", // 1646
+ "roll-from-right", // 1647
+ "roll-from-top", // 1648
+ "roman", // 1649
+ "rotate", // 1650
+ "rotation", // 1651
+ "rotation-align", // 1652
+ "rotation-angle", // 1653
+ "round", // 1654
+ "row", // 1655
+ "row-count", // 1656
+ "row-height", // 1657
+ "row-mapping", // 1658
+ "row-number", // 1659
+ "row-percentage", // 1660
+ "row-retrieving-statement", // 1661
+ "rows", // 1662
+ "ruby", // 1663
+ "ruby-align", // 1664
+ "ruby-base", // 1665
+ "ruby-position", // 1666
+ "ruby-properties", // 1667
+ "ruby-text", // 1668
+ "run-through", // 1669
+ "running-total", // 1670
+ "rx", // 1671
+ "ry", // 1672
+ "s", // 1673
+ "scale", // 1674
+ "scale-min", // 1675
+ "scale-text", // 1676
+ "scale-to", // 1677
+ "scale-to-X", // 1678
+ "scale-to-Y", // 1679
+ "scale-to-pages", // 1680
+ "scenario", // 1681
+ "scenario-ranges", // 1682
+ "scene", // 1683
+ "schema-definition", // 1684
+ "schema-name", // 1685
+ "school", // 1686
+ "scientific-number", // 1687
+ "screen", // 1688
+ "script", // 1689
+ "script-asian", // 1690
+ "script-complex", // 1691
+ "script-type", // 1692
+ "scripts", // 1693
+ "scroll", // 1694
+ "search-criteria-must-apply-to-whole-cell", // 1695
+ "secondary-fill-color", // 1696
+ "seconds", // 1697
+ "section", // 1698
+ "section-name", // 1699
+ "section-properties", // 1700
+ "section-source", // 1701
+ "segments", // 1702
+ "select-page", // 1703
+ "selected", // 1704
+ "selected-page", // 1705
+ "selection", // 1706
+ "selection-indices", // 1707
+ "self", // 1708
+ "semi-automatic", // 1709
+ "semi-condensed", // 1710
+ "semi-expanded", // 1711
+ "sender-city", // 1712
+ "sender-company", // 1713
+ "sender-country", // 1714
+ "sender-email", // 1715
+ "sender-fax", // 1716
+ "sender-firstname", // 1717
+ "sender-initials", // 1718
+ "sender-lastname", // 1719
+ "sender-phone-private", // 1720
+ "sender-phone-work", // 1721
+ "sender-position", // 1722
+ "sender-postal-code", // 1723
+ "sender-state-or-province", // 1724
+ "sender-street", // 1725
+ "sender-title", // 1726
+ "sentence-count", // 1727
+ "separating", // 1728
+ "separation-character", // 1729
+ "separator", // 1730
+ "seq", // 1731
+ "sequence", // 1732
+ "sequence-decl", // 1733
+ "sequence-decls", // 1734
+ "sequence-ref", // 1735
+ "series", // 1736
+ "series-source", // 1737
+ "server-database", // 1738
+ "server-map", // 1739
+ "set", // 1740
+ "set-default", // 1741
+ "set-null", // 1742
+ "settings", // 1743
+ "shade-mode", // 1744
+ "shadow", // 1745
+ "shadow-color", // 1746
+ "shadow-offset-x", // 1747
+ "shadow-offset-y", // 1748
+ "shadow-opacity", // 1749
+ "shadow-slant", // 1750
+ "shape", // 1751
+ "shape-id", // 1752
+ "shapes", // 1753
+ "sharpness", // 1754
+ "sheet-name", // 1755
+ "shininess", // 1756
+ "short", // 1757
+ "show", // 1758
+ "show-deleted", // 1759
+ "show-details", // 1760
+ "show-empty", // 1761
+ "show-end-of-presentation-slide", // 1762
+ "show-filter-button", // 1763
+ "show-logo", // 1764
+ "show-shape", // 1765
+ "show-text", // 1766
+ "show-unit", // 1767
+ "shrink-to-fit", // 1768
+ "side-by-side", // 1769
+ "simple", // 1770
+ "single", // 1771
+ "size", // 1772
+ "skewX", // 1773
+ "skewY", // 1774
+ "skip-white-space", // 1775
+ "slide", // 1776
+ "slope", // 1777
+ "slow", // 1778
+ "small-caps", // 1779
+ "smallint", // 1780
+ "smil", // 1781
+ "snap-to-layout-grid", // 1782
+ "soft-page-break", // 1783
+ "solid", // 1784
+ "solid-type", // 1785
+ "sort", // 1786
+ "sort-algorithm", // 1787
+ "sort-ascending", // 1788
+ "sort-by", // 1789
+ "sort-by-position", // 1790
+ "sort-by-x-values", // 1791
+ "sort-groups", // 1792
+ "sort-key", // 1793
+ "sort-mode", // 1794
+ "sound", // 1795
+ "source", // 1796
+ "source-cell-range", // 1797
+ "source-cell-range-addresses", // 1798
+ "source-field-name", // 1799
+ "source-name", // 1800
+ "source-range-address", // 1801
+ "source-service", // 1802
+ "space", // 1803
+ "space-after", // 1804
+ "space-before", // 1805
+ "span", // 1806
+ "specular", // 1807
+ "specular-color", // 1808
+ "speed", // 1809
+ "sphere", // 1810
+ "spin-button", // 1811
+ "spiral-inward-left", // 1812
+ "spiral-inward-right", // 1813
+ "spiral-outward-left", // 1814
+ "spiral-outward-right", // 1815
+ "spiralin-left", // 1816
+ "spiralin-right", // 1817
+ "spiralout-left", // 1818
+ "spiralout-right", // 1819
+ "spline", // 1820
+ "spline-order", // 1821
+ "spline-resolution", // 1822
+ "spreadMethod", // 1823
+ "spreadsheet", // 1824
+ "sql", // 1825
+ "sql-pass-through", // 1826
+ "sql-statement", // 1827
+ "sqlnull", // 1828
+ "square", // 1829
+ "stacked", // 1830
+ "stagger-even", // 1831
+ "stagger-odd", // 1832
+ "standard", // 1833
+ "standard-deviation", // 1834
+ "standard-error", // 1835
+ "star", // 1836
+ "start", // 1837
+ "start-angle", // 1838
+ "start-color", // 1839
+ "start-column", // 1840
+ "start-glue-point", // 1841
+ "start-guide", // 1842
+ "start-indent", // 1843
+ "start-intensity", // 1844
+ "start-line-spacing-horizontal", // 1845
+ "start-line-spacing-vertical", // 1846
+ "start-numbering-at", // 1847
+ "start-page", // 1848
+ "start-position", // 1849
+ "start-row", // 1850
+ "start-scale", // 1851
+ "start-shape", // 1852
+ "start-table", // 1853
+ "start-value", // 1854
+ "start-with-navigator", // 1855
+ "state", // 1856
+ "status", // 1857
+ "stay-on-top", // 1858
+ "stdev", // 1859
+ "stdevp", // 1860
+ "stemh", // 1861
+ "stemv", // 1862
+ "step", // 1863
+ "step-center-x", // 1864
+ "step-center-y", // 1865
+ "step-end", // 1866
+ "step-size", // 1867
+ "step-start", // 1868
+ "steps", // 1869
+ "stock-gain-marker", // 1870
+ "stock-loss-marker", // 1871
+ "stock-range-line", // 1872
+ "stop", // 1873
+ "stop-color", // 1874
+ "stop-opacity", // 1875
+ "straight-line", // 1876
+ "stretch", // 1877
+ "stretch-from-bottom", // 1878
+ "stretch-from-left", // 1879
+ "stretch-from-right", // 1880
+ "stretch-from-top", // 1881
+ "strict", // 1882
+ "strikethrough-position", // 1883
+ "strikethrough-thickness", // 1884
+ "string", // 1885
+ "string-value", // 1886
+ "string-value-if-false", // 1887
+ "string-value-if-true", // 1888
+ "string-value-phonetic", // 1889
+ "stripes", // 1890
+ "stroke", // 1891
+ "stroke-color", // 1892
+ "stroke-dash", // 1893
+ "stroke-dash-names", // 1894
+ "stroke-linecap", // 1895
+ "stroke-linejoin", // 1896
+ "stroke-opacity", // 1897
+ "stroke-width", // 1898
+ "struct", // 1899
+ "structure-protected", // 1900
+ "style", // 1901
+ "style-name", // 1902
+ "style-override", // 1903
+ "styles", // 1904
+ "sub", // 1905
+ "sub-item", // 1906
+ "subject", // 1907
+ "submit", // 1908
+ "subtitle", // 1909
+ "subtotal-field", // 1910
+ "subtotal-rule", // 1911
+ "subtotal-rules", // 1912
+ "subtype", // 1913
+ "suffix", // 1914
+ "sum", // 1915
+ "super", // 1916
+ "suppress-version-columns", // 1917
+ "svg", // 1918
+ "swiss", // 1919
+ "syllable-count", // 1920
+ "symbol-color", // 1921
+ "symbol-height", // 1922
+ "symbol-image", // 1923
+ "symbol-name", // 1924
+ "symbol-type", // 1925
+ "symbol-width", // 1926
+ "system", // 1927
+ "system-driver-settings", // 1928
+ "tab", // 1929
+ "tab-color", // 1930
+ "tab-cycle", // 1931
+ "tab-index", // 1932
+ "tab-ref", // 1933
+ "tab-stop", // 1934
+ "tab-stop-distance", // 1935
+ "tab-stops", // 1936
+ "table", // 1937
+ "table-background", // 1938
+ "table-cell", // 1939
+ "table-cell-properties", // 1940
+ "table-centering", // 1941
+ "table-column", // 1942
+ "table-column-group", // 1943
+ "table-column-properties", // 1944
+ "table-columns", // 1945
+ "table-count", // 1946
+ "table-definition", // 1947
+ "table-definitions", // 1948
+ "table-exclude-filter", // 1949
+ "table-fields", // 1950
+ "table-filter", // 1951
+ "table-filter-pattern", // 1952
+ "table-formula", // 1953
+ "table-header-columns", // 1954
+ "table-header-rows", // 1955
+ "table-include-filter", // 1956
+ "table-index", // 1957
+ "table-index-entry-template", // 1958
+ "table-index-source", // 1959
+ "table-name", // 1960
+ "table-of-content", // 1961
+ "table-of-content-entry-template", // 1962
+ "table-of-content-source", // 1963
+ "table-properties", // 1964
+ "table-representation", // 1965
+ "table-representations", // 1966
+ "table-row", // 1967
+ "table-row-group", // 1968
+ "table-row-properties", // 1969
+ "table-rows", // 1970
+ "table-setting", // 1971
+ "table-settings", // 1972
+ "table-source", // 1973
+ "table-template", // 1974
+ "table-type", // 1975
+ "table-type-filter", // 1976
+ "tabular-layout", // 1977
+ "target-cell-address", // 1978
+ "target-frame", // 1979
+ "target-frame-name", // 1980
+ "target-range-address", // 1981
+ "targetElement", // 1982
+ "tb", // 1983
+ "tb-lr", // 1984
+ "tb-rl", // 1985
+ "techreport", // 1986
+ "template", // 1987
+ "template-name", // 1988
+ "text", // 1989
+ "text-align", // 1990
+ "text-align-last", // 1991
+ "text-align-source", // 1992
+ "text-areas", // 1993
+ "text-autospace", // 1994
+ "text-blinking", // 1995
+ "text-box", // 1996
+ "text-combine", // 1997
+ "text-combine-end-char", // 1998
+ "text-combine-start-char", // 1999
+ "text-content", // 2000
+ "text-emphasize", // 2001
+ "text-indent", // 2002
+ "text-input", // 2003
+ "text-line-through-color", // 2004
+ "text-line-through-mode", // 2005
+ "text-line-through-style", // 2006
+ "text-line-through-text", // 2007
+ "text-line-through-text-style", // 2008
+ "text-line-through-type", // 2009
+ "text-line-through-width", // 2010
+ "text-outline", // 2011
+ "text-overlap", // 2012
+ "text-overline-color", // 2013
+ "text-overline-mode", // 2014
+ "text-overline-style", // 2015
+ "text-overline-type", // 2016
+ "text-overline-width", // 2017
+ "text-path", // 2018
+ "text-path-allowed", // 2019
+ "text-path-mode", // 2020
+ "text-path-same-letter-heights", // 2021
+ "text-path-scale", // 2022
+ "text-position", // 2023
+ "text-properties", // 2024
+ "text-rotate-angle", // 2025
+ "text-rotation-angle", // 2026
+ "text-rotation-scale", // 2027
+ "text-scale", // 2028
+ "text-shadow", // 2029
+ "text-style", // 2030
+ "text-style-name", // 2031
+ "text-transform", // 2032
+ "text-underline-color", // 2033
+ "text-underline-mode", // 2034
+ "text-underline-style", // 2035
+ "text-underline-type", // 2036
+ "text-underline-width", // 2037
+ "textarea", // 2038
+ "textarea-horizontal-align", // 2039
+ "textarea-vertical-align", // 2040
+ "textual", // 2041
+ "texture-filter", // 2042
+ "texture-generation-mode-x", // 2043
+ "texture-generation-mode-y", // 2044
+ "texture-kind", // 2045
+ "texture-mode", // 2046
+ "thick", // 2047
+ "thin", // 2048
+ "thousand", // 2049
+ "three-dimensional", // 2050
+ "thumbnail", // 2051
+ "tick-mark-position", // 2052
+ "tick-marks-major-inner", // 2053
+ "tick-marks-major-outer", // 2054
+ "tick-marks-minor-inner", // 2055
+ "tick-marks-minor-outer", // 2056
+ "tile-repeat-offset", // 2057
+ "time", // 2058
+ "time-adjust", // 2059
+ "time-style", // 2060
+ "time-value", // 2061
+ "timestmp", // 2062
+ "timing-root", // 2063
+ "tinyint", // 2064
+ "title", // 2065
+ "to", // 2066
+ "to-another-table", // 2067
+ "to-bottom", // 2068
+ "to-center", // 2069
+ "to-left", // 2070
+ "to-lower-left", // 2071
+ "to-lower-right", // 2072
+ "to-right", // 2073
+ "to-top", // 2074
+ "to-upper-left", // 2075
+ "to-upper-right", // 2076
+ "toc-mark", // 2077
+ "toc-mark-end", // 2078
+ "toc-mark-start", // 2079
+ "toggle", // 2080
+ "top", // 2081
+ "top-end", // 2082
+ "top-left", // 2083
+ "top-right", // 2084
+ "top-start", // 2085
+ "total-percentage", // 2086
+ "trace-dependents", // 2087
+ "trace-errors", // 2088
+ "trace-precedents", // 2089
+ "track-changes", // 2090
+ "tracked-changes", // 2091
+ "transform", // 2092
+ "transformation", // 2093
+ "transition", // 2094
+ "transition-on-click", // 2095
+ "transition-speed", // 2096
+ "transition-style", // 2097
+ "transition-type", // 2098
+ "transitionFilter", // 2099
+ "translate", // 2100
+ "transliteration-country", // 2101
+ "transliteration-format", // 2102
+ "transliteration-language", // 2103
+ "transliteration-style", // 2104
+ "transparent", // 2105
+ "treat-empty-cells", // 2106
+ "triple", // 2107
+ "true", // 2108
+ "truncate-on-overflow", // 2109
+ "ttb", // 2110
+ "type", // 2111
+ "type-name", // 2112
+ "ultra-condensed", // 2113
+ "ultra-expanded", // 2114
+ "unchecked", // 2115
+ "uncover-to-bottom", // 2116
+ "uncover-to-left", // 2117
+ "uncover-to-lowerleft", // 2118
+ "uncover-to-lowerright", // 2119
+ "uncover-to-right", // 2120
+ "uncover-to-top", // 2121
+ "uncover-to-upperleft", // 2122
+ "uncover-to-upperright", // 2123
+ "underline-position", // 2124
+ "underline-thickness", // 2125
+ "unicode-range", // 2126
+ "unique", // 2127
+ "unit", // 2128
+ "units-per-em", // 2129
+ "unknown", // 2130
+ "unpublished", // 2131
+ "unsorted", // 2132
+ "up", // 2133
+ "update-rule", // 2134
+ "update-table", // 2135
+ "uppercase", // 2136
+ "url", // 2137
+ "use-banding-columns-styles", // 2138
+ "use-banding-rows-styles", // 2139
+ "use-caption", // 2140
+ "use-catalog", // 2141
+ "use-chart-objects", // 2142
+ "use-date-time-name", // 2143
+ "use-draw-objects", // 2144
+ "use-first-column-styles", // 2145
+ "use-first-row-styles", // 2146
+ "use-floating-frames", // 2147
+ "use-footer-name", // 2148
+ "use-graphics", // 2149
+ "use-header-name", // 2150
+ "use-index-marks", // 2151
+ "use-index-source-styles", // 2152
+ "use-keys-as-entries", // 2153
+ "use-labels", // 2154
+ "use-last-column-styles", // 2155
+ "use-last-row-styles", // 2156
+ "use-math-objects", // 2157
+ "use-objects", // 2158
+ "use-optimal-column-width", // 2159
+ "use-optimal-row-height", // 2160
+ "use-other-objects", // 2161
+ "use-outline-level", // 2162
+ "use-regular-expressions", // 2163
+ "use-soft-page-breaks", // 2164
+ "use-spreadsheet-objects", // 2165
+ "use-system-user", // 2166
+ "use-tables", // 2167
+ "use-wildcards", // 2168
+ "use-window-font-color", // 2169
+ "use-zero", // 2170
+ "used-hierarchy", // 2171
+ "user-defined", // 2172
+ "user-field-decl", // 2173
+ "user-field-decls", // 2174
+ "user-field-get", // 2175
+ "user-field-input", // 2176
+ "user-index", // 2177
+ "user-index-entry-template", // 2178
+ "user-index-mark", // 2179
+ "user-index-mark-end", // 2180
+ "user-index-mark-start", // 2181
+ "user-index-source", // 2182
+ "user-name", // 2183
+ "user-transformed", // 2184
+ "v-alphabetic", // 2185
+ "v-hanging", // 2186
+ "v-ideographic", // 2187
+ "v-mathematical", // 2188
+ "validation", // 2189
+ "value", // 2190
+ "value-and-percentage", // 2191
+ "value-list", // 2192
+ "value-range", // 2193
+ "value-type", // 2194
+ "values", // 2195
+ "values-cell-range-address", // 2196
+ "var", // 2197
+ "varbinary", // 2198
+ "varchar", // 2199
+ "variable", // 2200
+ "variable-decl", // 2201
+ "variable-decls", // 2202
+ "variable-get", // 2203
+ "variable-input", // 2204
+ "variable-set", // 2205
+ "variance", // 2206
+ "varp", // 2207
+ "verb", // 2208
+ "version", // 2209
+ "vertical", // 2210
+ "vertical-align", // 2211
+ "vertical-bar", // 2212
+ "vertical-checkerboard", // 2213
+ "vertical-lines", // 2214
+ "vertical-pos", // 2215
+ "vertical-rel", // 2216
+ "vertical-segments", // 2217
+ "vertical-stripes", // 2218
+ "viewBox", // 2219
+ "visibility", // 2220
+ "visible", // 2221
+ "visible-area-height", // 2222
+ "visible-area-left", // 2223
+ "visible-area-top", // 2224
+ "visible-area-width", // 2225
+ "visited-style-name", // 2226
+ "visual-effect", // 2227
+ "void", // 2228
+ "volatile", // 2229
+ "volume", // 2230
+ "vpn", // 2231
+ "vrp", // 2232
+ "vup", // 2233
+ "wall", // 2234
+ "warning", // 2235
+ "watermark", // 2236
+ "wave", // 2237
+ "wavyline", // 2238
+ "wavyline-from-bottom", // 2239
+ "wavyline-from-left", // 2240
+ "wavyline-from-right", // 2241
+ "wavyline-from-top", // 2242
+ "week-of-year", // 2243
+ "whenNotActive", // 2244
+ "wide", // 2245
+ "widows", // 2246
+ "width", // 2247
+ "widths", // 2248
+ "with-previous", // 2249
+ "word", // 2250
+ "word-count", // 2251
+ "wrap", // 2252
+ "wrap-contour", // 2253
+ "wrap-contour-mode", // 2254
+ "wrap-dynamic-threshold", // 2255
+ "wrap-influence-on-position", // 2256
+ "wrap-option", // 2257
+ "writing-mode", // 2258
+ "writing-mode-automatic", // 2259
+ "www", // 2260
+ "x", // 2261
+ "x-height", // 2262
+ "x1", // 2263
+ "x2", // 2264
+ "xforms", // 2265
+ "xforms-list-source", // 2266
+ "xforms-submission", // 2267
+ "xhtml", // 2268
+ "xlink", // 2269
+ "xml", // 2270
+ "y", // 2271
+ "y1", // 2272
+ "y2", // 2273
+ "year", // 2274
+ "years", // 2275
+ "z", // 2276
+ "z-index", // 2277
+ "zero-values" // 2278
+};
+
+size_t token_name_count = 2279; \ No newline at end of file
diff --git a/src/liborcus/ods_content_xml_context.cpp b/src/liborcus/ods_content_xml_context.cpp
new file mode 100644
index 0000000..5f07594
--- /dev/null
+++ b/src/liborcus/ods_content_xml_context.cpp
@@ -0,0 +1,900 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ods_content_xml_context.hpp"
+#include "odf_token_constants.hpp"
+#include "odf_namespace_types.hpp"
+#include "session_context.hpp"
+#include "ods_session_data.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <cstring>
+
+#include <mdds/sorted_string_map.hpp>
+
+using namespace std;
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace cell_value {
+
+using map_type = mdds::sorted_string_map<ods_content_xml_context::cell_value_type, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+map_type::entry entries[] = {
+ { "date", ods_content_xml_context::vt_date },
+ { "float", ods_content_xml_context::vt_float },
+ { "string", ods_content_xml_context::vt_string }
+};
+
+const map_type& get()
+{
+ static map_type cv_map(
+ entries, std::size(entries), ods_content_xml_context::vt_unknown);
+
+ return cv_map;
+}
+
+} // namespace cell_value
+
+void pick_up_named_range_or_expression(
+ session_context& cxt, const xml_token_attrs_t& attrs, xmlns_id_t exp_attr_ns, xml_token_t exp_attr_name,
+ ods_session_data::named_exp_type name_type, ss::sheet_t scope)
+{
+ std::string_view name;
+ std::string_view expression;
+ std::string_view base;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == exp_attr_ns && attr.name == exp_attr_name)
+ {
+ expression = cxt.intern(attr);
+ continue;
+ }
+
+ switch (attr.name)
+ {
+ case XML_name:
+ name = cxt.intern(attr);
+ break;
+ case XML_base_cell_address:
+ base = cxt.intern(attr);
+ break;
+ }
+ }
+
+ auto& ods_data = cxt.get_data<ods_session_data>();
+
+ if (!name.empty() && !expression.empty() && !base.empty())
+ ods_data.named_exps.emplace_back(name, expression, base, name_type, scope);
+}
+
+} // anonymous namespace
+
+// ============================================================================
+
+ods_content_xml_context::sheet_data::sheet_data() :
+ sheet(nullptr), index(-1) {}
+
+void ods_content_xml_context::sheet_data::reset()
+{
+ sheet = nullptr;
+ index = -1;
+}
+
+ods_content_xml_context::row_attr::row_attr() :
+ number_rows_repeated(1)
+{
+}
+
+ods_content_xml_context::cell_attr::cell_attr() :
+ number_columns_repeated(1),
+ type(vt_unknown),
+ value(0.0),
+ formula_grammar(spreadsheet::formula_grammar_t::ods)
+{
+}
+
+// ============================================================================
+
+ods_content_xml_context::ods_content_xml_context(session_context& session_cxt, const tokens& tokens, spreadsheet::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory),
+ m_row(0), m_col(0), m_col_repeated(0),
+ m_para_index(0),
+ m_has_content(false),
+ m_styles(),
+ m_child_styles(session_cxt, tokens, mp_factory->get_styles()),
+ m_child_para(session_cxt, tokens, factory->get_shared_strings(), m_styles),
+ m_child_dde_links(session_cxt, tokens)
+{
+ register_child(&m_child_styles);
+ register_child(&m_child_para);
+ register_child(&m_child_dde_links);
+
+ spreadsheet::iface::import_global_settings* gs = mp_factory->get_global_settings();
+ if (gs)
+ {
+ // Set the default null date to 1899-12-30 per specification (19.614).
+ gs->set_origin_date(1899, 12, 30);
+ }
+}
+
+ods_content_xml_context::~ods_content_xml_context() = default;
+
+xml_context_base* ods_content_xml_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_text && name == XML_p)
+ {
+ m_child_para.reset();
+ return &m_child_para;
+ }
+
+ if (ns == NS_odf_office && name == XML_automatic_styles)
+ {
+ m_child_styles.reset();
+ return &m_child_styles;
+ }
+
+ if (ns == NS_odf_table && name == XML_dde_links)
+ {
+ m_child_dde_links.reset();
+ return &m_child_dde_links;
+ }
+
+ return nullptr;
+}
+
+void ods_content_xml_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_odf_text && name == XML_p)
+ {
+ text_para_context* para_context = static_cast<text_para_context*>(child);
+ m_has_content = !para_context->empty();
+ m_para_index = para_context->get_string_index();
+ }
+ else if (ns == NS_odf_office && name == XML_automatic_styles)
+ {
+ auto new_styles = m_child_styles.pop_styles();
+ merge(m_styles, new_styles);
+ assert(new_styles.empty());
+
+ if (get_config().debug)
+ dump_state(m_styles, std::cout);
+
+ spreadsheet::iface::import_styles* xstyles = mp_factory->get_styles();
+ if (xstyles)
+ {
+ for (const auto& [style_name, style_value] : m_styles)
+ {
+ if (style_value->family == style_family_table_cell)
+ {
+ // TODO: Actually we need a boolean flag to see if it is an automatic style or a real style
+ // currently we have no way to set a real style to a cell anyway
+ const auto& cell = std::get<odf_style::cell>(style_value->data);
+ m_cell_format_map.insert(name2id_type::value_type(style_name, cell.xf));
+ }
+ }
+ }
+ }
+}
+
+void ods_content_xml_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_odf_office)
+ {
+ switch (name)
+ {
+ case XML_body:
+ break;
+ case XML_spreadsheet:
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_odf_table)
+ {
+ switch (name)
+ {
+ case XML_calculation_settings:
+ break;
+ case XML_null_date:
+ xml_element_expected(parent, NS_odf_table, XML_calculation_settings);
+ start_null_date(attrs);
+ break;
+ case XML_table:
+ start_table(parent, attrs);
+ break;
+ case XML_table_column:
+ {
+ static const xml_elem_set_t expected = {
+ { NS_odf_table, XML_table },
+ { NS_odf_table, XML_table_column_group },
+ { NS_odf_table, XML_table_columns },
+ { NS_odf_table, XML_table_header_columns }
+ };
+ xml_element_expected(parent, expected);
+ start_column(attrs);
+ break;
+ }
+ case XML_table_row:
+ {
+ static const xml_elem_set_t expected = {
+ { NS_odf_table, XML_table },
+ { NS_odf_table, XML_table_header_rows },
+ { NS_odf_table, XML_table_row_group },
+ };
+ xml_element_expected(parent, expected);
+ start_row(attrs);
+ break;
+ }
+ case XML_table_cell:
+ xml_element_expected(parent, NS_odf_table, XML_table_row);
+ start_cell(attrs);
+ break;
+ case XML_dde_links:
+ xml_element_expected(parent, NS_odf_office, XML_spreadsheet);
+ break;
+ case XML_dde_link:
+ xml_element_expected(parent, NS_odf_table, XML_dde_links);
+ break;
+ case XML_named_expressions:
+ {
+ static const xml_elem_set_t expected = {
+ { NS_odf_office, XML_spreadsheet },
+ { NS_odf_table, XML_table },
+ };
+ xml_element_expected(parent, expected);
+ break;
+ }
+ case XML_named_range:
+ start_named_range(parent, attrs);
+ break;
+ case XML_named_expression:
+ start_named_expression(parent, attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool ods_content_xml_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_odf_office)
+ {
+ switch (name)
+ {
+ case XML_body:
+ break;
+ case XML_spreadsheet:
+ end_spreadsheet();
+ break;
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_odf_table)
+ {
+ switch (name)
+ {
+ case XML_calculation_settings:
+ break;
+ case XML_null_date:
+ break;
+ case XML_table:
+ end_table();
+ break;
+ case XML_table_column:
+ end_column();
+ break;
+ case XML_table_row:
+ end_row();
+ break;
+ case XML_table_cell:
+ end_cell();
+ break;
+ case XML_named_range:
+ end_named_range();
+ break;
+ case XML_named_expression:
+ end_named_expression();
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void ods_content_xml_context::start_null_date(const xml_token_attrs_t& attrs)
+{
+ spreadsheet::iface::import_global_settings* gs = mp_factory->get_global_settings();
+ if (!gs)
+ // Global settings not available. No point going further.
+ return;
+
+ std::string_view null_date;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_table && attr.name == XML_date_value)
+ null_date = attr.value;
+ }
+
+ date_time_t val = date_time_t::from_chars(null_date);
+
+ gs->set_origin_date(val.year, val.month, val.day);
+}
+
+void ods_content_xml_context::start_table(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ static const xml_elem_set_t expected = {
+ { NS_odf_office, XML_spreadsheet },
+ { NS_odf_table, XML_dde_link },
+ };
+ xml_element_expected(parent, expected);
+
+ if (parent == xml_token_pair_t(NS_odf_office, XML_spreadsheet))
+ {
+ std::string_view name;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_table && attr.name == XML_name)
+ name = attr.value;
+ }
+
+ m_tables.push_back(mp_factory->append_sheet(m_tables.size(), name));
+ m_cur_sheet.sheet = m_tables.back();
+ m_cur_sheet.index = m_tables.size() - 1;
+
+ if (get_config().debug)
+ cout << "start table " << name << endl;
+
+ m_row = m_col = 0;
+ }
+ else if (parent == xml_token_pair_t(NS_odf_table, XML_dde_link))
+ {
+ if (get_config().debug)
+ cout << "start table (DDE link)" << endl;
+ }
+}
+
+void ods_content_xml_context::end_table()
+{
+ if (m_cur_sheet.sheet)
+ {
+ if (get_config().debug)
+ cout << "end table" << endl;
+
+ m_cur_sheet.reset();
+ }
+}
+
+void ods_content_xml_context::start_named_range(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_element_expected(parent, NS_odf_table, XML_named_expressions);
+
+ pick_up_named_range_or_expression(
+ get_session_context(), attrs, NS_odf_table, XML_cell_range_address,
+ ods_session_data::ne_range, m_cur_sheet.index);
+}
+
+void ods_content_xml_context::end_named_range()
+{
+}
+
+void ods_content_xml_context::start_named_expression(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_element_expected(parent, NS_odf_table, XML_named_expressions);
+
+ pick_up_named_range_or_expression(
+ get_session_context(), attrs, NS_odf_table, XML_expression,
+ ods_session_data::ne_expression, m_cur_sheet.index);
+}
+
+void ods_content_xml_context::end_named_expression()
+{
+}
+
+void ods_content_xml_context::start_column(const xml_token_attrs_t& attrs)
+{
+ if (!m_cur_sheet.sheet)
+ return;
+
+ spreadsheet::iface::import_sheet_properties* sheet_props =
+ m_cur_sheet.sheet->get_sheet_properties();
+
+ if (!sheet_props)
+ return;
+
+ std::string_view style_name;
+ std::string_view default_cell_style_name;
+ m_col_repeated = 1;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_table)
+ {
+ switch (attr.name)
+ {
+ case XML_style_name:
+ style_name = attr.value;
+ break;
+ case XML_default_cell_style_name:
+ default_cell_style_name = intern(attr);
+ break;
+ case XML_number_columns_repeated:
+ m_col_repeated = to_long(attr.value);
+ break;
+ }
+ }
+ }
+
+ if (auto it = m_styles.find(style_name); it != m_styles.end())
+ {
+ const odf_style& style = *it->second;
+
+ sheet_props->set_column_width(
+ m_col, m_col_repeated,
+ std::get<odf_style::column>(style.data).width.value,
+ std::get<odf_style::column>(style.data).width.unit);
+ }
+
+ push_default_column_cell_style(default_cell_style_name, m_col_repeated);
+}
+
+void ods_content_xml_context::end_column()
+{
+ m_col += m_col_repeated;
+}
+
+void ods_content_xml_context::start_row(const xml_token_attrs_t& attrs)
+{
+ m_col = 0;
+ m_row_attr = row_attr();
+
+ std::string_view style_name;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_odf_table)
+ {
+ switch (attr.name)
+ {
+ case XML_number_rows_repeated:
+ m_row_attr.number_rows_repeated = to_long(attr.value);
+ break;
+ case XML_style_name:
+ style_name = attr.value;
+ break;
+ }
+ }
+ }
+
+ if (get_config().debug)
+ std::cout << "row: (style='" << style_name << "')" << std::endl;
+
+ if (!m_cur_sheet.sheet)
+ return;
+
+ // Pass row properties to the interface.
+ spreadsheet::iface::import_sheet_properties* sheet_props =
+ m_cur_sheet.sheet->get_sheet_properties();
+
+ if (sheet_props)
+ {
+ if (auto it = m_styles.find(style_name); it != m_styles.end())
+ {
+ const odf_style& style = *it->second;
+ if (style.family == style_family_table_row)
+ {
+ const auto& data = std::get<odf_style::row>(style.data);
+ if (data.height_set)
+ sheet_props->set_row_height(m_row, data.height.value, data.height.unit);
+ }
+ }
+ }
+}
+
+void ods_content_xml_context::end_row()
+{
+ if (m_row_attr.number_rows_repeated > 1)
+ {
+ // TODO: repeat this row.
+ if (get_config().debug)
+ cout << "TODO: repeat this row " << m_row_attr.number_rows_repeated << " times." << endl;
+ }
+ m_row += m_row_attr.number_rows_repeated;
+}
+
+void ods_content_xml_context::start_cell(const xml_token_attrs_t& attrs)
+{
+ m_cell_attr = cell_attr();
+
+ /**
+ * Process the prefixed raw formula string stored as attribute value.
+ */
+ auto process_formula = [](std::string_view str) -> std::string_view
+ {
+ if (str.empty())
+ return {};
+
+ // Formula is prefixed with formula type, followed by a ':'
+ // then the actual formula content.
+
+ // First, detect prefix if any. Only try up to the first 5 characters.
+ const char* p0 = str.data();
+ const char* end = p0 + std::min<size_t>(str.size(), 5);
+ size_t prefix_size = 0;
+ for (const char* p = p0; p != end; ++p)
+ {
+ if (*p == ':')
+ {
+ // Prefix separator found.
+ prefix_size = p - p0;
+ break;
+ }
+
+ if (!is_alpha(*p))
+ // Only alphabets are allowed in the prefix space.
+ break;
+ }
+
+ std::string_view prefix, formula;
+ if (prefix_size)
+ {
+ prefix = std::string_view(p0, prefix_size);
+ const char* p = p0;
+ p += prefix_size + 1;
+ end = p0 + str.size();
+ formula = std::string_view(p, end - p);
+ }
+ else
+ {
+ // TODO : Handle cases where a formula doesn't have a prefix.
+ }
+
+ // Formula needs to begin with '='.
+ if (formula.empty() || formula[0] != '=')
+ return {};
+
+ // Remove the '='.
+ formula = std::string_view(formula.data()+1, formula.size()-1);
+
+ if (prefix == "of")
+ {
+ // ODF formula. No action needed.
+ }
+
+ return formula;
+ };
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ continue;
+
+ if (attr.ns == NS_odf_table)
+ {
+ switch (attr.name)
+ {
+ case XML_style_name:
+ {
+ m_cell_attr.style_name = intern(attr);
+ break;
+ }
+ case XML_number_columns_repeated:
+ m_cell_attr.number_columns_repeated = to_long(attr.value);
+ break;
+ case XML_formula:
+ m_cell_attr.formula = process_formula(attr.value);
+ m_cell_attr.formula = intern(m_cell_attr.formula);
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (attr.ns == NS_odf_office)
+ {
+ switch (attr.name)
+ {
+ case XML_value:
+ {
+ const char* end = attr.value.data() + attr.value.size();
+ char* endptr;
+ double val = strtod(attr.value.data(), &endptr);
+ if (endptr == end)
+ m_cell_attr.value = val;
+ break;
+ }
+ case XML_value_type:
+ m_cell_attr.type = cell_value::get().find(attr.value.data(), attr.value.size());
+ break;
+ case XML_date_value:
+ m_cell_attr.date_value = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+}
+
+void ods_content_xml_context::end_cell()
+{
+ push_cell_format();
+ push_cell_value();
+
+ ++m_col;
+ if (m_cell_attr.number_columns_repeated > 1)
+ {
+ int col_upper = m_col + m_cell_attr.number_columns_repeated - 2;
+ for (; m_col <= col_upper; ++m_col)
+ push_cell_value();
+ }
+ m_has_content = false;
+}
+
+std::optional<std::size_t> ods_content_xml_context::push_named_cell_style(std::string_view style_name)
+{
+ ss::iface::import_styles* xstyles = mp_factory->get_styles();
+ if (!xstyles)
+ return {};
+
+ const ods_session_data& ods_data = get_session_context().get_data<ods_session_data>();
+
+ auto it = ods_data.styles_map.find(style_name);
+ if (it == ods_data.styles_map.end())
+ return {};
+
+ // found in the named styles store.
+ const odf_style& style = *it->second;
+ if (style.family != style_family_table_cell)
+ // it's a named style but not a cell style
+ return {};
+
+ // It references a named style. Create a direct cell (aka automatic) style
+ // that references this named style, and set that as the cell format since
+ // we can't reference a named style directly from a cell.
+ const auto& celldata = std::get<odf_style::cell>(style.data);
+
+ ss::iface::import_xf* xf = xstyles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(xf, import_xf);
+ xf->set_style_xf(celldata.xf);
+ std::size_t xfid = xf->commit();
+ m_cell_format_map.insert({style_name, xfid});
+ return xfid;
+}
+
+void ods_content_xml_context::push_default_column_cell_style(
+ std::string_view style_name, ss::col_t span)
+{
+ if (span < 1)
+ {
+ std::ostringstream os;
+ os << "Column " << m_col << " on sheet " << m_cur_sheet.index << " has an invalid span of " << span;
+ warn(os.str());
+ return;
+ }
+
+ if (style_name.empty())
+ return;
+
+ if (!m_cur_sheet.sheet)
+ return;
+
+ if (auto it = m_cell_format_map.find(style_name); it != m_cell_format_map.end())
+ {
+ // automatic style already present for this name.
+ m_cur_sheet.sheet->set_column_format(m_col, span, it->second);
+ return;
+ }
+
+ auto xfid = push_named_cell_style(style_name);
+ if (!xfid)
+ {
+ std::ostringstream os;
+ os << "failed to push a new cell style of name '" << style_name << "' to cache";
+ warn(os.str());
+ return;
+ }
+
+ m_cur_sheet.sheet->set_column_format(m_col, span, *xfid);
+}
+
+void ods_content_xml_context::push_cell_format()
+{
+ if (!m_cur_sheet.sheet)
+ return;
+
+ if (auto it = m_cell_format_map.find(m_cell_attr.style_name); it != m_cell_format_map.end())
+ {
+ for (ss::col_t col_offset = 0; col_offset < m_cell_attr.number_columns_repeated; ++col_offset)
+ m_cur_sheet.sheet->set_format(m_row, m_col + col_offset, it->second);
+ // style key found and direct cell format set.
+ return;
+ }
+
+ auto xfid = push_named_cell_style(m_cell_attr.style_name);
+ if (!xfid)
+ return;
+
+ for (ss::col_t col_offset = 0; col_offset < m_cell_attr.number_columns_repeated; ++col_offset)
+ m_cur_sheet.sheet->set_format(m_row, m_col + col_offset, *xfid);
+}
+
+void ods_content_xml_context::push_cell_value()
+{
+ assert(m_cur_sheet.index >= 0); // this is expected to be called only within a valid sheet scope.
+
+ bool has_formula = !m_cell_attr.formula.empty();
+ if (has_formula)
+ {
+ // Store formula cell data for later processing.
+ auto& ods_data = get_session_context().get_data<ods_session_data>();
+ ods_data.formulas.emplace_back(
+ m_cur_sheet.index, m_row, m_col, m_cell_attr.formula_grammar, m_cell_attr.formula);
+
+ ods_session_data::formula& formula_data = ods_data.formulas.back();
+
+ // Store formula result.
+ switch (m_cell_attr.type)
+ {
+ case vt_float:
+ {
+ formula_data.result.type = orcus::ods_session_data::rt_numeric;
+ formula_data.result.numeric_value = m_cell_attr.value;
+ break;
+ }
+ case vt_string:
+ // TODO : pass string result here. We need to decide whether
+ // to pass a string ID or a raw string.
+ break;
+ default:
+ ;
+ }
+ return;
+ }
+
+ if (m_cur_sheet.sheet)
+ {
+ switch (m_cell_attr.type)
+ {
+ case vt_float:
+ m_cur_sheet.sheet->set_value(m_row, m_col, m_cell_attr.value);
+ break;
+ case vt_string:
+ if (m_has_content)
+ m_cur_sheet.sheet->set_string(m_row, m_col, m_para_index);
+ break;
+ case vt_date:
+ {
+ date_time_t val = date_time_t::from_chars(m_cell_attr.date_value);
+ m_cur_sheet.sheet->set_date_time(
+ m_row, m_col, val.year, val.month, val.day, val.hour, val.minute, val.second);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+}
+
+void ods_content_xml_context::end_spreadsheet()
+{
+ auto& ods_data = get_session_context().get_data<ods_session_data>();
+
+ ss::iface::import_reference_resolver* resolver =
+ mp_factory->get_reference_resolver(ss::formula_ref_context_t::named_expression_base);
+
+ if (resolver)
+ {
+ for (const ods_session_data::named_exp& data : ods_data.named_exps)
+ {
+ if (get_config().debug)
+ {
+ cout << "named expression: name='" << data.name
+ << "'; base='" << data.base
+ << "'; expression='" << data.expression
+ << "'; sheet-scope=" << data.scope
+ << endl;
+ }
+
+ ss::src_address_t base = resolver->resolve_address(data.base);
+
+ ss::iface::import_named_expression* named_exp = nullptr;
+
+ if (data.scope >= 0)
+ {
+ // sheet local scope
+ assert(data.scope < ss::sheet_t(m_tables.size()));
+ named_exp = m_tables[data.scope]->get_named_expression();
+ }
+ else
+ {
+ // global scope.
+ named_exp = mp_factory->get_named_expression();
+ }
+
+ if (named_exp)
+ {
+ named_exp->set_base_position(base);
+ switch (data.type)
+ {
+ case ods_session_data::ne_range:
+ named_exp->set_named_range(data.name, data.expression);
+ break;
+ case ods_session_data::ne_expression:
+ named_exp->set_named_expression(data.name, data.expression);
+ break;
+ default:
+ ;
+ }
+ named_exp->commit();
+ }
+ }
+ }
+
+ // Push all formula cells. Formula cells needs to be processed after all
+ // the sheet data have been imported, else 3D reference would fail to
+ // resolve.
+ for (ods_session_data::formula& data : ods_data.formulas)
+ {
+ if (data.sheet < 0 || static_cast<size_t>(data.sheet) >= m_tables.size())
+ // Invalid sheet index.
+ continue;
+
+ spreadsheet::iface::import_sheet* sheet = m_tables[data.sheet];
+ if (sheet)
+ {
+ spreadsheet::iface::import_formula* formula = sheet->get_formula();
+ if (formula)
+ {
+ formula->set_position(data.row, data.column);
+ formula->set_formula(data.grammar, data.exp);
+
+ switch (data.result.type)
+ {
+ case ods_session_data::rt_numeric:
+ formula->set_result_value(data.result.numeric_value);
+ break;
+ case ods_session_data::rt_string:
+ case ods_session_data::rt_error:
+ case ods_session_data::rt_none:
+ default:
+ ;
+ }
+
+ formula->commit();
+ }
+ }
+ }
+
+ // Clear the formula buffer.
+ ods_data.formulas.clear();
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ods_content_xml_context.hpp b/src/liborcus/ods_content_xml_context.hpp
new file mode 100644
index 0000000..bc50a67
--- /dev/null
+++ b/src/liborcus/ods_content_xml_context.hpp
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_ODSCONTEXT_XML_CONTEXT_HPP
+#define INCLUDED_ORCUS_ODSCONTEXT_XML_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "odf_para_context.hpp"
+#include "ods_dde_links_context.hpp"
+#include "odf_styles.hpp"
+#include "odf_styles_context.hpp"
+#include "orcus/spreadsheet/types.hpp"
+
+#include <vector>
+#include <unordered_map>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+
+}}
+
+class ods_content_xml_context : public xml_context_base
+{
+ typedef std::unordered_map<std::string_view, std::size_t> name2id_type;
+
+public:
+ struct sheet_data
+ {
+ spreadsheet::iface::import_sheet* sheet;
+ spreadsheet::sheet_t index;
+
+ sheet_data();
+
+ void reset();
+ };
+
+ struct row_attr
+ {
+ long number_rows_repeated;
+ row_attr();
+ };
+
+ enum cell_value_type { vt_unknown, vt_float, vt_string, vt_date };
+
+ struct cell_attr
+ {
+ long number_columns_repeated;
+ cell_value_type type;
+ double value;
+ std::string_view date_value;
+ std::string_view style_name;
+
+ std::string_view formula;
+ spreadsheet::formula_grammar_t formula_grammar;
+
+ cell_attr();
+ };
+
+ ods_content_xml_context(session_context& session_cxt, const tokens& tokens, spreadsheet::iface::import_factory* factory);
+ virtual ~ods_content_xml_context() override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+private:
+ void start_null_date(const xml_token_attrs_t& attrs);
+
+ void start_table(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void end_table();
+
+ void start_named_range(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void end_named_range();
+
+ void start_named_expression(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void end_named_expression();
+
+ void start_column(const xml_token_attrs_t& attrs);
+ void end_column();
+
+ void start_row(const xml_token_attrs_t& attrs);
+ void end_row();
+
+ void start_cell(const xml_token_attrs_t& attrs);
+ void end_cell();
+
+ /**
+ * Push a named cell style as a parent style of an automatic style, as we
+ * cannot directly reference a named cell style from a cell, column etc.
+ *
+ * @param style_name name of the named cell style to push.
+ *
+ * @return xfid of the newly-created automatic style that "wraps" the named
+ * cell as its parent if the call is successful, else it's not set.
+ */
+ std::optional<std::size_t> push_named_cell_style(std::string_view style_name);
+ void push_default_column_cell_style(std::string_view style_name, spreadsheet::col_t span);
+ void push_cell_format();
+ void push_cell_value();
+
+ void end_spreadsheet();
+
+private:
+ spreadsheet::iface::import_factory* mp_factory;
+ std::vector<spreadsheet::iface::import_sheet*> m_tables;
+ sheet_data m_cur_sheet;
+
+ row_attr m_row_attr;
+ cell_attr m_cell_attr; /// attributes of current cell.
+
+ int m_row;
+ int m_col;
+ int m_col_repeated;
+ size_t m_para_index;
+ bool m_has_content;
+
+ odf_styles_map_type m_styles; /// map storing all automatic styles by their names.
+ name2id_type m_cell_format_map; /// map of automatic style names to cell format (xf) IDs.
+
+ styles_context m_child_styles;
+ text_para_context m_child_para;
+ ods_dde_links_context m_child_dde_links;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ods_dde_links_context.cpp b/src/liborcus/ods_dde_links_context.cpp
new file mode 100644
index 0000000..4b644a2
--- /dev/null
+++ b/src/liborcus/ods_dde_links_context.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ods_dde_links_context.hpp"
+
+namespace orcus {
+
+ods_dde_links_context::ods_dde_links_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens) {}
+
+ods_dde_links_context::~ods_dde_links_context() {}
+
+xml_context_base* ods_dde_links_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void ods_dde_links_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void ods_dde_links_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& /*attrs*/)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ (void)parent;
+
+ warn_unhandled();
+}
+
+bool ods_dde_links_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void ods_dde_links_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void ods_dde_links_context::reset()
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ods_dde_links_context.hpp b/src/liborcus/ods_dde_links_context.hpp
new file mode 100644
index 0000000..0abba49
--- /dev/null
+++ b/src/liborcus/ods_dde_links_context.hpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ODS_DDE_LINKS_CONTEXT_HPP
+#define INCLUDED_ODS_DDE_LINKS_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+
+namespace orcus {
+
+/**
+ * Handle <table:dde-links> element structure. For now, this context exists
+ * only to ignore all DDE related data.
+ */
+class ods_dde_links_context : public xml_context_base
+{
+public:
+ ods_dde_links_context(session_context& session_cxt, const tokens& tokens);
+ virtual ~ods_dde_links_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base *child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t> &attrs) override;
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset();
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ods_session_data.cpp b/src/liborcus/ods_session_data.cpp
new file mode 100644
index 0000000..c039e05
--- /dev/null
+++ b/src/liborcus/ods_session_data.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ods_session_data.hpp"
+
+#include <limits>
+
+namespace orcus {
+
+ods_session_data::formula_result::formula_result() :
+ type(rt_none), numeric_value(std::numeric_limits<double>::quiet_NaN()) {}
+
+ods_session_data::formula::formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _col,
+ spreadsheet::formula_grammar_t _grammar, std::string_view _exp) :
+ sheet(_sheet), row(_row), column(_col), grammar(_grammar), exp(_exp) {}
+
+ods_session_data::named_exp::named_exp(
+ std::string_view _name, std::string_view _expression, std::string_view _base, named_exp_type _type, spreadsheet::sheet_t _scope) :
+ name(_name), expression(_expression), base(_base), type(_type), scope(_scope) {}
+
+std::string_view ods_session_data::number_formats_store::get_code(std::string_view name) const
+{
+ auto it_name = name2id_map.find(name);
+ if (it_name == name2id_map.end())
+ return {};
+
+ std::size_t id = it_name->second;
+ auto it_code = id2code_map.find(id);
+ if (it_code == id2code_map.end())
+ return {};
+
+ return it_code->second;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ods_session_data.hpp b/src/liborcus/ods_session_data.hpp
new file mode 100644
index 0000000..4223095
--- /dev/null
+++ b/src/liborcus/ods_session_data.hpp
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_ODS_SESSION_DATA_HPP
+#define INCLUDED_ORCUS_ODS_SESSION_DATA_HPP
+
+#include "session_context.hpp"
+#include "odf_styles.hpp"
+
+#include <orcus/spreadsheet/types.hpp>
+
+#include <deque>
+
+namespace orcus {
+
+struct ods_session_data : public session_context::custom_data
+{
+ enum formula_result_type { rt_none, rt_numeric, rt_string, rt_error };
+ enum named_exp_type { ne_unknown, ne_range, ne_expression };
+
+ struct formula_result
+ {
+ formula_result_type type;
+ double numeric_value;
+ std::string_view string_value;
+
+ formula_result();
+ };
+
+ struct formula
+ {
+ spreadsheet::sheet_t sheet;
+ spreadsheet::row_t row;
+ spreadsheet::col_t column;
+
+ spreadsheet::formula_grammar_t grammar;
+ std::string_view exp;
+
+ formula_result result;
+
+ formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _col,
+ spreadsheet::formula_grammar_t _grammar, std::string_view _exp);
+ };
+
+ struct named_exp
+ {
+ std::string_view name;
+ std::string_view expression;
+ std::string_view base;
+
+ named_exp_type type;
+ spreadsheet::sheet_t scope; // >= 0 for sheet scope, or < 0 for global scope.
+
+ named_exp(std::string_view _name, std::string_view _expression, std::string_view _base, named_exp_type _type, spreadsheet::sheet_t _scope);
+ };
+
+ std::deque<formula> formulas;
+ std::deque<named_exp> named_exps;
+
+ odf_styles_map_type styles_map;
+
+ struct number_formats_store
+ {
+ std::map<std::string_view, std::size_t> name2id_map;
+ std::map<std::size_t, std::string> id2code_map;
+
+ std::string_view get_code(std::string_view name) const;
+ };
+
+ number_formats_store number_formats;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_content_types.cpp b/src/liborcus/ooxml_content_types.cpp
new file mode 100644
index 0000000..eb614c7
--- /dev/null
+++ b/src/liborcus/ooxml_content_types.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_content_types.hpp"
+
+namespace orcus {
+
+const content_type_t CT_ooxml_extended_properties = "application/vnd.openxmlformats-officedocument.extended-properties+xml";
+const content_type_t CT_ooxml_drawing = "application/vnd.openxmlformats-officedocument.drawing+xml";
+const content_type_t CT_ooxml_vml_drawing = "application/vnd.openxmlformats-officedocument.vmlDrawing";
+const content_type_t CT_ooxml_xlsx_calc_chain = "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml";
+const content_type_t CT_ooxml_xlsx_comments = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
+const content_type_t CT_ooxml_xlsx_connections = "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml";
+const content_type_t CT_ooxml_xlsx_external_link = "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml";
+const content_type_t CT_ooxml_xlsx_pivot_cache_def = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml";
+const content_type_t CT_ooxml_xlsx_pivot_cache_rec = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml";
+const content_type_t CT_ooxml_xlsx_pivot_table = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml";
+const content_type_t CT_ooxml_xlsx_printer_settings = "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings";
+const content_type_t CT_ooxml_xlsx_query_table = "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml";
+const content_type_t CT_ooxml_xlsx_shared_strings = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
+const content_type_t CT_ooxml_xlsx_sheet_main = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
+const content_type_t CT_ooxml_xlsx_styles = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml";
+const content_type_t CT_ooxml_xlsx_table = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml";
+const content_type_t CT_ooxml_xlsx_worksheet = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
+const content_type_t CT_ooxml_xlsx_usernames = "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml";
+const content_type_t CT_ooxml_xlsx_rev_headers = "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml";
+const content_type_t CT_ooxml_xlsx_rev_log = "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml";
+const content_type_t CT_ooxml_theme = "application/vnd.openxmlformats-officedocument.theme+xml";
+const content_type_t CT_opc_core_properties = "application/vnd.openxmlformats-package.core-properties+xml";
+const content_type_t CT_opc_relationships = "application/vnd.openxmlformats-package.relationships+xml";
+const content_type_t CT_xml = "application/xml";
+const content_type_t CT_image_png = "image/png";
+
+namespace {
+
+content_type_t cts[] = {
+ CT_ooxml_extended_properties,
+ CT_ooxml_drawing,
+ CT_ooxml_vml_drawing,
+ CT_ooxml_xlsx_calc_chain,
+ CT_ooxml_xlsx_comments,
+ CT_ooxml_xlsx_connections,
+ CT_ooxml_xlsx_external_link,
+ CT_ooxml_xlsx_pivot_cache_def,
+ CT_ooxml_xlsx_pivot_cache_rec,
+ CT_ooxml_xlsx_pivot_table,
+ CT_ooxml_xlsx_printer_settings,
+ CT_ooxml_xlsx_query_table,
+ CT_ooxml_xlsx_shared_strings,
+ CT_ooxml_xlsx_sheet_main,
+ CT_ooxml_xlsx_styles,
+ CT_ooxml_xlsx_table,
+ CT_ooxml_xlsx_worksheet,
+ CT_ooxml_xlsx_usernames,
+ CT_ooxml_xlsx_rev_headers,
+ CT_ooxml_xlsx_rev_log,
+ CT_ooxml_theme,
+ CT_opc_core_properties,
+ CT_opc_relationships,
+ CT_xml,
+ CT_image_png,
+ nullptr
+};
+
+}
+
+const content_type_t* CT_all = cts;
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_content_types.hpp b/src/liborcus/ooxml_content_types.hpp
new file mode 100644
index 0000000..d82dd53
--- /dev/null
+++ b/src/liborcus/ooxml_content_types.hpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OOXML_CONTENT_TYPES_HPP
+#define INCLUDED_ORCUS_OOXML_CONTENT_TYPES_HPP
+
+#include "ooxml_types.hpp"
+
+namespace orcus {
+
+extern const content_type_t CT_ooxml_extended_properties;
+extern const content_type_t CT_ooxml_drawing;
+extern const content_type_t CT_ooxml_vml_drawing;
+extern const content_type_t CT_ooxml_xlsx_calc_chain;
+extern const content_type_t CT_ooxml_xlsx_comments;
+extern const content_type_t CT_ooxml_xlsx_connections;
+extern const content_type_t CT_ooxml_xlsx_external_link;
+extern const content_type_t CT_ooxml_xlsx_pivot_cache_def;
+extern const content_type_t CT_ooxml_xlsx_pivot_cache_rec;
+extern const content_type_t CT_ooxml_xlsx_pivot_table;
+extern const content_type_t CT_ooxml_xlsx_printer_settings;
+extern const content_type_t CT_ooxml_xlsx_query_table;
+extern const content_type_t CT_ooxml_xlsx_shared_strings;
+extern const content_type_t CT_ooxml_xlsx_sheet_main;
+extern const content_type_t CT_ooxml_xlsx_styles;
+extern const content_type_t CT_ooxml_xlsx_table;
+extern const content_type_t CT_ooxml_xlsx_worksheet;
+extern const content_type_t CT_ooxml_xlsx_usernames;
+extern const content_type_t CT_ooxml_xlsx_rev_headers;
+extern const content_type_t CT_ooxml_xlsx_rev_log;
+extern const content_type_t CT_ooxml_theme;
+extern const content_type_t CT_opc_core_properties;
+extern const content_type_t CT_opc_relationships;
+extern const content_type_t CT_xml;
+extern const content_type_t CT_image_png;
+
+/**
+ * Null-terminated array of all content types.
+ */
+extern const content_type_t* CT_all;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_global.cpp b/src/liborcus/ooxml_global.cpp
new file mode 100644
index 0000000..6c6d93b
--- /dev/null
+++ b/src/liborcus/ooxml_global.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_global.hpp"
+#include "ooxml_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "xml_context_base.hpp"
+
+#include <iostream>
+#include <sstream>
+
+namespace orcus {
+
+void print_opc_rel::operator() (const opc_rel_t& v) const
+{
+ std::cout << v.rid << ": " << v.target << " (" << v.type << ")" << std::endl;
+}
+
+std::string resolve_file_path(const std::string& dir_path, const std::string& file_name)
+{
+ if (dir_path.empty())
+ return file_name;
+
+ const char* p = &dir_path[0];
+ const char* p_end = p + dir_path.size();
+
+ bool has_root = *p == '/';
+ if (has_root)
+ ++p;
+
+ std::vector<std::string_view> dir_stack;
+ const char* p_head = nullptr;
+ for (; p != p_end; ++p)
+ {
+ if (*p == '/')
+ {
+ if (!p_head)
+ // invalid directory path.
+ return file_name;
+
+ size_t len = p - p_head;
+ std::string_view dir(p_head, len);
+ if (dir == "..")
+ {
+ if (dir_stack.empty())
+ // invalid directory path.
+ return file_name;
+
+ dir_stack.pop_back();
+ }
+ else
+ dir_stack.push_back(dir);
+
+ p_head = nullptr;
+ }
+ else if (p_head)
+ {
+ // Do nothing.
+ }
+ else
+ p_head = p;
+ }
+
+ if (p_head)
+ {
+ // directory path must end with '/'. This one doesn't.
+ return file_name;
+ }
+
+ std::ostringstream full_path;
+ if (has_root)
+ full_path << '/';
+
+ for (auto dir : dir_stack)
+ full_path << dir << '/';
+
+ full_path << file_name;
+
+ return full_path.str();
+}
+
+void init_ooxml_context(xml_context_base& cxt)
+{
+ cxt.set_always_allowed_elements({
+ { NS_mc, XML_Choice },
+ { NS_mc, XML_Fallback },
+ });
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_global.hpp b/src/liborcus/ooxml_global.hpp
new file mode 100644
index 0000000..853c4e9
--- /dev/null
+++ b/src/liborcus/ooxml_global.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_OOXML_GLOBAL_HPP
+#define ORCUS_OOXML_GLOBAL_HPP
+
+#include "orcus/types.hpp"
+#include "ooxml_types.hpp"
+
+#include <string>
+#include <functional>
+
+namespace orcus {
+
+struct opc_rel_t;
+struct xml_token_attr_t;
+class xml_context_base;
+
+/**
+ * Function object to print relationship information.
+ */
+struct print_opc_rel
+{
+ void operator() (const opc_rel_t& v) const;
+};
+
+/**
+ * Given a directory path and a file name, return a full path that combines
+ * the two while resolving any parent directory path ".." markers.
+ *
+ * @param dir_path directory path. It can optionally start with a '/', but
+ * it must end with a '/'.
+ * @param file_name file name.
+ *
+ * @return full file path.
+ */
+std::string resolve_file_path(const std::string& dir_path, const std::string& file_name);
+
+void init_ooxml_context(xml_context_base& cxt);
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_namespace_types.cpp b/src/liborcus/ooxml_namespace_types.cpp
new file mode 100644
index 0000000..8c1224b
--- /dev/null
+++ b/src/liborcus/ooxml_namespace_types.cpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_namespace_types.hpp"
+
+namespace orcus {
+
+const xmlns_id_t NS_ooxml_a = "http://schemas.openxmlformats.org/drawingml/2006/main";
+const xmlns_id_t NS_ooxml_r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
+const xmlns_id_t NS_ooxml_xdr = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing";
+const xmlns_id_t NS_ooxml_xlsx = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
+
+const xmlns_id_t NS_opc_ct = "http://schemas.openxmlformats.org/package/2006/content-types";
+const xmlns_id_t NS_opc_rel = "http://schemas.openxmlformats.org/package/2006/relationships";
+
+const xmlns_id_t NS_mc = "http://schemas.openxmlformats.org/markup-compatibility/2006";
+const xmlns_id_t NS_mso_x14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main";
+
+namespace {
+
+xmlns_id_t ooxml_ns[] = {
+ NS_ooxml_a,
+ NS_ooxml_r,
+ NS_ooxml_xdr,
+ NS_ooxml_xlsx,
+ nullptr
+};
+
+xmlns_id_t opc_ns[] = {
+ NS_opc_ct,
+ NS_opc_rel,
+ nullptr
+};
+
+xmlns_id_t misc_ns[] = {
+ NS_mc,
+ NS_mso_x14,
+ nullptr
+};
+
+}
+
+const xmlns_id_t* NS_ooxml_all = ooxml_ns;
+const xmlns_id_t* NS_opc_all = opc_ns;
+const xmlns_id_t* NS_misc_all = misc_ns;
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_namespace_types.hpp b/src/liborcus/ooxml_namespace_types.hpp
new file mode 100644
index 0000000..8183bf8
--- /dev/null
+++ b/src/liborcus/ooxml_namespace_types.hpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OOXML_NAMESPACE_TYPES_HPP
+#define INCLUDED_ORCUS_OOXML_NAMESPACE_TYPES_HPP
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+extern const xmlns_id_t NS_ooxml_a;
+extern const xmlns_id_t NS_ooxml_r;
+extern const xmlns_id_t NS_ooxml_xlsx;
+extern const xmlns_id_t NS_ooxml_xdr;
+
+extern const xmlns_id_t NS_opc_ct;
+extern const xmlns_id_t NS_opc_rel;
+
+extern const xmlns_id_t NS_mc;
+extern const xmlns_id_t NS_mso_x14;
+
+/**
+ * Null-terminated array of all ooxml namespaces.
+ */
+extern const xmlns_id_t* NS_ooxml_all;
+
+/**
+ * Null-terminated array of all opc namespaces.
+ */
+extern const xmlns_id_t* NS_opc_all;
+
+/**
+ * Null-terminated array of all the other namespaces.
+ */
+extern const xmlns_id_t* NS_misc_all;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_schemas.cpp b/src/liborcus/ooxml_schemas.cpp
new file mode 100644
index 0000000..b0e86e4
--- /dev/null
+++ b/src/liborcus/ooxml_schemas.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_schemas.hpp"
+
+namespace orcus {
+
+schema_t SCH_mc = "http://schemas.openxmlformats.org/markup-compatibility/2006";
+schema_t SCH_opc_content_types = "http://schemas.openxmlformats.org/package/2006/content-types";
+schema_t SCH_opc_rels = "http://schemas.openxmlformats.org/package/2006/relationships";
+schema_t SCH_opc_rels_metadata_core_props = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+schema_t SCH_od_rels_calc_chain = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain";
+schema_t SCH_od_rels_connections = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections";
+schema_t SCH_od_rels_printer_settings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/printerSettings";
+schema_t SCH_od_rels_rev_headers = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionHeaders";
+schema_t SCH_od_rels_rev_log = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog";
+schema_t SCH_od_rels_shared_strings = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
+schema_t SCH_od_rels_styles = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
+schema_t SCH_od_rels_theme = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
+schema_t SCH_od_rels_usernames = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/usernames";
+schema_t SCH_od_rels_worksheet = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
+schema_t SCH_od_rels_extended_props = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
+schema_t SCH_od_rels_office_doc = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
+schema_t SCH_od_rels_table = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table";
+schema_t SCH_od_rels_pivot_cache_def = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition";
+schema_t SCH_od_rels_pivot_cache_rec = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords";
+schema_t SCH_od_rels_pivot_table = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable";
+schema_t SCH_od_rels_drawing = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
+schema_t SCH_xlsx_main = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
+schema_t SCH_mso_x14ac = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac";
+
+namespace {
+
+schema_t schs[] = {
+ SCH_mc,
+ SCH_opc_content_types,
+ SCH_opc_rels,
+ SCH_opc_rels_metadata_core_props,
+ SCH_od_rels_calc_chain,
+ SCH_od_rels_connections,
+ SCH_od_rels_printer_settings,
+ SCH_od_rels_rev_headers,
+ SCH_od_rels_rev_log,
+ SCH_od_rels_shared_strings,
+ SCH_od_rels_styles,
+ SCH_od_rels_theme,
+ SCH_od_rels_usernames,
+ SCH_od_rels_worksheet,
+ SCH_od_rels_extended_props,
+ SCH_od_rels_office_doc,
+ SCH_od_rels_table,
+ SCH_od_rels_pivot_cache_def,
+ SCH_od_rels_pivot_cache_rec,
+ SCH_od_rels_pivot_table,
+ SCH_od_rels_drawing,
+ SCH_xlsx_main,
+ SCH_mso_x14ac,
+ nullptr
+};
+
+}
+
+schema_t* SCH_all = schs;
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_schemas.hpp b/src/liborcus/ooxml_schemas.hpp
new file mode 100644
index 0000000..85adb6f
--- /dev/null
+++ b/src/liborcus/ooxml_schemas.hpp
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OOXML_SCHEMAS_HPP
+#define INCLUDED_ORCUS_OOXML_SCHEMAS_HPP
+
+#include "ooxml_types.hpp"
+
+namespace orcus {
+
+extern schema_t SCH_mc;
+extern schema_t SCH_opc_content_types;
+extern schema_t SCH_opc_rels;
+extern schema_t SCH_opc_rels_metadata_core_props;
+extern schema_t SCH_od_rels_calc_chain;
+extern schema_t SCH_od_rels_connections;
+extern schema_t SCH_od_rels_printer_settings;
+extern schema_t SCH_od_rels_rev_headers;
+extern schema_t SCH_od_rels_rev_log;
+extern schema_t SCH_od_rels_shared_strings;
+extern schema_t SCH_od_rels_styles;
+extern schema_t SCH_od_rels_theme;
+extern schema_t SCH_od_rels_usernames;
+extern schema_t SCH_od_rels_worksheet;
+extern schema_t SCH_od_rels_extended_props;
+extern schema_t SCH_od_rels_office_doc;
+extern schema_t SCH_od_rels_table;
+extern schema_t SCH_od_rels_pivot_cache_def;
+extern schema_t SCH_od_rels_pivot_cache_rec;
+extern schema_t SCH_od_rels_pivot_table;
+extern schema_t SCH_od_rels_drawing;
+extern schema_t SCH_xlsx_main;
+extern schema_t SCH_mso_x14ac;
+
+/**
+ * Null-terminated array of all schema types.
+ */
+extern schema_t* SCH_all;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_token_constants.hpp b/src/liborcus/ooxml_token_constants.hpp
new file mode 100644
index 0000000..13f7fcf
--- /dev/null
+++ b/src/liborcus/ooxml_token_constants.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_OOXML_TOKEN_CONSTANTS_HPP__
+#define __ORCUS_OOXML_TOKEN_CONSTANTS_HPP__
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+#include "ooxml_token_constants.inl"
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_token_constants.inl b/src/liborcus/ooxml_token_constants.inl
new file mode 100644
index 0000000..c2a047d
--- /dev/null
+++ b/src/liborcus/ooxml_token_constants.inl
@@ -0,0 +1,3519 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const xml_token_t XML_AbbreviatedCaseNumber = 1;
+const xml_token_t XML_Accel = 2;
+const xml_token_t XML_Accel2 = 3;
+const xml_token_t XML_AlbumTitle = 4;
+const xml_token_t XML_AlternateContent = 5;
+const xml_token_t XML_Anchor = 6;
+const xml_token_t XML_AppVersion = 7;
+const xml_token_t XML_Append = 8;
+const xml_token_t XML_Application = 9;
+const xml_token_t XML_Artist = 10;
+const xml_token_t XML_Author = 11;
+const xml_token_t XML_AutoFill = 12;
+const xml_token_t XML_AutoFit = 13;
+const xml_token_t XML_AutoLine = 14;
+const xml_token_t XML_AutoPict = 15;
+const xml_token_t XML_AutoScale = 16;
+const xml_token_t XML_BookAuthor = 17;
+const xml_token_t XML_BookTitle = 18;
+const xml_token_t XML_BroadcastTitle = 19;
+const xml_token_t XML_Broadcaster = 20;
+const xml_token_t XML_CF = 21;
+const xml_token_t XML_Camera = 22;
+const xml_token_t XML_Cancel = 23;
+const xml_token_t XML_CaseNumber = 24;
+const xml_token_t XML_ChapterNumber = 25;
+const xml_token_t XML_Characters = 26;
+const xml_token_t XML_CharactersWithSpaces = 27;
+const xml_token_t XML_Checked = 28;
+const xml_token_t XML_Choice = 29;
+const xml_token_t XML_City = 30;
+const xml_token_t XML_ClientData = 31;
+const xml_token_t XML_ColHidden = 32;
+const xml_token_t XML_Colored = 33;
+const xml_token_t XML_Column = 34;
+const xml_token_t XML_Comments = 35;
+const xml_token_t XML_Company = 36;
+const xml_token_t XML_Compiler = 37;
+const xml_token_t XML_Composer = 38;
+const xml_token_t XML_Conductor = 39;
+const xml_token_t XML_ConferenceName = 40;
+const xml_token_t XML_ConnectionID = 41;
+const xml_token_t XML_Corporate = 42;
+const xml_token_t XML_Counsel = 43;
+const xml_token_t XML_CountryRegion = 44;
+const xml_token_t XML_Court = 45;
+const xml_token_t XML_DDE = 46;
+const xml_token_t XML_DataBinding = 47;
+const xml_token_t XML_DataBindingLoadMode = 48;
+const xml_token_t XML_DataBindingName = 49;
+const xml_token_t XML_Day = 50;
+const xml_token_t XML_DayAccessed = 51;
+const xml_token_t XML_Default = 52;
+const xml_token_t XML_DefaultSize = 53;
+const xml_token_t XML_Department = 54;
+const xml_token_t XML_DigSig = 55;
+const xml_token_t XML_Director = 56;
+const xml_token_t XML_Disabled = 57;
+const xml_token_t XML_Dismiss = 58;
+const xml_token_t XML_Distributor = 59;
+const xml_token_t XML_DocSecurity = 60;
+const xml_token_t XML_DrawAspect = 61;
+const xml_token_t XML_DropLines = 62;
+const xml_token_t XML_DropStyle = 63;
+const xml_token_t XML_Dx = 64;
+const xml_token_t XML_Edition = 65;
+const xml_token_t XML_Editor = 66;
+const xml_token_t XML_Fallback = 67;
+const xml_token_t XML_FieldCodes = 68;
+const xml_token_t XML_FileBinding = 69;
+const xml_token_t XML_FileBindingName = 70;
+const xml_token_t XML_First = 71;
+const xml_token_t XML_FirstButton = 72;
+const xml_token_t XML_FmlaGroup = 73;
+const xml_token_t XML_FmlaLink = 74;
+const xml_token_t XML_FmlaMacro = 75;
+const xml_token_t XML_FmlaPict = 76;
+const xml_token_t XML_FmlaRange = 77;
+const xml_token_t XML_FmlaTxbx = 78;
+const xml_token_t XML_Guid = 79;
+const xml_token_t XML_HLinks = 80;
+const xml_token_t XML_HeadingPairs = 81;
+const xml_token_t XML_Help = 82;
+const xml_token_t XML_HiddenSlides = 83;
+const xml_token_t XML_Horiz = 84;
+const xml_token_t XML_HyperlinkBase = 85;
+const xml_token_t XML_HyperlinksChanged = 86;
+const xml_token_t XML_ID = 87;
+const xml_token_t XML_Inc = 88;
+const xml_token_t XML_Institution = 89;
+const xml_token_t XML_InternetSiteTitle = 90;
+const xml_token_t XML_Interviewee = 91;
+const xml_token_t XML_Interviewer = 92;
+const xml_token_t XML_Inventor = 93;
+const xml_token_t XML_Issue = 94;
+const xml_token_t XML_JournalName = 95;
+const xml_token_t XML_JustLastX = 96;
+const xml_token_t XML_LCID = 97;
+const xml_token_t XML_LCT = 98;
+const xml_token_t XML_Last = 99;
+const xml_token_t XML_Lines = 100;
+const xml_token_t XML_LinkType = 101;
+const xml_token_t XML_LinksUpToDate = 102;
+const xml_token_t XML_ListItem = 103;
+const xml_token_t XML_LockText = 104;
+const xml_token_t XML_Locked = 105;
+const xml_token_t XML_LockedField = 106;
+const xml_token_t XML_MMClips = 107;
+const xml_token_t XML_Manager = 108;
+const xml_token_t XML_Map = 109;
+const xml_token_t XML_MapInfo = 110;
+const xml_token_t XML_MapOCX = 111;
+const xml_token_t XML_Max = 112;
+const xml_token_t XML_Medium = 113;
+const xml_token_t XML_Middle = 114;
+const xml_token_t XML_Min = 115;
+const xml_token_t XML_Month = 116;
+const xml_token_t XML_MonthAccessed = 117;
+const xml_token_t XML_MoveWithCells = 118;
+const xml_token_t XML_MultiLine = 119;
+const xml_token_t XML_MultiSel = 120;
+const xml_token_t XML_Name = 121;
+const xml_token_t XML_NameList = 122;
+const xml_token_t XML_Namespace = 123;
+const xml_token_t XML_NoThreeD = 124;
+const xml_token_t XML_NoThreeD2 = 125;
+const xml_token_t XML_Notes = 126;
+const xml_token_t XML_NumberVolumes = 127;
+const xml_token_t XML_OLEObject = 128;
+const xml_token_t XML_ObjectID = 129;
+const xml_token_t XML_ObjectType = 130;
+const xml_token_t XML_Page = 131;
+const xml_token_t XML_Pages = 132;
+const xml_token_t XML_Paragraphs = 133;
+const xml_token_t XML_PatentNumber = 134;
+const xml_token_t XML_Performer = 135;
+const xml_token_t XML_PeriodicalTitle = 136;
+const xml_token_t XML_Person = 137;
+const xml_token_t XML_PresentationFormat = 138;
+const xml_token_t XML_PreserveFormat = 139;
+const xml_token_t XML_PreserveSortAFLayout = 140;
+const xml_token_t XML_PrintObject = 141;
+const xml_token_t XML_ProducerName = 142;
+const xml_token_t XML_ProductionCompany = 143;
+const xml_token_t XML_ProgID = 144;
+const xml_token_t XML_Properties = 145;
+const xml_token_t XML_PublicationTitle = 146;
+const xml_token_t XML_Publisher = 147;
+const xml_token_t XML_RecalcAlways = 148;
+const xml_token_t XML_RecordingNumber = 149;
+const xml_token_t XML_RefOrder = 150;
+const xml_token_t XML_Reporter = 151;
+const xml_token_t XML_RootElement = 152;
+const xml_token_t XML_Row = 153;
+const xml_token_t XML_RowHidden = 154;
+const xml_token_t XML_ScaleCrop = 155;
+const xml_token_t XML_Schema = 156;
+const xml_token_t XML_SchemaID = 157;
+const xml_token_t XML_SchemaRef = 158;
+const xml_token_t XML_ScriptExtended = 159;
+const xml_token_t XML_ScriptLanguage = 160;
+const xml_token_t XML_ScriptLocation = 161;
+const xml_token_t XML_ScriptText = 162;
+const xml_token_t XML_SecretEdit = 163;
+const xml_token_t XML_Sel = 164;
+const xml_token_t XML_SelType = 165;
+const xml_token_t XML_SelectedStyle = 166;
+const xml_token_t XML_SelectionNamespaces = 167;
+const xml_token_t XML_ShapeID = 168;
+const xml_token_t XML_SharedDoc = 169;
+const xml_token_t XML_ShortTitle = 170;
+const xml_token_t XML_ShowImportExportValidationErrors = 171;
+const xml_token_t XML_SizeWithCells = 172;
+const xml_token_t XML_Slides = 173;
+const xml_token_t XML_Source = 174;
+const xml_token_t XML_SourceType = 175;
+const xml_token_t XML_Sources = 176;
+const xml_token_t XML_StandardNumber = 177;
+const xml_token_t XML_StateProvince = 178;
+const xml_token_t XML_Station = 179;
+const xml_token_t XML_StyleName = 180;
+const xml_token_t XML_Tag = 181;
+const xml_token_t XML_Template = 182;
+const xml_token_t XML_TextHAlign = 183;
+const xml_token_t XML_TextVAlign = 184;
+const xml_token_t XML_Theater = 185;
+const xml_token_t XML_ThesisType = 186;
+const xml_token_t XML_Title = 187;
+const xml_token_t XML_TitlesOfParts = 188;
+const xml_token_t XML_TotalTime = 189;
+const xml_token_t XML_Translator = 190;
+const xml_token_t XML_Type = 191;
+const xml_token_t XML_UIObj = 192;
+const xml_token_t XML_URI = 193;
+const xml_token_t XML_URL = 194;
+const xml_token_t XML_UpdateMode = 195;
+const xml_token_t XML_VScroll = 196;
+const xml_token_t XML_VTEdit = 197;
+const xml_token_t XML_Val = 198;
+const xml_token_t XML_ValidIds = 199;
+const xml_token_t XML_Version = 200;
+const xml_token_t XML_Visible = 201;
+const xml_token_t XML_Volume = 202;
+const xml_token_t XML_WidthMin = 203;
+const xml_token_t XML_Words = 204;
+const xml_token_t XML_Writer = 205;
+const xml_token_t XML_Year = 206;
+const xml_token_t XML_YearAccessed = 207;
+const xml_token_t XML_a = 208;
+const xml_token_t XML_aboveAverage = 209;
+const xml_token_t XML_absSizeAnchor = 210;
+const xml_token_t XML_absoluteAnchor = 211;
+const xml_token_t XML_abstractNum = 212;
+const xml_token_t XML_abstractNumId = 213;
+const xml_token_t XML_aca = 214;
+const xml_token_t XML_acc = 215;
+const xml_token_t XML_accPr = 216;
+const xml_token_t XML_accel = 217;
+const xml_token_t XML_accent1 = 218;
+const xml_token_t XML_accent2 = 219;
+const xml_token_t XML_accent3 = 220;
+const xml_token_t XML_accent4 = 221;
+const xml_token_t XML_accent5 = 222;
+const xml_token_t XML_accent6 = 223;
+const xml_token_t XML_accentbar = 224;
+const xml_token_t XML_accumulate = 225;
+const xml_token_t XML_action = 226;
+const xml_token_t XML_active = 227;
+const xml_token_t XML_activeCell = 228;
+const xml_token_t XML_activeCellId = 229;
+const xml_token_t XML_activeCol = 230;
+const xml_token_t XML_activePane = 231;
+const xml_token_t XML_activeRecord = 232;
+const xml_token_t XML_activeRow = 233;
+const xml_token_t XML_activeSheetId = 234;
+const xml_token_t XML_activeTab = 235;
+const xml_token_t XML_activeWritingStyle = 236;
+const xml_token_t XML_actualPg = 237;
+const xml_token_t XML_additionalCharacteristics = 238;
+const xml_token_t XML_additive = 239;
+const xml_token_t XML_addlxml = 240;
+const xml_token_t XML_addressFieldName = 241;
+const xml_token_t XML_adj = 242;
+const xml_token_t XML_adjLst = 243;
+const xml_token_t XML_adjust = 244;
+const xml_token_t XML_adjustColumnWidth = 245;
+const xml_token_t XML_adjustLineHeightInTable = 246;
+const xml_token_t XML_adjustRightInd = 247;
+const xml_token_t XML_adjusthandles = 248;
+const xml_token_t XML_advAuto = 249;
+const xml_token_t XML_advClick = 250;
+const xml_token_t XML_advTm = 251;
+const xml_token_t XML_advise = 252;
+const xml_token_t XML_after = 253;
+const xml_token_t XML_afterAutospacing = 254;
+const xml_token_t XML_afterEffect = 255;
+const xml_token_t XML_afterLines = 256;
+const xml_token_t XML_ahLst = 257;
+const xml_token_t XML_ahPolar = 258;
+const xml_token_t XML_ahXY = 259;
+const xml_token_t XML_alg = 260;
+const xml_token_t XML_algIdExt = 261;
+const xml_token_t XML_algIdExtSource = 262;
+const xml_token_t XML_algn = 263;
+const xml_token_t XML_alias = 264;
+const xml_token_t XML_aliases = 265;
+const xml_token_t XML_align = 266;
+const xml_token_t XML_alignBordersAndEdges = 267;
+const xml_token_t XML_alignTablesRowByRow = 268;
+const xml_token_t XML_alignWithMargins = 269;
+const xml_token_t XML_alignment = 270;
+const xml_token_t XML_alignshape = 271;
+const xml_token_t XML_all = 272;
+const xml_token_t XML_allCaption = 273;
+const xml_token_t XML_allDrilled = 274;
+const xml_token_t XML_allUniqueName = 275;
+const xml_token_t XML_allowBlank = 276;
+const xml_token_t XML_allowOverlap = 277;
+const xml_token_t XML_allowPNG = 278;
+const xml_token_t XML_allowPng = 279;
+const xml_token_t XML_allowRefreshQuery = 280;
+const xml_token_t XML_allowSpaceOfSameStyleInTable = 281;
+const xml_token_t XML_allowcomments = 282;
+const xml_token_t XML_allowincell = 283;
+const xml_token_t XML_allowoverlap = 284;
+const xml_token_t XML_aln = 285;
+const xml_token_t XML_alnAt = 286;
+const xml_token_t XML_alnScr = 287;
+const xml_token_t XML_alpha = 288;
+const xml_token_t XML_alphaBiLevel = 289;
+const xml_token_t XML_alphaCeiling = 290;
+const xml_token_t XML_alphaFloor = 291;
+const xml_token_t XML_alphaInv = 292;
+const xml_token_t XML_alphaMod = 293;
+const xml_token_t XML_alphaModFix = 294;
+const xml_token_t XML_alphaOff = 295;
+const xml_token_t XML_alphaOutset = 296;
+const xml_token_t XML_alphaRepl = 297;
+const xml_token_t XML_alt = 298;
+const xml_token_t XML_altChunk = 299;
+const xml_token_t XML_altChunkPr = 300;
+const xml_token_t XML_altLang = 301;
+const xml_token_t XML_altName = 302;
+const xml_token_t XML_althref = 303;
+const xml_token_t XML_alwaysMergeEmptyNamespace = 304;
+const xml_token_t XML_alwaysShow = 305;
+const xml_token_t XML_alwaysShowPlaceholderText = 306;
+const xml_token_t XML_amt = 307;
+const xml_token_t XML_anchor = 308;
+const xml_token_t XML_anchorCtr = 309;
+const xml_token_t XML_anchorLock = 310;
+const xml_token_t XML_anchorlock = 311;
+const xml_token_t XML_anchorx = 312;
+const xml_token_t XML_anchory = 313;
+const xml_token_t XML_and = 314;
+const xml_token_t XML_ang = 315;
+const xml_token_t XML_angle = 316;
+const xml_token_t XML_anim = 317;
+const xml_token_t XML_animBg = 318;
+const xml_token_t XML_animClr = 319;
+const xml_token_t XML_animEffect = 320;
+const xml_token_t XML_animLvl = 321;
+const xml_token_t XML_animMotion = 322;
+const xml_token_t XML_animOne = 323;
+const xml_token_t XML_animRot = 324;
+const xml_token_t XML_animScale = 325;
+const xml_token_t XML_annotation = 326;
+const xml_token_t XML_annotationRef = 327;
+const xml_token_t XML_appName = 328;
+const xml_token_t XML_applyAlignment = 329;
+const xml_token_t XML_applyAlignmentFormats = 330;
+const xml_token_t XML_applyBorder = 331;
+const xml_token_t XML_applyBorderFormats = 332;
+const xml_token_t XML_applyBreakingRules = 333;
+const xml_token_t XML_applyFill = 334;
+const xml_token_t XML_applyFont = 335;
+const xml_token_t XML_applyFontFormats = 336;
+const xml_token_t XML_applyNumberFormat = 337;
+const xml_token_t XML_applyNumberFormats = 338;
+const xml_token_t XML_applyPatternFormats = 339;
+const xml_token_t XML_applyProtection = 340;
+const xml_token_t XML_applyStyles = 341;
+const xml_token_t XML_applyToEnd = 342;
+const xml_token_t XML_applyToFront = 343;
+const xml_token_t XML_applyToSides = 344;
+const xml_token_t XML_applyWidthHeightFormats = 345;
+const xml_token_t XML_arc = 346;
+const xml_token_t XML_arcTo = 347;
+const xml_token_t XML_arcsize = 348;
+const xml_token_t XML_area3DChart = 349;
+const xml_token_t XML_areaChart = 350;
+const xml_token_t XML_arg = 351;
+const xml_token_t XML_argPr = 352;
+const xml_token_t XML_argSz = 353;
+const xml_token_t XML_array = 354;
+const xml_token_t XML_arrowok = 355;
+const xml_token_t XML_ascii = 356;
+const xml_token_t XML_asciiTheme = 357;
+const xml_token_t XML_aspect = 358;
+const xml_token_t XML_aspectratio = 359;
+const xml_token_t XML_assign = 360;
+const xml_token_t XML_asteriskTotals = 361;
+const xml_token_t XML_attachedSchema = 362;
+const xml_token_t XML_attachedTemplate = 363;
+const xml_token_t XML_attr = 364;
+const xml_token_t XML_attrName = 365;
+const xml_token_t XML_attrNameLst = 366;
+const xml_token_t XML_attribute = 367;
+const xml_token_t XML_audio = 368;
+const xml_token_t XML_audioCd = 369;
+const xml_token_t XML_audioFile = 370;
+const xml_token_t XML_author = 371;
+const xml_token_t XML_authorId = 372;
+const xml_token_t XML_authors = 373;
+const xml_token_t XML_auto = 374;
+const xml_token_t XML_autoAdjust = 375;
+const xml_token_t XML_autoCaption = 376;
+const xml_token_t XML_autoCaptions = 377;
+const xml_token_t XML_autoCompressPictures = 378;
+const xml_token_t XML_autoEnd = 379;
+const xml_token_t XML_autoFilter = 380;
+const xml_token_t XML_autoFilterDateGrouping = 381;
+const xml_token_t XML_autoFormatId = 382;
+const xml_token_t XML_autoFormatOverride = 383;
+const xml_token_t XML_autoHyphenation = 384;
+const xml_token_t XML_autoLoad = 385;
+const xml_token_t XML_autoPage = 386;
+const xml_token_t XML_autoPageBreaks = 387;
+const xml_token_t XML_autoRecover = 388;
+const xml_token_t XML_autoRedefine = 389;
+const xml_token_t XML_autoRepublish = 390;
+const xml_token_t XML_autoRev = 391;
+const xml_token_t XML_autoShow = 392;
+const xml_token_t XML_autoSortScope = 393;
+const xml_token_t XML_autoSpaceDE = 394;
+const xml_token_t XML_autoSpaceDN = 395;
+const xml_token_t XML_autoSpaceLikeWord95 = 396;
+const xml_token_t XML_autoStart = 397;
+const xml_token_t XML_autoTitleDeleted = 398;
+const xml_token_t XML_autoUpdate = 399;
+const xml_token_t XML_autoUpdateAnimBg = 400;
+const xml_token_t XML_autofitToFirstFixedWidthCell = 401;
+const xml_token_t XML_autoformat = 402;
+const xml_token_t XML_autolayout = 403;
+const xml_token_t XML_autorotationcenter = 404;
+const xml_token_t XML_avLst = 405;
+const xml_token_t XML_avgSubtotal = 406;
+const xml_token_t XML_axId = 407;
+const xml_token_t XML_axPos = 408;
+const xml_token_t XML_axis = 409;
+const xml_token_t XML_b = 410;
+const xml_token_t XML_bCs = 411;
+const xml_token_t XML_bIns = 412;
+const xml_token_t XML_backWall = 413;
+const xml_token_t XML_backdepth = 414;
+const xml_token_t XML_backdrop = 415;
+const xml_token_t XML_background = 416;
+const xml_token_t XML_backgroundQuery = 417;
+const xml_token_t XML_backgroundRefresh = 418;
+const xml_token_t XML_backupFile = 419;
+const xml_token_t XML_backward = 420;
+const xml_token_t XML_backwards = 421;
+const xml_token_t XML_balanceSingleByteDoubleByteWidth = 422;
+const xml_token_t XML_band1H = 423;
+const xml_token_t XML_band1V = 424;
+const xml_token_t XML_band2H = 425;
+const xml_token_t XML_band2V = 426;
+const xml_token_t XML_bandCol = 427;
+const xml_token_t XML_bandFmt = 428;
+const xml_token_t XML_bandFmts = 429;
+const xml_token_t XML_bandRow = 430;
+const xml_token_t XML_bar = 431;
+const xml_token_t XML_bar3DChart = 432;
+const xml_token_t XML_barChart = 433;
+const xml_token_t XML_barDir = 434;
+const xml_token_t XML_barPr = 435;
+const xml_token_t XML_base = 436;
+const xml_token_t XML_baseColWidth = 437;
+const xml_token_t XML_baseField = 438;
+const xml_token_t XML_baseItem = 439;
+const xml_token_t XML_baseJc = 440;
+const xml_token_t XML_baseTimeUnit = 441;
+const xml_token_t XML_baseType = 442;
+const xml_token_t XML_basedOn = 443;
+const xml_token_t XML_baseline = 444;
+const xml_token_t XML_bc = 445;
+const xml_token_t XML_bdr = 446;
+const xml_token_t XML_before = 447;
+const xml_token_t XML_beforeAutospacing = 448;
+const xml_token_t XML_beforeLines = 449;
+const xml_token_t XML_begChr = 450;
+const xml_token_t XML_behavior = 451;
+const xml_token_t XML_behaviors = 452;
+const xml_token_t XML_behindDoc = 453;
+const xml_token_t XML_bestFit = 454;
+const xml_token_t XML_between = 455;
+const xml_token_t XML_bevel = 456;
+const xml_token_t XML_bevelB = 457;
+const xml_token_t XML_bevelT = 458;
+const xml_token_t XML_bg = 459;
+const xml_token_t XML_bg1 = 460;
+const xml_token_t XML_bg2 = 461;
+const xml_token_t XML_bgClr = 462;
+const xml_token_t XML_bgColor = 463;
+const xml_token_t XML_bgFillStyleLst = 464;
+const xml_token_t XML_bgPr = 465;
+const xml_token_t XML_bgRef = 466;
+const xml_token_t XML_biLevel = 467;
+const xml_token_t XML_bibliography = 468;
+const xml_token_t XML_bidi = 469;
+const xml_token_t XML_bidiVisual = 470;
+const xml_token_t XML_bilevel = 471;
+const xml_token_t XML_bk = 472;
+const xml_token_t XML_blackAndWhite = 473;
+const xml_token_t XML_blacklevel = 474;
+const xml_token_t XML_blank = 475;
+const xml_token_t XML_bld = 476;
+const xml_token_t XML_bldAsOne = 477;
+const xml_token_t XML_bldChart = 478;
+const xml_token_t XML_bldDgm = 479;
+const xml_token_t XML_bldGraphic = 480;
+const xml_token_t XML_bldLst = 481;
+const xml_token_t XML_bldLvl = 482;
+const xml_token_t XML_bldOleChart = 483;
+const xml_token_t XML_bldP = 484;
+const xml_token_t XML_bldStep = 485;
+const xml_token_t XML_bldSub = 486;
+const xml_token_t XML_blend = 487;
+const xml_token_t XML_blinds = 488;
+const xml_token_t XML_blip = 489;
+const xml_token_t XML_blipFill = 490;
+const xml_token_t XML_blipPhldr = 491;
+const xml_token_t XML_blob = 492;
+const xml_token_t XML_blockQuote = 493;
+const xml_token_t XML_blue = 494;
+const xml_token_t XML_blueMod = 495;
+const xml_token_t XML_blueOff = 496;
+const xml_token_t XML_blur = 497;
+const xml_token_t XML_blurRad = 498;
+const xml_token_t XML_bmk = 499;
+const xml_token_t XML_body = 500;
+const xml_token_t XML_bodyDiv = 501;
+const xml_token_t XML_bodyPr = 502;
+const xml_token_t XML_bodyStyle = 503;
+const xml_token_t XML_bold = 504;
+const xml_token_t XML_boldItalic = 505;
+const xml_token_t XML_bookFoldPrinting = 506;
+const xml_token_t XML_bookFoldPrintingSheets = 507;
+const xml_token_t XML_bookFoldRevPrinting = 508;
+const xml_token_t XML_bookViews = 509;
+const xml_token_t XML_bookmarkEnd = 510;
+const xml_token_t XML_bookmarkIdSeed = 511;
+const xml_token_t XML_bookmarkStart = 512;
+const xml_token_t XML_bool = 513;
+const xml_token_t XML_boolVal = 514;
+const xml_token_t XML_boolean = 515;
+const xml_token_t XML_border = 516;
+const xml_token_t XML_borderBox = 517;
+const xml_token_t XML_borderBoxPr = 518;
+const xml_token_t XML_borderId = 519;
+const xml_token_t XML_borderbottom = 520;
+const xml_token_t XML_borderbottomcolor = 521;
+const xml_token_t XML_borderleft = 522;
+const xml_token_t XML_borderleftcolor = 523;
+const xml_token_t XML_borderright = 524;
+const xml_token_t XML_borderrightcolor = 525;
+const xml_token_t XML_borders = 526;
+const xml_token_t XML_bordersDoNotSurroundFooter = 527;
+const xml_token_t XML_bordersDoNotSurroundHeader = 528;
+const xml_token_t XML_bordertop = 529;
+const xml_token_t XML_bordertopcolor = 530;
+const xml_token_t XML_bottom = 531;
+const xml_token_t XML_bottomFromText = 532;
+const xml_token_t XML_box = 533;
+const xml_token_t XML_boxPr = 534;
+const xml_token_t XML_br = 535;
+const xml_token_t XML_bright = 536;
+const xml_token_t XML_brightness = 537;
+const xml_token_t XML_brk = 538;
+const xml_token_t XML_brkBin = 539;
+const xml_token_t XML_brkBinSub = 540;
+const xml_token_t XML_browse = 541;
+const xml_token_t XML_bstr = 542;
+const xml_token_t XML_buAutoNum = 543;
+const xml_token_t XML_buBlip = 544;
+const xml_token_t XML_buChar = 545;
+const xml_token_t XML_buClr = 546;
+const xml_token_t XML_buClrTx = 547;
+const xml_token_t XML_buFont = 548;
+const xml_token_t XML_buFontTx = 549;
+const xml_token_t XML_buNone = 550;
+const xml_token_t XML_buSzPct = 551;
+const xml_token_t XML_buSzPts = 552;
+const xml_token_t XML_buSzTx = 553;
+const xml_token_t XML_bubble3D = 554;
+const xml_token_t XML_bubbleChart = 555;
+const xml_token_t XML_bubbleScale = 556;
+const xml_token_t XML_bubbleSize = 557;
+const xml_token_t XML_build = 558;
+const xml_token_t XML_builtIn = 559;
+const xml_token_t XML_builtInGroupCount = 560;
+const xml_token_t XML_builtInUnit = 561;
+const xml_token_t XML_builtinId = 562;
+const xml_token_t XML_bullet = 563;
+const xml_token_t XML_bulletEnabled = 564;
+const xml_token_t XML_button = 565;
+const xml_token_t XML_bw = 566;
+const xml_token_t XML_bwMode = 567;
+const xml_token_t XML_bwmode = 568;
+const xml_token_t XML_bwnormal = 569;
+const xml_token_t XML_bwpure = 570;
+const xml_token_t XML_bx = 571;
+const xml_token_t XML_by = 572;
+const xml_token_t XML_byPosition = 573;
+const xml_token_t XML_c = 574;
+const xml_token_t XML_cBhvr = 575;
+const xml_token_t XML_cGp = 576;
+const xml_token_t XML_cGpRule = 577;
+const xml_token_t XML_cMediaNode = 578;
+const xml_token_t XML_cNvCxnSpPr = 579;
+const xml_token_t XML_cNvGraphicFramePr = 580;
+const xml_token_t XML_cNvGrpSpPr = 581;
+const xml_token_t XML_cNvPicPr = 582;
+const xml_token_t XML_cNvPr = 583;
+const xml_token_t XML_cNvSpPr = 584;
+const xml_token_t XML_cSld = 585;
+const xml_token_t XML_cSldViewPr = 586;
+const xml_token_t XML_cSp = 587;
+const xml_token_t XML_cTn = 588;
+const xml_token_t XML_cViewPr = 589;
+const xml_token_t XML_ca = 590;
+const xml_token_t XML_cacheField = 591;
+const xml_token_t XML_cacheFields = 592;
+const xml_token_t XML_cacheHierarchies = 593;
+const xml_token_t XML_cacheHierarchy = 594;
+const xml_token_t XML_cacheId = 595;
+const xml_token_t XML_cacheIndex = 596;
+const xml_token_t XML_cacheSource = 597;
+const xml_token_t XML_cachedColBalance = 598;
+const xml_token_t XML_calcChain = 599;
+const xml_token_t XML_calcCompleted = 600;
+const xml_token_t XML_calcId = 601;
+const xml_token_t XML_calcMode = 602;
+const xml_token_t XML_calcOnExit = 603;
+const xml_token_t XML_calcOnSave = 604;
+const xml_token_t XML_calcPr = 605;
+const xml_token_t XML_calcmode = 606;
+const xml_token_t XML_calculatedColumn = 607;
+const xml_token_t XML_calculatedColumnFormula = 608;
+const xml_token_t XML_calculatedItem = 609;
+const xml_token_t XML_calculatedItems = 610;
+const xml_token_t XML_calculatedMember = 611;
+const xml_token_t XML_calculatedMembers = 612;
+const xml_token_t XML_calendar = 613;
+const xml_token_t XML_calendarType = 614;
+const xml_token_t XML_callout = 615;
+const xml_token_t XML_camera = 616;
+const xml_token_t XML_cantSplit = 617;
+const xml_token_t XML_cap = 618;
+const xml_token_t XML_caps = 619;
+const xml_token_t XML_caption = 620;
+const xml_token_t XML_captions = 621;
+const xml_token_t XML_caseSensitive = 622;
+const xml_token_t XML_cat = 623;
+const xml_token_t XML_catAx = 624;
+const xml_token_t XML_catLst = 625;
+const xml_token_t XML_category = 626;
+const xml_token_t XML_categoryIdx = 627;
+const xml_token_t XML_cell = 628;
+const xml_token_t XML_cell3D = 629;
+const xml_token_t XML_cellColor = 630;
+const xml_token_t XML_cellComments = 631;
+const xml_token_t XML_cellDel = 632;
+const xml_token_t XML_cellIns = 633;
+const xml_token_t XML_cellMerge = 634;
+const xml_token_t XML_cellMeta = 635;
+const xml_token_t XML_cellMetadata = 636;
+const xml_token_t XML_cellSmartTag = 637;
+const xml_token_t XML_cellSmartTagPr = 638;
+const xml_token_t XML_cellSmartTags = 639;
+const xml_token_t XML_cellStyle = 640;
+const xml_token_t XML_cellStyleXfs = 641;
+const xml_token_t XML_cellStyles = 642;
+const xml_token_t XML_cellWatch = 643;
+const xml_token_t XML_cellWatches = 644;
+const xml_token_t XML_cellXfs = 645;
+const xml_token_t XML_cf = 646;
+const xml_token_t XML_cfRule = 647;
+const xml_token_t XML_cfvo = 648;
+const xml_token_t XML_chExt = 649;
+const xml_token_t XML_chMax = 650;
+const xml_token_t XML_chOff = 651;
+const xml_token_t XML_chOrder = 652;
+const xml_token_t XML_chPref = 653;
+const xml_token_t XML_changesSavedWin = 654;
+const xml_token_t XML_chapNum = 655;
+const xml_token_t XML_chapSep = 656;
+const xml_token_t XML_chapStyle = 657;
+const xml_token_t XML_char = 658;
+const xml_token_t XML_charRg = 659;
+const xml_token_t XML_charSpace = 660;
+const xml_token_t XML_characterSpacingControl = 661;
+const xml_token_t XML_characteristic = 662;
+const xml_token_t XML_charset = 663;
+const xml_token_t XML_chart = 664;
+const xml_token_t XML_chartFormat = 665;
+const xml_token_t XML_chartFormats = 666;
+const xml_token_t XML_chartObject = 667;
+const xml_token_t XML_chartSpace = 668;
+const xml_token_t XML_chartsheet = 669;
+const xml_token_t XML_checkBox = 670;
+const xml_token_t XML_checkCompatibility = 671;
+const xml_token_t XML_checkErrors = 672;
+const xml_token_t XML_checkStyle = 673;
+const xml_token_t XML_checked = 674;
+const xml_token_t XML_checker = 675;
+const xml_token_t XML_childTnLst = 676;
+const xml_token_t XML_choose = 677;
+const xml_token_t XML_chr = 678;
+const xml_token_t XML_chromakey = 679;
+const xml_token_t XML_circle = 680;
+const xml_token_t XML_citation = 681;
+const xml_token_t XML_class = 682;
+const xml_token_t XML_clear = 683;
+const xml_token_t XML_clearAll = 684;
+const xml_token_t XML_clearComments = 685;
+const xml_token_t XML_clearContents = 686;
+const xml_token_t XML_clearFormats = 687;
+const xml_token_t XML_click = 688;
+const xml_token_t XML_clickAndTypeStyle = 689;
+const xml_token_t XML_clientData = 690;
+const xml_token_t XML_clientInsertedTime = 691;
+const xml_token_t XML_clip = 692;
+const xml_token_t XML_clippath = 693;
+const xml_token_t XML_clipped = 694;
+const xml_token_t XML_cliptowrap = 695;
+const xml_token_t XML_close = 696;
+const xml_token_t XML_clr = 697;
+const xml_token_t XML_clrChange = 698;
+const xml_token_t XML_clrData = 699;
+const xml_token_t XML_clrFrom = 700;
+const xml_token_t XML_clrIdx = 701;
+const xml_token_t XML_clrMap = 702;
+const xml_token_t XML_clrMapOvr = 703;
+const xml_token_t XML_clrMode = 704;
+const xml_token_t XML_clrMru = 705;
+const xml_token_t XML_clrRepl = 706;
+const xml_token_t XML_clrScheme = 707;
+const xml_token_t XML_clrSchemeMapping = 708;
+const xml_token_t XML_clrSpc = 709;
+const xml_token_t XML_clrTo = 710;
+const xml_token_t XML_clrVal = 711;
+const xml_token_t XML_clsid = 712;
+const xml_token_t XML_cm = 713;
+const xml_token_t XML_cmAuthor = 714;
+const xml_token_t XML_cmAuthorLst = 715;
+const xml_token_t XML_cmLst = 716;
+const xml_token_t XML_cmd = 717;
+const xml_token_t XML_cmpd = 718;
+const xml_token_t XML_cnfStyle = 719;
+const xml_token_t XML_cnt = 720;
+const xml_token_t XML_code = 721;
+const xml_token_t XML_codeName = 722;
+const xml_token_t XML_codePage = 723;
+const xml_token_t XML_coerce = 724;
+const xml_token_t XML_coherent3DOff = 725;
+const xml_token_t XML_col = 726;
+const xml_token_t XML_colBreaks = 727;
+const xml_token_t XML_colDelim = 728;
+const xml_token_t XML_colFields = 729;
+const xml_token_t XML_colFirst = 730;
+const xml_token_t XML_colGrandTotals = 731;
+const xml_token_t XML_colHeaderCaption = 732;
+const xml_token_t XML_colHierarchiesUsage = 733;
+const xml_token_t XML_colHierarchyUsage = 734;
+const xml_token_t XML_colId = 735;
+const xml_token_t XML_colItems = 736;
+const xml_token_t XML_colLast = 737;
+const xml_token_t XML_colOff = 738;
+const xml_token_t XML_colPageCount = 739;
+const xml_token_t XML_collapse = 740;
+const xml_token_t XML_collapsed = 741;
+const xml_token_t XML_collapsedLevelsAreSubtotals = 742;
+const xml_token_t XML_color = 743;
+const xml_token_t XML_color2 = 744;
+const xml_token_t XML_colorFilter = 745;
+const xml_token_t XML_colorId = 746;
+const xml_token_t XML_colorScale = 747;
+const xml_token_t XML_colormenu = 748;
+const xml_token_t XML_colormode = 749;
+const xml_token_t XML_colormru = 750;
+const xml_token_t XML_colors = 751;
+const xml_token_t XML_colorsDef = 752;
+const xml_token_t XML_colorsDefHdr = 753;
+const xml_token_t XML_colorsDefHdrLst = 754;
+const xml_token_t XML_cols = 755;
+const xml_token_t XML_column = 756;
+const xml_token_t XML_columnSort = 757;
+const xml_token_t XML_comb = 758;
+const xml_token_t XML_combine = 759;
+const xml_token_t XML_combineBrackets = 760;
+const xml_token_t XML_comboBox = 761;
+const xml_token_t XML_comma = 762;
+const xml_token_t XML_command = 763;
+const xml_token_t XML_commandType = 764;
+const xml_token_t XML_comment = 765;
+const xml_token_t XML_commentList = 766;
+const xml_token_t XML_commentRangeEnd = 767;
+const xml_token_t XML_commentRangeStart = 768;
+const xml_token_t XML_commentReference = 769;
+const xml_token_t XML_comments = 770;
+const xml_token_t XML_comp = 771;
+const xml_token_t XML_compact = 772;
+const xml_token_t XML_compactData = 773;
+const xml_token_t XML_compat = 774;
+const xml_token_t XML_compatLnSpc = 775;
+const xml_token_t XML_compatMode = 776;
+const xml_token_t XML_complex = 777;
+const xml_token_t XML_concurrent = 778;
+const xml_token_t XML_concurrentCalc = 779;
+const xml_token_t XML_concurrentManualCount = 780;
+const xml_token_t XML_cond = 781;
+const xml_token_t XML_condense = 782;
+const xml_token_t XML_conditionalFormat = 783;
+const xml_token_t XML_conditionalFormats = 784;
+const xml_token_t XML_conditionalFormatting = 785;
+const xml_token_t XML_connectString = 786;
+const xml_token_t XML_connectangles = 787;
+const xml_token_t XML_connection = 788;
+const xml_token_t XML_connectionId = 789;
+const xml_token_t XML_connections = 790;
+const xml_token_t XML_connectloc = 791;
+const xml_token_t XML_connectlocs = 792;
+const xml_token_t XML_connectortype = 793;
+const xml_token_t XML_connecttype = 794;
+const xml_token_t XML_consecutive = 795;
+const xml_token_t XML_consecutiveHyphenLimit = 796;
+const xml_token_t XML_consolidation = 797;
+const xml_token_t XML_constr = 798;
+const xml_token_t XML_constrLst = 799;
+const xml_token_t XML_constrainbounds = 800;
+const xml_token_t XML_cont = 801;
+const xml_token_t XML_containsBlank = 802;
+const xml_token_t XML_containsDate = 803;
+const xml_token_t XML_containsInteger = 804;
+const xml_token_t XML_containsMixedTypes = 805;
+const xml_token_t XML_containsNonDate = 806;
+const xml_token_t XML_containsNumber = 807;
+const xml_token_t XML_containsSemiMixedTypes = 808;
+const xml_token_t XML_containsString = 809;
+const xml_token_t XML_content = 810;
+const xml_token_t XML_contextualSpacing = 811;
+const xml_token_t XML_continuationSeparator = 812;
+const xml_token_t XML_contourClr = 813;
+const xml_token_t XML_contourW = 814;
+const xml_token_t XML_contrast = 815;
+const xml_token_t XML_control = 816;
+const xml_token_t XML_control1 = 817;
+const xml_token_t XML_control2 = 818;
+const xml_token_t XML_controls = 819;
+const xml_token_t XML_convMailMergeEsc = 820;
+const xml_token_t XML_coordorigin = 821;
+const xml_token_t XML_coordsize = 822;
+const xml_token_t XML_copies = 823;
+const xml_token_t XML_copy = 824;
+const xml_token_t XML_count = 825;
+const xml_token_t XML_countASubtotal = 826;
+const xml_token_t XML_countBy = 827;
+const xml_token_t XML_countSubtotal = 828;
+const xml_token_t XML_cover = 829;
+const xml_token_t XML_cp = 830;
+const xml_token_t XML_cr = 831;
+const xml_token_t XML_crashSave = 832;
+const xml_token_t XML_createdVersion = 833;
+const xml_token_t XML_credentials = 834;
+const xml_token_t XML_cropbottom = 835;
+const xml_token_t XML_cropleft = 836;
+const xml_token_t XML_cropping = 837;
+const xml_token_t XML_cropright = 838;
+const xml_token_t XML_croptop = 839;
+const xml_token_t XML_crossAx = 840;
+const xml_token_t XML_crossBetween = 841;
+const xml_token_t XML_crosses = 842;
+const xml_token_t XML_crossesAt = 843;
+const xml_token_t XML_cryptAlgorithmClass = 844;
+const xml_token_t XML_cryptAlgorithmSid = 845;
+const xml_token_t XML_cryptAlgorithmType = 846;
+const xml_token_t XML_cryptProvider = 847;
+const xml_token_t XML_cryptProviderType = 848;
+const xml_token_t XML_cryptProviderTypeExt = 849;
+const xml_token_t XML_cryptProviderTypeExtSource = 850;
+const xml_token_t XML_cryptSpinCount = 851;
+const xml_token_t XML_cs = 852;
+const xml_token_t XML_csCatId = 853;
+const xml_token_t XML_csTypeId = 854;
+const xml_token_t XML_csb0 = 855;
+const xml_token_t XML_csb1 = 856;
+const xml_token_t XML_css = 857;
+const xml_token_t XML_cstate = 858;
+const xml_token_t XML_cstheme = 859;
+const xml_token_t XML_ct = 860;
+const xml_token_t XML_ctrlPr = 861;
+const xml_token_t XML_cubicBezTo = 862;
+const xml_token_t XML_culture = 863;
+const xml_token_t XML_current = 864;
+const xml_token_t XML_curve = 865;
+const xml_token_t XML_custAng = 866;
+const xml_token_t XML_custClr = 867;
+const xml_token_t XML_custClrLst = 868;
+const xml_token_t XML_custDash = 869;
+const xml_token_t XML_custData = 870;
+const xml_token_t XML_custDataLst = 871;
+const xml_token_t XML_custFlipHor = 872;
+const xml_token_t XML_custFlipVert = 873;
+const xml_token_t XML_custGeom = 874;
+const xml_token_t XML_custLinFactNeighborX = 875;
+const xml_token_t XML_custLinFactNeighborY = 876;
+const xml_token_t XML_custLinFactX = 877;
+const xml_token_t XML_custLinFactY = 878;
+const xml_token_t XML_custRadScaleInc = 879;
+const xml_token_t XML_custRadScaleRad = 880;
+const xml_token_t XML_custScaleX = 881;
+const xml_token_t XML_custScaleY = 882;
+const xml_token_t XML_custShow = 883;
+const xml_token_t XML_custShowLst = 884;
+const xml_token_t XML_custSplit = 885;
+const xml_token_t XML_custSzX = 886;
+const xml_token_t XML_custSzY = 887;
+const xml_token_t XML_custT = 888;
+const xml_token_t XML_custUnit = 889;
+const xml_token_t XML_customBuiltin = 890;
+const xml_token_t XML_customFilter = 891;
+const xml_token_t XML_customFilters = 892;
+const xml_token_t XML_customFormat = 893;
+const xml_token_t XML_customHeight = 894;
+const xml_token_t XML_customList = 895;
+const xml_token_t XML_customListSort = 896;
+const xml_token_t XML_customMarkFollows = 897;
+const xml_token_t XML_customMenu = 898;
+const xml_token_t XML_customPr = 899;
+const xml_token_t XML_customProperties = 900;
+const xml_token_t XML_customRollUp = 901;
+const xml_token_t XML_customSheetView = 902;
+const xml_token_t XML_customSheetViews = 903;
+const xml_token_t XML_customStyle = 904;
+const xml_token_t XML_customView = 905;
+const xml_token_t XML_customWidth = 906;
+const xml_token_t XML_customWorkbookView = 907;
+const xml_token_t XML_customWorkbookViews = 908;
+const xml_token_t XML_customXml = 909;
+const xml_token_t XML_customXmlDelRangeEnd = 910;
+const xml_token_t XML_customXmlDelRangeStart = 911;
+const xml_token_t XML_customXmlInsRangeEnd = 912;
+const xml_token_t XML_customXmlInsRangeStart = 913;
+const xml_token_t XML_customXmlMoveFromRangeEnd = 914;
+const xml_token_t XML_customXmlMoveFromRangeStart = 915;
+const xml_token_t XML_customXmlMoveToRangeEnd = 916;
+const xml_token_t XML_customXmlMoveToRangeStart = 917;
+const xml_token_t XML_customXmlPr = 918;
+const xml_token_t XML_cut = 919;
+const xml_token_t XML_cx = 920;
+const xml_token_t XML_cxn = 921;
+const xml_token_t XML_cxnId = 922;
+const xml_token_t XML_cxnLst = 923;
+const xml_token_t XML_cxnSp = 924;
+const xml_token_t XML_cxnSpLocks = 925;
+const xml_token_t XML_cy = 926;
+const xml_token_t XML_d = 927;
+const xml_token_t XML_dLbl = 928;
+const xml_token_t XML_dLblPos = 929;
+const xml_token_t XML_dLbls = 930;
+const xml_token_t XML_dPr = 931;
+const xml_token_t XML_dPt = 932;
+const xml_token_t XML_dTable = 933;
+const xml_token_t XML_dashstyle = 934;
+const xml_token_t XML_data = 935;
+const xml_token_t XML_dataBar = 936;
+const xml_token_t XML_dataBinding = 937;
+const xml_token_t XML_dataBound = 938;
+const xml_token_t XML_dataCaption = 939;
+const xml_token_t XML_dataCellStyle = 940;
+const xml_token_t XML_dataConsolidate = 941;
+const xml_token_t XML_dataDxfId = 942;
+const xml_token_t XML_dataExtractLoad = 943;
+const xml_token_t XML_dataField = 944;
+const xml_token_t XML_dataFields = 945;
+const xml_token_t XML_dataModel = 946;
+const xml_token_t XML_dataOnRows = 947;
+const xml_token_t XML_dataOnly = 948;
+const xml_token_t XML_dataPosition = 949;
+const xml_token_t XML_dataRef = 950;
+const xml_token_t XML_dataRefs = 951;
+const xml_token_t XML_dataSource = 952;
+const xml_token_t XML_dataSourceSort = 953;
+const xml_token_t XML_dataType = 954;
+const xml_token_t XML_dataValidation = 955;
+const xml_token_t XML_dataValidations = 956;
+const xml_token_t XML_databaseField = 957;
+const xml_token_t XML_datastoreItem = 958;
+const xml_token_t XML_date = 959;
+const xml_token_t XML_date1904 = 960;
+const xml_token_t XML_dateAx = 961;
+const xml_token_t XML_dateFormat = 962;
+const xml_token_t XML_dateGroupItem = 963;
+const xml_token_t XML_dateTime = 964;
+const xml_token_t XML_dateTimeGrouping = 965;
+const xml_token_t XML_day = 966;
+const xml_token_t XML_dayLong = 967;
+const xml_token_t XML_dayShort = 968;
+const xml_token_t XML_dbPr = 969;
+const xml_token_t XML_ddList = 970;
+const xml_token_t XML_ddeItem = 971;
+const xml_token_t XML_ddeItems = 972;
+const xml_token_t XML_ddeLink = 973;
+const xml_token_t XML_ddeService = 974;
+const xml_token_t XML_ddeTopic = 975;
+const xml_token_t XML_decel = 976;
+const xml_token_t XML_decimal = 977;
+const xml_token_t XML_decimalSymbol = 978;
+const xml_token_t XML_decorated = 979;
+const xml_token_t XML_def = 980;
+const xml_token_t XML_defJc = 981;
+const xml_token_t XML_defLockedState = 982;
+const xml_token_t XML_defPPr = 983;
+const xml_token_t XML_defQFormat = 984;
+const xml_token_t XML_defRPr = 985;
+const xml_token_t XML_defSemiHidden = 986;
+const xml_token_t XML_defStyle = 987;
+const xml_token_t XML_defTabSz = 988;
+const xml_token_t XML_defUIPriority = 989;
+const xml_token_t XML_defUnhideWhenUsed = 990;
+const xml_token_t XML_default = 991;
+const xml_token_t XML_defaultAttributeDrillState = 992;
+const xml_token_t XML_defaultColWidth = 993;
+const xml_token_t XML_defaultGridColor = 994;
+const xml_token_t XML_defaultMemberUniqueName = 995;
+const xml_token_t XML_defaultPivotStyle = 996;
+const xml_token_t XML_defaultRowHeight = 997;
+const xml_token_t XML_defaultSubtotal = 998;
+const xml_token_t XML_defaultTabStop = 999;
+const xml_token_t XML_defaultTableStyle = 1000;
+const xml_token_t XML_defaultTextStyle = 1001;
+const xml_token_t XML_defaultThemeVersion = 1002;
+const xml_token_t XML_definedName = 1003;
+const xml_token_t XML_definedNames = 1004;
+const xml_token_t XML_deg = 1005;
+const xml_token_t XML_degHide = 1006;
+const xml_token_t XML_degree = 1007;
+const xml_token_t XML_del = 1008;
+const xml_token_t XML_del1 = 1009;
+const xml_token_t XML_del2 = 1010;
+const xml_token_t XML_delInstrText = 1011;
+const xml_token_t XML_delText = 1012;
+const xml_token_t XML_delay = 1013;
+const xml_token_t XML_delete = 1014;
+const xml_token_t XML_deleteColumns = 1015;
+const xml_token_t XML_deleteRows = 1016;
+const xml_token_t XML_deleted = 1017;
+const xml_token_t XML_deletedField = 1018;
+const xml_token_t XML_delimited = 1019;
+const xml_token_t XML_delimiter = 1020;
+const xml_token_t XML_den = 1021;
+const xml_token_t XML_denormalized = 1022;
+const xml_token_t XML_depthPercent = 1023;
+const xml_token_t XML_desc = 1024;
+const xml_token_t XML_descending = 1025;
+const xml_token_t XML_descr = 1026;
+const xml_token_t XML_description = 1027;
+const xml_token_t XML_destId = 1028;
+const xml_token_t XML_destOrd = 1029;
+const xml_token_t XML_destination = 1030;
+const xml_token_t XML_destinationFile = 1031;
+const xml_token_t XML_detectmouseclick = 1032;
+const xml_token_t XML_dgm = 1033;
+const xml_token_t XML_dgmbasetextscale = 1034;
+const xml_token_t XML_dgmfontsize = 1035;
+const xml_token_t XML_dgmlayout = 1036;
+const xml_token_t XML_dgmlayoutmru = 1037;
+const xml_token_t XML_dgmnodekind = 1038;
+const xml_token_t XML_dgmscalex = 1039;
+const xml_token_t XML_dgmscaley = 1040;
+const xml_token_t XML_dgmstyle = 1041;
+const xml_token_t XML_diagonal = 1042;
+const xml_token_t XML_diagonalDown = 1043;
+const xml_token_t XML_diagonalUp = 1044;
+const xml_token_t XML_diagram = 1045;
+const xml_token_t XML_dialogsheet = 1046;
+const xml_token_t XML_diamond = 1047;
+const xml_token_t XML_diff = 1048;
+const xml_token_t XML_differentFirst = 1049;
+const xml_token_t XML_differentOddEven = 1050;
+const xml_token_t XML_diffusity = 1051;
+const xml_token_t XML_dimension = 1052;
+const xml_token_t XML_dimensionUniqueName = 1053;
+const xml_token_t XML_dimensions = 1054;
+const xml_token_t XML_dir = 1055;
+const xml_token_t XML_dirty = 1056;
+const xml_token_t XML_disableEdit = 1057;
+const xml_token_t XML_disableFieldList = 1058;
+const xml_token_t XML_disablePrompts = 1059;
+const xml_token_t XML_disableRefresh = 1060;
+const xml_token_t XML_discretePr = 1061;
+const xml_token_t XML_diskRevisions = 1062;
+const xml_token_t XML_dispBlanksAs = 1063;
+const xml_token_t XML_dispDef = 1064;
+const xml_token_t XML_dispEq = 1065;
+const xml_token_t XML_dispRSqr = 1066;
+const xml_token_t XML_dispUnits = 1067;
+const xml_token_t XML_dispUnitsLbl = 1068;
+const xml_token_t XML_displacedByCustomXml = 1069;
+const xml_token_t XML_display = 1070;
+const xml_token_t XML_displayBackgroundShape = 1071;
+const xml_token_t XML_displayFolder = 1072;
+const xml_token_t XML_displayHangulFixedWidth = 1073;
+const xml_token_t XML_displayHorizontalDrawingGridEvery = 1074;
+const xml_token_t XML_displayName = 1075;
+const xml_token_t XML_displayText = 1076;
+const xml_token_t XML_displayVerticalDrawingGridEvery = 1077;
+const xml_token_t XML_dissolve = 1078;
+const xml_token_t XML_dist = 1079;
+const xml_token_t XML_distB = 1080;
+const xml_token_t XML_distL = 1081;
+const xml_token_t XML_distR = 1082;
+const xml_token_t XML_distT = 1083;
+const xml_token_t XML_distance = 1084;
+const xml_token_t XML_div = 1085;
+const xml_token_t XML_divBdr = 1086;
+const xml_token_t XML_divId = 1087;
+const xml_token_t XML_divs = 1088;
+const xml_token_t XML_divsChild = 1089;
+const xml_token_t XML_dk1 = 1090;
+const xml_token_t XML_dk2 = 1091;
+const xml_token_t XML_dllVersion = 1092;
+const xml_token_t XML_dm = 1093;
+const xml_token_t XML_dn = 1094;
+const xml_token_t XML_doNotAutoCompressPictures = 1095;
+const xml_token_t XML_doNotAutofitConstrainedTables = 1096;
+const xml_token_t XML_doNotBreakConstrainedForcedTable = 1097;
+const xml_token_t XML_doNotBreakWrappedTables = 1098;
+const xml_token_t XML_doNotDemarcateInvalidXml = 1099;
+const xml_token_t XML_doNotDisplayPageBoundaries = 1100;
+const xml_token_t XML_doNotEmbedSmartTags = 1101;
+const xml_token_t XML_doNotExpandShiftReturn = 1102;
+const xml_token_t XML_doNotHyphenateCaps = 1103;
+const xml_token_t XML_doNotIncludeSubdocsInStats = 1104;
+const xml_token_t XML_doNotLeaveBackslashAlone = 1105;
+const xml_token_t XML_doNotOrganizeInFolder = 1106;
+const xml_token_t XML_doNotRelyOnCSS = 1107;
+const xml_token_t XML_doNotSaveAsSingleFile = 1108;
+const xml_token_t XML_doNotShadeFormData = 1109;
+const xml_token_t XML_doNotSnapToGridInCell = 1110;
+const xml_token_t XML_doNotSuppressBlankLines = 1111;
+const xml_token_t XML_doNotSuppressIndentation = 1112;
+const xml_token_t XML_doNotSuppressParagraphBorders = 1113;
+const xml_token_t XML_doNotTrackFormatting = 1114;
+const xml_token_t XML_doNotTrackMoves = 1115;
+const xml_token_t XML_doNotUseEastAsianBreakRules = 1116;
+const xml_token_t XML_doNotUseHTMLParagraphAutoSpacing = 1117;
+const xml_token_t XML_doNotUseIndentAsNumberingTabStop = 1118;
+const xml_token_t XML_doNotUseLongFileNames = 1119;
+const xml_token_t XML_doNotUseMarginsForDrawingGridOrigin = 1120;
+const xml_token_t XML_doNotValidateAgainstSchema = 1121;
+const xml_token_t XML_doNotVertAlignCellWithSp = 1122;
+const xml_token_t XML_doNotVertAlignInTxbx = 1123;
+const xml_token_t XML_doNotWrapTextWithPunct = 1124;
+const xml_token_t XML_docDefaults = 1125;
+const xml_token_t XML_docGrid = 1126;
+const xml_token_t XML_docLocation = 1127;
+const xml_token_t XML_docPart = 1128;
+const xml_token_t XML_docPartBody = 1129;
+const xml_token_t XML_docPartCategory = 1130;
+const xml_token_t XML_docPartGallery = 1131;
+const xml_token_t XML_docPartList = 1132;
+const xml_token_t XML_docPartObj = 1133;
+const xml_token_t XML_docPartPr = 1134;
+const xml_token_t XML_docPartUnique = 1135;
+const xml_token_t XML_docParts = 1136;
+const xml_token_t XML_docPr = 1137;
+const xml_token_t XML_docVar = 1138;
+const xml_token_t XML_docVars = 1139;
+const xml_token_t XML_document = 1140;
+const xml_token_t XML_documentProtection = 1141;
+const xml_token_t XML_documentType = 1142;
+const xml_token_t XML_double = 1143;
+const xml_token_t XML_doubleclicknotify = 1144;
+const xml_token_t XML_doughnutChart = 1145;
+const xml_token_t XML_downBars = 1146;
+const xml_token_t XML_dpi = 1147;
+const xml_token_t XML_dr = 1148;
+const xml_token_t XML_draft = 1149;
+const xml_token_t XML_dragOff = 1150;
+const xml_token_t XML_dragToCol = 1151;
+const xml_token_t XML_dragToData = 1152;
+const xml_token_t XML_dragToPage = 1153;
+const xml_token_t XML_dragToRow = 1154;
+const xml_token_t XML_drawing = 1155;
+const xml_token_t XML_drawingGridHorizontalOrigin = 1156;
+const xml_token_t XML_drawingGridHorizontalSpacing = 1157;
+const xml_token_t XML_drawingGridVerticalOrigin = 1158;
+const xml_token_t XML_drawingGridVerticalSpacing = 1159;
+const xml_token_t XML_drop = 1160;
+const xml_token_t XML_dropCap = 1161;
+const xml_token_t XML_dropDownList = 1162;
+const xml_token_t XML_dropLines = 1163;
+const xml_token_t XML_dropauto = 1164;
+const xml_token_t XML_ds = 1165;
+const xml_token_t XML_dstrike = 1166;
+const xml_token_t XML_dt = 1167;
+const xml_token_t XML_dt2D = 1168;
+const xml_token_t XML_dtr = 1169;
+const xml_token_t XML_duotone = 1170;
+const xml_token_t XML_dur = 1171;
+const xml_token_t XML_dvAspect = 1172;
+const xml_token_t XML_dx = 1173;
+const xml_token_t XML_dxaOrig = 1174;
+const xml_token_t XML_dxf = 1175;
+const xml_token_t XML_dxfId = 1176;
+const xml_token_t XML_dxfs = 1177;
+const xml_token_t XML_dy = 1178;
+const xml_token_t XML_dyaOrig = 1179;
+const xml_token_t XML_dynamicAddress = 1180;
+const xml_token_t XML_dynamicFilter = 1181;
+const xml_token_t XML_dz = 1182;
+const xml_token_t XML_e = 1183;
+const xml_token_t XML_ea = 1184;
+const xml_token_t XML_eaLnBrk = 1185;
+const xml_token_t XML_eastAsia = 1186;
+const xml_token_t XML_eastAsiaTheme = 1187;
+const xml_token_t XML_eastAsianLayout = 1188;
+const xml_token_t XML_eb = 1189;
+const xml_token_t XML_ed = 1190;
+const xml_token_t XML_edGrp = 1191;
+const xml_token_t XML_edge = 1192;
+const xml_token_t XML_edit = 1193;
+const xml_token_t XML_editAs = 1194;
+const xml_token_t XML_editData = 1195;
+const xml_token_t XML_editPage = 1196;
+const xml_token_t XML_editas = 1197;
+const xml_token_t XML_edited = 1198;
+const xml_token_t XML_effect = 1199;
+const xml_token_t XML_effectClrLst = 1200;
+const xml_token_t XML_effectDag = 1201;
+const xml_token_t XML_effectExtent = 1202;
+const xml_token_t XML_effectLst = 1203;
+const xml_token_t XML_effectRef = 1204;
+const xml_token_t XML_effectStyle = 1205;
+const xml_token_t XML_effectStyleLst = 1206;
+const xml_token_t XML_element = 1207;
+const xml_token_t XML_else = 1208;
+const xml_token_t XML_em = 1209;
+const xml_token_t XML_embed = 1210;
+const xml_token_t XML_embedBold = 1211;
+const xml_token_t XML_embedBoldItalic = 1212;
+const xml_token_t XML_embedItalic = 1213;
+const xml_token_t XML_embedRegular = 1214;
+const xml_token_t XML_embedSystemFonts = 1215;
+const xml_token_t XML_embedTrueTypeFonts = 1216;
+const xml_token_t XML_embeddedFont = 1217;
+const xml_token_t XML_embeddedFontLst = 1218;
+const xml_token_t XML_emboss = 1219;
+const xml_token_t XML_embosscolor = 1220;
+const xml_token_t XML_empty = 1221;
+const xml_token_t XML_emptyCellReference = 1222;
+const xml_token_t XML_enableDrill = 1223;
+const xml_token_t XML_enableFieldProperties = 1224;
+const xml_token_t XML_enableFormatConditionsCalculation = 1225;
+const xml_token_t XML_enableRefresh = 1226;
+const xml_token_t XML_enableWizard = 1227;
+const xml_token_t XML_enabled = 1228;
+const xml_token_t XML_encoding = 1229;
+const xml_token_t XML_end = 1230;
+const xml_token_t XML_endA = 1231;
+const xml_token_t XML_endAngle = 1232;
+const xml_token_t XML_endChr = 1233;
+const xml_token_t XML_endCondLst = 1234;
+const xml_token_t XML_endCxn = 1235;
+const xml_token_t XML_endDate = 1236;
+const xml_token_t XML_endNum = 1237;
+const xml_token_t XML_endOfListFormulaUpdate = 1238;
+const xml_token_t XML_endParaRPr = 1239;
+const xml_token_t XML_endPos = 1240;
+const xml_token_t XML_endSnd = 1241;
+const xml_token_t XML_endSync = 1242;
+const xml_token_t XML_endarrow = 1243;
+const xml_token_t XML_endarrowlength = 1244;
+const xml_token_t XML_endarrowwidth = 1245;
+const xml_token_t XML_endcap = 1246;
+const xml_token_t XML_endnote = 1247;
+const xml_token_t XML_endnotePr = 1248;
+const xml_token_t XML_endnoteRef = 1249;
+const xml_token_t XML_endnoteReference = 1250;
+const xml_token_t XML_endnotes = 1251;
+const xml_token_t XML_enforcement = 1252;
+const xml_token_t XML_entries = 1253;
+const xml_token_t XML_entry = 1254;
+const xml_token_t XML_entryMacro = 1255;
+const xml_token_t XML_eol = 1256;
+const xml_token_t XML_eqArr = 1257;
+const xml_token_t XML_eqArrPr = 1258;
+const xml_token_t XML_eqn = 1259;
+const xml_token_t XML_equalAverage = 1260;
+const xml_token_t XML_equalWidth = 1261;
+const xml_token_t XML_equation = 1262;
+const xml_token_t XML_equationxml = 1263;
+const xml_token_t XML_err = 1264;
+const xml_token_t XML_errBarType = 1265;
+const xml_token_t XML_errBars = 1266;
+const xml_token_t XML_errDir = 1267;
+const xml_token_t XML_errValType = 1268;
+const xml_token_t XML_error = 1269;
+const xml_token_t XML_errorCaption = 1270;
+const xml_token_t XML_errorStyle = 1271;
+const xml_token_t XML_errorTitle = 1272;
+const xml_token_t XML_errors = 1273;
+const xml_token_t XML_evalError = 1274;
+const xml_token_t XML_evalOrder = 1275;
+const xml_token_t XML_evenAndOddHeaders = 1276;
+const xml_token_t XML_evenFooter = 1277;
+const xml_token_t XML_evenHeader = 1278;
+const xml_token_t XML_evt = 1279;
+const xml_token_t XML_evtFilter = 1280;
+const xml_token_t XML_excl = 1281;
+const xml_token_t XML_exclusive = 1282;
+const xml_token_t XML_exitMacro = 1283;
+const xml_token_t XML_exp = 1284;
+const xml_token_t XML_explosion = 1285;
+const xml_token_t XML_ext = 1286;
+const xml_token_t XML_extLst = 1287;
+const xml_token_t XML_extend = 1288;
+const xml_token_t XML_extendable = 1289;
+const xml_token_t XML_extent = 1290;
+const xml_token_t XML_externalBook = 1291;
+const xml_token_t XML_externalData = 1292;
+const xml_token_t XML_externalLink = 1293;
+const xml_token_t XML_externalReference = 1294;
+const xml_token_t XML_externalReferences = 1295;
+const xml_token_t XML_extraClrScheme = 1296;
+const xml_token_t XML_extraClrSchemeLst = 1297;
+const xml_token_t XML_extrusion = 1298;
+const xml_token_t XML_extrusionClr = 1299;
+const xml_token_t XML_extrusionH = 1300;
+const xml_token_t XML_extrusionOk = 1301;
+const xml_token_t XML_extrusioncolor = 1302;
+const xml_token_t XML_extrusionok = 1303;
+const xml_token_t XML_f = 1304;
+const xml_token_t XML_fHdr = 1305;
+const xml_token_t XML_fLocksText = 1306;
+const xml_token_t XML_fLocksWithSheet = 1307;
+const xml_token_t XML_fName = 1308;
+const xml_token_t XML_fPr = 1309;
+const xml_token_t XML_fPrintsWithSheet = 1310;
+const xml_token_t XML_fPublished = 1311;
+const xml_token_t XML_facet = 1312;
+const xml_token_t XML_fact = 1313;
+const xml_token_t XML_fade = 1314;
+const xml_token_t XML_fadeDir = 1315;
+const xml_token_t XML_family = 1316;
+const xml_token_t XML_fc = 1317;
+const xml_token_t XML_ffData = 1318;
+const xml_token_t XML_fgClr = 1319;
+const xml_token_t XML_fgColor = 1320;
+const xml_token_t XML_fi = 1321;
+const xml_token_t XML_field = 1322;
+const xml_token_t XML_fieldGroup = 1323;
+const xml_token_t XML_fieldId = 1324;
+const xml_token_t XML_fieldIdWrapped = 1325;
+const xml_token_t XML_fieldListSortAscending = 1326;
+const xml_token_t XML_fieldMapData = 1327;
+const xml_token_t XML_fieldPosition = 1328;
+const xml_token_t XML_fieldPrintTitles = 1329;
+const xml_token_t XML_fieldUsage = 1330;
+const xml_token_t XML_fieldsUsage = 1331;
+const xml_token_t XML_fileRecoveryPr = 1332;
+const xml_token_t XML_fileSharing = 1333;
+const xml_token_t XML_fileType = 1334;
+const xml_token_t XML_fileVersion = 1335;
+const xml_token_t XML_filetime = 1336;
+const xml_token_t XML_fill = 1337;
+const xml_token_t XML_fillClrLst = 1338;
+const xml_token_t XML_fillFormulas = 1339;
+const xml_token_t XML_fillId = 1340;
+const xml_token_t XML_fillOverlay = 1341;
+const xml_token_t XML_fillRect = 1342;
+const xml_token_t XML_fillRef = 1343;
+const xml_token_t XML_fillStyleLst = 1344;
+const xml_token_t XML_fillToRect = 1345;
+const xml_token_t XML_fillcolor = 1346;
+const xml_token_t XML_filled = 1347;
+const xml_token_t XML_fillok = 1348;
+const xml_token_t XML_fills = 1349;
+const xml_token_t XML_filltype = 1350;
+const xml_token_t XML_filter = 1351;
+const xml_token_t XML_filterColumn = 1352;
+const xml_token_t XML_filterMode = 1353;
+const xml_token_t XML_filterPrivacy = 1354;
+const xml_token_t XML_filterUnique = 1355;
+const xml_token_t XML_filterVal = 1356;
+const xml_token_t XML_filters = 1357;
+const xml_token_t XML_first = 1358;
+const xml_token_t XML_firstBackgroundRefresh = 1359;
+const xml_token_t XML_firstCol = 1360;
+const xml_token_t XML_firstDataCol = 1361;
+const xml_token_t XML_firstDataRow = 1362;
+const xml_token_t XML_firstFooter = 1363;
+const xml_token_t XML_firstHeader = 1364;
+const xml_token_t XML_firstHeaderRow = 1365;
+const xml_token_t XML_firstLine = 1366;
+const xml_token_t XML_firstLineChars = 1367;
+const xml_token_t XML_firstPageNumber = 1368;
+const xml_token_t XML_firstRow = 1369;
+const xml_token_t XML_firstSheet = 1370;
+const xml_token_t XML_firstSliceAng = 1371;
+const xml_token_t XML_firstSlideNum = 1372;
+const xml_token_t XML_fitText = 1373;
+const xml_token_t XML_fitToHeight = 1374;
+const xml_token_t XML_fitToPage = 1375;
+const xml_token_t XML_fitToWidth = 1376;
+const xml_token_t XML_fitpath = 1377;
+const xml_token_t XML_fitshape = 1378;
+const xml_token_t XML_flatBorders = 1379;
+const xml_token_t XML_flatTx = 1380;
+const xml_token_t XML_fld = 1381;
+const xml_token_t XML_fldChar = 1382;
+const xml_token_t XML_fldCharType = 1383;
+const xml_token_t XML_fldData = 1384;
+const xml_token_t XML_fldLock = 1385;
+const xml_token_t XML_fldSimple = 1386;
+const xml_token_t XML_flip = 1387;
+const xml_token_t XML_flipH = 1388;
+const xml_token_t XML_flipV = 1389;
+const xml_token_t XML_floor = 1390;
+const xml_token_t XML_fltVal = 1391;
+const xml_token_t XML_fmla = 1392;
+const xml_token_t XML_fmt = 1393;
+const xml_token_t XML_fmtId = 1394;
+const xml_token_t XML_fmtScheme = 1395;
+const xml_token_t XML_fmtid = 1396;
+const xml_token_t XML_focus = 1397;
+const xml_token_t XML_focusposition = 1398;
+const xml_token_t XML_focussize = 1399;
+const xml_token_t XML_folHlink = 1400;
+const xml_token_t XML_followColorScheme = 1401;
+const xml_token_t XML_followedHyperlink = 1402;
+const xml_token_t XML_font = 1403;
+const xml_token_t XML_fontAlgn = 1404;
+const xml_token_t XML_fontId = 1405;
+const xml_token_t XML_fontKey = 1406;
+const xml_token_t XML_fontRef = 1407;
+const xml_token_t XML_fontScale = 1408;
+const xml_token_t XML_fontScheme = 1409;
+const xml_token_t XML_fontSz = 1410;
+const xml_token_t XML_fonts = 1411;
+const xml_token_t XML_footer = 1412;
+const xml_token_t XML_footerReference = 1413;
+const xml_token_t XML_footnote = 1414;
+const xml_token_t XML_footnoteLayoutLikeWW8 = 1415;
+const xml_token_t XML_footnotePr = 1416;
+const xml_token_t XML_footnoteRef = 1417;
+const xml_token_t XML_footnoteReference = 1418;
+const xml_token_t XML_footnotes = 1419;
+const xml_token_t XML_for = 1420;
+const xml_token_t XML_forEach = 1421;
+const xml_token_t XML_forName = 1422;
+const xml_token_t XML_forceAA = 1423;
+const xml_token_t XML_forceFullCalc = 1424;
+const xml_token_t XML_forceUpgrade = 1425;
+const xml_token_t XML_forcedash = 1426;
+const xml_token_t XML_foredepth = 1427;
+const xml_token_t XML_forgetLastTabAlignment = 1428;
+const xml_token_t XML_formProt = 1429;
+const xml_token_t XML_format = 1430;
+const xml_token_t XML_formatCells = 1431;
+const xml_token_t XML_formatCode = 1432;
+const xml_token_t XML_formatColumns = 1433;
+const xml_token_t XML_formatRows = 1434;
+const xml_token_t XML_formats = 1435;
+const xml_token_t XML_formatting = 1436;
+const xml_token_t XML_formsDesign = 1437;
+const xml_token_t XML_formula = 1438;
+const xml_token_t XML_formula1 = 1439;
+const xml_token_t XML_formula2 = 1440;
+const xml_token_t XML_formulaRange = 1441;
+const xml_token_t XML_formulas = 1442;
+const xml_token_t XML_forward = 1443;
+const xml_token_t XML_fov = 1444;
+const xml_token_t XML_frame = 1445;
+const xml_token_t XML_frameLayout = 1446;
+const xml_token_t XML_framePr = 1447;
+const xml_token_t XML_frameSlides = 1448;
+const xml_token_t XML_frameset = 1449;
+const xml_token_t XML_framesetSplitbar = 1450;
+const xml_token_t XML_from = 1451;
+const xml_token_t XML_fromWordArt = 1452;
+const xml_token_t XML_ftr = 1453;
+const xml_token_t XML_fullCalcOnLoad = 1454;
+const xml_token_t XML_fullDate = 1455;
+const xml_token_t XML_fullPrecision = 1456;
+const xml_token_t XML_fullScrn = 1457;
+const xml_token_t XML_func = 1458;
+const xml_token_t XML_funcPr = 1459;
+const xml_token_t XML_function = 1460;
+const xml_token_t XML_functionGroup = 1461;
+const xml_token_t XML_functionGroupId = 1462;
+const xml_token_t XML_functionGroups = 1463;
+const xml_token_t XML_futureMetadata = 1464;
+const xml_token_t XML_g = 1465;
+const xml_token_t XML_gain = 1466;
+const xml_token_t XML_gallery = 1467;
+const xml_token_t XML_gamma = 1468;
+const xml_token_t XML_gap = 1469;
+const xml_token_t XML_gapDepth = 1470;
+const xml_token_t XML_gapWidth = 1471;
+const xml_token_t XML_gd = 1472;
+const xml_token_t XML_gdLst = 1473;
+const xml_token_t XML_gdRefAng = 1474;
+const xml_token_t XML_gdRefR = 1475;
+const xml_token_t XML_gdRefX = 1476;
+const xml_token_t XML_gdRefY = 1477;
+const xml_token_t XML_gfxdata = 1478;
+const xml_token_t XML_ghostCol = 1479;
+const xml_token_t XML_ghostRow = 1480;
+const xml_token_t XML_glossaryDocument = 1481;
+const xml_token_t XML_glow = 1482;
+const xml_token_t XML_goal = 1483;
+const xml_token_t XML_gradFill = 1484;
+const xml_token_t XML_gradientFill = 1485;
+const xml_token_t XML_gradientshapeok = 1486;
+const xml_token_t XML_grammar = 1487;
+const xml_token_t XML_grandCol = 1488;
+const xml_token_t XML_grandRow = 1489;
+const xml_token_t XML_grandTotalCaption = 1490;
+const xml_token_t XML_graphic = 1491;
+const xml_token_t XML_graphicData = 1492;
+const xml_token_t XML_graphicEl = 1493;
+const xml_token_t XML_graphicFrame = 1494;
+const xml_token_t XML_graphicFrameLocks = 1495;
+const xml_token_t XML_gray = 1496;
+const xml_token_t XML_grayscale = 1497;
+const xml_token_t XML_grayscl = 1498;
+const xml_token_t XML_green = 1499;
+const xml_token_t XML_greenMod = 1500;
+const xml_token_t XML_greenOff = 1501;
+const xml_token_t XML_gridAfter = 1502;
+const xml_token_t XML_gridBefore = 1503;
+const xml_token_t XML_gridCol = 1504;
+const xml_token_t XML_gridDropZones = 1505;
+const xml_token_t XML_gridLines = 1506;
+const xml_token_t XML_gridLinesSet = 1507;
+const xml_token_t XML_gridSpacing = 1508;
+const xml_token_t XML_gridSpan = 1509;
+const xml_token_t XML_group = 1510;
+const xml_token_t XML_groupBy = 1511;
+const xml_token_t XML_groupChr = 1512;
+const xml_token_t XML_groupChrPr = 1513;
+const xml_token_t XML_groupInterval = 1514;
+const xml_token_t XML_groupItems = 1515;
+const xml_token_t XML_groupLevel = 1516;
+const xml_token_t XML_groupLevels = 1517;
+const xml_token_t XML_groupMember = 1518;
+const xml_token_t XML_groupMembers = 1519;
+const xml_token_t XML_grouping = 1520;
+const xml_token_t XML_groups = 1521;
+const xml_token_t XML_grow = 1522;
+const xml_token_t XML_growAutofit = 1523;
+const xml_token_t XML_growShrinkType = 1524;
+const xml_token_t XML_grpFill = 1525;
+const xml_token_t XML_grpId = 1526;
+const xml_token_t XML_grpSp = 1527;
+const xml_token_t XML_grpSpLocks = 1528;
+const xml_token_t XML_grpSpPr = 1529;
+const xml_token_t XML_gs = 1530;
+const xml_token_t XML_gsLst = 1531;
+const xml_token_t XML_gte = 1532;
+const xml_token_t XML_guid = 1533;
+const xml_token_t XML_guide = 1534;
+const xml_token_t XML_guideLst = 1535;
+const xml_token_t XML_gutter = 1536;
+const xml_token_t XML_gutterAtTop = 1537;
+const xml_token_t XML_h = 1538;
+const xml_token_t XML_hAnchor = 1539;
+const xml_token_t XML_hAnsi = 1540;
+const xml_token_t XML_hAnsiTheme = 1541;
+const xml_token_t XML_hMerge = 1542;
+const xml_token_t XML_hMode = 1543;
+const xml_token_t XML_hPercent = 1544;
+const xml_token_t XML_hR = 1545;
+const xml_token_t XML_hRule = 1546;
+const xml_token_t XML_hSpace = 1547;
+const xml_token_t XML_handles = 1548;
+const xml_token_t XML_handoutMaster = 1549;
+const xml_token_t XML_handoutMasterId = 1550;
+const xml_token_t XML_handoutMasterIdLst = 1551;
+const xml_token_t XML_hanging = 1552;
+const xml_token_t XML_hangingChars = 1553;
+const xml_token_t XML_hangingPunct = 1554;
+const xml_token_t XML_hasCustomPrompt = 1555;
+const xml_token_t XML_hash = 1556;
+const xml_token_t XML_hashData = 1557;
+const xml_token_t XML_hdr = 1558;
+const xml_token_t XML_hdrShapeDefaults = 1559;
+const xml_token_t XML_headEnd = 1560;
+const xml_token_t XML_header = 1561;
+const xml_token_t XML_headerFooter = 1562;
+const xml_token_t XML_headerReference = 1563;
+const xml_token_t XML_headerRowBorderDxfId = 1564;
+const xml_token_t XML_headerRowCellStyle = 1565;
+const xml_token_t XML_headerRowCount = 1566;
+const xml_token_t XML_headerRowDxfId = 1567;
+const xml_token_t XML_headerSource = 1568;
+const xml_token_t XML_headers = 1569;
+const xml_token_t XML_headersInLastRefresh = 1570;
+const xml_token_t XML_heading = 1571;
+const xml_token_t XML_headings = 1572;
+const xml_token_t XML_help = 1573;
+const xml_token_t XML_helpText = 1574;
+const xml_token_t XML_hf = 1575;
+const xml_token_t XML_hiLowLines = 1576;
+const xml_token_t XML_hidden = 1577;
+const xml_token_t XML_hiddenButton = 1578;
+const xml_token_t XML_hiddenColumn = 1579;
+const xml_token_t XML_hiddenColumns = 1580;
+const xml_token_t XML_hiddenLevel = 1581;
+const xml_token_t XML_hiddenRow = 1582;
+const xml_token_t XML_hiddenRows = 1583;
+const xml_token_t XML_hiddenSlides = 1584;
+const xml_token_t XML_hideBot = 1585;
+const xml_token_t XML_hideGeom = 1586;
+const xml_token_t XML_hideGrammaticalErrors = 1587;
+const xml_token_t XML_hideLastTrans = 1588;
+const xml_token_t XML_hideLeft = 1589;
+const xml_token_t XML_hideMark = 1590;
+const xml_token_t XML_hideNewItems = 1591;
+const xml_token_t XML_hidePivotFieldList = 1592;
+const xml_token_t XML_hideRight = 1593;
+const xml_token_t XML_hideSpellingErrors = 1594;
+const xml_token_t XML_hideTop = 1595;
+const xml_token_t XML_hier = 1596;
+const xml_token_t XML_hierBranch = 1597;
+const xml_token_t XML_hierarchy = 1598;
+const xml_token_t XML_hierarchyUsage = 1599;
+const xml_token_t XML_highlight = 1600;
+const xml_token_t XML_highlightClick = 1601;
+const xml_token_t XML_hint = 1602;
+const xml_token_t XML_history = 1603;
+const xml_token_t XML_hlink = 1604;
+const xml_token_t XML_hlinkClick = 1605;
+const xml_token_t XML_hlinkHover = 1606;
+const xml_token_t XML_hlinkMouseOver = 1607;
+const xml_token_t XML_holeSize = 1608;
+const xml_token_t XML_horizontal = 1609;
+const xml_token_t XML_horizontalCentered = 1610;
+const xml_token_t XML_horizontalDpi = 1611;
+const xml_token_t XML_horzAnchor = 1612;
+const xml_token_t XML_horzBarState = 1613;
+const xml_token_t XML_horzOverflow = 1614;
+const xml_token_t XML_hour = 1615;
+const xml_token_t XML_how = 1616;
+const xml_token_t XML_hps = 1617;
+const xml_token_t XML_hpsBaseText = 1618;
+const xml_token_t XML_hpsRaise = 1619;
+const xml_token_t XML_hr = 1620;
+const xml_token_t XML_hralign = 1621;
+const xml_token_t XML_href = 1622;
+const xml_token_t XML_hrnoshade = 1623;
+const xml_token_t XML_hrpct = 1624;
+const xml_token_t XML_hrstd = 1625;
+const xml_token_t XML_hsl = 1626;
+const xml_token_t XML_hslClr = 1627;
+const xml_token_t XML_ht = 1628;
+const xml_token_t XML_htmlFormat = 1629;
+const xml_token_t XML_htmlPubPr = 1630;
+const xml_token_t XML_htmlTables = 1631;
+const xml_token_t XML_hue = 1632;
+const xml_token_t XML_hueDir = 1633;
+const xml_token_t XML_hueMod = 1634;
+const xml_token_t XML_hueOff = 1635;
+const xml_token_t XML_hyperlink = 1636;
+const xml_token_t XML_hyperlinks = 1637;
+const xml_token_t XML_hyphenationZone = 1638;
+const xml_token_t XML_i = 1639;
+const xml_token_t XML_i1 = 1640;
+const xml_token_t XML_i2 = 1641;
+const xml_token_t XML_i3 = 1642;
+const xml_token_t XML_i4 = 1643;
+const xml_token_t XML_i8 = 1644;
+const xml_token_t XML_iCs = 1645;
+const xml_token_t XML_iLevel = 1646;
+const xml_token_t XML_iMeasureFld = 1647;
+const xml_token_t XML_iMeasureHier = 1648;
+const xml_token_t XML_icon = 1649;
+const xml_token_t XML_iconFilter = 1650;
+const xml_token_t XML_iconId = 1651;
+const xml_token_t XML_iconSet = 1652;
+const xml_token_t XML_id = 1653;
+const xml_token_t XML_idcntr = 1654;
+const xml_token_t XML_iddest = 1655;
+const xml_token_t XML_idmap = 1656;
+const xml_token_t XML_idref = 1657;
+const xml_token_t XML_idsrc = 1658;
+const xml_token_t XML_idx = 1659;
+const xml_token_t XML_if = 1660;
+const xml_token_t XML_ignoreMixedContent = 1661;
+const xml_token_t XML_ignoredError = 1662;
+const xml_token_t XML_ignoredErrors = 1663;
+const xml_token_t XML_ilvl = 1664;
+const xml_token_t XML_image = 1665;
+const xml_token_t XML_imagealignshape = 1666;
+const xml_token_t XML_imageaspect = 1667;
+const xml_token_t XML_imagedata = 1668;
+const xml_token_t XML_imagesize = 1669;
+const xml_token_t XML_imeMode = 1670;
+const xml_token_t XML_imgH = 1671;
+const xml_token_t XML_imgSz = 1672;
+const xml_token_t XML_imgW = 1673;
+const xml_token_t XML_immersive = 1674;
+const xml_token_t XML_imprint = 1675;
+const xml_token_t XML_in = 1676;
+const xml_token_t XML_includeHiddenRowCol = 1677;
+const xml_token_t XML_includeNewItemsInFilter = 1678;
+const xml_token_t XML_includePrintSettings = 1679;
+const xml_token_t XML_ind = 1680;
+const xml_token_t XML_indent = 1681;
+const xml_token_t XML_index = 1682;
+const xml_token_t XML_indexed = 1683;
+const xml_token_t XML_indexedColors = 1684;
+const xml_token_t XML_initials = 1685;
+const xml_token_t XML_ink = 1686;
+const xml_token_t XML_inkAnnotations = 1687;
+const xml_token_t XML_inkTgt = 1688;
+const xml_token_t XML_inline = 1689;
+const xml_token_t XML_innerShdw = 1690;
+const xml_token_t XML_inputCells = 1691;
+const xml_token_t XML_ins = 1692;
+const xml_token_t XML_insDel = 1693;
+const xml_token_t XML_insertBlankRow = 1694;
+const xml_token_t XML_insertColumns = 1695;
+const xml_token_t XML_insertHyperlinks = 1696;
+const xml_token_t XML_insertPageBreak = 1697;
+const xml_token_t XML_insertRow = 1698;
+const xml_token_t XML_insertRowShift = 1699;
+const xml_token_t XML_insertRows = 1700;
+const xml_token_t XML_inset = 1701;
+const xml_token_t XML_insetmode = 1702;
+const xml_token_t XML_insetpen = 1703;
+const xml_token_t XML_insetpenok = 1704;
+const xml_token_t XML_insideH = 1705;
+const xml_token_t XML_insideV = 1706;
+const xml_token_t XML_instr = 1707;
+const xml_token_t XML_instrText = 1708;
+const xml_token_t XML_int = 1709;
+const xml_token_t XML_intLim = 1710;
+const xml_token_t XML_intVal = 1711;
+const xml_token_t XML_integer = 1712;
+const xml_token_t XML_interSp = 1713;
+const xml_token_t XML_intercept = 1714;
+const xml_token_t XML_intermediate = 1715;
+const xml_token_t XML_interval = 1716;
+const xml_token_t XML_intraSp = 1717;
+const xml_token_t XML_inv = 1718;
+const xml_token_t XML_invGamma = 1719;
+const xml_token_t XML_invalEndChars = 1720;
+const xml_token_t XML_invalStChars = 1721;
+const xml_token_t XML_invalid = 1722;
+const xml_token_t XML_invalidUrl = 1723;
+const xml_token_t XML_invertIfNegative = 1724;
+const xml_token_t XML_invx = 1725;
+const xml_token_t XML_invy = 1726;
+const xml_token_t XML_is = 1727;
+const xml_token_t XML_isLgl = 1728;
+const xml_token_t XML_isNarration = 1729;
+const xml_token_t XML_isPhoto = 1730;
+const xml_token_t XML_iscomment = 1731;
+const xml_token_t XML_issignatureline = 1732;
+const xml_token_t XML_italic = 1733;
+const xml_token_t XML_item = 1734;
+const xml_token_t XML_itemID = 1735;
+const xml_token_t XML_itemPageCount = 1736;
+const xml_token_t XML_itemPrintTitles = 1737;
+const xml_token_t XML_items = 1738;
+const xml_token_t XML_iterate = 1739;
+const xml_token_t XML_iterateCount = 1740;
+const xml_token_t XML_iterateDelta = 1741;
+const xml_token_t XML_jc = 1742;
+const xml_token_t XML_joinstyle = 1743;
+const xml_token_t XML_justifyLastLine = 1744;
+const xml_token_t XML_k = 1745;
+const xml_token_t XML_keepAlive = 1746;
+const xml_token_t XML_keepChangeHistory = 1747;
+const xml_token_t XML_keepLines = 1748;
+const xml_token_t XML_keepNext = 1749;
+const xml_token_t XML_kern = 1750;
+const xml_token_t XML_key = 1751;
+const xml_token_t XML_keyAttribute = 1752;
+const xml_token_t XML_kinsoku = 1753;
+const xml_token_t XML_kiosk = 1754;
+const xml_token_t XML_kpi = 1755;
+const xml_token_t XML_kpis = 1756;
+const xml_token_t XML_kumimoji = 1757;
+const xml_token_t XML_kx = 1758;
+const xml_token_t XML_ky = 1759;
+const xml_token_t XML_l = 1760;
+const xml_token_t XML_lBounds = 1761;
+const xml_token_t XML_lIns = 1762;
+const xml_token_t XML_lMargin = 1763;
+const xml_token_t XML_label = 1764;
+const xml_token_t XML_labelOnly = 1765;
+const xml_token_t XML_lang = 1766;
+const xml_token_t XML_lastClr = 1767;
+const xml_token_t XML_lastCol = 1768;
+const xml_token_t XML_lastEdited = 1769;
+const xml_token_t XML_lastGuid = 1770;
+const xml_token_t XML_lastIdx = 1771;
+const xml_token_t XML_lastRenderedPageBreak = 1772;
+const xml_token_t XML_lastRow = 1773;
+const xml_token_t XML_lastValue = 1774;
+const xml_token_t XML_lastView = 1775;
+const xml_token_t XML_lat = 1776;
+const xml_token_t XML_latentStyles = 1777;
+const xml_token_t XML_latin = 1778;
+const xml_token_t XML_latinLnBrk = 1779;
+const xml_token_t XML_layout = 1780;
+const xml_token_t XML_layoutDef = 1781;
+const xml_token_t XML_layoutDefHdr = 1782;
+const xml_token_t XML_layoutDefHdrLst = 1783;
+const xml_token_t XML_layoutInCell = 1784;
+const xml_token_t XML_layoutNode = 1785;
+const xml_token_t XML_layoutRawTableWidth = 1786;
+const xml_token_t XML_layoutTableRowsApart = 1787;
+const xml_token_t XML_layoutTarget = 1788;
+const xml_token_t XML_lblAlgn = 1789;
+const xml_token_t XML_lblOffset = 1790;
+const xml_token_t XML_leader = 1791;
+const xml_token_t XML_leaderLines = 1792;
+const xml_token_t XML_left = 1793;
+const xml_token_t XML_leftChars = 1794;
+const xml_token_t XML_leftFromText = 1795;
+const xml_token_t XML_leftLabels = 1796;
+const xml_token_t XML_legacy = 1797;
+const xml_token_t XML_legacyDrawing = 1798;
+const xml_token_t XML_legacyDrawingHF = 1799;
+const xml_token_t XML_legacyIndent = 1800;
+const xml_token_t XML_legacySpace = 1801;
+const xml_token_t XML_legend = 1802;
+const xml_token_t XML_legendEntry = 1803;
+const xml_token_t XML_legendPos = 1804;
+const xml_token_t XML_len = 1805;
+const xml_token_t XML_length = 1806;
+const xml_token_t XML_lengthspecified = 1807;
+const xml_token_t XML_level = 1808;
+const xml_token_t XML_lid = 1809;
+const xml_token_t XML_lightRig = 1810;
+const xml_token_t XML_lightface = 1811;
+const xml_token_t XML_lightharsh = 1812;
+const xml_token_t XML_lightharsh2 = 1813;
+const xml_token_t XML_lightlevel = 1814;
+const xml_token_t XML_lightlevel2 = 1815;
+const xml_token_t XML_lightposition = 1816;
+const xml_token_t XML_lightposition2 = 1817;
+const xml_token_t XML_lim = 1818;
+const xml_token_t XML_limLoc = 1819;
+const xml_token_t XML_limLow = 1820;
+const xml_token_t XML_limLowPr = 1821;
+const xml_token_t XML_limUpp = 1822;
+const xml_token_t XML_limUppPr = 1823;
+const xml_token_t XML_limo = 1824;
+const xml_token_t XML_lin = 1825;
+const xml_token_t XML_linClrLst = 1826;
+const xml_token_t XML_line = 1827;
+const xml_token_t XML_line3DChart = 1828;
+const xml_token_t XML_lineChart = 1829;
+const xml_token_t XML_linePitch = 1830;
+const xml_token_t XML_lineRule = 1831;
+const xml_token_t XML_lineTo = 1832;
+const xml_token_t XML_lineWrapLikeWord6 = 1833;
+const xml_token_t XML_lines = 1834;
+const xml_token_t XML_linestyle = 1835;
+const xml_token_t XML_link = 1836;
+const xml_token_t XML_linkStyles = 1837;
+const xml_token_t XML_linkTarget = 1838;
+const xml_token_t XML_linkToQuery = 1839;
+const xml_token_t XML_linkedToFile = 1840;
+const xml_token_t XML_listDataValidation = 1841;
+const xml_token_t XML_listEntry = 1842;
+const xml_token_t XML_listItem = 1843;
+const xml_token_t XML_listSeparator = 1844;
+const xml_token_t XML_lit = 1845;
+const xml_token_t XML_lkTxEntry = 1846;
+const xml_token_t XML_ln = 1847;
+const xml_token_t XML_lnB = 1848;
+const xml_token_t XML_lnBlToTr = 1849;
+const xml_token_t XML_lnDef = 1850;
+const xml_token_t XML_lnL = 1851;
+const xml_token_t XML_lnNumType = 1852;
+const xml_token_t XML_lnR = 1853;
+const xml_token_t XML_lnRef = 1854;
+const xml_token_t XML_lnSpc = 1855;
+const xml_token_t XML_lnSpcReduction = 1856;
+const xml_token_t XML_lnStyleLst = 1857;
+const xml_token_t XML_lnT = 1858;
+const xml_token_t XML_lnTlToBr = 1859;
+const xml_token_t XML_lnTo = 1860;
+const xml_token_t XML_lo = 1861;
+const xml_token_t XML_loCatId = 1862;
+const xml_token_t XML_loTypeId = 1863;
+const xml_token_t XML_local = 1864;
+const xml_token_t XML_localConnection = 1865;
+const xml_token_t XML_localRefresh = 1866;
+const xml_token_t XML_localSheetId = 1867;
+const xml_token_t XML_location = 1868;
+const xml_token_t XML_lock = 1869;
+const xml_token_t XML_lockRevision = 1870;
+const xml_token_t XML_lockStructure = 1871;
+const xml_token_t XML_lockWindows = 1872;
+const xml_token_t XML_locked = 1873;
+const xml_token_t XML_lockedCanvas = 1874;
+const xml_token_t XML_lockrotationcenter = 1875;
+const xml_token_t XML_logBase = 1876;
+const xml_token_t XML_lon = 1877;
+const xml_token_t XML_longFileNames = 1878;
+const xml_token_t XML_longText = 1879;
+const xml_token_t XML_loop = 1880;
+const xml_token_t XML_lowestEdited = 1881;
+const xml_token_t XML_lpstr = 1882;
+const xml_token_t XML_lpwstr = 1883;
+const xml_token_t XML_lsdException = 1884;
+const xml_token_t XML_lstStyle = 1885;
+const xml_token_t XML_lt1 = 1886;
+const xml_token_t XML_lt2 = 1887;
+const xml_token_t XML_lum = 1888;
+const xml_token_t XML_lumMod = 1889;
+const xml_token_t XML_lumOff = 1890;
+const xml_token_t XML_lvl = 1891;
+const xml_token_t XML_lvl1pPr = 1892;
+const xml_token_t XML_lvl2pPr = 1893;
+const xml_token_t XML_lvl3pPr = 1894;
+const xml_token_t XML_lvl4pPr = 1895;
+const xml_token_t XML_lvl5pPr = 1896;
+const xml_token_t XML_lvl6pPr = 1897;
+const xml_token_t XML_lvl7pPr = 1898;
+const xml_token_t XML_lvl8pPr = 1899;
+const xml_token_t XML_lvl9pPr = 1900;
+const xml_token_t XML_lvlJc = 1901;
+const xml_token_t XML_lvlOverride = 1902;
+const xml_token_t XML_lvlPicBulletId = 1903;
+const xml_token_t XML_lvlRestart = 1904;
+const xml_token_t XML_lvlText = 1905;
+const xml_token_t XML_m = 1906;
+const xml_token_t XML_mPr = 1907;
+const xml_token_t XML_macro = 1908;
+const xml_token_t XML_mailAsAttachment = 1909;
+const xml_token_t XML_mailMerge = 1910;
+const xml_token_t XML_mailSubject = 1911;
+const xml_token_t XML_main = 1912;
+const xml_token_t XML_mainDocumentType = 1913;
+const xml_token_t XML_majorFont = 1914;
+const xml_token_t XML_majorGridlines = 1915;
+const xml_token_t XML_majorTickMark = 1916;
+const xml_token_t XML_majorTimeUnit = 1917;
+const xml_token_t XML_majorUnit = 1918;
+const xml_token_t XML_man = 1919;
+const xml_token_t XML_manifestLocation = 1920;
+const xml_token_t XML_manualBreakCount = 1921;
+const xml_token_t XML_manualLayout = 1922;
+const xml_token_t XML_map = 1923;
+const xml_token_t XML_mapId = 1924;
+const xml_token_t XML_mappedName = 1925;
+const xml_token_t XML_mappingCount = 1926;
+const xml_token_t XML_maps = 1927;
+const xml_token_t XML_marB = 1928;
+const xml_token_t XML_marBottom = 1929;
+const xml_token_t XML_marH = 1930;
+const xml_token_t XML_marL = 1931;
+const xml_token_t XML_marLeft = 1932;
+const xml_token_t XML_marR = 1933;
+const xml_token_t XML_marRight = 1934;
+const xml_token_t XML_marT = 1935;
+const xml_token_t XML_marTop = 1936;
+const xml_token_t XML_marW = 1937;
+const xml_token_t XML_marker = 1938;
+const xml_token_t XML_markup = 1939;
+const xml_token_t XML_master = 1940;
+const xml_token_t XML_masterClrMapping = 1941;
+const xml_token_t XML_masterRel = 1942;
+const xml_token_t XML_matchSrc = 1943;
+const xml_token_t XML_matchingName = 1944;
+const xml_token_t XML_mathFont = 1945;
+const xml_token_t XML_mathPr = 1946;
+const xml_token_t XML_matrix = 1947;
+const xml_token_t XML_max = 1948;
+const xml_token_t XML_maxAng = 1949;
+const xml_token_t XML_maxDate = 1950;
+const xml_token_t XML_maxDist = 1951;
+const xml_token_t XML_maxLength = 1952;
+const xml_token_t XML_maxR = 1953;
+const xml_token_t XML_maxRId = 1954;
+const xml_token_t XML_maxRank = 1955;
+const xml_token_t XML_maxSheetId = 1956;
+const xml_token_t XML_maxSubtotal = 1957;
+const xml_token_t XML_maxVal = 1958;
+const xml_token_t XML_maxValue = 1959;
+const xml_token_t XML_maxX = 1960;
+const xml_token_t XML_maxY = 1961;
+const xml_token_t XML_maximized = 1962;
+const xml_token_t XML_mc = 1963;
+const xml_token_t XML_mcJc = 1964;
+const xml_token_t XML_mcPr = 1965;
+const xml_token_t XML_mcs = 1966;
+const xml_token_t XML_mdx = 1967;
+const xml_token_t XML_mdxMetadata = 1968;
+const xml_token_t XML_mdxSubqueries = 1969;
+const xml_token_t XML_measure = 1970;
+const xml_token_t XML_measureFilter = 1971;
+const xml_token_t XML_measureGroup = 1972;
+const xml_token_t XML_measureGroups = 1973;
+const xml_token_t XML_measures = 1974;
+const xml_token_t XML_member = 1975;
+const xml_token_t XML_memberName = 1976;
+const xml_token_t XML_memberPropertyField = 1977;
+const xml_token_t XML_memberValueDatatype = 1978;
+const xml_token_t XML_members = 1979;
+const xml_token_t XML_merge = 1980;
+const xml_token_t XML_mergeCell = 1981;
+const xml_token_t XML_mergeCells = 1982;
+const xml_token_t XML_mergeInterval = 1983;
+const xml_token_t XML_mergeItem = 1984;
+const xml_token_t XML_metadata = 1985;
+const xml_token_t XML_metadataStrings = 1986;
+const xml_token_t XML_metadataType = 1987;
+const xml_token_t XML_metadataTypes = 1988;
+const xml_token_t XML_metal = 1989;
+const xml_token_t XML_meth = 1990;
+const xml_token_t XML_method = 1991;
+const xml_token_t XML_min = 1992;
+const xml_token_t XML_minAng = 1993;
+const xml_token_t XML_minDate = 1994;
+const xml_token_t XML_minLength = 1995;
+const xml_token_t XML_minR = 1996;
+const xml_token_t XML_minRId = 1997;
+const xml_token_t XML_minRefreshableVersion = 1998;
+const xml_token_t XML_minSubtotal = 1999;
+const xml_token_t XML_minSupportedVersion = 2000;
+const xml_token_t XML_minValue = 2001;
+const xml_token_t XML_minVer = 2002;
+const xml_token_t XML_minX = 2003;
+const xml_token_t XML_minY = 2004;
+const xml_token_t XML_minimized = 2005;
+const xml_token_t XML_minimumVersion = 2006;
+const xml_token_t XML_minorFont = 2007;
+const xml_token_t XML_minorGridlines = 2008;
+const xml_token_t XML_minorTickMark = 2009;
+const xml_token_t XML_minorTimeUnit = 2010;
+const xml_token_t XML_minorUnit = 2011;
+const xml_token_t XML_minus = 2012;
+const xml_token_t XML_minusx = 2013;
+const xml_token_t XML_minusy = 2014;
+const xml_token_t XML_minute = 2015;
+const xml_token_t XML_mirrorIndents = 2016;
+const xml_token_t XML_mirrorMargins = 2017;
+const xml_token_t XML_missingCaption = 2018;
+const xml_token_t XML_missingItemsLimit = 2019;
+const xml_token_t XML_miter = 2020;
+const xml_token_t XML_miterlimit = 2021;
+const xml_token_t XML_mod = 2022;
+const xml_token_t XML_modelId = 2023;
+const xml_token_t XML_modifyVerifier = 2024;
+const xml_token_t XML_month = 2025;
+const xml_token_t XML_monthLong = 2026;
+const xml_token_t XML_monthShort = 2027;
+const xml_token_t XML_moveFrom = 2028;
+const xml_token_t XML_moveFromRangeEnd = 2029;
+const xml_token_t XML_moveFromRangeStart = 2030;
+const xml_token_t XML_moveTo = 2031;
+const xml_token_t XML_moveToRangeEnd = 2032;
+const xml_token_t XML_moveToRangeStart = 2033;
+const xml_token_t XML_moveWith = 2034;
+const xml_token_t XML_movie = 2035;
+const xml_token_t XML_mp = 2036;
+const xml_token_t XML_mpFld = 2037;
+const xml_token_t XML_mpMap = 2038;
+const xml_token_t XML_mps = 2039;
+const xml_token_t XML_mr = 2040;
+const xml_token_t XML_mruColors = 2041;
+const xml_token_t XML_ms = 2042;
+const xml_token_t XML_multiLevelType = 2043;
+const xml_token_t XML_multiLine = 2044;
+const xml_token_t XML_multiLvlStrCache = 2045;
+const xml_token_t XML_multiLvlStrRef = 2046;
+const xml_token_t XML_multipleFieldFilters = 2047;
+const xml_token_t XML_multipleItemSelectionAllowed = 2048;
+const xml_token_t XML_mute = 2049;
+const xml_token_t XML_mwSmallCaps = 2050;
+const xml_token_t XML_n = 2051;
+const xml_token_t XML_name = 2052;
+const xml_token_t XML_nameLen = 2053;
+const xml_token_t XML_namespaceUri = 2054;
+const xml_token_t XML_namespaceuri = 2055;
+const xml_token_t XML_nary = 2056;
+const xml_token_t XML_naryLim = 2057;
+const xml_token_t XML_naryPr = 2058;
+const xml_token_t XML_nc = 2059;
+const xml_token_t XML_ndxf = 2060;
+const xml_token_t XML_neCell = 2061;
+const xml_token_t XML_new = 2062;
+const xml_token_t XML_newLength = 2063;
+const xml_token_t XML_newName = 2064;
+const xml_token_t XML_newsflash = 2065;
+const xml_token_t XML_next = 2066;
+const xml_token_t XML_nextAc = 2067;
+const xml_token_t XML_nextCondLst = 2068;
+const xml_token_t XML_nextId = 2069;
+const xml_token_t XML_nf = 2070;
+const xml_token_t XML_nlCheck = 2071;
+const xml_token_t XML_noAdjustHandles = 2072;
+const xml_token_t XML_noAutofit = 2073;
+const xml_token_t XML_noBorder = 2074;
+const xml_token_t XML_noBreak = 2075;
+const xml_token_t XML_noBreakHyphen = 2076;
+const xml_token_t XML_noChangeArrowheads = 2077;
+const xml_token_t XML_noChangeAspect = 2078;
+const xml_token_t XML_noChangeShapeType = 2079;
+const xml_token_t XML_noColumnBalance = 2080;
+const xml_token_t XML_noCrop = 2081;
+const xml_token_t XML_noDrilldown = 2082;
+const xml_token_t XML_noEditPoints = 2083;
+const xml_token_t XML_noEndCap = 2084;
+const xml_token_t XML_noEndnote = 2085;
+const xml_token_t XML_noExtraLineSpacing = 2086;
+const xml_token_t XML_noFill = 2087;
+const xml_token_t XML_noGrp = 2088;
+const xml_token_t XML_noLabel = 2089;
+const xml_token_t XML_noLeading = 2090;
+const xml_token_t XML_noLineBreaksAfter = 2091;
+const xml_token_t XML_noLineBreaksBefore = 2092;
+const xml_token_t XML_noMove = 2093;
+const xml_token_t XML_noMultiLvlLbl = 2094;
+const xml_token_t XML_noProof = 2095;
+const xml_token_t XML_noPunctuationKerning = 2096;
+const xml_token_t XML_noResize = 2097;
+const xml_token_t XML_noResizeAllowed = 2098;
+const xml_token_t XML_noRot = 2099;
+const xml_token_t XML_noSelect = 2100;
+const xml_token_t XML_noSpaceRaiseLower = 2101;
+const xml_token_t XML_noTabHangInd = 2102;
+const xml_token_t XML_noTextEdit = 2103;
+const xml_token_t XML_noUngrp = 2104;
+const xml_token_t XML_noWrap = 2105;
+const xml_token_t XML_nodePh = 2106;
+const xml_token_t XML_nodeType = 2107;
+const xml_token_t XML_nonAutoSortDefault = 2108;
+const xml_token_t XML_nor = 2109;
+const xml_token_t XML_norm = 2110;
+const xml_token_t XML_normAutofit = 2111;
+const xml_token_t XML_normalViewPr = 2112;
+const xml_token_t XML_normalizeH = 2113;
+const xml_token_t XML_notTrueType = 2114;
+const xml_token_t XML_notes = 2115;
+const xml_token_t XML_notesMaster = 2116;
+const xml_token_t XML_notesMasterId = 2117;
+const xml_token_t XML_notesMasterIdLst = 2118;
+const xml_token_t XML_notesStyle = 2119;
+const xml_token_t XML_notesSz = 2120;
+const xml_token_t XML_notesTextViewPr = 2121;
+const xml_token_t XML_notesViewPr = 2122;
+const xml_token_t XML_np = 2123;
+const xml_token_t XML_ns = 2124;
+const xml_token_t XML_nsid = 2125;
+const xml_token_t XML_null = 2126;
+const xml_token_t XML_num = 2127;
+const xml_token_t XML_numCache = 2128;
+const xml_token_t XML_numCol = 2129;
+const xml_token_t XML_numFmt = 2130;
+const xml_token_t XML_numFmtId = 2131;
+const xml_token_t XML_numFmts = 2132;
+const xml_token_t XML_numId = 2133;
+const xml_token_t XML_numIdMacAtCleanup = 2134;
+const xml_token_t XML_numLit = 2135;
+const xml_token_t XML_numPicBullet = 2136;
+const xml_token_t XML_numPicBulletId = 2137;
+const xml_token_t XML_numPr = 2138;
+const xml_token_t XML_numRef = 2139;
+const xml_token_t XML_numRestart = 2140;
+const xml_token_t XML_numSld = 2141;
+const xml_token_t XML_numStart = 2142;
+const xml_token_t XML_numStyleLink = 2143;
+const xml_token_t XML_numberStoredAsText = 2144;
+const xml_token_t XML_numbering = 2145;
+const xml_token_t XML_numberingChange = 2146;
+const xml_token_t XML_nvCxnSpPr = 2147;
+const xml_token_t XML_nvGraphicFramePr = 2148;
+const xml_token_t XML_nvGrpSpPr = 2149;
+const xml_token_t XML_nvPicPr = 2150;
+const xml_token_t XML_nvPr = 2151;
+const xml_token_t XML_nvSpPr = 2152;
+const xml_token_t XML_nwCell = 2153;
+const xml_token_t XML_o = 2154;
+const xml_token_t XML_oMath = 2155;
+const xml_token_t XML_oMathPara = 2156;
+const xml_token_t XML_oMathParaPr = 2157;
+const xml_token_t XML_objDist = 2158;
+const xml_token_t XML_object = 2159;
+const xml_token_t XML_objectDefaults = 2160;
+const xml_token_t XML_objects = 2161;
+const xml_token_t XML_oblob = 2162;
+const xml_token_t XML_obscured = 2163;
+const xml_token_t XML_oc = 2164;
+const xml_token_t XML_odcFile = 2165;
+const xml_token_t XML_oddFooter = 2166;
+const xml_token_t XML_oddHeader = 2167;
+const xml_token_t XML_odso = 2168;
+const xml_token_t XML_odxf = 2169;
+const xml_token_t XML_ofPieChart = 2170;
+const xml_token_t XML_ofPieType = 2171;
+const xml_token_t XML_off = 2172;
+const xml_token_t XML_offset = 2173;
+const xml_token_t XML_offset2 = 2174;
+const xml_token_t XML_offsetFrom = 2175;
+const xml_token_t XML_olapPr = 2176;
+const xml_token_t XML_old = 2177;
+const xml_token_t XML_oldComment = 2178;
+const xml_token_t XML_oldCustomMenu = 2179;
+const xml_token_t XML_oldDescription = 2180;
+const xml_token_t XML_oldFormula = 2181;
+const xml_token_t XML_oldFunction = 2182;
+const xml_token_t XML_oldFunctionGroupId = 2183;
+const xml_token_t XML_oldHelp = 2184;
+const xml_token_t XML_oldHidden = 2185;
+const xml_token_t XML_oldLength = 2186;
+const xml_token_t XML_oldName = 2187;
+const xml_token_t XML_oldPh = 2188;
+const xml_token_t XML_oldQuotePrefix = 2189;
+const xml_token_t XML_oldShortcutKey = 2190;
+const xml_token_t XML_oldStatusBar = 2191;
+const xml_token_t XML_ole = 2192;
+const xml_token_t XML_oleChartEl = 2193;
+const xml_token_t XML_oleItem = 2194;
+const xml_token_t XML_oleItems = 2195;
+const xml_token_t XML_oleLink = 2196;
+const xml_token_t XML_oleObj = 2197;
+const xml_token_t XML_oleObject = 2198;
+const xml_token_t XML_oleObjects = 2199;
+const xml_token_t XML_oleSize = 2200;
+const xml_token_t XML_oleUpdate = 2201;
+const xml_token_t XML_oleicon = 2202;
+const xml_token_t XML_oleid = 2203;
+const xml_token_t XML_on = 2204;
+const xml_token_t XML_oneCellAnchor = 2205;
+const xml_token_t XML_oneField = 2206;
+const xml_token_t XML_oned = 2207;
+const xml_token_t XML_onlySync = 2208;
+const xml_token_t XML_onlyUseConnectionFile = 2209;
+const xml_token_t XML_op = 2210;
+const xml_token_t XML_opEmu = 2211;
+const xml_token_t XML_opacity = 2212;
+const xml_token_t XML_opacity2 = 2213;
+const xml_token_t XML_operator = 2214;
+const xml_token_t XML_optimizeForBrowser = 2215;
+const xml_token_t XML_optimizeMemory = 2216;
+const xml_token_t XML_order = 2217;
+const xml_token_t XML_orgChart = 2218;
+const xml_token_t XML_organizeInFolders = 2219;
+const xml_token_t XML_orient = 2220;
+const xml_token_t XML_orientation = 2221;
+const xml_token_t XML_orientationangle = 2222;
+const xml_token_t XML_origin = 2223;
+const xml_token_t XML_original = 2224;
+const xml_token_t XML_ostorage = 2225;
+const xml_token_t XML_ostream = 2226;
+const xml_token_t XML_other = 2227;
+const xml_token_t XML_otherStyle = 2228;
+const xml_token_t XML_outerShdw = 2229;
+const xml_token_t XML_outline = 2230;
+const xml_token_t XML_outlineData = 2231;
+const xml_token_t XML_outlineLevel = 2232;
+const xml_token_t XML_outlineLevelCol = 2233;
+const xml_token_t XML_outlineLevelRow = 2234;
+const xml_token_t XML_outlineLvl = 2235;
+const xml_token_t XML_outlinePr = 2236;
+const xml_token_t XML_outlineSymbols = 2237;
+const xml_token_t XML_outlineViewPr = 2238;
+const xml_token_t XML_oval = 2239;
+const xml_token_t XML_overflowPunct = 2240;
+const xml_token_t XML_overlap = 2241;
+const xml_token_t XML_overlay = 2242;
+const xml_token_t XML_override = 2243;
+const xml_token_t XML_overrideClrMapping = 2244;
+const xml_token_t XML_p = 2245;
+const xml_token_t XML_pBdr = 2246;
+const xml_token_t XML_pLen = 2247;
+const xml_token_t XML_pPos = 2248;
+const xml_token_t XML_pPr = 2249;
+const xml_token_t XML_pPrChange = 2250;
+const xml_token_t XML_pPrDefault = 2251;
+const xml_token_t XML_pRg = 2252;
+const xml_token_t XML_pStyle = 2253;
+const xml_token_t XML_page = 2254;
+const xml_token_t XML_pageBreakBefore = 2255;
+const xml_token_t XML_pageField = 2256;
+const xml_token_t XML_pageFields = 2257;
+const xml_token_t XML_pageItem = 2258;
+const xml_token_t XML_pageMargins = 2259;
+const xml_token_t XML_pageOrder = 2260;
+const xml_token_t XML_pageOverThenDown = 2261;
+const xml_token_t XML_pageSetUpPr = 2262;
+const xml_token_t XML_pageSetup = 2263;
+const xml_token_t XML_pageStyle = 2264;
+const xml_token_t XML_pageWrap = 2265;
+const xml_token_t XML_pages = 2266;
+const xml_token_t XML_pane = 2267;
+const xml_token_t XML_panose = 2268;
+const xml_token_t XML_panose1 = 2269;
+const xml_token_t XML_paperSize = 2270;
+const xml_token_t XML_paperSrc = 2271;
+const xml_token_t XML_par = 2272;
+const xml_token_t XML_parTransId = 2273;
+const xml_token_t XML_param = 2274;
+const xml_token_t XML_parameter = 2275;
+const xml_token_t XML_parameterType = 2276;
+const xml_token_t XML_parameters = 2277;
+const xml_token_t XML_parent = 2278;
+const xml_token_t XML_parentSet = 2279;
+const xml_token_t XML_parsePre = 2280;
+const xml_token_t XML_password = 2281;
+const xml_token_t XML_pasteAll = 2282;
+const xml_token_t XML_pasteBorders = 2283;
+const xml_token_t XML_pasteColWidths = 2284;
+const xml_token_t XML_pasteComments = 2285;
+const xml_token_t XML_pasteDataValidation = 2286;
+const xml_token_t XML_pasteFormats = 2287;
+const xml_token_t XML_pasteFormulas = 2288;
+const xml_token_t XML_pasteNumberFormats = 2289;
+const xml_token_t XML_pasteValues = 2290;
+const xml_token_t XML_path = 2291;
+const xml_token_t XML_pathEditMode = 2292;
+const xml_token_t XML_pathLst = 2293;
+const xml_token_t XML_pattFill = 2294;
+const xml_token_t XML_patternFill = 2295;
+const xml_token_t XML_patternType = 2296;
+const xml_token_t XML_penClr = 2297;
+const xml_token_t XML_percent = 2298;
+const xml_token_t XML_period = 2299;
+const xml_token_t XML_permEnd = 2300;
+const xml_token_t XML_permStart = 2301;
+const xml_token_t XML_personal = 2302;
+const xml_token_t XML_personalCompose = 2303;
+const xml_token_t XML_personalReply = 2304;
+const xml_token_t XML_personalView = 2305;
+const xml_token_t XML_perspective = 2306;
+const xml_token_t XML_pgBorders = 2307;
+const xml_token_t XML_pgMar = 2308;
+const xml_token_t XML_pgNum = 2309;
+const xml_token_t XML_pgNumType = 2310;
+const xml_token_t XML_pgSz = 2311;
+const xml_token_t XML_ph = 2312;
+const xml_token_t XML_phant = 2313;
+const xml_token_t XML_phantPr = 2314;
+const xml_token_t XML_phldr = 2315;
+const xml_token_t XML_phldrT = 2316;
+const xml_token_t XML_phonetic = 2317;
+const xml_token_t XML_phoneticPr = 2318;
+const xml_token_t XML_photoAlbum = 2319;
+const xml_token_t XML_pic = 2320;
+const xml_token_t XML_picLocks = 2321;
+const xml_token_t XML_pict = 2322;
+const xml_token_t XML_picture = 2323;
+const xml_token_t XML_pictureFormat = 2324;
+const xml_token_t XML_pictureOptions = 2325;
+const xml_token_t XML_pictureStackUnit = 2326;
+const xml_token_t XML_pid = 2327;
+const xml_token_t XML_pie3DChart = 2328;
+const xml_token_t XML_pieChart = 2329;
+const xml_token_t XML_pitch = 2330;
+const xml_token_t XML_pitchFamily = 2331;
+const xml_token_t XML_pivot = 2332;
+const xml_token_t XML_pivotArea = 2333;
+const xml_token_t XML_pivotAreas = 2334;
+const xml_token_t XML_pivotButton = 2335;
+const xml_token_t XML_pivotCache = 2336;
+const xml_token_t XML_pivotCacheDefinition = 2337;
+const xml_token_t XML_pivotCacheRecords = 2338;
+const xml_token_t XML_pivotCaches = 2339;
+const xml_token_t XML_pivotField = 2340;
+const xml_token_t XML_pivotFields = 2341;
+const xml_token_t XML_pivotFmt = 2342;
+const xml_token_t XML_pivotFmts = 2343;
+const xml_token_t XML_pivotHierarchies = 2344;
+const xml_token_t XML_pivotHierarchy = 2345;
+const xml_token_t XML_pivotSelection = 2346;
+const xml_token_t XML_pivotSource = 2347;
+const xml_token_t XML_pivotTableDefinition = 2348;
+const xml_token_t XML_pivotTableStyle = 2349;
+const xml_token_t XML_pivotTableStyleInfo = 2350;
+const xml_token_t XML_pivotTables = 2351;
+const xml_token_t XML_pixelsPerInch = 2352;
+const xml_token_t XML_placeholder = 2353;
+const xml_token_t XML_plane = 2354;
+const xml_token_t XML_plcHide = 2355;
+const xml_token_t XML_plotArea = 2356;
+const xml_token_t XML_plotVisOnly = 2357;
+const xml_token_t XML_plus = 2358;
+const xml_token_t XML_points = 2359;
+const xml_token_t XML_polar = 2360;
+const xml_token_t XML_polyline = 2361;
+const xml_token_t XML_pos = 2362;
+const xml_token_t XML_posOffset = 2363;
+const xml_token_t XML_position = 2364;
+const xml_token_t XML_positionH = 2365;
+const xml_token_t XML_positionV = 2366;
+const xml_token_t XML_post = 2367;
+const xml_token_t XML_postSp = 2368;
+const xml_token_t XML_prLst = 2369;
+const xml_token_t XML_prSet = 2370;
+const xml_token_t XML_preSp = 2371;
+const xml_token_t XML_preferPic = 2372;
+const xml_token_t XML_preferRelativeResize = 2373;
+const xml_token_t XML_preferSingleView = 2374;
+const xml_token_t XML_preferrelative = 2375;
+const xml_token_t XML_prefixMappings = 2376;
+const xml_token_t XML_presAssocID = 2377;
+const xml_token_t XML_presId = 2378;
+const xml_token_t XML_presLayoutVars = 2379;
+const xml_token_t XML_presName = 2380;
+const xml_token_t XML_presOf = 2381;
+const xml_token_t XML_presStyleCnt = 2382;
+const xml_token_t XML_presStyleIdx = 2383;
+const xml_token_t XML_presStyleLbl = 2384;
+const xml_token_t XML_present = 2385;
+const xml_token_t XML_presentation = 2386;
+const xml_token_t XML_presentationPr = 2387;
+const xml_token_t XML_preserve = 2388;
+const xml_token_t XML_preserveFormatting = 2389;
+const xml_token_t XML_preserveHistory = 2390;
+const xml_token_t XML_preserveSortFilterLayout = 2391;
+const xml_token_t XML_presetClass = 2392;
+const xml_token_t XML_presetID = 2393;
+const xml_token_t XML_presetSubtype = 2394;
+const xml_token_t XML_prevAc = 2395;
+const xml_token_t XML_prevCondLst = 2396;
+const xml_token_t XML_previousCol = 2397;
+const xml_token_t XML_previousRow = 2398;
+const xml_token_t XML_pri = 2399;
+const xml_token_t XML_print = 2400;
+const xml_token_t XML_printArea = 2401;
+const xml_token_t XML_printBodyTextBeforeHeader = 2402;
+const xml_token_t XML_printColBlack = 2403;
+const xml_token_t XML_printDrill = 2404;
+const xml_token_t XML_printFormsData = 2405;
+const xml_token_t XML_printFractionalCharacterWidth = 2406;
+const xml_token_t XML_printOptions = 2407;
+const xml_token_t XML_printPostScriptOverText = 2408;
+const xml_token_t XML_printSettings = 2409;
+const xml_token_t XML_printTwoOnOne = 2410;
+const xml_token_t XML_printerSettings = 2411;
+const xml_token_t XML_priority = 2412;
+const xml_token_t XML_prnPr = 2413;
+const xml_token_t XML_prnWhat = 2414;
+const xml_token_t XML_productSubtotal = 2415;
+const xml_token_t XML_progId = 2416;
+const xml_token_t XML_progress = 2417;
+const xml_token_t XML_prompt = 2418;
+const xml_token_t XML_promptTitle = 2419;
+const xml_token_t XML_promptedSolutions = 2420;
+const xml_token_t XML_proofErr = 2421;
+const xml_token_t XML_proofState = 2422;
+const xml_token_t XML_property = 2423;
+const xml_token_t XML_propertyName = 2424;
+const xml_token_t XML_protected = 2425;
+const xml_token_t XML_protectedRange = 2426;
+const xml_token_t XML_protectedRanges = 2427;
+const xml_token_t XML_protection = 2428;
+const xml_token_t XML_provid = 2429;
+const xml_token_t XML_proxy = 2430;
+const xml_token_t XML_prst = 2431;
+const xml_token_t XML_prstClr = 2432;
+const xml_token_t XML_prstDash = 2433;
+const xml_token_t XML_prstGeom = 2434;
+const xml_token_t XML_prstMaterial = 2435;
+const xml_token_t XML_prstShdw = 2436;
+const xml_token_t XML_prstTxWarp = 2437;
+const xml_token_t XML_pt = 2438;
+const xml_token_t XML_ptCount = 2439;
+const xml_token_t XML_ptLst = 2440;
+const xml_token_t XML_ptType = 2441;
+const xml_token_t XML_ptab = 2442;
+const xml_token_t XML_ptsTypes = 2443;
+const xml_token_t XML_pubBrowser = 2444;
+const xml_token_t XML_publishItems = 2445;
+const xml_token_t XML_publishToServer = 2446;
+const xml_token_t XML_published = 2447;
+const xml_token_t XML_pull = 2448;
+const xml_token_t XML_push = 2449;
+const xml_token_t XML_qFormat = 2450;
+const xml_token_t XML_qs = 2451;
+const xml_token_t XML_qsCatId = 2452;
+const xml_token_t XML_qsTypeId = 2453;
+const xml_token_t XML_quadBezTo = 2454;
+const xml_token_t XML_qualifier = 2455;
+const xml_token_t XML_query = 2456;
+const xml_token_t XML_queryCache = 2457;
+const xml_token_t XML_queryFailed = 2458;
+const xml_token_t XML_queryTable = 2459;
+const xml_token_t XML_queryTableDeletedFields = 2460;
+const xml_token_t XML_queryTableField = 2461;
+const xml_token_t XML_queryTableFieldId = 2462;
+const xml_token_t XML_queryTableFields = 2463;
+const xml_token_t XML_queryTableRefresh = 2464;
+const xml_token_t XML_quickTimeFile = 2465;
+const xml_token_t XML_quotePrefix = 2466;
+const xml_token_t XML_r = 2467;
+const xml_token_t XML_r1 = 2468;
+const xml_token_t XML_r2 = 2469;
+const xml_token_t XML_r4 = 2470;
+const xml_token_t XML_r8 = 2471;
+const xml_token_t XML_rAng = 2472;
+const xml_token_t XML_rAngAx = 2473;
+const xml_token_t XML_rCtr = 2474;
+const xml_token_t XML_rFont = 2475;
+const xml_token_t XML_rFonts = 2476;
+const xml_token_t XML_rId = 2477;
+const xml_token_t XML_rIns = 2478;
+const xml_token_t XML_rMargin = 2479;
+const xml_token_t XML_rPh = 2480;
+const xml_token_t XML_rPr = 2481;
+const xml_token_t XML_rPrChange = 2482;
+const xml_token_t XML_rPrDefault = 2483;
+const xml_token_t XML_rSp = 2484;
+const xml_token_t XML_rSpRule = 2485;
+const xml_token_t XML_rStyle = 2486;
+const xml_token_t XML_ra = 2487;
+const xml_token_t XML_rad = 2488;
+const xml_token_t XML_radPr = 2489;
+const xml_token_t XML_radarChart = 2490;
+const xml_token_t XML_radarStyle = 2491;
+const xml_token_t XML_radiusrange = 2492;
+const xml_token_t XML_raf = 2493;
+const xml_token_t XML_random = 2494;
+const xml_token_t XML_randomBar = 2495;
+const xml_token_t XML_rangePr = 2496;
+const xml_token_t XML_rangeSet = 2497;
+const xml_token_t XML_rangeSets = 2498;
+const xml_token_t XML_rank = 2499;
+const xml_token_t XML_rankBy = 2500;
+const xml_token_t XML_rc = 2501;
+const xml_token_t XML_rcc = 2502;
+const xml_token_t XML_rcft = 2503;
+const xml_token_t XML_rcmt = 2504;
+const xml_token_t XML_rctx = 2505;
+const xml_token_t XML_rcv = 2506;
+const xml_token_t XML_rdn = 2507;
+const xml_token_t XML_readModeInkLockDown = 2508;
+const xml_token_t XML_readOnlyRecommended = 2509;
+const xml_token_t XML_readingOrder = 2510;
+const xml_token_t XML_recipientData = 2511;
+const xml_token_t XML_recipients = 2512;
+const xml_token_t XML_recolor = 2513;
+const xml_token_t XML_recolortarget = 2514;
+const xml_token_t XML_recommended = 2515;
+const xml_token_t XML_reconnectionMethod = 2516;
+const xml_token_t XML_recordCount = 2517;
+const xml_token_t XML_rect = 2518;
+const xml_token_t XML_red = 2519;
+const xml_token_t XML_redMod = 2520;
+const xml_token_t XML_redOff = 2521;
+const xml_token_t XML_ref = 2522;
+const xml_token_t XML_ref3D = 2523;
+const xml_token_t XML_refFor = 2524;
+const xml_token_t XML_refForName = 2525;
+const xml_token_t XML_refMode = 2526;
+const xml_token_t XML_refPtType = 2527;
+const xml_token_t XML_refType = 2528;
+const xml_token_t XML_reference = 2529;
+const xml_token_t XML_references = 2530;
+const xml_token_t XML_refersTo = 2531;
+const xml_token_t XML_reflection = 2532;
+const xml_token_t XML_refreshAllConnections = 2533;
+const xml_token_t XML_refreshError = 2534;
+const xml_token_t XML_refreshOnChange = 2535;
+const xml_token_t XML_refreshOnLoad = 2536;
+const xml_token_t XML_refreshedBy = 2537;
+const xml_token_t XML_refreshedDate = 2538;
+const xml_token_t XML_refreshedVersion = 2539;
+const xml_token_t XML_regroupid = 2540;
+const xml_token_t XML_regrouptable = 2541;
+const xml_token_t XML_regular = 2542;
+const xml_token_t XML_rel = 2543;
+const xml_token_t XML_relIds = 2544;
+const xml_token_t XML_relOff = 2545;
+const xml_token_t XML_relSizeAnchor = 2546;
+const xml_token_t XML_relation = 2547;
+const xml_token_t XML_relationtable = 2548;
+const xml_token_t XML_relative = 2549;
+const xml_token_t XML_relativeFrom = 2550;
+const xml_token_t XML_relativeHeight = 2551;
+const xml_token_t XML_relativeIndent = 2552;
+const xml_token_t XML_relativeTo = 2553;
+const xml_token_t XML_relid = 2554;
+const xml_token_t XML_relyOnVML = 2555;
+const xml_token_t XML_relyOnVml = 2556;
+const xml_token_t XML_removeDataOnSave = 2557;
+const xml_token_t XML_removeDateAndTime = 2558;
+const xml_token_t XML_removePersonalInfoOnSave = 2559;
+const xml_token_t XML_removePersonalInformation = 2560;
+const xml_token_t XML_render = 2561;
+const xml_token_t XML_repairLoad = 2562;
+const xml_token_t XML_repeatCount = 2563;
+const xml_token_t XML_repeatDur = 2564;
+const xml_token_t XML_resId = 2565;
+const xml_token_t XML_reservationPassword = 2566;
+const xml_token_t XML_resizeGraphics = 2567;
+const xml_token_t XML_resizeHandles = 2568;
+const xml_token_t XML_restart = 2569;
+const xml_token_t XML_restoredLeft = 2570;
+const xml_token_t XML_restoredTop = 2571;
+const xml_token_t XML_result = 2572;
+const xml_token_t XML_rev = 2573;
+const xml_token_t XML_reverse = 2574;
+const xml_token_t XML_reviewed = 2575;
+const xml_token_t XML_reviewedList = 2576;
+const xml_token_t XML_revisionId = 2577;
+const xml_token_t XML_revisionView = 2578;
+const xml_token_t XML_revisions = 2579;
+const xml_token_t XML_revisionsPassword = 2580;
+const xml_token_t XML_rfmt = 2581;
+const xml_token_t XML_rgb = 2582;
+const xml_token_t XML_rgbColor = 2583;
+const xml_token_t XML_rich = 2584;
+const xml_token_t XML_richText = 2585;
+const xml_token_t XML_rig = 2586;
+const xml_token_t XML_right = 2587;
+const xml_token_t XML_rightChars = 2588;
+const xml_token_t XML_rightFromText = 2589;
+const xml_token_t XML_rightToLeft = 2590;
+const xml_token_t XML_ris = 2591;
+const xml_token_t XML_rm = 2592;
+const xml_token_t XML_rot = 2593;
+const xml_token_t XML_rotWithShape = 2594;
+const xml_token_t XML_rotX = 2595;
+const xml_token_t XML_rotY = 2596;
+const xml_token_t XML_rotate = 2597;
+const xml_token_t XML_rotation = 2598;
+const xml_token_t XML_rotationangle = 2599;
+const xml_token_t XML_rotationcenter = 2600;
+const xml_token_t XML_round = 2601;
+const xml_token_t XML_roundedCorners = 2602;
+const xml_token_t XML_roundrect = 2603;
+const xml_token_t XML_row = 2604;
+const xml_token_t XML_rowBreaks = 2605;
+const xml_token_t XML_rowColShift = 2606;
+const xml_token_t XML_rowDrillCount = 2607;
+const xml_token_t XML_rowFields = 2608;
+const xml_token_t XML_rowGrandTotals = 2609;
+const xml_token_t XML_rowHeaderCaption = 2610;
+const xml_token_t XML_rowHierarchiesUsage = 2611;
+const xml_token_t XML_rowHierarchyUsage = 2612;
+const xml_token_t XML_rowItems = 2613;
+const xml_token_t XML_rowNumbers = 2614;
+const xml_token_t XML_rowOff = 2615;
+const xml_token_t XML_rowPageCount = 2616;
+const xml_token_t XML_rowSpan = 2617;
+const xml_token_t XML_rows = 2618;
+const xml_token_t XML_rqt = 2619;
+const xml_token_t XML_rrc = 2620;
+const xml_token_t XML_rsid = 2621;
+const xml_token_t XML_rsidDel = 2622;
+const xml_token_t XML_rsidP = 2623;
+const xml_token_t XML_rsidR = 2624;
+const xml_token_t XML_rsidRDefault = 2625;
+const xml_token_t XML_rsidRPr = 2626;
+const xml_token_t XML_rsidRoot = 2627;
+const xml_token_t XML_rsidSect = 2628;
+const xml_token_t XML_rsidTr = 2629;
+const xml_token_t XML_rsids = 2630;
+const xml_token_t XML_rsnm = 2631;
+const xml_token_t XML_rt = 2632;
+const xml_token_t XML_rtl = 2633;
+const xml_token_t XML_rtlCol = 2634;
+const xml_token_t XML_rtlGutter = 2635;
+const xml_token_t XML_rtn = 2636;
+const xml_token_t XML_ruby = 2637;
+const xml_token_t XML_rubyAlign = 2638;
+const xml_token_t XML_rubyBase = 2639;
+const xml_token_t XML_rubyPr = 2640;
+const xml_token_t XML_rule = 2641;
+const xml_token_t XML_ruleLst = 2642;
+const xml_token_t XML_rules = 2643;
+const xml_token_t XML_rupBuild = 2644;
+const xml_token_t XML_s = 2645;
+const xml_token_t XML_sId = 2646;
+const xml_token_t XML_sPre = 2647;
+const xml_token_t XML_sPrePr = 2648;
+const xml_token_t XML_sSub = 2649;
+const xml_token_t XML_sSubPr = 2650;
+const xml_token_t XML_sSubSup = 2651;
+const xml_token_t XML_sSubSupPr = 2652;
+const xml_token_t XML_sSup = 2653;
+const xml_token_t XML_sSupPr = 2654;
+const xml_token_t XML_salt = 2655;
+const xml_token_t XML_saltData = 2656;
+const xml_token_t XML_sampData = 2657;
+const xml_token_t XML_sat = 2658;
+const xml_token_t XML_satMod = 2659;
+const xml_token_t XML_satOff = 2660;
+const xml_token_t XML_saveData = 2661;
+const xml_token_t XML_saveExternalLinkValues = 2662;
+const xml_token_t XML_saveFormsData = 2663;
+const xml_token_t XML_saveInvalidXml = 2664;
+const xml_token_t XML_savePassword = 2665;
+const xml_token_t XML_savePreviewPicture = 2666;
+const xml_token_t XML_saveSmartTagsAsXml = 2667;
+const xml_token_t XML_saveSubsetFonts = 2668;
+const xml_token_t XML_saveThroughXslt = 2669;
+const xml_token_t XML_saveXmlDataOnly = 2670;
+const xml_token_t XML_sb = 2671;
+const xml_token_t XML_scale = 2672;
+const xml_token_t XML_scaleToFitPaper = 2673;
+const xml_token_t XML_scaleWithDoc = 2674;
+const xml_token_t XML_scaled = 2675;
+const xml_token_t XML_scaling = 2676;
+const xml_token_t XML_scatterChart = 2677;
+const xml_token_t XML_scatterStyle = 2678;
+const xml_token_t XML_scenario = 2679;
+const xml_token_t XML_scenarios = 2680;
+const xml_token_t XML_scene3d = 2681;
+const xml_token_t XML_schema = 2682;
+const xml_token_t XML_schemaLibrary = 2683;
+const xml_token_t XML_schemaLocation = 2684;
+const xml_token_t XML_schemaRef = 2685;
+const xml_token_t XML_schemaRefs = 2686;
+const xml_token_t XML_scheme = 2687;
+const xml_token_t XML_schemeClr = 2688;
+const xml_token_t XML_scope = 2689;
+const xml_token_t XML_scr = 2690;
+const xml_token_t XML_scrgbClr = 2691;
+const xml_token_t XML_script = 2692;
+const xml_token_t XML_scrollbar = 2693;
+const xml_token_t XML_sd = 2694;
+const xml_token_t XML_sdt = 2695;
+const xml_token_t XML_sdtContent = 2696;
+const xml_token_t XML_sdtEndPr = 2697;
+const xml_token_t XML_sdtPr = 2698;
+const xml_token_t XML_seCell = 2699;
+const xml_token_t XML_second = 2700;
+const xml_token_t XML_secondPiePt = 2701;
+const xml_token_t XML_secondPieSize = 2702;
+const xml_token_t XML_sectPr = 2703;
+const xml_token_t XML_sectPrChange = 2704;
+const xml_token_t XML_securityDescriptor = 2705;
+const xml_token_t XML_selectFldWithFirstOrLastChar = 2706;
+const xml_token_t XML_selectLockedCells = 2707;
+const xml_token_t XML_selectUnlockedCells = 2708;
+const xml_token_t XML_selected = 2709;
+const xml_token_t XML_selection = 2710;
+const xml_token_t XML_semiHidden = 2711;
+const xml_token_t XML_semicolon = 2712;
+const xml_token_t XML_sendLocale = 2713;
+const xml_token_t XML_sep = 2714;
+const xml_token_t XML_sepChr = 2715;
+const xml_token_t XML_separator = 2716;
+const xml_token_t XML_seq = 2717;
+const xml_token_t XML_ser = 2718;
+const xml_token_t XML_serAx = 2719;
+const xml_token_t XML_serLines = 2720;
+const xml_token_t XML_series = 2721;
+const xml_token_t XML_seriesIdx = 2722;
+const xml_token_t XML_serverCommand = 2723;
+const xml_token_t XML_serverField = 2724;
+const xml_token_t XML_serverFill = 2725;
+const xml_token_t XML_serverFont = 2726;
+const xml_token_t XML_serverFontColor = 2727;
+const xml_token_t XML_serverFormat = 2728;
+const xml_token_t XML_serverFormats = 2729;
+const xml_token_t XML_serverNumberFormat = 2730;
+const xml_token_t XML_serverSldId = 2731;
+const xml_token_t XML_serverSldModifiedTime = 2732;
+const xml_token_t XML_serverZoom = 2733;
+const xml_token_t XML_set = 2734;
+const xml_token_t XML_setDefinition = 2735;
+const xml_token_t XML_sets = 2736;
+const xml_token_t XML_settings = 2737;
+const xml_token_t XML_shade = 2738;
+const xml_token_t XML_shadeToTitle = 2739;
+const xml_token_t XML_shadow = 2740;
+const xml_token_t XML_shadowcolor = 2741;
+const xml_token_t XML_shadowok = 2742;
+const xml_token_t XML_shape = 2743;
+const xml_token_t XML_shapeDefaults = 2744;
+const xml_token_t XML_shapeId = 2745;
+const xml_token_t XML_shapeLayoutLikeWW8 = 2746;
+const xml_token_t XML_shapedefaults = 2747;
+const xml_token_t XML_shapeid = 2748;
+const xml_token_t XML_shapelayout = 2749;
+const xml_token_t XML_shapetype = 2750;
+const xml_token_t XML_shared = 2751;
+const xml_token_t XML_sharedItems = 2752;
+const xml_token_t XML_shd = 2753;
+const xml_token_t XML_sheet = 2754;
+const xml_token_t XML_sheetCalcPr = 2755;
+const xml_token_t XML_sheetData = 2756;
+const xml_token_t XML_sheetDataSet = 2757;
+const xml_token_t XML_sheetFormatPr = 2758;
+const xml_token_t XML_sheetId = 2759;
+const xml_token_t XML_sheetIdMap = 2760;
+const xml_token_t XML_sheetName = 2761;
+const xml_token_t XML_sheetNames = 2762;
+const xml_token_t XML_sheetPosition = 2763;
+const xml_token_t XML_sheetPr = 2764;
+const xml_token_t XML_sheetProtection = 2765;
+const xml_token_t XML_sheetView = 2766;
+const xml_token_t XML_sheetViews = 2767;
+const xml_token_t XML_sheets = 2768;
+const xml_token_t XML_shininess = 2769;
+const xml_token_t XML_shortcutKey = 2770;
+const xml_token_t XML_show = 2771;
+const xml_token_t XML_showAll = 2772;
+const xml_token_t XML_showAnimation = 2773;
+const xml_token_t XML_showAsCaption = 2774;
+const xml_token_t XML_showAsIcon = 2775;
+const xml_token_t XML_showAutoFilter = 2776;
+const xml_token_t XML_showBorderUnselectedTables = 2777;
+const xml_token_t XML_showBreaksInFrames = 2778;
+const xml_token_t XML_showBubbleSize = 2779;
+const xml_token_t XML_showButton = 2780;
+const xml_token_t XML_showCalcMbrs = 2781;
+const xml_token_t XML_showCaptions = 2782;
+const xml_token_t XML_showCatName = 2783;
+const xml_token_t XML_showCell = 2784;
+const xml_token_t XML_showColHeaders = 2785;
+const xml_token_t XML_showColStripes = 2786;
+const xml_token_t XML_showColumnStripes = 2787;
+const xml_token_t XML_showComments = 2788;
+const xml_token_t XML_showDLblsOverMax = 2789;
+const xml_token_t XML_showDataAs = 2790;
+const xml_token_t XML_showDataDropDown = 2791;
+const xml_token_t XML_showDataTips = 2792;
+const xml_token_t XML_showDrill = 2793;
+const xml_token_t XML_showDropDown = 2794;
+const xml_token_t XML_showDropDowns = 2795;
+const xml_token_t XML_showDropZones = 2796;
+const xml_token_t XML_showEmptyCol = 2797;
+const xml_token_t XML_showEmptyRow = 2798;
+const xml_token_t XML_showEnvelope = 2799;
+const xml_token_t XML_showError = 2800;
+const xml_token_t XML_showErrorMessage = 2801;
+const xml_token_t XML_showFirstColumn = 2802;
+const xml_token_t XML_showFormatting = 2803;
+const xml_token_t XML_showFormulaBar = 2804;
+const xml_token_t XML_showFormulas = 2805;
+const xml_token_t XML_showGridLines = 2806;
+const xml_token_t XML_showGuides = 2807;
+const xml_token_t XML_showHeader = 2808;
+const xml_token_t XML_showHeaders = 2809;
+const xml_token_t XML_showHorizontalScroll = 2810;
+const xml_token_t XML_showHorzBorder = 2811;
+const xml_token_t XML_showInFieldList = 2812;
+const xml_token_t XML_showInkAnnotation = 2813;
+const xml_token_t XML_showInputMessage = 2814;
+const xml_token_t XML_showItems = 2815;
+const xml_token_t XML_showKeys = 2816;
+const xml_token_t XML_showLastColumn = 2817;
+const xml_token_t XML_showLeaderLines = 2818;
+const xml_token_t XML_showLegendKey = 2819;
+const xml_token_t XML_showMasterPhAnim = 2820;
+const xml_token_t XML_showMasterSp = 2821;
+const xml_token_t XML_showMemberPropertyTips = 2822;
+const xml_token_t XML_showMissing = 2823;
+const xml_token_t XML_showMultipleLabel = 2824;
+const xml_token_t XML_showNarration = 2825;
+const xml_token_t XML_showNegBubbles = 2826;
+const xml_token_t XML_showObjects = 2827;
+const xml_token_t XML_showOutline = 2828;
+const xml_token_t XML_showOutlineIcons = 2829;
+const xml_token_t XML_showOutlineSymbols = 2830;
+const xml_token_t XML_showPageBreaks = 2831;
+const xml_token_t XML_showPercent = 2832;
+const xml_token_t XML_showPivotChartFilter = 2833;
+const xml_token_t XML_showPr = 2834;
+const xml_token_t XML_showPropAsCaption = 2835;
+const xml_token_t XML_showPropCell = 2836;
+const xml_token_t XML_showPropTip = 2837;
+const xml_token_t XML_showRowCol = 2838;
+const xml_token_t XML_showRowColHeaders = 2839;
+const xml_token_t XML_showRowHeaders = 2840;
+const xml_token_t XML_showRowStripes = 2841;
+const xml_token_t XML_showRuler = 2842;
+const xml_token_t XML_showScrollbar = 2843;
+const xml_token_t XML_showSerName = 2844;
+const xml_token_t XML_showSheetTabs = 2845;
+const xml_token_t XML_showSpeakerNotes = 2846;
+const xml_token_t XML_showSpecialPlsOnTitleSld = 2847;
+const xml_token_t XML_showStatusbar = 2848;
+const xml_token_t XML_showTip = 2849;
+const xml_token_t XML_showVal = 2850;
+const xml_token_t XML_showValue = 2851;
+const xml_token_t XML_showVertBorder = 2852;
+const xml_token_t XML_showVerticalScroll = 2853;
+const xml_token_t XML_showWhenStopped = 2854;
+const xml_token_t XML_showWhiteSpace = 2855;
+const xml_token_t XML_showXMLTags = 2856;
+const xml_token_t XML_showZeros = 2857;
+const xml_token_t XML_showingPlcHdr = 2858;
+const xml_token_t XML_showsigndate = 2859;
+const xml_token_t XML_shp = 2860;
+const xml_token_t XML_shrinkToFit = 2861;
+const xml_token_t XML_si = 2862;
+const xml_token_t XML_sibTransId = 2863;
+const xml_token_t XML_side = 2864;
+const xml_token_t XML_sideWall = 2865;
+const xml_token_t XML_sig = 2866;
+const xml_token_t XML_signatureline = 2867;
+const xml_token_t XML_signinginstructions = 2868;
+const xml_token_t XML_signinginstructionsset = 2869;
+const xml_token_t XML_sigprovurl = 2870;
+const xml_token_t XML_simplePos = 2871;
+const xml_token_t XML_singleSignOnId = 2872;
+const xml_token_t XML_singleXmlCell = 2873;
+const xml_token_t XML_singleXmlCells = 2874;
+const xml_token_t XML_singleclick = 2875;
+const xml_token_t XML_size = 2876;
+const xml_token_t XML_sizeAuto = 2877;
+const xml_token_t XML_sizeRepresents = 2878;
+const xml_token_t XML_skew = 2879;
+const xml_token_t XML_skewamt = 2880;
+const xml_token_t XML_skewangle = 2881;
+const xml_token_t XML_sld = 2882;
+const xml_token_t XML_sldAll = 2883;
+const xml_token_t XML_sldId = 2884;
+const xml_token_t XML_sldIdLst = 2885;
+const xml_token_t XML_sldLayout = 2886;
+const xml_token_t XML_sldLayoutId = 2887;
+const xml_token_t XML_sldLayoutIdLst = 2888;
+const xml_token_t XML_sldLst = 2889;
+const xml_token_t XML_sldMaster = 2890;
+const xml_token_t XML_sldMasterId = 2891;
+const xml_token_t XML_sldMasterIdLst = 2892;
+const xml_token_t XML_sldNum = 2893;
+const xml_token_t XML_sldRg = 2894;
+const xml_token_t XML_sldSyncPr = 2895;
+const xml_token_t XML_sldSz = 2896;
+const xml_token_t XML_sldTgt = 2897;
+const xml_token_t XML_slideViewPr = 2898;
+const xml_token_t XML_smallCaps = 2899;
+const xml_token_t XML_smallFrac = 2900;
+const xml_token_t XML_smartTag = 2901;
+const xml_token_t XML_smartTagPr = 2902;
+const xml_token_t XML_smartTagType = 2903;
+const xml_token_t XML_smartTagTypes = 2904;
+const xml_token_t XML_smartTags = 2905;
+const xml_token_t XML_smooth = 2906;
+const xml_token_t XML_smtClean = 2907;
+const xml_token_t XML_smtId = 2908;
+const xml_token_t XML_snapToGrid = 2909;
+const xml_token_t XML_snapToObjects = 2910;
+const xml_token_t XML_snapVertSplitter = 2911;
+const xml_token_t XML_snd = 2912;
+const xml_token_t XML_sndAc = 2913;
+const xml_token_t XML_sndTgt = 2914;
+const xml_token_t XML_softEdge = 2915;
+const xml_token_t XML_softHyphen = 2916;
+const xml_token_t XML_solidFill = 2917;
+const xml_token_t XML_solutionID = 2918;
+const xml_token_t XML_solveOrder = 2919;
+const xml_token_t XML_sort = 2920;
+const xml_token_t XML_sortBy = 2921;
+const xml_token_t XML_sortByTuple = 2922;
+const xml_token_t XML_sortCondition = 2923;
+const xml_token_t XML_sortMethod = 2924;
+const xml_token_t XML_sortState = 2925;
+const xml_token_t XML_sortType = 2926;
+const xml_token_t XML_sorterViewPr = 2927;
+const xml_token_t XML_source = 2928;
+const xml_token_t XML_sourceData = 2929;
+const xml_token_t XML_sourceFile = 2930;
+const xml_token_t XML_sourceFileName = 2931;
+const xml_token_t XML_sourceLinked = 2932;
+const xml_token_t XML_sourceObject = 2933;
+const xml_token_t XML_sourceRef = 2934;
+const xml_token_t XML_sourceSheetId = 2935;
+const xml_token_t XML_sourceType = 2936;
+const xml_token_t XML_sp = 2937;
+const xml_token_t XML_sp3d = 2938;
+const xml_token_t XML_spAutoFit = 2939;
+const xml_token_t XML_spDef = 2940;
+const xml_token_t XML_spLocks = 2941;
+const xml_token_t XML_spPr = 2942;
+const xml_token_t XML_spTgt = 2943;
+const xml_token_t XML_spTree = 2944;
+const xml_token_t XML_space = 2945;
+const xml_token_t XML_spaceForUL = 2946;
+const xml_token_t XML_spacing = 2947;
+const xml_token_t XML_spacingInWholePoints = 2948;
+const xml_token_t XML_spans = 2949;
+const xml_token_t XML_spc = 2950;
+const xml_token_t XML_spcAft = 2951;
+const xml_token_t XML_spcBef = 2952;
+const xml_token_t XML_spcCol = 2953;
+const xml_token_t XML_spcFirstLastPara = 2954;
+const xml_token_t XML_spcPct = 2955;
+const xml_token_t XML_spcPts = 2956;
+const xml_token_t XML_spd = 2957;
+const xml_token_t XML_specVanish = 2958;
+const xml_token_t XML_specularity = 2959;
+const xml_token_t XML_spelling = 2960;
+const xml_token_t XML_spid = 2961;
+const xml_token_t XML_spidmax = 2962;
+const xml_token_t XML_spinCount = 2963;
+const xml_token_t XML_split = 2964;
+const xml_token_t XML_splitAll = 2965;
+const xml_token_t XML_splitFirst = 2966;
+const xml_token_t XML_splitPgBreakAndParaMark = 2967;
+const xml_token_t XML_splitPos = 2968;
+const xml_token_t XML_splitType = 2969;
+const xml_token_t XML_spokes = 2970;
+const xml_token_t XML_spt = 2971;
+const xml_token_t XML_sqlType = 2972;
+const xml_token_t XML_sqref = 2973;
+const xml_token_t XML_src = 2974;
+const xml_token_t XML_srcId = 2975;
+const xml_token_t XML_srcOrd = 2976;
+const xml_token_t XML_srcRect = 2977;
+const xml_token_t XML_srgbClr = 2978;
+const xml_token_t XML_sst = 2979;
+const xml_token_t XML_st = 2980;
+const xml_token_t XML_stA = 2981;
+const xml_token_t XML_stAng = 2982;
+const xml_token_t XML_stCondLst = 2983;
+const xml_token_t XML_stCxn = 2984;
+const xml_token_t XML_stPos = 2985;
+const xml_token_t XML_stSnd = 2986;
+const xml_token_t XML_start = 2987;
+const xml_token_t XML_startAngle = 2988;
+const xml_token_t XML_startAt = 2989;
+const xml_token_t XML_startDate = 2990;
+const xml_token_t XML_startNum = 2991;
+const xml_token_t XML_startOverride = 2992;
+const xml_token_t XML_startarrow = 2993;
+const xml_token_t XML_startarrowlength = 2994;
+const xml_token_t XML_startarrowwidth = 2995;
+const xml_token_t XML_state = 2996;
+const xml_token_t XML_status = 2997;
+const xml_token_t XML_statusBar = 2998;
+const xml_token_t XML_statusText = 2999;
+const xml_token_t XML_stdDev = 3000;
+const xml_token_t XML_stdDevPSubtotal = 3001;
+const xml_token_t XML_stdDevSubtotal = 3002;
+const xml_token_t XML_step = 3003;
+const xml_token_t XML_stockChart = 3004;
+const xml_token_t XML_stop = 3005;
+const xml_token_t XML_stopIfTrue = 3006;
+const xml_token_t XML_storage = 3007;
+const xml_token_t XML_storeItemID = 3008;
+const xml_token_t XML_storeMappedDataAs = 3009;
+const xml_token_t XML_stp = 3010;
+const xml_token_t XML_strCache = 3011;
+const xml_token_t XML_strLit = 3012;
+const xml_token_t XML_strRef = 3013;
+const xml_token_t XML_strVal = 3014;
+const xml_token_t XML_stream = 3015;
+const xml_token_t XML_stretch = 3016;
+const xml_token_t XML_strictFirstAndLastChars = 3017;
+const xml_token_t XML_strike = 3018;
+const xml_token_t XML_strikeBLTR = 3019;
+const xml_token_t XML_strikeH = 3020;
+const xml_token_t XML_strikeTLBR = 3021;
+const xml_token_t XML_strikeV = 3022;
+const xml_token_t XML_string = 3023;
+const xml_token_t XML_stringValue1 = 3024;
+const xml_token_t XML_stringValue2 = 3025;
+const xml_token_t XML_strips = 3026;
+const xml_token_t XML_stroke = 3027;
+const xml_token_t XML_strokecolor = 3028;
+const xml_token_t XML_stroked = 3029;
+const xml_token_t XML_strokeok = 3030;
+const xml_token_t XML_strokeweight = 3031;
+const xml_token_t XML_sty = 3032;
+const xml_token_t XML_style = 3033;
+const xml_token_t XML_styleData = 3034;
+const xml_token_t XML_styleDef = 3035;
+const xml_token_t XML_styleDefHdr = 3036;
+const xml_token_t XML_styleDefHdrLst = 3037;
+const xml_token_t XML_styleId = 3038;
+const xml_token_t XML_styleLbl = 3039;
+const xml_token_t XML_styleLink = 3040;
+const xml_token_t XML_styleLockQFSet = 3041;
+const xml_token_t XML_styleLockTheme = 3042;
+const xml_token_t XML_styleName = 3043;
+const xml_token_t XML_stylePaneFormatFilter = 3044;
+const xml_token_t XML_stylePaneSortMethod = 3045;
+const xml_token_t XML_styleSheet = 3046;
+const xml_token_t XML_styles = 3047;
+const xml_token_t XML_sub = 3048;
+const xml_token_t XML_subDoc = 3049;
+const xml_token_t XML_subFontBySize = 3050;
+const xml_token_t XML_subHide = 3051;
+const xml_token_t XML_subSp = 3052;
+const xml_token_t XML_subTnLst = 3053;
+const xml_token_t XML_subsetted = 3054;
+const xml_token_t XML_subtotal = 3055;
+const xml_token_t XML_subtotalCaption = 3056;
+const xml_token_t XML_subtotalHiddenItems = 3057;
+const xml_token_t XML_subtotalTop = 3058;
+const xml_token_t XML_suff = 3059;
+const xml_token_t XML_suggestedsigner = 3060;
+const xml_token_t XML_suggestedsigner2 = 3061;
+const xml_token_t XML_suggestedsigneremail = 3062;
+const xml_token_t XML_sumSubtotal = 3063;
+const xml_token_t XML_summaryBelow = 3064;
+const xml_token_t XML_summaryLength = 3065;
+const xml_token_t XML_summaryRight = 3066;
+const xml_token_t XML_sup = 3067;
+const xml_token_t XML_supHide = 3068;
+const xml_token_t XML_supportAdvancedDrill = 3069;
+const xml_token_t XML_supportSubquery = 3070;
+const xml_token_t XML_suppressAutoHyphens = 3071;
+const xml_token_t XML_suppressBottomSpacing = 3072;
+const xml_token_t XML_suppressLineNumbers = 3073;
+const xml_token_t XML_suppressOverlap = 3074;
+const xml_token_t XML_suppressSpBfAfterPgBrk = 3075;
+const xml_token_t XML_suppressSpacingAtTopOfPage = 3076;
+const xml_token_t XML_suppressTopSpacing = 3077;
+const xml_token_t XML_suppressTopSpacingWP = 3078;
+const xml_token_t XML_surface3DChart = 3079;
+const xml_token_t XML_surfaceChart = 3080;
+const xml_token_t XML_swAng = 3081;
+const xml_token_t XML_swCell = 3082;
+const xml_token_t XML_swapBordersFacingPages = 3083;
+const xml_token_t XML_switch = 3084;
+const xml_token_t XML_sx = 3085;
+const xml_token_t XML_sy = 3086;
+const xml_token_t XML_sym = 3087;
+const xml_token_t XML_symbol = 3088;
+const xml_token_t XML_syncBehavior = 3089;
+const xml_token_t XML_syncHorizontal = 3090;
+const xml_token_t XML_syncRef = 3091;
+const xml_token_t XML_syncVertical = 3092;
+const xml_token_t XML_sysClr = 3093;
+const xml_token_t XML_sz = 3094;
+const xml_token_t XML_szCs = 3095;
+const xml_token_t XML_t = 3096;
+const xml_token_t XML_t1 = 3097;
+const xml_token_t XML_t2 = 3098;
+const xml_token_t XML_tIns = 3099;
+const xml_token_t XML_tab = 3100;
+const xml_token_t XML_tabColor = 3101;
+const xml_token_t XML_tabLst = 3102;
+const xml_token_t XML_tabRatio = 3103;
+const xml_token_t XML_tabSelected = 3104;
+const xml_token_t XML_table = 3105;
+const xml_token_t XML_tableBorderDxfId = 3106;
+const xml_token_t XML_tableColumn = 3107;
+const xml_token_t XML_tableColumnId = 3108;
+const xml_token_t XML_tableColumns = 3109;
+const xml_token_t XML_tablePart = 3110;
+const xml_token_t XML_tableParts = 3111;
+const xml_token_t XML_tableStyle = 3112;
+const xml_token_t XML_tableStyleElement = 3113;
+const xml_token_t XML_tableStyleId = 3114;
+const xml_token_t XML_tableStyleInfo = 3115;
+const xml_token_t XML_tableStyles = 3116;
+const xml_token_t XML_tableType = 3117;
+const xml_token_t XML_tablelimits = 3118;
+const xml_token_t XML_tableproperties = 3119;
+const xml_token_t XML_tables = 3120;
+const xml_token_t XML_tabs = 3121;
+const xml_token_t XML_tag = 3122;
+const xml_token_t XML_tagLst = 3123;
+const xml_token_t XML_tags = 3124;
+const xml_token_t XML_tailEnd = 3125;
+const xml_token_t XML_target = 3126;
+const xml_token_t XML_targetScreenSize = 3127;
+const xml_token_t XML_targetScreenSz = 3128;
+const xml_token_t XML_targetscreensize = 3129;
+const xml_token_t XML_tav = 3130;
+const xml_token_t XML_tavLst = 3131;
+const xml_token_t XML_tbl = 3132;
+const xml_token_t XML_tblBg = 3133;
+const xml_token_t XML_tblBorders = 3134;
+const xml_token_t XML_tblCellMar = 3135;
+const xml_token_t XML_tblCellSpacing = 3136;
+const xml_token_t XML_tblGrid = 3137;
+const xml_token_t XML_tblGridChange = 3138;
+const xml_token_t XML_tblHeader = 3139;
+const xml_token_t XML_tblInd = 3140;
+const xml_token_t XML_tblLayout = 3141;
+const xml_token_t XML_tblLook = 3142;
+const xml_token_t XML_tblOverlap = 3143;
+const xml_token_t XML_tblPr = 3144;
+const xml_token_t XML_tblPrChange = 3145;
+const xml_token_t XML_tblPrEx = 3146;
+const xml_token_t XML_tblPrExChange = 3147;
+const xml_token_t XML_tblStyle = 3148;
+const xml_token_t XML_tblStyleColBandSize = 3149;
+const xml_token_t XML_tblStyleLst = 3150;
+const xml_token_t XML_tblStylePr = 3151;
+const xml_token_t XML_tblStyleRowBandSize = 3152;
+const xml_token_t XML_tblW = 3153;
+const xml_token_t XML_tblpPr = 3154;
+const xml_token_t XML_tblpX = 3155;
+const xml_token_t XML_tblpXSpec = 3156;
+const xml_token_t XML_tblpY = 3157;
+const xml_token_t XML_tblpYSpec = 3158;
+const xml_token_t XML_tc = 3159;
+const xml_token_t XML_tcBdr = 3160;
+const xml_token_t XML_tcBorders = 3161;
+const xml_token_t XML_tcFitText = 3162;
+const xml_token_t XML_tcMar = 3163;
+const xml_token_t XML_tcPr = 3164;
+const xml_token_t XML_tcPrChange = 3165;
+const xml_token_t XML_tcStyle = 3166;
+const xml_token_t XML_tcTxStyle = 3167;
+const xml_token_t XML_tcW = 3168;
+const xml_token_t XML_temporary = 3169;
+const xml_token_t XML_tentative = 3170;
+const xml_token_t XML_text = 3171;
+const xml_token_t XML_textAlignment = 3172;
+const xml_token_t XML_textDates = 3173;
+const xml_token_t XML_textDirection = 3174;
+const xml_token_t XML_textField = 3175;
+const xml_token_t XML_textFields = 3176;
+const xml_token_t XML_textInput = 3177;
+const xml_token_t XML_textPr = 3178;
+const xml_token_t XML_textRotation = 3179;
+const xml_token_t XML_textborder = 3180;
+const xml_token_t XML_textbox = 3181;
+const xml_token_t XML_textboxTightWrap = 3182;
+const xml_token_t XML_textboxrect = 3183;
+const xml_token_t XML_textdata = 3184;
+const xml_token_t XML_textlink = 3185;
+const xml_token_t XML_textpath = 3186;
+const xml_token_t XML_textpathok = 3187;
+const xml_token_t XML_tgtEl = 3188;
+const xml_token_t XML_tgtFrame = 3189;
+const xml_token_t XML_theme = 3190;
+const xml_token_t XML_themeColor = 3191;
+const xml_token_t XML_themeElements = 3192;
+const xml_token_t XML_themeFill = 3193;
+const xml_token_t XML_themeFillShade = 3194;
+const xml_token_t XML_themeFillTint = 3195;
+const xml_token_t XML_themeFontLang = 3196;
+const xml_token_t XML_themeManager = 3197;
+const xml_token_t XML_themeOverride = 3198;
+const xml_token_t XML_themeShade = 3199;
+const xml_token_t XML_themeTint = 3200;
+const xml_token_t XML_thickBot = 3201;
+const xml_token_t XML_thickBottom = 3202;
+const xml_token_t XML_thickTop = 3203;
+const xml_token_t XML_thicket = 3204;
+const xml_token_t XML_thickness = 3205;
+const xml_token_t XML_thousands = 3206;
+const xml_token_t XML_thresh = 3207;
+const xml_token_t XML_thruBlk = 3208;
+const xml_token_t XML_tickLblPos = 3209;
+const xml_token_t XML_tickLblSkip = 3210;
+const xml_token_t XML_tickMarkSkip = 3211;
+const xml_token_t XML_tile = 3212;
+const xml_token_t XML_tileRect = 3213;
+const xml_token_t XML_time = 3214;
+const xml_token_t XML_timePeriod = 3215;
+const xml_token_t XML_timing = 3216;
+const xml_token_t XML_tint = 3217;
+const xml_token_t XML_title = 3218;
+const xml_token_t XML_titlePg = 3219;
+const xml_token_t XML_titleStyle = 3220;
+const xml_token_t XML_tl2br = 3221;
+const xml_token_t XML_tm = 3222;
+const xml_token_t XML_tmAbs = 3223;
+const xml_token_t XML_tmFilter = 3224;
+const xml_token_t XML_tmPct = 3225;
+const xml_token_t XML_tmpl = 3226;
+const xml_token_t XML_tmplLst = 3227;
+const xml_token_t XML_tn = 3228;
+const xml_token_t XML_tnLst = 3229;
+const xml_token_t XML_to = 3230;
+const xml_token_t XML_tooltip = 3231;
+const xml_token_t XML_top = 3232;
+const xml_token_t XML_top10 = 3233;
+const xml_token_t XML_topAutoShow = 3234;
+const xml_token_t XML_topFromText = 3235;
+const xml_token_t XML_topLabels = 3236;
+const xml_token_t XML_topLeftCell = 3237;
+const xml_token_t XML_topLinePunct = 3238;
+const xml_token_t XML_totalsRowBorderDxfId = 3239;
+const xml_token_t XML_totalsRowCellStyle = 3240;
+const xml_token_t XML_totalsRowCount = 3241;
+const xml_token_t XML_totalsRowDxfId = 3242;
+const xml_token_t XML_totalsRowFormula = 3243;
+const xml_token_t XML_totalsRowFunction = 3244;
+const xml_token_t XML_totalsRowLabel = 3245;
+const xml_token_t XML_totalsRowShown = 3246;
+const xml_token_t XML_tp = 3247;
+const xml_token_t XML_tpl = 3248;
+const xml_token_t XML_tplc = 3249;
+const xml_token_t XML_tpls = 3250;
+const xml_token_t XML_tr = 3251;
+const xml_token_t XML_tr2bl = 3252;
+const xml_token_t XML_trHeight = 3253;
+const xml_token_t XML_trPr = 3254;
+const xml_token_t XML_trPrChange = 3255;
+const xml_token_t XML_track = 3256;
+const xml_token_t XML_trackRevisions = 3257;
+const xml_token_t XML_transition = 3258;
+const xml_token_t XML_transitionEntry = 3259;
+const xml_token_t XML_transitionEvaluation = 3260;
+const xml_token_t XML_transp = 3261;
+const xml_token_t XML_trend = 3262;
+const xml_token_t XML_trendline = 3263;
+const xml_token_t XML_trendlineLbl = 3264;
+const xml_token_t XML_trendlineType = 3265;
+const xml_token_t XML_trim = 3266;
+const xml_token_t XML_truncateFontHeightsLikeWP6 = 3267;
+const xml_token_t XML_tupleCache = 3268;
+const xml_token_t XML_twoCellAnchor = 3269;
+const xml_token_t XML_twoDigitTextYear = 3270;
+const xml_token_t XML_tx = 3271;
+const xml_token_t XML_tx1 = 3272;
+const xml_token_t XML_tx2 = 3273;
+const xml_token_t XML_txBody = 3274;
+const xml_token_t XML_txBox = 3275;
+const xml_token_t XML_txDef = 3276;
+const xml_token_t XML_txEffectClrLst = 3277;
+const xml_token_t XML_txEl = 3278;
+const xml_token_t XML_txFillClrLst = 3279;
+const xml_token_t XML_txLinClrLst = 3280;
+const xml_token_t XML_txPr = 3281;
+const xml_token_t XML_txSp = 3282;
+const xml_token_t XML_txStyles = 3283;
+const xml_token_t XML_txbxContent = 3284;
+const xml_token_t XML_ty = 3285;
+const xml_token_t XML_type = 3286;
+const xml_token_t XML_typeface = 3287;
+const xml_token_t XML_types = 3288;
+const xml_token_t XML_u = 3289;
+const xml_token_t XML_uBounds = 3290;
+const xml_token_t XML_uFill = 3291;
+const xml_token_t XML_uFillTx = 3292;
+const xml_token_t XML_uLn = 3293;
+const xml_token_t XML_uLnTx = 3294;
+const xml_token_t XML_ua = 3295;
+const xml_token_t XML_udl = 3296;
+const xml_token_t XML_ui1 = 3297;
+const xml_token_t XML_ui2 = 3298;
+const xml_token_t XML_ui4 = 3299;
+const xml_token_t XML_ui8 = 3300;
+const xml_token_t XML_uiCompat97To2003 = 3301;
+const xml_token_t XML_uiExpand = 3302;
+const xml_token_t XML_uiPriority = 3303;
+const xml_token_t XML_uint = 3304;
+const xml_token_t XML_ulTrailSpace = 3305;
+const xml_token_t XML_un = 3306;
+const xml_token_t XML_unbalanced = 3307;
+const xml_token_t XML_unbalancedGroup = 3308;
+const xml_token_t XML_unboundColumnsLeft = 3309;
+const xml_token_t XML_unboundColumnsRight = 3310;
+const xml_token_t XML_underlineTabInNumList = 3311;
+const xml_token_t XML_undo = 3312;
+const xml_token_t XML_undone = 3313;
+const xml_token_t XML_ungrouping = 3314;
+const xml_token_t XML_unhideWhenUsed = 3315;
+const xml_token_t XML_uniqueCount = 3316;
+const xml_token_t XML_uniqueId = 3317;
+const xml_token_t XML_uniqueList = 3318;
+const xml_token_t XML_uniqueMemberProperty = 3319;
+const xml_token_t XML_uniqueName = 3320;
+const xml_token_t XML_uniqueParent = 3321;
+const xml_token_t XML_uniqueTag = 3322;
+const xml_token_t XML_unlockedFormula = 3323;
+const xml_token_t XML_up = 3324;
+const xml_token_t XML_upBars = 3325;
+const xml_token_t XML_upDownBars = 3326;
+const xml_token_t XML_updateAutomatic = 3327;
+const xml_token_t XML_updateFields = 3328;
+const xml_token_t XML_updateLinks = 3329;
+const xml_token_t XML_updatedVersion = 3330;
+const xml_token_t XML_upgradeOnRefresh = 3331;
+const xml_token_t XML_upright = 3332;
+const xml_token_t XML_uri = 3333;
+const xml_token_t XML_url = 3334;
+const xml_token_t XML_usb0 = 3335;
+const xml_token_t XML_usb1 = 3336;
+const xml_token_t XML_usb2 = 3337;
+const xml_token_t XML_usb3 = 3338;
+const xml_token_t XML_useA = 3339;
+const xml_token_t XML_useAltKinsokuLineBreakRules = 3340;
+const xml_token_t XML_useAnsiKerningPairs = 3341;
+const xml_token_t XML_useAutoFormatting = 3342;
+const xml_token_t XML_useBgFill = 3343;
+const xml_token_t XML_useDef = 3344;
+const xml_token_t XML_useFELayout = 3345;
+const xml_token_t XML_useFirstPageNumber = 3346;
+const xml_token_t XML_useLongFilenames = 3347;
+const xml_token_t XML_useNormalStyleForList = 3348;
+const xml_token_t XML_usePrinterDefaults = 3349;
+const xml_token_t XML_usePrinterMetrics = 3350;
+const xml_token_t XML_useSingleBorderforContiguousCells = 3351;
+const xml_token_t XML_useSpRect = 3352;
+const xml_token_t XML_useTimings = 3353;
+const xml_token_t XML_useWord2002TableStyleRules = 3354;
+const xml_token_t XML_useWord97LineBreakRules = 3355;
+const xml_token_t XML_useXSLTWhenSaving = 3356;
+const xml_token_t XML_user = 3357;
+const xml_token_t XML_userDrawn = 3358;
+const xml_token_t XML_userInfo = 3359;
+const xml_token_t XML_userInterface = 3360;
+const xml_token_t XML_userName = 3361;
+const xml_token_t XML_userShapes = 3362;
+const xml_token_t XML_userdrawn = 3363;
+const xml_token_t XML_userhidden = 3364;
+const xml_token_t XML_users = 3365;
+const xml_token_t XML_v = 3366;
+const xml_token_t XML_vAlign = 3367;
+const xml_token_t XML_vAnchor = 3368;
+const xml_token_t XML_vMerge = 3369;
+const xml_token_t XML_vMergeOrig = 3370;
+const xml_token_t XML_vSpace = 3371;
+const xml_token_t XML_vacatedStyle = 3372;
+const xml_token_t XML_val = 3373;
+const xml_token_t XML_valAx = 3374;
+const xml_token_t XML_value = 3375;
+const xml_token_t XML_valueMetadata = 3376;
+const xml_token_t XML_valueType = 3377;
+const xml_token_t XML_values = 3378;
+const xml_token_t XML_vanish = 3379;
+const xml_token_t XML_varLst = 3380;
+const xml_token_t XML_varPSubtotal = 3381;
+const xml_token_t XML_varScale = 3382;
+const xml_token_t XML_varSubtotal = 3383;
+const xml_token_t XML_variant = 3384;
+const xml_token_t XML_varyColors = 3385;
+const xml_token_t XML_vbProcedure = 3386;
+const xml_token_t XML_vector = 3387;
+const xml_token_t XML_vendorID = 3388;
+const xml_token_t XML_version = 3389;
+const xml_token_t XML_vert = 3390;
+const xml_token_t XML_vertAlign = 3391;
+const xml_token_t XML_vertAnchor = 3392;
+const xml_token_t XML_vertBarState = 3393;
+const xml_token_t XML_vertCompress = 3394;
+const xml_token_t XML_vertJc = 3395;
+const xml_token_t XML_vertOverflow = 3396;
+const xml_token_t XML_vertical = 3397;
+const xml_token_t XML_verticalCentered = 3398;
+const xml_token_t XML_verticalDpi = 3399;
+const xml_token_t XML_verticies = 3400;
+const xml_token_t XML_video = 3401;
+const xml_token_t XML_videoFile = 3402;
+const xml_token_t XML_view = 3403;
+const xml_token_t XML_view3D = 3404;
+const xml_token_t XML_viewMergedData = 3405;
+const xml_token_t XML_viewPr = 3406;
+const xml_token_t XML_viewpoint = 3407;
+const xml_token_t XML_viewpointorigin = 3408;
+const xml_token_t XML_visibility = 3409;
+const xml_token_t XML_visualTotals = 3410;
+const xml_token_t XML_vm = 3411;
+const xml_token_t XML_vml = 3412;
+const xml_token_t XML_vocabulary = 3413;
+const xml_token_t XML_vol = 3414;
+const xml_token_t XML_volType = 3415;
+const xml_token_t XML_volTypes = 3416;
+const xml_token_t XML_vstream = 3417;
+const xml_token_t XML_w = 3418;
+const xml_token_t XML_wAfter = 3419;
+const xml_token_t XML_wBefore = 3420;
+const xml_token_t XML_wMode = 3421;
+const xml_token_t XML_wR = 3422;
+const xml_token_t XML_wavAudioFile = 3423;
+const xml_token_t XML_webHidden = 3424;
+const xml_token_t XML_webPr = 3425;
+const xml_token_t XML_webPublishItem = 3426;
+const xml_token_t XML_webPublishItems = 3427;
+const xml_token_t XML_webPublishObject = 3428;
+const xml_token_t XML_webPublishObjects = 3429;
+const xml_token_t XML_webPublishing = 3430;
+const xml_token_t XML_webSettings = 3431;
+const xml_token_t XML_wedge = 3432;
+const xml_token_t XML_weight = 3433;
+const xml_token_t XML_wheel = 3434;
+const xml_token_t XML_whole = 3435;
+const xml_token_t XML_wholeTbl = 3436;
+const xml_token_t XML_widowControl = 3437;
+const xml_token_t XML_width = 3438;
+const xml_token_t XML_windowHeight = 3439;
+const xml_token_t XML_windowProtection = 3440;
+const xml_token_t XML_windowWidth = 3441;
+const xml_token_t XML_wipe = 3442;
+const xml_token_t XML_wireframe = 3443;
+const xml_token_t XML_wordWrap = 3444;
+const xml_token_t XML_workbook = 3445;
+const xml_token_t XML_workbookParameter = 3446;
+const xml_token_t XML_workbookPassword = 3447;
+const xml_token_t XML_workbookPr = 3448;
+const xml_token_t XML_workbookProtection = 3449;
+const xml_token_t XML_workbookView = 3450;
+const xml_token_t XML_workbookViewId = 3451;
+const xml_token_t XML_worksheet = 3452;
+const xml_token_t XML_worksheetSource = 3453;
+const xml_token_t XML_wpJustification = 3454;
+const xml_token_t XML_wpSpaceWidth = 3455;
+const xml_token_t XML_wrap = 3456;
+const xml_token_t XML_wrapIndent = 3457;
+const xml_token_t XML_wrapNone = 3458;
+const xml_token_t XML_wrapPolygon = 3459;
+const xml_token_t XML_wrapRight = 3460;
+const xml_token_t XML_wrapSquare = 3461;
+const xml_token_t XML_wrapText = 3462;
+const xml_token_t XML_wrapThrough = 3463;
+const xml_token_t XML_wrapTight = 3464;
+const xml_token_t XML_wrapTopAndBottom = 3465;
+const xml_token_t XML_wrapTrailSpaces = 3466;
+const xml_token_t XML_wrapcoords = 3467;
+const xml_token_t XML_writeProtection = 3468;
+const xml_token_t XML_wsDr = 3469;
+const xml_token_t XML_x = 3470;
+const xml_token_t XML_xAlign = 3471;
+const xml_token_t XML_xMode = 3472;
+const xml_token_t XML_xSplit = 3473;
+const xml_token_t XML_xVal = 3474;
+const xml_token_t XML_xWindow = 3475;
+const xml_token_t XML_xf = 3476;
+const xml_token_t XML_xfDxf = 3477;
+const xml_token_t XML_xfId = 3478;
+const xml_token_t XML_xfrm = 3479;
+const xml_token_t XML_xfrmType = 3480;
+const xml_token_t XML_xl2000 = 3481;
+const xml_token_t XML_xl97 = 3482;
+const xml_token_t XML_xlm = 3483;
+const xml_token_t XML_xml = 3484;
+const xml_token_t XML_xmlBased = 3485;
+const xml_token_t XML_xmlCellPr = 3486;
+const xml_token_t XML_xmlColumnPr = 3487;
+const xml_token_t XML_xmlDataType = 3488;
+const xml_token_t XML_xmlPr = 3489;
+const xml_token_t XML_xpath = 3490;
+const xml_token_t XML_xrange = 3491;
+const xml_token_t XML_xscale = 3492;
+const xml_token_t XML_y = 3493;
+const xml_token_t XML_yAlign = 3494;
+const xml_token_t XML_yMode = 3495;
+const xml_token_t XML_ySplit = 3496;
+const xml_token_t XML_yVal = 3497;
+const xml_token_t XML_yWindow = 3498;
+const xml_token_t XML_year = 3499;
+const xml_token_t XML_yearLong = 3500;
+const xml_token_t XML_yearShort = 3501;
+const xml_token_t XML_yrange = 3502;
+const xml_token_t XML_z = 3503;
+const xml_token_t XML_zOrder = 3504;
+const xml_token_t XML_zOrderOff = 3505;
+const xml_token_t XML_zeroAsc = 3506;
+const xml_token_t XML_zeroDesc = 3507;
+const xml_token_t XML_zeroHeight = 3508;
+const xml_token_t XML_zeroValues = 3509;
+const xml_token_t XML_zeroWid = 3510;
+const xml_token_t XML_zoom = 3511;
+const xml_token_t XML_zoomContents = 3512;
+const xml_token_t XML_zoomScale = 3513;
+const xml_token_t XML_zoomScaleNormal = 3514;
+const xml_token_t XML_zoomScalePageLayoutView = 3515;
+const xml_token_t XML_zoomScaleSheetLayoutView = 3516;
+const xml_token_t XML_zoomToFit = 3517;
diff --git a/src/liborcus/ooxml_tokens.cpp b/src/liborcus/ooxml_tokens.cpp
new file mode 100644
index 0000000..f73a06c
--- /dev/null
+++ b/src/liborcus/ooxml_tokens.cpp
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_tokens.hpp"
+
+namespace orcus {
+
+namespace ooxml {
+
+#include "ooxml_tokens.inl"
+
+}
+
+namespace opc {
+
+#include "opc_tokens.inl"
+
+}
+
+tokens ooxml_tokens = tokens(ooxml::token_names, ooxml::token_name_count);
+
+tokens opc_tokens = tokens(opc::token_names, opc::token_name_count);
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_tokens.hpp b/src/liborcus/ooxml_tokens.hpp
new file mode 100644
index 0000000..3e8380b
--- /dev/null
+++ b/src/liborcus/ooxml_tokens.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_OOXML_TOKENS_HPP__
+#define __ORCUS_OOXML_TOKENS_HPP__
+
+#include "orcus/tokens.hpp"
+
+namespace orcus {
+
+extern tokens ooxml_tokens;
+extern tokens opc_tokens;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_tokens.inl b/src/liborcus/ooxml_tokens.inl
new file mode 100644
index 0000000..5fa2ad0
--- /dev/null
+++ b/src/liborcus/ooxml_tokens.inl
@@ -0,0 +1,3524 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const char* token_names[] = {
+ "??", // 0
+ "AbbreviatedCaseNumber", // 1
+ "Accel", // 2
+ "Accel2", // 3
+ "AlbumTitle", // 4
+ "AlternateContent", // 5
+ "Anchor", // 6
+ "AppVersion", // 7
+ "Append", // 8
+ "Application", // 9
+ "Artist", // 10
+ "Author", // 11
+ "AutoFill", // 12
+ "AutoFit", // 13
+ "AutoLine", // 14
+ "AutoPict", // 15
+ "AutoScale", // 16
+ "BookAuthor", // 17
+ "BookTitle", // 18
+ "BroadcastTitle", // 19
+ "Broadcaster", // 20
+ "CF", // 21
+ "Camera", // 22
+ "Cancel", // 23
+ "CaseNumber", // 24
+ "ChapterNumber", // 25
+ "Characters", // 26
+ "CharactersWithSpaces", // 27
+ "Checked", // 28
+ "Choice", // 29
+ "City", // 30
+ "ClientData", // 31
+ "ColHidden", // 32
+ "Colored", // 33
+ "Column", // 34
+ "Comments", // 35
+ "Company", // 36
+ "Compiler", // 37
+ "Composer", // 38
+ "Conductor", // 39
+ "ConferenceName", // 40
+ "ConnectionID", // 41
+ "Corporate", // 42
+ "Counsel", // 43
+ "CountryRegion", // 44
+ "Court", // 45
+ "DDE", // 46
+ "DataBinding", // 47
+ "DataBindingLoadMode", // 48
+ "DataBindingName", // 49
+ "Day", // 50
+ "DayAccessed", // 51
+ "Default", // 52
+ "DefaultSize", // 53
+ "Department", // 54
+ "DigSig", // 55
+ "Director", // 56
+ "Disabled", // 57
+ "Dismiss", // 58
+ "Distributor", // 59
+ "DocSecurity", // 60
+ "DrawAspect", // 61
+ "DropLines", // 62
+ "DropStyle", // 63
+ "Dx", // 64
+ "Edition", // 65
+ "Editor", // 66
+ "Fallback", // 67
+ "FieldCodes", // 68
+ "FileBinding", // 69
+ "FileBindingName", // 70
+ "First", // 71
+ "FirstButton", // 72
+ "FmlaGroup", // 73
+ "FmlaLink", // 74
+ "FmlaMacro", // 75
+ "FmlaPict", // 76
+ "FmlaRange", // 77
+ "FmlaTxbx", // 78
+ "Guid", // 79
+ "HLinks", // 80
+ "HeadingPairs", // 81
+ "Help", // 82
+ "HiddenSlides", // 83
+ "Horiz", // 84
+ "HyperlinkBase", // 85
+ "HyperlinksChanged", // 86
+ "ID", // 87
+ "Inc", // 88
+ "Institution", // 89
+ "InternetSiteTitle", // 90
+ "Interviewee", // 91
+ "Interviewer", // 92
+ "Inventor", // 93
+ "Issue", // 94
+ "JournalName", // 95
+ "JustLastX", // 96
+ "LCID", // 97
+ "LCT", // 98
+ "Last", // 99
+ "Lines", // 100
+ "LinkType", // 101
+ "LinksUpToDate", // 102
+ "ListItem", // 103
+ "LockText", // 104
+ "Locked", // 105
+ "LockedField", // 106
+ "MMClips", // 107
+ "Manager", // 108
+ "Map", // 109
+ "MapInfo", // 110
+ "MapOCX", // 111
+ "Max", // 112
+ "Medium", // 113
+ "Middle", // 114
+ "Min", // 115
+ "Month", // 116
+ "MonthAccessed", // 117
+ "MoveWithCells", // 118
+ "MultiLine", // 119
+ "MultiSel", // 120
+ "Name", // 121
+ "NameList", // 122
+ "Namespace", // 123
+ "NoThreeD", // 124
+ "NoThreeD2", // 125
+ "Notes", // 126
+ "NumberVolumes", // 127
+ "OLEObject", // 128
+ "ObjectID", // 129
+ "ObjectType", // 130
+ "Page", // 131
+ "Pages", // 132
+ "Paragraphs", // 133
+ "PatentNumber", // 134
+ "Performer", // 135
+ "PeriodicalTitle", // 136
+ "Person", // 137
+ "PresentationFormat", // 138
+ "PreserveFormat", // 139
+ "PreserveSortAFLayout", // 140
+ "PrintObject", // 141
+ "ProducerName", // 142
+ "ProductionCompany", // 143
+ "ProgID", // 144
+ "Properties", // 145
+ "PublicationTitle", // 146
+ "Publisher", // 147
+ "RecalcAlways", // 148
+ "RecordingNumber", // 149
+ "RefOrder", // 150
+ "Reporter", // 151
+ "RootElement", // 152
+ "Row", // 153
+ "RowHidden", // 154
+ "ScaleCrop", // 155
+ "Schema", // 156
+ "SchemaID", // 157
+ "SchemaRef", // 158
+ "ScriptExtended", // 159
+ "ScriptLanguage", // 160
+ "ScriptLocation", // 161
+ "ScriptText", // 162
+ "SecretEdit", // 163
+ "Sel", // 164
+ "SelType", // 165
+ "SelectedStyle", // 166
+ "SelectionNamespaces", // 167
+ "ShapeID", // 168
+ "SharedDoc", // 169
+ "ShortTitle", // 170
+ "ShowImportExportValidationErrors", // 171
+ "SizeWithCells", // 172
+ "Slides", // 173
+ "Source", // 174
+ "SourceType", // 175
+ "Sources", // 176
+ "StandardNumber", // 177
+ "StateProvince", // 178
+ "Station", // 179
+ "StyleName", // 180
+ "Tag", // 181
+ "Template", // 182
+ "TextHAlign", // 183
+ "TextVAlign", // 184
+ "Theater", // 185
+ "ThesisType", // 186
+ "Title", // 187
+ "TitlesOfParts", // 188
+ "TotalTime", // 189
+ "Translator", // 190
+ "Type", // 191
+ "UIObj", // 192
+ "URI", // 193
+ "URL", // 194
+ "UpdateMode", // 195
+ "VScroll", // 196
+ "VTEdit", // 197
+ "Val", // 198
+ "ValidIds", // 199
+ "Version", // 200
+ "Visible", // 201
+ "Volume", // 202
+ "WidthMin", // 203
+ "Words", // 204
+ "Writer", // 205
+ "Year", // 206
+ "YearAccessed", // 207
+ "a", // 208
+ "aboveAverage", // 209
+ "absSizeAnchor", // 210
+ "absoluteAnchor", // 211
+ "abstractNum", // 212
+ "abstractNumId", // 213
+ "aca", // 214
+ "acc", // 215
+ "accPr", // 216
+ "accel", // 217
+ "accent1", // 218
+ "accent2", // 219
+ "accent3", // 220
+ "accent4", // 221
+ "accent5", // 222
+ "accent6", // 223
+ "accentbar", // 224
+ "accumulate", // 225
+ "action", // 226
+ "active", // 227
+ "activeCell", // 228
+ "activeCellId", // 229
+ "activeCol", // 230
+ "activePane", // 231
+ "activeRecord", // 232
+ "activeRow", // 233
+ "activeSheetId", // 234
+ "activeTab", // 235
+ "activeWritingStyle", // 236
+ "actualPg", // 237
+ "additionalCharacteristics", // 238
+ "additive", // 239
+ "addlxml", // 240
+ "addressFieldName", // 241
+ "adj", // 242
+ "adjLst", // 243
+ "adjust", // 244
+ "adjustColumnWidth", // 245
+ "adjustLineHeightInTable", // 246
+ "adjustRightInd", // 247
+ "adjusthandles", // 248
+ "advAuto", // 249
+ "advClick", // 250
+ "advTm", // 251
+ "advise", // 252
+ "after", // 253
+ "afterAutospacing", // 254
+ "afterEffect", // 255
+ "afterLines", // 256
+ "ahLst", // 257
+ "ahPolar", // 258
+ "ahXY", // 259
+ "alg", // 260
+ "algIdExt", // 261
+ "algIdExtSource", // 262
+ "algn", // 263
+ "alias", // 264
+ "aliases", // 265
+ "align", // 266
+ "alignBordersAndEdges", // 267
+ "alignTablesRowByRow", // 268
+ "alignWithMargins", // 269
+ "alignment", // 270
+ "alignshape", // 271
+ "all", // 272
+ "allCaption", // 273
+ "allDrilled", // 274
+ "allUniqueName", // 275
+ "allowBlank", // 276
+ "allowOverlap", // 277
+ "allowPNG", // 278
+ "allowPng", // 279
+ "allowRefreshQuery", // 280
+ "allowSpaceOfSameStyleInTable", // 281
+ "allowcomments", // 282
+ "allowincell", // 283
+ "allowoverlap", // 284
+ "aln", // 285
+ "alnAt", // 286
+ "alnScr", // 287
+ "alpha", // 288
+ "alphaBiLevel", // 289
+ "alphaCeiling", // 290
+ "alphaFloor", // 291
+ "alphaInv", // 292
+ "alphaMod", // 293
+ "alphaModFix", // 294
+ "alphaOff", // 295
+ "alphaOutset", // 296
+ "alphaRepl", // 297
+ "alt", // 298
+ "altChunk", // 299
+ "altChunkPr", // 300
+ "altLang", // 301
+ "altName", // 302
+ "althref", // 303
+ "alwaysMergeEmptyNamespace", // 304
+ "alwaysShow", // 305
+ "alwaysShowPlaceholderText", // 306
+ "amt", // 307
+ "anchor", // 308
+ "anchorCtr", // 309
+ "anchorLock", // 310
+ "anchorlock", // 311
+ "anchorx", // 312
+ "anchory", // 313
+ "and", // 314
+ "ang", // 315
+ "angle", // 316
+ "anim", // 317
+ "animBg", // 318
+ "animClr", // 319
+ "animEffect", // 320
+ "animLvl", // 321
+ "animMotion", // 322
+ "animOne", // 323
+ "animRot", // 324
+ "animScale", // 325
+ "annotation", // 326
+ "annotationRef", // 327
+ "appName", // 328
+ "applyAlignment", // 329
+ "applyAlignmentFormats", // 330
+ "applyBorder", // 331
+ "applyBorderFormats", // 332
+ "applyBreakingRules", // 333
+ "applyFill", // 334
+ "applyFont", // 335
+ "applyFontFormats", // 336
+ "applyNumberFormat", // 337
+ "applyNumberFormats", // 338
+ "applyPatternFormats", // 339
+ "applyProtection", // 340
+ "applyStyles", // 341
+ "applyToEnd", // 342
+ "applyToFront", // 343
+ "applyToSides", // 344
+ "applyWidthHeightFormats", // 345
+ "arc", // 346
+ "arcTo", // 347
+ "arcsize", // 348
+ "area3DChart", // 349
+ "areaChart", // 350
+ "arg", // 351
+ "argPr", // 352
+ "argSz", // 353
+ "array", // 354
+ "arrowok", // 355
+ "ascii", // 356
+ "asciiTheme", // 357
+ "aspect", // 358
+ "aspectratio", // 359
+ "assign", // 360
+ "asteriskTotals", // 361
+ "attachedSchema", // 362
+ "attachedTemplate", // 363
+ "attr", // 364
+ "attrName", // 365
+ "attrNameLst", // 366
+ "attribute", // 367
+ "audio", // 368
+ "audioCd", // 369
+ "audioFile", // 370
+ "author", // 371
+ "authorId", // 372
+ "authors", // 373
+ "auto", // 374
+ "autoAdjust", // 375
+ "autoCaption", // 376
+ "autoCaptions", // 377
+ "autoCompressPictures", // 378
+ "autoEnd", // 379
+ "autoFilter", // 380
+ "autoFilterDateGrouping", // 381
+ "autoFormatId", // 382
+ "autoFormatOverride", // 383
+ "autoHyphenation", // 384
+ "autoLoad", // 385
+ "autoPage", // 386
+ "autoPageBreaks", // 387
+ "autoRecover", // 388
+ "autoRedefine", // 389
+ "autoRepublish", // 390
+ "autoRev", // 391
+ "autoShow", // 392
+ "autoSortScope", // 393
+ "autoSpaceDE", // 394
+ "autoSpaceDN", // 395
+ "autoSpaceLikeWord95", // 396
+ "autoStart", // 397
+ "autoTitleDeleted", // 398
+ "autoUpdate", // 399
+ "autoUpdateAnimBg", // 400
+ "autofitToFirstFixedWidthCell", // 401
+ "autoformat", // 402
+ "autolayout", // 403
+ "autorotationcenter", // 404
+ "avLst", // 405
+ "avgSubtotal", // 406
+ "axId", // 407
+ "axPos", // 408
+ "axis", // 409
+ "b", // 410
+ "bCs", // 411
+ "bIns", // 412
+ "backWall", // 413
+ "backdepth", // 414
+ "backdrop", // 415
+ "background", // 416
+ "backgroundQuery", // 417
+ "backgroundRefresh", // 418
+ "backupFile", // 419
+ "backward", // 420
+ "backwards", // 421
+ "balanceSingleByteDoubleByteWidth", // 422
+ "band1H", // 423
+ "band1V", // 424
+ "band2H", // 425
+ "band2V", // 426
+ "bandCol", // 427
+ "bandFmt", // 428
+ "bandFmts", // 429
+ "bandRow", // 430
+ "bar", // 431
+ "bar3DChart", // 432
+ "barChart", // 433
+ "barDir", // 434
+ "barPr", // 435
+ "base", // 436
+ "baseColWidth", // 437
+ "baseField", // 438
+ "baseItem", // 439
+ "baseJc", // 440
+ "baseTimeUnit", // 441
+ "baseType", // 442
+ "basedOn", // 443
+ "baseline", // 444
+ "bc", // 445
+ "bdr", // 446
+ "before", // 447
+ "beforeAutospacing", // 448
+ "beforeLines", // 449
+ "begChr", // 450
+ "behavior", // 451
+ "behaviors", // 452
+ "behindDoc", // 453
+ "bestFit", // 454
+ "between", // 455
+ "bevel", // 456
+ "bevelB", // 457
+ "bevelT", // 458
+ "bg", // 459
+ "bg1", // 460
+ "bg2", // 461
+ "bgClr", // 462
+ "bgColor", // 463
+ "bgFillStyleLst", // 464
+ "bgPr", // 465
+ "bgRef", // 466
+ "biLevel", // 467
+ "bibliography", // 468
+ "bidi", // 469
+ "bidiVisual", // 470
+ "bilevel", // 471
+ "bk", // 472
+ "blackAndWhite", // 473
+ "blacklevel", // 474
+ "blank", // 475
+ "bld", // 476
+ "bldAsOne", // 477
+ "bldChart", // 478
+ "bldDgm", // 479
+ "bldGraphic", // 480
+ "bldLst", // 481
+ "bldLvl", // 482
+ "bldOleChart", // 483
+ "bldP", // 484
+ "bldStep", // 485
+ "bldSub", // 486
+ "blend", // 487
+ "blinds", // 488
+ "blip", // 489
+ "blipFill", // 490
+ "blipPhldr", // 491
+ "blob", // 492
+ "blockQuote", // 493
+ "blue", // 494
+ "blueMod", // 495
+ "blueOff", // 496
+ "blur", // 497
+ "blurRad", // 498
+ "bmk", // 499
+ "body", // 500
+ "bodyDiv", // 501
+ "bodyPr", // 502
+ "bodyStyle", // 503
+ "bold", // 504
+ "boldItalic", // 505
+ "bookFoldPrinting", // 506
+ "bookFoldPrintingSheets", // 507
+ "bookFoldRevPrinting", // 508
+ "bookViews", // 509
+ "bookmarkEnd", // 510
+ "bookmarkIdSeed", // 511
+ "bookmarkStart", // 512
+ "bool", // 513
+ "boolVal", // 514
+ "boolean", // 515
+ "border", // 516
+ "borderBox", // 517
+ "borderBoxPr", // 518
+ "borderId", // 519
+ "borderbottom", // 520
+ "borderbottomcolor", // 521
+ "borderleft", // 522
+ "borderleftcolor", // 523
+ "borderright", // 524
+ "borderrightcolor", // 525
+ "borders", // 526
+ "bordersDoNotSurroundFooter", // 527
+ "bordersDoNotSurroundHeader", // 528
+ "bordertop", // 529
+ "bordertopcolor", // 530
+ "bottom", // 531
+ "bottomFromText", // 532
+ "box", // 533
+ "boxPr", // 534
+ "br", // 535
+ "bright", // 536
+ "brightness", // 537
+ "brk", // 538
+ "brkBin", // 539
+ "brkBinSub", // 540
+ "browse", // 541
+ "bstr", // 542
+ "buAutoNum", // 543
+ "buBlip", // 544
+ "buChar", // 545
+ "buClr", // 546
+ "buClrTx", // 547
+ "buFont", // 548
+ "buFontTx", // 549
+ "buNone", // 550
+ "buSzPct", // 551
+ "buSzPts", // 552
+ "buSzTx", // 553
+ "bubble3D", // 554
+ "bubbleChart", // 555
+ "bubbleScale", // 556
+ "bubbleSize", // 557
+ "build", // 558
+ "builtIn", // 559
+ "builtInGroupCount", // 560
+ "builtInUnit", // 561
+ "builtinId", // 562
+ "bullet", // 563
+ "bulletEnabled", // 564
+ "button", // 565
+ "bw", // 566
+ "bwMode", // 567
+ "bwmode", // 568
+ "bwnormal", // 569
+ "bwpure", // 570
+ "bx", // 571
+ "by", // 572
+ "byPosition", // 573
+ "c", // 574
+ "cBhvr", // 575
+ "cGp", // 576
+ "cGpRule", // 577
+ "cMediaNode", // 578
+ "cNvCxnSpPr", // 579
+ "cNvGraphicFramePr", // 580
+ "cNvGrpSpPr", // 581
+ "cNvPicPr", // 582
+ "cNvPr", // 583
+ "cNvSpPr", // 584
+ "cSld", // 585
+ "cSldViewPr", // 586
+ "cSp", // 587
+ "cTn", // 588
+ "cViewPr", // 589
+ "ca", // 590
+ "cacheField", // 591
+ "cacheFields", // 592
+ "cacheHierarchies", // 593
+ "cacheHierarchy", // 594
+ "cacheId", // 595
+ "cacheIndex", // 596
+ "cacheSource", // 597
+ "cachedColBalance", // 598
+ "calcChain", // 599
+ "calcCompleted", // 600
+ "calcId", // 601
+ "calcMode", // 602
+ "calcOnExit", // 603
+ "calcOnSave", // 604
+ "calcPr", // 605
+ "calcmode", // 606
+ "calculatedColumn", // 607
+ "calculatedColumnFormula", // 608
+ "calculatedItem", // 609
+ "calculatedItems", // 610
+ "calculatedMember", // 611
+ "calculatedMembers", // 612
+ "calendar", // 613
+ "calendarType", // 614
+ "callout", // 615
+ "camera", // 616
+ "cantSplit", // 617
+ "cap", // 618
+ "caps", // 619
+ "caption", // 620
+ "captions", // 621
+ "caseSensitive", // 622
+ "cat", // 623
+ "catAx", // 624
+ "catLst", // 625
+ "category", // 626
+ "categoryIdx", // 627
+ "cell", // 628
+ "cell3D", // 629
+ "cellColor", // 630
+ "cellComments", // 631
+ "cellDel", // 632
+ "cellIns", // 633
+ "cellMerge", // 634
+ "cellMeta", // 635
+ "cellMetadata", // 636
+ "cellSmartTag", // 637
+ "cellSmartTagPr", // 638
+ "cellSmartTags", // 639
+ "cellStyle", // 640
+ "cellStyleXfs", // 641
+ "cellStyles", // 642
+ "cellWatch", // 643
+ "cellWatches", // 644
+ "cellXfs", // 645
+ "cf", // 646
+ "cfRule", // 647
+ "cfvo", // 648
+ "chExt", // 649
+ "chMax", // 650
+ "chOff", // 651
+ "chOrder", // 652
+ "chPref", // 653
+ "changesSavedWin", // 654
+ "chapNum", // 655
+ "chapSep", // 656
+ "chapStyle", // 657
+ "char", // 658
+ "charRg", // 659
+ "charSpace", // 660
+ "characterSpacingControl", // 661
+ "characteristic", // 662
+ "charset", // 663
+ "chart", // 664
+ "chartFormat", // 665
+ "chartFormats", // 666
+ "chartObject", // 667
+ "chartSpace", // 668
+ "chartsheet", // 669
+ "checkBox", // 670
+ "checkCompatibility", // 671
+ "checkErrors", // 672
+ "checkStyle", // 673
+ "checked", // 674
+ "checker", // 675
+ "childTnLst", // 676
+ "choose", // 677
+ "chr", // 678
+ "chromakey", // 679
+ "circle", // 680
+ "citation", // 681
+ "class", // 682
+ "clear", // 683
+ "clearAll", // 684
+ "clearComments", // 685
+ "clearContents", // 686
+ "clearFormats", // 687
+ "click", // 688
+ "clickAndTypeStyle", // 689
+ "clientData", // 690
+ "clientInsertedTime", // 691
+ "clip", // 692
+ "clippath", // 693
+ "clipped", // 694
+ "cliptowrap", // 695
+ "close", // 696
+ "clr", // 697
+ "clrChange", // 698
+ "clrData", // 699
+ "clrFrom", // 700
+ "clrIdx", // 701
+ "clrMap", // 702
+ "clrMapOvr", // 703
+ "clrMode", // 704
+ "clrMru", // 705
+ "clrRepl", // 706
+ "clrScheme", // 707
+ "clrSchemeMapping", // 708
+ "clrSpc", // 709
+ "clrTo", // 710
+ "clrVal", // 711
+ "clsid", // 712
+ "cm", // 713
+ "cmAuthor", // 714
+ "cmAuthorLst", // 715
+ "cmLst", // 716
+ "cmd", // 717
+ "cmpd", // 718
+ "cnfStyle", // 719
+ "cnt", // 720
+ "code", // 721
+ "codeName", // 722
+ "codePage", // 723
+ "coerce", // 724
+ "coherent3DOff", // 725
+ "col", // 726
+ "colBreaks", // 727
+ "colDelim", // 728
+ "colFields", // 729
+ "colFirst", // 730
+ "colGrandTotals", // 731
+ "colHeaderCaption", // 732
+ "colHierarchiesUsage", // 733
+ "colHierarchyUsage", // 734
+ "colId", // 735
+ "colItems", // 736
+ "colLast", // 737
+ "colOff", // 738
+ "colPageCount", // 739
+ "collapse", // 740
+ "collapsed", // 741
+ "collapsedLevelsAreSubtotals", // 742
+ "color", // 743
+ "color2", // 744
+ "colorFilter", // 745
+ "colorId", // 746
+ "colorScale", // 747
+ "colormenu", // 748
+ "colormode", // 749
+ "colormru", // 750
+ "colors", // 751
+ "colorsDef", // 752
+ "colorsDefHdr", // 753
+ "colorsDefHdrLst", // 754
+ "cols", // 755
+ "column", // 756
+ "columnSort", // 757
+ "comb", // 758
+ "combine", // 759
+ "combineBrackets", // 760
+ "comboBox", // 761
+ "comma", // 762
+ "command", // 763
+ "commandType", // 764
+ "comment", // 765
+ "commentList", // 766
+ "commentRangeEnd", // 767
+ "commentRangeStart", // 768
+ "commentReference", // 769
+ "comments", // 770
+ "comp", // 771
+ "compact", // 772
+ "compactData", // 773
+ "compat", // 774
+ "compatLnSpc", // 775
+ "compatMode", // 776
+ "complex", // 777
+ "concurrent", // 778
+ "concurrentCalc", // 779
+ "concurrentManualCount", // 780
+ "cond", // 781
+ "condense", // 782
+ "conditionalFormat", // 783
+ "conditionalFormats", // 784
+ "conditionalFormatting", // 785
+ "connectString", // 786
+ "connectangles", // 787
+ "connection", // 788
+ "connectionId", // 789
+ "connections", // 790
+ "connectloc", // 791
+ "connectlocs", // 792
+ "connectortype", // 793
+ "connecttype", // 794
+ "consecutive", // 795
+ "consecutiveHyphenLimit", // 796
+ "consolidation", // 797
+ "constr", // 798
+ "constrLst", // 799
+ "constrainbounds", // 800
+ "cont", // 801
+ "containsBlank", // 802
+ "containsDate", // 803
+ "containsInteger", // 804
+ "containsMixedTypes", // 805
+ "containsNonDate", // 806
+ "containsNumber", // 807
+ "containsSemiMixedTypes", // 808
+ "containsString", // 809
+ "content", // 810
+ "contextualSpacing", // 811
+ "continuationSeparator", // 812
+ "contourClr", // 813
+ "contourW", // 814
+ "contrast", // 815
+ "control", // 816
+ "control1", // 817
+ "control2", // 818
+ "controls", // 819
+ "convMailMergeEsc", // 820
+ "coordorigin", // 821
+ "coordsize", // 822
+ "copies", // 823
+ "copy", // 824
+ "count", // 825
+ "countASubtotal", // 826
+ "countBy", // 827
+ "countSubtotal", // 828
+ "cover", // 829
+ "cp", // 830
+ "cr", // 831
+ "crashSave", // 832
+ "createdVersion", // 833
+ "credentials", // 834
+ "cropbottom", // 835
+ "cropleft", // 836
+ "cropping", // 837
+ "cropright", // 838
+ "croptop", // 839
+ "crossAx", // 840
+ "crossBetween", // 841
+ "crosses", // 842
+ "crossesAt", // 843
+ "cryptAlgorithmClass", // 844
+ "cryptAlgorithmSid", // 845
+ "cryptAlgorithmType", // 846
+ "cryptProvider", // 847
+ "cryptProviderType", // 848
+ "cryptProviderTypeExt", // 849
+ "cryptProviderTypeExtSource", // 850
+ "cryptSpinCount", // 851
+ "cs", // 852
+ "csCatId", // 853
+ "csTypeId", // 854
+ "csb0", // 855
+ "csb1", // 856
+ "css", // 857
+ "cstate", // 858
+ "cstheme", // 859
+ "ct", // 860
+ "ctrlPr", // 861
+ "cubicBezTo", // 862
+ "culture", // 863
+ "current", // 864
+ "curve", // 865
+ "custAng", // 866
+ "custClr", // 867
+ "custClrLst", // 868
+ "custDash", // 869
+ "custData", // 870
+ "custDataLst", // 871
+ "custFlipHor", // 872
+ "custFlipVert", // 873
+ "custGeom", // 874
+ "custLinFactNeighborX", // 875
+ "custLinFactNeighborY", // 876
+ "custLinFactX", // 877
+ "custLinFactY", // 878
+ "custRadScaleInc", // 879
+ "custRadScaleRad", // 880
+ "custScaleX", // 881
+ "custScaleY", // 882
+ "custShow", // 883
+ "custShowLst", // 884
+ "custSplit", // 885
+ "custSzX", // 886
+ "custSzY", // 887
+ "custT", // 888
+ "custUnit", // 889
+ "customBuiltin", // 890
+ "customFilter", // 891
+ "customFilters", // 892
+ "customFormat", // 893
+ "customHeight", // 894
+ "customList", // 895
+ "customListSort", // 896
+ "customMarkFollows", // 897
+ "customMenu", // 898
+ "customPr", // 899
+ "customProperties", // 900
+ "customRollUp", // 901
+ "customSheetView", // 902
+ "customSheetViews", // 903
+ "customStyle", // 904
+ "customView", // 905
+ "customWidth", // 906
+ "customWorkbookView", // 907
+ "customWorkbookViews", // 908
+ "customXml", // 909
+ "customXmlDelRangeEnd", // 910
+ "customXmlDelRangeStart", // 911
+ "customXmlInsRangeEnd", // 912
+ "customXmlInsRangeStart", // 913
+ "customXmlMoveFromRangeEnd", // 914
+ "customXmlMoveFromRangeStart", // 915
+ "customXmlMoveToRangeEnd", // 916
+ "customXmlMoveToRangeStart", // 917
+ "customXmlPr", // 918
+ "cut", // 919
+ "cx", // 920
+ "cxn", // 921
+ "cxnId", // 922
+ "cxnLst", // 923
+ "cxnSp", // 924
+ "cxnSpLocks", // 925
+ "cy", // 926
+ "d", // 927
+ "dLbl", // 928
+ "dLblPos", // 929
+ "dLbls", // 930
+ "dPr", // 931
+ "dPt", // 932
+ "dTable", // 933
+ "dashstyle", // 934
+ "data", // 935
+ "dataBar", // 936
+ "dataBinding", // 937
+ "dataBound", // 938
+ "dataCaption", // 939
+ "dataCellStyle", // 940
+ "dataConsolidate", // 941
+ "dataDxfId", // 942
+ "dataExtractLoad", // 943
+ "dataField", // 944
+ "dataFields", // 945
+ "dataModel", // 946
+ "dataOnRows", // 947
+ "dataOnly", // 948
+ "dataPosition", // 949
+ "dataRef", // 950
+ "dataRefs", // 951
+ "dataSource", // 952
+ "dataSourceSort", // 953
+ "dataType", // 954
+ "dataValidation", // 955
+ "dataValidations", // 956
+ "databaseField", // 957
+ "datastoreItem", // 958
+ "date", // 959
+ "date1904", // 960
+ "dateAx", // 961
+ "dateFormat", // 962
+ "dateGroupItem", // 963
+ "dateTime", // 964
+ "dateTimeGrouping", // 965
+ "day", // 966
+ "dayLong", // 967
+ "dayShort", // 968
+ "dbPr", // 969
+ "ddList", // 970
+ "ddeItem", // 971
+ "ddeItems", // 972
+ "ddeLink", // 973
+ "ddeService", // 974
+ "ddeTopic", // 975
+ "decel", // 976
+ "decimal", // 977
+ "decimalSymbol", // 978
+ "decorated", // 979
+ "def", // 980
+ "defJc", // 981
+ "defLockedState", // 982
+ "defPPr", // 983
+ "defQFormat", // 984
+ "defRPr", // 985
+ "defSemiHidden", // 986
+ "defStyle", // 987
+ "defTabSz", // 988
+ "defUIPriority", // 989
+ "defUnhideWhenUsed", // 990
+ "default", // 991
+ "defaultAttributeDrillState", // 992
+ "defaultColWidth", // 993
+ "defaultGridColor", // 994
+ "defaultMemberUniqueName", // 995
+ "defaultPivotStyle", // 996
+ "defaultRowHeight", // 997
+ "defaultSubtotal", // 998
+ "defaultTabStop", // 999
+ "defaultTableStyle", // 1000
+ "defaultTextStyle", // 1001
+ "defaultThemeVersion", // 1002
+ "definedName", // 1003
+ "definedNames", // 1004
+ "deg", // 1005
+ "degHide", // 1006
+ "degree", // 1007
+ "del", // 1008
+ "del1", // 1009
+ "del2", // 1010
+ "delInstrText", // 1011
+ "delText", // 1012
+ "delay", // 1013
+ "delete", // 1014
+ "deleteColumns", // 1015
+ "deleteRows", // 1016
+ "deleted", // 1017
+ "deletedField", // 1018
+ "delimited", // 1019
+ "delimiter", // 1020
+ "den", // 1021
+ "denormalized", // 1022
+ "depthPercent", // 1023
+ "desc", // 1024
+ "descending", // 1025
+ "descr", // 1026
+ "description", // 1027
+ "destId", // 1028
+ "destOrd", // 1029
+ "destination", // 1030
+ "destinationFile", // 1031
+ "detectmouseclick", // 1032
+ "dgm", // 1033
+ "dgmbasetextscale", // 1034
+ "dgmfontsize", // 1035
+ "dgmlayout", // 1036
+ "dgmlayoutmru", // 1037
+ "dgmnodekind", // 1038
+ "dgmscalex", // 1039
+ "dgmscaley", // 1040
+ "dgmstyle", // 1041
+ "diagonal", // 1042
+ "diagonalDown", // 1043
+ "diagonalUp", // 1044
+ "diagram", // 1045
+ "dialogsheet", // 1046
+ "diamond", // 1047
+ "diff", // 1048
+ "differentFirst", // 1049
+ "differentOddEven", // 1050
+ "diffusity", // 1051
+ "dimension", // 1052
+ "dimensionUniqueName", // 1053
+ "dimensions", // 1054
+ "dir", // 1055
+ "dirty", // 1056
+ "disableEdit", // 1057
+ "disableFieldList", // 1058
+ "disablePrompts", // 1059
+ "disableRefresh", // 1060
+ "discretePr", // 1061
+ "diskRevisions", // 1062
+ "dispBlanksAs", // 1063
+ "dispDef", // 1064
+ "dispEq", // 1065
+ "dispRSqr", // 1066
+ "dispUnits", // 1067
+ "dispUnitsLbl", // 1068
+ "displacedByCustomXml", // 1069
+ "display", // 1070
+ "displayBackgroundShape", // 1071
+ "displayFolder", // 1072
+ "displayHangulFixedWidth", // 1073
+ "displayHorizontalDrawingGridEvery", // 1074
+ "displayName", // 1075
+ "displayText", // 1076
+ "displayVerticalDrawingGridEvery", // 1077
+ "dissolve", // 1078
+ "dist", // 1079
+ "distB", // 1080
+ "distL", // 1081
+ "distR", // 1082
+ "distT", // 1083
+ "distance", // 1084
+ "div", // 1085
+ "divBdr", // 1086
+ "divId", // 1087
+ "divs", // 1088
+ "divsChild", // 1089
+ "dk1", // 1090
+ "dk2", // 1091
+ "dllVersion", // 1092
+ "dm", // 1093
+ "dn", // 1094
+ "doNotAutoCompressPictures", // 1095
+ "doNotAutofitConstrainedTables", // 1096
+ "doNotBreakConstrainedForcedTable", // 1097
+ "doNotBreakWrappedTables", // 1098
+ "doNotDemarcateInvalidXml", // 1099
+ "doNotDisplayPageBoundaries", // 1100
+ "doNotEmbedSmartTags", // 1101
+ "doNotExpandShiftReturn", // 1102
+ "doNotHyphenateCaps", // 1103
+ "doNotIncludeSubdocsInStats", // 1104
+ "doNotLeaveBackslashAlone", // 1105
+ "doNotOrganizeInFolder", // 1106
+ "doNotRelyOnCSS", // 1107
+ "doNotSaveAsSingleFile", // 1108
+ "doNotShadeFormData", // 1109
+ "doNotSnapToGridInCell", // 1110
+ "doNotSuppressBlankLines", // 1111
+ "doNotSuppressIndentation", // 1112
+ "doNotSuppressParagraphBorders", // 1113
+ "doNotTrackFormatting", // 1114
+ "doNotTrackMoves", // 1115
+ "doNotUseEastAsianBreakRules", // 1116
+ "doNotUseHTMLParagraphAutoSpacing", // 1117
+ "doNotUseIndentAsNumberingTabStop", // 1118
+ "doNotUseLongFileNames", // 1119
+ "doNotUseMarginsForDrawingGridOrigin", // 1120
+ "doNotValidateAgainstSchema", // 1121
+ "doNotVertAlignCellWithSp", // 1122
+ "doNotVertAlignInTxbx", // 1123
+ "doNotWrapTextWithPunct", // 1124
+ "docDefaults", // 1125
+ "docGrid", // 1126
+ "docLocation", // 1127
+ "docPart", // 1128
+ "docPartBody", // 1129
+ "docPartCategory", // 1130
+ "docPartGallery", // 1131
+ "docPartList", // 1132
+ "docPartObj", // 1133
+ "docPartPr", // 1134
+ "docPartUnique", // 1135
+ "docParts", // 1136
+ "docPr", // 1137
+ "docVar", // 1138
+ "docVars", // 1139
+ "document", // 1140
+ "documentProtection", // 1141
+ "documentType", // 1142
+ "double", // 1143
+ "doubleclicknotify", // 1144
+ "doughnutChart", // 1145
+ "downBars", // 1146
+ "dpi", // 1147
+ "dr", // 1148
+ "draft", // 1149
+ "dragOff", // 1150
+ "dragToCol", // 1151
+ "dragToData", // 1152
+ "dragToPage", // 1153
+ "dragToRow", // 1154
+ "drawing", // 1155
+ "drawingGridHorizontalOrigin", // 1156
+ "drawingGridHorizontalSpacing", // 1157
+ "drawingGridVerticalOrigin", // 1158
+ "drawingGridVerticalSpacing", // 1159
+ "drop", // 1160
+ "dropCap", // 1161
+ "dropDownList", // 1162
+ "dropLines", // 1163
+ "dropauto", // 1164
+ "ds", // 1165
+ "dstrike", // 1166
+ "dt", // 1167
+ "dt2D", // 1168
+ "dtr", // 1169
+ "duotone", // 1170
+ "dur", // 1171
+ "dvAspect", // 1172
+ "dx", // 1173
+ "dxaOrig", // 1174
+ "dxf", // 1175
+ "dxfId", // 1176
+ "dxfs", // 1177
+ "dy", // 1178
+ "dyaOrig", // 1179
+ "dynamicAddress", // 1180
+ "dynamicFilter", // 1181
+ "dz", // 1182
+ "e", // 1183
+ "ea", // 1184
+ "eaLnBrk", // 1185
+ "eastAsia", // 1186
+ "eastAsiaTheme", // 1187
+ "eastAsianLayout", // 1188
+ "eb", // 1189
+ "ed", // 1190
+ "edGrp", // 1191
+ "edge", // 1192
+ "edit", // 1193
+ "editAs", // 1194
+ "editData", // 1195
+ "editPage", // 1196
+ "editas", // 1197
+ "edited", // 1198
+ "effect", // 1199
+ "effectClrLst", // 1200
+ "effectDag", // 1201
+ "effectExtent", // 1202
+ "effectLst", // 1203
+ "effectRef", // 1204
+ "effectStyle", // 1205
+ "effectStyleLst", // 1206
+ "element", // 1207
+ "else", // 1208
+ "em", // 1209
+ "embed", // 1210
+ "embedBold", // 1211
+ "embedBoldItalic", // 1212
+ "embedItalic", // 1213
+ "embedRegular", // 1214
+ "embedSystemFonts", // 1215
+ "embedTrueTypeFonts", // 1216
+ "embeddedFont", // 1217
+ "embeddedFontLst", // 1218
+ "emboss", // 1219
+ "embosscolor", // 1220
+ "empty", // 1221
+ "emptyCellReference", // 1222
+ "enableDrill", // 1223
+ "enableFieldProperties", // 1224
+ "enableFormatConditionsCalculation", // 1225
+ "enableRefresh", // 1226
+ "enableWizard", // 1227
+ "enabled", // 1228
+ "encoding", // 1229
+ "end", // 1230
+ "endA", // 1231
+ "endAngle", // 1232
+ "endChr", // 1233
+ "endCondLst", // 1234
+ "endCxn", // 1235
+ "endDate", // 1236
+ "endNum", // 1237
+ "endOfListFormulaUpdate", // 1238
+ "endParaRPr", // 1239
+ "endPos", // 1240
+ "endSnd", // 1241
+ "endSync", // 1242
+ "endarrow", // 1243
+ "endarrowlength", // 1244
+ "endarrowwidth", // 1245
+ "endcap", // 1246
+ "endnote", // 1247
+ "endnotePr", // 1248
+ "endnoteRef", // 1249
+ "endnoteReference", // 1250
+ "endnotes", // 1251
+ "enforcement", // 1252
+ "entries", // 1253
+ "entry", // 1254
+ "entryMacro", // 1255
+ "eol", // 1256
+ "eqArr", // 1257
+ "eqArrPr", // 1258
+ "eqn", // 1259
+ "equalAverage", // 1260
+ "equalWidth", // 1261
+ "equation", // 1262
+ "equationxml", // 1263
+ "err", // 1264
+ "errBarType", // 1265
+ "errBars", // 1266
+ "errDir", // 1267
+ "errValType", // 1268
+ "error", // 1269
+ "errorCaption", // 1270
+ "errorStyle", // 1271
+ "errorTitle", // 1272
+ "errors", // 1273
+ "evalError", // 1274
+ "evalOrder", // 1275
+ "evenAndOddHeaders", // 1276
+ "evenFooter", // 1277
+ "evenHeader", // 1278
+ "evt", // 1279
+ "evtFilter", // 1280
+ "excl", // 1281
+ "exclusive", // 1282
+ "exitMacro", // 1283
+ "exp", // 1284
+ "explosion", // 1285
+ "ext", // 1286
+ "extLst", // 1287
+ "extend", // 1288
+ "extendable", // 1289
+ "extent", // 1290
+ "externalBook", // 1291
+ "externalData", // 1292
+ "externalLink", // 1293
+ "externalReference", // 1294
+ "externalReferences", // 1295
+ "extraClrScheme", // 1296
+ "extraClrSchemeLst", // 1297
+ "extrusion", // 1298
+ "extrusionClr", // 1299
+ "extrusionH", // 1300
+ "extrusionOk", // 1301
+ "extrusioncolor", // 1302
+ "extrusionok", // 1303
+ "f", // 1304
+ "fHdr", // 1305
+ "fLocksText", // 1306
+ "fLocksWithSheet", // 1307
+ "fName", // 1308
+ "fPr", // 1309
+ "fPrintsWithSheet", // 1310
+ "fPublished", // 1311
+ "facet", // 1312
+ "fact", // 1313
+ "fade", // 1314
+ "fadeDir", // 1315
+ "family", // 1316
+ "fc", // 1317
+ "ffData", // 1318
+ "fgClr", // 1319
+ "fgColor", // 1320
+ "fi", // 1321
+ "field", // 1322
+ "fieldGroup", // 1323
+ "fieldId", // 1324
+ "fieldIdWrapped", // 1325
+ "fieldListSortAscending", // 1326
+ "fieldMapData", // 1327
+ "fieldPosition", // 1328
+ "fieldPrintTitles", // 1329
+ "fieldUsage", // 1330
+ "fieldsUsage", // 1331
+ "fileRecoveryPr", // 1332
+ "fileSharing", // 1333
+ "fileType", // 1334
+ "fileVersion", // 1335
+ "filetime", // 1336
+ "fill", // 1337
+ "fillClrLst", // 1338
+ "fillFormulas", // 1339
+ "fillId", // 1340
+ "fillOverlay", // 1341
+ "fillRect", // 1342
+ "fillRef", // 1343
+ "fillStyleLst", // 1344
+ "fillToRect", // 1345
+ "fillcolor", // 1346
+ "filled", // 1347
+ "fillok", // 1348
+ "fills", // 1349
+ "filltype", // 1350
+ "filter", // 1351
+ "filterColumn", // 1352
+ "filterMode", // 1353
+ "filterPrivacy", // 1354
+ "filterUnique", // 1355
+ "filterVal", // 1356
+ "filters", // 1357
+ "first", // 1358
+ "firstBackgroundRefresh", // 1359
+ "firstCol", // 1360
+ "firstDataCol", // 1361
+ "firstDataRow", // 1362
+ "firstFooter", // 1363
+ "firstHeader", // 1364
+ "firstHeaderRow", // 1365
+ "firstLine", // 1366
+ "firstLineChars", // 1367
+ "firstPageNumber", // 1368
+ "firstRow", // 1369
+ "firstSheet", // 1370
+ "firstSliceAng", // 1371
+ "firstSlideNum", // 1372
+ "fitText", // 1373
+ "fitToHeight", // 1374
+ "fitToPage", // 1375
+ "fitToWidth", // 1376
+ "fitpath", // 1377
+ "fitshape", // 1378
+ "flatBorders", // 1379
+ "flatTx", // 1380
+ "fld", // 1381
+ "fldChar", // 1382
+ "fldCharType", // 1383
+ "fldData", // 1384
+ "fldLock", // 1385
+ "fldSimple", // 1386
+ "flip", // 1387
+ "flipH", // 1388
+ "flipV", // 1389
+ "floor", // 1390
+ "fltVal", // 1391
+ "fmla", // 1392
+ "fmt", // 1393
+ "fmtId", // 1394
+ "fmtScheme", // 1395
+ "fmtid", // 1396
+ "focus", // 1397
+ "focusposition", // 1398
+ "focussize", // 1399
+ "folHlink", // 1400
+ "followColorScheme", // 1401
+ "followedHyperlink", // 1402
+ "font", // 1403
+ "fontAlgn", // 1404
+ "fontId", // 1405
+ "fontKey", // 1406
+ "fontRef", // 1407
+ "fontScale", // 1408
+ "fontScheme", // 1409
+ "fontSz", // 1410
+ "fonts", // 1411
+ "footer", // 1412
+ "footerReference", // 1413
+ "footnote", // 1414
+ "footnoteLayoutLikeWW8", // 1415
+ "footnotePr", // 1416
+ "footnoteRef", // 1417
+ "footnoteReference", // 1418
+ "footnotes", // 1419
+ "for", // 1420
+ "forEach", // 1421
+ "forName", // 1422
+ "forceAA", // 1423
+ "forceFullCalc", // 1424
+ "forceUpgrade", // 1425
+ "forcedash", // 1426
+ "foredepth", // 1427
+ "forgetLastTabAlignment", // 1428
+ "formProt", // 1429
+ "format", // 1430
+ "formatCells", // 1431
+ "formatCode", // 1432
+ "formatColumns", // 1433
+ "formatRows", // 1434
+ "formats", // 1435
+ "formatting", // 1436
+ "formsDesign", // 1437
+ "formula", // 1438
+ "formula1", // 1439
+ "formula2", // 1440
+ "formulaRange", // 1441
+ "formulas", // 1442
+ "forward", // 1443
+ "fov", // 1444
+ "frame", // 1445
+ "frameLayout", // 1446
+ "framePr", // 1447
+ "frameSlides", // 1448
+ "frameset", // 1449
+ "framesetSplitbar", // 1450
+ "from", // 1451
+ "fromWordArt", // 1452
+ "ftr", // 1453
+ "fullCalcOnLoad", // 1454
+ "fullDate", // 1455
+ "fullPrecision", // 1456
+ "fullScrn", // 1457
+ "func", // 1458
+ "funcPr", // 1459
+ "function", // 1460
+ "functionGroup", // 1461
+ "functionGroupId", // 1462
+ "functionGroups", // 1463
+ "futureMetadata", // 1464
+ "g", // 1465
+ "gain", // 1466
+ "gallery", // 1467
+ "gamma", // 1468
+ "gap", // 1469
+ "gapDepth", // 1470
+ "gapWidth", // 1471
+ "gd", // 1472
+ "gdLst", // 1473
+ "gdRefAng", // 1474
+ "gdRefR", // 1475
+ "gdRefX", // 1476
+ "gdRefY", // 1477
+ "gfxdata", // 1478
+ "ghostCol", // 1479
+ "ghostRow", // 1480
+ "glossaryDocument", // 1481
+ "glow", // 1482
+ "goal", // 1483
+ "gradFill", // 1484
+ "gradientFill", // 1485
+ "gradientshapeok", // 1486
+ "grammar", // 1487
+ "grandCol", // 1488
+ "grandRow", // 1489
+ "grandTotalCaption", // 1490
+ "graphic", // 1491
+ "graphicData", // 1492
+ "graphicEl", // 1493
+ "graphicFrame", // 1494
+ "graphicFrameLocks", // 1495
+ "gray", // 1496
+ "grayscale", // 1497
+ "grayscl", // 1498
+ "green", // 1499
+ "greenMod", // 1500
+ "greenOff", // 1501
+ "gridAfter", // 1502
+ "gridBefore", // 1503
+ "gridCol", // 1504
+ "gridDropZones", // 1505
+ "gridLines", // 1506
+ "gridLinesSet", // 1507
+ "gridSpacing", // 1508
+ "gridSpan", // 1509
+ "group", // 1510
+ "groupBy", // 1511
+ "groupChr", // 1512
+ "groupChrPr", // 1513
+ "groupInterval", // 1514
+ "groupItems", // 1515
+ "groupLevel", // 1516
+ "groupLevels", // 1517
+ "groupMember", // 1518
+ "groupMembers", // 1519
+ "grouping", // 1520
+ "groups", // 1521
+ "grow", // 1522
+ "growAutofit", // 1523
+ "growShrinkType", // 1524
+ "grpFill", // 1525
+ "grpId", // 1526
+ "grpSp", // 1527
+ "grpSpLocks", // 1528
+ "grpSpPr", // 1529
+ "gs", // 1530
+ "gsLst", // 1531
+ "gte", // 1532
+ "guid", // 1533
+ "guide", // 1534
+ "guideLst", // 1535
+ "gutter", // 1536
+ "gutterAtTop", // 1537
+ "h", // 1538
+ "hAnchor", // 1539
+ "hAnsi", // 1540
+ "hAnsiTheme", // 1541
+ "hMerge", // 1542
+ "hMode", // 1543
+ "hPercent", // 1544
+ "hR", // 1545
+ "hRule", // 1546
+ "hSpace", // 1547
+ "handles", // 1548
+ "handoutMaster", // 1549
+ "handoutMasterId", // 1550
+ "handoutMasterIdLst", // 1551
+ "hanging", // 1552
+ "hangingChars", // 1553
+ "hangingPunct", // 1554
+ "hasCustomPrompt", // 1555
+ "hash", // 1556
+ "hashData", // 1557
+ "hdr", // 1558
+ "hdrShapeDefaults", // 1559
+ "headEnd", // 1560
+ "header", // 1561
+ "headerFooter", // 1562
+ "headerReference", // 1563
+ "headerRowBorderDxfId", // 1564
+ "headerRowCellStyle", // 1565
+ "headerRowCount", // 1566
+ "headerRowDxfId", // 1567
+ "headerSource", // 1568
+ "headers", // 1569
+ "headersInLastRefresh", // 1570
+ "heading", // 1571
+ "headings", // 1572
+ "help", // 1573
+ "helpText", // 1574
+ "hf", // 1575
+ "hiLowLines", // 1576
+ "hidden", // 1577
+ "hiddenButton", // 1578
+ "hiddenColumn", // 1579
+ "hiddenColumns", // 1580
+ "hiddenLevel", // 1581
+ "hiddenRow", // 1582
+ "hiddenRows", // 1583
+ "hiddenSlides", // 1584
+ "hideBot", // 1585
+ "hideGeom", // 1586
+ "hideGrammaticalErrors", // 1587
+ "hideLastTrans", // 1588
+ "hideLeft", // 1589
+ "hideMark", // 1590
+ "hideNewItems", // 1591
+ "hidePivotFieldList", // 1592
+ "hideRight", // 1593
+ "hideSpellingErrors", // 1594
+ "hideTop", // 1595
+ "hier", // 1596
+ "hierBranch", // 1597
+ "hierarchy", // 1598
+ "hierarchyUsage", // 1599
+ "highlight", // 1600
+ "highlightClick", // 1601
+ "hint", // 1602
+ "history", // 1603
+ "hlink", // 1604
+ "hlinkClick", // 1605
+ "hlinkHover", // 1606
+ "hlinkMouseOver", // 1607
+ "holeSize", // 1608
+ "horizontal", // 1609
+ "horizontalCentered", // 1610
+ "horizontalDpi", // 1611
+ "horzAnchor", // 1612
+ "horzBarState", // 1613
+ "horzOverflow", // 1614
+ "hour", // 1615
+ "how", // 1616
+ "hps", // 1617
+ "hpsBaseText", // 1618
+ "hpsRaise", // 1619
+ "hr", // 1620
+ "hralign", // 1621
+ "href", // 1622
+ "hrnoshade", // 1623
+ "hrpct", // 1624
+ "hrstd", // 1625
+ "hsl", // 1626
+ "hslClr", // 1627
+ "ht", // 1628
+ "htmlFormat", // 1629
+ "htmlPubPr", // 1630
+ "htmlTables", // 1631
+ "hue", // 1632
+ "hueDir", // 1633
+ "hueMod", // 1634
+ "hueOff", // 1635
+ "hyperlink", // 1636
+ "hyperlinks", // 1637
+ "hyphenationZone", // 1638
+ "i", // 1639
+ "i1", // 1640
+ "i2", // 1641
+ "i3", // 1642
+ "i4", // 1643
+ "i8", // 1644
+ "iCs", // 1645
+ "iLevel", // 1646
+ "iMeasureFld", // 1647
+ "iMeasureHier", // 1648
+ "icon", // 1649
+ "iconFilter", // 1650
+ "iconId", // 1651
+ "iconSet", // 1652
+ "id", // 1653
+ "idcntr", // 1654
+ "iddest", // 1655
+ "idmap", // 1656
+ "idref", // 1657
+ "idsrc", // 1658
+ "idx", // 1659
+ "if", // 1660
+ "ignoreMixedContent", // 1661
+ "ignoredError", // 1662
+ "ignoredErrors", // 1663
+ "ilvl", // 1664
+ "image", // 1665
+ "imagealignshape", // 1666
+ "imageaspect", // 1667
+ "imagedata", // 1668
+ "imagesize", // 1669
+ "imeMode", // 1670
+ "imgH", // 1671
+ "imgSz", // 1672
+ "imgW", // 1673
+ "immersive", // 1674
+ "imprint", // 1675
+ "in", // 1676
+ "includeHiddenRowCol", // 1677
+ "includeNewItemsInFilter", // 1678
+ "includePrintSettings", // 1679
+ "ind", // 1680
+ "indent", // 1681
+ "index", // 1682
+ "indexed", // 1683
+ "indexedColors", // 1684
+ "initials", // 1685
+ "ink", // 1686
+ "inkAnnotations", // 1687
+ "inkTgt", // 1688
+ "inline", // 1689
+ "innerShdw", // 1690
+ "inputCells", // 1691
+ "ins", // 1692
+ "insDel", // 1693
+ "insertBlankRow", // 1694
+ "insertColumns", // 1695
+ "insertHyperlinks", // 1696
+ "insertPageBreak", // 1697
+ "insertRow", // 1698
+ "insertRowShift", // 1699
+ "insertRows", // 1700
+ "inset", // 1701
+ "insetmode", // 1702
+ "insetpen", // 1703
+ "insetpenok", // 1704
+ "insideH", // 1705
+ "insideV", // 1706
+ "instr", // 1707
+ "instrText", // 1708
+ "int", // 1709
+ "intLim", // 1710
+ "intVal", // 1711
+ "integer", // 1712
+ "interSp", // 1713
+ "intercept", // 1714
+ "intermediate", // 1715
+ "interval", // 1716
+ "intraSp", // 1717
+ "inv", // 1718
+ "invGamma", // 1719
+ "invalEndChars", // 1720
+ "invalStChars", // 1721
+ "invalid", // 1722
+ "invalidUrl", // 1723
+ "invertIfNegative", // 1724
+ "invx", // 1725
+ "invy", // 1726
+ "is", // 1727
+ "isLgl", // 1728
+ "isNarration", // 1729
+ "isPhoto", // 1730
+ "iscomment", // 1731
+ "issignatureline", // 1732
+ "italic", // 1733
+ "item", // 1734
+ "itemID", // 1735
+ "itemPageCount", // 1736
+ "itemPrintTitles", // 1737
+ "items", // 1738
+ "iterate", // 1739
+ "iterateCount", // 1740
+ "iterateDelta", // 1741
+ "jc", // 1742
+ "joinstyle", // 1743
+ "justifyLastLine", // 1744
+ "k", // 1745
+ "keepAlive", // 1746
+ "keepChangeHistory", // 1747
+ "keepLines", // 1748
+ "keepNext", // 1749
+ "kern", // 1750
+ "key", // 1751
+ "keyAttribute", // 1752
+ "kinsoku", // 1753
+ "kiosk", // 1754
+ "kpi", // 1755
+ "kpis", // 1756
+ "kumimoji", // 1757
+ "kx", // 1758
+ "ky", // 1759
+ "l", // 1760
+ "lBounds", // 1761
+ "lIns", // 1762
+ "lMargin", // 1763
+ "label", // 1764
+ "labelOnly", // 1765
+ "lang", // 1766
+ "lastClr", // 1767
+ "lastCol", // 1768
+ "lastEdited", // 1769
+ "lastGuid", // 1770
+ "lastIdx", // 1771
+ "lastRenderedPageBreak", // 1772
+ "lastRow", // 1773
+ "lastValue", // 1774
+ "lastView", // 1775
+ "lat", // 1776
+ "latentStyles", // 1777
+ "latin", // 1778
+ "latinLnBrk", // 1779
+ "layout", // 1780
+ "layoutDef", // 1781
+ "layoutDefHdr", // 1782
+ "layoutDefHdrLst", // 1783
+ "layoutInCell", // 1784
+ "layoutNode", // 1785
+ "layoutRawTableWidth", // 1786
+ "layoutTableRowsApart", // 1787
+ "layoutTarget", // 1788
+ "lblAlgn", // 1789
+ "lblOffset", // 1790
+ "leader", // 1791
+ "leaderLines", // 1792
+ "left", // 1793
+ "leftChars", // 1794
+ "leftFromText", // 1795
+ "leftLabels", // 1796
+ "legacy", // 1797
+ "legacyDrawing", // 1798
+ "legacyDrawingHF", // 1799
+ "legacyIndent", // 1800
+ "legacySpace", // 1801
+ "legend", // 1802
+ "legendEntry", // 1803
+ "legendPos", // 1804
+ "len", // 1805
+ "length", // 1806
+ "lengthspecified", // 1807
+ "level", // 1808
+ "lid", // 1809
+ "lightRig", // 1810
+ "lightface", // 1811
+ "lightharsh", // 1812
+ "lightharsh2", // 1813
+ "lightlevel", // 1814
+ "lightlevel2", // 1815
+ "lightposition", // 1816
+ "lightposition2", // 1817
+ "lim", // 1818
+ "limLoc", // 1819
+ "limLow", // 1820
+ "limLowPr", // 1821
+ "limUpp", // 1822
+ "limUppPr", // 1823
+ "limo", // 1824
+ "lin", // 1825
+ "linClrLst", // 1826
+ "line", // 1827
+ "line3DChart", // 1828
+ "lineChart", // 1829
+ "linePitch", // 1830
+ "lineRule", // 1831
+ "lineTo", // 1832
+ "lineWrapLikeWord6", // 1833
+ "lines", // 1834
+ "linestyle", // 1835
+ "link", // 1836
+ "linkStyles", // 1837
+ "linkTarget", // 1838
+ "linkToQuery", // 1839
+ "linkedToFile", // 1840
+ "listDataValidation", // 1841
+ "listEntry", // 1842
+ "listItem", // 1843
+ "listSeparator", // 1844
+ "lit", // 1845
+ "lkTxEntry", // 1846
+ "ln", // 1847
+ "lnB", // 1848
+ "lnBlToTr", // 1849
+ "lnDef", // 1850
+ "lnL", // 1851
+ "lnNumType", // 1852
+ "lnR", // 1853
+ "lnRef", // 1854
+ "lnSpc", // 1855
+ "lnSpcReduction", // 1856
+ "lnStyleLst", // 1857
+ "lnT", // 1858
+ "lnTlToBr", // 1859
+ "lnTo", // 1860
+ "lo", // 1861
+ "loCatId", // 1862
+ "loTypeId", // 1863
+ "local", // 1864
+ "localConnection", // 1865
+ "localRefresh", // 1866
+ "localSheetId", // 1867
+ "location", // 1868
+ "lock", // 1869
+ "lockRevision", // 1870
+ "lockStructure", // 1871
+ "lockWindows", // 1872
+ "locked", // 1873
+ "lockedCanvas", // 1874
+ "lockrotationcenter", // 1875
+ "logBase", // 1876
+ "lon", // 1877
+ "longFileNames", // 1878
+ "longText", // 1879
+ "loop", // 1880
+ "lowestEdited", // 1881
+ "lpstr", // 1882
+ "lpwstr", // 1883
+ "lsdException", // 1884
+ "lstStyle", // 1885
+ "lt1", // 1886
+ "lt2", // 1887
+ "lum", // 1888
+ "lumMod", // 1889
+ "lumOff", // 1890
+ "lvl", // 1891
+ "lvl1pPr", // 1892
+ "lvl2pPr", // 1893
+ "lvl3pPr", // 1894
+ "lvl4pPr", // 1895
+ "lvl5pPr", // 1896
+ "lvl6pPr", // 1897
+ "lvl7pPr", // 1898
+ "lvl8pPr", // 1899
+ "lvl9pPr", // 1900
+ "lvlJc", // 1901
+ "lvlOverride", // 1902
+ "lvlPicBulletId", // 1903
+ "lvlRestart", // 1904
+ "lvlText", // 1905
+ "m", // 1906
+ "mPr", // 1907
+ "macro", // 1908
+ "mailAsAttachment", // 1909
+ "mailMerge", // 1910
+ "mailSubject", // 1911
+ "main", // 1912
+ "mainDocumentType", // 1913
+ "majorFont", // 1914
+ "majorGridlines", // 1915
+ "majorTickMark", // 1916
+ "majorTimeUnit", // 1917
+ "majorUnit", // 1918
+ "man", // 1919
+ "manifestLocation", // 1920
+ "manualBreakCount", // 1921
+ "manualLayout", // 1922
+ "map", // 1923
+ "mapId", // 1924
+ "mappedName", // 1925
+ "mappingCount", // 1926
+ "maps", // 1927
+ "marB", // 1928
+ "marBottom", // 1929
+ "marH", // 1930
+ "marL", // 1931
+ "marLeft", // 1932
+ "marR", // 1933
+ "marRight", // 1934
+ "marT", // 1935
+ "marTop", // 1936
+ "marW", // 1937
+ "marker", // 1938
+ "markup", // 1939
+ "master", // 1940
+ "masterClrMapping", // 1941
+ "masterRel", // 1942
+ "matchSrc", // 1943
+ "matchingName", // 1944
+ "mathFont", // 1945
+ "mathPr", // 1946
+ "matrix", // 1947
+ "max", // 1948
+ "maxAng", // 1949
+ "maxDate", // 1950
+ "maxDist", // 1951
+ "maxLength", // 1952
+ "maxR", // 1953
+ "maxRId", // 1954
+ "maxRank", // 1955
+ "maxSheetId", // 1956
+ "maxSubtotal", // 1957
+ "maxVal", // 1958
+ "maxValue", // 1959
+ "maxX", // 1960
+ "maxY", // 1961
+ "maximized", // 1962
+ "mc", // 1963
+ "mcJc", // 1964
+ "mcPr", // 1965
+ "mcs", // 1966
+ "mdx", // 1967
+ "mdxMetadata", // 1968
+ "mdxSubqueries", // 1969
+ "measure", // 1970
+ "measureFilter", // 1971
+ "measureGroup", // 1972
+ "measureGroups", // 1973
+ "measures", // 1974
+ "member", // 1975
+ "memberName", // 1976
+ "memberPropertyField", // 1977
+ "memberValueDatatype", // 1978
+ "members", // 1979
+ "merge", // 1980
+ "mergeCell", // 1981
+ "mergeCells", // 1982
+ "mergeInterval", // 1983
+ "mergeItem", // 1984
+ "metadata", // 1985
+ "metadataStrings", // 1986
+ "metadataType", // 1987
+ "metadataTypes", // 1988
+ "metal", // 1989
+ "meth", // 1990
+ "method", // 1991
+ "min", // 1992
+ "minAng", // 1993
+ "minDate", // 1994
+ "minLength", // 1995
+ "minR", // 1996
+ "minRId", // 1997
+ "minRefreshableVersion", // 1998
+ "minSubtotal", // 1999
+ "minSupportedVersion", // 2000
+ "minValue", // 2001
+ "minVer", // 2002
+ "minX", // 2003
+ "minY", // 2004
+ "minimized", // 2005
+ "minimumVersion", // 2006
+ "minorFont", // 2007
+ "minorGridlines", // 2008
+ "minorTickMark", // 2009
+ "minorTimeUnit", // 2010
+ "minorUnit", // 2011
+ "minus", // 2012
+ "minusx", // 2013
+ "minusy", // 2014
+ "minute", // 2015
+ "mirrorIndents", // 2016
+ "mirrorMargins", // 2017
+ "missingCaption", // 2018
+ "missingItemsLimit", // 2019
+ "miter", // 2020
+ "miterlimit", // 2021
+ "mod", // 2022
+ "modelId", // 2023
+ "modifyVerifier", // 2024
+ "month", // 2025
+ "monthLong", // 2026
+ "monthShort", // 2027
+ "moveFrom", // 2028
+ "moveFromRangeEnd", // 2029
+ "moveFromRangeStart", // 2030
+ "moveTo", // 2031
+ "moveToRangeEnd", // 2032
+ "moveToRangeStart", // 2033
+ "moveWith", // 2034
+ "movie", // 2035
+ "mp", // 2036
+ "mpFld", // 2037
+ "mpMap", // 2038
+ "mps", // 2039
+ "mr", // 2040
+ "mruColors", // 2041
+ "ms", // 2042
+ "multiLevelType", // 2043
+ "multiLine", // 2044
+ "multiLvlStrCache", // 2045
+ "multiLvlStrRef", // 2046
+ "multipleFieldFilters", // 2047
+ "multipleItemSelectionAllowed", // 2048
+ "mute", // 2049
+ "mwSmallCaps", // 2050
+ "n", // 2051
+ "name", // 2052
+ "nameLen", // 2053
+ "namespaceUri", // 2054
+ "namespaceuri", // 2055
+ "nary", // 2056
+ "naryLim", // 2057
+ "naryPr", // 2058
+ "nc", // 2059
+ "ndxf", // 2060
+ "neCell", // 2061
+ "new", // 2062
+ "newLength", // 2063
+ "newName", // 2064
+ "newsflash", // 2065
+ "next", // 2066
+ "nextAc", // 2067
+ "nextCondLst", // 2068
+ "nextId", // 2069
+ "nf", // 2070
+ "nlCheck", // 2071
+ "noAdjustHandles", // 2072
+ "noAutofit", // 2073
+ "noBorder", // 2074
+ "noBreak", // 2075
+ "noBreakHyphen", // 2076
+ "noChangeArrowheads", // 2077
+ "noChangeAspect", // 2078
+ "noChangeShapeType", // 2079
+ "noColumnBalance", // 2080
+ "noCrop", // 2081
+ "noDrilldown", // 2082
+ "noEditPoints", // 2083
+ "noEndCap", // 2084
+ "noEndnote", // 2085
+ "noExtraLineSpacing", // 2086
+ "noFill", // 2087
+ "noGrp", // 2088
+ "noLabel", // 2089
+ "noLeading", // 2090
+ "noLineBreaksAfter", // 2091
+ "noLineBreaksBefore", // 2092
+ "noMove", // 2093
+ "noMultiLvlLbl", // 2094
+ "noProof", // 2095
+ "noPunctuationKerning", // 2096
+ "noResize", // 2097
+ "noResizeAllowed", // 2098
+ "noRot", // 2099
+ "noSelect", // 2100
+ "noSpaceRaiseLower", // 2101
+ "noTabHangInd", // 2102
+ "noTextEdit", // 2103
+ "noUngrp", // 2104
+ "noWrap", // 2105
+ "nodePh", // 2106
+ "nodeType", // 2107
+ "nonAutoSortDefault", // 2108
+ "nor", // 2109
+ "norm", // 2110
+ "normAutofit", // 2111
+ "normalViewPr", // 2112
+ "normalizeH", // 2113
+ "notTrueType", // 2114
+ "notes", // 2115
+ "notesMaster", // 2116
+ "notesMasterId", // 2117
+ "notesMasterIdLst", // 2118
+ "notesStyle", // 2119
+ "notesSz", // 2120
+ "notesTextViewPr", // 2121
+ "notesViewPr", // 2122
+ "np", // 2123
+ "ns", // 2124
+ "nsid", // 2125
+ "null", // 2126
+ "num", // 2127
+ "numCache", // 2128
+ "numCol", // 2129
+ "numFmt", // 2130
+ "numFmtId", // 2131
+ "numFmts", // 2132
+ "numId", // 2133
+ "numIdMacAtCleanup", // 2134
+ "numLit", // 2135
+ "numPicBullet", // 2136
+ "numPicBulletId", // 2137
+ "numPr", // 2138
+ "numRef", // 2139
+ "numRestart", // 2140
+ "numSld", // 2141
+ "numStart", // 2142
+ "numStyleLink", // 2143
+ "numberStoredAsText", // 2144
+ "numbering", // 2145
+ "numberingChange", // 2146
+ "nvCxnSpPr", // 2147
+ "nvGraphicFramePr", // 2148
+ "nvGrpSpPr", // 2149
+ "nvPicPr", // 2150
+ "nvPr", // 2151
+ "nvSpPr", // 2152
+ "nwCell", // 2153
+ "o", // 2154
+ "oMath", // 2155
+ "oMathPara", // 2156
+ "oMathParaPr", // 2157
+ "objDist", // 2158
+ "object", // 2159
+ "objectDefaults", // 2160
+ "objects", // 2161
+ "oblob", // 2162
+ "obscured", // 2163
+ "oc", // 2164
+ "odcFile", // 2165
+ "oddFooter", // 2166
+ "oddHeader", // 2167
+ "odso", // 2168
+ "odxf", // 2169
+ "ofPieChart", // 2170
+ "ofPieType", // 2171
+ "off", // 2172
+ "offset", // 2173
+ "offset2", // 2174
+ "offsetFrom", // 2175
+ "olapPr", // 2176
+ "old", // 2177
+ "oldComment", // 2178
+ "oldCustomMenu", // 2179
+ "oldDescription", // 2180
+ "oldFormula", // 2181
+ "oldFunction", // 2182
+ "oldFunctionGroupId", // 2183
+ "oldHelp", // 2184
+ "oldHidden", // 2185
+ "oldLength", // 2186
+ "oldName", // 2187
+ "oldPh", // 2188
+ "oldQuotePrefix", // 2189
+ "oldShortcutKey", // 2190
+ "oldStatusBar", // 2191
+ "ole", // 2192
+ "oleChartEl", // 2193
+ "oleItem", // 2194
+ "oleItems", // 2195
+ "oleLink", // 2196
+ "oleObj", // 2197
+ "oleObject", // 2198
+ "oleObjects", // 2199
+ "oleSize", // 2200
+ "oleUpdate", // 2201
+ "oleicon", // 2202
+ "oleid", // 2203
+ "on", // 2204
+ "oneCellAnchor", // 2205
+ "oneField", // 2206
+ "oned", // 2207
+ "onlySync", // 2208
+ "onlyUseConnectionFile", // 2209
+ "op", // 2210
+ "opEmu", // 2211
+ "opacity", // 2212
+ "opacity2", // 2213
+ "operator", // 2214
+ "optimizeForBrowser", // 2215
+ "optimizeMemory", // 2216
+ "order", // 2217
+ "orgChart", // 2218
+ "organizeInFolders", // 2219
+ "orient", // 2220
+ "orientation", // 2221
+ "orientationangle", // 2222
+ "origin", // 2223
+ "original", // 2224
+ "ostorage", // 2225
+ "ostream", // 2226
+ "other", // 2227
+ "otherStyle", // 2228
+ "outerShdw", // 2229
+ "outline", // 2230
+ "outlineData", // 2231
+ "outlineLevel", // 2232
+ "outlineLevelCol", // 2233
+ "outlineLevelRow", // 2234
+ "outlineLvl", // 2235
+ "outlinePr", // 2236
+ "outlineSymbols", // 2237
+ "outlineViewPr", // 2238
+ "oval", // 2239
+ "overflowPunct", // 2240
+ "overlap", // 2241
+ "overlay", // 2242
+ "override", // 2243
+ "overrideClrMapping", // 2244
+ "p", // 2245
+ "pBdr", // 2246
+ "pLen", // 2247
+ "pPos", // 2248
+ "pPr", // 2249
+ "pPrChange", // 2250
+ "pPrDefault", // 2251
+ "pRg", // 2252
+ "pStyle", // 2253
+ "page", // 2254
+ "pageBreakBefore", // 2255
+ "pageField", // 2256
+ "pageFields", // 2257
+ "pageItem", // 2258
+ "pageMargins", // 2259
+ "pageOrder", // 2260
+ "pageOverThenDown", // 2261
+ "pageSetUpPr", // 2262
+ "pageSetup", // 2263
+ "pageStyle", // 2264
+ "pageWrap", // 2265
+ "pages", // 2266
+ "pane", // 2267
+ "panose", // 2268
+ "panose1", // 2269
+ "paperSize", // 2270
+ "paperSrc", // 2271
+ "par", // 2272
+ "parTransId", // 2273
+ "param", // 2274
+ "parameter", // 2275
+ "parameterType", // 2276
+ "parameters", // 2277
+ "parent", // 2278
+ "parentSet", // 2279
+ "parsePre", // 2280
+ "password", // 2281
+ "pasteAll", // 2282
+ "pasteBorders", // 2283
+ "pasteColWidths", // 2284
+ "pasteComments", // 2285
+ "pasteDataValidation", // 2286
+ "pasteFormats", // 2287
+ "pasteFormulas", // 2288
+ "pasteNumberFormats", // 2289
+ "pasteValues", // 2290
+ "path", // 2291
+ "pathEditMode", // 2292
+ "pathLst", // 2293
+ "pattFill", // 2294
+ "patternFill", // 2295
+ "patternType", // 2296
+ "penClr", // 2297
+ "percent", // 2298
+ "period", // 2299
+ "permEnd", // 2300
+ "permStart", // 2301
+ "personal", // 2302
+ "personalCompose", // 2303
+ "personalReply", // 2304
+ "personalView", // 2305
+ "perspective", // 2306
+ "pgBorders", // 2307
+ "pgMar", // 2308
+ "pgNum", // 2309
+ "pgNumType", // 2310
+ "pgSz", // 2311
+ "ph", // 2312
+ "phant", // 2313
+ "phantPr", // 2314
+ "phldr", // 2315
+ "phldrT", // 2316
+ "phonetic", // 2317
+ "phoneticPr", // 2318
+ "photoAlbum", // 2319
+ "pic", // 2320
+ "picLocks", // 2321
+ "pict", // 2322
+ "picture", // 2323
+ "pictureFormat", // 2324
+ "pictureOptions", // 2325
+ "pictureStackUnit", // 2326
+ "pid", // 2327
+ "pie3DChart", // 2328
+ "pieChart", // 2329
+ "pitch", // 2330
+ "pitchFamily", // 2331
+ "pivot", // 2332
+ "pivotArea", // 2333
+ "pivotAreas", // 2334
+ "pivotButton", // 2335
+ "pivotCache", // 2336
+ "pivotCacheDefinition", // 2337
+ "pivotCacheRecords", // 2338
+ "pivotCaches", // 2339
+ "pivotField", // 2340
+ "pivotFields", // 2341
+ "pivotFmt", // 2342
+ "pivotFmts", // 2343
+ "pivotHierarchies", // 2344
+ "pivotHierarchy", // 2345
+ "pivotSelection", // 2346
+ "pivotSource", // 2347
+ "pivotTableDefinition", // 2348
+ "pivotTableStyle", // 2349
+ "pivotTableStyleInfo", // 2350
+ "pivotTables", // 2351
+ "pixelsPerInch", // 2352
+ "placeholder", // 2353
+ "plane", // 2354
+ "plcHide", // 2355
+ "plotArea", // 2356
+ "plotVisOnly", // 2357
+ "plus", // 2358
+ "points", // 2359
+ "polar", // 2360
+ "polyline", // 2361
+ "pos", // 2362
+ "posOffset", // 2363
+ "position", // 2364
+ "positionH", // 2365
+ "positionV", // 2366
+ "post", // 2367
+ "postSp", // 2368
+ "prLst", // 2369
+ "prSet", // 2370
+ "preSp", // 2371
+ "preferPic", // 2372
+ "preferRelativeResize", // 2373
+ "preferSingleView", // 2374
+ "preferrelative", // 2375
+ "prefixMappings", // 2376
+ "presAssocID", // 2377
+ "presId", // 2378
+ "presLayoutVars", // 2379
+ "presName", // 2380
+ "presOf", // 2381
+ "presStyleCnt", // 2382
+ "presStyleIdx", // 2383
+ "presStyleLbl", // 2384
+ "present", // 2385
+ "presentation", // 2386
+ "presentationPr", // 2387
+ "preserve", // 2388
+ "preserveFormatting", // 2389
+ "preserveHistory", // 2390
+ "preserveSortFilterLayout", // 2391
+ "presetClass", // 2392
+ "presetID", // 2393
+ "presetSubtype", // 2394
+ "prevAc", // 2395
+ "prevCondLst", // 2396
+ "previousCol", // 2397
+ "previousRow", // 2398
+ "pri", // 2399
+ "print", // 2400
+ "printArea", // 2401
+ "printBodyTextBeforeHeader", // 2402
+ "printColBlack", // 2403
+ "printDrill", // 2404
+ "printFormsData", // 2405
+ "printFractionalCharacterWidth", // 2406
+ "printOptions", // 2407
+ "printPostScriptOverText", // 2408
+ "printSettings", // 2409
+ "printTwoOnOne", // 2410
+ "printerSettings", // 2411
+ "priority", // 2412
+ "prnPr", // 2413
+ "prnWhat", // 2414
+ "productSubtotal", // 2415
+ "progId", // 2416
+ "progress", // 2417
+ "prompt", // 2418
+ "promptTitle", // 2419
+ "promptedSolutions", // 2420
+ "proofErr", // 2421
+ "proofState", // 2422
+ "property", // 2423
+ "propertyName", // 2424
+ "protected", // 2425
+ "protectedRange", // 2426
+ "protectedRanges", // 2427
+ "protection", // 2428
+ "provid", // 2429
+ "proxy", // 2430
+ "prst", // 2431
+ "prstClr", // 2432
+ "prstDash", // 2433
+ "prstGeom", // 2434
+ "prstMaterial", // 2435
+ "prstShdw", // 2436
+ "prstTxWarp", // 2437
+ "pt", // 2438
+ "ptCount", // 2439
+ "ptLst", // 2440
+ "ptType", // 2441
+ "ptab", // 2442
+ "ptsTypes", // 2443
+ "pubBrowser", // 2444
+ "publishItems", // 2445
+ "publishToServer", // 2446
+ "published", // 2447
+ "pull", // 2448
+ "push", // 2449
+ "qFormat", // 2450
+ "qs", // 2451
+ "qsCatId", // 2452
+ "qsTypeId", // 2453
+ "quadBezTo", // 2454
+ "qualifier", // 2455
+ "query", // 2456
+ "queryCache", // 2457
+ "queryFailed", // 2458
+ "queryTable", // 2459
+ "queryTableDeletedFields", // 2460
+ "queryTableField", // 2461
+ "queryTableFieldId", // 2462
+ "queryTableFields", // 2463
+ "queryTableRefresh", // 2464
+ "quickTimeFile", // 2465
+ "quotePrefix", // 2466
+ "r", // 2467
+ "r1", // 2468
+ "r2", // 2469
+ "r4", // 2470
+ "r8", // 2471
+ "rAng", // 2472
+ "rAngAx", // 2473
+ "rCtr", // 2474
+ "rFont", // 2475
+ "rFonts", // 2476
+ "rId", // 2477
+ "rIns", // 2478
+ "rMargin", // 2479
+ "rPh", // 2480
+ "rPr", // 2481
+ "rPrChange", // 2482
+ "rPrDefault", // 2483
+ "rSp", // 2484
+ "rSpRule", // 2485
+ "rStyle", // 2486
+ "ra", // 2487
+ "rad", // 2488
+ "radPr", // 2489
+ "radarChart", // 2490
+ "radarStyle", // 2491
+ "radiusrange", // 2492
+ "raf", // 2493
+ "random", // 2494
+ "randomBar", // 2495
+ "rangePr", // 2496
+ "rangeSet", // 2497
+ "rangeSets", // 2498
+ "rank", // 2499
+ "rankBy", // 2500
+ "rc", // 2501
+ "rcc", // 2502
+ "rcft", // 2503
+ "rcmt", // 2504
+ "rctx", // 2505
+ "rcv", // 2506
+ "rdn", // 2507
+ "readModeInkLockDown", // 2508
+ "readOnlyRecommended", // 2509
+ "readingOrder", // 2510
+ "recipientData", // 2511
+ "recipients", // 2512
+ "recolor", // 2513
+ "recolortarget", // 2514
+ "recommended", // 2515
+ "reconnectionMethod", // 2516
+ "recordCount", // 2517
+ "rect", // 2518
+ "red", // 2519
+ "redMod", // 2520
+ "redOff", // 2521
+ "ref", // 2522
+ "ref3D", // 2523
+ "refFor", // 2524
+ "refForName", // 2525
+ "refMode", // 2526
+ "refPtType", // 2527
+ "refType", // 2528
+ "reference", // 2529
+ "references", // 2530
+ "refersTo", // 2531
+ "reflection", // 2532
+ "refreshAllConnections", // 2533
+ "refreshError", // 2534
+ "refreshOnChange", // 2535
+ "refreshOnLoad", // 2536
+ "refreshedBy", // 2537
+ "refreshedDate", // 2538
+ "refreshedVersion", // 2539
+ "regroupid", // 2540
+ "regrouptable", // 2541
+ "regular", // 2542
+ "rel", // 2543
+ "relIds", // 2544
+ "relOff", // 2545
+ "relSizeAnchor", // 2546
+ "relation", // 2547
+ "relationtable", // 2548
+ "relative", // 2549
+ "relativeFrom", // 2550
+ "relativeHeight", // 2551
+ "relativeIndent", // 2552
+ "relativeTo", // 2553
+ "relid", // 2554
+ "relyOnVML", // 2555
+ "relyOnVml", // 2556
+ "removeDataOnSave", // 2557
+ "removeDateAndTime", // 2558
+ "removePersonalInfoOnSave", // 2559
+ "removePersonalInformation", // 2560
+ "render", // 2561
+ "repairLoad", // 2562
+ "repeatCount", // 2563
+ "repeatDur", // 2564
+ "resId", // 2565
+ "reservationPassword", // 2566
+ "resizeGraphics", // 2567
+ "resizeHandles", // 2568
+ "restart", // 2569
+ "restoredLeft", // 2570
+ "restoredTop", // 2571
+ "result", // 2572
+ "rev", // 2573
+ "reverse", // 2574
+ "reviewed", // 2575
+ "reviewedList", // 2576
+ "revisionId", // 2577
+ "revisionView", // 2578
+ "revisions", // 2579
+ "revisionsPassword", // 2580
+ "rfmt", // 2581
+ "rgb", // 2582
+ "rgbColor", // 2583
+ "rich", // 2584
+ "richText", // 2585
+ "rig", // 2586
+ "right", // 2587
+ "rightChars", // 2588
+ "rightFromText", // 2589
+ "rightToLeft", // 2590
+ "ris", // 2591
+ "rm", // 2592
+ "rot", // 2593
+ "rotWithShape", // 2594
+ "rotX", // 2595
+ "rotY", // 2596
+ "rotate", // 2597
+ "rotation", // 2598
+ "rotationangle", // 2599
+ "rotationcenter", // 2600
+ "round", // 2601
+ "roundedCorners", // 2602
+ "roundrect", // 2603
+ "row", // 2604
+ "rowBreaks", // 2605
+ "rowColShift", // 2606
+ "rowDrillCount", // 2607
+ "rowFields", // 2608
+ "rowGrandTotals", // 2609
+ "rowHeaderCaption", // 2610
+ "rowHierarchiesUsage", // 2611
+ "rowHierarchyUsage", // 2612
+ "rowItems", // 2613
+ "rowNumbers", // 2614
+ "rowOff", // 2615
+ "rowPageCount", // 2616
+ "rowSpan", // 2617
+ "rows", // 2618
+ "rqt", // 2619
+ "rrc", // 2620
+ "rsid", // 2621
+ "rsidDel", // 2622
+ "rsidP", // 2623
+ "rsidR", // 2624
+ "rsidRDefault", // 2625
+ "rsidRPr", // 2626
+ "rsidRoot", // 2627
+ "rsidSect", // 2628
+ "rsidTr", // 2629
+ "rsids", // 2630
+ "rsnm", // 2631
+ "rt", // 2632
+ "rtl", // 2633
+ "rtlCol", // 2634
+ "rtlGutter", // 2635
+ "rtn", // 2636
+ "ruby", // 2637
+ "rubyAlign", // 2638
+ "rubyBase", // 2639
+ "rubyPr", // 2640
+ "rule", // 2641
+ "ruleLst", // 2642
+ "rules", // 2643
+ "rupBuild", // 2644
+ "s", // 2645
+ "sId", // 2646
+ "sPre", // 2647
+ "sPrePr", // 2648
+ "sSub", // 2649
+ "sSubPr", // 2650
+ "sSubSup", // 2651
+ "sSubSupPr", // 2652
+ "sSup", // 2653
+ "sSupPr", // 2654
+ "salt", // 2655
+ "saltData", // 2656
+ "sampData", // 2657
+ "sat", // 2658
+ "satMod", // 2659
+ "satOff", // 2660
+ "saveData", // 2661
+ "saveExternalLinkValues", // 2662
+ "saveFormsData", // 2663
+ "saveInvalidXml", // 2664
+ "savePassword", // 2665
+ "savePreviewPicture", // 2666
+ "saveSmartTagsAsXml", // 2667
+ "saveSubsetFonts", // 2668
+ "saveThroughXslt", // 2669
+ "saveXmlDataOnly", // 2670
+ "sb", // 2671
+ "scale", // 2672
+ "scaleToFitPaper", // 2673
+ "scaleWithDoc", // 2674
+ "scaled", // 2675
+ "scaling", // 2676
+ "scatterChart", // 2677
+ "scatterStyle", // 2678
+ "scenario", // 2679
+ "scenarios", // 2680
+ "scene3d", // 2681
+ "schema", // 2682
+ "schemaLibrary", // 2683
+ "schemaLocation", // 2684
+ "schemaRef", // 2685
+ "schemaRefs", // 2686
+ "scheme", // 2687
+ "schemeClr", // 2688
+ "scope", // 2689
+ "scr", // 2690
+ "scrgbClr", // 2691
+ "script", // 2692
+ "scrollbar", // 2693
+ "sd", // 2694
+ "sdt", // 2695
+ "sdtContent", // 2696
+ "sdtEndPr", // 2697
+ "sdtPr", // 2698
+ "seCell", // 2699
+ "second", // 2700
+ "secondPiePt", // 2701
+ "secondPieSize", // 2702
+ "sectPr", // 2703
+ "sectPrChange", // 2704
+ "securityDescriptor", // 2705
+ "selectFldWithFirstOrLastChar", // 2706
+ "selectLockedCells", // 2707
+ "selectUnlockedCells", // 2708
+ "selected", // 2709
+ "selection", // 2710
+ "semiHidden", // 2711
+ "semicolon", // 2712
+ "sendLocale", // 2713
+ "sep", // 2714
+ "sepChr", // 2715
+ "separator", // 2716
+ "seq", // 2717
+ "ser", // 2718
+ "serAx", // 2719
+ "serLines", // 2720
+ "series", // 2721
+ "seriesIdx", // 2722
+ "serverCommand", // 2723
+ "serverField", // 2724
+ "serverFill", // 2725
+ "serverFont", // 2726
+ "serverFontColor", // 2727
+ "serverFormat", // 2728
+ "serverFormats", // 2729
+ "serverNumberFormat", // 2730
+ "serverSldId", // 2731
+ "serverSldModifiedTime", // 2732
+ "serverZoom", // 2733
+ "set", // 2734
+ "setDefinition", // 2735
+ "sets", // 2736
+ "settings", // 2737
+ "shade", // 2738
+ "shadeToTitle", // 2739
+ "shadow", // 2740
+ "shadowcolor", // 2741
+ "shadowok", // 2742
+ "shape", // 2743
+ "shapeDefaults", // 2744
+ "shapeId", // 2745
+ "shapeLayoutLikeWW8", // 2746
+ "shapedefaults", // 2747
+ "shapeid", // 2748
+ "shapelayout", // 2749
+ "shapetype", // 2750
+ "shared", // 2751
+ "sharedItems", // 2752
+ "shd", // 2753
+ "sheet", // 2754
+ "sheetCalcPr", // 2755
+ "sheetData", // 2756
+ "sheetDataSet", // 2757
+ "sheetFormatPr", // 2758
+ "sheetId", // 2759
+ "sheetIdMap", // 2760
+ "sheetName", // 2761
+ "sheetNames", // 2762
+ "sheetPosition", // 2763
+ "sheetPr", // 2764
+ "sheetProtection", // 2765
+ "sheetView", // 2766
+ "sheetViews", // 2767
+ "sheets", // 2768
+ "shininess", // 2769
+ "shortcutKey", // 2770
+ "show", // 2771
+ "showAll", // 2772
+ "showAnimation", // 2773
+ "showAsCaption", // 2774
+ "showAsIcon", // 2775
+ "showAutoFilter", // 2776
+ "showBorderUnselectedTables", // 2777
+ "showBreaksInFrames", // 2778
+ "showBubbleSize", // 2779
+ "showButton", // 2780
+ "showCalcMbrs", // 2781
+ "showCaptions", // 2782
+ "showCatName", // 2783
+ "showCell", // 2784
+ "showColHeaders", // 2785
+ "showColStripes", // 2786
+ "showColumnStripes", // 2787
+ "showComments", // 2788
+ "showDLblsOverMax", // 2789
+ "showDataAs", // 2790
+ "showDataDropDown", // 2791
+ "showDataTips", // 2792
+ "showDrill", // 2793
+ "showDropDown", // 2794
+ "showDropDowns", // 2795
+ "showDropZones", // 2796
+ "showEmptyCol", // 2797
+ "showEmptyRow", // 2798
+ "showEnvelope", // 2799
+ "showError", // 2800
+ "showErrorMessage", // 2801
+ "showFirstColumn", // 2802
+ "showFormatting", // 2803
+ "showFormulaBar", // 2804
+ "showFormulas", // 2805
+ "showGridLines", // 2806
+ "showGuides", // 2807
+ "showHeader", // 2808
+ "showHeaders", // 2809
+ "showHorizontalScroll", // 2810
+ "showHorzBorder", // 2811
+ "showInFieldList", // 2812
+ "showInkAnnotation", // 2813
+ "showInputMessage", // 2814
+ "showItems", // 2815
+ "showKeys", // 2816
+ "showLastColumn", // 2817
+ "showLeaderLines", // 2818
+ "showLegendKey", // 2819
+ "showMasterPhAnim", // 2820
+ "showMasterSp", // 2821
+ "showMemberPropertyTips", // 2822
+ "showMissing", // 2823
+ "showMultipleLabel", // 2824
+ "showNarration", // 2825
+ "showNegBubbles", // 2826
+ "showObjects", // 2827
+ "showOutline", // 2828
+ "showOutlineIcons", // 2829
+ "showOutlineSymbols", // 2830
+ "showPageBreaks", // 2831
+ "showPercent", // 2832
+ "showPivotChartFilter", // 2833
+ "showPr", // 2834
+ "showPropAsCaption", // 2835
+ "showPropCell", // 2836
+ "showPropTip", // 2837
+ "showRowCol", // 2838
+ "showRowColHeaders", // 2839
+ "showRowHeaders", // 2840
+ "showRowStripes", // 2841
+ "showRuler", // 2842
+ "showScrollbar", // 2843
+ "showSerName", // 2844
+ "showSheetTabs", // 2845
+ "showSpeakerNotes", // 2846
+ "showSpecialPlsOnTitleSld", // 2847
+ "showStatusbar", // 2848
+ "showTip", // 2849
+ "showVal", // 2850
+ "showValue", // 2851
+ "showVertBorder", // 2852
+ "showVerticalScroll", // 2853
+ "showWhenStopped", // 2854
+ "showWhiteSpace", // 2855
+ "showXMLTags", // 2856
+ "showZeros", // 2857
+ "showingPlcHdr", // 2858
+ "showsigndate", // 2859
+ "shp", // 2860
+ "shrinkToFit", // 2861
+ "si", // 2862
+ "sibTransId", // 2863
+ "side", // 2864
+ "sideWall", // 2865
+ "sig", // 2866
+ "signatureline", // 2867
+ "signinginstructions", // 2868
+ "signinginstructionsset", // 2869
+ "sigprovurl", // 2870
+ "simplePos", // 2871
+ "singleSignOnId", // 2872
+ "singleXmlCell", // 2873
+ "singleXmlCells", // 2874
+ "singleclick", // 2875
+ "size", // 2876
+ "sizeAuto", // 2877
+ "sizeRepresents", // 2878
+ "skew", // 2879
+ "skewamt", // 2880
+ "skewangle", // 2881
+ "sld", // 2882
+ "sldAll", // 2883
+ "sldId", // 2884
+ "sldIdLst", // 2885
+ "sldLayout", // 2886
+ "sldLayoutId", // 2887
+ "sldLayoutIdLst", // 2888
+ "sldLst", // 2889
+ "sldMaster", // 2890
+ "sldMasterId", // 2891
+ "sldMasterIdLst", // 2892
+ "sldNum", // 2893
+ "sldRg", // 2894
+ "sldSyncPr", // 2895
+ "sldSz", // 2896
+ "sldTgt", // 2897
+ "slideViewPr", // 2898
+ "smallCaps", // 2899
+ "smallFrac", // 2900
+ "smartTag", // 2901
+ "smartTagPr", // 2902
+ "smartTagType", // 2903
+ "smartTagTypes", // 2904
+ "smartTags", // 2905
+ "smooth", // 2906
+ "smtClean", // 2907
+ "smtId", // 2908
+ "snapToGrid", // 2909
+ "snapToObjects", // 2910
+ "snapVertSplitter", // 2911
+ "snd", // 2912
+ "sndAc", // 2913
+ "sndTgt", // 2914
+ "softEdge", // 2915
+ "softHyphen", // 2916
+ "solidFill", // 2917
+ "solutionID", // 2918
+ "solveOrder", // 2919
+ "sort", // 2920
+ "sortBy", // 2921
+ "sortByTuple", // 2922
+ "sortCondition", // 2923
+ "sortMethod", // 2924
+ "sortState", // 2925
+ "sortType", // 2926
+ "sorterViewPr", // 2927
+ "source", // 2928
+ "sourceData", // 2929
+ "sourceFile", // 2930
+ "sourceFileName", // 2931
+ "sourceLinked", // 2932
+ "sourceObject", // 2933
+ "sourceRef", // 2934
+ "sourceSheetId", // 2935
+ "sourceType", // 2936
+ "sp", // 2937
+ "sp3d", // 2938
+ "spAutoFit", // 2939
+ "spDef", // 2940
+ "spLocks", // 2941
+ "spPr", // 2942
+ "spTgt", // 2943
+ "spTree", // 2944
+ "space", // 2945
+ "spaceForUL", // 2946
+ "spacing", // 2947
+ "spacingInWholePoints", // 2948
+ "spans", // 2949
+ "spc", // 2950
+ "spcAft", // 2951
+ "spcBef", // 2952
+ "spcCol", // 2953
+ "spcFirstLastPara", // 2954
+ "spcPct", // 2955
+ "spcPts", // 2956
+ "spd", // 2957
+ "specVanish", // 2958
+ "specularity", // 2959
+ "spelling", // 2960
+ "spid", // 2961
+ "spidmax", // 2962
+ "spinCount", // 2963
+ "split", // 2964
+ "splitAll", // 2965
+ "splitFirst", // 2966
+ "splitPgBreakAndParaMark", // 2967
+ "splitPos", // 2968
+ "splitType", // 2969
+ "spokes", // 2970
+ "spt", // 2971
+ "sqlType", // 2972
+ "sqref", // 2973
+ "src", // 2974
+ "srcId", // 2975
+ "srcOrd", // 2976
+ "srcRect", // 2977
+ "srgbClr", // 2978
+ "sst", // 2979
+ "st", // 2980
+ "stA", // 2981
+ "stAng", // 2982
+ "stCondLst", // 2983
+ "stCxn", // 2984
+ "stPos", // 2985
+ "stSnd", // 2986
+ "start", // 2987
+ "startAngle", // 2988
+ "startAt", // 2989
+ "startDate", // 2990
+ "startNum", // 2991
+ "startOverride", // 2992
+ "startarrow", // 2993
+ "startarrowlength", // 2994
+ "startarrowwidth", // 2995
+ "state", // 2996
+ "status", // 2997
+ "statusBar", // 2998
+ "statusText", // 2999
+ "stdDev", // 3000
+ "stdDevPSubtotal", // 3001
+ "stdDevSubtotal", // 3002
+ "step", // 3003
+ "stockChart", // 3004
+ "stop", // 3005
+ "stopIfTrue", // 3006
+ "storage", // 3007
+ "storeItemID", // 3008
+ "storeMappedDataAs", // 3009
+ "stp", // 3010
+ "strCache", // 3011
+ "strLit", // 3012
+ "strRef", // 3013
+ "strVal", // 3014
+ "stream", // 3015
+ "stretch", // 3016
+ "strictFirstAndLastChars", // 3017
+ "strike", // 3018
+ "strikeBLTR", // 3019
+ "strikeH", // 3020
+ "strikeTLBR", // 3021
+ "strikeV", // 3022
+ "string", // 3023
+ "stringValue1", // 3024
+ "stringValue2", // 3025
+ "strips", // 3026
+ "stroke", // 3027
+ "strokecolor", // 3028
+ "stroked", // 3029
+ "strokeok", // 3030
+ "strokeweight", // 3031
+ "sty", // 3032
+ "style", // 3033
+ "styleData", // 3034
+ "styleDef", // 3035
+ "styleDefHdr", // 3036
+ "styleDefHdrLst", // 3037
+ "styleId", // 3038
+ "styleLbl", // 3039
+ "styleLink", // 3040
+ "styleLockQFSet", // 3041
+ "styleLockTheme", // 3042
+ "styleName", // 3043
+ "stylePaneFormatFilter", // 3044
+ "stylePaneSortMethod", // 3045
+ "styleSheet", // 3046
+ "styles", // 3047
+ "sub", // 3048
+ "subDoc", // 3049
+ "subFontBySize", // 3050
+ "subHide", // 3051
+ "subSp", // 3052
+ "subTnLst", // 3053
+ "subsetted", // 3054
+ "subtotal", // 3055
+ "subtotalCaption", // 3056
+ "subtotalHiddenItems", // 3057
+ "subtotalTop", // 3058
+ "suff", // 3059
+ "suggestedsigner", // 3060
+ "suggestedsigner2", // 3061
+ "suggestedsigneremail", // 3062
+ "sumSubtotal", // 3063
+ "summaryBelow", // 3064
+ "summaryLength", // 3065
+ "summaryRight", // 3066
+ "sup", // 3067
+ "supHide", // 3068
+ "supportAdvancedDrill", // 3069
+ "supportSubquery", // 3070
+ "suppressAutoHyphens", // 3071
+ "suppressBottomSpacing", // 3072
+ "suppressLineNumbers", // 3073
+ "suppressOverlap", // 3074
+ "suppressSpBfAfterPgBrk", // 3075
+ "suppressSpacingAtTopOfPage", // 3076
+ "suppressTopSpacing", // 3077
+ "suppressTopSpacingWP", // 3078
+ "surface3DChart", // 3079
+ "surfaceChart", // 3080
+ "swAng", // 3081
+ "swCell", // 3082
+ "swapBordersFacingPages", // 3083
+ "switch", // 3084
+ "sx", // 3085
+ "sy", // 3086
+ "sym", // 3087
+ "symbol", // 3088
+ "syncBehavior", // 3089
+ "syncHorizontal", // 3090
+ "syncRef", // 3091
+ "syncVertical", // 3092
+ "sysClr", // 3093
+ "sz", // 3094
+ "szCs", // 3095
+ "t", // 3096
+ "t1", // 3097
+ "t2", // 3098
+ "tIns", // 3099
+ "tab", // 3100
+ "tabColor", // 3101
+ "tabLst", // 3102
+ "tabRatio", // 3103
+ "tabSelected", // 3104
+ "table", // 3105
+ "tableBorderDxfId", // 3106
+ "tableColumn", // 3107
+ "tableColumnId", // 3108
+ "tableColumns", // 3109
+ "tablePart", // 3110
+ "tableParts", // 3111
+ "tableStyle", // 3112
+ "tableStyleElement", // 3113
+ "tableStyleId", // 3114
+ "tableStyleInfo", // 3115
+ "tableStyles", // 3116
+ "tableType", // 3117
+ "tablelimits", // 3118
+ "tableproperties", // 3119
+ "tables", // 3120
+ "tabs", // 3121
+ "tag", // 3122
+ "tagLst", // 3123
+ "tags", // 3124
+ "tailEnd", // 3125
+ "target", // 3126
+ "targetScreenSize", // 3127
+ "targetScreenSz", // 3128
+ "targetscreensize", // 3129
+ "tav", // 3130
+ "tavLst", // 3131
+ "tbl", // 3132
+ "tblBg", // 3133
+ "tblBorders", // 3134
+ "tblCellMar", // 3135
+ "tblCellSpacing", // 3136
+ "tblGrid", // 3137
+ "tblGridChange", // 3138
+ "tblHeader", // 3139
+ "tblInd", // 3140
+ "tblLayout", // 3141
+ "tblLook", // 3142
+ "tblOverlap", // 3143
+ "tblPr", // 3144
+ "tblPrChange", // 3145
+ "tblPrEx", // 3146
+ "tblPrExChange", // 3147
+ "tblStyle", // 3148
+ "tblStyleColBandSize", // 3149
+ "tblStyleLst", // 3150
+ "tblStylePr", // 3151
+ "tblStyleRowBandSize", // 3152
+ "tblW", // 3153
+ "tblpPr", // 3154
+ "tblpX", // 3155
+ "tblpXSpec", // 3156
+ "tblpY", // 3157
+ "tblpYSpec", // 3158
+ "tc", // 3159
+ "tcBdr", // 3160
+ "tcBorders", // 3161
+ "tcFitText", // 3162
+ "tcMar", // 3163
+ "tcPr", // 3164
+ "tcPrChange", // 3165
+ "tcStyle", // 3166
+ "tcTxStyle", // 3167
+ "tcW", // 3168
+ "temporary", // 3169
+ "tentative", // 3170
+ "text", // 3171
+ "textAlignment", // 3172
+ "textDates", // 3173
+ "textDirection", // 3174
+ "textField", // 3175
+ "textFields", // 3176
+ "textInput", // 3177
+ "textPr", // 3178
+ "textRotation", // 3179
+ "textborder", // 3180
+ "textbox", // 3181
+ "textboxTightWrap", // 3182
+ "textboxrect", // 3183
+ "textdata", // 3184
+ "textlink", // 3185
+ "textpath", // 3186
+ "textpathok", // 3187
+ "tgtEl", // 3188
+ "tgtFrame", // 3189
+ "theme", // 3190
+ "themeColor", // 3191
+ "themeElements", // 3192
+ "themeFill", // 3193
+ "themeFillShade", // 3194
+ "themeFillTint", // 3195
+ "themeFontLang", // 3196
+ "themeManager", // 3197
+ "themeOverride", // 3198
+ "themeShade", // 3199
+ "themeTint", // 3200
+ "thickBot", // 3201
+ "thickBottom", // 3202
+ "thickTop", // 3203
+ "thicket", // 3204
+ "thickness", // 3205
+ "thousands", // 3206
+ "thresh", // 3207
+ "thruBlk", // 3208
+ "tickLblPos", // 3209
+ "tickLblSkip", // 3210
+ "tickMarkSkip", // 3211
+ "tile", // 3212
+ "tileRect", // 3213
+ "time", // 3214
+ "timePeriod", // 3215
+ "timing", // 3216
+ "tint", // 3217
+ "title", // 3218
+ "titlePg", // 3219
+ "titleStyle", // 3220
+ "tl2br", // 3221
+ "tm", // 3222
+ "tmAbs", // 3223
+ "tmFilter", // 3224
+ "tmPct", // 3225
+ "tmpl", // 3226
+ "tmplLst", // 3227
+ "tn", // 3228
+ "tnLst", // 3229
+ "to", // 3230
+ "tooltip", // 3231
+ "top", // 3232
+ "top10", // 3233
+ "topAutoShow", // 3234
+ "topFromText", // 3235
+ "topLabels", // 3236
+ "topLeftCell", // 3237
+ "topLinePunct", // 3238
+ "totalsRowBorderDxfId", // 3239
+ "totalsRowCellStyle", // 3240
+ "totalsRowCount", // 3241
+ "totalsRowDxfId", // 3242
+ "totalsRowFormula", // 3243
+ "totalsRowFunction", // 3244
+ "totalsRowLabel", // 3245
+ "totalsRowShown", // 3246
+ "tp", // 3247
+ "tpl", // 3248
+ "tplc", // 3249
+ "tpls", // 3250
+ "tr", // 3251
+ "tr2bl", // 3252
+ "trHeight", // 3253
+ "trPr", // 3254
+ "trPrChange", // 3255
+ "track", // 3256
+ "trackRevisions", // 3257
+ "transition", // 3258
+ "transitionEntry", // 3259
+ "transitionEvaluation", // 3260
+ "transp", // 3261
+ "trend", // 3262
+ "trendline", // 3263
+ "trendlineLbl", // 3264
+ "trendlineType", // 3265
+ "trim", // 3266
+ "truncateFontHeightsLikeWP6", // 3267
+ "tupleCache", // 3268
+ "twoCellAnchor", // 3269
+ "twoDigitTextYear", // 3270
+ "tx", // 3271
+ "tx1", // 3272
+ "tx2", // 3273
+ "txBody", // 3274
+ "txBox", // 3275
+ "txDef", // 3276
+ "txEffectClrLst", // 3277
+ "txEl", // 3278
+ "txFillClrLst", // 3279
+ "txLinClrLst", // 3280
+ "txPr", // 3281
+ "txSp", // 3282
+ "txStyles", // 3283
+ "txbxContent", // 3284
+ "ty", // 3285
+ "type", // 3286
+ "typeface", // 3287
+ "types", // 3288
+ "u", // 3289
+ "uBounds", // 3290
+ "uFill", // 3291
+ "uFillTx", // 3292
+ "uLn", // 3293
+ "uLnTx", // 3294
+ "ua", // 3295
+ "udl", // 3296
+ "ui1", // 3297
+ "ui2", // 3298
+ "ui4", // 3299
+ "ui8", // 3300
+ "uiCompat97To2003", // 3301
+ "uiExpand", // 3302
+ "uiPriority", // 3303
+ "uint", // 3304
+ "ulTrailSpace", // 3305
+ "un", // 3306
+ "unbalanced", // 3307
+ "unbalancedGroup", // 3308
+ "unboundColumnsLeft", // 3309
+ "unboundColumnsRight", // 3310
+ "underlineTabInNumList", // 3311
+ "undo", // 3312
+ "undone", // 3313
+ "ungrouping", // 3314
+ "unhideWhenUsed", // 3315
+ "uniqueCount", // 3316
+ "uniqueId", // 3317
+ "uniqueList", // 3318
+ "uniqueMemberProperty", // 3319
+ "uniqueName", // 3320
+ "uniqueParent", // 3321
+ "uniqueTag", // 3322
+ "unlockedFormula", // 3323
+ "up", // 3324
+ "upBars", // 3325
+ "upDownBars", // 3326
+ "updateAutomatic", // 3327
+ "updateFields", // 3328
+ "updateLinks", // 3329
+ "updatedVersion", // 3330
+ "upgradeOnRefresh", // 3331
+ "upright", // 3332
+ "uri", // 3333
+ "url", // 3334
+ "usb0", // 3335
+ "usb1", // 3336
+ "usb2", // 3337
+ "usb3", // 3338
+ "useA", // 3339
+ "useAltKinsokuLineBreakRules", // 3340
+ "useAnsiKerningPairs", // 3341
+ "useAutoFormatting", // 3342
+ "useBgFill", // 3343
+ "useDef", // 3344
+ "useFELayout", // 3345
+ "useFirstPageNumber", // 3346
+ "useLongFilenames", // 3347
+ "useNormalStyleForList", // 3348
+ "usePrinterDefaults", // 3349
+ "usePrinterMetrics", // 3350
+ "useSingleBorderforContiguousCells", // 3351
+ "useSpRect", // 3352
+ "useTimings", // 3353
+ "useWord2002TableStyleRules", // 3354
+ "useWord97LineBreakRules", // 3355
+ "useXSLTWhenSaving", // 3356
+ "user", // 3357
+ "userDrawn", // 3358
+ "userInfo", // 3359
+ "userInterface", // 3360
+ "userName", // 3361
+ "userShapes", // 3362
+ "userdrawn", // 3363
+ "userhidden", // 3364
+ "users", // 3365
+ "v", // 3366
+ "vAlign", // 3367
+ "vAnchor", // 3368
+ "vMerge", // 3369
+ "vMergeOrig", // 3370
+ "vSpace", // 3371
+ "vacatedStyle", // 3372
+ "val", // 3373
+ "valAx", // 3374
+ "value", // 3375
+ "valueMetadata", // 3376
+ "valueType", // 3377
+ "values", // 3378
+ "vanish", // 3379
+ "varLst", // 3380
+ "varPSubtotal", // 3381
+ "varScale", // 3382
+ "varSubtotal", // 3383
+ "variant", // 3384
+ "varyColors", // 3385
+ "vbProcedure", // 3386
+ "vector", // 3387
+ "vendorID", // 3388
+ "version", // 3389
+ "vert", // 3390
+ "vertAlign", // 3391
+ "vertAnchor", // 3392
+ "vertBarState", // 3393
+ "vertCompress", // 3394
+ "vertJc", // 3395
+ "vertOverflow", // 3396
+ "vertical", // 3397
+ "verticalCentered", // 3398
+ "verticalDpi", // 3399
+ "verticies", // 3400
+ "video", // 3401
+ "videoFile", // 3402
+ "view", // 3403
+ "view3D", // 3404
+ "viewMergedData", // 3405
+ "viewPr", // 3406
+ "viewpoint", // 3407
+ "viewpointorigin", // 3408
+ "visibility", // 3409
+ "visualTotals", // 3410
+ "vm", // 3411
+ "vml", // 3412
+ "vocabulary", // 3413
+ "vol", // 3414
+ "volType", // 3415
+ "volTypes", // 3416
+ "vstream", // 3417
+ "w", // 3418
+ "wAfter", // 3419
+ "wBefore", // 3420
+ "wMode", // 3421
+ "wR", // 3422
+ "wavAudioFile", // 3423
+ "webHidden", // 3424
+ "webPr", // 3425
+ "webPublishItem", // 3426
+ "webPublishItems", // 3427
+ "webPublishObject", // 3428
+ "webPublishObjects", // 3429
+ "webPublishing", // 3430
+ "webSettings", // 3431
+ "wedge", // 3432
+ "weight", // 3433
+ "wheel", // 3434
+ "whole", // 3435
+ "wholeTbl", // 3436
+ "widowControl", // 3437
+ "width", // 3438
+ "windowHeight", // 3439
+ "windowProtection", // 3440
+ "windowWidth", // 3441
+ "wipe", // 3442
+ "wireframe", // 3443
+ "wordWrap", // 3444
+ "workbook", // 3445
+ "workbookParameter", // 3446
+ "workbookPassword", // 3447
+ "workbookPr", // 3448
+ "workbookProtection", // 3449
+ "workbookView", // 3450
+ "workbookViewId", // 3451
+ "worksheet", // 3452
+ "worksheetSource", // 3453
+ "wpJustification", // 3454
+ "wpSpaceWidth", // 3455
+ "wrap", // 3456
+ "wrapIndent", // 3457
+ "wrapNone", // 3458
+ "wrapPolygon", // 3459
+ "wrapRight", // 3460
+ "wrapSquare", // 3461
+ "wrapText", // 3462
+ "wrapThrough", // 3463
+ "wrapTight", // 3464
+ "wrapTopAndBottom", // 3465
+ "wrapTrailSpaces", // 3466
+ "wrapcoords", // 3467
+ "writeProtection", // 3468
+ "wsDr", // 3469
+ "x", // 3470
+ "xAlign", // 3471
+ "xMode", // 3472
+ "xSplit", // 3473
+ "xVal", // 3474
+ "xWindow", // 3475
+ "xf", // 3476
+ "xfDxf", // 3477
+ "xfId", // 3478
+ "xfrm", // 3479
+ "xfrmType", // 3480
+ "xl2000", // 3481
+ "xl97", // 3482
+ "xlm", // 3483
+ "xml", // 3484
+ "xmlBased", // 3485
+ "xmlCellPr", // 3486
+ "xmlColumnPr", // 3487
+ "xmlDataType", // 3488
+ "xmlPr", // 3489
+ "xpath", // 3490
+ "xrange", // 3491
+ "xscale", // 3492
+ "y", // 3493
+ "yAlign", // 3494
+ "yMode", // 3495
+ "ySplit", // 3496
+ "yVal", // 3497
+ "yWindow", // 3498
+ "year", // 3499
+ "yearLong", // 3500
+ "yearShort", // 3501
+ "yrange", // 3502
+ "z", // 3503
+ "zOrder", // 3504
+ "zOrderOff", // 3505
+ "zeroAsc", // 3506
+ "zeroDesc", // 3507
+ "zeroHeight", // 3508
+ "zeroValues", // 3509
+ "zeroWid", // 3510
+ "zoom", // 3511
+ "zoomContents", // 3512
+ "zoomScale", // 3513
+ "zoomScaleNormal", // 3514
+ "zoomScalePageLayoutView", // 3515
+ "zoomScaleSheetLayoutView", // 3516
+ "zoomToFit" // 3517
+};
+
+size_t token_name_count = 3518; \ No newline at end of file
diff --git a/src/liborcus/ooxml_types.cpp b/src/liborcus/ooxml_types.cpp
new file mode 100644
index 0000000..f5165a0
--- /dev/null
+++ b/src/liborcus/ooxml_types.cpp
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ooxml_types.hpp"
+
+namespace orcus {
+
+opc_rel_extra::~opc_rel_extra() = default;
+
+opc_rel_extras_t::opc_rel_extras_t() = default;
+opc_rel_extras_t::~opc_rel_extras_t() = default;
+
+opc_rel_extras_t::opc_rel_extras_t(opc_rel_extras_t&& other) :
+ data(std::move(other.data)) {}
+
+void opc_rel_extras_t::swap(opc_rel_extras_t& other)
+{
+ data.swap(other.data);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/ooxml_types.hpp b/src/liborcus/ooxml_types.hpp
new file mode 100644
index 0000000..2b9e43c
--- /dev/null
+++ b/src/liborcus/ooxml_types.hpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OOXML_TYPES_HPP
+#define INCLUDED_ORCUS_OOXML_TYPES_HPP
+
+#include <iostream>
+#include <memory>
+#include <unordered_map>
+
+namespace orcus {
+
+typedef const char* content_type_t;
+typedef const char* schema_t;
+
+/**
+ * Part name (first) and content type (second).
+ */
+typedef ::std::pair<std::string_view, content_type_t> xml_part_t;
+
+/**
+ * Single OPC relationship that corresponds with a Relationship element in
+ * .rels parts.
+ */
+struct opc_rel_t
+{
+ std::string_view rid;
+ std::string_view target;
+ schema_t type;
+
+ opc_rel_t() : type(nullptr) {}
+ opc_rel_t(std::string_view _rid, const std::string_view& _target, schema_t _type) :
+ rid(_rid), target(_target), type(_type) {}
+};
+
+/**
+ * Used as a base struct only to allow storage of custom data associated
+ * with a relationship.
+ */
+struct opc_rel_extra
+{
+ virtual ~opc_rel_extra() = 0;
+};
+
+struct opc_rel_extras_t
+{
+ typedef std::unordered_map<std::string_view, std::unique_ptr<opc_rel_extra>> map_type;
+
+ /**
+ * Key is a textual relation ID, while the value is an arbitrary data
+ * associated with the relation ID.
+ */
+ map_type data;
+
+ opc_rel_extras_t(opc_rel_extras_t&& other);
+
+ opc_rel_extras_t(const opc_rel_extras_t&) = delete;
+ opc_rel_extras_t& operator=(const opc_rel_extras_t&) = delete;
+
+ opc_rel_extras_t();
+ ~opc_rel_extras_t();
+
+ void swap(opc_rel_extras_t& other);
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_context.cpp b/src/liborcus/opc_context.cpp
new file mode 100644
index 0000000..e3b1bb5
--- /dev/null
+++ b/src/liborcus/opc_context.cpp
@@ -0,0 +1,310 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "opc_context.hpp"
+#include "opc_token_constants.hpp"
+#include "ooxml_content_types.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_schemas.hpp"
+#include "session_context.hpp"
+
+#include "orcus/exception.hpp"
+
+#include <cassert>
+#include <iostream>
+#include <algorithm>
+
+namespace orcus {
+
+namespace {
+
+class part_ext_attr_parser
+{
+public:
+ part_ext_attr_parser(
+ opc_content_types_context::ct_cache_type* p_ct_cache, xml_token_t attr_name, const config* conf) :
+ mp_ct_cache(p_ct_cache),
+ m_attr_name(attr_name),
+ m_config(conf),
+ m_content_type(nullptr) {}
+
+ part_ext_attr_parser(const part_ext_attr_parser& r) :
+ mp_ct_cache(r.mp_ct_cache),
+ m_attr_name(r.m_attr_name),
+ m_config(r.m_config),
+ m_name(r.m_name),
+ m_content_type(r.m_content_type) {}
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.name == m_attr_name)
+ m_name = attr.value;
+ else if (attr.name == XML_ContentType)
+ m_content_type = to_content_type(attr.value);
+ }
+
+ const std::string_view& get_name() const { return m_name; }
+ content_type_t get_content_type() const { return m_content_type; }
+
+private:
+ content_type_t to_content_type(const std::string_view& p) const
+ {
+ opc_content_types_context::ct_cache_type::const_iterator itr =
+ mp_ct_cache->find(p);
+ if (itr == mp_ct_cache->end())
+ {
+ if (m_config->debug)
+ std::cout << "unknown content type: " << p << std::endl;
+ return nullptr;
+ }
+ std::string_view val = *itr;
+ return val.data();
+ }
+
+private:
+ const opc_content_types_context::ct_cache_type* mp_ct_cache;
+ xml_token_t m_attr_name;
+ const config* m_config;
+ std::string_view m_name;
+ content_type_t m_content_type;
+};
+
+}
+
+opc_content_types_context::opc_content_types_context(session_context& session_cxt, const tokens& _tokens) :
+ xml_context_base(session_cxt, _tokens)
+{
+ // build content type cache.
+ for (const content_type_t* p = CT_all; *p; ++p)
+ m_ct_cache.insert(std::string_view(*p));
+}
+
+opc_content_types_context::~opc_content_types_context()
+{
+}
+
+xml_context_base* opc_content_types_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void opc_content_types_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void opc_content_types_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t> &attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ switch (name)
+ {
+ case XML_Types:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+ }
+ break;
+ case XML_Override:
+ {
+ xml_element_expected(parent, NS_opc_ct, XML_Types);
+ part_ext_attr_parser func(&m_ct_cache, XML_PartName, &get_config());
+ func = for_each(attrs.begin(), attrs.end(), func);
+
+ // We need to use allocated strings for part names here because
+ // the part names need to survive after the [Content_Types].xml
+ // stream is destroyed.
+ std::string_view part_name = get_session_context().spool.intern(func.get_name()).first;
+ m_parts.push_back(
+ xml_part_t(part_name, func.get_content_type()));
+ }
+ break;
+ case XML_Default:
+ {
+ xml_element_expected(parent, NS_opc_ct, XML_Types);
+ part_ext_attr_parser func(&m_ct_cache, XML_Extension, &get_config());
+ func = for_each(attrs.begin(), attrs.end(), func);
+
+ // Like the part names, we need to use allocated strings for
+ // extension names.
+ std::string_view ext_name = get_session_context().spool.intern(func.get_name()).first;
+ m_ext_defaults.push_back(
+ xml_part_t(ext_name, func.get_content_type()));
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+}
+
+bool opc_content_types_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void opc_content_types_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void opc_content_types_context::pop_parts(std::vector<xml_part_t>& parts)
+{
+ m_parts.swap(parts);
+}
+
+void opc_content_types_context::pop_ext_defaults(std::vector<xml_part_t>& ext_defaults)
+{
+ m_ext_defaults.swap(ext_defaults);
+}
+
+// ============================================================================
+
+namespace {
+
+class rel_attr_parser
+{
+public:
+ rel_attr_parser(session_context* cxt, const opc_relations_context::schema_cache_type* cache, const config* conf) :
+ m_cxt(cxt), mp_schema_cache(cache), mp_config(conf) {}
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ // Target and rId strings must be interned as they must survive after
+ // the rels part gets destroyed.
+
+ switch (attr.name)
+ {
+ case XML_Target:
+ m_rel.target = m_cxt->spool.intern(attr.value).first;
+ break;
+ case XML_Type:
+ m_rel.type = to_schema(attr.value);
+ break;
+ case XML_Id:
+ m_rel.rid = m_cxt->spool.intern(attr.value).first;
+ break;
+ }
+ }
+
+ const opc_rel_t& get_rel() const { return m_rel; }
+
+private:
+ schema_t to_schema(const std::string_view& p) const
+ {
+ opc_relations_context::schema_cache_type::const_iterator itr =
+ mp_schema_cache->find(p);
+ if (itr == mp_schema_cache->end())
+ {
+ if (mp_config->debug)
+ std::cout << "unknown schema: " << p << std::endl;
+ return nullptr;
+ }
+ std::string_view val = *itr;
+ return val.data();
+ }
+
+private:
+ session_context* m_cxt;
+ const opc_relations_context::schema_cache_type* mp_schema_cache;
+ const config* mp_config;
+ opc_rel_t m_rel;
+};
+
+/**
+ * Compare relations by the rId.
+ */
+struct compare_rels
+{
+ bool operator() (const opc_rel_t& r1, const opc_rel_t& r2) const
+ {
+ std::size_t n1 = r1.rid.size(), n2 = r2.rid.size();
+ std::size_t n = std::min(n1, n2);
+ const char *p1 = r1.rid.data(), *p2 = r2.rid.data();
+ for (std::size_t i = 0; i < n; ++i, ++p1, ++p2)
+ {
+ if (*p1 < *p2)
+ return true;
+ if (*p1 > *p2)
+ return false;
+ assert(*p1 == *p2);
+ }
+ return n1 < n2;
+ }
+};
+
+}
+
+opc_relations_context::opc_relations_context(session_context& session_cxt, const tokens &_tokens) :
+ xml_context_base(session_cxt, _tokens)
+{
+ // build content type cache.
+ for (schema_t* p = SCH_all; *p; ++p)
+ m_schema_cache.insert(std::string_view(*p));
+}
+
+opc_relations_context::~opc_relations_context()
+{
+}
+
+xml_context_base* opc_relations_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void opc_relations_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void opc_relations_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t> &attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ switch (name)
+ {
+ case XML_Relationships:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+ }
+ break;
+ case XML_Relationship:
+ {
+ rel_attr_parser func(&get_session_context(), &m_schema_cache, &get_config());
+ xml_element_expected(parent, NS_opc_rel, XML_Relationships);
+ func = for_each(attrs.begin(), attrs.end(), func);
+ const opc_rel_t& rel = func.get_rel();
+ if (rel.type)
+ m_rels.push_back(rel);
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+}
+
+bool opc_relations_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void opc_relations_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void opc_relations_context::init()
+{
+ m_rels.clear();
+}
+
+void opc_relations_context::pop_rels(std::vector<opc_rel_t>& rels)
+{
+ // Sort by the rId.
+ sort(m_rels.begin(), m_rels.end(), compare_rels());
+ m_rels.swap(rels);
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_context.hpp b/src/liborcus/opc_context.hpp
new file mode 100644
index 0000000..c965895
--- /dev/null
+++ b/src/liborcus/opc_context.hpp
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OPC_CONTEXT_HPP
+#define INCLUDED_ORCUS_OPC_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "ooxml_types.hpp"
+
+#include <unordered_set>
+#include <vector>
+
+namespace orcus {
+
+/**
+ * Main context class for the [Content_Types].xml part. This context does
+ * not use any child contexts; [Content_Types].xml part is simple enough
+ * that we can handle all in a single context class.
+ */
+class opc_content_types_context : public xml_context_base
+{
+public:
+ typedef std::unordered_set<std::string_view> ct_cache_type;
+
+ opc_content_types_context(session_context& session_cxt, const tokens& _tokens);
+ virtual ~opc_content_types_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base *child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t> &attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ /**
+ * Swap stored xml part info with the instance passed as the argument.
+ * Calling this will clear the storage.
+ *
+ * @param parts instance to swap the stored xml part info with.
+ */
+ void pop_parts(::std::vector<xml_part_t>& parts);
+
+ /**
+ * Swap stored xml extension info with the instance passed as the
+ * argument. Calling this will clear the storage.
+ *
+ * @param parts instance to swap the stored extension info with.
+ */
+ void pop_ext_defaults(::std::vector<xml_part_t>& ext_defaults);
+
+private:
+ ct_cache_type m_ct_cache; // content type cache;
+ ::std::vector<xml_part_t> m_parts;
+ ::std::vector<xml_part_t> m_ext_defaults;
+};
+
+/**
+ * Context class for relations parts.
+ */
+class opc_relations_context : public xml_context_base
+{
+public:
+ typedef std::unordered_set<std::string_view> schema_cache_type;
+
+ opc_relations_context(session_context& session_cxt, const tokens& _tokens);
+ virtual ~opc_relations_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base *child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t> &attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ void init();
+ void pop_rels(::std::vector<opc_rel_t>& rels);
+
+private:
+ schema_cache_type m_schema_cache;
+ ::std::vector<opc_rel_t> m_rels;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_reader.cpp b/src/liborcus/opc_reader.cpp
new file mode 100644
index 0000000..7126f66
--- /dev/null
+++ b/src/liborcus/opc_reader.cpp
@@ -0,0 +1,306 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "opc_reader.hpp"
+#include "xml_stream_parser.hpp"
+
+#include "ooxml_global.hpp"
+#include "opc_context.hpp"
+#include "ooxml_tokens.hpp"
+
+#include "orcus/config.hpp"
+
+#include <iostream>
+
+using namespace std;
+
+namespace orcus {
+
+namespace {
+
+class print_xml_content_types
+{
+public:
+ print_xml_content_types(const char* prefix) :
+ m_prefix(prefix) {}
+
+ void operator() (const xml_part_t& v) const
+ {
+ cout << "* " << m_prefix << ": " << v.first;
+ if (v.second)
+ cout << " (" << v.second << ")";
+ else
+ cout << " (<unknown content type>)";
+ cout << endl;
+ }
+private:
+ const char* m_prefix;
+};
+
+}
+
+opc_reader::part_handler::~part_handler() {}
+
+opc_reader::opc_reader(const config& opt, xmlns_repository& ns_repo, session_context& cxt, part_handler& handler) :
+ m_config(opt),
+ m_ns_repo(ns_repo),
+ m_session_cxt(cxt),
+ m_handler(handler),
+ m_opc_rel_handler(m_session_cxt, opc_tokens, std::make_unique<opc_relations_context>(m_session_cxt, opc_tokens)) {}
+
+void opc_reader::read_file(std::unique_ptr<zip_archive_stream>&& stream)
+{
+ m_archive_stream.reset(stream.release());
+ m_archive.reset(new zip_archive(m_archive_stream.get()));
+
+ m_archive->load();
+
+ m_dir_stack.push_back(string()); // push root directory.
+
+ if (m_config.debug)
+ list_content();
+ read_content();
+
+ m_archive.reset();
+ m_archive_stream.reset();
+}
+
+bool opc_reader::open_zip_stream(const string& path, vector<unsigned char>& buf)
+{
+ try
+ {
+ std::vector<unsigned char> entry = m_archive->read_file_entry(path.c_str());
+ buf.swap(entry);
+ return true;
+ }
+ catch (const std::exception&)
+ {
+ return false;
+ }
+}
+
+void opc_reader::read_part(std::string_view path, const schema_t type, opc_rel_extra* data)
+{
+ assert(!m_dir_stack.empty());
+
+ dir_stack_type dir_changed;
+
+ // Change current directory and read the in-file.
+ const char* p = path.data();
+ const char* p_name = nullptr;
+ size_t name_len = 0;
+ for (size_t i = 0, n = path.size(); i < n; ++i, ++p)
+ {
+ if (!p_name)
+ p_name = p;
+
+ ++name_len;
+
+ if (*p == '/')
+ {
+ // Push a new directory.
+ string dir_name(p_name, name_len);
+ if (dir_name == "..")
+ {
+ dir_changed.push_back(m_dir_stack.back());
+ m_dir_stack.pop_back();
+ }
+ else
+ {
+ m_dir_stack.push_back(dir_name);
+
+ // Add a null directory to the change record to remove it at the end.
+ dir_changed.push_back(string());
+ }
+
+ p_name = nullptr;
+ name_len = 0;
+ }
+ }
+
+ if (p_name)
+ {
+ // This is a file.
+ string file_name(p_name, name_len);
+ string cur_dir = get_current_dir();
+ string full_path = resolve_file_path(cur_dir, file_name);
+
+ if (m_handled_parts.count(full_path) > 0)
+ {
+ // This part has been previously read. Let's not read it twice.
+ if (m_config.debug)
+ {
+ cout << "---" << endl;
+ cout << "skipping previously read part: " << full_path << endl;
+ }
+ }
+ else if (m_handler.handle_part(type, cur_dir, file_name, data))
+ {
+ m_handled_parts.insert(full_path);
+ }
+ else if (m_config.debug)
+ {
+ cout << "---" << endl;
+ cout << "unhandled relationship type: " << type << endl;
+ }
+ }
+
+ // Unwind to the original directory.
+ while (!dir_changed.empty())
+ {
+ const string& dir = dir_changed.back();
+ if (dir.empty())
+ // remove added directory.
+ m_dir_stack.pop_back();
+ else
+ // re-add removed directory.
+ m_dir_stack.push_back(dir);
+
+ dir_changed.pop_back();
+ }
+}
+
+void opc_reader::check_relation_part(
+ const std::string& file_name, opc_rel_extras_t* extras, sort_compare_type* sorter)
+{
+ // Read the relationship file associated with this file, located at
+ // _rels/<file name>.rels.
+ vector<opc_rel_t> rels;
+ m_dir_stack.push_back(string("_rels/"));
+ string rels_file_name = file_name + ".rels";
+ read_relations(rels_file_name.c_str(), rels);
+ m_dir_stack.pop_back();
+
+ if (sorter)
+ std::sort(rels.begin(), rels.end(), *sorter);
+
+ if (m_config.debug)
+ for_each(rels.begin(), rels.end(), print_opc_rel());
+
+ for_each(rels.begin(), rels.end(),
+ [&](opc_rel_t& v)
+ {
+ opc_rel_extra* data = nullptr;
+ if (extras)
+ {
+ // See if there is an extra data associated with this relation ID.
+ opc_rel_extras_t::map_type::iterator it = extras->data.find(v.rid);
+ if (it != extras->data.end())
+ // There is one !
+ data = it->second.get();
+ }
+ read_part(v.target, v.type, data);
+ }
+ );
+}
+
+void opc_reader::list_content() const
+{
+ size_t num = m_archive->get_file_entry_count();
+ cout << "number of files this archive contains: " << num << endl;
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ std::string_view filename = m_archive->get_file_entry_name(i);
+ cout << filename << endl;
+ }
+}
+
+void opc_reader::read_content()
+{
+ if (m_dir_stack.empty())
+ return;
+
+ // [Content_Types].xml
+
+ read_content_types();
+ if (m_config.debug)
+ {
+ for_each(m_parts.begin(), m_parts.end(), print_xml_content_types("part name"));
+ for_each(m_ext_defaults.begin(), m_ext_defaults.end(), print_xml_content_types("extension default"));
+ }
+
+ // _rels/.rels
+
+ m_dir_stack.push_back(string("_rels/"));
+ vector<opc_rel_t> rels;
+ read_relations(".rels", rels);
+ m_dir_stack.pop_back();
+
+ if (m_config.debug)
+ for_each(rels.begin(), rels.end(), print_opc_rel());
+
+ for_each(rels.begin(), rels.end(),
+ [this](opc_rel_t& v)
+ {
+ read_part(v.target, v.type, nullptr);
+ }
+ );
+}
+
+void opc_reader::read_content_types()
+{
+ string filepath("[Content_Types].xml");
+ vector<unsigned char> buffer;
+ if (!open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ m_config, m_ns_repo, opc_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ m_session_cxt, opc_tokens,
+ std::make_unique<opc_content_types_context>(m_session_cxt, opc_tokens));
+
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ opc_content_types_context& context =
+ static_cast<opc_content_types_context&>(handler->get_context());
+ context.pop_parts(m_parts);
+ context.pop_ext_defaults(m_ext_defaults);
+}
+
+void opc_reader::read_relations(const char* path, vector<opc_rel_t>& rels)
+{
+ string filepath = resolve_file_path(get_current_dir(), path);
+ if (m_config.debug)
+ cout << "relation file path: " << filepath << endl;
+
+ vector<unsigned char> buffer;
+ if (!open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ m_config, m_ns_repo, opc_tokens, reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ opc_relations_context& context =
+ static_cast<opc_relations_context&>(m_opc_rel_handler.get_context());
+ context.init();
+ parser.set_handler(&m_opc_rel_handler);
+ parser.parse();
+ context.pop_rels(rels);
+}
+
+string opc_reader::get_current_dir() const
+{
+ string pwd;
+ vector<string>::const_iterator itr = m_dir_stack.begin(), itr_end = m_dir_stack.end();
+ for (; itr != itr_end; ++itr)
+ pwd += *itr;
+ return pwd;
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_reader.hpp b/src/liborcus/opc_reader.hpp
new file mode 100644
index 0000000..5733c02
--- /dev/null
+++ b/src/liborcus/opc_reader.hpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_OPC_READER_HPP
+#define INCLUDED_ORCUS_OPC_READER_HPP
+
+#include "orcus/env.hpp"
+#include "orcus/zip_archive.hpp"
+#include "orcus/zip_archive_stream.hpp"
+
+#include "ooxml_schemas.hpp"
+#include "xml_simple_stream_handler.hpp"
+
+#include <vector>
+#include <string>
+#include <unordered_set>
+
+namespace orcus {
+
+struct config;
+
+class xmlns_repository;
+struct session_context;
+struct opc_rel_extra;
+
+/**
+ * Class to handle parsing through all xml parts stored in a file packaged
+ * according to the Open Package Convention (OPC).
+ */
+class opc_reader
+{
+ typedef std::vector<std::string> dir_stack_type;
+ typedef std::unordered_set<std::string> part_set_type;
+
+ opc_reader(const opc_reader&) = delete;
+ opc_reader& operator=(const opc_reader&) = delete;
+
+public:
+
+ using sort_compare_type = std::function<bool(const opc_rel_t&, const opc_rel_t&)>;
+
+ /**
+ * Interface class for the user of opc_reader to receive callback to
+ * handle each xml part.
+ */
+ class part_handler
+ {
+ public:
+ virtual ~part_handler() = 0;
+
+ /**
+ * Client code needs to implement this method to handle each xml part.
+ *
+ * @param type schema type signifying the content type stored in this
+ * part.
+ * @param dir_path directory path relative to package root.
+ * @param file_name name of the xml part without the directory path.
+ * @param data extra data passed on from the client code.
+ *
+ * @return true if handled, false if not handled.
+ */
+ virtual bool handle_part(
+ schema_t type, const std::string& dir_path, const std::string& file_name, opc_rel_extra* data) = 0;
+ };
+
+ opc_reader(const config& opt, xmlns_repository& ns_repo, session_context& session_cxt, part_handler& handler);
+
+ void read_file(std::unique_ptr<zip_archive_stream>&& stream);
+ bool open_zip_stream(const std::string& path, std::vector<unsigned char>& buf);
+
+ /**
+ * Read an xml part inside package. The path is relative to the relation
+ * file.
+ *
+ * @param path the path to the xml part.
+ * @param type schema type.
+ */
+ void read_part(std::string_view path, const schema_t type, opc_rel_extra* data);
+
+ /**
+ * Check if a relation file exists for a given xml part, and if it does,
+ * read and process it.
+ *
+ * @param file_name name of the current xml part.
+ * @param extras optional extra data file for client code to pass on to
+ * the next xml part(s).
+ * @param sorter optoinal comparator function used to sort the relation
+ * items prior to processing them.
+ */
+ void check_relation_part(
+ const std::string& file_name, opc_rel_extras_t* extras = nullptr,
+ sort_compare_type* sorter = nullptr);
+
+private:
+
+ void list_content() const;
+ void read_content();
+ void read_content_types();
+ void read_relations(const char* path, std::vector<opc_rel_t>& rels);
+
+ std::string get_current_dir() const;
+
+private:
+ const config& m_config;
+ xmlns_repository& m_ns_repo;
+ session_context& m_session_cxt;
+ part_handler& m_handler;
+
+ std::unique_ptr<zip_archive> m_archive;
+ std::unique_ptr<zip_archive_stream> m_archive_stream;
+
+ xml_simple_stream_handler m_opc_rel_handler;
+
+ std::vector<xml_part_t> m_parts;
+ std::vector<xml_part_t> m_ext_defaults;
+ dir_stack_type m_dir_stack;
+ part_set_type m_handled_parts;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_token_constants.hpp b/src/liborcus/opc_token_constants.hpp
new file mode 100644
index 0000000..a7b1370
--- /dev/null
+++ b/src/liborcus/opc_token_constants.hpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_OPC_TOKEN_CONSTANTS_HPP__
+#define __ORCUS_OPC_TOKEN_CONSTANTS_HPP__
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+#include "opc_token_constants.inl"
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/opc_token_constants.inl b/src/liborcus/opc_token_constants.inl
new file mode 100644
index 0000000..7f3c7da
--- /dev/null
+++ b/src/liborcus/opc_token_constants.inl
@@ -0,0 +1,31 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const xml_token_t XML_ContentType = 1;
+const xml_token_t XML_Default = 2;
+const xml_token_t XML_Extension = 3;
+const xml_token_t XML_Format = 4;
+const xml_token_t XML_Id = 5;
+const xml_token_t XML_Override = 6;
+const xml_token_t XML_PartName = 7;
+const xml_token_t XML_Relationship = 8;
+const xml_token_t XML_RelationshipReference = 9;
+const xml_token_t XML_Relationships = 10;
+const xml_token_t XML_RelationshipsGroupReference = 11;
+const xml_token_t XML_SignatureTime = 12;
+const xml_token_t XML_SourceId = 13;
+const xml_token_t XML_SourceType = 14;
+const xml_token_t XML_Target = 15;
+const xml_token_t XML_TargetMode = 16;
+const xml_token_t XML_Type = 17;
+const xml_token_t XML_Types = 18;
+const xml_token_t XML_Value = 19;
+const xml_token_t XML_category = 20;
+const xml_token_t XML_contentStatus = 21;
+const xml_token_t XML_contentType = 22;
+const xml_token_t XML_coreProperties = 23;
+const xml_token_t XML_keywords = 24;
+const xml_token_t XML_lastModifiedBy = 25;
+const xml_token_t XML_lastPrinted = 26;
+const xml_token_t XML_revision = 27;
+const xml_token_t XML_version = 28;
+
diff --git a/src/liborcus/opc_tokens.inl b/src/liborcus/opc_tokens.inl
new file mode 100644
index 0000000..5f72a6a
--- /dev/null
+++ b/src/liborcus/opc_tokens.inl
@@ -0,0 +1,36 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const char* token_names[] = {
+ "??", // 0
+ "ContentType", // 1
+ "Default", // 2
+ "Extension", // 3
+ "Format", // 4
+ "Id", // 5
+ "Override", // 6
+ "PartName", // 7
+ "Relationship", // 8
+ "RelationshipReference", // 9
+ "Relationships", // 10
+ "RelationshipsGroupReference", // 11
+ "SignatureTime", // 12
+ "SourceId", // 13
+ "SourceType", // 14
+ "Target", // 15
+ "TargetMode", // 16
+ "Type", // 17
+ "Types", // 18
+ "Value", // 19
+ "category", // 20
+ "contentStatus", // 21
+ "contentType", // 22
+ "coreProperties", // 23
+ "keywords", // 24
+ "lastModifiedBy", // 25
+ "lastPrinted", // 26
+ "revision", // 27
+ "version" // 28
+};
+
+size_t token_name_count = 29;
+
diff --git a/src/liborcus/orcus_csv.cpp b/src/liborcus/orcus_csv.cpp
new file mode 100644
index 0000000..dff2b2d
--- /dev/null
+++ b/src/liborcus/orcus_csv.cpp
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_csv.hpp"
+
+#include "orcus/csv_parser.hpp"
+#include "orcus/stream.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/config.hpp"
+#include "orcus/string_pool.hpp"
+
+#include <cstring>
+#include <iostream>
+
+using namespace std;
+
+namespace orcus {
+
+namespace {
+
+constexpr const char* base_sheet_name = "data";
+
+struct header_cell
+{
+ spreadsheet::row_t row;
+ spreadsheet::col_t col;
+ std::string_view value;
+
+ header_cell(spreadsheet::row_t _row, spreadsheet::col_t _col, std::string_view _value) :
+ row(_row), col(_col), value(_value) {}
+};
+
+class max_row_size_reached {};
+
+class orcus_csv_handler
+{
+public:
+ orcus_csv_handler(spreadsheet::iface::import_factory& factory, const orcus::config& app_config) :
+ m_factory(factory),
+ m_app_config(app_config),
+ mp_sheet(nullptr),
+ m_sheet(0),
+ m_row(0),
+ m_col(0) {}
+
+ void begin_parse()
+ {
+ std::string sheet_name = get_sheet_name();
+ mp_sheet = m_factory.append_sheet(m_sheet, sheet_name);
+ }
+
+ void end_parse() {}
+ void begin_row()
+ {
+ // Check to see if this row is beyond the max row of the current
+ // sheet, and if so, append a new sheet and reset the current row to
+ // 0.
+ if (m_row >= mp_sheet->get_sheet_size().rows)
+ {
+ auto csv = std::get<config::csv_config>(m_app_config.data);
+
+ if (!csv.split_to_multiple_sheets)
+ throw max_row_size_reached();
+
+ // The next row will be outside the boundary of the current sheet.
+ ++m_sheet;
+ std::string sheet_name = get_sheet_name();
+ mp_sheet = m_factory.append_sheet(m_sheet, sheet_name);
+ m_row = 0;
+
+ if (!m_header_cells.empty())
+ {
+ // Duplicate the header rows from the first sheet.
+ for (const header_cell& c : m_header_cells)
+ mp_sheet->set_auto(c.row, c.col, c.value);
+
+ m_row += csv.header_row_size;
+ }
+ }
+ }
+
+ void end_row()
+ {
+ ++m_row;
+ m_col = 0;
+ }
+
+ void cell(std::string_view v, bool transient)
+ {
+ auto csv = std::get<config::csv_config>(m_app_config.data);
+
+ if (m_sheet == 0 && size_t(m_row) < csv.header_row_size)
+ {
+ if (transient)
+ v = m_pool.intern(v).first;
+
+ m_header_cells.emplace_back(m_row, m_col, v);
+ }
+
+ mp_sheet->set_auto(m_row, m_col, v);
+ ++m_col;
+ }
+
+private:
+ std::string get_sheet_name() const
+ {
+ if (!m_sheet)
+ // First sheet has no suffix.
+ return base_sheet_name;
+
+ // Add a suffix to keep the sheet name unique.
+ std::ostringstream os;
+ os << base_sheet_name << '_' << m_sheet;
+ return os.str();
+ }
+
+private:
+ string_pool m_pool;
+ std::vector<header_cell> m_header_cells;
+
+ spreadsheet::iface::import_factory& m_factory;
+ const config& m_app_config;
+ spreadsheet::iface::import_sheet* mp_sheet;
+ spreadsheet::sheet_t m_sheet;
+ spreadsheet::row_t m_row;
+ spreadsheet::col_t m_col;
+};
+
+}
+
+struct orcus_csv::impl
+{
+ spreadsheet::iface::import_factory* factory;
+
+ impl(spreadsheet::iface::import_factory* _factory) : factory(_factory) {}
+
+ void parse(std::string_view stream, const config& conf)
+ {
+ if (stream.empty())
+ return;
+
+ orcus_csv_handler handler(*factory, conf);
+ csv::parser_config config;
+ config.delimiters.push_back(',');
+ config.text_qualifier = '"';
+ csv_parser<orcus_csv_handler> parser(stream, handler, config);
+ try
+ {
+ parser.parse();
+ }
+ catch (const max_row_size_reached&)
+ {
+ // The parser has decided to end the import due to the destination
+ // sheet being full.
+ }
+ catch (const parse_error& e)
+ {
+ cout << "parse failed at offset " << e.offset() << ": " << e.what() << endl;
+ }
+ }
+};
+
+orcus_csv::orcus_csv(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::csv),
+ mp_impl(std::make_unique<impl>(factory)) {}
+
+orcus_csv::~orcus_csv() {}
+
+void orcus_csv::read_file(std::string_view filepath)
+{
+ file_content fc(filepath);
+ mp_impl->parse(fc.str(), get_config());
+ mp_impl->factory->finalize();
+}
+
+void orcus_csv::read_stream(std::string_view stream)
+{
+ if (stream.empty())
+ return;
+
+ mp_impl->parse(stream, get_config());
+ mp_impl->factory->finalize();
+}
+
+std::string_view orcus_csv::get_name() const
+{
+ return "csv";
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_gnumeric.cpp b/src/liborcus/orcus_gnumeric.cpp
new file mode 100644
index 0000000..849759b
--- /dev/null
+++ b/src/liborcus/orcus_gnumeric.cpp
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_gnumeric.hpp"
+#include "orcus/xml_namespace.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/stream.hpp"
+#include "orcus/config.hpp"
+
+#include "xml_stream_parser.hpp"
+#include "gnumeric_handler.hpp"
+#include "gnumeric_tokens.hpp"
+#include "gnumeric_namespace_types.hpp"
+#include "gnumeric_detection_handler.hpp"
+#include "session_context.hpp"
+#include "detection_result.hpp"
+
+#define ORCUS_DEBUG_GNUMERIC 0
+#define BOOST_IOSTREAMS_NO_LIB 1
+
+#include <iostream>
+#include <string>
+
+#include <boost/iostreams/filtering_stream.hpp>
+#include <boost/iostreams/filter/gzip.hpp>
+
+using namespace std;
+
+namespace orcus {
+
+namespace {
+
+bool decompress_gzip(const char* buffer, size_t size, string& decompressed)
+{
+ string buf;
+
+ try
+ {
+ boost::iostreams::filtering_ostream os;
+ os.push(boost::iostreams::gzip_decompressor());
+ os.push(boost::iostreams::back_inserter(buf));
+ boost::iostreams::write(os, buffer, size);
+ os.flush();
+ }
+ catch (const exception&)
+ {
+ return false;
+ }
+
+ buf.swap(decompressed);
+ return true;
+}
+
+}
+
+struct orcus_gnumeric::impl
+{
+ xmlns_repository m_ns_repo;
+ session_context m_cxt;
+ spreadsheet::iface::import_factory* mp_factory;
+
+ impl(spreadsheet::iface::import_factory* im_factory) :
+ mp_factory(im_factory) {}
+
+ void read_content_xml(std::string_view s, const config& conf)
+ {
+ xml_stream_parser parser(conf, m_ns_repo, gnumeric_tokens, s.data(), s.size());
+
+ auto handler = std::make_unique<gnumeric_content_xml_handler>(
+ m_cxt, gnumeric_tokens, mp_factory);
+
+ parser.set_handler(handler.get());
+ parser.parse();
+ }
+};
+
+orcus_gnumeric::orcus_gnumeric(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::gnumeric),
+ mp_impl(std::make_unique<impl>(factory))
+{
+ mp_impl->m_ns_repo.add_predefined_values(NS_gnumeric_all);
+}
+
+orcus_gnumeric::~orcus_gnumeric()
+{
+}
+
+bool orcus_gnumeric::detect(const unsigned char* buffer, size_t size)
+{
+ // Detect gnumeric format that's already in memory.
+
+ string decompressed;
+ if (!decompress_gzip(reinterpret_cast<const char*>(buffer), size, decompressed))
+ return false;
+
+ if (decompressed.empty())
+ return false;
+
+ // Parse this xml stream for detection.
+ config opt(format_t::gnumeric);
+ xmlns_repository ns_repo;
+ ns_repo.add_predefined_values(NS_gnumeric_all);
+ session_context cxt;
+ xml_stream_parser parser(opt, ns_repo, gnumeric_tokens, &decompressed[0], decompressed.size());
+ gnumeric_detection_handler handler(cxt, gnumeric_tokens);
+ parser.set_handler(&handler);
+
+ try
+ {
+ parser.parse();
+ }
+ catch (const detection_result& res)
+ {
+ return res.get_result();
+ }
+ catch (...) {}
+
+ return false;
+}
+
+void orcus_gnumeric::read_file(std::string_view filepath)
+{
+#if ORCUS_DEBUG_GNUMERIC
+ cout << "reading " << filepath << endl;
+#endif
+
+ file_content content(filepath);
+ if (content.empty())
+ return;
+
+ read_stream(content.str());
+}
+
+void orcus_gnumeric::read_stream(std::string_view stream)
+{
+ if (stream.empty())
+ return;
+
+ std::string file_content;
+ if (!decompress_gzip(stream.data(), stream.size(), file_content))
+ return;
+
+ if (auto* gs = mp_impl->mp_factory->get_global_settings(); gs)
+ {
+ gs->set_origin_date(1899, 12, 30);
+ gs->set_default_formula_grammar(spreadsheet::formula_grammar_t::gnumeric);
+ }
+
+ mp_impl->read_content_xml(file_content, get_config());
+ mp_impl->mp_factory->finalize();
+}
+
+std::string_view orcus_gnumeric::get_name() const
+{
+ return "gnumeric";
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_import_ods.cpp b/src/liborcus/orcus_import_ods.cpp
new file mode 100644
index 0000000..0c73472
--- /dev/null
+++ b/src/liborcus/orcus_import_ods.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_import_ods.hpp"
+
+#include "orcus/xml_namespace.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/config.hpp"
+
+#include "odf_styles_context.hpp"
+#include "odf_tokens.hpp"
+#include "odf_namespace_types.hpp"
+#include "session_context.hpp"
+#include "ods_session_data.hpp"
+
+#include "xml_stream_parser.hpp"
+
+namespace orcus {
+
+void import_ods::read_styles(std::string_view s, spreadsheet::iface::import_styles* styles)
+{
+ if (!styles)
+ return;
+
+ if (s.empty())
+ return;
+
+ session_context cxt{std::make_unique<ods_session_data>()};
+ auto context = std::make_unique<styles_context>(cxt, odf_tokens, styles);
+
+ xml_stream_handler stream_handler(cxt, odf_tokens, std::move(context));
+
+ xmlns_repository ns_repo;
+ ns_repo.add_predefined_values(NS_odf_all);
+
+ orcus::config config(format_t::ods);
+ config.debug = true;
+ xml_stream_parser parser(
+ config, ns_repo, odf_tokens,
+ s.data(), s.size());
+ parser.set_handler(&stream_handler);
+ parser.parse();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_import_xlsx.cpp b/src/liborcus/orcus_import_xlsx.cpp
new file mode 100644
index 0000000..265f419
--- /dev/null
+++ b/src/liborcus/orcus_import_xlsx.cpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_import_xlsx.hpp"
+
+#include "orcus/xml_namespace.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/config.hpp"
+
+#include "xlsx_types.hpp"
+#include "xlsx_handler.hpp"
+#include "ooxml_tokens.hpp"
+
+#include "xml_stream_parser.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "xlsx_session_data.hpp"
+#include "ooxml_global.hpp"
+
+namespace orcus {
+
+void import_xlsx::read_table(
+ std::string_view s,
+ spreadsheet::iface::import_table& table,
+ spreadsheet::iface::import_reference_resolver& resolver)
+{
+ if (s.empty())
+ return;
+
+ session_context cxt;
+ auto handler = std::make_unique<xlsx_table_xml_handler>(cxt, ooxml_tokens, table, resolver);
+
+ xmlns_repository ns_repo;
+ ns_repo.add_predefined_values(NS_ooxml_all);
+ ns_repo.add_predefined_values(NS_opc_all);
+ ns_repo.add_predefined_values(NS_misc_all);
+
+ orcus::config config(format_t::xlsx);
+ xml_stream_parser parser(
+ config, ns_repo, ooxml_tokens,
+ s.data(), s.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_json.cpp b/src/liborcus/orcus_json.cpp
new file mode 100644
index 0000000..9b6195f
--- /dev/null
+++ b/src/liborcus/orcus_json.cpp
@@ -0,0 +1,513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/orcus_json.hpp>
+#include <orcus/json_document_tree.hpp>
+#include <orcus/json_structure_tree.hpp>
+#include <orcus/config.hpp>
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/json_parser.hpp>
+#include <orcus/stream.hpp>
+
+#include "json_map_tree.hpp"
+#include "json_structure_mapper.hpp"
+
+#include <iostream>
+#include <sstream>
+
+namespace orcus {
+
+namespace {
+
+struct json_value
+{
+ enum class value_type { string, numeric, boolean, null };
+
+ value_type type;
+
+ union
+ {
+ struct { const char* p; size_t n; } str;
+ double numeric;
+ bool boolean;
+
+ } value;
+
+ json_value(double v) : type(value_type::numeric)
+ {
+ value.numeric = v;
+ }
+
+ json_value(const char* p, size_t n) : type(value_type::string)
+ {
+ value.str.p = p;
+ value.str.n = n;
+ }
+
+ json_value(bool v) : type(value_type::boolean)
+ {
+ value.boolean = v;
+ }
+
+ json_value(value_type vt) : type(vt) {}
+
+ void commit(spreadsheet::iface::import_factory& im_factory, const cell_position_t& pos) const
+ {
+ spreadsheet::iface::import_sheet* sheet = im_factory.get_sheet(pos.sheet);
+
+ if (!sheet)
+ return;
+
+ switch (type)
+ {
+ case value_type::string:
+ {
+ spreadsheet::iface::import_shared_strings* ss = im_factory.get_shared_strings();
+ if (!ss)
+ break;
+
+ size_t sid = ss->add({value.str.p, value.str.n});
+ sheet->set_string(pos.row, pos.col, sid);
+ break;
+ }
+ case value_type::numeric:
+ sheet->set_value(pos.row, pos.col, value.numeric);
+ break;
+ case value_type::boolean:
+ sheet->set_bool(pos.row, pos.col, value.boolean);
+ break;
+ case value_type::null:
+ break;
+ }
+ }
+};
+
+class json_content_handler
+{
+ json_map_tree::walker m_walker;
+ json_map_tree::node* mp_current_node;
+ json_map_tree::range_reference_type* mp_increment_row;
+
+ struct row_group_scope
+ {
+ json_map_tree::node* node;
+ spreadsheet::row_t row_position;
+
+ row_group_scope(json_map_tree::node* _node, spreadsheet::row_t _row_position) :
+ node(_node), row_position(_row_position) {}
+ };
+
+ /**
+ * Stack of row group nodes, used to keep track of whether or not we are
+ * currently within a linked range.
+ */
+ std::vector<row_group_scope> m_row_group_stack;
+
+ spreadsheet::iface::import_factory& m_im_factory;
+
+public:
+ json_content_handler(const json_map_tree& map_tree, spreadsheet::iface::import_factory& im_factory) :
+ m_walker(map_tree.get_tree_walker()),
+ mp_current_node(nullptr),
+ mp_increment_row(nullptr),
+ m_im_factory(im_factory) {}
+
+ void begin_parse() {}
+ void end_parse() {}
+
+ void begin_array()
+ {
+ push_node(json_map_tree::input_node_type::array);
+ }
+
+ void end_array()
+ {
+ pop_node(json_map_tree::input_node_type::array);
+ }
+
+ void begin_object()
+ {
+ push_node(json_map_tree::input_node_type::object);
+ }
+
+ void object_key(std::string_view key, bool /*transient*/)
+ {
+ m_walker.set_object_key(key.data(), key.size());
+ }
+
+ void end_object()
+ {
+ pop_node(json_map_tree::input_node_type::object);
+ }
+
+ void boolean_true()
+ {
+ push_node(json_map_tree::input_node_type::value);
+ commit_value(true);
+ pop_node(json_map_tree::input_node_type::value);
+ }
+
+ void boolean_false()
+ {
+ push_node(json_map_tree::input_node_type::value);
+ commit_value(false);
+ pop_node(json_map_tree::input_node_type::value);
+ }
+
+ void null()
+ {
+ push_node(json_map_tree::input_node_type::value);
+ commit_value(json_value::value_type::null);
+ pop_node(json_map_tree::input_node_type::value);
+ }
+
+ void string(std::string_view val, bool /*transient*/)
+ {
+ push_node(json_map_tree::input_node_type::value);
+ commit_value(json_value(val.data(), val.size()));
+ pop_node(json_map_tree::input_node_type::value);
+ }
+
+ void number(double val)
+ {
+ push_node(json_map_tree::input_node_type::value);
+ commit_value(val);
+ pop_node(json_map_tree::input_node_type::value);
+ }
+
+private:
+
+ void push_node(json_map_tree::input_node_type nt)
+ {
+ if (!m_row_group_stack.empty() && mp_current_node)
+ {
+ if (mp_current_node->row_group && mp_increment_row == mp_current_node->row_group)
+ {
+ // The last closing node was a row group boundary. Increment the row position.
+ ++mp_current_node->row_group->row_position;
+ mp_increment_row = nullptr;
+ }
+ }
+
+ mp_current_node = m_walker.push_node(nt);
+
+ if (mp_current_node && mp_current_node->row_group)
+ {
+ m_row_group_stack.emplace_back(
+ mp_current_node, mp_current_node->row_group->row_position);
+ }
+ }
+
+ void pop_node(json_map_tree::input_node_type nt)
+ {
+ spreadsheet::row_t row_start = -1;
+ spreadsheet::row_t row_end = -1;
+ json_map_tree::range_reference_type* fill_down_ref = nullptr;
+
+ if (mp_current_node && mp_current_node->row_group)
+ {
+ // We are exiting a row group.
+ assert(!m_row_group_stack.empty());
+ assert(m_row_group_stack.back().node == mp_current_node);
+
+ // Record the current row range for this level.
+ row_start = m_row_group_stack.back().row_position;
+ row_end = mp_current_node->row_group->row_position;
+
+ if (row_end > row_start && m_row_group_stack.size() > 1)
+ {
+ // The current range is longer than 1. We need to perform fill-downs for the parent level.
+ fill_down_ref = mp_current_node->row_group;
+
+ if (fill_down_ref->row_header)
+ {
+ // Account for the row header.
+ ++row_start;
+ ++row_end;
+ }
+ }
+
+ m_row_group_stack.pop_back();
+ }
+
+ mp_current_node = m_walker.pop_node(nt);
+
+ if (!m_row_group_stack.empty())
+ {
+ if (mp_current_node && mp_current_node->row_group)
+ {
+ assert(m_row_group_stack.back().node == mp_current_node);
+ mp_increment_row = mp_current_node->row_group;
+ }
+
+ if (fill_down_ref)
+ {
+ // Perform fill-downs for all anchored fields.
+ const cell_position_t& pos = fill_down_ref->pos;
+ spreadsheet::iface::import_sheet* sheet = m_im_factory.get_sheet(pos.sheet);
+
+ if (sheet)
+ {
+ json_map_tree::node* node = m_row_group_stack.back().node;
+ for (const json_map_tree::node* anchored_field : node->anchored_fields)
+ {
+ spreadsheet::col_t col_offset =
+ anchored_field->value.range_field_ref->column_pos;
+ sheet->fill_down_cells(
+ pos.row + row_start, pos.col + col_offset, row_end - row_start);
+ }
+ }
+ }
+ }
+ }
+
+ void commit_value(const json_value& v)
+ {
+ if (!mp_current_node)
+ return;
+
+ switch (mp_current_node->type)
+ {
+ case json_map_tree::map_node_type::cell_ref:
+ {
+ // Single cell reference
+ v.commit(m_im_factory, mp_current_node->value.cell_ref->pos);
+ break;
+ }
+ case json_map_tree::map_node_type::range_field_ref:
+ {
+ // Range field reference. Offset from the origin before
+ // pushing the value.
+ spreadsheet::col_t col_offset = mp_current_node->value.range_field_ref->column_pos;
+ json_map_tree::range_reference_type* ref = mp_current_node->value.range_field_ref->ref;
+
+ cell_position_t pos = ref->pos; // copy
+ pos.col += col_offset;
+ pos.row += ref->row_position;
+ if (ref->row_header)
+ ++pos.row; // Account for the row header.
+
+ v.commit(m_im_factory, pos);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+};
+
+} // anonymous namespace
+
+struct orcus_json::impl
+{
+ spreadsheet::iface::import_factory* im_factory;
+ spreadsheet::sheet_t sheet_count;
+ json_map_tree map_tree;
+
+ impl(spreadsheet::iface::import_factory* _im_factory) :
+ im_factory(_im_factory), sheet_count(0) {}
+};
+
+orcus_json::orcus_json(spreadsheet::iface::import_factory* im_fact) :
+ mp_impl(std::make_unique<impl>(im_fact)) {}
+
+orcus_json::~orcus_json() {}
+
+void orcus_json::set_cell_link(std::string_view path, std::string_view sheet, spreadsheet::row_t row, spreadsheet::col_t col)
+{
+ mp_impl->map_tree.set_cell_link(path, cell_position_t(sheet, row, col));
+}
+
+void orcus_json::start_range(std::string_view sheet, spreadsheet::row_t row, spreadsheet::col_t col, bool row_header)
+{
+ mp_impl->map_tree.start_range(cell_position_t(sheet, row, col), row_header);
+}
+
+void orcus_json::append_field_link(std::string_view path, std::string_view label)
+{
+ mp_impl->map_tree.append_field_link(path, label);
+}
+
+void orcus_json::set_range_row_group(std::string_view path)
+{
+ mp_impl->map_tree.set_range_row_group(path);
+}
+
+void orcus_json::commit_range()
+{
+ mp_impl->map_tree.commit_range();
+}
+
+void orcus_json::append_sheet(std::string_view name)
+{
+ if (name.empty())
+ return;
+
+ mp_impl->im_factory->append_sheet(mp_impl->sheet_count++, name);
+}
+
+void orcus_json::read_stream(std::string_view stream)
+{
+ if (!mp_impl->im_factory)
+ return;
+
+ spreadsheet::iface::import_shared_strings* ss = mp_impl->im_factory->get_shared_strings();
+ if (!ss)
+ return;
+
+ // Insert range headers first (if applicable).
+ for (const auto& entry : mp_impl->map_tree.get_range_references())
+ {
+ const json_map_tree::range_reference_type& ref = entry.second;
+ if (!ref.row_header)
+ // This range does not use row header.
+ continue;
+
+ const cell_position_t& origin = ref.pos;
+
+ spreadsheet::iface::import_sheet* sheet = mp_impl->im_factory->get_sheet(origin.sheet);
+
+ if (!sheet)
+ continue;
+
+ for (const json_map_tree::range_field_reference_type* field : ref.fields)
+ {
+ cell_position_t pos = origin;
+ pos.col += field->column_pos;
+ size_t sid = ss->add(field->label);
+ sheet->set_string(pos.row, pos.col, sid);
+ }
+ }
+
+ json_content_handler hdl(mp_impl->map_tree, *mp_impl->im_factory);
+ json_parser<json_content_handler> parser(stream, hdl);
+ parser.parse();
+
+ mp_impl->im_factory->finalize();
+}
+
+void orcus_json::read_map_definition(std::string_view stream)
+{
+ try
+ {
+ // Since a typical map file will likely be very small, let's be lazy and
+ // load the whole thing into a in-memory tree.
+ json::document_tree map_doc;
+ json_config jc;
+ jc.preserve_object_order = false;
+ jc.persistent_string_values = false;
+ jc.resolve_references = false;
+
+ map_doc.load(stream, jc);
+ json::const_node root = map_doc.get_document_root();
+
+ // Create sheets first.
+
+ if (!root.has_key("sheets"))
+ throw json_structure_error("The map definition must contains 'sheets' section.");
+
+ for (const json::const_node& node_name : root.child("sheets"))
+ append_sheet(node_name.string_value());
+
+ if (root.has_key("cells"))
+ {
+ // Set cell links.
+ for (const json::const_node& link_node : root.child("cells"))
+ {
+ std::string_view path = link_node.child("path").string_value();
+ std::string_view sheet = link_node.child("sheet").string_value();
+ spreadsheet::row_t row = link_node.child("row").numeric_value();
+ spreadsheet::col_t col = link_node.child("column").numeric_value();
+
+ set_cell_link(path, sheet, row, col);
+ }
+ }
+
+ if (root.has_key("ranges"))
+ {
+ // Set range links.
+ for (const json::const_node& link_node : root.child("ranges"))
+ {
+ std::string_view sheet = link_node.child("sheet").string_value();
+ spreadsheet::row_t row = link_node.child("row").numeric_value();
+ spreadsheet::col_t col = link_node.child("column").numeric_value();
+
+ bool row_header = link_node.has_key("row-header") && link_node.child("row-header").type() == json::node_t::boolean_true;
+
+ start_range(sheet, row, col, row_header);
+
+ for (const json::const_node& field_node : link_node.child("fields"))
+ {
+ std::string_view path = field_node.child("path").string_value();
+ std::string_view label;
+ if (field_node.has_key("label"))
+ {
+ json::const_node label_node = field_node.child("label");
+ if (label_node.type() == json::node_t::string)
+ label = label_node.string_value();
+ }
+
+ append_field_link(path, label);
+ }
+
+ for (const json::const_node& rg_node : link_node.child("row-groups"))
+ {
+ std::string_view path = rg_node.child("path").string_value();
+ set_range_row_group(path);
+ }
+
+ commit_range();
+ }
+ }
+ }
+ catch (const parse_error& e)
+ {
+ std::ostringstream os;
+ os << "Error parsing the map definition file:" << std::endl
+ << std::endl
+ << create_parse_error_output(stream, e.offset()) << std::endl
+ << e.what();
+
+ throw invalid_map_error(os.str());
+ }
+}
+
+void orcus_json::detect_map_definition(std::string_view stream)
+{
+ size_t range_count = 0;
+ std::string sheet_name_prefix = "range-";
+
+ json::structure_tree::range_handler_type rh = [&](json::table_range_t&& range)
+ {
+ // Build sheet name first and insert a new sheet.
+ std::ostringstream os_sheet_name;
+ os_sheet_name << sheet_name_prefix << range_count;
+ std::string sheet_name = os_sheet_name.str();
+ append_sheet(sheet_name);
+
+ // Push the linked range.
+ start_range(sheet_name, 0, 0, true);
+
+ for (const std::string& s : range.paths)
+ append_field_link(s, std::string_view());
+
+ for (const std::string& s : range.row_groups)
+ set_range_row_group(s);
+
+ commit_range();
+
+ ++range_count;
+ };
+
+ json::structure_tree structure;
+ structure.parse(stream);
+ structure.process_ranges(rh);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_ods.cpp b/src/liborcus/orcus_ods.cpp
new file mode 100644
index 0000000..41acf65
--- /dev/null
+++ b/src/liborcus/orcus_ods.cpp
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/orcus_ods.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <orcus/zip_archive.hpp>
+#include <orcus/zip_archive_stream.hpp>
+#include <orcus/measurement.hpp>
+
+#include "xml_stream_parser.hpp"
+#include "ods_content_xml_context.hpp"
+#include "ods_session_data.hpp"
+#include "odf_document_styles_context.hpp"
+#include "odf_tokens.hpp"
+#include "odf_styles.hpp"
+#include "odf_namespace_types.hpp"
+#include "session_context.hpp"
+
+#include <cstdlib>
+#include <iostream>
+#include <vector>
+#include <cstring>
+
+namespace orcus {
+
+struct orcus_ods::impl
+{
+ xmlns_repository ns_repo;
+ session_context cxt;
+ spreadsheet::iface::import_factory* xfactory;
+
+ impl(spreadsheet::iface::import_factory* im_factory) :
+ cxt(std::make_unique<ods_session_data>()), xfactory(im_factory) {}
+};
+
+orcus_ods::orcus_ods(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::ods),
+ mp_impl(std::make_unique<impl>(factory))
+{
+ mp_impl->ns_repo.add_predefined_values(NS_odf_all);
+}
+
+orcus_ods::~orcus_ods() = default;
+
+void orcus_ods::list_content(const zip_archive& archive)
+{
+ size_t num = archive.get_file_entry_count();
+ std::cout << "number of files this archive contains: " << num << std::endl;
+
+ for (size_t i = 0; i < num; ++i)
+ {
+ std::string_view filename = archive.get_file_entry_name(i);
+ if (filename.empty())
+ std::cout << "(empty)" << std::endl;
+ else
+ std::cout << filename << std::endl;
+ }
+}
+
+void orcus_ods::read_styles(const zip_archive& archive)
+{
+ auto* xstyles = mp_impl->xfactory->get_styles();
+ if (!xstyles)
+ return;
+
+ std::vector<unsigned char> buf;
+
+ try
+ {
+ buf = archive.read_file_entry("styles.xml");
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "failed to get stat on styles.xml (reason: " << e.what() << ")" << std::endl;
+ return;
+ }
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->ns_repo, odf_tokens,
+ reinterpret_cast<const char*>(buf.data()), buf.size());
+
+ auto& ods_data = mp_impl->cxt.get_data<ods_session_data>();
+ auto context = std::make_unique<document_styles_context>(
+ mp_impl->cxt, odf_tokens, ods_data.styles_map, xstyles);
+
+ xml_stream_handler handler(mp_impl->cxt, odf_tokens, std::move(context));
+
+ parser.set_handler(&handler);
+ parser.parse();
+
+ if (get_config().debug)
+ dump_state(ods_data.styles_map, std::cout);
+}
+
+void orcus_ods::read_content(const zip_archive& archive)
+{
+ std::vector<unsigned char> buf;
+
+ try
+ {
+ buf = archive.read_file_entry("content.xml");
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "failed to get stat on content.xml (reason: " << e.what() << ")" << std::endl;
+ return;
+ }
+
+ read_content_xml(buf.data(), buf.size());
+}
+
+void orcus_ods::read_content_xml(const unsigned char* p, size_t size)
+{
+ bool use_threads = true;
+
+ if (const char* p_env = std::getenv("ORCUS_ODS_USE_THREADS"); p_env)
+ use_threads = to_bool(p_env);
+
+ auto context = std::make_unique<ods_content_xml_context>(
+ mp_impl->cxt, odf_tokens, mp_impl->xfactory);
+
+ if (use_threads)
+ {
+ threaded_xml_stream_parser parser(
+ get_config(), mp_impl->ns_repo, odf_tokens,
+ reinterpret_cast<const char*>(p), size);
+
+ xml_stream_handler handler(mp_impl->cxt, odf_tokens, std::move(context));
+ parser.set_handler(&handler);
+ parser.parse();
+
+ string_pool this_pool;
+ parser.swap_string_pool(this_pool);
+ mp_impl->cxt.spool.merge(this_pool);
+ }
+ else
+ {
+ xml_stream_parser parser(
+ get_config(), mp_impl->ns_repo, odf_tokens,
+ reinterpret_cast<const char*>(p), size);
+
+ xml_stream_handler handler(mp_impl->cxt, odf_tokens, std::move(context));
+ parser.set_handler(&handler);
+ parser.parse();
+ }
+}
+
+bool orcus_ods::detect(const unsigned char* blob, size_t size)
+{
+ zip_archive_stream_blob stream(blob, size);
+ zip_archive archive(&stream);
+
+ try
+ {
+ archive.load();
+
+ std::vector<unsigned char> buf = archive.read_file_entry("mimetype");
+
+ if (buf.empty())
+ // mimetype is empty.
+ return false;
+
+ const char* mimetype = "application/vnd.oasis.opendocument.spreadsheet";
+ size_t n = std::strlen(mimetype);
+ if (buf.size() < n)
+ return false;
+
+ if (strncmp(mimetype, reinterpret_cast<const char*>(buf.data()), n))
+ // The mimetype content differs.
+ return false;
+ }
+ catch (const zip_error&)
+ {
+ // Not a valid zip archive.
+ return false;
+ }
+
+ return true;
+}
+
+void orcus_ods::read_file(std::string_view filepath)
+{
+ zip_archive_stream_fd stream(std::string{filepath}.c_str());
+ read_file_impl(&stream);
+}
+
+void orcus_ods::read_stream(std::string_view stream)
+{
+ zip_archive_stream_blob blob(
+ reinterpret_cast<const uint8_t*>(stream.data()), stream.size());
+ read_file_impl(&blob);
+}
+
+void orcus_ods::read_file_impl(zip_archive_stream* stream)
+{
+ zip_archive archive(stream);
+ archive.load();
+ if (get_config().debug)
+ list_content(archive);
+
+ spreadsheet::formula_grammar_t old_grammar = spreadsheet::formula_grammar_t::unknown;
+
+ spreadsheet::iface::import_global_settings* gs = mp_impl->xfactory->get_global_settings();
+ if (gs)
+ {
+ old_grammar = gs->get_default_formula_grammar();
+ gs->set_default_formula_grammar(spreadsheet::formula_grammar_t::ods);
+ }
+
+ read_styles(archive);
+ read_content(archive);
+
+ mp_impl->xfactory->finalize();
+
+ if (gs)
+ // This grammar will be used
+ gs->set_default_formula_grammar(old_grammar);
+}
+
+std::string_view orcus_ods::get_name() const
+{
+ return "ods";
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_parquet.cpp b/src/liborcus/orcus_parquet.cpp
new file mode 100644
index 0000000..2bd85ac
--- /dev/null
+++ b/src/liborcus/orcus_parquet.cpp
@@ -0,0 +1,547 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/orcus_parquet.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/config.hpp>
+#include <orcus/spreadsheet/types.hpp>
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#include <arrow/io/file.h>
+#include <arrow/io/memory.h>
+#include <parquet/stream_reader.h>
+#include <parquet/arrow/reader.h>
+#pragma GCC diagnostic pop
+
+#include "filesystem_env.hpp"
+
+#include <iostream>
+#include <unordered_map>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+class orcus_parquet::impl
+{
+ using columns_type = std::vector<std::pair<ss::col_t, const parquet::ColumnDescriptor*>>;
+
+ const config& m_config;
+
+ ss::iface::import_factory* m_factory = nullptr;
+ ss::iface::import_shared_strings* m_sstrings = nullptr;
+ ss::iface::import_sheet* m_sheet = nullptr;
+
+ columns_type m_columns;
+
+ parquet::StreamReader m_stream;
+
+ static columns_type init_columns(const parquet::FileMetaData& file_md)
+ {
+ columns_type columns;
+
+ const parquet::SchemaDescriptor* schema_desc = file_md.schema();
+
+ if (!schema_desc)
+ return columns;
+
+ columns.reserve(schema_desc->num_columns());
+
+ for (int i = 0; i < schema_desc->num_columns(); ++i)
+ {
+ const parquet::ColumnDescriptor* col_desc = schema_desc->Column(i);
+ columns.emplace_back(i, col_desc);
+ }
+
+ return columns;
+ }
+
+ void warn(std::string_view msg) const
+ {
+ if (!m_config.debug)
+ return;
+
+ std::cerr << "warning: " << msg << std::endl;
+ }
+
+ /**
+ * Import column labels as the first row.
+ */
+ void import_column_labels()
+ {
+ // Import column labels as first row
+ for (const auto& [col, p] : m_columns)
+ {
+ if (!m_sstrings)
+ continue;
+
+ std::size_t si = m_sstrings->add(p->name());
+ m_sheet->set_string(0, col, si);
+ }
+ }
+
+ template<typename T>
+ std::optional<T> read_or_warn(ss::row_t row, ss::col_t col)
+ {
+ T v;
+
+ try
+ {
+ m_stream >> v;
+ return v;
+ }
+ catch (const std::exception& e)
+ {
+ std::ostringstream os;
+ os << "failed to read a value for (row=" << row << "; col=" << col << "): " << e.what();
+ warn(os.str());
+ }
+
+ return std::optional<T>{};
+ }
+
+ void import_byte_array(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ switch (p->converted_type())
+ {
+ case parquet::ConvertedType::UTF8:
+ {
+ if (!m_sstrings)
+ {
+ m_stream.SkipColumns(1);
+ break;
+ }
+
+ if (auto v = read_or_warn<std::string>(row, col); v)
+ {
+ std::size_t si = m_sstrings->add(*v);
+ m_sheet->set_string(row, col, si);
+ }
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os << "WIP: unhandled converted type for BYTE_ARRAY (converted="
+ << p->converted_type() << ")";
+ warn(os.str());
+ m_stream.SkipColumns(1);
+ }
+ }
+ }
+
+ void import_fixed_len_byte_array(ss::row_t /*row*/, ss::col_t /*col*/, const parquet::ColumnDescriptor* /*p*/)
+ {
+ warn("WIP: physical=FIXED_LEN_BYTE_ARRAY not handled yet");
+ m_stream.SkipColumns(1);
+ }
+
+ void import_int32(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ switch (p->converted_type())
+ {
+ case parquet::ConvertedType::NONE:
+ {
+ if (auto v = read_or_warn<int32_t>(row, col); v)
+ m_sheet->set_value(row, col, *v);
+ break;
+ }
+ default:
+ warn("WIP: unhandled converted type for INT32");
+ m_stream.SkipColumns(1);
+ }
+ }
+
+ void import_int64(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ switch (p->converted_type())
+ {
+ case parquet::ConvertedType::NONE:
+ {
+ if (auto v = read_or_warn<int64_t>(row, col); v)
+ m_sheet->set_value(row, col, *v);
+ break;
+ }
+ default:
+ warn("WIP: unhandled converted type for INT64");
+ m_stream.SkipColumns(1);
+ }
+ }
+
+ void import_int96(ss::row_t /*row*/, ss::col_t /*col*/, const parquet::ColumnDescriptor* /*p*/)
+ {
+ warn("WIP: physical=INT96 not handled yet");
+ m_stream.SkipColumns(1);
+ }
+
+ void import_boolean(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ if (p->converted_type() != parquet::ConvertedType::NONE)
+ {
+ warn("WIP: unhandled covnerted type for BOOLEAN");
+ m_stream.SkipColumns(1);
+ return;
+ }
+
+ if (auto v = read_or_warn<bool>(row, col); v)
+ m_sheet->set_bool(row, col, *v);
+ }
+
+ void import_float(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ if (p->converted_type() != parquet::ConvertedType::NONE)
+ {
+ warn("WIP: unhandled covnerted type for FLOAT");
+ m_stream.SkipColumns(1);
+ return;
+ }
+
+ if (auto v = read_or_warn<float>(row, col); v)
+ m_sheet->set_value(row, col, *v);
+ }
+
+ void import_double(ss::row_t row, ss::col_t col, const parquet::ColumnDescriptor* p)
+ {
+ if (p->converted_type() != parquet::ConvertedType::NONE)
+ {
+ warn("WIP: unhandled covnerted type for DOUBLE");
+ m_stream.SkipColumns(1);
+ return;
+ }
+
+ if (auto v = read_or_warn<double>(row, col); v)
+ m_sheet->set_value(row, col, *v);
+ }
+
+ void dump_metadata(const parquet::FileMetaData& metadata) const
+ {
+ if (!m_config.debug)
+ return;
+
+ auto _bool_v = [](bool v) { return v ? "true" : "false"; };
+
+ auto _version_v = [](parquet::ParquetVersion::type t) -> std::string
+ {
+ const std::unordered_map<parquet::ParquetVersion::type, std::string_view> mapping =
+ {
+ { parquet::ParquetVersion::PARQUET_1_0, "PARQUET_1_0" },
+ { parquet::ParquetVersion::PARQUET_2_4, "PARQUET_2_4" },
+ { parquet::ParquetVersion::PARQUET_2_6, "PARQUET_2_6" },
+ };
+
+ std::ostringstream os;
+ auto it = mapping.find(t);
+ os << (it == mapping.end() ? "???" : it->second) << " (" << int(t) << ")";
+ return os.str();
+ };
+
+ auto _compression_v = [](parquet::Compression::type t) -> std::string
+ {
+ const std::unordered_map<parquet::Compression::type, std::string_view> mapping =
+ {
+ { parquet::Compression::UNCOMPRESSED, "UNCOMPRESSED" },
+ { parquet::Compression::SNAPPY, "SNAPPY" },
+ { parquet::Compression::GZIP, "GZIP" },
+ { parquet::Compression::BROTLI, "BROTLI" },
+ { parquet::Compression::ZSTD, "ZSTD" },
+ { parquet::Compression::LZ4, "LZ4" },
+ { parquet::Compression::LZ4_FRAME, "LZ4_FRAME" },
+ { parquet::Compression::LZO, "LZO" },
+ { parquet::Compression::BZ2, "BZ2" },
+ { parquet::Compression::LZ4_HADOOP, "LZ4_HADOOP" },
+ };
+
+ std::ostringstream os;
+ auto it = mapping.find(t);
+ os << (it == mapping.end() ? "???" : it->second) << " (" << int(t) << ")";
+ return os.str();
+ };
+
+ std::cerr << "metadata size: " << metadata.size() << std::endl;
+ std::cerr << "version: " << _version_v(metadata.version()) << std::endl;
+ std::cerr << "created by: " << metadata.created_by() << std::endl;
+ std::cerr << "num columns: " << metadata.num_columns() << std::endl;
+ std::cerr << "num rows: " << metadata.num_rows() << std::endl;
+ std::cerr << "num row groups: " << metadata.num_row_groups() << std::endl;
+ std::cerr << "num schema elements: " << metadata.num_schema_elements() << std::endl;
+ std::cerr << "can decompress: " << _bool_v(metadata.can_decompress()) << std::endl;
+
+ for (int i = 0; i < metadata.num_row_groups(); ++i)
+ {
+ std::cerr << "row group " << i << ":" << std::endl;
+ auto rg = metadata.RowGroup(i);
+ std::cerr << " num rows: " << rg->num_rows() << std::endl;
+ std::cerr << " total byte size: " << rg->total_byte_size() << std::endl;
+ std::cerr << " total compressed size: " << rg->total_compressed_size() << std::endl;
+ std::cerr << " file offset: " << rg->file_offset() << std::endl;
+ std::cerr << " num columns: " << rg->num_columns() << std::endl;
+
+ for (int j = 0; j < rg->num_columns(); ++j)
+ {
+ std::cerr << " column chunk " << j << ":" << std::endl;
+ auto cc = rg->ColumnChunk(j);
+ std::cerr << " file path: " << cc->file_path() << std::endl;
+ std::cerr << " num values: " << cc->num_values() << std::endl;
+ std::cerr << " type: " << cc->type() << std::endl;
+ std::cerr << " data page offset: " << std::dec << cc->data_page_offset() << std::endl;
+ std::cerr << " compression: " << _compression_v(cc->compression()) << std::endl;
+ std::cerr << " has dictionary page: " << _bool_v(cc->has_dictionary_page()) << std::endl;
+
+ if (cc->has_dictionary_page())
+ std::cerr << " dictionary page offset: " << cc->dictionary_page_offset() << std::endl;
+
+ std::cerr << " has index page: " << _bool_v(cc->has_index_page()) << std::endl;
+ if (cc->has_index_page())
+ std::cerr << " index page offset: " << cc->index_page_offset() << std::endl;
+ }
+ }
+
+ if (const parquet::SchemaDescriptor* schema_desc = metadata.schema(); schema_desc)
+ {
+ std::cerr << "schema:" << std::endl;
+ std::cerr << " name: " << schema_desc->name() << std::endl;
+ std::cerr << " num columns: " << schema_desc->num_columns() << std::endl;
+
+ for (int i = 0; i < schema_desc->num_columns(); ++i)
+ {
+ if (const parquet::ColumnDescriptor* col_desc = schema_desc->Column(i); col_desc)
+ {
+ std::cerr << " column " << i << ":" << std::endl;
+ std::cerr << " name: " << col_desc->name() << std::endl;
+ std::cerr << " physical type: " << col_desc->physical_type() << std::endl;
+ std::cerr << " converted type: " << col_desc->converted_type() << std::endl;
+ std::cerr << " type length: " << col_desc->type_length() << std::endl;
+ }
+ }
+ }
+ }
+
+ /**
+ * Check to see if this file is safe to load. There are some conditions
+ * that are known to lead to trouble if we proceed to load.
+ */
+ bool is_safe_to_load(const parquet::FileMetaData& metadata) const
+ {
+ const parquet::SchemaDescriptor* schema = metadata.schema();
+ if (!schema)
+ return false;
+
+ const auto* gnode = schema->group_node();
+ if (!gnode)
+ return false;
+
+ if (schema->group_node()->field_count() != schema->num_columns())
+ // StreamReader assumes these two values to be equal, and crashes
+ // if not. But with some files the two can be different.
+ return false;
+
+ return true;
+ }
+
+ void read_stream_with_sheet_name(std::string_view sheet_name, std::string_view stream)
+ {
+ auto buf = std::make_shared<arrow::io::BufferReader>(stream);
+
+ auto file_reader = parquet::ParquetFileReader::Open(buf);
+ if (!file_reader)
+ {
+ warn("failed to open a parquet file reader from an in-memory buffer.");
+ return;
+ }
+
+ auto file_md = file_reader->metadata();
+
+ dump_metadata(*file_md);
+
+ if (!is_safe_to_load(*file_md))
+ {
+ warn("aborting because this file exhibits a condition known to lead to issues if loaded.");
+ return;
+ }
+
+ if (file_md->num_rows() < 0 || file_md->num_columns() < 0)
+ // Nothing to import. Bail out.
+ return;
+
+ m_sheet = m_factory->append_sheet(0, sheet_name);
+
+ if (!m_sheet)
+ // Failed to append sheet. Bail out.
+ return;
+
+ m_columns = init_columns(*file_md);
+ if (m_columns.empty())
+ // Column data initialization failed. Bail out.
+ return;
+
+ m_stream = parquet::StreamReader{std::move(file_reader)};
+ if (m_stream.eof())
+ return;
+
+ m_sstrings = m_factory->get_shared_strings();
+
+ import_column_labels();
+
+ for (int i = 0; i < file_md->num_rows(); ++i)
+ {
+ ss::row_t row = i + 1; // account for the header row
+
+ for (const auto& [col, p] : m_columns)
+ {
+ switch (p->physical_type())
+ {
+ case parquet::Type::BOOLEAN:
+ {
+ import_boolean(row, col, p);
+ break;
+ }
+ case parquet::Type::INT32:
+ {
+ import_int32(row, col, p);
+ break;
+ }
+ case parquet::Type::INT64:
+ {
+ import_int64(row, col, p);
+ break;
+ }
+ case parquet::Type::INT96:
+ {
+ import_int96(row, col, p);
+ break;
+ }
+ case parquet::Type::FLOAT:
+ {
+ import_float(row, col, p);
+ break;
+ }
+ case parquet::Type::DOUBLE:
+ {
+ import_double(row, col, p);
+ break;
+ }
+ case parquet::Type::BYTE_ARRAY:
+ {
+ import_byte_array(row, col, p);
+ break;
+ }
+ case parquet::Type::FIXED_LEN_BYTE_ARRAY:
+ {
+ import_fixed_len_byte_array(row, col, p);
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os << "WIP: type not handled: physical=" << p->physical_type() << "; converted=" << p->converted_type();
+ warn(os.str());
+ m_stream.SkipColumns(1);
+ }
+ }
+ }
+
+ m_stream >> parquet::EndRow;
+ }
+
+ m_factory->finalize();
+ }
+
+public:
+ impl(const config& c, ss::iface::import_factory* factory) : m_config(c), m_factory(factory) {}
+
+ void read_file(fs::path filepath)
+ {
+ file_content fc(filepath.string());
+ try
+ {
+ read_stream_with_sheet_name(filepath.stem().string(), fc.str());
+ }
+ catch (const std::exception& e)
+ {
+ warn(e.what());
+ m_factory->finalize();
+ }
+ }
+
+ void read_stream(std::string_view stream)
+ {
+ try
+ {
+ read_stream_with_sheet_name("Data", stream);
+ }
+ catch (const std::exception& e)
+ {
+ warn(e.what());
+ m_factory->finalize();
+ }
+ }
+};
+
+orcus_parquet::orcus_parquet(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::parquet),
+ mp_impl(std::make_unique<impl>(get_config(), factory))
+{
+}
+
+orcus_parquet::~orcus_parquet() = default;
+
+bool orcus_parquet::detect(const unsigned char* blob, std::size_t size)
+{
+ if (size < 12u)
+ // At minimum header magic bytes (4), footer magic bytes (4), and the
+ // footer metadata length (4).
+ return false;
+
+ const auto* p = blob;
+
+ // Check the first 4 bytes.
+ if (std::string_view(reinterpret_cast<const char*>(p), 4) != "PAR1")
+ return false;
+
+ // Check the last 4 bytes.
+ p += size - 4u;
+ if (std::string_view(reinterpret_cast<const char*>(p), 4) != "PAR1")
+ return false;
+
+ // Check the footer metadata size (little endian)
+ p -= 1u;
+ std::uint32_t footer_size = *p--;
+ footer_size <<= 8;
+ footer_size |= *p--;
+ footer_size <<= 8;
+ footer_size |= *p--;
+ footer_size <<= 8;
+ footer_size |= *p;
+
+ p -= footer_size;
+ if (p <= blob)
+ // footer metadata position must be within the stream.
+ return false;
+
+ return true;
+}
+
+void orcus_parquet::read_file(std::string_view filepath)
+{
+ mp_impl->read_file(fs::path{std::string{filepath}});
+}
+
+void orcus_parquet::read_stream(std::string_view stream)
+{
+ mp_impl->read_stream(stream);
+}
+
+std::string_view orcus_parquet::get_name() const
+{
+ return "parquet";
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xls_xml.cpp b/src/liborcus/orcus_xls_xml.cpp
new file mode 100644
index 0000000..b37f9c5
--- /dev/null
+++ b/src/liborcus/orcus_xls_xml.cpp
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_xls_xml.hpp"
+#include "orcus/stream.hpp"
+#include "orcus/xml_namespace.hpp"
+#include "orcus/config.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/parser_base.hpp"
+
+#include "xml_stream_parser.hpp"
+#include "xls_xml_handler.hpp"
+#include "xls_xml_detection_handler.hpp"
+#include "session_context.hpp"
+#include "xls_xml_tokens.hpp"
+#include "xls_xml_namespace_types.hpp"
+#include "detection_result.hpp"
+
+#include <iostream>
+#include <locale>
+#include <codecvt>
+
+using namespace std;
+
+namespace orcus {
+
+struct orcus_xls_xml::impl
+{
+ xmlns_repository m_ns_repo;
+ session_context m_cxt;
+ spreadsheet::iface::import_factory* mp_factory;
+
+ impl(spreadsheet::iface::import_factory* factory) : mp_factory(factory) {}
+
+ void read_stream(const char* content, size_t len, const config& cnf)
+ {
+ if (!content || !len)
+ return;
+
+ spreadsheet::iface::import_global_settings* gs =
+ mp_factory->get_global_settings();
+
+ if (!gs)
+ return;
+
+ gs->set_origin_date(1899, 12, 30);
+ gs->set_default_formula_grammar(spreadsheet::formula_grammar_t::xls_xml);
+
+ xml_stream_parser parser(cnf, m_ns_repo, xls_xml_tokens, content, len);
+
+ auto handler = std::make_unique<xls_xml_handler>(m_cxt, xls_xml_tokens, mp_factory);
+
+ parser.set_handler(handler.get());
+ try
+ {
+ parser.parse();
+ }
+ catch (const parse_error& e)
+ {
+ std::cerr << create_parse_error_output(std::string_view(content, len), e.offset()) << std::endl;
+ std::cerr << e.what() << std::endl;
+ return;
+ }
+
+ mp_factory->finalize();
+ }
+};
+
+orcus_xls_xml::orcus_xls_xml(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::xls_xml),
+ mp_impl(std::make_unique<impl>(factory))
+{
+ mp_impl->m_ns_repo.add_predefined_values(NS_xls_xml_all);
+}
+
+orcus_xls_xml::~orcus_xls_xml() = default;
+
+bool orcus_xls_xml::detect(const unsigned char* buffer, size_t size)
+{
+ memory_content mem_content({reinterpret_cast<const char*>(buffer), size});
+ mem_content.convert_to_utf8();
+
+ config opt(format_t::xls_xml);
+ xmlns_repository ns_repo;
+ ns_repo.add_predefined_values(NS_xls_xml_all);
+ xml_stream_parser parser(opt, ns_repo, xls_xml_tokens, mem_content.data(), mem_content.size());
+
+ session_context cxt;
+ xls_xml_detection_handler handler(cxt, xls_xml_tokens);
+ parser.set_handler(&handler);
+ try
+ {
+ parser.parse();
+ }
+ catch (const detection_result& res)
+ {
+ return res.get_result();
+ }
+ catch (...) {}
+
+ return false;
+}
+
+void orcus_xls_xml::read_file(std::string_view filepath)
+{
+ file_content content(filepath.data());
+ if (content.empty())
+ return;
+
+ content.convert_to_utf8();
+ mp_impl->read_stream(content.data(), content.size(), get_config());
+}
+
+void orcus_xls_xml::read_stream(std::string_view stream)
+{
+ memory_content mem_content(stream);
+ if (mem_content.empty())
+ return;
+
+ mem_content.convert_to_utf8();
+ mp_impl->read_stream(mem_content.data(), mem_content.size(), get_config());
+}
+
+std::string_view orcus_xls_xml::get_name() const
+{
+ return "xls-xml";
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xlsx.cpp b/src/liborcus/orcus_xlsx.cpp
new file mode 100644
index 0000000..db55dd2
--- /dev/null
+++ b/src/liborcus/orcus_xlsx.cpp
@@ -0,0 +1,824 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_xlsx.hpp"
+
+#include "orcus/xml_namespace.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/exception.hpp"
+#include "orcus/config.hpp"
+#include "orcus/measurement.hpp"
+
+#include "xlsx_types.hpp"
+#include "xlsx_handler.hpp"
+#include "xlsx_shared_strings_context.hpp"
+#include "xlsx_styles_context.hpp"
+#include "xlsx_workbook_context.hpp"
+#include "xlsx_revision_context.hpp"
+#include "ooxml_tokens.hpp"
+
+#include "xml_stream_parser.hpp"
+#include "xml_simple_stream_handler.hpp"
+#include "opc_reader.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "xlsx_session_data.hpp"
+#include "opc_context.hpp"
+#include "ooxml_global.hpp"
+#include "spreadsheet_iface_util.hpp"
+#include "ooxml_content_types.hpp"
+
+#include <cstdlib>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <cstring>
+#include <sstream>
+
+using namespace std;
+
+namespace orcus {
+
+class xlsx_opc_handler : public opc_reader::part_handler
+{
+ orcus_xlsx& m_parent;
+public:
+ xlsx_opc_handler(orcus_xlsx& parent) : m_parent(parent) {}
+ virtual ~xlsx_opc_handler() {}
+
+ virtual bool handle_part(
+ schema_t type, const std::string& dir_path, const std::string& file_name, opc_rel_extra* data)
+ {
+ if (type == SCH_od_rels_office_doc)
+ {
+ m_parent.read_workbook(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_worksheet)
+ {
+ m_parent.read_sheet(dir_path, file_name, static_cast<xlsx_rel_sheet_info*>(data));
+ return true;
+ }
+ else if (type == SCH_od_rels_shared_strings)
+ {
+ m_parent.read_shared_strings(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_styles)
+ {
+ m_parent.read_styles(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_drawing)
+ {
+ m_parent.read_drawing(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_table)
+ {
+ m_parent.read_table(dir_path, file_name, static_cast<xlsx_rel_table_info*>(data));
+ return true;
+ }
+ else if (type == SCH_od_rels_pivot_cache_def)
+ {
+ m_parent.read_pivot_cache_def(
+ dir_path, file_name, static_cast<xlsx_rel_pivot_cache_info*>(data));
+ return true;
+ }
+ else if (type == SCH_od_rels_pivot_cache_rec)
+ {
+ m_parent.read_pivot_cache_rec(
+ dir_path, file_name,
+ static_cast<const xlsx_rel_pivot_cache_record_info*>(data));
+ return true;
+ }
+ else if (type == SCH_od_rels_pivot_table)
+ {
+ m_parent.read_pivot_table(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_rev_headers)
+ {
+ m_parent.read_rev_headers(dir_path, file_name);
+ return true;
+ }
+ else if (type == SCH_od_rels_rev_log)
+ {
+ m_parent.read_rev_log(dir_path, file_name);
+ return true;
+ }
+
+ return false;
+ }
+};
+
+struct orcus_xlsx::impl
+{
+ session_context m_cxt;
+ xmlns_repository m_ns_repo;
+ spreadsheet::iface::import_factory* mp_factory;
+ xlsx_opc_handler m_opc_handler;
+ opc_reader m_opc_reader;
+
+ impl(spreadsheet::iface::import_factory* factory, orcus_xlsx& parent) :
+ m_cxt(std::make_unique<xlsx_session_data>()),
+ mp_factory(factory),
+ m_opc_handler(parent),
+ m_opc_reader(parent.get_config(), m_ns_repo, m_cxt, m_opc_handler) {}
+};
+
+orcus_xlsx::orcus_xlsx(spreadsheet::iface::import_factory* factory) :
+ iface::import_filter(format_t::xlsx),
+ mp_impl(std::make_unique<impl>(factory, *this))
+{
+ if (!factory)
+ throw std::invalid_argument("factory instance is required.");
+
+ spreadsheet::iface::import_global_settings* gs = factory->get_global_settings();
+ if (gs)
+ {
+ gs->set_origin_date(1899, 12, 30);
+ gs->set_default_formula_grammar(spreadsheet::formula_grammar_t::xlsx);
+ }
+
+ mp_impl->m_ns_repo.add_predefined_values(NS_ooxml_all);
+ mp_impl->m_ns_repo.add_predefined_values(NS_opc_all);
+ mp_impl->m_ns_repo.add_predefined_values(NS_misc_all);
+}
+
+orcus_xlsx::~orcus_xlsx() {}
+
+bool orcus_xlsx::detect(const unsigned char* blob, size_t size)
+{
+ zip_archive_stream_blob stream(blob, size);
+ zip_archive archive(&stream);
+
+ try
+ {
+ archive.load();
+
+ // Find and parse [Content_Types].xml which is required for OPC package.
+ std::vector<unsigned char> buf = archive.read_file_entry("[Content_Types].xml");
+
+ if (buf.empty())
+ return false;
+
+ config opt(format_t::xlsx);
+ xmlns_repository ns_repo;
+ ns_repo.add_predefined_values(NS_opc_all);
+ session_context session_cxt;
+ xml_stream_parser parser(
+ opt, ns_repo, opc_tokens, reinterpret_cast<const char*>(&buf[0]), buf.size());
+
+ xml_simple_stream_handler handler(
+ session_cxt, opc_tokens,
+ std::make_unique<opc_content_types_context>(session_cxt, opc_tokens));
+ parser.set_handler(&handler);
+ parser.parse();
+
+ opc_content_types_context& context =
+ static_cast<opc_content_types_context&>(handler.get_context());
+
+ std::vector<xml_part_t> parts;
+ context.pop_parts(parts);
+
+ if (parts.empty())
+ return false;
+
+ // See if we can find the workbook stream.
+ xml_part_t workbook_part("/xl/workbook.xml", CT_ooxml_xlsx_sheet_main);
+ return std::find(parts.begin(), parts.end(), workbook_part) != parts.end();
+ }
+ catch (const std::exception&)
+ {
+ return false;
+ }
+}
+
+void orcus_xlsx::read_file(std::string_view filepath)
+{
+ std::unique_ptr<zip_archive_stream> stream(
+ new zip_archive_stream_fd(std::string{filepath}.c_str()));
+ mp_impl->m_opc_reader.read_file(std::move(stream));
+
+ // Formulas need to be inserted to the document after the shared string
+ // table get imported, because tokenization of formulas may add new shared
+ // string instances.
+ set_formulas_to_doc();
+
+ mp_impl->mp_factory->finalize();
+}
+
+void orcus_xlsx::read_stream(std::string_view stream)
+{
+ std::unique_ptr<zip_archive_stream> blob(
+ new zip_archive_stream_blob(
+ reinterpret_cast<const uint8_t*>(stream.data()), stream.size()));
+ mp_impl->m_opc_reader.read_file(std::move(blob));
+
+ // Formulas need to be inserted to the document after the shared string
+ // table get imported, because tokenization of formulas may add new shared
+ // string instances.
+ set_formulas_to_doc();
+
+ mp_impl->mp_factory->finalize();
+}
+
+std::string_view orcus_xlsx::get_name() const
+{
+ return "xlsx";
+}
+
+void orcus_xlsx::set_formulas_to_doc()
+{
+ auto push_formula_result = [this](spreadsheet::iface::import_formula* formula, const formula_result& res)
+ {
+ switch (res.type)
+ {
+ case formula_result::result_type::numeric:
+ formula->set_result_value(res.value_numeric);
+ break;
+ case formula_result::result_type::string:
+ formula->set_result_string({res.value_string.p, res.value_string.n});
+ break;
+ case formula_result::result_type::empty:
+ break;
+ default:
+ {
+ if (get_config().debug)
+ std::cerr << "warning: unhandled formula result (orcus_xlsx::set_formulas_to_doc)" << std::endl;
+ }
+ }
+ };
+
+ auto& sdata = mp_impl->m_cxt.get_data<xlsx_session_data>();
+
+ // Insert shared formulas first.
+ for (auto& p : sdata.m_shared_formulas)
+ {
+ xlsx_session_data::shared_formula& sf = *p;
+ spreadsheet::iface::import_sheet* sheet = mp_impl->mp_factory->get_sheet(sf.sheet);
+ if (!sheet)
+ continue;
+
+ spreadsheet::iface::import_formula* formula = sheet->get_formula();
+ if (!formula)
+ continue;
+
+ formula->set_position(sf.row, sf.column);
+ if (sf.master)
+ formula->set_formula(orcus::spreadsheet::formula_grammar_t::xlsx, sf.formula);
+ formula->set_shared_formula_index(sf.identifier);
+
+ push_formula_result(formula, sf.result);
+ formula->commit();
+ }
+
+ // Insert regular (non-shared) formulas.
+ for (auto& p : sdata.m_formulas)
+ {
+ xlsx_session_data::formula& f = *p;
+ spreadsheet::iface::import_sheet* sheet = mp_impl->mp_factory->get_sheet(f.sheet);
+ if (!sheet)
+ continue;
+
+ spreadsheet::iface::import_formula* formula = sheet->get_formula();
+ if (!formula)
+ continue;
+
+ formula->set_position(f.ref.row, f.ref.column);
+ formula->set_formula(orcus::spreadsheet::formula_grammar_t::xlsx, f.exp);
+
+ push_formula_result(formula, f.result);
+ formula->commit();
+ }
+
+ // Insert array formulas.
+ for (auto& p : sdata.m_array_formulas)
+ {
+ xlsx_session_data::array_formula& af = *p;
+ spreadsheet::iface::import_sheet* sheet = mp_impl->mp_factory->get_sheet(af.sheet);
+ if (!sheet)
+ continue;
+
+ spreadsheet::iface::import_array_formula* xaf = sheet->get_array_formula();
+ push_array_formula(xaf, af.ref, af.exp, spreadsheet::formula_grammar_t::xlsx, *af.results);
+ }
+}
+
+namespace {
+
+size_t get_schema_rank(const schema_t sch)
+{
+ using map_type = std::unordered_map <schema_t, size_t>;
+
+ static const schema_t schema_rank[] = {
+ SCH_od_rels_shared_strings,
+ SCH_od_rels_pivot_cache_def,
+ SCH_od_rels_worksheet,
+ nullptr
+ };
+
+ static map_type rank_map;
+
+ if (rank_map.empty())
+ {
+ // initialize it.
+ size_t rank = 0;
+ for (const schema_t* p = schema_rank; *p; ++rank, ++p)
+ {
+ rank_map.insert(
+ map_type::value_type(*p, rank));
+ }
+ }
+
+ auto it = rank_map.find(sch);
+ return it == rank_map.end() ? numeric_limits<size_t>::max() : it->second;
+}
+
+}
+
+void orcus_xlsx::read_workbook(const string& dir_path, const string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ cout << "read_workbook: file path = " << filepath << endl;
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ mp_impl->m_cxt, ooxml_tokens,
+ std::make_unique<xlsx_workbook_context>(mp_impl->m_cxt, ooxml_tokens, *mp_impl->mp_factory));
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ // Get sheet info from the context instance.
+ xlsx_workbook_context& context =
+ static_cast<xlsx_workbook_context&>(handler->get_context());
+ opc_rel_extras_t workbook_data;
+ context.pop_workbook_info(workbook_data);
+ if (get_config().debug)
+ {
+ for_each(workbook_data.data.begin(), workbook_data.data.end(),
+ [](const opc_rel_extras_t::map_type::value_type& v)
+ {
+ const xlsx_rel_sheet_info* info =
+ dynamic_cast<const xlsx_rel_sheet_info*>(v.second.get());
+
+ if (info)
+ {
+ cout << "relationship id: " << v.first << "; sheet name: " << info->name << "; sheet id: " << info->id << endl;
+ }
+
+ const xlsx_rel_pivot_cache_info* info_pc =
+ dynamic_cast<const xlsx_rel_pivot_cache_info*>(v.second.get());
+
+ if (info_pc)
+ {
+ cout << "relationship id: " << v.first << "; pivot cache id: " << info_pc->id << endl;
+ }
+ }
+ );
+ }
+
+ handler.reset();
+
+ // Re-order the relation items so that shared strings get imported first,
+ // pivot caches get imported before the sheets and so on.
+
+ opc_reader::sort_compare_type sort_func =
+ [](const opc_rel_t& left, const opc_rel_t& right)
+ {
+ size_t rank_left = get_schema_rank(left.type), rank_right = get_schema_rank(right.type);
+ if (rank_left != rank_right)
+ return rank_left < rank_right;
+
+ std::string_view rid1 = left.rid, rid2 = right.rid;
+
+ if (rid1.size() > 1 && rid2.size() > 1)
+ {
+ // numerical comparison of relation ID's.
+ rid1 = std::string_view(rid1.data()+1, rid1.size()-1); // remove the 'r' prefix.
+ rid2 = std::string_view(rid2.data()+1, rid2.size()-1); // remove the 'r' prefix.
+ return to_long(rid1) < to_long(rid2);
+ }
+
+ // textural comparison of relation ID's.
+ return left.rid < right.rid;
+ };
+
+ mp_impl->m_opc_reader.check_relation_part(file_name, &workbook_data, &sort_func);
+}
+
+void orcus_xlsx::read_sheet(
+ const std::string& dir_path, const std::string& file_name, xlsx_rel_sheet_info* data)
+{
+ if (!data || !data->id)
+ // Sheet ID must not be 0.
+ return;
+
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_sheet: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ if (get_config().debug)
+ {
+ cout << "relationship sheet data: " << endl;
+ cout << " sheet name: " << data->name << " sheet ID: " << data->id << endl;
+ }
+
+ spreadsheet::iface::import_sheet* sheet = mp_impl->mp_factory->get_sheet(data->name);
+ if (!sheet)
+ {
+ std::ostringstream os;
+ os << "orcus_xlsx::read_sheet: ";
+ os << "sheet named '" << data->name << "' doesn't exist.";
+ throw general_error(os.str());
+ }
+
+ spreadsheet::iface::import_reference_resolver* resolver =
+ mp_impl->mp_factory->get_reference_resolver(spreadsheet::formula_ref_context_t::global);
+ if (!resolver)
+ throw general_error("orcus_xlsx::read_sheet: reference resolver interface is not available.");
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xlsx_sheet_xml_handler>(
+ mp_impl->m_cxt, ooxml_tokens, data->id-1, *resolver, *sheet);
+
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ opc_rel_extras_t table_info;
+ handler->pop_rel_extras(table_info);
+ handler.reset();
+ mp_impl->m_opc_reader.check_relation_part(file_name, &table_info);
+}
+
+void orcus_xlsx::read_shared_strings(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_shared_strings: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ mp_impl->m_cxt, ooxml_tokens,
+ std::make_unique<xlsx_shared_strings_context>(
+ mp_impl->m_cxt, ooxml_tokens, mp_impl->mp_factory->get_shared_strings()));
+
+ parser.set_handler(handler.get());
+ parser.parse();
+}
+
+void orcus_xlsx::read_styles(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_styles: file path = " << filepath << endl;
+ }
+
+ spreadsheet::iface::import_styles* styles = mp_impl->mp_factory->get_styles();
+ if (!styles)
+ // Client code doesn't support styles.
+ return;
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ return;
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ mp_impl->m_cxt, ooxml_tokens,
+ std::make_unique<xlsx_styles_context>(
+ mp_impl->m_cxt, ooxml_tokens, mp_impl->mp_factory->get_styles()));
+
+ parser.set_handler(handler.get());
+ parser.parse();
+}
+
+void orcus_xlsx::read_table(const std::string& dir_path, const std::string& file_name, xlsx_rel_table_info* data)
+{
+ if (!data || !data->sheet_interface)
+ return;
+
+ spreadsheet::iface::import_table* table = data->sheet_interface->get_table();
+ if (!table)
+ // Client code doesn't support tables. No point going further.
+ return;
+
+ spreadsheet::iface::import_reference_resolver* resolver =
+ mp_impl->mp_factory->get_reference_resolver(spreadsheet::formula_ref_context_t::global);
+
+ if (!resolver)
+ // This client doesn't support reference resolver, but is required.
+ return;
+
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_table: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ auto handler = std::make_unique<xlsx_table_xml_handler>(
+ mp_impl->m_cxt, ooxml_tokens, *table, *resolver);
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+}
+
+void orcus_xlsx::read_pivot_cache_def(
+ const std::string& dir_path, const std::string& file_name,
+ const xlsx_rel_pivot_cache_info* data)
+{
+ if (!data)
+ {
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "required pivot cache relation info was not present." << endl;
+ }
+ return;
+ }
+
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_pivot_cache_def: file path = " << filepath
+ << "; cache id = " << data->id << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ spreadsheet::iface::import_pivot_cache_definition* pcache =
+ mp_impl->mp_factory->create_pivot_cache_definition(data->id);
+
+ if (!pcache)
+ // failed to create a cache instance for whatever reason.
+ return;
+
+ auto handler = std::make_unique<xlsx_pivot_cache_def_xml_handler>(
+ mp_impl->m_cxt, ooxml_tokens, *pcache, data->id);
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ opc_rel_extras_t pcache_info = handler->pop_rel_extras();
+
+ handler.reset();
+ mp_impl->m_opc_reader.check_relation_part(file_name, &pcache_info);
+}
+
+void orcus_xlsx::read_pivot_cache_rec(
+ const std::string& dir_path, const std::string& file_name,
+ const xlsx_rel_pivot_cache_record_info* data)
+{
+ if (!data)
+ {
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "required pivot cache record relation info was not present." << endl;
+ }
+ return;
+ }
+
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_pivot_cache_rec: file path = " << filepath << "; cache id = " << data->id << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ spreadsheet::iface::import_pivot_cache_records* pcache_records =
+ mp_impl->mp_factory->create_pivot_cache_records(data->id);
+
+ if (!pcache_records)
+ return;
+
+ auto handler = std::make_unique<xlsx_pivot_cache_rec_xml_handler>(
+ mp_impl->m_cxt, ooxml_tokens, *pcache_records);
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+}
+
+void orcus_xlsx::read_pivot_table(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_pivot_table: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ auto handler = std::make_unique<xlsx_pivot_table_xml_handler>(mp_impl->m_cxt, ooxml_tokens);
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+ mp_impl->m_opc_reader.check_relation_part(file_name, nullptr);
+}
+
+void orcus_xlsx::read_rev_headers(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_rev_headers: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ mp_impl->m_cxt, ooxml_tokens,
+ std::make_unique<xlsx_revheaders_context>(mp_impl->m_cxt, ooxml_tokens));
+
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+ mp_impl->m_opc_reader.check_relation_part(file_name, nullptr);
+}
+
+void orcus_xlsx::read_rev_log(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_rev_log: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+
+ auto handler = std::make_unique<xml_simple_stream_handler>(
+ mp_impl->m_cxt, ooxml_tokens,
+ std::make_unique<xlsx_revlog_context>(mp_impl->m_cxt, ooxml_tokens));
+
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+}
+
+void orcus_xlsx::read_drawing(const std::string& dir_path, const std::string& file_name)
+{
+ std::string filepath = resolve_file_path(dir_path, file_name);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "read_drawing: file path = " << filepath << endl;
+ }
+
+ vector<unsigned char> buffer;
+ if (!mp_impl->m_opc_reader.open_zip_stream(filepath, buffer))
+ {
+ cerr << "failed to open zip stream: " << filepath << endl;
+ return;
+ }
+
+ if (buffer.empty())
+ return;
+
+ auto handler = std::make_unique<xlsx_drawing_xml_handler>(
+ mp_impl->m_cxt, ooxml_tokens);
+
+ xml_stream_parser parser(
+ get_config(), mp_impl->m_ns_repo, ooxml_tokens,
+ reinterpret_cast<const char*>(&buffer[0]), buffer.size());
+ parser.set_handler(handler.get());
+ parser.parse();
+
+ handler.reset();
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xml.cpp b/src/liborcus/orcus_xml.cpp
new file mode 100644
index 0000000..e123265
--- /dev/null
+++ b/src/liborcus/orcus_xml.cpp
@@ -0,0 +1,702 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/orcus_xml.hpp>
+#include <orcus/sax_ns_parser.hpp>
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/export_interface.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/string_pool.hpp>
+
+#include "orcus_xml_impl.hpp"
+
+#define ORCUS_DEBUG_XML 0
+
+#if ORCUS_DEBUG_XML
+#include <iostream>
+#endif
+
+#include <vector>
+#include <fstream>
+
+namespace orcus {
+
+namespace {
+
+class xml_data_sax_handler
+{
+ struct scope
+ {
+ xml_name_t name;
+ std::ptrdiff_t element_open_begin;
+ std::ptrdiff_t element_open_end;
+
+ xml_map_tree::element_type type;
+
+ scope(xmlns_id_t _ns, std::string_view _name) :
+ name(_ns, _name),
+ element_open_begin(0),
+ element_open_end(0),
+ type(xml_map_tree::element_type::unknown) {}
+ };
+
+ std::vector<sax_ns_parser_attribute> m_attrs;
+ std::vector<scope> m_scopes;
+
+ string_pool m_pool;
+ spreadsheet::iface::import_factory& m_factory;
+ xml_map_tree::const_element_list_type& m_link_positions;
+ const xml_map_tree& m_map_tree;
+ xml_map_tree::walker m_map_tree_walker;
+
+ xml_map_tree::element* mp_current_elem;
+ std::string_view m_current_chars;
+ bool m_in_range_ref;
+ xml_map_tree::range_reference* mp_increment_row;
+
+private:
+
+ const sax_ns_parser_attribute* find_attr_by_name(const xml_name_t& name)
+ {
+ for (const sax_ns_parser_attribute& attr : m_attrs)
+ {
+ if (attr.ns == name.ns && attr.name == name.name)
+ return &attr;
+ }
+ return nullptr;
+ }
+
+ void set_single_link_cell(const xml_map_tree::cell_reference& ref, std::string_view val)
+ {
+ spreadsheet::iface::import_sheet* sheet = m_factory.get_sheet(ref.pos.sheet);
+ if (sheet)
+ sheet->set_auto(ref.pos.row, ref.pos.col, val);
+ }
+
+ void set_field_link_cell(xml_map_tree::field_in_range& field, std::string_view val)
+ {
+ assert(field.ref);
+ assert(!field.ref->pos.sheet.empty());
+
+ const xml_map_tree::cell_position& pos = field.ref->pos;
+ spreadsheet::iface::import_sheet* sheet = m_factory.get_sheet(pos.sheet);
+ if (sheet)
+ sheet->set_auto(
+ pos.row + field.ref->row_position,
+ pos.col + field.column_pos,
+ val);
+ }
+
+public:
+ xml_data_sax_handler(
+ spreadsheet::iface::import_factory& factory,
+ xml_map_tree::const_element_list_type& link_positions,
+ const xml_map_tree& map_tree) :
+ m_factory(factory),
+ m_link_positions(link_positions),
+ m_map_tree(map_tree),
+ m_map_tree_walker(map_tree.get_tree_walker()),
+ mp_current_elem(nullptr),
+ m_in_range_ref(false),
+ mp_increment_row(nullptr) {}
+
+ void doctype(const sax::doctype_declaration&)
+ {
+ }
+
+ void start_declaration(std::string_view)
+ {
+ }
+
+ void end_declaration(std::string_view)
+ {
+ m_attrs.clear();
+ }
+
+ void start_element(const sax_ns_parser_element& elem)
+ {
+ m_scopes.emplace_back(elem.ns, elem.name);
+ scope& cur = m_scopes.back();
+ cur.element_open_begin = elem.begin_pos;
+ cur.element_open_end = elem.end_pos;
+ m_current_chars = std::string_view{};
+
+ mp_current_elem = m_map_tree_walker.push_element({elem.ns, elem.name});
+ if (mp_current_elem)
+ {
+ if (mp_current_elem->row_group && mp_increment_row == mp_current_elem->row_group)
+ {
+ // The last closing element was a row group boundary. Increment the row position.
+ xml_map_tree::range_reference* ref = mp_current_elem->row_group;
+ ++ref->row_position;
+ mp_increment_row = nullptr;
+ }
+
+ // Go through all linked attributes that belong to this element,
+ // and see if they exist in this content xml.
+ for (const auto& p_attr : mp_current_elem->attributes)
+ {
+ const xml_map_tree::attribute& linked_attr = *p_attr;
+ const sax_ns_parser_attribute* p = find_attr_by_name(linked_attr.name);
+ if (!p)
+ continue;
+
+ // This attribute is linked. Import its value.
+
+ std::string_view val_trimmed = trim(p->value);
+ switch (linked_attr.ref_type)
+ {
+ case xml_map_tree::reference_type::cell:
+ set_single_link_cell(*linked_attr.cell_ref, val_trimmed);
+ break;
+ case xml_map_tree::reference_type::range_field:
+ {
+ set_field_link_cell(*linked_attr.field_ref, val_trimmed);
+ break;
+ }
+ default:
+ ;
+ }
+
+ // Record the namespace alias used in the content stream.
+ linked_attr.ns_alias = m_map_tree.intern_string(p->ns_alias);
+ }
+
+ if (mp_current_elem->range_parent)
+ m_in_range_ref = true;
+ }
+ m_attrs.clear();
+ }
+
+ void end_element(const sax_ns_parser_element& elem)
+ {
+ assert(!m_scopes.empty());
+
+ if (mp_current_elem)
+ {
+ switch (mp_current_elem->ref_type)
+ {
+ case xml_map_tree::reference_type::cell:
+ {
+ set_single_link_cell(*mp_current_elem->cell_ref, m_current_chars);
+ break;
+ }
+ case xml_map_tree::reference_type::range_field:
+ {
+ set_field_link_cell(*mp_current_elem->field_ref, m_current_chars);
+ break;
+ }
+ default:
+ ;
+ }
+
+ if (mp_current_elem->row_group)
+ {
+ // This element defines a row-group boundary.
+ spreadsheet::row_t row_start = mp_current_elem->row_group_position;
+ spreadsheet::row_t row_end = mp_current_elem->row_group->row_position - 1;
+ if (row_end > row_start)
+ {
+ // This is the end of a parent row-group. Fill down the
+ // cell values.
+ const xml_map_tree::range_reference& ref = *mp_current_elem->row_group;
+
+ spreadsheet::iface::import_sheet* sheet = m_factory.get_sheet(ref.pos.sheet);
+
+ if (sheet)
+ {
+ row_start += ref.pos.row + 1;
+ row_end += ref.pos.row + 1;
+
+ for (spreadsheet::col_t col : mp_current_elem->linked_range_fields)
+ {
+ col += ref.pos.col;
+ sheet->fill_down_cells(row_start, col, row_end - row_start);
+ }
+ }
+ }
+
+ mp_current_elem->row_group_position = mp_current_elem->row_group->row_position;
+ mp_increment_row = mp_current_elem->row_group;
+ }
+
+ // Store the end element position in stream for linked elements.
+ const scope& cur = m_scopes.back();
+ if (mp_current_elem->ref_type == xml_map_tree::reference_type::cell ||
+ mp_current_elem->range_parent ||
+ (!m_in_range_ref && mp_current_elem->unlinked_attribute_anchor()))
+ {
+ // either single link element, parent of range link elements,
+ // or an unlinked attribute anchor outside linked ranges.
+ mp_current_elem->stream_pos.open_begin = cur.element_open_begin;
+ mp_current_elem->stream_pos.open_end = cur.element_open_end;
+ mp_current_elem->stream_pos.close_begin = elem.begin_pos;
+ mp_current_elem->stream_pos.close_end = elem.end_pos;
+ m_link_positions.push_back(mp_current_elem);
+ }
+
+ if (mp_current_elem->range_parent)
+ m_in_range_ref = false;
+
+ // Record the namespace alias used in the content stream.
+ mp_current_elem->ns_alias = m_map_tree.intern_string(elem.ns_alias);
+ }
+
+ m_scopes.pop_back();
+ mp_current_elem = m_map_tree_walker.pop_element({elem.ns, elem.name});
+ }
+
+ void characters(std::string_view val, bool transient)
+ {
+ if (!mp_current_elem)
+ return;
+
+ m_current_chars = trim(val);
+ if (transient)
+ m_current_chars = m_pool.intern(m_current_chars).first;
+ }
+
+ void attribute(std::string_view name, std::string_view val)
+ {
+ if (name == "encoding")
+ {
+ if (auto* gs = m_factory.get_global_settings(); gs)
+ {
+ character_set_t cs = to_character_set(val);
+ gs->set_character_set(cs);
+ }
+ }
+ }
+
+ void attribute(const sax_ns_parser_attribute& at)
+ {
+ m_attrs.push_back(at);
+ }
+};
+
+/**
+ * Used in write_range_reference_group().
+ */
+struct scope
+{
+ const xml_map_tree::element& element;
+ xml_map_tree::element_store_type::const_iterator current_child_pos;
+ xml_map_tree::element_store_type::const_iterator end_child_pos;
+ bool opened:1;
+
+ scope(const scope&) = delete;
+ scope& operator=(const scope&) = delete;
+
+ scope(const xml_map_tree::element& _elem) :
+ element(_elem), opened(false)
+ {
+ current_child_pos = end_child_pos;
+
+ if (element.elem_type == xml_map_tree::element_type::unlinked)
+ {
+ current_child_pos = element.child_elements->begin();
+ end_child_pos = element.child_elements->end();
+ }
+ }
+};
+
+typedef std::vector<std::unique_ptr<scope>> scopes_type;
+
+void write_opening_element(
+ std::ostream& os, const xml_map_tree::element& elem, const xml_map_tree::range_reference& ref,
+ const spreadsheet::iface::export_sheet& sheet, spreadsheet::row_t current_row, bool self_close)
+{
+ if (elem.attributes.empty())
+ {
+ // This element has no linked attributes. Just write the element name and be done with it.
+ os << '<' << elem << '>';
+ return;
+ }
+
+ // Element has one or more linked attributes.
+
+ os << '<' << elem;
+
+ for (const auto& p_attr : elem.attributes)
+ {
+ const xml_map_tree::attribute& attr = *p_attr;
+ if (attr.ref_type != xml_map_tree::reference_type::range_field)
+ // In theory this should never happen but it won't hurt to check.
+ continue;
+
+ os << ' ' << attr << "=\"";
+ sheet.write_string(os, ref.pos.row + 1 + current_row, ref.pos.col + attr.field_ref->column_pos);
+ os << "\"";
+ }
+
+ if (self_close)
+ os << '/';
+
+ os << '>';
+}
+
+void write_opening_element(
+ std::ostream& os, const xml_map_tree::element& elem, const spreadsheet::iface::export_factory& fact, bool self_close)
+{
+ os << '<' << elem;
+ for (const auto& p_attr : elem.attributes)
+ {
+ const xml_map_tree::attribute& attr = *p_attr;
+ if (attr.ref_type != xml_map_tree::reference_type::cell)
+ // We should only see single linked cell here, as all
+ // field links are handled by the range parent above.
+ continue;
+
+ const xml_map_tree::cell_position& pos = attr.cell_ref->pos;
+
+ const spreadsheet::iface::export_sheet* sheet = fact.get_sheet(pos.sheet);
+ if (!sheet)
+ continue;
+
+ os << ' ' << attr << "=\"";
+ sheet->write_string(os, pos.row, pos.col);
+ os << "\"";
+ }
+
+ if (self_close)
+ os << '/';
+
+ os << '>';
+}
+
+/**
+ * Write to the output stream a single range reference.
+ *
+ * @param os output stream.
+ * @param root root map tree element representing the root of a single range
+ * reference.
+ * @param ref range reference data.
+ * @param factory export factory instance.
+ */
+void write_range_reference_group(
+ std::ostream& os, const xml_map_tree::element& root, const xml_map_tree::range_reference& ref,
+ const spreadsheet::iface::export_factory& factory)
+{
+ const spreadsheet::iface::export_sheet* sheet = factory.get_sheet(ref.pos.sheet);
+ if (!sheet)
+ return;
+
+ scopes_type scopes;
+ for (spreadsheet::row_t current_row = 0; current_row < ref.row_position; ++current_row)
+ {
+ scopes.push_back(std::make_unique<scope>(root)); // root element
+
+ while (!scopes.empty())
+ {
+ bool new_scope = false;
+
+ scope& cur_scope = *scopes.back();
+
+ // Self-closing element has no child elements nor content.
+ bool self_close =
+ (cur_scope.current_child_pos == cur_scope.end_child_pos) &&
+ (cur_scope.element.ref_type != xml_map_tree::reference_type::range_field);
+
+ if (!cur_scope.opened)
+ {
+ // Write opening element of this scope only on the 1st entrance.
+ write_opening_element(os, cur_scope.element, ref, *sheet, current_row, self_close);
+ cur_scope.opened = true;
+ }
+
+ if (self_close)
+ {
+ scopes.pop_back();
+ continue;
+ }
+
+ // Go though all child elements.
+ for (; cur_scope.current_child_pos != cur_scope.end_child_pos; ++cur_scope.current_child_pos)
+ {
+ const xml_map_tree::element& child_elem = **cur_scope.current_child_pos;
+ if (child_elem.elem_type == xml_map_tree::element_type::unlinked)
+ {
+ // This is a non-leaf element. Push a new scope with this
+ // element and re-start the loop.
+ ++cur_scope.current_child_pos;
+ scopes.push_back(std::make_unique<scope>(child_elem));
+ new_scope = true;
+ break;
+ }
+
+ // This is a leaf element. This must be a field link element.
+ if (child_elem.ref_type == xml_map_tree::reference_type::range_field)
+ {
+ write_opening_element(os, child_elem, ref, *sheet, current_row, false);
+ sheet->write_string(os, ref.pos.row + 1 + current_row, ref.pos.col + child_elem.field_ref->column_pos);
+ os << "</" << child_elem << ">";
+ }
+ }
+
+ if (new_scope)
+ // Re-start the loop with a new scope.
+ continue;
+
+ // Write content of this element before closing it (if it's linked).
+ if (scopes.back()->element.ref_type == xml_map_tree::reference_type::range_field)
+ sheet->write_string(
+ os, ref.pos.row + 1 + current_row, ref.pos.col + scopes.back()->element.field_ref->column_pos);
+
+ // Close this element for good, and exit the current scope.
+ os << "</" << scopes.back()->element << ">";
+ scopes.pop_back();
+ }
+ }
+}
+
+/**
+ * Write to an output stream the sub-structure comprising one or more range
+ * references.
+ *
+ * @param os output stream
+ * @param elem_top topmost element in the range reference sub-structure.
+ */
+void write_range_reference(std::ostream& os, const xml_map_tree::element& elem_top, const spreadsheet::iface::export_factory& factory)
+{
+ // Top element is expected to have one or more child elements, and each
+ // child element represents a separate database range.
+ if (elem_top.elem_type != xml_map_tree::element_type::unlinked)
+ return;
+
+ assert(elem_top.child_elements);
+
+ if (elem_top.child_elements->empty())
+ return;
+
+ // TODO: For now, we assume that there is only one child element under the
+ // range ref parent.
+ write_range_reference_group(
+ os, **elem_top.child_elements->begin(), *elem_top.range_parent, factory);
+}
+
+struct less_by_opening_elem_pos
+{
+ bool operator() (const xml_map_tree::element* left, const xml_map_tree::element* right) const
+ {
+ return left->stream_pos.open_begin < right->stream_pos.open_begin;
+ }
+};
+
+} // anonymous namespace
+
+orcus_xml::orcus_xml(xmlns_repository& ns_repo, spreadsheet::iface::import_factory* im_fact, spreadsheet::iface::export_factory* ex_fact) :
+ mp_impl(std::make_unique<impl>(ns_repo))
+{
+ mp_impl->im_factory = im_fact;
+ mp_impl->ex_factory = ex_fact;
+}
+
+orcus_xml::~orcus_xml() {}
+
+void orcus_xml::set_namespace_alias(std::string_view alias, std::string_view uri, bool default_ns)
+{
+ mp_impl->map_tree.set_namespace_alias(alias, uri, default_ns);
+}
+
+void orcus_xml::set_cell_link(std::string_view xpath, std::string_view sheet, spreadsheet::row_t row, spreadsheet::col_t col)
+{
+ std::string_view sheet_safe = mp_impl->map_tree.intern_string(sheet);
+ mp_impl->map_tree.set_cell_link(xpath, xml_map_tree::cell_position(sheet_safe, row, col));
+}
+
+void orcus_xml::start_range(std::string_view sheet, spreadsheet::row_t row, spreadsheet::col_t col)
+{
+ std::string_view sheet_safe = mp_impl->map_tree.intern_string(sheet);
+ mp_impl->cur_range_ref = xml_map_tree::cell_position(sheet_safe, row, col);
+ mp_impl->map_tree.start_range(mp_impl->cur_range_ref);
+}
+
+void orcus_xml::append_field_link(std::string_view xpath, std::string_view label)
+{
+ mp_impl->map_tree.append_range_field_link(xpath, label);
+}
+
+void orcus_xml::set_range_row_group(std::string_view xpath)
+{
+ mp_impl->map_tree.set_range_row_group(xpath);
+}
+
+void orcus_xml::commit_range()
+{
+ mp_impl->cur_range_ref = xml_map_tree::cell_position();
+ mp_impl->map_tree.commit_range();
+}
+
+void orcus_xml::append_sheet(std::string_view name)
+{
+ if (name.empty())
+ return;
+
+ mp_impl->im_factory->append_sheet(mp_impl->sheet_count++, name);
+}
+
+void orcus_xml::read_stream(std::string_view stream)
+{
+ if (stream.empty())
+ return;
+
+ // Insert the range headers and reset the row size counters.
+ xml_map_tree::range_ref_map_type& range_refs = mp_impl->map_tree.get_range_references();
+
+ for (const auto& ref_pair : range_refs)
+ {
+ const xml_map_tree::cell_position& ref = ref_pair.first;
+ xml_map_tree::range_reference& range_ref = *ref_pair.second;
+ range_ref.row_position = 1; // Reset the row offset.
+
+ spreadsheet::iface::import_sheet* sheet = mp_impl->im_factory->get_sheet(ref.sheet);
+
+ if (!sheet)
+ continue;
+
+ spreadsheet::row_t row = ref.row;
+ spreadsheet::col_t col = ref.col;
+
+ for (const xml_map_tree::linkable* e : range_ref.field_nodes)
+ {
+ if (e->label.empty())
+ {
+ // No custom header label. Create a label from the name of the linkable.
+ std::string s = e->name.to_string(mp_impl->ns_repo);
+ if (!s.empty())
+ sheet->set_auto(row, col, s);
+ }
+ else
+ sheet->set_auto(row, col, e->label);
+
+ ++col;
+ }
+ }
+
+ // Parse the content xml.
+ xmlns_context ns_cxt = mp_impl->ns_repo.create_context(); // new ns context for the content xml stream.
+ xml_data_sax_handler handler(
+ *mp_impl->im_factory, mp_impl->link_positions, mp_impl->map_tree);
+
+ sax_ns_parser<xml_data_sax_handler> parser(stream, ns_cxt, handler);
+ parser.parse();
+}
+
+#if ORCUS_DEBUG_XML
+
+namespace {
+
+void dump_links(const xml_map_tree::const_element_list_type& links)
+{
+ cout << "link count: " << links.size() << endl;
+}
+
+}
+
+#endif
+
+void orcus_xml::write(std::string_view stream, std::ostream& out) const
+{
+ if (!mp_impl->ex_factory)
+ // We can't export data witout export factory.
+ return;
+
+ if (stream.empty())
+ // Source input stream is empty.
+ return;
+
+ xml_map_tree::const_element_list_type& links = mp_impl->link_positions;
+ if (links.empty())
+ // nothing to write.
+ return;
+
+ // Sort all link position by opening element positions.
+ std::sort(links.begin(), links.end(), less_by_opening_elem_pos());
+
+ spreadsheet::iface::export_factory& fact = *mp_impl->ex_factory;
+ xml_map_tree::const_element_list_type::const_iterator it = links.begin(), it_end = links.end();
+
+#if ORCUS_DEBUG_XML
+ dump_links(links);
+#endif
+
+ const char* p0 = stream.data();
+ std::ptrdiff_t begin_pos = 0;
+
+ for (; it != it_end; ++it)
+ {
+ const xml_map_tree::element& elem = **it;
+ if (elem.ref_type == xml_map_tree::reference_type::cell)
+ {
+ // Single cell link
+ const xml_map_tree::cell_position& pos = elem.cell_ref->pos;
+
+ const spreadsheet::iface::export_sheet* sheet = fact.get_sheet(pos.sheet);
+ if (!sheet)
+ continue;
+
+ std::ptrdiff_t open_begin = elem.stream_pos.open_begin;
+ std::ptrdiff_t close_begin = elem.stream_pos.close_begin;
+ std::ptrdiff_t close_end = elem.stream_pos.close_end;
+
+ assert(open_begin > begin_pos);
+ out << std::string_view(p0+begin_pos, open_begin-begin_pos); // stream since last linked element.
+
+ write_opening_element(out, elem, fact, false);
+ sheet->write_string(out, pos.row, pos.col);
+ out << std::string_view(p0+close_begin, close_end-close_begin); // closing element.
+ begin_pos = close_end;
+ }
+ else if (elem.range_parent)
+ {
+ // Range link
+ const xml_map_tree::range_reference& ref = *elem.range_parent;
+ const xml_map_tree::cell_position& pos = ref.pos;
+
+ const spreadsheet::iface::export_sheet* sheet = fact.get_sheet(pos.sheet);
+ if (!sheet)
+ continue;
+
+ std::ptrdiff_t open_begin = elem.stream_pos.open_begin;
+ std::ptrdiff_t close_begin = elem.stream_pos.close_begin;
+ std::ptrdiff_t close_end = elem.stream_pos.close_end;
+
+ assert(open_begin > begin_pos);
+ out << std::string_view(p0+begin_pos, open_begin-begin_pos); // stream since last linked element.
+
+ write_opening_element(out, elem, fact, false);
+ write_range_reference(out, elem, fact);
+ out << std::string_view(p0+close_begin, close_end-close_begin); // closing element.
+ begin_pos = close_end;
+ }
+ else if (elem.unlinked_attribute_anchor())
+ {
+ // Element is not linked but has one or more attributes that are
+ // linked. Here, only write the opening element with attributes.
+
+ std::ptrdiff_t open_begin = elem.stream_pos.open_begin;
+ std::ptrdiff_t open_end = elem.stream_pos.open_end;
+
+ bool self_close = elem.stream_pos.open_begin == elem.stream_pos.close_begin;
+
+ assert(open_begin > begin_pos);
+ out << std::string_view(p0+begin_pos, open_begin-begin_pos); // stream since last linked element.
+
+ write_opening_element(out, elem, fact, self_close);
+ begin_pos = open_end;
+ }
+ else
+ throw general_error("Non-link element type encountered.");
+ }
+
+ // Flush the remaining stream.
+ out << std::string_view(p0+begin_pos, stream.size()-begin_pos);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xml_impl.cpp b/src/liborcus/orcus_xml_impl.cpp
new file mode 100644
index 0000000..4718f3c
--- /dev/null
+++ b/src/liborcus/orcus_xml_impl.cpp
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus_xml_impl.hpp"
+
+namespace orcus {
+
+orcus_xml::impl::impl(xmlns_repository& _ns_repo) :
+ im_factory(nullptr),
+ ex_factory(nullptr),
+ ns_repo(_ns_repo),
+ ns_cxt_map(ns_repo.create_context()),
+ map_tree(ns_repo),
+ sheet_count(0) {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xml_impl.hpp b/src/liborcus/orcus_xml_impl.hpp
new file mode 100644
index 0000000..56c8156
--- /dev/null
+++ b/src/liborcus/orcus_xml_impl.hpp
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_ORCUS_XML_IMPL_HPP
+#define INCLUDED_ORCUS_ORCUS_XML_IMPL_HPP
+
+#include "orcus/orcus_xml.hpp"
+#include "orcus/xml_namespace.hpp"
+
+#include "xml_map_tree.hpp"
+
+namespace orcus {
+
+struct orcus_xml::impl
+{
+ spreadsheet::iface::import_factory* im_factory;
+ spreadsheet::iface::export_factory* ex_factory;
+
+ /** xml namespace repository for the whole session. */
+ xmlns_repository& ns_repo;
+
+ /** xml namespace context */
+ xmlns_context ns_cxt_map;
+
+ /** xml element tree that represents all mapped paths. */
+ xml_map_tree map_tree;
+
+ spreadsheet::sheet_t sheet_count;
+
+ /**
+ * Positions of all linked elements, single and range reference alike.
+ * Stored link elements must be sorted in order of stream positions, and
+ * as such, no linked elements should be nested; there should never be a
+ * linked element inside the substructure of another linked element.
+ */
+ xml_map_tree::const_element_list_type link_positions;
+
+ xml_map_tree::cell_position cur_range_ref;
+
+ explicit impl(xmlns_repository& _ns_repo);
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/orcus_xml_map_def.cpp b/src/liborcus/orcus_xml_map_def.cpp
new file mode 100644
index 0000000..5c484de
--- /dev/null
+++ b/src/liborcus/orcus_xml_map_def.cpp
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/orcus_xml.hpp"
+#include "orcus/sax_parser_base.hpp"
+#include "orcus/sax_parser.hpp"
+#include "orcus/stream.hpp"
+#include "orcus/xml_structure_tree.hpp"
+#include "orcus/xml_namespace.hpp"
+#include "orcus/xml_writer.hpp"
+#include "orcus/measurement.hpp"
+
+#include "orcus_xml_impl.hpp"
+
+#include <vector>
+#include <iostream>
+
+namespace orcus {
+
+namespace {
+
+class xml_map_sax_handler
+{
+ struct scope
+ {
+ std::string_view ns;
+ std::string_view name;
+
+ scope(std::string_view _ns, std::string_view _name) : ns(_ns), name(_name) {}
+ };
+
+ std::vector<sax::parser_attribute> m_attrs;
+ std::vector<scope> m_scopes;
+ orcus_xml& m_app;
+
+public:
+
+ xml_map_sax_handler(orcus_xml& app) : m_app(app) {}
+
+ void doctype(const sax::doctype_declaration&) {}
+ void start_declaration(std::string_view /*name*/) {}
+
+ void end_declaration(std::string_view /*name*/)
+ {
+ m_attrs.clear();
+ }
+
+ void start_element(const sax::parser_element& elem);
+
+ void end_element(const sax::parser_element& elem)
+ {
+ if (elem.name == "range")
+ m_app.commit_range();
+
+ m_scopes.pop_back();
+ }
+
+ void attribute(const sax::parser_attribute& attr)
+ {
+ m_attrs.push_back(attr);
+ }
+
+ void characters(std::string_view, bool) {}
+};
+
+void xml_map_sax_handler::start_element(const sax::parser_element& elem)
+{
+ std::string_view xpath, sheet, label;
+ spreadsheet::row_t row = -1;
+ spreadsheet::col_t col = -1;
+
+ auto to_row = [](std::string_view s) -> spreadsheet::row_t
+ {
+ long v;
+ parse_integer(s.data(), s.data() + s.size(), v);
+ return v;
+ };
+
+ auto to_col = [](std::string_view s) -> spreadsheet::col_t
+ {
+ long v;
+ parse_integer(s.data(), s.data() + s.size(), v);
+ return v;
+ };
+
+ if (elem.name == "ns")
+ {
+ // empty alias is associated with default namespace.
+ std::string_view alias, uri;
+ bool default_ns = false;
+
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "alias")
+ alias = attr.value;
+ else if (attr.name == "uri")
+ uri = attr.value;
+ else if (attr.name == "default")
+ default_ns = to_bool(attr.value);
+ }
+
+ if (!uri.empty())
+ m_app.set_namespace_alias(alias, uri, default_ns);
+ }
+ else if (elem.name == "cell")
+ {
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "path")
+ xpath = attr.value;
+ else if (attr.name == "sheet")
+ sheet = attr.value;
+ else if (attr.name == "row")
+ row = to_row(attr.value);
+ else if (attr.name == "column")
+ col = to_col(attr.value);
+ }
+
+ m_app.set_cell_link(xpath, sheet, row, col);
+ }
+ else if (elem.name == "range")
+ {
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "sheet")
+ sheet = attr.value;
+ else if (attr.name == "row")
+ row = to_row(attr.value);
+ else if (attr.name == "column")
+ col = to_col(attr.value);
+ }
+
+ m_app.start_range(sheet, row, col);
+ }
+ else if (elem.name == "field")
+ {
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "path")
+ xpath = attr.value;
+ else if (attr.name == "label")
+ label = attr.value;
+ }
+
+ m_app.append_field_link(xpath, label);
+ }
+ else if (elem.name == "row-group")
+ {
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "path")
+ {
+ xpath = attr.value;
+ break;
+ }
+ }
+
+ m_app.set_range_row_group(xpath);
+ }
+ else if (elem.name == "sheet")
+ {
+ std::string_view sheet_name;
+ for (const sax::parser_attribute& attr : m_attrs)
+ {
+ if (attr.name == "name")
+ {
+ sheet_name = attr.value;
+ break;
+ }
+ }
+
+ if (!sheet_name.empty())
+ m_app.append_sheet(sheet_name);
+ }
+
+ m_scopes.push_back(scope(elem.ns, elem.name));
+ m_attrs.clear();
+}
+
+} // anonymous namespace
+
+void orcus_xml::read_map_definition(std::string_view stream)
+{
+ try
+ {
+ xml_map_sax_handler handler(*this);
+ sax_parser<xml_map_sax_handler> parser(stream, handler);
+ parser.parse();
+ }
+ catch (const parse_error& e)
+ {
+ std::ostringstream os;
+ os << "Error parsing the map definition file:" << std::endl
+ << std::endl
+ << create_parse_error_output(stream, e.offset()) << std::endl
+ << e.what();
+
+ throw invalid_map_error(os.str());
+ }
+}
+
+void orcus_xml::detect_map_definition(std::string_view stream)
+{
+ size_t range_count = 0;
+ std::string sheet_name_prefix = "range-";
+
+ xml_structure_tree::range_handler_type rh = [&](xml_table_range_t&& range)
+ {
+ // Build sheet name first and insert a new sheet.
+ std::ostringstream os_sheet_name;
+ os_sheet_name << sheet_name_prefix << range_count;
+ std::string sheet_name = os_sheet_name.str();
+ append_sheet(sheet_name);
+
+ // Push the linked range.
+ start_range(sheet_name, 0, 0);
+
+ for (const auto& path : range.paths)
+ append_field_link(path, std::string_view());
+
+ for (const auto& row_group : range.row_groups)
+ set_range_row_group(row_group);
+
+ commit_range();
+
+ ++range_count;
+ };
+
+ xmlns_repository repo;
+ xmlns_context cxt = repo.create_context();
+ xml_structure_tree structure(cxt);
+ structure.parse(stream);
+
+ // Register all namespace aliases first.
+ for (const xmlns_id_t& ns : cxt.get_all_namespaces())
+ set_namespace_alias(cxt.get_short_name(ns), std::string_view(ns));
+
+ structure.process_ranges(rh);
+}
+
+void orcus_xml::write_map_definition(std::string_view stream, std::ostream& out) const
+{
+ xmlns_context cxt = mp_impl->ns_repo.create_context();
+ xml_structure_tree tree(cxt);
+ tree.parse(stream);
+
+ xml_writer writer(mp_impl->ns_repo, out);
+ xmlns_id_t default_ns = writer.add_namespace("", "https://gitlab.com/orcus/orcus/xml-map-definition");
+ auto map_scope = writer.push_element_scope({default_ns, "map"});
+
+ for (const xmlns_id_t& ns : cxt.get_all_namespaces())
+ {
+ writer.add_attribute({default_ns, "alias"}, cxt.get_short_name(ns));
+ writer.add_attribute({default_ns, "uri"}, ns);
+ writer.push_element_scope({default_ns, "ns"});
+ }
+
+ size_t range_count = 0;
+ std::string sheet_name_prefix = "range-";
+
+ xml_structure_tree::range_handler_type rh = [&](xml_table_range_t&& range)
+ {
+ std::ostringstream os_sheet_name;
+ os_sheet_name << sheet_name_prefix << range_count;
+ std::string sheet_name = os_sheet_name.str();
+
+ writer.add_attribute({default_ns, "name"}, sheet_name);
+ writer.push_element_scope({default_ns, "sheet"});
+
+ writer.add_attribute({default_ns, "sheet"}, sheet_name);
+ writer.add_attribute({default_ns, "row"}, "0");
+ writer.add_attribute({default_ns, "column"}, "0");
+ auto range_scope = writer.push_element_scope({default_ns, "range"});
+
+ for (const auto& path : range.paths)
+ {
+ writer.add_attribute({default_ns, "path"}, path);
+ writer.push_element_scope({default_ns, "field"});
+ }
+
+ for (const auto& row_group : range.row_groups)
+ {
+ writer.add_attribute({default_ns, "path"}, row_group);
+ writer.push_element_scope({default_ns, "row-group"});
+ }
+
+ ++range_count;
+ };
+
+ tree.process_ranges(rh);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/session_context.cpp b/src/liborcus/session_context.cpp
new file mode 100644
index 0000000..b054106
--- /dev/null
+++ b/src/liborcus/session_context.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "session_context.hpp"
+
+namespace orcus {
+
+session_context::custom_data::~custom_data() {}
+
+session_context::session_context(std::unique_ptr<custom_data> data) : cdata(std::move(data)) {}
+
+std::string_view session_context::intern(const xml_token_attr_t& attr)
+{
+ // NB: always intern regardless of the transient flag since the string may
+ // be used in another stream.
+ return spool.intern(attr.value).first;
+}
+
+std::string_view session_context::intern(std::string_view s)
+{
+ return spool.intern(s).first;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/session_context.hpp b/src/liborcus/session_context.hpp
new file mode 100644
index 0000000..ab50836
--- /dev/null
+++ b/src/liborcus/session_context.hpp
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_SESSION_CONTEXT_HPP
+#define INCLUDED_ORCUS_SESSION_CONTEXT_HPP
+
+#include <orcus/string_pool.hpp>
+#include <orcus/types.hpp>
+
+#include <memory>
+
+namespace orcus {
+
+struct session_context
+{
+ session_context(const session_context&) = delete;
+ session_context& operator=(const session_context&) = delete;
+
+ string_pool spool;
+
+ /**
+ * Derive from this class in case the filter needs to store its own
+ * session data.
+ */
+ struct custom_data
+ {
+ virtual ~custom_data() = 0;
+ };
+
+ std::unique_ptr<custom_data> cdata;
+
+ session_context() = default;
+ session_context(std::unique_ptr<custom_data> data);
+
+ template<typename CDataT>
+ CDataT& get_data()
+ {
+ return static_cast<CDataT&>(*cdata);
+ }
+
+ template<typename CDataT>
+ const CDataT& get_data() const
+ {
+ return static_cast<const CDataT&>(*cdata);
+ }
+
+ std::string_view intern(const xml_token_attr_t& attr);
+ std::string_view intern(std::string_view s);
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_iface_util.cpp b/src/liborcus/spreadsheet_iface_util.cpp
new file mode 100644
index 0000000..740864c
--- /dev/null
+++ b/src/liborcus/spreadsheet_iface_util.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "spreadsheet_iface_util.hpp"
+#include "formula_result.hpp"
+
+#include "orcus/spreadsheet/import_interface.hpp"
+
+namespace orcus {
+
+void push_array_formula(
+ spreadsheet::iface::import_array_formula* xformula,
+ const spreadsheet::range_t& range, std::string_view formula,
+ spreadsheet::formula_grammar_t grammar, const range_formula_results& results)
+{
+ xformula->set_range(range);
+ xformula->set_formula(grammar, formula);
+
+ for (size_t row = 0; row < results.row_size(); ++row)
+ {
+ for (size_t col = 0; col < results.col_size(); ++col)
+ {
+ const formula_result& v = results.get(row, col);
+ switch (v.type)
+ {
+ case formula_result::result_type::numeric:
+ xformula->set_result_value(row, col, v.value_numeric);
+ break;
+ case formula_result::result_type::string:
+ xformula->set_result_string(row, col, {v.value_string.p, v.value_string.n});
+ break;
+ case formula_result::result_type::boolean:
+ xformula->set_result_bool(row, col, v.value_boolean);
+ break;
+ case formula_result::result_type::empty:
+ xformula->set_result_empty(row, col);
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ xformula->commit();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_iface_util.hpp b/src/liborcus/spreadsheet_iface_util.hpp
new file mode 100644
index 0000000..1262be6
--- /dev/null
+++ b/src/liborcus/spreadsheet_iface_util.hpp
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_SPREADSHEET_IFACE_UTIL_HPP
+#define INCLUDED_ORCUS_SPREADSHEET_IFACE_UTIL_HPP
+
+#include "orcus/spreadsheet/types.hpp"
+
+namespace orcus {
+
+class range_formula_results;
+
+namespace spreadsheet {
+
+namespace iface {
+
+class import_array_formula;
+
+}
+
+}
+
+void push_array_formula(
+ spreadsheet::iface::import_array_formula* xformula,
+ const spreadsheet::range_t& range, std::string_view formula,
+ spreadsheet::formula_grammar_t grammar, const range_formula_results& results);
+
+} // namespace orcus
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_impl_types.cpp b/src/liborcus/spreadsheet_impl_types.cpp
new file mode 100644
index 0000000..735f546
--- /dev/null
+++ b/src/liborcus/spreadsheet_impl_types.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "spreadsheet_impl_types.hpp"
+
+#include <ostream>
+
+namespace orcus { namespace spreadsheet { namespace detail {
+
+cell_position_t::cell_position_t() : row(-1), col(-1) {}
+
+cell_position_t::cell_position_t(std::string_view _sheet, spreadsheet::row_t _row, spreadsheet::col_t _col) :
+ sheet(_sheet), row(_row), col(_col) {}
+
+cell_position_t::cell_position_t(const cell_position_t& r) : sheet(r.sheet), row(r.row), col(r.col) {}
+
+bool cell_position_t::operator== (const cell_position_t& other) const
+{
+ return sheet == other.sheet && row == other.row && col == other.col;
+}
+
+bool cell_position_t::operator!= (const cell_position_t& other) const
+{
+ return !operator==(other);
+}
+
+std::ostream& operator<< (std::ostream& os, const cell_position_t& ref)
+{
+ os << "[sheet='" << ref.sheet << "' row=" << ref.row << " column=" << ref.col << "]";
+ return os;
+}
+
+bool operator< (const cell_position_t& left, const cell_position_t& right)
+{
+ if (left.sheet != right.sheet)
+ return left.sheet < right.sheet;
+
+ if (left.row != right.row)
+ return left.row < right.row;
+
+ return left.col < right.col;
+}
+
+}}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_impl_types.hpp b/src/liborcus/spreadsheet_impl_types.hpp
new file mode 100644
index 0000000..0c2c110
--- /dev/null
+++ b/src/liborcus/spreadsheet_impl_types.hpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_SPREADSHEET_IMPL_TYPES_HPP
+#define INCLUDED_ORCUS_SPREADSHEET_IMPL_TYPES_HPP
+
+#include "orcus/spreadsheet/types.hpp"
+
+#include <iosfwd>
+
+namespace orcus { namespace spreadsheet { namespace detail {
+
+struct cell_position_t
+{
+ std::string_view sheet;
+ spreadsheet::row_t row;
+ spreadsheet::col_t col;
+
+ cell_position_t();
+ cell_position_t(std::string_view _sheet, spreadsheet::row_t _row, spreadsheet::col_t _col);
+ cell_position_t(const cell_position_t& r);
+
+ bool operator== (const cell_position_t& other) const;
+ bool operator!= (const cell_position_t& other) const;
+};
+
+std::ostream& operator<< (std::ostream& os, const cell_position_t& ref);
+
+bool operator< (const cell_position_t& left, const cell_position_t& right);
+
+}}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_interface.cpp b/src/liborcus/spreadsheet_interface.cpp
new file mode 100644
index 0000000..0accf63
--- /dev/null
+++ b/src/liborcus/spreadsheet_interface.cpp
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+#include <orcus/spreadsheet/import_interface_pivot.hpp>
+#include <orcus/spreadsheet/import_interface_view.hpp>
+#include <orcus/spreadsheet/export_interface.hpp>
+
+namespace orcus { namespace spreadsheet { namespace iface {
+
+import_sheet_view::~import_sheet_view() {}
+
+import_pivot_cache_definition::~import_pivot_cache_definition() {}
+
+import_pivot_cache_field_group::~import_pivot_cache_field_group() {}
+
+import_pivot_cache_records::~import_pivot_cache_records() {}
+
+import_shared_strings::~import_shared_strings() {}
+
+import_styles::~import_styles() {}
+
+import_font_style::~import_font_style() {}
+
+import_fill_style::~import_fill_style() {}
+
+import_border_style::~import_border_style() {}
+
+import_cell_protection::~import_cell_protection() {}
+
+import_number_format::~import_number_format() {}
+
+import_xf::~import_xf() {}
+
+import_cell_style::~import_cell_style() {}
+
+import_sheet_properties::~import_sheet_properties() {}
+
+import_named_expression::~import_named_expression() {}
+
+import_data_table::~import_data_table() {}
+
+import_auto_filter::~import_auto_filter() {}
+
+import_table::~import_table() {}
+
+import_conditional_format::~import_conditional_format() {}
+
+import_auto_filter* import_table::get_auto_filter()
+{
+ return nullptr;
+}
+
+import_formula::~import_formula() {}
+
+import_array_formula::~import_array_formula() {}
+
+import_sheet::~import_sheet() {}
+
+import_sheet_view* import_sheet::get_sheet_view()
+{
+ return nullptr;
+}
+
+import_sheet_properties* import_sheet::get_sheet_properties()
+{
+ return nullptr;
+}
+
+import_data_table* import_sheet::get_data_table()
+{
+ return nullptr;
+}
+
+import_auto_filter* import_sheet::get_auto_filter()
+{
+ return nullptr;
+}
+
+import_table* import_sheet::get_table()
+{
+ return nullptr;
+}
+
+import_conditional_format* import_sheet::get_conditional_format()
+{
+ return nullptr;
+}
+
+import_named_expression* import_sheet::get_named_expression()
+{
+ return nullptr;
+}
+
+import_array_formula* import_sheet::get_array_formula()
+{
+ return nullptr;
+}
+
+import_formula* import_sheet::get_formula()
+{
+ return nullptr;
+}
+
+import_global_settings::~import_global_settings() {}
+
+import_reference_resolver::~import_reference_resolver() {}
+
+import_factory::~import_factory() {}
+
+import_global_settings* import_factory::get_global_settings()
+{
+ return nullptr;
+}
+
+import_shared_strings* import_factory::get_shared_strings()
+{
+ return nullptr;
+}
+
+import_named_expression* import_factory::get_named_expression()
+{
+ return nullptr;
+}
+
+import_styles* import_factory::get_styles()
+{
+ return nullptr;
+}
+
+import_reference_resolver* import_factory::get_reference_resolver(formula_ref_context_t /*cxt*/)
+{
+ return nullptr;
+}
+
+import_pivot_cache_definition* import_factory::create_pivot_cache_definition(
+ orcus::spreadsheet::pivot_cache_id_t /*cache_id*/)
+{
+ return nullptr;
+}
+
+import_pivot_cache_records* import_factory::create_pivot_cache_records(
+ orcus::spreadsheet::pivot_cache_id_t /*cache_id*/)
+{
+ return nullptr;
+}
+
+export_sheet::~export_sheet() {}
+
+export_factory::~export_factory() {}
+
+}}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/spreadsheet_types.cpp b/src/liborcus/spreadsheet_types.cpp
new file mode 100644
index 0000000..3b7d357
--- /dev/null
+++ b/src/liborcus/spreadsheet_types.cpp
@@ -0,0 +1,763 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/spreadsheet/types.hpp>
+#include <orcus/exception.hpp>
+
+#include <limits>
+#include <sstream>
+
+#include <mdds/sorted_string_map.hpp>
+
+namespace orcus { namespace spreadsheet {
+
+namespace {
+
+namespace trf {
+
+using map_type = mdds::sorted_string_map<totals_row_function_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "average", totals_row_function_t::average },
+ { "count", totals_row_function_t::count },
+ { "countNums", totals_row_function_t::count_numbers },
+ { "custom", totals_row_function_t::custom },
+ { "max", totals_row_function_t::maximum },
+ { "min", totals_row_function_t::minimum },
+ { "none", totals_row_function_t::none },
+ { "stdDev", totals_row_function_t::standard_deviation },
+ { "sum", totals_row_function_t::sum },
+ { "var", totals_row_function_t::variance },
+};
+
+const map_type& get()
+{
+ static const map_type map(entries, std::size(entries), totals_row_function_t::none);
+ return map;
+}
+
+} // namespace trf
+
+namespace pc_group_by {
+
+using map_type = mdds::sorted_string_map<pivot_cache_group_by_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "days", pivot_cache_group_by_t::days },
+ { "hours", pivot_cache_group_by_t::hours },
+ { "minutes", pivot_cache_group_by_t::minutes },
+ { "months", pivot_cache_group_by_t::months },
+ { "quarters", pivot_cache_group_by_t::quarters },
+ { "range", pivot_cache_group_by_t::range },
+ { "seconds", pivot_cache_group_by_t::seconds },
+ { "years", pivot_cache_group_by_t::years },
+};
+
+const map_type& get()
+{
+ static const map_type map(entries, std::size(entries), pivot_cache_group_by_t::unknown);
+ return map;
+}
+
+} // namespace pc_group_by
+
+namespace error_value {
+
+using map_type = mdds::sorted_string_map<error_value_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] =
+{
+ { "#DIV/0!", error_value_t::div0 },
+ { "#N/A!", error_value_t::na },
+ { "#NAME?", error_value_t::name },
+ { "#NULL!", error_value_t::null },
+ { "#NUM!", error_value_t::num },
+ { "#REF!", error_value_t::ref },
+ { "#VALUE!", error_value_t::value },
+};
+
+const map_type& get()
+{
+ static const map_type map(entries, std::size(entries), error_value_t::unknown);
+ return map;
+}
+
+} // namespace error_value
+
+namespace named_colors {
+
+using map_type = mdds::sorted_string_map<color_rgb_t, mdds::string_view_map_entry>;
+
+constexpr map_type::entry entries[] =
+{
+ { "aliceblue", { 0xF0, 0xF8, 0xFF } },
+ { "antiquewhite", { 0xFA, 0xEB, 0xD7 } },
+ { "aquamarine", { 0x7F, 0xFF, 0xD4 } },
+ { "azure", { 0xF0, 0xFF, 0xFF } },
+ { "beige", { 0xF5, 0xF5, 0xDC } },
+ { "bisque", { 0xFF, 0xE4, 0xC4 } },
+ { "black", { 0x00, 0x00, 0x00 } },
+ { "blanchedalmond", { 0xFF, 0xEB, 0xCD } },
+ { "blue", { 0x00, 0x00, 0xFF } },
+ { "blueviolet", { 0x8A, 0x2B, 0xE2 } },
+ { "brown", { 0xA5, 0x2A, 0x2A } },
+ { "burlywood", { 0xDE, 0xB8, 0x87 } },
+ { "cadetblue", { 0x5F, 0x9E, 0xA0 } },
+ { "chartreuse", { 0x7F, 0xFF, 0x00 } },
+ { "chocolate", { 0xD2, 0x69, 0x1E } },
+ { "coral", { 0xFF, 0x7F, 0x50 } },
+ { "cornflowerblue", { 0x64, 0x95, 0xED } },
+ { "cornsilk", { 0xFF, 0xF8, 0xDC } },
+ { "crimson", { 0xDC, 0x14, 0x3C } },
+ { "cyan", { 0x00, 0xFF, 0xFF } },
+ { "darkblue", { 0x00, 0x00, 0x8B } },
+ { "darkcyan", { 0x00, 0x8B, 0x8B } },
+ { "darkgoldenrod", { 0xB8, 0x86, 0x0B } },
+ { "darkgray", { 0xA9, 0xA9, 0xA9 } },
+ { "darkgreen", { 0x00, 0x64, 0x00 } },
+ { "darkkhaki", { 0xBD, 0xB7, 0x6B } },
+ { "darkmagenta", { 0x8B, 0x00, 0x8B } },
+ { "darkolivegreen", { 0x55, 0x6B, 0x2F } },
+ { "darkorange", { 0xFF, 0x8C, 0x00 } },
+ { "darkorchid", { 0x99, 0x32, 0xCC } },
+ { "darkred", { 0x8B, 0x00, 0x00 } },
+ { "darksalmon", { 0xE9, 0x96, 0x7A } },
+ { "darkseagreen", { 0x8F, 0xBC, 0x8F } },
+ { "darkslateblue", { 0x48, 0x3D, 0x8B } },
+ { "darkslategray", { 0x2F, 0x4F, 0x4F } },
+ { "darkturquoise", { 0x00, 0xCE, 0xD1 } },
+ { "darkviolet", { 0x94, 0x00, 0xD3 } },
+ { "deeppink", { 0xFF, 0x14, 0x93 } },
+ { "deepskyblue", { 0x00, 0xBF, 0xFF } },
+ { "dimgray", { 0x69, 0x69, 0x69 } },
+ { "dodgerblue", { 0x1E, 0x90, 0xFF } },
+ { "firebrick", { 0xB2, 0x22, 0x22 } },
+ { "floralwhite", { 0xFF, 0xFA, 0xF0 } },
+ { "forestgreen", { 0x22, 0x8B, 0x22 } },
+ { "gainsboro", { 0xDC, 0xDC, 0xDC } },
+ { "ghostwhite", { 0xF8, 0xF8, 0xFF } },
+ { "gold", { 0xFF, 0xD7, 0x00 } },
+ { "goldenrod", { 0xDA, 0xA5, 0x20 } },
+ { "gray", { 0x80, 0x80, 0x80 } },
+ { "green", { 0x00, 0x80, 0x00 } },
+ { "greenyellow", { 0xAD, 0xFF, 0x2F } },
+ { "honeydew", { 0xF0, 0xFF, 0xF0 } },
+ { "hotpink", { 0xFF, 0x69, 0xB4 } },
+ { "indianred", { 0xCD, 0x5C, 0x5C } },
+ { "indigo", { 0x4B, 0x00, 0x82 } },
+ { "ivory", { 0xFF, 0xFF, 0xF0 } },
+ { "khaki", { 0xF0, 0xE6, 0x8C } },
+ { "lavender", { 0xE6, 0xE6, 0xFA } },
+ { "lavenderblush", { 0xFF, 0xF0, 0xF5 } },
+ { "lawngreen", { 0x7C, 0xFC, 0x00 } },
+ { "lemonchiffon", { 0xFF, 0xFA, 0xCD } },
+ { "lightblue", { 0xAD, 0xD8, 0xE6 } },
+ { "lightcoral", { 0xF0, 0x80, 0x80 } },
+ { "lightcyan", { 0xE0, 0xFF, 0xFF } },
+ { "lightgoldenrodyellow", { 0xFA, 0xFA, 0xD2 } },
+ { "lightgray", { 0xD3, 0xD3, 0xD3 } },
+ { "lightgreen", { 0x90, 0xEE, 0x90 } },
+ { "lightpink", { 0xFF, 0xB6, 0xC1 } },
+ { "lightsalmon", { 0xFF, 0xA0, 0x7A } },
+ { "lightseagreen", { 0x20, 0xB2, 0xAA } },
+ { "lightskyblue", { 0x87, 0xCE, 0xFA } },
+ { "lightslategray", { 0x77, 0x88, 0x99 } },
+ { "lightsteelblue", { 0xB0, 0xC4, 0xDE } },
+ { "lightyellow", { 0xFF, 0xFF, 0xE0 } },
+ { "lime", { 0x00, 0xFF, 0x00 } },
+ { "limegreen", { 0x32, 0xCD, 0x32 } },
+ { "linen", { 0xFA, 0xF0, 0xE6 } },
+ { "magenta", { 0xFF, 0x00, 0xFF } },
+ { "maroon", { 0x80, 0x00, 0x00 } },
+ { "mediumaquamarine", { 0x66, 0xCD, 0xAA } },
+ { "mediumblue", { 0x00, 0x00, 0xCD } },
+ { "mediumorchid", { 0xBA, 0x55, 0xD3 } },
+ { "mediumpurple", { 0x93, 0x70, 0xDB } },
+ { "mediumseagreen", { 0x3C, 0xB3, 0x71 } },
+ { "mediumslateblue", { 0x7B, 0x68, 0xEE } },
+ { "mediumspringgreen", { 0x00, 0xFA, 0x9A } },
+ { "mediumturquoise", { 0x48, 0xD1, 0xCC } },
+ { "mediumvioletred", { 0xC7, 0x15, 0x85 } },
+ { "midnightblue", { 0x19, 0x19, 0x70 } },
+ { "mintcream", { 0xF5, 0xFF, 0xFA } },
+ { "mistyrose", { 0xFF, 0xE4, 0xE1 } },
+ { "moccasin", { 0xFF, 0xE4, 0xB5 } },
+ { "navajowhite", { 0xFF, 0xDE, 0xAD } },
+ { "navy", { 0x00, 0x00, 0x80 } },
+ { "oldlace", { 0xFD, 0xF5, 0xE6 } },
+ { "olive", { 0x80, 0x80, 0x00 } },
+ { "olivedrab", { 0x6B, 0x8E, 0x23 } },
+ { "orange", { 0xFF, 0xA5, 0x00 } },
+ { "orangered", { 0xFF, 0x45, 0x00 } },
+ { "orchid", { 0xDA, 0x70, 0xD6 } },
+ { "palegoldenrod", { 0xEE, 0xE8, 0xAA } },
+ { "palegreen", { 0x98, 0xFB, 0x98 } },
+ { "paleturquoise", { 0xAF, 0xEE, 0xEE } },
+ { "palevioletred", { 0xDB, 0x70, 0x93 } },
+ { "papayawhip", { 0xFF, 0xEF, 0xD5 } },
+ { "peachpuff", { 0xFF, 0xDA, 0xB9 } },
+ { "peru", { 0xCD, 0x85, 0x3F } },
+ { "pink", { 0xFF, 0xC0, 0xCB } },
+ { "plum", { 0xDD, 0xA0, 0xDD } },
+ { "powderblue", { 0xB0, 0xE0, 0xE6 } },
+ { "purple", { 0x80, 0x00, 0x80 } },
+ { "red", { 0xFF, 0x00, 0x00 } },
+ { "rosybrown", { 0xBC, 0x8F, 0x8F } },
+ { "royalblue", { 0x41, 0x69, 0xE1 } },
+ { "saddlebrown", { 0x8B, 0x45, 0x13 } },
+ { "salmon", { 0xFA, 0x80, 0x72 } },
+ { "sandybrown", { 0xF4, 0xA4, 0x60 } },
+ { "seagreen", { 0x2E, 0x8B, 0x57 } },
+ { "seashell", { 0xFF, 0xF5, 0xEE } },
+ { "sienna", { 0xA0, 0x52, 0x2D } },
+ { "silver", { 0xC0, 0xC0, 0xC0 } },
+ { "skyblue", { 0x87, 0xCE, 0xEB } },
+ { "slateblue", { 0x6A, 0x5A, 0xCD } },
+ { "slategray", { 0x70, 0x80, 0x90 } },
+ { "snow", { 0xFF, 0xFA, 0xFA } },
+ { "springgreen", { 0x00, 0xFF, 0x7F } },
+ { "steelblue", { 0x46, 0x82, 0xB4 } },
+ { "tan", { 0xD2, 0xB4, 0x8C } },
+ { "teal", { 0x00, 0x80, 0x80 } },
+ { "thistle", { 0xD8, 0xBF, 0xD8 } },
+ { "tomato", { 0xFF, 0x63, 0x47 } },
+ { "turquoise", { 0x40, 0xE0, 0xD0 } },
+ { "violet", { 0xEE, 0x82, 0xEE } },
+ { "wheat", { 0xF5, 0xDE, 0xB3 } },
+ { "white", { 0xFF, 0xFF, 0xFF } },
+ { "whitesmoke", { 0xF5, 0xF5, 0xF5 } },
+ { "yellow", { 0xFF, 0xFF, 0x00 } },
+ { "yellowgreen", { 0x9A, 0xCD, 0x32 } },
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), { 0x00, 0x00, 0x00 });
+ return mt;
+}
+
+} // namespace named_color
+
+namespace formula_error_policy {
+
+using map_type = mdds::sorted_string_map<formula_error_policy_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "fail", formula_error_policy_t::fail },
+ { "skip", formula_error_policy_t::skip },
+};
+
+const map_type& get()
+{
+ static map_type mt(entries, std::size(entries), formula_error_policy_t::unknown);
+ return mt;
+}
+
+}
+
+class to_size_t
+{
+ std::size_t m_value;
+
+public:
+ template<typename T>
+ to_size_t(T v) : m_value(static_cast<std::size_t>(v))
+ {
+ static_assert(std::is_enum_v<T>, "source value type must be enum!");
+ }
+
+ operator std::size_t() const
+ {
+ return m_value;
+ }
+};
+
+std::ostream& write_name_for_pos(
+ std::ostream& os, const std::string_view* names, std::size_t n_names, to_size_t pos)
+{
+ if (pos < n_names)
+ os << names[pos];
+ else
+ os << "???";
+
+ return os;
+}
+
+} // anonymous namespace
+
+address_t to_rc_address(const src_address_t& r)
+{
+ address_t ret;
+ ret.row = r.row;
+ ret.column = r.column;
+ return ret;
+}
+
+range_t to_rc_range(const src_range_t& r)
+{
+ range_t ret;
+ ret.first.row = r.first.row;
+ ret.first.column = r.first.column;
+ ret.last.row = r.last.row;
+ ret.last.column = r.last.column;
+ return ret;
+}
+
+bool operator== (const address_t& left, const address_t& right)
+{
+ return left.column == right.column && left.row == right.row;
+}
+
+bool operator!= (const address_t& left, const address_t& right)
+{
+ return !operator== (left, right);
+}
+
+bool operator== (const src_address_t& left, const src_address_t& right)
+{
+ return left.column == right.column && left.row == right.row;
+}
+
+bool operator!= (const src_address_t& left, const src_address_t& right)
+{
+ return !operator== (left, right);
+}
+
+bool operator== (const range_t& left, const range_t& right)
+{
+ return left.first == right.first && left.last == right.last;
+}
+
+bool operator!= (const range_t& left, const range_t& right)
+{
+ return !operator== (left, right);
+}
+
+bool operator== (const src_range_t& left, const src_range_t& right)
+{
+ return left.first == right.first && left.last == right.last;
+}
+
+bool operator!= (const src_range_t& left, const src_range_t& right)
+{
+ return !operator== (left, right);
+}
+
+bool operator< (const range_t& left, const range_t& right)
+{
+ if (left.first.row != right.first.row)
+ return left.first.row < right.first.row;
+
+ if (left.first.column != right.first.column)
+ return left.first.column < right.first.column;
+
+ if (left.last.row != right.last.row)
+ return left.last.row < right.last.row;
+
+ return left.last.column < right.last.column;
+}
+
+bool operator> (const range_t& left, const range_t& right)
+{
+ if (left.first.row != right.first.row)
+ return left.first.row > right.first.row;
+
+ if (left.first.column != right.first.column)
+ return left.first.column > right.first.column;
+
+ if (left.last.row != right.last.row)
+ return left.last.row > right.last.row;
+
+ return left.last.column > right.last.column;
+}
+
+range_t& operator+= (range_t& left, const address_t& right)
+{
+ left.first.column += right.column;
+ left.first.row += right.row;
+ left.last.column += right.column;
+ left.last.row += right.row;
+
+ return left;
+}
+
+range_t& operator-= (range_t& left, const address_t& right)
+{
+ left.first.column -= right.column;
+ left.first.row -= right.row;
+ left.last.column -= right.column;
+ left.last.row -= right.row;
+
+ return left;
+}
+
+std::ostream& operator<< (std::ostream& os, const address_t& v)
+{
+ os << "(column=" << v.column << ",row=" << v.row << ")";
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const src_address_t& v)
+{
+ os << "(sheet=" << v.sheet << ",column=" << v.column << ",row=" << v.row << ")";
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const range_t& v)
+{
+ os << v.first << "-" << v.last;
+ return os;
+}
+
+col_width_t get_default_column_width()
+{
+ return std::numeric_limits<col_width_t>::max();
+}
+
+row_height_t get_default_row_height()
+{
+ return std::numeric_limits<row_height_t>::max();
+}
+
+totals_row_function_t to_totals_row_function_enum(std::string_view s)
+{
+ return trf::get().find(s);
+}
+
+pivot_cache_group_by_t to_pivot_cache_group_by_enum(std::string_view s)
+{
+ return pc_group_by::get().find(s);
+}
+
+error_value_t to_error_value_enum(std::string_view s)
+{
+ return error_value::get().find(s);
+}
+
+color_rgb_t to_color_rgb(std::string_view s)
+{
+ const char* p = s.data();
+ std::size_t n = s.size();
+
+ // RGB string is a 6-character string representing 24-bit hexadecimal
+ // number e.g. '004A12' (red - green - blue)
+
+ // store the original head position and size.
+ const char* p0 = p;
+ size_t n0 = n;
+
+ if (n == 7 && *p == '#')
+ {
+ // Skip the leading '#' character.
+ --n;
+ ++p;
+ }
+
+ if (n != 6)
+ {
+ std::ostringstream os;
+ os << "'" << std::string_view(p0, n0) << "' is not a valid RGB color string.";
+ throw value_error(os.str());
+ }
+
+ color_rgb_t ret;
+ long converted = 0;
+ const char* p_end = p + n;
+
+ for (; p != p_end; ++p)
+ {
+ converted <<= 4;
+
+ char c = *p;
+ long this_val = 0;
+
+ if ('0' <= c && c <= '9')
+ this_val = c - '0';
+ else if ('a' <= c && c <= 'f')
+ this_val = 10 + c - 'a';
+ else if ('A' <= c && c <= 'F')
+ this_val = 10 + c - 'A';
+ else
+ {
+ std::ostringstream os;
+ os << "'" << std::string_view(p0, n0) << "' is not a valid RGB color string.";
+ throw value_error(os.str());
+ }
+
+ converted += this_val;
+ }
+
+ ret.blue = (0x000000FF & converted);
+ converted >>= 8;
+ ret.green = (0x000000FF & converted);
+ converted >>= 8;
+ ret.red = (0x000000FF & converted);
+
+ return ret;
+}
+
+color_rgb_t to_color_rgb_from_name(std::string_view s)
+{
+ return named_colors::get().find(s);
+}
+
+formula_error_policy_t to_formula_error_policy(std::string_view s)
+{
+ return formula_error_policy::get().find(s);
+}
+
+std::ostream& operator<< (std::ostream& os, error_value_t ev)
+{
+ switch (ev)
+ {
+ case error_value_t::div0:
+ os << error_value::entries[0].key;
+ break;
+ case error_value_t::na:
+ os << error_value::entries[1].key;
+ break;
+ case error_value_t::name:
+ os << error_value::entries[2].key;
+ break;
+ case error_value_t::null:
+ os << error_value::entries[3].key;
+ break;
+ case error_value_t::num:
+ os << error_value::entries[4].key;
+ break;
+ case error_value_t::ref:
+ os << error_value::entries[5].key;
+ break;
+ case error_value_t::value:
+ os << error_value::entries[6].key;
+ break;
+ case error_value_t::unknown:
+ default:
+ ;
+ }
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, border_style_t border)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "none",
+ "solid",
+ "dash_dot",
+ "dash_dot_dot",
+ "dashed",
+ "dotted",
+ "double_border",
+ "hair",
+ "medium",
+ "medium_dash_dot",
+ "medium_dash_dot_dot",
+ "medium_dashed",
+ "slant_dash_dot",
+ "thick",
+ "thin",
+ "double_thin",
+ "fine_dashed",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), border);
+}
+
+std::ostream& operator<< (std::ostream& os, formula_grammar_t grammar)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "xls_xml",
+ "xlsx",
+ "ods",
+ "gnumeric"
+ };
+
+ return write_name_for_pos(os, names, std::size(names), grammar);
+}
+
+std::ostream& operator<< (std::ostream& os, underline_t uline)
+{
+ static constexpr std::string_view names[] = {
+ "none",
+ "single_line",
+ "single_accounting",
+ "double_line",
+ "double_accounting",
+ "dotted",
+ "dash",
+ "long_dash",
+ "dot_dash",
+ "dot_dot_dash",
+ "wave",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), uline);
+}
+
+std::ostream& operator<< (std::ostream& os, underline_width_t ulwidth)
+{
+ static constexpr std::string_view names[] = {
+ "none",
+ "automatic",
+ "bold",
+ "dash",
+ "medium",
+ "thick",
+ "thin",
+ "percent",
+ "positive_integer",
+ "positive_length",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), ulwidth);
+}
+
+std::ostream& operator<< (std::ostream& os, underline_mode_t ulmode)
+{
+ static constexpr std::string_view names[] = {
+ "continuous",
+ "skip_white_space",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), ulmode);
+}
+
+std::ostream& operator<< (std::ostream& os, underline_type_t ultype)
+{
+ static constexpr std::string_view names[] = {
+ "none",
+ "single_type",
+ "double_type",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), ultype);
+}
+
+std::ostream& operator<< (std::ostream& os, hor_alignment_t halign)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "left",
+ "center",
+ "right",
+ "justified",
+ "distributed",
+ "filled",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), halign);
+}
+
+std::ostream& operator<< (std::ostream& os, ver_alignment_t valign)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "top",
+ "middle",
+ "bottom",
+ "justified",
+ "distributed",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), valign);
+}
+
+std::ostream& operator<< (std::ostream& os, const color_rgb_t& color)
+{
+ os << "(r=" << (int)color.red << ",g=" << (int)color.green << ",b=" << (int)color.blue << ")";
+ return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const fill_pattern_t& fill)
+{
+ static constexpr std::string_view names[] = {
+ "none",
+ "solid",
+ "dark_down",
+ "dark_gray",
+ "dark_grid",
+ "dark_horizontal",
+ "dark_trellis",
+ "dark_up",
+ "dark_vertical",
+ "gray_0625",
+ "gray_125",
+ "light_down",
+ "light_gray",
+ "light_grid",
+ "light_horizontal",
+ "light_trellis",
+ "light_up",
+ "light_vertical",
+ "medium_gray",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), fill);
+}
+
+std::ostream& operator<< (std::ostream& os, const strikethrough_style_t& ss)
+{
+ static constexpr std::string_view names[] = {
+ "none",
+ "solid",
+ "dash",
+ "dot_dash",
+ "dot_dot_dash",
+ "dotted",
+ "long_dash",
+ "wave",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), ss);
+}
+
+std::ostream& operator<< (std::ostream& os, const strikethrough_type_t& st)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "none",
+ "single_type",
+ "double_type",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), st);
+}
+
+std::ostream& operator<< (std::ostream& os, const strikethrough_width_t& sw)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "width_auto",
+ "thin",
+ "medium",
+ "thick",
+ "bold",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), sw);
+}
+
+std::ostream& operator<< (std::ostream& os, const strikethrough_text_t& st)
+{
+ static constexpr std::string_view names[] = {
+ "unknown",
+ "slash",
+ "cross",
+ };
+
+ return write_name_for_pos(os, names, std::size(names), st);
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/string_helper.cpp b/src/liborcus/string_helper.cpp
new file mode 100644
index 0000000..3bf9c63
--- /dev/null
+++ b/src/liborcus/string_helper.cpp
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "string_helper.hpp"
+
+namespace orcus {
+
+std::vector<std::string_view> string_helper::split_string(std::string_view str, const char sep)
+{
+ std::vector<std::string_view> ret;
+
+ std::size_t len = 0;
+ const char* start = str.data();
+ for (size_t i = 0, n = str.size(); i < n; ++i)
+ {
+ if (str[i] == sep)
+ {
+ ret.emplace_back(start, len);
+
+ // if not at the end move the start string
+ if (i < n-1)
+ start = start + len + 1;
+
+ len = 0;
+ }
+ else
+ ++len;
+ }
+ ret.emplace_back(start, len);
+
+ return ret;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/string_helper.hpp b/src/liborcus/string_helper.hpp
new file mode 100644
index 0000000..1885a33
--- /dev/null
+++ b/src/liborcus/string_helper.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <vector>
+#include <string_view>
+
+namespace orcus {
+
+class string_helper
+{
+public:
+ static std::vector<std::string_view> split_string(std::string_view str, const char sep);
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_context.cpp b/src/liborcus/xls_xml_context.cpp
new file mode 100644
index 0000000..ed30616
--- /dev/null
+++ b/src/liborcus/xls_xml_context.cpp
@@ -0,0 +1,2396 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xls_xml_context.hpp"
+#include "xls_xml_namespace_types.hpp"
+#include "xls_xml_token_constants.hpp"
+#include "spreadsheet_iface_util.hpp"
+#include "impl_utils.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+#include <orcus/spreadsheet/import_interface_view.hpp>
+#include <orcus/measurement.hpp>
+
+#include <mdds/sorted_string_map.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <limits>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+ss::color_rgb_t to_rgb(std::string_view s)
+{
+ if (!s.empty() && s[0] == '#')
+ return ss::to_color_rgb(s);
+ else
+ {
+ // This may be a color name. Lower-case it before sending it to the
+ // function.
+ std::string s_lower(s.size(), '\0');
+ const char* p = s.data();
+ std::transform(p, p + s.size(), s_lower.begin(),
+ [](char c) -> char
+ {
+ if ('A' <= c && c <= 'Z')
+ c += 'a' - 'A';
+ return c;
+ }
+ );
+
+ return ss::to_color_rgb_from_name(s_lower);
+ }
+}
+
+namespace border_dir {
+
+using map_type = mdds::sorted_string_map<ss::border_direction_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Bottom", ss::border_direction_t::bottom },
+ { "DiagonalLeft", ss::border_direction_t::diagonal_tl_br },
+ { "DiagonalRight", ss::border_direction_t::diagonal_bl_tr },
+ { "Left", ss::border_direction_t::left },
+ { "Right", ss::border_direction_t::right },
+ { "Top", ss::border_direction_t::top },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::border_direction_t::unknown);
+ return mt;
+}
+
+} // namespace border_dir
+
+namespace border_style {
+
+using map_type = mdds::sorted_string_map<ss::border_style_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Continuous", ss::border_style_t::solid },
+ { "Dash", ss::border_style_t::dashed },
+ { "DashDot", ss::border_style_t::dash_dot },
+ { "DashDotDot", ss::border_style_t::dash_dot_dot },
+ { "Dot", ss::border_style_t::dotted },
+ { "Double", ss::border_style_t::double_border },
+ { "SlantDashDot", ss::border_style_t::slant_dash_dot },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::border_style_t::unknown);
+ return mt;
+}
+
+}
+
+namespace hor_align {
+
+using map_type = mdds::sorted_string_map<ss::hor_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Center", ss::hor_alignment_t::center },
+ { "Distributed", ss::hor_alignment_t::distributed },
+ { "Justify", ss::hor_alignment_t::justified },
+ { "Left", ss::hor_alignment_t::left },
+ { "Right", ss::hor_alignment_t::right },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::hor_alignment_t::unknown);
+ return mt;
+}
+
+}
+
+namespace ver_align {
+
+using map_type = mdds::sorted_string_map<ss::ver_alignment_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Bottom", ss::ver_alignment_t::bottom },
+ { "Center", ss::ver_alignment_t::middle },
+ { "Distributed", ss::ver_alignment_t::distributed },
+ { "Justify", ss::ver_alignment_t::justified },
+ { "Top", ss::ver_alignment_t::top },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::ver_alignment_t::unknown);
+ return mt;
+}
+
+}
+
+namespace num_format {
+
+using map_type = mdds::sorted_string_map<std::string_view, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Currency", "$#,##0.00_);[Red]($#,##0.00)" },
+ { "Euro Currency", "[$\xe2\x82\xac-x-euro2] #,##0.00_);[Red]([$\xe2\x82\xac-x-euro2] #,##0.00)" },
+ { "Fixed", "0.00" },
+ { "General Date", "m/d/yyyy h:mm" },
+ { "General Number", "General" },
+ { "Long Date", "d-mmm-yy" },
+ { "Long Time", "h:mm:ss AM/PM" },
+ { "Medium Date", "d-mmm-yy" },
+ { "Medium Time", "h:mm AM/PM" },
+ { "On/Off", "\"On\";\"On\";\"Off\"" },
+ { "Percent", "0.00%" },
+ { "Scientific", "0.00E+00" },
+ { "Short Date", "m/d/yyyy" },
+ { "Short Time", "h:mm" },
+ { "Standard", "#,##0.00" },
+ { "True/False", "\"True\";\"True\";\"False\"" },
+ { "Yes/No", "\"Yes\";\"Yes\";\"No\"" },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), std::string_view{});
+ return mt;
+}
+
+} // namespace num_format
+
+namespace underline {
+
+using map_type = mdds::sorted_string_map<ss::underline_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "Double", ss::underline_t::double_line },
+ { "DoubleAccounting", ss::underline_t::double_accounting },
+ { "None", ss::underline_t::none },
+ { "Single", ss::underline_t::single_line },
+ { "SingleAccounting", ss::underline_t::single_accounting },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::underline_t::none);
+ return mt;
+}
+
+} // namespace underline
+
+} // anonymous namespace
+
+void xls_xml_data_context::format_type::merge(const format_type& fmt)
+{
+ if (fmt.bold)
+ bold = fmt.bold;
+
+ if (fmt.italic)
+ italic = fmt.italic;
+
+ if (fmt.underline)
+ underline = fmt.underline;
+
+ if (fmt.strikethrough)
+ strikethrough = fmt.strikethrough;
+
+ if (fmt.subscript)
+ subscript = fmt.subscript;
+
+ if (fmt.superscript)
+ superscript = fmt.superscript;
+
+ if (fmt.font_face)
+ font_face = fmt.font_face;
+
+ if (fmt.font_size)
+ font_size = fmt.font_size;
+
+ if (fmt.color)
+ color = fmt.color;
+}
+
+bool xls_xml_data_context::format_type::formatted() const
+{
+ return bold || italic || underline || strikethrough
+ || subscript || superscript || font_face || font_size
+ || color;
+}
+
+xls_xml_data_context::string_segment_type::string_segment_type(std::string_view _str) :
+ str(_str) {}
+
+xls_xml_data_context::xls_xml_data_context(
+ session_context& session_cxt, const tokens& tokens, xls_xml_context& parent_cxt) :
+ xml_context_base(session_cxt, tokens),
+ m_parent_cxt(parent_cxt),
+ m_cell_type(ct_unknown),
+ m_cell_value(std::numeric_limits<double>::quiet_NaN())
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_xls_xml_ss, XML_Data }, // root element
+ { NS_xls_xml_html, XML_B, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_B },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_I },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_S },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_Sub },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_Sup },
+ { NS_xls_xml_html, XML_Font, NS_xls_xml_html, XML_U },
+ { NS_xls_xml_html, XML_I, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_html, XML_S, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_html, XML_Sub, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_html, XML_Sup, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_html, XML_U, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_B },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_Font },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_I },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_S },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_Sub },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_Sup },
+ { NS_xls_xml_ss, XML_Data, NS_xls_xml_html, XML_U },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+xls_xml_data_context::~xls_xml_data_context() {}
+
+xml_context_base* xls_xml_data_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xls_xml_data_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xls_xml_data_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Data:
+ start_element_data(parent, attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_xls_xml_html)
+ {
+ switch (name)
+ {
+ case XML_B:
+ m_format_stack.emplace_back();
+ m_format_stack.back().bold = true;
+ update_current_format();
+ break;
+ case XML_I:
+ m_format_stack.emplace_back();
+ m_format_stack.back().italic = true;
+ update_current_format();
+ break;
+ case XML_U:
+ m_format_stack.emplace_back();
+ m_format_stack.back().underline = true;
+ update_current_format();
+ break;
+ case XML_S:
+ m_format_stack.emplace_back();
+ m_format_stack.back().strikethrough = true;
+ update_current_format();
+ break;
+ case XML_Sub:
+ m_format_stack.emplace_back();
+ m_format_stack.back().subscript = true;
+ update_current_format();
+ break;
+ case XML_Sup:
+ m_format_stack.emplace_back();
+ m_format_stack.back().superscript = true;
+ update_current_format();
+ break;
+ case XML_Font:
+ {
+ m_format_stack.emplace_back();
+ format_type& fmt = m_format_stack.back();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (ns == NS_xls_xml_html)
+ {
+ switch (attr.name)
+ {
+ case XML_Color:
+ fmt.color = to_rgb(attr.value);
+ break;
+ case XML_Face:
+ fmt.font_face = attr.transient ? intern(attr.value) : attr.value;
+ break;
+ case XML_Size:
+ {
+ const char* p_end = nullptr;
+ double v = to_double(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ fmt.font_size = v;
+ break;
+ }
+ }
+ }
+ }
+
+ update_current_format();
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+void xls_xml_data_context::characters(std::string_view str, bool transient)
+{
+ if (str.empty())
+ return;
+
+ switch (m_cell_type)
+ {
+ case ct_unknown:
+ break;
+ case ct_string:
+ {
+ if (transient)
+ m_cell_string.emplace_back(intern(str));
+ else
+ m_cell_string.emplace_back(str);
+
+ if (m_current_format.formatted())
+ {
+ // Apply the current format to this string segment.
+ string_segment_type& ss = m_cell_string.back();
+ ss.format = m_current_format;
+ ss.formatted = true;
+ }
+
+ break;
+ }
+ case ct_number:
+ {
+ m_cell_value = to_double(str);
+ break;
+ }
+ case ct_datetime:
+ m_cell_datetime = date_time_t::from_chars(str);
+ break;
+ default:
+ {
+ std::ostringstream os;
+ os << "unknown cell type '" << m_cell_type << "': characters='" << str << "'";
+ warn(os.str());
+ }
+ }
+}
+
+bool xls_xml_data_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Data:
+ end_element_data();
+ break;
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_xls_xml_html)
+ {
+ switch (name)
+ {
+ case XML_B:
+ case XML_I:
+ case XML_U:
+ case XML_S:
+ case XML_Sub:
+ case XML_Sup:
+ case XML_Font:
+ assert(!m_format_stack.empty());
+ m_format_stack.pop_back();
+ update_current_format();
+ break;
+ default:
+ ;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void xls_xml_data_context::reset()
+{
+ m_format_stack.clear();
+ m_format_stack.emplace_back(); // set default format.
+ update_current_format();
+
+ m_cell_type = ct_unknown;
+ m_cell_string.clear();
+
+ m_cell_value = std::numeric_limits<double>::quiet_NaN();
+ m_cell_datetime = date_time_t();
+}
+
+void xls_xml_data_context::start_element_data(
+ const xml_token_pair_t& /*parent*/, const xml_token_attrs_t& attrs)
+{
+ m_cell_type = ct_unknown;
+ m_cell_string.clear();
+ m_cell_datetime = date_time_t();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Type:
+ {
+ if (attr.value == "String")
+ m_cell_type = ct_string;
+ else if (attr.value == "Number")
+ m_cell_type = ct_number;
+ else if (attr.value == "DateTime")
+ m_cell_type = ct_datetime;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+}
+
+void xls_xml_data_context::end_element_data()
+{
+ auto formula = m_parent_cxt.pop_and_clear_formula();
+
+ if (!formula.empty())
+ {
+ if (m_parent_cxt.is_array_formula())
+ store_array_formula_parent_cell(formula);
+ else
+ push_formula_cell(formula);
+ m_cell_type = ct_unknown;
+ return;
+ }
+
+ if (handle_array_formula_result())
+ {
+ m_cell_type = ct_unknown;
+ return;
+ }
+
+ ss::iface::import_sheet* sheet = m_parent_cxt.get_import_sheet();
+ ss::address_t pos = m_parent_cxt.get_current_pos();
+
+ switch (m_cell_type)
+ {
+ case ct_unknown:
+ break;
+ case ct_number:
+ sheet->set_value(pos.row, pos.column, m_cell_value);
+ break;
+ case ct_string:
+ {
+ ss::iface::import_shared_strings* ss =
+ m_parent_cxt.get_import_factory()->get_shared_strings();
+
+ if (!ss)
+ break;
+
+ if (m_cell_string.empty())
+ break;
+
+ if (m_cell_string.size() == 1 && !m_cell_string[0].formatted)
+ {
+ // Unformatted string.
+ std::string_view s = m_cell_string.back().str;
+ sheet->set_string(pos.row, pos.column, ss->append(s));
+ }
+ else
+ {
+ // Formatted string. Note that an absence of a format type
+ // appears to mean its negative value is implied.
+
+ for (const string_segment_type& sstr : m_cell_string)
+ {
+ if (sstr.format.bold)
+ ss->set_segment_bold(*sstr.format.bold);
+ else
+ ss->set_segment_bold(false); // implied
+
+ if (sstr.format.italic)
+ ss->set_segment_italic(*sstr.format.italic);
+ else
+ ss->set_segment_italic(false); // implied
+
+ if (sstr.format.font_face)
+ ss->set_segment_font_name(*sstr.format.font_face);
+
+ if (sstr.format.font_size)
+ ss->set_segment_font_size(*sstr.format.font_size);
+
+ if (sstr.format.color)
+ ss->set_segment_font_color(
+ 255,
+ sstr.format.color->red,
+ sstr.format.color->green,
+ sstr.format.color->blue);
+
+ ss->append_segment(sstr.str);
+ }
+
+ size_t si = ss->commit_segments();
+ sheet->set_string(pos.row, pos.column, si);
+ }
+
+ m_cell_string.clear();
+
+ break;
+ }
+ case ct_datetime:
+ {
+ sheet->set_date_time(
+ pos.row, pos.column,
+ m_cell_datetime.year, m_cell_datetime.month, m_cell_datetime.day,
+ m_cell_datetime.hour, m_cell_datetime.minute, m_cell_datetime.second);
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os <<"unknown cell type '" << m_cell_type << "': value not pushed.";
+ warn(os.str());
+ }
+ }
+
+ m_cell_type = ct_unknown;
+}
+
+bool xls_xml_data_context::handle_array_formula_result()
+{
+ xls_xml_context::array_formulas_type& store = m_parent_cxt.get_array_formula_store();
+ ss::address_t cur_pos = m_parent_cxt.get_current_pos();
+
+ // See if the current cell is within an array formula range.
+ auto it = store.begin(), ite = store.end();
+
+ while (it != ite)
+ {
+ const ss::range_t& ref = it->first;
+ xls_xml_context::array_formula_type& af = *it->second;
+
+ if (ref.last.row < cur_pos.row)
+ {
+ // If this result range lies above the current row, push the array
+ // and delete it from the list.
+
+ ss::iface::import_sheet* sheet = m_parent_cxt.get_import_sheet();
+ ss::iface::import_array_formula* array = nullptr;
+
+ if (sheet)
+ array = sheet->get_array_formula();
+
+ if (array)
+ {
+ push_array_formula(
+ array, ref, af.formula, ss::formula_grammar_t::xls_xml, af.results);
+ }
+
+ store.erase(it++);
+ continue;
+ }
+
+ if (cur_pos.column < ref.first.column || ref.last.column < cur_pos.column ||
+ cur_pos.row < ref.first.row || ref.last.row < cur_pos.row)
+ {
+ // This cell is not within this array formula range. Move on to
+ // the next one.
+ ++it;
+ continue;
+ }
+
+ size_t row_offset = cur_pos.row - ref.first.row;
+ size_t col_offset = cur_pos.column - ref.first.column;
+ range_formula_results& res = af.results;
+ push_array_result(res, row_offset, col_offset);
+
+ return true;
+ }
+
+ return false;
+}
+
+void xls_xml_data_context::push_array_result(
+ range_formula_results& res, size_t row_offset, size_t col_offset)
+{
+ switch (m_cell_type)
+ {
+ case ct_number:
+ {
+ res.set(row_offset, col_offset, m_cell_value);
+ break;
+ }
+ case ct_unknown:
+ case ct_datetime:
+ case ct_string:
+ default:
+ {
+ std::ostringstream os;
+ os << "unknown cell type '" << m_cell_type << "': value not pushed.";
+ warn(os.str());
+ }
+ }
+}
+
+void xls_xml_data_context::push_formula_cell(std::string_view formula)
+{
+ switch (m_cell_type)
+ {
+ case ct_number:
+ m_parent_cxt.store_cell_formula(formula, m_cell_value);
+ break;
+ default:
+ {
+ formula_result res;
+ m_parent_cxt.store_cell_formula(formula, res);
+ }
+ }
+}
+
+void xls_xml_data_context::store_array_formula_parent_cell(std::string_view formula)
+{
+ ss::address_t pos = m_parent_cxt.get_current_pos();
+ ss::range_t range = m_parent_cxt.get_array_range();
+ xls_xml_context::array_formulas_type& store = m_parent_cxt.get_array_formula_store();
+
+ range += pos;
+
+ store.push_back(
+ std::make_pair(
+ range,
+ std::make_unique<xls_xml_context::array_formula_type>(range, formula)));
+
+ xls_xml_context::array_formula_type& af = *store.back().second;
+
+ switch (m_cell_type)
+ {
+ case ct_number:
+ af.results.set(0, 0, m_cell_value);
+ break;
+ default:
+ ;
+ }
+}
+
+void xls_xml_data_context::update_current_format()
+{
+ // format stack should have at least one entry at any given moment.
+ assert(!m_format_stack.empty());
+
+ // Grab the bottom format.
+ auto it = m_format_stack.begin();
+ m_current_format = *it;
+ ++it;
+
+ // Merge in the rest of the format data.
+ std::for_each(it, m_format_stack.end(),
+ [&](const format_type& fmt)
+ {
+ m_current_format.merge(fmt);
+ }
+ );
+}
+
+xls_xml_context::array_formula_type::array_formula_type(
+ const ss::range_t& _range, std::string_view _formula) :
+ formula(_formula),
+ results(_range.last.row-_range.first.row+1, _range.last.column-_range.first.column+1) {}
+
+xls_xml_context::named_exp::named_exp(std::string_view _name, std::string_view _expression, ss::sheet_t _scope) :
+ name(_name), expression(_expression), scope(_scope) {}
+
+xls_xml_context::selection::selection() : pane(ss::sheet_pane_t::unspecified), col(-1), row(-1)
+{
+ range.first.column = -1;
+ range.first.row = -1;
+ range.last.column = -1;
+ range.last.row = -1;
+}
+
+void xls_xml_context::selection::reset()
+{
+ pane = ss::sheet_pane_t::unspecified;
+ col = 0;
+ row = 0;
+
+ range.first.column = -1;
+ range.first.row = -1;
+ range.last.column = -1;
+ range.last.row = -1;
+}
+
+bool xls_xml_context::selection::valid_cursor() const
+{
+ return col >= 0 && row >= 0;
+}
+
+bool xls_xml_context::selection::valid_range() const
+{
+ return range.first.column >= 0 && range.first.row >= 0 && range.last.column >= 0 && range.last.row >= 0;
+}
+
+xls_xml_context::split_pane::split_pane() :
+ pane_state(ss::pane_state_t::split),
+ active_pane(ss::sheet_pane_t::top_left),
+ split_horizontal(0.0), split_vertical(0.0),
+ top_row_bottom_pane(0), left_col_right_pane(0) {}
+
+void xls_xml_context::split_pane::reset()
+{
+ pane_state = ss::pane_state_t::split;
+ active_pane = ss::sheet_pane_t::top_left;
+ split_horizontal = 0.0;
+ split_vertical = 0.0;
+ top_row_bottom_pane = 0;
+ left_col_right_pane = 0;
+}
+
+bool xls_xml_context::split_pane::split() const
+{
+ return (split_horizontal || split_vertical) && (top_row_bottom_pane || left_col_right_pane);
+}
+
+ss::address_t xls_xml_context::split_pane::get_top_left_cell() const
+{
+ ss::address_t pos;
+ pos.column = left_col_right_pane;
+ pos.row = top_row_bottom_pane;
+ return pos;
+}
+
+xls_xml_context::table_properties::table_properties()
+{
+ reset();
+}
+
+void xls_xml_context::table_properties::reset()
+{
+ pos.row = 0;
+ pos.column = 0;
+}
+
+xls_xml_context::xls_xml_context(session_context& session_cxt, const tokens& tokens, ss::iface::import_factory* factory) :
+ xml_context_base(session_cxt, tokens),
+ mp_factory(factory),
+ mp_cur_sheet(nullptr),
+ mp_sheet_props(nullptr),
+ m_cur_sheet(-1),
+ m_cur_row(0), m_cur_col(0),
+ m_cur_prop_col(0),
+ m_cur_merge_down(0), m_cur_merge_across(0),
+ m_cc_data(session_cxt, tokens, *this)
+{
+ register_child(&m_cc_data);
+
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_xls_xml_ss, XML_Workbook }, // root element
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_Author },
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_Company },
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_Created },
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_LastAuthor },
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_LastSaved },
+ { NS_xls_xml_o, XML_DocumentProperties, NS_xls_xml_o, XML_Version },
+ { NS_xls_xml_o, XML_OfficeDocumentSettings, NS_xls_xml_o, XML_AllowPNG },
+ { NS_xls_xml_o, XML_OfficeDocumentSettings, NS_xls_xml_o, XML_DownloadComponents },
+ { NS_xls_xml_o, XML_OfficeDocumentSettings, NS_xls_xml_o, XML_LocationOfComponents },
+ { NS_xls_xml_ss, XML_Borders, NS_xls_xml_ss, XML_Border },
+ { NS_xls_xml_ss, XML_Cell, NS_xls_xml_ss, XML_Data },
+ { NS_xls_xml_ss, XML_Cell, NS_xls_xml_ss, XML_NamedCell },
+ { NS_xls_xml_ss, XML_Names, NS_xls_xml_ss, XML_NamedRange },
+ { NS_xls_xml_ss, XML_Row, NS_xls_xml_ss, XML_Cell },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_Alignment },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_Borders },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_Font },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_Interior },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_NumberFormat },
+ { NS_xls_xml_ss, XML_Style, NS_xls_xml_ss, XML_Protection },
+ { NS_xls_xml_ss, XML_Styles, NS_xls_xml_ss, XML_Style },
+ { NS_xls_xml_ss, XML_Table, NS_xls_xml_ss, XML_Column },
+ { NS_xls_xml_ss, XML_Table, NS_xls_xml_ss, XML_Row },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_o, XML_DocumentProperties },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_o, XML_OfficeDocumentSettings },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_ss, XML_Names },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_ss, XML_Styles },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_ss, XML_Worksheet },
+ { NS_xls_xml_ss, XML_Workbook, NS_xls_xml_x, XML_ExcelWorkbook },
+ { NS_xls_xml_ss, XML_Worksheet, NS_xls_xml_ss, XML_Names },
+ { NS_xls_xml_ss, XML_Worksheet, NS_xls_xml_ss, XML_Table },
+ { NS_xls_xml_ss, XML_Worksheet, NS_xls_xml_x, XML_AutoFilter },
+ { NS_xls_xml_ss, XML_Worksheet, NS_xls_xml_x, XML_WorksheetOptions },
+ { NS_xls_xml_x, XML_AutoFilter, NS_xls_xml_x, XML_AutoFilterColumn },
+ { NS_xls_xml_x, XML_AutoFilterColumn, NS_xls_xml_x, XML_AutoFilterCondition },
+ { NS_xls_xml_x, XML_AutoFilterColumn, NS_xls_xml_x, XML_AutoFilterOr },
+ { NS_xls_xml_x, XML_AutoFilterOr, NS_xls_xml_x, XML_AutoFilterCondition },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_ActiveSheet },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_FirstVisibleSheet },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_ProtectStructure },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_ProtectWindows },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_RefModeR1C1 },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_TabRatio },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_WindowHeight },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_WindowTopX },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_WindowTopY },
+ { NS_xls_xml_x, XML_ExcelWorkbook, NS_xls_xml_x, XML_WindowWidth },
+ { NS_xls_xml_x, XML_PageSetup, NS_xls_xml_x, XML_Footer },
+ { NS_xls_xml_x, XML_PageSetup, NS_xls_xml_x, XML_Header },
+ { NS_xls_xml_x, XML_PageSetup, NS_xls_xml_x, XML_PageMargins },
+ { NS_xls_xml_x, XML_Pane, NS_xls_xml_x, XML_ActiveCol },
+ { NS_xls_xml_x, XML_Pane, NS_xls_xml_x, XML_ActiveRow },
+ { NS_xls_xml_x, XML_Pane, NS_xls_xml_x, XML_Number },
+ { NS_xls_xml_x, XML_Pane, NS_xls_xml_x, XML_RangeSelection },
+ { NS_xls_xml_x, XML_Panes, NS_xls_xml_x, XML_Pane },
+ { NS_xls_xml_x, XML_Print, NS_xls_xml_x, XML_HorizontalResolution },
+ { NS_xls_xml_x, XML_Print, NS_xls_xml_x, XML_ValidPrinterInfo },
+ { NS_xls_xml_x, XML_Print, NS_xls_xml_x, XML_VerticalResolution },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_ActivePane },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_FilterOn },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_FreezePanes },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_FrozenNoSplit },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_LeftColumnRightPane },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_PageSetup },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_Panes },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_Print },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_ProtectObjects },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_ProtectScenarios },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_Selected },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_SplitHorizontal },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_SplitVertical },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_TopRowBottomPane },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_TopRowVisible },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_Unsynced },
+ { NS_xls_xml_x, XML_WorksheetOptions, NS_xls_xml_x, XML_Zoom },
+ };
+
+ init_element_validator(rules, std::size(rules));
+
+ m_cur_array_range.first.column = -1;
+ m_cur_array_range.first.row = -1;
+ m_cur_array_range.last = m_cur_array_range.first;
+}
+
+xls_xml_context::~xls_xml_context()
+{
+}
+
+void xls_xml_context::declaration(const xml_declaration_t& decl)
+{
+ ss::iface::import_global_settings* gs = mp_factory->get_global_settings();
+ if (!gs)
+ return;
+
+ gs->set_character_set(decl.encoding);
+}
+
+xml_context_base* xls_xml_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Data:
+ {
+ // Move the cell formula string to the Data element context.
+ m_cc_data.reset();
+ return &m_cc_data;
+ }
+ default:
+ ;
+ }
+ }
+ return nullptr;
+}
+
+void xls_xml_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xls_xml_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ push_stack(ns, name);
+
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Workbook:
+ // Do nothing.
+ break;
+ case XML_Worksheet:
+ {
+ start_element_worksheet(attrs);
+ break;
+ }
+ case XML_Table:
+ start_element_table(attrs);
+ break;
+ case XML_Row:
+ start_element_row(attrs);
+ break;
+ case XML_Cell:
+ start_element_cell(attrs);
+ break;
+ case XML_Column:
+ start_element_column(attrs);
+ break;
+ case XML_Names:
+ break;
+ case XML_NamedRange:
+ {
+ std::string_view name_s, exp;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Name:
+ name_s = intern(attr);
+ break;
+ case XML_RefersTo:
+ {
+ exp = attr.value;
+ if (exp.size() > 1 && exp[0] == '=')
+ exp = std::string_view{exp.data()+1, exp.size()-1};
+ if (!exp.empty() && attr.transient)
+ exp = intern(exp);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ if (!name_s.empty() && !exp.empty())
+ {
+ if (m_cur_sheet >= 0)
+ m_named_exps_sheet.emplace_back(name_s, exp, m_cur_sheet);
+ else
+ m_named_exps_global.emplace_back(name_s, exp, -1);
+ }
+
+ break;
+ }
+ case XML_Styles:
+ break;
+ case XML_Style:
+ {
+ m_current_style = std::make_unique<style_type>();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_ID:
+ m_current_style->id = intern(attr);
+ break;
+ case XML_Name:
+ m_current_style->name = intern(attr);
+ break;
+ case XML_Parent:
+ m_current_style->parent_id = intern(attr);
+ break;
+ default:
+ ;
+ }
+ }
+
+ break;
+ }
+ case XML_Borders:
+ start_element_borders(attrs);
+ break;
+ case XML_Border:
+ start_element_border(attrs);
+ break;
+ case XML_NumberFormat:
+ start_element_number_format(attrs);
+ break;
+ case XML_Font:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_FontName:
+ {
+ m_current_style->font.name = intern(attr);
+ break;
+ }
+ case XML_Bold:
+ {
+ m_current_style->font.bold = to_bool(attr.value);
+ break;
+ }
+ case XML_Italic:
+ {
+ m_current_style->font.italic = to_bool(attr.value);
+ break;
+ }
+ case XML_Color:
+ {
+ m_current_style->font.color = to_rgb(attr.value);
+ break;
+ }
+ case XML_Size:
+ {
+ m_current_style->font.size = to_double(attr.value);
+ break;
+ }
+ case XML_Underline:
+ {
+ m_current_style->font.underline = underline::get().find(attr.value);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case XML_Interior:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Color:
+ {
+ m_current_style->fill.color = to_rgb(attr.value);
+ break;
+ }
+ case XML_Pattern:
+ {
+ // TODO : support fill types other than 'solid'.
+ m_current_style->fill.solid = (attr.value == "Solid");
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ break;
+ }
+ case XML_Alignment:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Horizontal:
+ {
+ m_current_style->text_alignment.hor = hor_align::get().find(attr.value);
+ break;
+ }
+ case XML_Vertical:
+ {
+ m_current_style->text_alignment.ver = ver_align::get().find(attr.value);
+ break;
+ }
+ case XML_Indent:
+ {
+ m_current_style->text_alignment.indent = to_long(attr.value);
+ break;
+ }
+ case XML_WrapText:
+ {
+ m_current_style->text_alignment.wrap_text = to_bool(attr.value);
+ break;
+ }
+ case XML_ShrinkToFit:
+ {
+ m_current_style->text_alignment.shrink_to_fit = to_bool(attr.value);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ break;
+ }
+ case XML_Protection:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_xls_xml_x && attr.name == XML_HideFormula)
+ {
+ m_current_style->cell_protection.hide_formula = to_bool(attr.value);
+ }
+ else if (attr.ns == NS_xls_xml_ss && attr.name == XML_Protected)
+ {
+ m_current_style->cell_protection.locked = to_bool(attr.value);
+ }
+ }
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_xls_xml_x)
+ {
+ switch (name)
+ {
+ case XML_WorksheetOptions:
+ m_split_pane.reset();
+ break;
+ case XML_FreezePanes:
+ // TODO : check if this is correct.
+ m_split_pane.pane_state = ss::pane_state_t::frozen_split;
+ break;
+ case XML_FrozenNoSplit:
+ m_split_pane.pane_state = ss::pane_state_t::frozen;
+ break;
+ case XML_ActivePane:
+ m_split_pane.active_pane = ss::sheet_pane_t::unspecified;
+ break;
+ case XML_SplitHorizontal:
+ m_split_pane.split_horizontal = 0.0;
+ break;
+ case XML_SplitVertical:
+ m_split_pane.split_vertical = 0.0;
+ break;
+ case XML_TopRowBottomPane:
+ m_split_pane.top_row_bottom_pane = 0;
+ break;
+ case XML_LeftColumnRightPane:
+ m_split_pane.left_col_right_pane = 0;
+ break;
+ case XML_Panes:
+ break;
+ case XML_Pane:
+ m_cursor_selection.reset();
+ break;
+ case XML_Number:
+ break;
+ case XML_ActiveCol:
+ break;
+ case XML_ActiveRow:
+ break;
+ case XML_RangeSelection:
+ break;
+ case XML_Selected:
+ {
+ if (mp_cur_sheet)
+ {
+ ss::iface::import_sheet_view* sv = mp_cur_sheet->get_sheet_view();
+ if (sv)
+ sv->set_sheet_active();
+ }
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool xls_xml_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Borders:
+ end_element_borders();
+ break;
+ case XML_Border:
+ end_element_border();
+ break;
+ case XML_NumberFormat:
+ end_element_number_format();
+ break;
+ case XML_Row:
+ end_element_row();
+ break;
+ case XML_Cell:
+ end_element_cell();
+ break;
+ case XML_Column:
+ end_element_column();
+ break;
+ case XML_Table:
+ end_element_table();
+ break;
+ case XML_Workbook:
+ end_element_workbook();
+ break;
+ case XML_Worksheet:
+ end_element_worksheet();
+ break;
+ case XML_Style:
+ {
+ if (m_current_style)
+ {
+ if (m_current_style->id == "Default")
+ m_default_style = std::move(m_current_style);
+ else
+ m_styles.push_back(std::move(m_current_style));
+ }
+ break;
+ }
+ case XML_Styles:
+ {
+ end_element_styles();
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_xls_xml_x)
+ {
+ switch (name)
+ {
+ case XML_Pane:
+ end_element_pane();
+ break;
+ case XML_WorksheetOptions:
+ end_element_worksheet_options();
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+namespace {
+
+ss::sheet_pane_t to_sheet_pane(long v)
+{
+ static const std::vector<ss::sheet_pane_t> mapping = {
+ ss::sheet_pane_t::bottom_right, // 0
+ ss::sheet_pane_t::top_right, // 1
+ ss::sheet_pane_t::bottom_left, // 2
+ ss::sheet_pane_t::top_left, // 3
+ };
+
+ if (v < 0 || size_t(v) >= mapping.size())
+ return ss::sheet_pane_t::unspecified;
+
+ return mapping[v];
+}
+
+}
+
+void xls_xml_context::characters(std::string_view str, bool /*transient*/)
+{
+ if (str.empty())
+ return;
+
+ xml_token_pair_t ce = get_current_element();
+
+ if (ce.first == NS_xls_xml_x)
+ {
+ switch (ce.second)
+ {
+ case XML_Number:
+ // sheet pane position.
+ // 3 | 1
+ //---+---
+ // 2 | 0
+ m_cursor_selection.pane = to_sheet_pane(to_long(str));
+ break;
+ case XML_ActiveCol:
+ m_cursor_selection.col = to_long(str);
+ break;
+ case XML_ActiveRow:
+ m_cursor_selection.row = to_long(str);
+ break;
+ case XML_ActivePane:
+ m_split_pane.active_pane = to_sheet_pane(to_long(str));
+ break;
+ case XML_SplitHorizontal:
+ m_split_pane.split_horizontal = to_double(str);
+ break;
+ case XML_SplitVertical:
+ m_split_pane.split_vertical = to_double(str);
+ break;
+ case XML_TopRowBottomPane:
+ m_split_pane.top_row_bottom_pane = to_long(str);
+ break;
+ case XML_LeftColumnRightPane:
+ m_split_pane.left_col_right_pane = to_long(str);
+ break;
+ case XML_RangeSelection:
+ {
+ ss::iface::import_reference_resolver* resolver =
+ mp_factory->get_reference_resolver(ss::formula_ref_context_t::global);
+
+ if (resolver)
+ m_cursor_selection.range = to_rc_range(resolver->resolve_range(str));
+
+ break;
+ }
+ default:
+ ;
+ }
+ }
+}
+
+void xls_xml_context::start_element_borders(const xml_token_attrs_t& /*attrs*/)
+{
+ m_current_style->borders.clear();
+}
+
+void xls_xml_context::start_element_border(const xml_token_attrs_t& attrs)
+{
+ ss::border_direction_t dir = ss::border_direction_t::unknown;
+ ss::border_style_t style = ss::border_style_t::unknown;
+ std::optional<ss::color_rgb_t> color;
+ long weight = 0;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Position:
+ {
+ dir = border_dir::get().find(attr.value);
+ break;
+ }
+ case XML_LineStyle:
+ {
+ style = border_style::get().find(attr.value);
+ break;
+ }
+ case XML_Weight:
+ {
+ weight = to_long(attr.value);
+ break;
+ }
+ case XML_Color:
+ {
+ color = to_rgb(attr.value);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ if (dir == ss::border_direction_t::unknown || style == ss::border_style_t::unknown)
+ return;
+
+ m_current_style->borders.emplace_back();
+ border_style_type& bs = m_current_style->borders.back();
+ bs.dir = dir;
+ bs.style = style;
+ bs.color = color;
+
+ switch (bs.style)
+ {
+ case ss::border_style_t::solid:
+ {
+ switch (weight)
+ {
+ case 0:
+ bs.style = ss::border_style_t::hair;
+ break;
+ case 1:
+ bs.style = ss::border_style_t::thin;
+ break;
+ case 2:
+ bs.style = ss::border_style_t::medium;
+ break;
+ case 3:
+ bs.style = ss::border_style_t::thick;
+ break;
+ default:
+ ;
+ }
+ break;
+ }
+ case ss::border_style_t::dashed:
+ if (weight > 1)
+ bs.style = ss::border_style_t::medium_dashed;
+ break;
+ case ss::border_style_t::dash_dot:
+ if (weight > 1)
+ bs.style = ss::border_style_t::medium_dash_dot;
+ break;
+ case ss::border_style_t::dash_dot_dot:
+ if (weight > 1)
+ bs.style = ss::border_style_t::medium_dash_dot_dot;
+ break;
+ default:
+ ;
+ }
+}
+
+void xls_xml_context::start_element_number_format(const xml_token_attrs_t& attrs)
+{
+ m_current_style->number_format = std::string_view{};
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Format:
+ {
+ std::string_view code = num_format::get().find(attr.value);
+ m_current_style->number_format = code.empty() ? intern(attr) : code;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+}
+
+void xls_xml_context::start_element_cell(const xml_token_attrs_t& attrs)
+{
+ long col_index = 0;
+ std::string_view formula;
+ m_cur_cell_style_id = std::string_view{};
+
+ m_cur_merge_across = 0; // extra column(s) that are part of the merged cell.
+ m_cur_merge_down = 0; // extra row(s) that are part of the merged cell.
+
+ m_cur_array_range.first.column = -1;
+ m_cur_array_range.first.row = -1;
+ m_cur_array_range.last = m_cur_array_range.first;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ return;
+
+ if (attr.ns != NS_xls_xml_ss)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_Index:
+ col_index = to_long(attr.value);
+ break;
+ case XML_Formula:
+ if (attr.value[0] == '=' && attr.value.size() > 1)
+ {
+ std::string_view s{attr.value.data()+1, attr.value.size()-1};
+ formula = s;
+ if (attr.transient)
+ formula = intern(s);
+ }
+ break;
+ case XML_MergeAcross:
+ m_cur_merge_across = to_long(attr.value);
+ break;
+ case XML_MergeDown:
+ m_cur_merge_down = to_long(attr.value);
+ break;
+ case XML_StyleID:
+ m_cur_cell_style_id = intern(attr);
+ break;
+ case XML_ArrayRange:
+ {
+ ss::iface::import_reference_resolver* resolver =
+ mp_factory->get_reference_resolver(ss::formula_ref_context_t::global);
+ if (resolver)
+ m_cur_array_range = to_rc_range(resolver->resolve_range(attr.value));
+
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ if (!formula.empty())
+ m_cur_cell_formula = formula;
+
+ if (col_index > 0)
+ {
+ // 1-based column index. Convert it to a 0-based one.
+ m_cur_col = m_table_props.pos.column + col_index - 1;
+ }
+}
+
+void xls_xml_context::start_element_column(const xml_token_attrs_t& attrs)
+{
+ if (!mp_sheet_props && !mp_cur_sheet)
+ return;
+
+ ss::col_t col_index = m_cur_prop_col;
+ ss::col_t span = 0;
+ double width = 0.0;
+ bool hidden = false;
+ std::optional<std::string_view> style_id;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ continue;
+
+ if (attr.ns != NS_xls_xml_ss)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_Index:
+ {
+ // Convert from 1-based to 0-based.
+ const char* p_end = nullptr;
+ long v = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ col_index = m_table_props.pos.column + v - 1;
+ break;
+ }
+ case XML_Width:
+ width = to_double(attr.value);
+ break;
+ case XML_Span:
+ // Span is the number of extra columns after the first one i.e.
+ // if the span is 1, the properties get applied to two
+ // consecutive columns. Not very intuitive, but this is how it
+ // appears to work.
+ span = to_long(attr.value);
+ break;
+ case XML_Hidden:
+ hidden = to_long(attr.value) != 0;
+ break;
+ case XML_StyleID:
+ style_id = attr.value; // no need to intern since it gets used in the same function scope
+ break;
+ }
+ }
+
+ if (mp_sheet_props)
+ {
+ // Column widths are stored as points.
+ mp_sheet_props->set_column_width(col_index, span + 1, width, orcus::length_unit_t::point);
+ mp_sheet_props->set_column_hidden(col_index, span + 1, hidden);
+ }
+
+ if (mp_cur_sheet && style_id)
+ {
+ auto it = m_style_map_cell.find(*style_id);
+ if (it != m_style_map_cell.end())
+ {
+ std::size_t xfid = it->second;
+ mp_cur_sheet->set_column_format(col_index, span + 1, xfid);
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "xfid for the style ID of '" << *style_id << "' not found in the cache";
+ warn(os.str());
+ }
+ }
+
+ m_cur_prop_col = col_index + span + 1;
+}
+
+void xls_xml_context::start_element_row(const xml_token_attrs_t& attrs)
+{
+ m_cur_col = m_table_props.pos.column;
+ ss::row_t row_index = -1;
+ bool has_height = false;
+ bool hidden = false;
+ double height = 0.0;
+ std::optional<std::string_view> style_id;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ return;
+
+ if (attr.ns == NS_xls_xml_ss)
+ {
+ switch (attr.name)
+ {
+ case XML_Index:
+ row_index = to_long(attr.value);
+ break;
+ case XML_Height:
+ has_height = true;
+ height = to_double(attr.value);
+ break;
+ case XML_Hidden:
+ hidden = to_long(attr.value) != 0;
+ break;
+ case XML_StyleID:
+ style_id = attr.value; // no need to intern since it gets used in the same function scope
+ break;
+ }
+ }
+ }
+
+ if (row_index > 0)
+ {
+ // 1-based row index. Convert it to a 0-based one.
+ m_cur_row = row_index - 1;
+ }
+
+ if (mp_cur_sheet && style_id)
+ {
+ auto it = m_style_map_cell.find(*style_id);
+ if (it != m_style_map_cell.end())
+ {
+ std::size_t xfid = it->second;
+ mp_cur_sheet->set_row_format(m_cur_row, xfid);
+ }
+ else
+ {
+ std::ostringstream os;
+ os << "xfid for the style ID of '" << *style_id << "' not found in the cache";
+ warn(os.str());
+ }
+ }
+
+ if (mp_sheet_props)
+ {
+ if (has_height)
+ mp_sheet_props->set_row_height(m_cur_row, height, length_unit_t::point);
+
+ if (hidden)
+ mp_sheet_props->set_row_hidden(m_cur_row, true);
+ }
+}
+
+void xls_xml_context::start_element_table(const xml_token_attrs_t& attrs)
+{
+ ss::row_t row_index = -1;
+ ss::col_t col_index = -1;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ return;
+
+ if (attr.ns == NS_xls_xml_ss)
+ {
+ switch (attr.name)
+ {
+ case XML_TopCell:
+ col_index = to_long(attr.value);
+ break;
+ case XML_LeftCell:
+ row_index = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ // Convert 1-based indices to 0-based.
+
+ if (row_index > 0)
+ m_table_props.pos.row = row_index - 1;
+
+ if (col_index > 0)
+ m_table_props.pos.column = col_index - 1;
+
+ m_cur_row = m_table_props.pos.row;
+ m_cur_prop_col = m_table_props.pos.column;
+}
+
+void xls_xml_context::start_element_worksheet(const xml_token_attrs_t& attrs)
+{
+ ++m_cur_sheet;
+ std::string_view sheet_name;
+ m_cell_formulas.emplace_back();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns == NS_xls_xml_ss)
+ {
+ switch (attr.name)
+ {
+ case XML_Name:
+ sheet_name = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ mp_cur_sheet = mp_factory->append_sheet(m_cur_sheet, sheet_name);
+ ss::iface::import_named_expression* sheet_named_exp = nullptr;
+ if (mp_cur_sheet)
+ {
+ mp_sheet_props = mp_cur_sheet->get_sheet_properties();
+ sheet_named_exp = mp_cur_sheet->get_named_expression();
+ }
+
+ m_sheet_named_exps.push_back(sheet_named_exp);
+
+ m_cur_row = 0;
+ m_cur_col = 0;
+
+ if (get_config().debug)
+ std::cout << "worksheet: name: '" << sheet_name << "'" << std::endl;
+}
+
+void xls_xml_context::end_element_borders()
+{
+}
+
+void xls_xml_context::end_element_border()
+{
+}
+
+void xls_xml_context::end_element_number_format()
+{
+}
+
+void xls_xml_context::end_element_cell()
+{
+ if (mp_sheet_props && (m_cur_merge_across > 0 || m_cur_merge_down > 0))
+ {
+ ss::range_t merge_range;
+ merge_range.first.column = m_cur_col;
+ merge_range.first.row = m_cur_row;
+ merge_range.last.column = m_cur_col + m_cur_merge_across;
+ merge_range.last.row = m_cur_row + m_cur_merge_down;
+
+ mp_sheet_props->set_merge_cell_range(merge_range);
+ }
+
+ if (mp_cur_sheet && !m_cur_cell_style_id.empty())
+ {
+ auto it = m_style_map_cell.find(m_cur_cell_style_id);
+ if (it != m_style_map_cell.end())
+ {
+ auto xf_id = it->second;
+ mp_cur_sheet->set_format(m_cur_row, m_cur_col, xf_id);
+ }
+ }
+
+ if (mp_cur_sheet && !m_cur_cell_formula.empty())
+ {
+ // Likely a Cell element without a child Data element.
+ store_cell_formula(m_cur_cell_formula, formula_result());
+ }
+
+ m_cur_cell_formula = std::string_view{};
+
+ ++m_cur_col;
+ if (m_cur_merge_across > 0)
+ m_cur_col += m_cur_merge_across;
+}
+
+void xls_xml_context::end_element_column()
+{
+}
+
+void xls_xml_context::end_element_row()
+{
+ ++m_cur_row;
+}
+
+void xls_xml_context::end_element_table()
+{
+ push_all_array_formulas();
+ m_array_formulas.clear();
+ m_table_props.reset();
+ m_cur_row = 0;
+ m_cur_prop_col = 0;
+}
+
+void xls_xml_context::end_element_worksheet()
+{
+ mp_cur_sheet = nullptr;
+}
+
+void xls_xml_context::end_element_workbook()
+{
+ if (!mp_factory)
+ return;
+
+ ss::iface::import_named_expression* ne_global = mp_factory->get_named_expression();
+ if (ne_global)
+ {
+ // global scope named expressions.
+
+ for (const named_exp& ne : m_named_exps_global)
+ {
+ ne_global->set_named_expression(ne.name, ne.expression);
+ ne_global->commit();
+ }
+ }
+
+ // sheet-local named expressions follow.
+
+ for (const named_exp& ne : m_named_exps_sheet)
+ {
+ ss::iface::import_named_expression* p = nullptr;
+ if (ne.scope >= 0 && size_t(ne.scope) < m_sheet_named_exps.size())
+ p = m_sheet_named_exps[ne.scope]; // it may be nullptr.
+
+ if (p)
+ {
+ p->set_named_expression(ne.name, ne.expression);
+ p->commit();
+ }
+ }
+
+ // push all cell formulas
+ for (size_t sheet_pos = 0; sheet_pos < m_cell_formulas.size(); ++sheet_pos)
+ {
+ ss::iface::import_sheet* sheet = mp_factory->get_sheet(sheet_pos);
+ if (!sheet)
+ continue;
+
+ ss::iface::import_formula* xformula = sheet->get_formula();
+ if (!xformula)
+ continue;
+
+ const std::deque<cell_formula_type>& store = m_cell_formulas[sheet_pos];
+ for (const cell_formula_type& cf : store)
+ {
+ xformula->set_position(cf.pos.row, cf.pos.column);
+ xformula->set_formula(ss::formula_grammar_t::xls_xml, cf.formula);
+
+ switch (cf.result.type)
+ {
+ case formula_result::result_type::numeric:
+ xformula->set_result_value(cf.result.value_numeric);
+ break;
+ case formula_result::result_type::string:
+ case formula_result::result_type::boolean:
+ case formula_result::result_type::empty:
+ ;
+ }
+
+ xformula->commit();
+ }
+ }
+}
+
+void xls_xml_context::end_element_styles()
+{
+ commit_default_style(); // Commit the default style first.
+ commit_styles();
+}
+
+void xls_xml_context::end_element_pane()
+{
+ ss::iface::import_sheet_view* sv = mp_cur_sheet->get_sheet_view();
+ if (!sv)
+ return;
+
+ if (m_cursor_selection.pane == ss::sheet_pane_t::unspecified)
+ return;
+
+ if (m_cursor_selection.valid_range())
+ {
+ sv->set_selected_range(m_cursor_selection.pane, m_cursor_selection.range);
+ }
+ else if (m_cursor_selection.valid_cursor())
+ {
+ ss::range_t sel;
+ sel.first.column = m_cursor_selection.col;
+ sel.first.row = m_cursor_selection.row;
+ sel.last = sel.first;
+
+ sv->set_selected_range(m_cursor_selection.pane, sel);
+ }
+}
+
+void xls_xml_context::end_element_worksheet_options()
+{
+ commit_split_pane();
+}
+
+void xls_xml_context::commit_split_pane()
+{
+ ss::iface::import_sheet_view* sv = mp_cur_sheet->get_sheet_view();
+ if (!sv)
+ return;
+
+ if (!m_split_pane.split())
+ return;
+
+ switch (m_split_pane.pane_state)
+ {
+ case ss::pane_state_t::split:
+ {
+ ss::address_t top_left_cell = m_split_pane.get_top_left_cell();
+
+ // NB: The term "split vertical" in Excel 2003 XML refers to the
+ // vertical split bar position which in this case corresponds with
+ // the "horizontal split" position of the set_split_pane() call,
+ // and vice versa.
+ sv->set_split_pane(
+ m_split_pane.split_vertical, m_split_pane.split_horizontal,
+ top_left_cell, m_split_pane.active_pane);
+ break;
+ }
+ case ss::pane_state_t::frozen:
+ {
+ ss::address_t top_left_cell = m_split_pane.get_top_left_cell();
+
+ // NB: Note for the split pane above also applies here.
+ ss::col_t visible_cols = m_split_pane.split_vertical;
+ ss::row_t visible_rows = m_split_pane.split_horizontal;
+
+ sv->set_frozen_pane(
+ visible_cols, visible_rows,
+ top_left_cell, m_split_pane.active_pane);
+ break;
+ }
+ case ss::pane_state_t::frozen_split:
+ // not handled yet.
+ break;
+ case ss::pane_state_t::unspecified:
+ default:
+ ;
+ }
+
+ m_split_pane.reset();
+}
+
+void xls_xml_context::commit_default_style()
+{
+ ss::iface::import_styles* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ ss::iface::import_font_style* font_style = styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ if (m_default_style)
+ {
+ const auto& font = m_default_style->font;
+
+ if (!font.name.empty())
+ font_style->set_name(font.name);
+
+ if (font.size)
+ font_style->set_size(*font.size);
+
+ if (font.underline)
+ font_style->set_underline(*font.underline);
+
+ font_style->set_bold(font.bold);
+ font_style->set_italic(font.italic);
+ font_style->set_color(255, font.color.red, font.color.green, font.color.blue);
+ }
+
+ std::size_t id = font_style->commit();
+ assert(id == 0);
+
+ ss::iface::import_fill_style* fill_style = styles->start_fill_style();
+ ENSURE_INTERFACE(fill_style, import_fill_style);
+
+ if (m_default_style)
+ {
+ if (m_default_style->fill.solid)
+ fill_style->set_pattern_type(ss::fill_pattern_t::solid);
+
+ fill_style->set_fg_color(
+ 255,
+ m_default_style->fill.color.red,
+ m_default_style->fill.color.green,
+ m_default_style->fill.color.blue
+ );
+ }
+
+ id = fill_style->commit();
+ assert(id == 0);
+
+ auto* border_style = styles->start_border_style();
+ ENSURE_INTERFACE(border_style, import_border_style);
+
+ if (m_default_style && !m_default_style->borders.empty())
+ {
+ for (const border_style_type& b : m_default_style->borders)
+ {
+ if (b.dir == ss::border_direction_t::unknown)
+ continue;
+
+ if (b.style != ss::border_style_t::unknown)
+ border_style->set_style(b.dir, b.style);
+
+ if (b.color)
+ border_style->set_color(b.dir, 255, b.color->red, b.color->green, b.color->blue);
+ }
+ }
+
+ id = border_style->commit();
+ assert(id == 0);
+
+ auto* cell_protection = styles->start_cell_protection();
+ ENSURE_INTERFACE(cell_protection, import_cell_protection);
+
+ if (m_default_style)
+ {
+ const auto& cp = m_default_style->cell_protection;
+ cell_protection->set_locked(cp.locked);
+ cell_protection->set_formula_hidden(cp.hide_formula);
+ }
+
+ id = cell_protection->commit();
+ assert(id == 0);
+
+ auto* number_format = styles->start_number_format();
+ ENSURE_INTERFACE(number_format, import_number_format);
+
+ if (m_default_style)
+ number_format->set_code(m_default_style->number_format);
+
+ id = number_format->commit();
+ assert(id == 0);
+
+ auto* xf = styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(xf, import_xf);
+
+ auto set_default_style = [this](ss::iface::import_xf* ixf)
+ {
+ bool apply_alignment =
+ m_default_style->text_alignment.hor != ss::hor_alignment_t::unknown ||
+ m_default_style->text_alignment.ver != ss::ver_alignment_t::unknown ||
+ m_default_style->text_alignment.wrap_text || m_default_style->text_alignment.shrink_to_fit;
+
+ ixf->set_apply_alignment(apply_alignment);
+ ixf->set_horizontal_alignment(m_default_style->text_alignment.hor);
+ ixf->set_vertical_alignment(m_default_style->text_alignment.ver);
+ ixf->set_wrap_text(m_default_style->text_alignment.wrap_text);
+ ixf->set_shrink_to_fit(m_default_style->text_alignment.shrink_to_fit);
+ };
+
+ if (m_default_style)
+ set_default_style(xf);
+
+ id = xf->commit();
+ assert(id == 0);
+
+ xf = styles->start_xf(ss::xf_category_t::cell_style);
+ ENSURE_INTERFACE(xf, import_xf);
+
+ if (m_default_style && m_default_style->name == "Normal")
+ set_default_style(xf);
+
+ id = xf->commit();
+ assert(id == 0);
+
+ auto* cell_style = styles->start_cell_style();
+ ENSURE_INTERFACE(cell_style, import_cell_style);
+
+ if (m_default_style && m_default_style->name == "Normal")
+ {
+ if (!m_default_style->name.empty())
+ cell_style->set_name(m_default_style->name);
+ }
+
+ cell_style->commit();
+}
+
+void xls_xml_context::commit_styles()
+{
+ if (m_styles.empty())
+ return;
+
+ ss::iface::import_styles* styles = mp_factory->get_styles();
+ if (!styles)
+ return;
+
+ // Build a map of cell style textural ID's to cell format (xf) numeric ID's.
+
+ for (const std::unique_ptr<style_type>& style : m_styles)
+ {
+ auto category = style->name.empty() ? ss::xf_category_t::cell : ss::xf_category_t::cell_style;
+
+ auto* xf = styles->start_xf(category);
+ ENSURE_INTERFACE(xf, import_xf);
+
+ if (!style->parent_id.empty())
+ {
+ auto it = m_style_map_named_style.find(style->parent_id);
+ if (it == m_style_map_named_style.end())
+ {
+ std::ostringstream os;
+ os << "style '" << style->id << "' inherits from a parent style of '" << style->parent_id << "' but no record for the parent style exists";
+ warn(os.str());
+ }
+ else
+ xf->set_style_xf(it->second);
+ }
+
+ auto* font_style = styles->start_font_style();
+ ENSURE_INTERFACE(font_style, import_font_style);
+
+ if (!style->font.name.empty())
+ font_style->set_name(style->font.name);
+
+ if (style->font.size)
+ font_style->set_size(*style->font.size);
+
+ if (style->font.underline)
+ font_style->set_underline(*style->font.underline);
+
+ font_style->set_bold(style->font.bold);
+ font_style->set_italic(style->font.italic);
+ font_style->set_color(255,
+ style->font.color.red,
+ style->font.color.green,
+ style->font.color.blue);
+
+ size_t font_id = font_style->commit();
+
+ xf->set_font(font_id);
+
+ auto* fill_style = styles->start_fill_style();
+ ENSURE_INTERFACE(fill_style, import_fill_style);
+
+ if (style->fill.solid)
+ {
+ // TODO : add support for fill types other than 'solid'.
+ fill_style->set_pattern_type(ss::fill_pattern_t::solid);
+ fill_style->set_fg_color(255,
+ style->fill.color.red,
+ style->fill.color.green,
+ style->fill.color.blue);
+
+ size_t fill_id = fill_style->commit();
+ xf->set_fill(fill_id);
+ }
+
+ auto* protect = styles->start_cell_protection();
+ ENSURE_INTERFACE(protect, import_cell_protection);
+
+ protect->set_locked(style->cell_protection.locked);
+ protect->set_formula_hidden(style->cell_protection.hide_formula);
+
+ std::size_t protect_id = protect->commit();
+ xf->set_protection(protect_id);
+
+ if (!style->borders.empty())
+ {
+ styles->set_border_count(style->borders.size());
+
+ auto* border_style = styles->start_border_style();
+ ENSURE_INTERFACE(border_style, import_border_style);
+
+ for (const border_style_type& b : style->borders)
+ {
+ if (b.dir == ss::border_direction_t::unknown)
+ continue;
+
+ if (b.style != ss::border_style_t::unknown)
+ border_style->set_style(b.dir, b.style);
+
+ if (b.color)
+ border_style->set_color(b.dir, 255, b.color->red, b.color->green, b.color->blue);
+ }
+
+ size_t border_id = border_style->commit();
+ xf->set_border(border_id);
+ }
+
+ bool apply_alignment =
+ style->text_alignment.hor != ss::hor_alignment_t::unknown ||
+ style->text_alignment.ver != ss::ver_alignment_t::unknown ||
+ style->text_alignment.wrap_text || style->text_alignment.shrink_to_fit;
+
+ xf->set_apply_alignment(apply_alignment);
+ xf->set_horizontal_alignment(style->text_alignment.hor);
+ xf->set_vertical_alignment(style->text_alignment.ver);
+ xf->set_wrap_text(style->text_alignment.wrap_text);
+ xf->set_shrink_to_fit(style->text_alignment.shrink_to_fit);
+
+ if (!style->number_format.empty())
+ {
+ auto* number_format = styles->start_number_format();
+ ENSURE_INTERFACE(number_format, import_number_format);
+ number_format->set_code(style->number_format);
+ size_t number_format_id = number_format->commit();
+ xf->set_number_format(number_format_id);
+ }
+
+ // TODO : handle text indent level.
+
+ std::size_t xfid = xf->commit();
+
+ switch (category)
+ {
+ case ss::xf_category_t::cell:
+ {
+ m_style_map_cell.insert({style->id, xfid});
+ break;
+ }
+ case ss::xf_category_t::cell_style:
+ {
+ m_style_map_named_style.insert({style->id, xfid});
+
+ // Push the named cell style record.
+ auto* cell_style = styles->start_cell_style();
+ ENSURE_INTERFACE(cell_style, import_cell_style);
+ cell_style->set_name(style->name);
+ cell_style->set_xf(xfid);
+ cell_style->commit();
+
+ // Since we don't allow directly referencing a named cell style,
+ // we will create a regular cell style that references the named
+ // style instead.
+ auto* xf_cell = styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(xf_cell, import_xf);
+ xf_cell->set_style_xf(xfid); // reference the named style
+ xfid = xf_cell->commit();
+ m_style_map_cell.insert({style->id, xfid});
+ break;
+ }
+ case ss::xf_category_t::differential:
+ {
+ std::ostringstream os;
+ os << "differential cell format type is not supported";
+ warn(os.str());
+ break;
+ }
+ case ss::xf_category_t::unknown:
+ {
+ std::ostringstream os;
+ os << "cell format type is unknown";
+ warn(os.str());
+ break;
+ }
+ }
+ }
+}
+
+void xls_xml_context::push_all_array_formulas()
+{
+ if (!mp_cur_sheet)
+ return;
+
+ ss::iface::import_array_formula* array = mp_cur_sheet->get_array_formula();
+ if (!array)
+ return;
+
+ for (const array_formula_pair_type& pair : m_array_formulas)
+ {
+ const array_formula_type& af = *pair.second;
+ push_array_formula(
+ array, pair.first, af.formula, ss::formula_grammar_t::xls_xml, af.results);
+ }
+}
+
+ss::iface::import_factory* xls_xml_context::get_import_factory()
+{
+ return mp_factory;
+}
+
+ss::iface::import_sheet* xls_xml_context::get_import_sheet()
+{
+ return mp_cur_sheet;
+}
+
+ss::address_t xls_xml_context::get_current_pos() const
+{
+ ss::address_t pos;
+ pos.row = m_cur_row;
+ pos.column = m_cur_col;
+ return pos;
+}
+
+std::string_view xls_xml_context::pop_and_clear_formula()
+{
+ std::string_view f = m_cur_cell_formula;
+ m_cur_cell_formula = std::string_view{};
+ return f;
+}
+
+bool xls_xml_context::is_array_formula() const
+{
+ if (m_cur_array_range.first.column < 0 || m_cur_array_range.first.row < 0)
+ return false;
+
+ if (m_cur_array_range.last.column < 0 || m_cur_array_range.last.row < 0)
+ return false;
+
+ if (m_cur_array_range.first.column > m_cur_array_range.last.column ||
+ m_cur_array_range.first.row > m_cur_array_range.last.row)
+ return false;
+
+ return true;
+}
+
+const ss::range_t& xls_xml_context::get_array_range() const
+{
+ return m_cur_array_range;
+}
+
+xls_xml_context::array_formulas_type& xls_xml_context::get_array_formula_store()
+{
+ return m_array_formulas;
+}
+
+void xls_xml_context::store_cell_formula(std::string_view formula, const formula_result& res)
+{
+ assert(m_cur_sheet < ss::sheet_t(m_cell_formulas.size()));
+
+ cell_formula_type cf;
+ cf.pos = get_current_pos();
+ cf.formula = formula;
+ cf.result = res;
+ std::deque<cell_formula_type>& store = m_cell_formulas[m_cur_sheet];
+ store.push_back(std::move(cf));
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_context.hpp b/src/liborcus/xls_xml_context.hpp
new file mode 100644
index 0000000..24cb803
--- /dev/null
+++ b/src/liborcus/xls_xml_context.hpp
@@ -0,0 +1,334 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XLS_XML_CONTEXT_HPP
+#define INCLUDED_ORCUS_XLS_XML_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "orcus/spreadsheet/types.hpp"
+#include "orcus/spreadsheet/view_types.hpp"
+#include "orcus/string_pool.hpp"
+
+#include "formula_result.hpp"
+
+#include <string>
+#include <unordered_map>
+#include <list>
+#include <deque>
+#include <optional>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_sheet;
+class import_sheet_properties;
+class import_named_expression;
+class import_array_formula;
+
+}}
+
+class xls_xml_context;
+
+/**
+ * Context for handling <Data> element scopes.
+ */
+class xls_xml_data_context : public xml_context_base
+{
+ struct format_type
+ {
+ std::optional<bool> bold;
+ std::optional<bool> italic;
+ std::optional<bool> underline;
+ std::optional<bool> strikethrough;
+ std::optional<bool> subscript;
+ std::optional<bool> superscript;
+
+ std::optional<std::string_view> font_face;
+ std::optional<double> font_size;
+ std::optional<spreadsheet::color_rgb_t> color;
+
+ void merge(const format_type& other);
+ bool formatted() const;
+ };
+
+ struct string_segment_type
+ {
+ std::string_view str;
+ format_type format;
+ bool formatted = false;
+
+ string_segment_type(std::string_view _str);
+ };
+
+ enum cell_type { ct_unknown = 0, ct_string, ct_number, ct_datetime };
+
+ xls_xml_context& m_parent_cxt;
+
+ cell_type m_cell_type;
+ std::vector<string_segment_type> m_cell_string;
+ std::vector<format_type> m_format_stack;
+
+ format_type m_current_format;
+
+ double m_cell_value;
+ date_time_t m_cell_datetime;
+
+public:
+ xls_xml_data_context(session_context& session_cxt, const tokens& tokens, xls_xml_context& parent_cxt);
+ virtual ~xls_xml_data_context() override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs) override;
+ virtual void characters(std::string_view str, bool transient) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ /**
+ * Intendted to be called from the parent context instance, to reset its
+ * internal state before its use.
+ */
+ void reset();
+
+private:
+
+ void start_element_data(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void end_element_data();
+
+ bool handle_array_formula_result();
+ void push_array_result(
+ range_formula_results& res, size_t row_offset, size_t col_offset);
+
+ void push_formula_cell(std::string_view formula);
+ void store_array_formula_parent_cell(std::string_view formula);
+ void update_current_format();
+};
+
+class xls_xml_context : public xml_context_base
+{
+ friend class xls_xml_data_context;
+
+ struct cell_formula_type
+ {
+ spreadsheet::address_t pos;
+ std::string_view formula;
+ formula_result result;
+ };
+
+ struct array_formula_type
+ {
+ std::string_view formula;
+ range_formula_results results;
+
+ array_formula_type(const spreadsheet::range_t& _range, std::string_view _formula);
+ };
+
+ struct border_style_type
+ {
+ spreadsheet::border_direction_t dir = spreadsheet::border_direction_t::unknown;
+ spreadsheet::border_style_t style = spreadsheet::border_style_t::unknown;
+ std::optional<spreadsheet::color_rgb_t> color;
+ };
+
+ struct font_style_type
+ {
+ std::string_view name;
+ std::string_view family;
+ std::optional<double> size;
+ std::optional<spreadsheet::underline_t> underline;
+ bool bold = false;
+ bool italic = false;
+
+ spreadsheet::color_rgb_t color;
+ };
+
+ /**
+ * TODO: we only support solid fill for now. More fill types to be added
+ * later.
+ */
+ struct fill_style_type
+ {
+ bool solid = false;
+ spreadsheet::color_rgb_t color;
+ };
+
+ struct text_alignment_type
+ {
+ spreadsheet::hor_alignment_t hor = spreadsheet::hor_alignment_t::unknown;
+ spreadsheet::ver_alignment_t ver = spreadsheet::ver_alignment_t::unknown;
+ int8_t indent = 0;
+ bool wrap_text = false;
+ bool shrink_to_fit = false;
+ };
+
+ struct cell_protection_type
+ {
+ bool locked = true; // NB: default is locked
+ bool hide_formula = false;
+ };
+
+ struct style_type
+ {
+ std::string_view id;
+ std::string_view parent_id;
+ std::string_view name;
+
+ font_style_type font;
+ fill_style_type fill;
+ text_alignment_type text_alignment;
+ cell_protection_type cell_protection;
+ std::string_view number_format;
+ std::vector<border_style_type> borders;
+ };
+
+ struct named_exp
+ {
+ std::string_view name;
+ std::string_view expression;
+ spreadsheet::sheet_t scope;
+
+ named_exp(std::string_view _name, std::string_view _expression, spreadsheet::sheet_t _scope);
+ };
+
+ struct selection
+ {
+ spreadsheet::sheet_pane_t pane;
+ spreadsheet::col_t col;
+ spreadsheet::row_t row;
+ spreadsheet::range_t range;
+
+ selection();
+ void reset();
+ bool valid_cursor() const;
+ bool valid_range() const;
+ };
+
+ struct split_pane
+ {
+ spreadsheet::pane_state_t pane_state;
+ spreadsheet::sheet_pane_t active_pane;
+ double split_horizontal;
+ double split_vertical;
+ spreadsheet::row_t top_row_bottom_pane;
+ spreadsheet::col_t left_col_right_pane;
+
+ split_pane();
+ void reset();
+ bool split() const;
+ spreadsheet::address_t get_top_left_cell() const;
+ };
+
+ struct table_properties
+ {
+ spreadsheet::address_t pos; // top-left position
+
+ table_properties();
+ void reset();
+ };
+
+ using named_expressions_type = std::vector<named_exp>;
+ using styles_type = std::vector<std::unique_ptr<style_type>>;
+ using style_id_xf_map_type = std::unordered_map<std::string_view, std::size_t>;
+ using array_formula_pair_type = std::pair<spreadsheet::range_t, std::unique_ptr<array_formula_type>>;
+ using array_formulas_type = std::list<array_formula_pair_type>;
+ using cell_formulas_type = std::deque<std::deque<cell_formula_type>>;
+
+public:
+ xls_xml_context(session_context& session_cxt, const tokens& tokens, spreadsheet::iface::import_factory* factory);
+ virtual ~xls_xml_context();
+
+ virtual void declaration(const xml_declaration_t& decl) override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+private:
+
+ void start_element_borders(const xml_token_attrs_t& attrs);
+ void start_element_border(const xml_token_attrs_t& attrs);
+ void start_element_number_format(const xml_token_attrs_t& attrs);
+ void start_element_cell(const xml_token_attrs_t& attrs);
+ void start_element_column(const xml_token_attrs_t& attrs);
+ void start_element_row(const xml_token_attrs_t& attrs);
+ void start_element_table(const xml_token_attrs_t& attrs);
+ void start_element_worksheet(const xml_token_attrs_t& attrs);
+
+ void end_element_borders();
+ void end_element_border();
+ void end_element_number_format();
+ void end_element_cell();
+ void end_element_column();
+ void end_element_row();
+ void end_element_table();
+ void end_element_worksheet();
+ void end_element_workbook();
+ void end_element_styles();
+ void end_element_pane();
+ void end_element_worksheet_options();
+
+ void commit_split_pane();
+ void commit_default_style();
+ void commit_styles();
+
+ void push_all_array_formulas();
+
+private:
+ spreadsheet::iface::import_factory* get_import_factory();
+ spreadsheet::iface::import_sheet* get_import_sheet();
+ spreadsheet::address_t get_current_pos() const;
+ std::string_view pop_and_clear_formula();
+ bool is_array_formula() const;
+ const spreadsheet::range_t& get_array_range() const;
+ array_formulas_type& get_array_formula_store();
+
+ void store_cell_formula(std::string_view formula, const formula_result& res);
+
+private:
+ spreadsheet::iface::import_factory* mp_factory;
+ spreadsheet::iface::import_sheet* mp_cur_sheet;
+ spreadsheet::iface::import_sheet_properties* mp_sheet_props;
+
+ std::vector<spreadsheet::iface::import_named_expression*> m_sheet_named_exps;
+
+ spreadsheet::sheet_t m_cur_sheet;
+ spreadsheet::row_t m_cur_row;
+ spreadsheet::col_t m_cur_col;
+ spreadsheet::col_t m_cur_prop_col; /// current column position for column properties.
+ spreadsheet::row_t m_cur_merge_down;
+ spreadsheet::col_t m_cur_merge_across;
+ spreadsheet::range_t m_cur_array_range;
+ std::string_view m_cur_cell_formula;
+ std::string_view m_cur_cell_style_id;
+
+ cell_formulas_type m_cell_formulas;
+ array_formulas_type m_array_formulas;
+ named_expressions_type m_named_exps_global;
+ named_expressions_type m_named_exps_sheet;
+ selection m_cursor_selection; /// cursor selection in a single pane.
+ split_pane m_split_pane;
+
+ std::unique_ptr<style_type> m_current_style;
+ std::unique_ptr<style_type> m_default_style;
+ styles_type m_styles;
+ table_properties m_table_props;
+
+ style_id_xf_map_type m_style_map_cell;
+ style_id_xf_map_type m_style_map_named_style;
+
+ xls_xml_data_context m_cc_data;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_detection_handler.cpp b/src/liborcus/xls_xml_detection_handler.cpp
new file mode 100644
index 0000000..775cfb7
--- /dev/null
+++ b/src/liborcus/xls_xml_detection_handler.cpp
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xls_xml_detection_handler.hpp"
+#include "xls_xml_token_constants.hpp"
+#include "xls_xml_namespace_types.hpp"
+#include "xml_context_base.hpp"
+#include "detection_result.hpp"
+
+namespace orcus {
+
+namespace {
+
+/**
+ * Try to parse the XML stream up to the 1st Worksheet element while
+ * checking its structure along the way. If the structure up to that element
+ * is correct, then we call it "detected".
+ */
+class xls_xml_detection_context : public xml_context_base
+{
+public:
+ xls_xml_detection_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens) {}
+
+ virtual xml_context_base* create_child_context(xmlns_id_t, xml_token_t)
+ {
+ return nullptr;
+ }
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& /*attrs*/)
+ {
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_xls_xml_ss)
+ {
+ switch (name)
+ {
+ case XML_Workbook:
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ break;
+ case XML_Styles:
+ case XML_Worksheet:
+ {
+ xml_element_expected(parent, NS_xls_xml_ss, XML_Workbook);
+
+ // All good. Let's call it detected.
+ throw detection_result(true);
+ }
+ break;
+ case XML_Style:
+ xml_element_expected(parent, NS_xls_xml_ss, XML_Style);
+ break;
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_xls_xml_o)
+ {
+ switch (name)
+ {
+ case XML_DocumentProperties:
+ case XML_OfficeDocumentSettings:
+ xml_element_expected(parent, NS_xls_xml_ss, XML_Workbook);
+ break;
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_xls_xml_x)
+ {
+ switch (name)
+ {
+ case XML_ExcelWorkbook:
+ xml_element_expected(parent, NS_xls_xml_ss, XML_Workbook);
+ break;
+ default:
+ ;
+ }
+ }
+ }
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name)
+ {
+ return pop_stack(ns, name);
+ }
+
+ virtual void characters(std::string_view, bool)
+ {
+ }
+
+ virtual void end_child_context(xmlns_id_t, xml_token_t, xml_context_base*)
+ {
+ }
+};
+
+}
+
+xls_xml_detection_handler::xls_xml_detection_handler(
+ session_context& session_cxt, const tokens& t) :
+ xml_stream_handler(session_cxt, t, std::make_unique<xls_xml_detection_context>(session_cxt, t))
+{
+}
+
+xls_xml_detection_handler::~xls_xml_detection_handler() {}
+
+void xls_xml_detection_handler::start_document() {}
+void xls_xml_detection_handler::end_document() {}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_detection_handler.hpp b/src/liborcus/xls_xml_detection_handler.hpp
new file mode 100644
index 0000000..e8fd57d
--- /dev/null
+++ b/src/liborcus/xls_xml_detection_handler.hpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLS_XML_DETECTION_HANDLER_HPP
+#define ORCUS_XLS_XML_DETECTION_HANDLER_HPP
+
+#include "xml_stream_handler.hpp"
+
+namespace orcus {
+
+class tokens;
+struct session_context;
+
+class xls_xml_detection_handler : public xml_stream_handler
+{
+public:
+ xls_xml_detection_handler(session_context& session_cxt, const tokens& t);
+ virtual ~xls_xml_detection_handler();
+
+ virtual void start_document();
+ virtual void end_document();
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_handler.cpp b/src/liborcus/xls_xml_handler.cpp
new file mode 100644
index 0000000..5095b1e
--- /dev/null
+++ b/src/liborcus/xls_xml_handler.cpp
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xls_xml_handler.hpp"
+#include "xls_xml_context.hpp"
+
+namespace orcus {
+
+xls_xml_handler::xls_xml_handler(
+ session_context& session_cxt, const tokens& t, spreadsheet::iface::import_factory* factory) :
+ xml_stream_handler(session_cxt, t, std::make_unique<xls_xml_context>(session_cxt, t, factory))
+{
+}
+
+xls_xml_handler::~xls_xml_handler() {}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_handler.hpp b/src/liborcus/xls_xml_handler.hpp
new file mode 100644
index 0000000..d9a454b
--- /dev/null
+++ b/src/liborcus/xls_xml_handler.hpp
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLS_XML_HANDLER_HPP
+#define ORCUS_XLS_XML_HANDLER_HPP
+
+#include "xml_stream_handler.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+
+}}
+
+class tokens;
+struct session_context;
+
+class xls_xml_handler : public xml_stream_handler
+{
+public:
+ xls_xml_handler(session_context& session_cxt, const tokens& t, spreadsheet::iface::import_factory* factory);
+ virtual ~xls_xml_handler() override;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_namespace_types.cpp b/src/liborcus/xls_xml_namespace_types.cpp
new file mode 100644
index 0000000..96ccf6d
--- /dev/null
+++ b/src/liborcus/xls_xml_namespace_types.cpp
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xls_xml_namespace_types.hpp"
+
+namespace orcus {
+
+const xmlns_id_t NS_xls_xml_ss = "urn:schemas-microsoft-com:office:spreadsheet";
+const xmlns_id_t NS_xls_xml_o ="urn:schemas-microsoft-com:office:office";
+const xmlns_id_t NS_xls_xml_x ="urn:schemas-microsoft-com:office:excel";
+const xmlns_id_t NS_xls_xml_html ="http://www.w3.org/TR/REC-html40";
+
+namespace {
+
+xmlns_id_t xls_xml_ns[] = {
+ NS_xls_xml_ss,
+ NS_xls_xml_o,
+ NS_xls_xml_x,
+ NS_xls_xml_html,
+ nullptr
+};
+
+}
+
+const xmlns_id_t* NS_xls_xml_all = xls_xml_ns;
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_namespace_types.hpp b/src/liborcus/xls_xml_namespace_types.hpp
new file mode 100644
index 0000000..37de5b0
--- /dev/null
+++ b/src/liborcus/xls_xml_namespace_types.hpp
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLS_XML_NAMESPACE_TYPES_HPP
+#define ORCUS_XLS_XML_NAMESPACE_TYPES_HPP
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+extern const xmlns_id_t NS_xls_xml_ss;
+extern const xmlns_id_t NS_xls_xml_o;
+extern const xmlns_id_t NS_xls_xml_x;
+extern const xmlns_id_t NS_xls_xml_html;
+
+/**
+ * Null-terminated array of all xls xml namespaces.
+ */
+extern const xmlns_id_t* NS_xls_xml_all;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_token_constants.hpp b/src/liborcus/xls_xml_token_constants.hpp
new file mode 100644
index 0000000..9aca315
--- /dev/null
+++ b/src/liborcus/xls_xml_token_constants.hpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLS_XML_TOKEN_CONSTANTS_HPP
+#define ORCUS_XLS_XML_TOKEN_CONSTANTS_HPP
+
+#include "orcus/types.hpp"
+
+namespace orcus {
+
+#include "xls_xml_token_constants.inl"
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_token_constants.inl b/src/liborcus/xls_xml_token_constants.inl
new file mode 100644
index 0000000..902e2d5
--- /dev/null
+++ b/src/liborcus/xls_xml_token_constants.inl
@@ -0,0 +1,992 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const xml_token_t XML_AcceptLabelsInFormulas = 1;
+const xml_token_t XML_Action = 2;
+const xml_token_t XML_ActiveChart = 3;
+const xml_token_t XML_ActiveCol = 4;
+const xml_token_t XML_ActiveColumn = 5;
+const xml_token_t XML_ActivePane = 6;
+const xml_token_t XML_ActiveRow = 7;
+const xml_token_t XML_ActiveRows = 8;
+const xml_token_t XML_ActiveSheet = 9;
+const xml_token_t XML_Aggregate = 10;
+const xml_token_t XML_AlertVersion = 11;
+const xml_token_t XML_Alignment = 12;
+const xml_token_t XML_AllItemName = 13;
+const xml_token_t XML_AllowDeleteCols = 14;
+const xml_token_t XML_AllowDeleteRows = 15;
+const xml_token_t XML_AllowFilter = 16;
+const xml_token_t XML_AllowFormatCells = 17;
+const xml_token_t XML_AllowInsertCols = 18;
+const xml_token_t XML_AllowInsertHyperlinks = 19;
+const xml_token_t XML_AllowInsertRows = 20;
+const xml_token_t XML_AllowPNG = 21;
+const xml_token_t XML_AllowSizeCols = 22;
+const xml_token_t XML_AllowSizeRows = 23;
+const xml_token_t XML_AllowSort = 24;
+const xml_token_t XML_AllowUsePivotTables = 25;
+const xml_token_t XML_AlternateMethod = 26;
+const xml_token_t XML_AppName = 27;
+const xml_token_t XML_Append = 28;
+const xml_token_t XML_ApplyAutomaticOutlineStyles = 29;
+const xml_token_t XML_Area = 30;
+const xml_token_t XML_ArrayRange = 31;
+const xml_token_t XML_Async = 32;
+const xml_token_t XML_Attribute = 33;
+const xml_token_t XML_AttributeType = 34;
+const xml_token_t XML_Authentication = 35;
+const xml_token_t XML_Author = 36;
+const xml_token_t XML_AutoFilter = 37;
+const xml_token_t XML_AutoFilterAnd = 38;
+const xml_token_t XML_AutoFilterColumn = 39;
+const xml_token_t XML_AutoFilterCondition = 40;
+const xml_token_t XML_AutoFilterOr = 41;
+const xml_token_t XML_AutoFitHeight = 42;
+const xml_token_t XML_AutoFitWidth = 43;
+const xml_token_t XML_AutoFormatAlignment = 44;
+const xml_token_t XML_AutoFormatBorder = 45;
+const xml_token_t XML_AutoFormatFont = 46;
+const xml_token_t XML_AutoFormatName = 47;
+const xml_token_t XML_AutoFormatNumber = 48;
+const xml_token_t XML_AutoFormatPattern = 49;
+const xml_token_t XML_AutoFormatWidth = 50;
+const xml_token_t XML_AutoRepublish = 51;
+const xml_token_t XML_AutoShowCount = 52;
+const xml_token_t XML_AutoShowField = 53;
+const xml_token_t XML_AutoShowRange = 54;
+const xml_token_t XML_AutoShowType = 55;
+const xml_token_t XML_AutoSortField = 56;
+const xml_token_t XML_AutoSortOrder = 57;
+const xml_token_t XML_B = 58;
+const xml_token_t XML_BackgroundQuery = 59;
+const xml_token_t XML_BaseField = 60;
+const xml_token_t XML_BaseItem = 61;
+const xml_token_t XML_Basic = 62;
+const xml_token_t XML_Behavior = 63;
+const xml_token_t XML_Binding = 64;
+const xml_token_t XML_BlackAndWhite = 65;
+const xml_token_t XML_BlankLineAfterItems = 66;
+const xml_token_t XML_BlockTotal = 67;
+const xml_token_t XML_Bold = 68;
+const xml_token_t XML_Boolean = 69;
+const xml_token_t XML_Border = 70;
+const xml_token_t XML_Borders = 71;
+const xml_token_t XML_Bottom = 72;
+const xml_token_t XML_BoundField = 73;
+const xml_token_t XML_Bytes = 74;
+const xml_token_t XML_CacheDetails = 75;
+const xml_token_t XML_CacheFile = 76;
+const xml_token_t XML_CacheIndex = 77;
+const xml_token_t XML_CachePosition = 78;
+const xml_token_t XML_CalculatedMember = 79;
+const xml_token_t XML_Calculation = 80;
+const xml_token_t XML_CantGetUniqueItems = 81;
+const xml_token_t XML_Caption = 82;
+const xml_token_t XML_CaptionAlignment = 83;
+const xml_token_t XML_CaseSensitive = 84;
+const xml_token_t XML_Category = 85;
+const xml_token_t XML_Cell = 86;
+const xml_token_t XML_CellRangeList = 87;
+const xml_token_t XML_CellsExpanded = 88;
+const xml_token_t XML_CellsExpandedSeqNum = 89;
+const xml_token_t XML_CellsNotExpanded = 90;
+const xml_token_t XML_CenterHorizontal = 91;
+const xml_token_t XML_CenterVertical = 92;
+const xml_token_t XML_Cf = 93;
+const xml_token_t XML_CharSet = 94;
+const xml_token_t XML_Characters = 95;
+const xml_token_t XML_CharactersWithSpaces = 96;
+const xml_token_t XML_ClientParameter = 97;
+const xml_token_t XML_ClientParameterBinding = 98;
+const xml_token_t XML_ClientParameterBindings = 99;
+const xml_token_t XML_ClientParameterValue = 100;
+const xml_token_t XML_Clipped = 101;
+const xml_token_t XML_CodeName = 102;
+const xml_token_t XML_Col1 = 103;
+const xml_token_t XML_Col10 = 104;
+const xml_token_t XML_Col11 = 105;
+const xml_token_t XML_Col12 = 106;
+const xml_token_t XML_Col13 = 107;
+const xml_token_t XML_Col14 = 108;
+const xml_token_t XML_Col15 = 109;
+const xml_token_t XML_Col16 = 110;
+const xml_token_t XML_Col17 = 111;
+const xml_token_t XML_Col18 = 112;
+const xml_token_t XML_Col19 = 113;
+const xml_token_t XML_Col2 = 114;
+const xml_token_t XML_Col20 = 115;
+const xml_token_t XML_Col3 = 116;
+const xml_token_t XML_Col4 = 117;
+const xml_token_t XML_Col5 = 118;
+const xml_token_t XML_Col6 = 119;
+const xml_token_t XML_Col7 = 120;
+const xml_token_t XML_Col8 = 121;
+const xml_token_t XML_Col9 = 122;
+const xml_token_t XML_ColBreak = 123;
+const xml_token_t XML_ColBreaks = 124;
+const xml_token_t XML_ColFirst = 125;
+const xml_token_t XML_ColLast = 126;
+const xml_token_t XML_Color = 127;
+const xml_token_t XML_Column = 128;
+const xml_token_t XML_ColumnInfo = 129;
+const xml_token_t XML_ColumnInputCell = 130;
+const xml_token_t XML_ColumnName = 131;
+const xml_token_t XML_ComboHide = 132;
+const xml_token_t XML_Comma = 133;
+const xml_token_t XML_CommandText = 134;
+const xml_token_t XML_CommandTextOrignal = 135;
+const xml_token_t XML_CommandType = 136;
+const xml_token_t XML_Comment = 137;
+const xml_token_t XML_CommentsLayout = 138;
+const xml_token_t XML_Company = 139;
+const xml_token_t XML_ComponentOptions = 140;
+const xml_token_t XML_Condition = 141;
+const xml_token_t XML_ConditionalFormatting = 142;
+const xml_token_t XML_Connection = 143;
+const xml_token_t XML_ConnectionInfo = 144;
+const xml_token_t XML_ConnectionString = 145;
+const xml_token_t XML_Consecutive = 146;
+const xml_token_t XML_ConsolidationReference = 147;
+const xml_token_t XML_Count = 148;
+const xml_token_t XML_CountOfSameItems = 149;
+const xml_token_t XML_CreateBackup = 150;
+const xml_token_t XML_Created = 151;
+const xml_token_t XML_Credential = 152;
+const xml_token_t XML_CredentialBinding = 153;
+const xml_token_t XML_CredentialValue = 154;
+const xml_token_t XML_Crn = 155;
+const xml_token_t XML_CubeField = 156;
+const xml_token_t XML_CubeSource = 157;
+const xml_token_t XML_CurrentPage = 158;
+const xml_token_t XML_Custom = 159;
+const xml_token_t XML_CustomDocumentProperties = 160;
+const xml_token_t XML_Data = 161;
+const xml_token_t XML_DataAxisEmpty = 162;
+const xml_token_t XML_DataField = 163;
+const xml_token_t XML_DataMember = 164;
+const xml_token_t XML_DataSource = 165;
+const xml_token_t XML_DataTable = 166;
+const xml_token_t XML_DataType = 167;
+const xml_token_t XML_DataValidation = 168;
+const xml_token_t XML_DataValueEditing = 169;
+const xml_token_t XML_Date1904 = 170;
+const xml_token_t XML_Decimal = 171;
+const xml_token_t XML_DefaultColumnWidth = 172;
+const xml_token_t XML_DefaultItem = 173;
+const xml_token_t XML_DefaultRowHeight = 174;
+const xml_token_t XML_DefaultValue = 175;
+const xml_token_t XML_DefaultVersion = 176;
+const xml_token_t XML_DeletedTitle = 177;
+const xml_token_t XML_Delimiters = 178;
+const xml_token_t XML_Descending = 179;
+const xml_token_t XML_Description = 180;
+const xml_token_t XML_DetailFormat = 181;
+const xml_token_t XML_DetailMaxHeight = 182;
+const xml_token_t XML_DetailMaxWidth = 183;
+const xml_token_t XML_DetailRowHeight = 184;
+const xml_token_t XML_DetailSortOrder = 185;
+const xml_token_t XML_DetailWidth = 186;
+const xml_token_t XML_Dimension = 187;
+const xml_token_t XML_DisableDateRecognition = 188;
+const xml_token_t XML_DisableDrillDown = 189;
+const xml_token_t XML_DisableEdit = 190;
+const xml_token_t XML_DisableFieldDialog = 191;
+const xml_token_t XML_DisableRefresh = 192;
+const xml_token_t XML_DisableWizard = 193;
+const xml_token_t XML_DisplayDrawingObjects = 194;
+const xml_token_t XML_DisplayEmptyMembers = 195;
+const xml_token_t XML_DisplayErrorString = 196;
+const xml_token_t XML_DisplayFieldList = 197;
+const xml_token_t XML_DisplayFormulas = 198;
+const xml_token_t XML_DisplayIn = 199;
+const xml_token_t XML_DisplayInkNotes = 200;
+const xml_token_t XML_DisplayPageBreak = 201;
+const xml_token_t XML_DisplayRightToLeft = 202;
+const xml_token_t XML_DivID = 203;
+const xml_token_t XML_DoNotCalculateBeforeSave = 204;
+const xml_token_t XML_DoNotDisplayColHeaders = 205;
+const xml_token_t XML_DoNotDisplayGridlines = 206;
+const xml_token_t XML_DoNotDisplayHeadings = 207;
+const xml_token_t XML_DoNotDisplayOutline = 208;
+const xml_token_t XML_DoNotDisplayRowHeaders = 209;
+const xml_token_t XML_DoNotDisplayZeros = 210;
+const xml_token_t XML_DoNotJoinDelimiters = 211;
+const xml_token_t XML_DoNotPersist = 212;
+const xml_token_t XML_DoNotPersistSort = 213;
+const xml_token_t XML_DoNotPersstAF = 214;
+const xml_token_t XML_DoNotPromptForFile = 215;
+const xml_token_t XML_DoNotSaveLinkValues = 216;
+const xml_token_t XML_DocumentProperties = 217;
+const xml_token_t XML_DontShowInFieldList = 218;
+const xml_token_t XML_DownloadComponents = 219;
+const xml_token_t XML_DraftQuality = 220;
+const xml_token_t XML_DrawAspect = 221;
+const xml_token_t XML_DrilledLevel = 222;
+const xml_token_t XML_DrilledMember = 223;
+const xml_token_t XML_EditWebPage = 224;
+const xml_token_t XML_ElementType = 225;
+const xml_token_t XML_EmbedSaveSmartTags = 226;
+const xml_token_t XML_EnableMultiplePageItems = 227;
+const xml_token_t XML_EnableRedirections = 228;
+const xml_token_t XML_EnableSelection = 229;
+const xml_token_t XML_Encode = 230;
+const xml_token_t XML_EntirePage = 231;
+const xml_token_t XML_Entry = 232;
+const xml_token_t XML_Error = 233;
+const xml_token_t XML_ErrorHide = 234;
+const xml_token_t XML_ErrorMessage = 235;
+const xml_token_t XML_ErrorString = 236;
+const xml_token_t XML_ErrorStyle = 237;
+const xml_token_t XML_ErrorTitle = 238;
+const xml_token_t XML_ExcelName = 239;
+const xml_token_t XML_ExcelType = 240;
+const xml_token_t XML_ExcelWorkbook = 241;
+const xml_token_t XML_ExcelWorksheetType = 242;
+const xml_token_t XML_Expanded = 243;
+const xml_token_t XML_ExpandedColumnCount = 244;
+const xml_token_t XML_ExpandedRowCount = 245;
+const xml_token_t XML_ExternName = 246;
+const xml_token_t XML_ExtraLeftColumns = 247;
+const xml_token_t XML_ExtraRightColumns = 248;
+const xml_token_t XML_Face = 249;
+const xml_token_t XML_Family = 250;
+const xml_token_t XML_Field = 251;
+const xml_token_t XML_FieldLabelFormat = 252;
+const xml_token_t XML_FieldListBottom = 253;
+const xml_token_t XML_FieldListLeft = 254;
+const xml_token_t XML_FieldListRight = 255;
+const xml_token_t XML_FieldListTop = 256;
+const xml_token_t XML_FieldStart = 257;
+const xml_token_t XML_FieldType = 258;
+const xml_token_t XML_File = 259;
+const xml_token_t XML_FileName = 260;
+const xml_token_t XML_FillDown = 261;
+const xml_token_t XML_Filled = 262;
+const xml_token_t XML_FilterCaption = 263;
+const xml_token_t XML_FilterMember = 264;
+const xml_token_t XML_FilterOn = 265;
+const xml_token_t XML_FirstVisibleSheet = 266;
+const xml_token_t XML_FitHeight = 267;
+const xml_token_t XML_FitToPage = 268;
+const xml_token_t XML_FitWidth = 269;
+const xml_token_t XML_Font = 270;
+const xml_token_t XML_FontName = 271;
+const xml_token_t XML_Footer = 272;
+const xml_token_t XML_Format = 273;
+const xml_token_t XML_FormatSettings = 274;
+const xml_token_t XML_FormatType = 275;
+const xml_token_t XML_Formula = 276;
+const xml_token_t XML_FormulaIndex = 277;
+const xml_token_t XML_FormulaV10 = 278;
+const xml_token_t XML_FreezePanes = 279;
+const xml_token_t XML_FrozenNoSplit = 280;
+const xml_token_t XML_FullColumns = 281;
+const xml_token_t XML_FullRows = 282;
+const xml_token_t XML_Function = 283;
+const xml_token_t XML_FunctionGroup = 284;
+const xml_token_t XML_FunctionGroupIndex = 285;
+const xml_token_t XML_FuturePersist = 286;
+const xml_token_t XML_FutureVer = 287;
+const xml_token_t XML_GrandTotalString = 288;
+const xml_token_t XML_GridlineColor = 289;
+const xml_token_t XML_GridlineColorIndex = 290;
+const xml_token_t XML_Gridlines = 291;
+const xml_token_t XML_GroupBy = 292;
+const xml_token_t XML_GroupDefinition = 293;
+const xml_token_t XML_GroupEnd = 294;
+const xml_token_t XML_GroupEndAuto = 295;
+const xml_token_t XML_GroupLevel = 296;
+const xml_token_t XML_GroupMember = 297;
+const xml_token_t XML_GroupNumber = 298;
+const xml_token_t XML_GroupStart = 299;
+const xml_token_t XML_GroupStartAuto = 300;
+const xml_token_t XML_GroupType = 301;
+const xml_token_t XML_GroupedWidth = 302;
+const xml_token_t XML_Guid = 303;
+const xml_token_t XML_HRef = 304;
+const xml_token_t XML_HRefScreenTip = 305;
+const xml_token_t XML_HTMLFormat = 306;
+const xml_token_t XML_HTMLTables = 307;
+const xml_token_t XML_HasNoAutoFormat = 308;
+const xml_token_t XML_HasNoRecords = 309;
+const xml_token_t XML_Header = 310;
+const xml_token_t XML_HeaderRange = 311;
+const xml_token_t XML_HeaderRow = 312;
+const xml_token_t XML_Height = 313;
+const xml_token_t XML_Hidden = 314;
+const xml_token_t XML_HideDetail = 315;
+const xml_token_t XML_HideDropDowns = 316;
+const xml_token_t XML_HideFormula = 317;
+const xml_token_t XML_HideHorizontalScrollBar = 318;
+const xml_token_t XML_HideInactiveListBorder = 319;
+const xml_token_t XML_HideOfficeLogo = 320;
+const xml_token_t XML_HidePivotTableFieldList = 321;
+const xml_token_t XML_HideTotalsAnnotation = 322;
+const xml_token_t XML_HideVerticalScrollBar = 323;
+const xml_token_t XML_HideWorkbookTabs = 324;
+const xml_token_t XML_Horizontal = 325;
+const xml_token_t XML_HorizontalResolution = 326;
+const xml_token_t XML_Href = 327;
+const xml_token_t XML_HtmlType = 328;
+const xml_token_t XML_HyperlinkBase = 329;
+const xml_token_t XML_I = 330;
+const xml_token_t XML_ID = 331;
+const xml_token_t XML_IMEMode = 332;
+const xml_token_t XML_Id = 333;
+const xml_token_t XML_IdWrapped = 334;
+const xml_token_t XML_If = 335;
+const xml_token_t XML_ImmediateItemsOnDrop = 336;
+const xml_token_t XML_Indent = 337;
+const xml_token_t XML_Index = 338;
+const xml_token_t XML_IndividualCellBorders = 339;
+const xml_token_t XML_InputHide = 340;
+const xml_token_t XML_InputMessage = 341;
+const xml_token_t XML_InputTitle = 342;
+const xml_token_t XML_InsertEntireRows = 343;
+const xml_token_t XML_InstanceShape = 344;
+const xml_token_t XML_Interior = 345;
+const xml_token_t XML_IntlMacro = 346;
+const xml_token_t XML_Invalid = 347;
+const xml_token_t XML_InvertedColumnMember = 348;
+const xml_token_t XML_InvertedRowMember = 349;
+const xml_token_t XML_IsGroupLevel = 350;
+const xml_token_t XML_IsMemberProperty = 351;
+const xml_token_t XML_IsNotFiltered = 352;
+const xml_token_t XML_Italic = 353;
+const xml_token_t XML_Item = 354;
+const xml_token_t XML_ItemType = 355;
+const xml_token_t XML_Iteration = 356;
+const xml_token_t XML_KeyboardShortcut = 357;
+const xml_token_t XML_Keywords = 358;
+const xml_token_t XML_Label = 359;
+const xml_token_t XML_LastAuthor = 360;
+const xml_token_t XML_LastPrinted = 361;
+const xml_token_t XML_LastSaved = 362;
+const xml_token_t XML_Layout = 363;
+const xml_token_t XML_LayoutForm = 364;
+const xml_token_t XML_LayoutPageBreak = 365;
+const xml_token_t XML_LayoutSubtotalLocation = 366;
+const xml_token_t XML_LeafColumnMember = 367;
+const xml_token_t XML_LeafRowMember = 368;
+const xml_token_t XML_Left = 369;
+const xml_token_t XML_LeftCell = 370;
+const xml_token_t XML_LeftColumnRightPane = 371;
+const xml_token_t XML_LeftColumnVisible = 372;
+const xml_token_t XML_LeftToRight = 373;
+const xml_token_t XML_LengthLevelUniqueName = 374;
+const xml_token_t XML_Level = 375;
+const xml_token_t XML_LineStyle = 376;
+const xml_token_t XML_Lines = 377;
+const xml_token_t XML_LoadMode = 378;
+const xml_token_t XML_LocalConnection = 379;
+const xml_token_t XML_Location = 380;
+const xml_token_t XML_LocationOfComponents = 381;
+const xml_token_t XML_Macro = 382;
+const xml_token_t XML_MainFile = 383;
+const xml_token_t XML_Maintain = 384;
+const xml_token_t XML_MajorVersion = 385;
+const xml_token_t XML_Manager = 386;
+const xml_token_t XML_Map = 387;
+const xml_token_t XML_MapChildItems = 388;
+const xml_token_t XML_MapID = 389;
+const xml_token_t XML_MapInfo = 390;
+const xml_token_t XML_Mapdata = 391;
+const xml_token_t XML_Margin = 392;
+const xml_token_t XML_Max = 393;
+const xml_token_t XML_MaxChange = 394;
+const xml_token_t XML_MaxHeight = 395;
+const xml_token_t XML_MaxIterations = 396;
+const xml_token_t XML_MaxWidth = 397;
+const xml_token_t XML_Measure = 398;
+const xml_token_t XML_Member = 399;
+const xml_token_t XML_MemberExpand = 400;
+const xml_token_t XML_MemberFormat = 401;
+const xml_token_t XML_MemberName = 402;
+const xml_token_t XML_MemberPropertiesOrder = 403;
+const xml_token_t XML_MemberProperty = 404;
+const xml_token_t XML_MemberPropertyParent = 405;
+const xml_token_t XML_MergeAcross = 406;
+const xml_token_t XML_MergeDown = 407;
+const xml_token_t XML_MergeLabels = 408;
+const xml_token_t XML_Min = 409;
+const xml_token_t XML_MinorVersion = 410;
+const xml_token_t XML_Missing = 411;
+const xml_token_t XML_MissingItemsLimit = 412;
+const xml_token_t XML_Moper = 413;
+const xml_token_t XML_MoveAfterReturn = 414;
+const xml_token_t XML_Name = 415;
+const xml_token_t XML_NamedCell = 416;
+const xml_token_t XML_NamedRange = 417;
+const xml_token_t XML_Names = 418;
+const xml_token_t XML_Namespace = 419;
+const xml_token_t XML_NewAsync = 420;
+const xml_token_t XML_NewItemsHidden = 421;
+const xml_token_t XML_NextId = 422;
+const xml_token_t XML_NextSheetNumber = 423;
+const xml_token_t XML_NoAutoFit = 424;
+const xml_token_t XML_NoAutoFormatWidth = 425;
+const xml_token_t XML_NoAutoPage = 426;
+const xml_token_t XML_NoAutoRecover = 427;
+const xml_token_t XML_NoAutofit = 428;
+const xml_token_t XML_NoColumnGrand = 429;
+const xml_token_t XML_NoDetailAutoFit = 430;
+const xml_token_t XML_NoDisplayNullString = 431;
+const xml_token_t XML_NoDragToColumn = 432;
+const xml_token_t XML_NoDragToData = 433;
+const xml_token_t XML_NoDragToHide = 434;
+const xml_token_t XML_NoDragToPage = 435;
+const xml_token_t XML_NoDragToRow = 436;
+const xml_token_t XML_NoInserts = 437;
+const xml_token_t XML_NoPreserveFormatting = 438;
+const xml_token_t XML_NoPrintRepeatItems = 439;
+const xml_token_t XML_NoPrinterInfo = 440;
+const xml_token_t XML_NoRefreshCache = 441;
+const xml_token_t XML_NoRowGrand = 442;
+const xml_token_t XML_NoSaveData = 443;
+const xml_token_t XML_NoSummaryColumnsRightDetail = 444;
+const xml_token_t XML_NoSummaryRowsBelowDetail = 445;
+const xml_token_t XML_NoTextToColumns = 446;
+const xml_token_t XML_NoTitles = 447;
+const xml_token_t XML_NoToggleDataHeader = 448;
+const xml_token_t XML_NoViewCalculatedMembers = 449;
+const xml_token_t XML_NonDefaultName = 450;
+const xml_token_t XML_NotInverted = 451;
+const xml_token_t XML_NotVisible = 452;
+const xml_token_t XML_NullString = 453;
+const xml_token_t XML_Number = 454;
+const xml_token_t XML_NumberFormat = 455;
+const xml_token_t XML_NumberOfCopies = 456;
+const xml_token_t XML_OLEObject = 457;
+const xml_token_t XML_OWCVersion = 458;
+const xml_token_t XML_ObjectID = 459;
+const xml_token_t XML_OfficeDocumentSettings = 460;
+const xml_token_t XML_OleLink = 461;
+const xml_token_t XML_Operator = 462;
+const xml_token_t XML_OptimizeCache = 463;
+const xml_token_t XML_Orientation = 464;
+const xml_token_t XML_Outline = 465;
+const xml_token_t XML_OverwriteCells = 466;
+const xml_token_t XML_PLCaption = 467;
+const xml_token_t XML_PLDataOrientation = 468;
+const xml_token_t XML_PLExport = 469;
+const xml_token_t XML_PLGroupType = 470;
+const xml_token_t XML_PLName = 471;
+const xml_token_t XML_PLPivotField = 472;
+const xml_token_t XML_PLPosition = 473;
+const xml_token_t XML_PLSubtotal = 474;
+const xml_token_t XML_PLTPivotItem = 475;
+const xml_token_t XML_PLTotal = 476;
+const xml_token_t XML_PTFormat = 477;
+const xml_token_t XML_PTFormula = 478;
+const xml_token_t XML_PTLineItem = 479;
+const xml_token_t XML_PTLineItems = 480;
+const xml_token_t XML_PTPivotData = 481;
+const xml_token_t XML_PTRule = 482;
+const xml_token_t XML_PTSource = 483;
+const xml_token_t XML_PageBreakZoom = 484;
+const xml_token_t XML_PageBreaks = 485;
+const xml_token_t XML_PageFieldOrder = 486;
+const xml_token_t XML_PageFieldStyle = 487;
+const xml_token_t XML_PageFieldWrapCount = 488;
+const xml_token_t XML_PageMargins = 489;
+const xml_token_t XML_PageSetup = 490;
+const xml_token_t XML_Pages = 491;
+const xml_token_t XML_Pane = 492;
+const xml_token_t XML_Panes = 493;
+const xml_token_t XML_PaperSizeIndex = 494;
+const xml_token_t XML_Paragraphs = 495;
+const xml_token_t XML_Parameter = 496;
+const xml_token_t XML_ParameterType = 497;
+const xml_token_t XML_ParameterValue = 498;
+const xml_token_t XML_Parent = 499;
+const xml_token_t XML_ParentField = 500;
+const xml_token_t XML_ParentIsOther = 501;
+const xml_token_t XML_ParentName = 502;
+const xml_token_t XML_ParentUniqueName = 503;
+const xml_token_t XML_ParseFormulaAsV10 = 504;
+const xml_token_t XML_ParseRuleAsV10 = 505;
+const xml_token_t XML_PasteFormula = 506;
+const xml_token_t XML_PasteRefersTo = 507;
+const xml_token_t XML_Path = 508;
+const xml_token_t XML_Pattern = 509;
+const xml_token_t XML_PatternColor = 510;
+const xml_token_t XML_PivotAxis = 511;
+const xml_token_t XML_PivotCache = 512;
+const xml_token_t XML_PivotField = 513;
+const xml_token_t XML_PivotItem = 514;
+const xml_token_t XML_PivotTable = 515;
+const xml_token_t XML_PivotView = 516;
+const xml_token_t XML_Position = 517;
+const xml_token_t XML_PrecisionAsDisplayed = 518;
+const xml_token_t XML_PresentationFormat = 519;
+const xml_token_t XML_Print = 520;
+const xml_token_t XML_PrintErrors = 521;
+const xml_token_t XML_PrintSetTitles = 522;
+const xml_token_t XML_ProgID = 523;
+const xml_token_t XML_PromptString = 524;
+const xml_token_t XML_ProtectContents = 525;
+const xml_token_t XML_ProtectObjects = 526;
+const xml_token_t XML_ProtectScenarios = 527;
+const xml_token_t XML_ProtectStructure = 528;
+const xml_token_t XML_ProtectWindows = 529;
+const xml_token_t XML_Protected = 530;
+const xml_token_t XML_Protection = 531;
+const xml_token_t XML_Proxy = 532;
+const xml_token_t XML_PublishObject = 533;
+const xml_token_t XML_PublishObjects = 534;
+const xml_token_t XML_Purpose = 535;
+const xml_token_t XML_QTSource = 536;
+const xml_token_t XML_Qualifier = 537;
+const xml_token_t XML_Query97 = 538;
+const xml_token_t XML_QuerySource = 539;
+const xml_token_t XML_QueryTable = 540;
+const xml_token_t XML_QueryType = 541;
+const xml_token_t XML_Range = 542;
+const xml_token_t XML_RangeSelection = 543;
+const xml_token_t XML_ReadOnly = 544;
+const xml_token_t XML_ReadingOrder = 545;
+const xml_token_t XML_RefModeR1C1 = 546;
+const xml_token_t XML_Reference = 547;
+const xml_token_t XML_RefersTo = 548;
+const xml_token_t XML_RefreshDate = 549;
+const xml_token_t XML_RefreshDateCopy = 550;
+const xml_token_t XML_RefreshInfo = 551;
+const xml_token_t XML_RefreshName = 552;
+const xml_token_t XML_RefreshOnChange = 553;
+const xml_token_t XML_RefreshOnFileOpen = 554;
+const xml_token_t XML_RefreshTimeSpan = 555;
+const xml_token_t XML_RefreshedInXl9 = 556;
+const xml_token_t XML_Resource = 557;
+const xml_token_t XML_Revision = 558;
+const xml_token_t XML_Right = 559;
+const xml_token_t XML_RightToLeft = 560;
+const xml_token_t XML_RobustConnect = 561;
+const xml_token_t XML_RootElement = 562;
+const xml_token_t XML_Rotate = 563;
+const xml_token_t XML_Rotation = 564;
+const xml_token_t XML_Row = 565;
+const xml_token_t XML_RowBreak = 566;
+const xml_token_t XML_RowBreaks = 567;
+const xml_token_t XML_RowColHeadings = 568;
+const xml_token_t XML_RowInputCell = 569;
+const xml_token_t XML_RowLast = 570;
+const xml_token_t XML_RowNumbers = 571;
+const xml_token_t XML_Rule = 572;
+const xml_token_t XML_RuleType = 573;
+const xml_token_t XML_RuleV10 = 574;
+const xml_token_t XML_S = 575;
+const xml_token_t XML_SOAPAction = 576;
+const xml_token_t XML_SQLType = 577;
+const xml_token_t XML_Scale = 578;
+const xml_token_t XML_Schema = 579;
+const xml_token_t XML_SchemaID = 580;
+const xml_token_t XML_SchemaRef = 581;
+const xml_token_t XML_Selected = 582;
+const xml_token_t XML_SelectedSheets = 583;
+const xml_token_t XML_Selection = 584;
+const xml_token_t XML_SelectionNamespaces = 585;
+const xml_token_t XML_SemiColon = 586;
+const xml_token_t XML_SeqNum = 587;
+const xml_token_t XML_Sequence = 588;
+const xml_token_t XML_ServerBased = 589;
+const xml_token_t XML_ServerSortOrder = 590;
+const xml_token_t XML_Set = 591;
+const xml_token_t XML_Shadow = 592;
+const xml_token_t XML_ShapeID = 593;
+const xml_token_t XML_SheetIndex = 594;
+const xml_token_t XML_SheetName = 595;
+const xml_token_t XML_ShowAllItems = 596;
+const xml_token_t XML_ShowAlways = 597;
+const xml_token_t XML_ShowCellBackgroundFromOLAP = 598;
+const xml_token_t XML_ShowImportExportValidationErrors = 599;
+const xml_token_t XML_ShowPageBreakZoom = 600;
+const xml_token_t XML_ShowPageMultipleItemLabel = 601;
+const xml_token_t XML_ShowTotals = 602;
+const xml_token_t XML_ShrinkToFit = 603;
+const xml_token_t XML_Size = 604;
+const xml_token_t XML_SmallGrid = 605;
+const xml_token_t XML_SmartTagType = 606;
+const xml_token_t XML_SmartTags = 607;
+const xml_token_t XML_SolveOrder = 608;
+const xml_token_t XML_Sort = 609;
+const xml_token_t XML_SortKey = 610;
+const xml_token_t XML_SortOrder = 611;
+const xml_token_t XML_Sorting = 612;
+const xml_token_t XML_Source = 613;
+const xml_token_t XML_SourceConnectionFile = 614;
+const xml_token_t XML_SourceConsolidation = 615;
+const xml_token_t XML_SourceDataFile = 616;
+const xml_token_t XML_SourceHierarchy = 617;
+const xml_token_t XML_SourceHierarchyLevel = 618;
+const xml_token_t XML_SourceName = 619;
+const xml_token_t XML_SourceType = 620;
+const xml_token_t XML_Space = 621;
+const xml_token_t XML_SpaceAbove = 622;
+const xml_token_t XML_SpaceBelow = 623;
+const xml_token_t XML_Span = 624;
+const xml_token_t XML_SplitHorizontal = 625;
+const xml_token_t XML_SplitVertical = 626;
+const xml_token_t XML_SpreadsheetAutoFit = 627;
+const xml_token_t XML_StandardWidth = 628;
+const xml_token_t XML_StartPageNumber = 629;
+const xml_token_t XML_StartRow = 630;
+const xml_token_t XML_StrikeThrough = 631;
+const xml_token_t XML_Style = 632;
+const xml_token_t XML_StyleID = 633;
+const xml_token_t XML_Styles = 634;
+const xml_token_t XML_Sub = 635;
+const xml_token_t XML_SubType = 636;
+const xml_token_t XML_Subject = 637;
+const xml_token_t XML_Subtotal = 638;
+const xml_token_t XML_SubtotalFormat = 639;
+const xml_token_t XML_SubtotalHiddenPageItems = 640;
+const xml_token_t XML_SubtotalName = 641;
+const xml_token_t XML_Sup = 642;
+const xml_token_t XML_SupBook = 643;
+const xml_token_t XML_Synchronous = 644;
+const xml_token_t XML_Tab = 645;
+const xml_token_t XML_TabColorIndex = 646;
+const xml_token_t XML_TabRatio = 647;
+const xml_token_t XML_Table = 648;
+const xml_token_t XML_TableStyle = 649;
+const xml_token_t XML_Tag = 650;
+const xml_token_t XML_Text = 651;
+const xml_token_t XML_TextQualifier = 652;
+const xml_token_t XML_TextWizardSettings = 653;
+const xml_token_t XML_ThousandSeparator = 654;
+const xml_token_t XML_Ticked = 655;
+const xml_token_t XML_Title = 656;
+const xml_token_t XML_Toolbar = 657;
+const xml_token_t XML_TooltipInfo = 658;
+const xml_token_t XML_Top = 659;
+const xml_token_t XML_TopCell = 660;
+const xml_token_t XML_TopRowBottomPane = 661;
+const xml_token_t XML_TopRowVisible = 662;
+const xml_token_t XML_TotalAlignment = 663;
+const xml_token_t XML_TotalAllMembers = 664;
+const xml_token_t XML_TotalCaptionAlignment = 665;
+const xml_token_t XML_TotalFormat = 666;
+const xml_token_t XML_TotalTime = 667;
+const xml_token_t XML_TotalWidth = 668;
+const xml_token_t XML_TransitionExpressionEvaluation = 669;
+const xml_token_t XML_TransitionFormulaEntry = 670;
+const xml_token_t XML_Type = 671;
+const xml_token_t XML_U = 672;
+const xml_token_t XML_URLString = 673;
+const xml_token_t XML_Uncalced = 674;
+const xml_token_t XML_Underline = 675;
+const xml_token_t XML_UniqueName = 676;
+const xml_token_t XML_Unsynced = 677;
+const xml_token_t XML_UseBlank = 678;
+const xml_token_t XML_UseLocalConnection = 679;
+const xml_token_t XML_UseSameSettings = 680;
+const xml_token_t XML_User = 681;
+const xml_token_t XML_VMLFrame = 682;
+const xml_token_t XML_VacatedStyle = 683;
+const xml_token_t XML_ValidPrinterInfo = 684;
+const xml_token_t XML_Value = 685;
+const xml_token_t XML_Value1 = 686;
+const xml_token_t XML_Value2 = 687;
+const xml_token_t XML_Version = 688;
+const xml_token_t XML_VersionLastEdit = 689;
+const xml_token_t XML_VersionLastRefresh = 690;
+const xml_token_t XML_VersionLastUpdate = 691;
+const xml_token_t XML_VersionRefreshableMin = 692;
+const xml_token_t XML_VersionUpdateableMin = 693;
+const xml_token_t XML_Vertical = 694;
+const xml_token_t XML_VerticalAlign = 695;
+const xml_token_t XML_VerticalResolution = 696;
+const xml_token_t XML_VerticalText = 697;
+const xml_token_t XML_ViewableRange = 698;
+const xml_token_t XML_Visible = 699;
+const xml_token_t XML_VisualTotals = 700;
+const xml_token_t XML_WantAdvise = 701;
+const xml_token_t XML_WantPict = 702;
+const xml_token_t XML_Watch = 703;
+const xml_token_t XML_Watches = 704;
+const xml_token_t XML_WebPostString = 705;
+const xml_token_t XML_Weight = 706;
+const xml_token_t XML_Width = 707;
+const xml_token_t XML_WindowHeight = 708;
+const xml_token_t XML_WindowHidden = 709;
+const xml_token_t XML_WindowIconic = 710;
+const xml_token_t XML_WindowTopX = 711;
+const xml_token_t XML_WindowTopY = 712;
+const xml_token_t XML_WindowWidth = 713;
+const xml_token_t XML_Windows = 714;
+const xml_token_t XML_Words = 715;
+const xml_token_t XML_Workbook = 716;
+const xml_token_t XML_WorkbookOptions = 717;
+const xml_token_t XML_Worksheet = 718;
+const xml_token_t XML_WorksheetOptions = 719;
+const xml_token_t XML_WorksheetSource = 720;
+const xml_token_t XML_WrapText = 721;
+const xml_token_t XML_XPath = 722;
+const xml_token_t XML_XSDType = 723;
+const xml_token_t XML_Xct = 724;
+const xml_token_t XML_ZeroHeight = 725;
+const xml_token_t XML_Zoom = 726;
+const xml_token_t XML_accentbar = 727;
+const xml_token_t XML_adj = 728;
+const xml_token_t XML_adjusthandles = 729;
+const xml_token_t XML_alignshape = 730;
+const xml_token_t XML_allowincell = 731;
+const xml_token_t XML_allowoverlap = 732;
+const xml_token_t XML_alt = 733;
+const xml_token_t XML_althref = 734;
+const xml_token_t XML_angle = 735;
+const xml_token_t XML_arc = 736;
+const xml_token_t XML_arcsize = 737;
+const xml_token_t XML_arrowok = 738;
+const xml_token_t XML_aspect = 739;
+const xml_token_t XML_aspectratio = 740;
+const xml_token_t XML_attribute = 741;
+const xml_token_t XML_autorotationcenter = 742;
+const xml_token_t XML_backdepth = 743;
+const xml_token_t XML_background = 744;
+const xml_token_t XML_bilevel = 745;
+const xml_token_t XML_blacklevel = 746;
+const xml_token_t XML_borderbottomcolor = 747;
+const xml_token_t XML_borderleftcolor = 748;
+const xml_token_t XML_borderrightcolor = 749;
+const xml_token_t XML_bordertopcolor = 750;
+const xml_token_t XML_brightness = 751;
+const xml_token_t XML_bullet = 752;
+const xml_token_t XML_button = 753;
+const xml_token_t XML_bwmode = 754;
+const xml_token_t XML_bwnormal = 755;
+const xml_token_t XML_bwpure = 756;
+const xml_token_t XML_callout = 757;
+const xml_token_t XML_caption = 758;
+const xml_token_t XML_chromakey = 759;
+const xml_token_t XML_class = 760;
+const xml_token_t XML_clip = 761;
+const xml_token_t XML_color = 762;
+const xml_token_t XML_color2 = 763;
+const xml_token_t XML_colormenu = 764;
+const xml_token_t XML_colormode = 765;
+const xml_token_t XML_colormru = 766;
+const xml_token_t XML_colors = 767;
+const xml_token_t XML_complex = 768;
+const xml_token_t XML_connectangles = 769;
+const xml_token_t XML_connectloc = 770;
+const xml_token_t XML_connectlocs = 771;
+const xml_token_t XML_connectortype = 772;
+const xml_token_t XML_connecttype = 773;
+const xml_token_t XML_content = 774;
+const xml_token_t XML_control1 = 775;
+const xml_token_t XML_control2 = 776;
+const xml_token_t XML_coordorigin = 777;
+const xml_token_t XML_coordsize = 778;
+const xml_token_t XML_cropbottom = 779;
+const xml_token_t XML_cropleft = 780;
+const xml_token_t XML_cropping = 781;
+const xml_token_t XML_cropright = 782;
+const xml_token_t XML_croptop = 783;
+const xml_token_t XML_curve = 784;
+const xml_token_t XML_dashstyle = 785;
+const xml_token_t XML_data = 786;
+const xml_token_t XML_datatype = 787;
+const xml_token_t XML_detectmouseclick = 788;
+const xml_token_t XML_diffusity = 789;
+const xml_token_t XML_displaycustomheaders = 790;
+const xml_token_t XML_distance = 791;
+const xml_token_t XML_doubleclicknotify = 792;
+const xml_token_t XML_drop = 793;
+const xml_token_t XML_dropauto = 794;
+const xml_token_t XML_dt = 795;
+const xml_token_t XML_edge = 796;
+const xml_token_t XML_editas = 797;
+const xml_token_t XML_embosscolor = 798;
+const xml_token_t XML_end = 799;
+const xml_token_t XML_endAngle = 800;
+const xml_token_t XML_endarrow = 801;
+const xml_token_t XML_endarrowlength = 802;
+const xml_token_t XML_endarrowwidth = 803;
+const xml_token_t XML_endcap = 804;
+const xml_token_t XML_entry = 805;
+const xml_token_t XML_eqn = 806;
+const xml_token_t XML_ext = 807;
+const xml_token_t XML_extends = 808;
+const xml_token_t XML_extrusion = 809;
+const xml_token_t XML_extrusioncolor = 810;
+const xml_token_t XML_extrusionok = 811;
+const xml_token_t XML_f = 812;
+const xml_token_t XML_facet = 813;
+const xml_token_t XML_fill = 814;
+const xml_token_t XML_fillcolor = 815;
+const xml_token_t XML_filled = 816;
+const xml_token_t XML_fillok = 817;
+const xml_token_t XML_filltype = 818;
+const xml_token_t XML_fitpath = 819;
+const xml_token_t XML_fitshape = 820;
+const xml_token_t XML_focus = 821;
+const xml_token_t XML_focusposition = 822;
+const xml_token_t XML_focussize = 823;
+const xml_token_t XML_forcedash = 824;
+const xml_token_t XML_foredepth = 825;
+const xml_token_t XML_formulas = 826;
+const xml_token_t XML_from = 827;
+const xml_token_t XML_gain = 828;
+const xml_token_t XML_gamma = 829;
+const xml_token_t XML_gap = 830;
+const xml_token_t XML_gradientshapeok = 831;
+const xml_token_t XML_grayscale = 832;
+const xml_token_t XML_group = 833;
+const xml_token_t XML_grouping = 834;
+const xml_token_t XML_h = 835;
+const xml_token_t XML_handles = 836;
+const xml_token_t XML_hidden = 837;
+const xml_token_t XML_how = 838;
+const xml_token_t XML_hr = 839;
+const xml_token_t XML_hralign = 840;
+const xml_token_t XML_href = 841;
+const xml_token_t XML_hrheight = 842;
+const xml_token_t XML_hrnoshade = 843;
+const xml_token_t XML_hrpct = 844;
+const xml_token_t XML_hrstd = 845;
+const xml_token_t XML_hrwidth = 846;
+const xml_token_t XML_id = 847;
+const xml_token_t XML_idmap = 848;
+const xml_token_t XML_idref = 849;
+const xml_token_t XML_image = 850;
+const xml_token_t XML_imagealignshape = 851;
+const xml_token_t XML_imageaspect = 852;
+const xml_token_t XML_imagedata = 853;
+const xml_token_t XML_imagesize = 854;
+const xml_token_t XML_inset = 855;
+const xml_token_t XML_insetmode = 856;
+const xml_token_t XML_invx = 857;
+const xml_token_t XML_invy = 858;
+const xml_token_t XML_joinstyle = 859;
+const xml_token_t XML_length = 860;
+const xml_token_t XML_lengthspecified = 861;
+const xml_token_t XML_lightface = 862;
+const xml_token_t XML_lightharsh = 863;
+const xml_token_t XML_lightharsh2 = 864;
+const xml_token_t XML_lightlevel = 865;
+const xml_token_t XML_lightlevel2 = 866;
+const xml_token_t XML_lightposition = 867;
+const xml_token_t XML_lightposition2 = 868;
+const xml_token_t XML_limo = 869;
+const xml_token_t XML_line = 870;
+const xml_token_t XML_linestyle = 871;
+const xml_token_t XML_lock = 872;
+const xml_token_t XML_lockrotationcenter = 873;
+const xml_token_t XML_map = 874;
+const xml_token_t XML_master = 875;
+const xml_token_t XML_matrix = 876;
+const xml_token_t XML_maxLength = 877;
+const xml_token_t XML_metal = 878;
+const xml_token_t XML_method = 879;
+const xml_token_t XML_minusx = 880;
+const xml_token_t XML_minusy = 881;
+const xml_token_t XML_miterlimit = 882;
+const xml_token_t XML_movie = 883;
+const xml_token_t XML_name = 884;
+const xml_token_t XML_namespaceuri = 885;
+const xml_token_t XML_new = 886;
+const xml_token_t XML_obscured = 887;
+const xml_token_t XML_offset = 888;
+const xml_token_t XML_offset2 = 889;
+const xml_token_t XML_old = 890;
+const xml_token_t XML_ole = 891;
+const xml_token_t XML_oleicon = 892;
+const xml_token_t XML_oleid = 893;
+const xml_token_t XML_on = 894;
+const xml_token_t XML_oned = 895;
+const xml_token_t XML_onmouseover = 896;
+const xml_token_t XML_opacity = 897;
+const xml_token_t XML_opacity2 = 898;
+const xml_token_t XML_orientation = 899;
+const xml_token_t XML_orientationangle = 900;
+const xml_token_t XML_origin = 901;
+const xml_token_t XML_oval = 902;
+const xml_token_t XML_password = 903;
+const xml_token_t XML_path = 904;
+const xml_token_t XML_phonetictext = 905;
+const xml_token_t XML_plane = 906;
+const xml_token_t XML_points = 907;
+const xml_token_t XML_polar = 908;
+const xml_token_t XML_polyline = 909;
+const xml_token_t XML_position = 910;
+const xml_token_t XML_preferrelative = 911;
+const xml_token_t XML_print = 912;
+const xml_token_t XML_proxy = 913;
+const xml_token_t XML_r = 914;
+const xml_token_t XML_radiusrange = 915;
+const xml_token_t XML_rect = 916;
+const xml_token_t XML_regroupid = 917;
+const xml_token_t XML_regrouptable = 918;
+const xml_token_t XML_relativeposition = 919;
+const xml_token_t XML_render = 920;
+const xml_token_t XML_rotation = 921;
+const xml_token_t XML_rotationangle = 922;
+const xml_token_t XML_rotationcenter = 923;
+const xml_token_t XML_roundrect = 924;
+const xml_token_t XML_row = 925;
+const xml_token_t XML_ruleinitiator = 926;
+const xml_token_t XML_ruleproxy = 927;
+const xml_token_t XML_rules = 928;
+const xml_token_t XML_selection = 929;
+const xml_token_t XML_shadow = 930;
+const xml_token_t XML_shadowcolor = 931;
+const xml_token_t XML_shadowok = 932;
+const xml_token_t XML_shape = 933;
+const xml_token_t XML_shapedefaults = 934;
+const xml_token_t XML_shapelayout = 935;
+const xml_token_t XML_shapetype = 936;
+const xml_token_t XML_shininess = 937;
+const xml_token_t XML_singleclick = 938;
+const xml_token_t XML_size = 939;
+const xml_token_t XML_skew = 940;
+const xml_token_t XML_skewamt = 941;
+const xml_token_t XML_skewangle = 942;
+const xml_token_t XML_specularity = 943;
+const xml_token_t XML_spid = 944;
+const xml_token_t XML_spidmax = 945;
+const xml_token_t XML_spt = 946;
+const xml_token_t XML_src = 947;
+const xml_token_t XML_start = 948;
+const xml_token_t XML_startAngle = 949;
+const xml_token_t XML_startarrow = 950;
+const xml_token_t XML_startarrowlength = 951;
+const xml_token_t XML_startarrowwidth = 952;
+const xml_token_t XML_string = 953;
+const xml_token_t XML_stroke = 954;
+const xml_token_t XML_strokecolor = 955;
+const xml_token_t XML_stroked = 956;
+const xml_token_t XML_strokeok = 957;
+const xml_token_t XML_strokeweight = 958;
+const xml_token_t XML_style = 959;
+const xml_token_t XML_switch = 960;
+const xml_token_t XML_tablelimits = 961;
+const xml_token_t XML_tableproperties = 962;
+const xml_token_t XML_target = 963;
+const xml_token_t XML_targetscreensize = 964;
+const xml_token_t XML_text = 965;
+const xml_token_t XML_textborder = 966;
+const xml_token_t XML_textbox = 967;
+const xml_token_t XML_textboxrect = 968;
+const xml_token_t XML_textpath = 969;
+const xml_token_t XML_textpathok = 970;
+const xml_token_t XML_title = 971;
+const xml_token_t XML_to = 972;
+const xml_token_t XML_trim = 973;
+const xml_token_t XML_type = 974;
+const xml_token_t XML_url = 975;
+const xml_token_t XML_useExplicit = 976;
+const xml_token_t XML_userId = 977;
+const xml_token_t XML_userdrawn = 978;
+const xml_token_t XML_userhidden = 979;
+const xml_token_t XML_v = 980;
+const xml_token_t XML_verticies = 981;
+const xml_token_t XML_viewpoint = 982;
+const xml_token_t XML_viewpointorigin = 983;
+const xml_token_t XML_visible = 984;
+const xml_token_t XML_weight = 985;
+const xml_token_t XML_worksheetoptions = 986;
+const xml_token_t XML_wrapcoords = 987;
+const xml_token_t XML_xrange = 988;
+const xml_token_t XML_xscale = 989;
+const xml_token_t XML_yrange = 990;
diff --git a/src/liborcus/xls_xml_tokens.cpp b/src/liborcus/xls_xml_tokens.cpp
new file mode 100644
index 0000000..1ba9001
--- /dev/null
+++ b/src/liborcus/xls_xml_tokens.cpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xls_xml_tokens.hpp"
+
+namespace orcus {
+
+namespace {
+
+#include "xls_xml_tokens.inl"
+
+}
+
+tokens xls_xml_tokens = tokens(token_names, token_name_count);
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_tokens.hpp b/src/liborcus/xls_xml_tokens.hpp
new file mode 100644
index 0000000..0180db1
--- /dev/null
+++ b/src/liborcus/xls_xml_tokens.hpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLS_XML_TOKENS_HPP
+#define ORCUS_XLS_XML_TOKENS_HPP
+
+#include "orcus/tokens.hpp"
+
+namespace orcus {
+
+extern tokens xls_xml_tokens;
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xls_xml_tokens.inl b/src/liborcus/xls_xml_tokens.inl
new file mode 100644
index 0000000..73cd1fc
--- /dev/null
+++ b/src/liborcus/xls_xml_tokens.inl
@@ -0,0 +1,997 @@
+// This file has been auto-generated. Do not hand-edit this.
+
+const char* token_names[] = {
+ "??", // 0
+ "AcceptLabelsInFormulas", // 1
+ "Action", // 2
+ "ActiveChart", // 3
+ "ActiveCol", // 4
+ "ActiveColumn", // 5
+ "ActivePane", // 6
+ "ActiveRow", // 7
+ "ActiveRows", // 8
+ "ActiveSheet", // 9
+ "Aggregate", // 10
+ "AlertVersion", // 11
+ "Alignment", // 12
+ "AllItemName", // 13
+ "AllowDeleteCols", // 14
+ "AllowDeleteRows", // 15
+ "AllowFilter", // 16
+ "AllowFormatCells", // 17
+ "AllowInsertCols", // 18
+ "AllowInsertHyperlinks", // 19
+ "AllowInsertRows", // 20
+ "AllowPNG", // 21
+ "AllowSizeCols", // 22
+ "AllowSizeRows", // 23
+ "AllowSort", // 24
+ "AllowUsePivotTables", // 25
+ "AlternateMethod", // 26
+ "AppName", // 27
+ "Append", // 28
+ "ApplyAutomaticOutlineStyles", // 29
+ "Area", // 30
+ "ArrayRange", // 31
+ "Async", // 32
+ "Attribute", // 33
+ "AttributeType", // 34
+ "Authentication", // 35
+ "Author", // 36
+ "AutoFilter", // 37
+ "AutoFilterAnd", // 38
+ "AutoFilterColumn", // 39
+ "AutoFilterCondition", // 40
+ "AutoFilterOr", // 41
+ "AutoFitHeight", // 42
+ "AutoFitWidth", // 43
+ "AutoFormatAlignment", // 44
+ "AutoFormatBorder", // 45
+ "AutoFormatFont", // 46
+ "AutoFormatName", // 47
+ "AutoFormatNumber", // 48
+ "AutoFormatPattern", // 49
+ "AutoFormatWidth", // 50
+ "AutoRepublish", // 51
+ "AutoShowCount", // 52
+ "AutoShowField", // 53
+ "AutoShowRange", // 54
+ "AutoShowType", // 55
+ "AutoSortField", // 56
+ "AutoSortOrder", // 57
+ "B", // 58
+ "BackgroundQuery", // 59
+ "BaseField", // 60
+ "BaseItem", // 61
+ "Basic", // 62
+ "Behavior", // 63
+ "Binding", // 64
+ "BlackAndWhite", // 65
+ "BlankLineAfterItems", // 66
+ "BlockTotal", // 67
+ "Bold", // 68
+ "Boolean", // 69
+ "Border", // 70
+ "Borders", // 71
+ "Bottom", // 72
+ "BoundField", // 73
+ "Bytes", // 74
+ "CacheDetails", // 75
+ "CacheFile", // 76
+ "CacheIndex", // 77
+ "CachePosition", // 78
+ "CalculatedMember", // 79
+ "Calculation", // 80
+ "CantGetUniqueItems", // 81
+ "Caption", // 82
+ "CaptionAlignment", // 83
+ "CaseSensitive", // 84
+ "Category", // 85
+ "Cell", // 86
+ "CellRangeList", // 87
+ "CellsExpanded", // 88
+ "CellsExpandedSeqNum", // 89
+ "CellsNotExpanded", // 90
+ "CenterHorizontal", // 91
+ "CenterVertical", // 92
+ "Cf", // 93
+ "CharSet", // 94
+ "Characters", // 95
+ "CharactersWithSpaces", // 96
+ "ClientParameter", // 97
+ "ClientParameterBinding", // 98
+ "ClientParameterBindings", // 99
+ "ClientParameterValue", // 100
+ "Clipped", // 101
+ "CodeName", // 102
+ "Col1", // 103
+ "Col10", // 104
+ "Col11", // 105
+ "Col12", // 106
+ "Col13", // 107
+ "Col14", // 108
+ "Col15", // 109
+ "Col16", // 110
+ "Col17", // 111
+ "Col18", // 112
+ "Col19", // 113
+ "Col2", // 114
+ "Col20", // 115
+ "Col3", // 116
+ "Col4", // 117
+ "Col5", // 118
+ "Col6", // 119
+ "Col7", // 120
+ "Col8", // 121
+ "Col9", // 122
+ "ColBreak", // 123
+ "ColBreaks", // 124
+ "ColFirst", // 125
+ "ColLast", // 126
+ "Color", // 127
+ "Column", // 128
+ "ColumnInfo", // 129
+ "ColumnInputCell", // 130
+ "ColumnName", // 131
+ "ComboHide", // 132
+ "Comma", // 133
+ "CommandText", // 134
+ "CommandTextOrignal", // 135
+ "CommandType", // 136
+ "Comment", // 137
+ "CommentsLayout", // 138
+ "Company", // 139
+ "ComponentOptions", // 140
+ "Condition", // 141
+ "ConditionalFormatting", // 142
+ "Connection", // 143
+ "ConnectionInfo", // 144
+ "ConnectionString", // 145
+ "Consecutive", // 146
+ "ConsolidationReference", // 147
+ "Count", // 148
+ "CountOfSameItems", // 149
+ "CreateBackup", // 150
+ "Created", // 151
+ "Credential", // 152
+ "CredentialBinding", // 153
+ "CredentialValue", // 154
+ "Crn", // 155
+ "CubeField", // 156
+ "CubeSource", // 157
+ "CurrentPage", // 158
+ "Custom", // 159
+ "CustomDocumentProperties", // 160
+ "Data", // 161
+ "DataAxisEmpty", // 162
+ "DataField", // 163
+ "DataMember", // 164
+ "DataSource", // 165
+ "DataTable", // 166
+ "DataType", // 167
+ "DataValidation", // 168
+ "DataValueEditing", // 169
+ "Date1904", // 170
+ "Decimal", // 171
+ "DefaultColumnWidth", // 172
+ "DefaultItem", // 173
+ "DefaultRowHeight", // 174
+ "DefaultValue", // 175
+ "DefaultVersion", // 176
+ "DeletedTitle", // 177
+ "Delimiters", // 178
+ "Descending", // 179
+ "Description", // 180
+ "DetailFormat", // 181
+ "DetailMaxHeight", // 182
+ "DetailMaxWidth", // 183
+ "DetailRowHeight", // 184
+ "DetailSortOrder", // 185
+ "DetailWidth", // 186
+ "Dimension", // 187
+ "DisableDateRecognition", // 188
+ "DisableDrillDown", // 189
+ "DisableEdit", // 190
+ "DisableFieldDialog", // 191
+ "DisableRefresh", // 192
+ "DisableWizard", // 193
+ "DisplayDrawingObjects", // 194
+ "DisplayEmptyMembers", // 195
+ "DisplayErrorString", // 196
+ "DisplayFieldList", // 197
+ "DisplayFormulas", // 198
+ "DisplayIn", // 199
+ "DisplayInkNotes", // 200
+ "DisplayPageBreak", // 201
+ "DisplayRightToLeft", // 202
+ "DivID", // 203
+ "DoNotCalculateBeforeSave", // 204
+ "DoNotDisplayColHeaders", // 205
+ "DoNotDisplayGridlines", // 206
+ "DoNotDisplayHeadings", // 207
+ "DoNotDisplayOutline", // 208
+ "DoNotDisplayRowHeaders", // 209
+ "DoNotDisplayZeros", // 210
+ "DoNotJoinDelimiters", // 211
+ "DoNotPersist", // 212
+ "DoNotPersistSort", // 213
+ "DoNotPersstAF", // 214
+ "DoNotPromptForFile", // 215
+ "DoNotSaveLinkValues", // 216
+ "DocumentProperties", // 217
+ "DontShowInFieldList", // 218
+ "DownloadComponents", // 219
+ "DraftQuality", // 220
+ "DrawAspect", // 221
+ "DrilledLevel", // 222
+ "DrilledMember", // 223
+ "EditWebPage", // 224
+ "ElementType", // 225
+ "EmbedSaveSmartTags", // 226
+ "EnableMultiplePageItems", // 227
+ "EnableRedirections", // 228
+ "EnableSelection", // 229
+ "Encode", // 230
+ "EntirePage", // 231
+ "Entry", // 232
+ "Error", // 233
+ "ErrorHide", // 234
+ "ErrorMessage", // 235
+ "ErrorString", // 236
+ "ErrorStyle", // 237
+ "ErrorTitle", // 238
+ "ExcelName", // 239
+ "ExcelType", // 240
+ "ExcelWorkbook", // 241
+ "ExcelWorksheetType", // 242
+ "Expanded", // 243
+ "ExpandedColumnCount", // 244
+ "ExpandedRowCount", // 245
+ "ExternName", // 246
+ "ExtraLeftColumns", // 247
+ "ExtraRightColumns", // 248
+ "Face", // 249
+ "Family", // 250
+ "Field", // 251
+ "FieldLabelFormat", // 252
+ "FieldListBottom", // 253
+ "FieldListLeft", // 254
+ "FieldListRight", // 255
+ "FieldListTop", // 256
+ "FieldStart", // 257
+ "FieldType", // 258
+ "File", // 259
+ "FileName", // 260
+ "FillDown", // 261
+ "Filled", // 262
+ "FilterCaption", // 263
+ "FilterMember", // 264
+ "FilterOn", // 265
+ "FirstVisibleSheet", // 266
+ "FitHeight", // 267
+ "FitToPage", // 268
+ "FitWidth", // 269
+ "Font", // 270
+ "FontName", // 271
+ "Footer", // 272
+ "Format", // 273
+ "FormatSettings", // 274
+ "FormatType", // 275
+ "Formula", // 276
+ "FormulaIndex", // 277
+ "FormulaV10", // 278
+ "FreezePanes", // 279
+ "FrozenNoSplit", // 280
+ "FullColumns", // 281
+ "FullRows", // 282
+ "Function", // 283
+ "FunctionGroup", // 284
+ "FunctionGroupIndex", // 285
+ "FuturePersist", // 286
+ "FutureVer", // 287
+ "GrandTotalString", // 288
+ "GridlineColor", // 289
+ "GridlineColorIndex", // 290
+ "Gridlines", // 291
+ "GroupBy", // 292
+ "GroupDefinition", // 293
+ "GroupEnd", // 294
+ "GroupEndAuto", // 295
+ "GroupLevel", // 296
+ "GroupMember", // 297
+ "GroupNumber", // 298
+ "GroupStart", // 299
+ "GroupStartAuto", // 300
+ "GroupType", // 301
+ "GroupedWidth", // 302
+ "Guid", // 303
+ "HRef", // 304
+ "HRefScreenTip", // 305
+ "HTMLFormat", // 306
+ "HTMLTables", // 307
+ "HasNoAutoFormat", // 308
+ "HasNoRecords", // 309
+ "Header", // 310
+ "HeaderRange", // 311
+ "HeaderRow", // 312
+ "Height", // 313
+ "Hidden", // 314
+ "HideDetail", // 315
+ "HideDropDowns", // 316
+ "HideFormula", // 317
+ "HideHorizontalScrollBar", // 318
+ "HideInactiveListBorder", // 319
+ "HideOfficeLogo", // 320
+ "HidePivotTableFieldList", // 321
+ "HideTotalsAnnotation", // 322
+ "HideVerticalScrollBar", // 323
+ "HideWorkbookTabs", // 324
+ "Horizontal", // 325
+ "HorizontalResolution", // 326
+ "Href", // 327
+ "HtmlType", // 328
+ "HyperlinkBase", // 329
+ "I", // 330
+ "ID", // 331
+ "IMEMode", // 332
+ "Id", // 333
+ "IdWrapped", // 334
+ "If", // 335
+ "ImmediateItemsOnDrop", // 336
+ "Indent", // 337
+ "Index", // 338
+ "IndividualCellBorders", // 339
+ "InputHide", // 340
+ "InputMessage", // 341
+ "InputTitle", // 342
+ "InsertEntireRows", // 343
+ "InstanceShape", // 344
+ "Interior", // 345
+ "IntlMacro", // 346
+ "Invalid", // 347
+ "InvertedColumnMember", // 348
+ "InvertedRowMember", // 349
+ "IsGroupLevel", // 350
+ "IsMemberProperty", // 351
+ "IsNotFiltered", // 352
+ "Italic", // 353
+ "Item", // 354
+ "ItemType", // 355
+ "Iteration", // 356
+ "KeyboardShortcut", // 357
+ "Keywords", // 358
+ "Label", // 359
+ "LastAuthor", // 360
+ "LastPrinted", // 361
+ "LastSaved", // 362
+ "Layout", // 363
+ "LayoutForm", // 364
+ "LayoutPageBreak", // 365
+ "LayoutSubtotalLocation", // 366
+ "LeafColumnMember", // 367
+ "LeafRowMember", // 368
+ "Left", // 369
+ "LeftCell", // 370
+ "LeftColumnRightPane", // 371
+ "LeftColumnVisible", // 372
+ "LeftToRight", // 373
+ "LengthLevelUniqueName", // 374
+ "Level", // 375
+ "LineStyle", // 376
+ "Lines", // 377
+ "LoadMode", // 378
+ "LocalConnection", // 379
+ "Location", // 380
+ "LocationOfComponents", // 381
+ "Macro", // 382
+ "MainFile", // 383
+ "Maintain", // 384
+ "MajorVersion", // 385
+ "Manager", // 386
+ "Map", // 387
+ "MapChildItems", // 388
+ "MapID", // 389
+ "MapInfo", // 390
+ "Mapdata", // 391
+ "Margin", // 392
+ "Max", // 393
+ "MaxChange", // 394
+ "MaxHeight", // 395
+ "MaxIterations", // 396
+ "MaxWidth", // 397
+ "Measure", // 398
+ "Member", // 399
+ "MemberExpand", // 400
+ "MemberFormat", // 401
+ "MemberName", // 402
+ "MemberPropertiesOrder", // 403
+ "MemberProperty", // 404
+ "MemberPropertyParent", // 405
+ "MergeAcross", // 406
+ "MergeDown", // 407
+ "MergeLabels", // 408
+ "Min", // 409
+ "MinorVersion", // 410
+ "Missing", // 411
+ "MissingItemsLimit", // 412
+ "Moper", // 413
+ "MoveAfterReturn", // 414
+ "Name", // 415
+ "NamedCell", // 416
+ "NamedRange", // 417
+ "Names", // 418
+ "Namespace", // 419
+ "NewAsync", // 420
+ "NewItemsHidden", // 421
+ "NextId", // 422
+ "NextSheetNumber", // 423
+ "NoAutoFit", // 424
+ "NoAutoFormatWidth", // 425
+ "NoAutoPage", // 426
+ "NoAutoRecover", // 427
+ "NoAutofit", // 428
+ "NoColumnGrand", // 429
+ "NoDetailAutoFit", // 430
+ "NoDisplayNullString", // 431
+ "NoDragToColumn", // 432
+ "NoDragToData", // 433
+ "NoDragToHide", // 434
+ "NoDragToPage", // 435
+ "NoDragToRow", // 436
+ "NoInserts", // 437
+ "NoPreserveFormatting", // 438
+ "NoPrintRepeatItems", // 439
+ "NoPrinterInfo", // 440
+ "NoRefreshCache", // 441
+ "NoRowGrand", // 442
+ "NoSaveData", // 443
+ "NoSummaryColumnsRightDetail", // 444
+ "NoSummaryRowsBelowDetail", // 445
+ "NoTextToColumns", // 446
+ "NoTitles", // 447
+ "NoToggleDataHeader", // 448
+ "NoViewCalculatedMembers", // 449
+ "NonDefaultName", // 450
+ "NotInverted", // 451
+ "NotVisible", // 452
+ "NullString", // 453
+ "Number", // 454
+ "NumberFormat", // 455
+ "NumberOfCopies", // 456
+ "OLEObject", // 457
+ "OWCVersion", // 458
+ "ObjectID", // 459
+ "OfficeDocumentSettings", // 460
+ "OleLink", // 461
+ "Operator", // 462
+ "OptimizeCache", // 463
+ "Orientation", // 464
+ "Outline", // 465
+ "OverwriteCells", // 466
+ "PLCaption", // 467
+ "PLDataOrientation", // 468
+ "PLExport", // 469
+ "PLGroupType", // 470
+ "PLName", // 471
+ "PLPivotField", // 472
+ "PLPosition", // 473
+ "PLSubtotal", // 474
+ "PLTPivotItem", // 475
+ "PLTotal", // 476
+ "PTFormat", // 477
+ "PTFormula", // 478
+ "PTLineItem", // 479
+ "PTLineItems", // 480
+ "PTPivotData", // 481
+ "PTRule", // 482
+ "PTSource", // 483
+ "PageBreakZoom", // 484
+ "PageBreaks", // 485
+ "PageFieldOrder", // 486
+ "PageFieldStyle", // 487
+ "PageFieldWrapCount", // 488
+ "PageMargins", // 489
+ "PageSetup", // 490
+ "Pages", // 491
+ "Pane", // 492
+ "Panes", // 493
+ "PaperSizeIndex", // 494
+ "Paragraphs", // 495
+ "Parameter", // 496
+ "ParameterType", // 497
+ "ParameterValue", // 498
+ "Parent", // 499
+ "ParentField", // 500
+ "ParentIsOther", // 501
+ "ParentName", // 502
+ "ParentUniqueName", // 503
+ "ParseFormulaAsV10", // 504
+ "ParseRuleAsV10", // 505
+ "PasteFormula", // 506
+ "PasteRefersTo", // 507
+ "Path", // 508
+ "Pattern", // 509
+ "PatternColor", // 510
+ "PivotAxis", // 511
+ "PivotCache", // 512
+ "PivotField", // 513
+ "PivotItem", // 514
+ "PivotTable", // 515
+ "PivotView", // 516
+ "Position", // 517
+ "PrecisionAsDisplayed", // 518
+ "PresentationFormat", // 519
+ "Print", // 520
+ "PrintErrors", // 521
+ "PrintSetTitles", // 522
+ "ProgID", // 523
+ "PromptString", // 524
+ "ProtectContents", // 525
+ "ProtectObjects", // 526
+ "ProtectScenarios", // 527
+ "ProtectStructure", // 528
+ "ProtectWindows", // 529
+ "Protected", // 530
+ "Protection", // 531
+ "Proxy", // 532
+ "PublishObject", // 533
+ "PublishObjects", // 534
+ "Purpose", // 535
+ "QTSource", // 536
+ "Qualifier", // 537
+ "Query97", // 538
+ "QuerySource", // 539
+ "QueryTable", // 540
+ "QueryType", // 541
+ "Range", // 542
+ "RangeSelection", // 543
+ "ReadOnly", // 544
+ "ReadingOrder", // 545
+ "RefModeR1C1", // 546
+ "Reference", // 547
+ "RefersTo", // 548
+ "RefreshDate", // 549
+ "RefreshDateCopy", // 550
+ "RefreshInfo", // 551
+ "RefreshName", // 552
+ "RefreshOnChange", // 553
+ "RefreshOnFileOpen", // 554
+ "RefreshTimeSpan", // 555
+ "RefreshedInXl9", // 556
+ "Resource", // 557
+ "Revision", // 558
+ "Right", // 559
+ "RightToLeft", // 560
+ "RobustConnect", // 561
+ "RootElement", // 562
+ "Rotate", // 563
+ "Rotation", // 564
+ "Row", // 565
+ "RowBreak", // 566
+ "RowBreaks", // 567
+ "RowColHeadings", // 568
+ "RowInputCell", // 569
+ "RowLast", // 570
+ "RowNumbers", // 571
+ "Rule", // 572
+ "RuleType", // 573
+ "RuleV10", // 574
+ "S", // 575
+ "SOAPAction", // 576
+ "SQLType", // 577
+ "Scale", // 578
+ "Schema", // 579
+ "SchemaID", // 580
+ "SchemaRef", // 581
+ "Selected", // 582
+ "SelectedSheets", // 583
+ "Selection", // 584
+ "SelectionNamespaces", // 585
+ "SemiColon", // 586
+ "SeqNum", // 587
+ "Sequence", // 588
+ "ServerBased", // 589
+ "ServerSortOrder", // 590
+ "Set", // 591
+ "Shadow", // 592
+ "ShapeID", // 593
+ "SheetIndex", // 594
+ "SheetName", // 595
+ "ShowAllItems", // 596
+ "ShowAlways", // 597
+ "ShowCellBackgroundFromOLAP", // 598
+ "ShowImportExportValidationErrors", // 599
+ "ShowPageBreakZoom", // 600
+ "ShowPageMultipleItemLabel", // 601
+ "ShowTotals", // 602
+ "ShrinkToFit", // 603
+ "Size", // 604
+ "SmallGrid", // 605
+ "SmartTagType", // 606
+ "SmartTags", // 607
+ "SolveOrder", // 608
+ "Sort", // 609
+ "SortKey", // 610
+ "SortOrder", // 611
+ "Sorting", // 612
+ "Source", // 613
+ "SourceConnectionFile", // 614
+ "SourceConsolidation", // 615
+ "SourceDataFile", // 616
+ "SourceHierarchy", // 617
+ "SourceHierarchyLevel", // 618
+ "SourceName", // 619
+ "SourceType", // 620
+ "Space", // 621
+ "SpaceAbove", // 622
+ "SpaceBelow", // 623
+ "Span", // 624
+ "SplitHorizontal", // 625
+ "SplitVertical", // 626
+ "SpreadsheetAutoFit", // 627
+ "StandardWidth", // 628
+ "StartPageNumber", // 629
+ "StartRow", // 630
+ "StrikeThrough", // 631
+ "Style", // 632
+ "StyleID", // 633
+ "Styles", // 634
+ "Sub", // 635
+ "SubType", // 636
+ "Subject", // 637
+ "Subtotal", // 638
+ "SubtotalFormat", // 639
+ "SubtotalHiddenPageItems", // 640
+ "SubtotalName", // 641
+ "Sup", // 642
+ "SupBook", // 643
+ "Synchronous", // 644
+ "Tab", // 645
+ "TabColorIndex", // 646
+ "TabRatio", // 647
+ "Table", // 648
+ "TableStyle", // 649
+ "Tag", // 650
+ "Text", // 651
+ "TextQualifier", // 652
+ "TextWizardSettings", // 653
+ "ThousandSeparator", // 654
+ "Ticked", // 655
+ "Title", // 656
+ "Toolbar", // 657
+ "TooltipInfo", // 658
+ "Top", // 659
+ "TopCell", // 660
+ "TopRowBottomPane", // 661
+ "TopRowVisible", // 662
+ "TotalAlignment", // 663
+ "TotalAllMembers", // 664
+ "TotalCaptionAlignment", // 665
+ "TotalFormat", // 666
+ "TotalTime", // 667
+ "TotalWidth", // 668
+ "TransitionExpressionEvaluation", // 669
+ "TransitionFormulaEntry", // 670
+ "Type", // 671
+ "U", // 672
+ "URLString", // 673
+ "Uncalced", // 674
+ "Underline", // 675
+ "UniqueName", // 676
+ "Unsynced", // 677
+ "UseBlank", // 678
+ "UseLocalConnection", // 679
+ "UseSameSettings", // 680
+ "User", // 681
+ "VMLFrame", // 682
+ "VacatedStyle", // 683
+ "ValidPrinterInfo", // 684
+ "Value", // 685
+ "Value1", // 686
+ "Value2", // 687
+ "Version", // 688
+ "VersionLastEdit", // 689
+ "VersionLastRefresh", // 690
+ "VersionLastUpdate", // 691
+ "VersionRefreshableMin", // 692
+ "VersionUpdateableMin", // 693
+ "Vertical", // 694
+ "VerticalAlign", // 695
+ "VerticalResolution", // 696
+ "VerticalText", // 697
+ "ViewableRange", // 698
+ "Visible", // 699
+ "VisualTotals", // 700
+ "WantAdvise", // 701
+ "WantPict", // 702
+ "Watch", // 703
+ "Watches", // 704
+ "WebPostString", // 705
+ "Weight", // 706
+ "Width", // 707
+ "WindowHeight", // 708
+ "WindowHidden", // 709
+ "WindowIconic", // 710
+ "WindowTopX", // 711
+ "WindowTopY", // 712
+ "WindowWidth", // 713
+ "Windows", // 714
+ "Words", // 715
+ "Workbook", // 716
+ "WorkbookOptions", // 717
+ "Worksheet", // 718
+ "WorksheetOptions", // 719
+ "WorksheetSource", // 720
+ "WrapText", // 721
+ "XPath", // 722
+ "XSDType", // 723
+ "Xct", // 724
+ "ZeroHeight", // 725
+ "Zoom", // 726
+ "accentbar", // 727
+ "adj", // 728
+ "adjusthandles", // 729
+ "alignshape", // 730
+ "allowincell", // 731
+ "allowoverlap", // 732
+ "alt", // 733
+ "althref", // 734
+ "angle", // 735
+ "arc", // 736
+ "arcsize", // 737
+ "arrowok", // 738
+ "aspect", // 739
+ "aspectratio", // 740
+ "attribute", // 741
+ "autorotationcenter", // 742
+ "backdepth", // 743
+ "background", // 744
+ "bilevel", // 745
+ "blacklevel", // 746
+ "borderbottomcolor", // 747
+ "borderleftcolor", // 748
+ "borderrightcolor", // 749
+ "bordertopcolor", // 750
+ "brightness", // 751
+ "bullet", // 752
+ "button", // 753
+ "bwmode", // 754
+ "bwnormal", // 755
+ "bwpure", // 756
+ "callout", // 757
+ "caption", // 758
+ "chromakey", // 759
+ "class", // 760
+ "clip", // 761
+ "color", // 762
+ "color2", // 763
+ "colormenu", // 764
+ "colormode", // 765
+ "colormru", // 766
+ "colors", // 767
+ "complex", // 768
+ "connectangles", // 769
+ "connectloc", // 770
+ "connectlocs", // 771
+ "connectortype", // 772
+ "connecttype", // 773
+ "content", // 774
+ "control1", // 775
+ "control2", // 776
+ "coordorigin", // 777
+ "coordsize", // 778
+ "cropbottom", // 779
+ "cropleft", // 780
+ "cropping", // 781
+ "cropright", // 782
+ "croptop", // 783
+ "curve", // 784
+ "dashstyle", // 785
+ "data", // 786
+ "datatype", // 787
+ "detectmouseclick", // 788
+ "diffusity", // 789
+ "displaycustomheaders", // 790
+ "distance", // 791
+ "doubleclicknotify", // 792
+ "drop", // 793
+ "dropauto", // 794
+ "dt", // 795
+ "edge", // 796
+ "editas", // 797
+ "embosscolor", // 798
+ "end", // 799
+ "endAngle", // 800
+ "endarrow", // 801
+ "endarrowlength", // 802
+ "endarrowwidth", // 803
+ "endcap", // 804
+ "entry", // 805
+ "eqn", // 806
+ "ext", // 807
+ "extends", // 808
+ "extrusion", // 809
+ "extrusioncolor", // 810
+ "extrusionok", // 811
+ "f", // 812
+ "facet", // 813
+ "fill", // 814
+ "fillcolor", // 815
+ "filled", // 816
+ "fillok", // 817
+ "filltype", // 818
+ "fitpath", // 819
+ "fitshape", // 820
+ "focus", // 821
+ "focusposition", // 822
+ "focussize", // 823
+ "forcedash", // 824
+ "foredepth", // 825
+ "formulas", // 826
+ "from", // 827
+ "gain", // 828
+ "gamma", // 829
+ "gap", // 830
+ "gradientshapeok", // 831
+ "grayscale", // 832
+ "group", // 833
+ "grouping", // 834
+ "h", // 835
+ "handles", // 836
+ "hidden", // 837
+ "how", // 838
+ "hr", // 839
+ "hralign", // 840
+ "href", // 841
+ "hrheight", // 842
+ "hrnoshade", // 843
+ "hrpct", // 844
+ "hrstd", // 845
+ "hrwidth", // 846
+ "id", // 847
+ "idmap", // 848
+ "idref", // 849
+ "image", // 850
+ "imagealignshape", // 851
+ "imageaspect", // 852
+ "imagedata", // 853
+ "imagesize", // 854
+ "inset", // 855
+ "insetmode", // 856
+ "invx", // 857
+ "invy", // 858
+ "joinstyle", // 859
+ "length", // 860
+ "lengthspecified", // 861
+ "lightface", // 862
+ "lightharsh", // 863
+ "lightharsh2", // 864
+ "lightlevel", // 865
+ "lightlevel2", // 866
+ "lightposition", // 867
+ "lightposition2", // 868
+ "limo", // 869
+ "line", // 870
+ "linestyle", // 871
+ "lock", // 872
+ "lockrotationcenter", // 873
+ "map", // 874
+ "master", // 875
+ "matrix", // 876
+ "maxLength", // 877
+ "metal", // 878
+ "method", // 879
+ "minusx", // 880
+ "minusy", // 881
+ "miterlimit", // 882
+ "movie", // 883
+ "name", // 884
+ "namespaceuri", // 885
+ "new", // 886
+ "obscured", // 887
+ "offset", // 888
+ "offset2", // 889
+ "old", // 890
+ "ole", // 891
+ "oleicon", // 892
+ "oleid", // 893
+ "on", // 894
+ "oned", // 895
+ "onmouseover", // 896
+ "opacity", // 897
+ "opacity2", // 898
+ "orientation", // 899
+ "orientationangle", // 900
+ "origin", // 901
+ "oval", // 902
+ "password", // 903
+ "path", // 904
+ "phonetictext", // 905
+ "plane", // 906
+ "points", // 907
+ "polar", // 908
+ "polyline", // 909
+ "position", // 910
+ "preferrelative", // 911
+ "print", // 912
+ "proxy", // 913
+ "r", // 914
+ "radiusrange", // 915
+ "rect", // 916
+ "regroupid", // 917
+ "regrouptable", // 918
+ "relativeposition", // 919
+ "render", // 920
+ "rotation", // 921
+ "rotationangle", // 922
+ "rotationcenter", // 923
+ "roundrect", // 924
+ "row", // 925
+ "ruleinitiator", // 926
+ "ruleproxy", // 927
+ "rules", // 928
+ "selection", // 929
+ "shadow", // 930
+ "shadowcolor", // 931
+ "shadowok", // 932
+ "shape", // 933
+ "shapedefaults", // 934
+ "shapelayout", // 935
+ "shapetype", // 936
+ "shininess", // 937
+ "singleclick", // 938
+ "size", // 939
+ "skew", // 940
+ "skewamt", // 941
+ "skewangle", // 942
+ "specularity", // 943
+ "spid", // 944
+ "spidmax", // 945
+ "spt", // 946
+ "src", // 947
+ "start", // 948
+ "startAngle", // 949
+ "startarrow", // 950
+ "startarrowlength", // 951
+ "startarrowwidth", // 952
+ "string", // 953
+ "stroke", // 954
+ "strokecolor", // 955
+ "stroked", // 956
+ "strokeok", // 957
+ "strokeweight", // 958
+ "style", // 959
+ "switch", // 960
+ "tablelimits", // 961
+ "tableproperties", // 962
+ "target", // 963
+ "targetscreensize", // 964
+ "text", // 965
+ "textborder", // 966
+ "textbox", // 967
+ "textboxrect", // 968
+ "textpath", // 969
+ "textpathok", // 970
+ "title", // 971
+ "to", // 972
+ "trim", // 973
+ "type", // 974
+ "url", // 975
+ "useExplicit", // 976
+ "userId", // 977
+ "userdrawn", // 978
+ "userhidden", // 979
+ "v", // 980
+ "verticies", // 981
+ "viewpoint", // 982
+ "viewpointorigin", // 983
+ "visible", // 984
+ "weight", // 985
+ "worksheetoptions", // 986
+ "wrapcoords", // 987
+ "xrange", // 988
+ "xscale", // 989
+ "yrange" // 990
+};
+
+size_t token_name_count = 991;
diff --git a/src/liborcus/xlsx_autofilter_context.cpp b/src/liborcus/xlsx_autofilter_context.cpp
new file mode 100644
index 0000000..7a4d5ab
--- /dev/null
+++ b/src/liborcus/xlsx_autofilter_context.cpp
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_autofilter_context.hpp"
+#include "xml_context_global.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+
+#include "orcus/spreadsheet/import_interface.hpp"
+
+#include <iostream>
+
+using namespace std;
+
+namespace orcus {
+
+xlsx_autofilter_context::xlsx_autofilter_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_reference_resolver& resolver) :
+ xml_context_base(session_cxt, tokens),
+ m_resolver(resolver),
+ m_cur_col(-1) {}
+
+xlsx_autofilter_context::~xlsx_autofilter_context() {}
+
+xml_context_base* xlsx_autofilter_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_autofilter_context::end_child_context(
+ xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_autofilter_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns != NS_ooxml_xlsx)
+ return;
+
+ switch (name)
+ {
+ case XML_autoFilter:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ m_ref_range = for_each(
+ attrs.begin(), attrs.end(),
+ single_attr_getter(m_pool, NS_ooxml_xlsx, XML_ref)).get_value();
+ }
+ break;
+ case XML_filterColumn:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_autoFilter);
+ m_cur_col = for_each(
+ attrs.begin(), attrs.end(),
+ single_long_attr_getter(NS_ooxml_xlsx, XML_colId)).get_value();
+ }
+ break;
+ case XML_filters:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_filterColumn);
+ break;
+ case XML_filter:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_filters);
+ std::string_view val = for_each(
+ attrs.begin(), attrs.end(),
+ single_attr_getter(m_pool, NS_ooxml_xlsx, XML_val)).get_value();
+ if (!val.empty())
+ m_cur_match_values.push_back(val);
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+}
+
+bool xlsx_autofilter_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_filterColumn:
+ {
+ if (m_cur_col >= 0)
+ {
+ m_column_filters.insert(
+ column_filters_type::value_type(m_cur_col, m_cur_match_values));
+ }
+ m_cur_col = -1;
+ m_cur_match_values.clear();
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_autofilter_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+void xlsx_autofilter_context::push_to_model(spreadsheet::iface::import_auto_filter& af) const
+{
+ spreadsheet::src_range_t range = m_resolver.resolve_range(m_ref_range);
+ af.set_range(to_rc_range(range));
+
+ for (const auto& v : m_column_filters)
+ {
+ spreadsheet::col_t col = v.first;
+ const match_values_type& match_values = v.second;
+
+ af.set_column(col);
+ for (std::string_view value : match_values)
+ af.append_column_match_value(value);
+ af.commit_column();
+ }
+ af.commit();
+}
+
+void xlsx_autofilter_context::reset()
+{
+ m_pool.clear();
+ m_ref_range = std::string_view{};
+ m_cur_col = -1;
+ m_cur_match_values.clear();
+ m_column_filters.clear();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_autofilter_context.hpp b/src/liborcus/xlsx_autofilter_context.hpp
new file mode 100644
index 0000000..27f5e7b
--- /dev/null
+++ b/src/liborcus/xlsx_autofilter_context.hpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_AUTOFILTER_CONTEXT_HPP
+#define ORCUS_XLSX_AUTOFILTER_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "orcus/string_pool.hpp"
+#include "orcus/spreadsheet/types.hpp"
+
+#include <vector>
+#include <map>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_auto_filter;
+class import_reference_resolver;
+
+}}
+
+class xlsx_autofilter_context : public xml_context_base
+{
+public:
+ typedef std::vector<std::string_view> match_values_type;
+ typedef std::map<spreadsheet::col_t, match_values_type> column_filters_type;
+
+ xlsx_autofilter_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_reference_resolver& resolver);
+ virtual ~xlsx_autofilter_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ void push_to_model(spreadsheet::iface::import_auto_filter& af) const;
+
+ void reset();
+
+private:
+ spreadsheet::iface::import_reference_resolver& m_resolver;
+
+ string_pool m_pool;
+
+ std::string_view m_ref_range;
+ spreadsheet::col_t m_cur_col;
+ match_values_type m_cur_match_values;
+ column_filters_type m_column_filters;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_conditional_format_context.cpp b/src/liborcus/xlsx_conditional_format_context.cpp
new file mode 100644
index 0000000..e667d83
--- /dev/null
+++ b/src/liborcus/xlsx_conditional_format_context.cpp
@@ -0,0 +1,878 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_conditional_format_context.hpp"
+#include "xlsx_helper.hpp"
+#include "xlsx_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_namespace_types.hpp"
+
+#include "orcus/exception.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/measurement.hpp"
+
+#include <mdds/sorted_string_map.hpp>
+#include <mdds/global.hpp>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+enum xlsx_cond_format_type
+{
+ none = 0,
+ expression,
+ cellIs,
+ colorScale,
+ dataBar,
+ iconSet,
+ top10,
+ uniqueValues,
+ duplicateValues,
+ containsText,
+ notContainsText,
+ beginsWith,
+ endsWith,
+ containsBlanks,
+ notContainsBlanks,
+ containsErrors,
+ notContainsErrors,
+ timePeriod,
+ aboveAverage
+};
+
+enum xlsx_cond_format_operator
+{
+ operator_default = 0,
+ operator_beginsWith,
+ operator_between,
+ operator_containsText,
+ operator_endsWith,
+ operator_equal,
+ operator_greaterThan,
+ operator_greaterThanOrEqual,
+ operator_lessThan,
+ operator_lessThanOrEqual,
+ operator_notBetween,
+ operator_notContains,
+ operator_notEqual
+};
+
+enum xlsx_cond_format_date
+{
+ date_default = 0,
+ date_last7Days,
+ date_lastMonth,
+ date_lastWeek,
+ date_nextMonth,
+ date_thisMonth,
+ date_thisWeek,
+ date_today,
+ date_tomorrow,
+ date_yesterday
+};
+
+enum xlsx_cond_format_boolean
+{
+ boolean_default = 0,
+ boolean_true,
+ boolean_false
+};
+
+typedef mdds::sorted_string_map<xlsx_cond_format_type> cond_format_type_map;
+
+typedef mdds::sorted_string_map<xlsx_cond_format_boolean> cond_format_boolean_map;
+
+typedef mdds::sorted_string_map<xlsx_cond_format_operator> cond_format_operator_map;
+
+typedef mdds::sorted_string_map<xlsx_cond_format_date> cond_format_date_map;
+
+cond_format_type_map::entry cond_format_type_entries[] =
+{
+ { MDDS_ASCII("aboveAverage"), aboveAverage },
+ { MDDS_ASCII("beginsWith"), beginsWith },
+ { MDDS_ASCII("cellIs"), cellIs },
+ { MDDS_ASCII("colorScale"), colorScale },
+ { MDDS_ASCII("containsBlanks"), containsBlanks },
+ { MDDS_ASCII("containsErrors"), containsErrors },
+ { MDDS_ASCII("containsText"), containsText },
+ { MDDS_ASCII("dataBar"), dataBar },
+ { MDDS_ASCII("duplicateValues"), duplicateValues },
+ { MDDS_ASCII("endsWith"), endsWith },
+ { MDDS_ASCII("expression"), expression },
+ { MDDS_ASCII("iconSet"), iconSet },
+ { MDDS_ASCII("notContainsErrors"), notContainsErrors },
+ { MDDS_ASCII("notContainsText"), notContainsText },
+ { MDDS_ASCII("timePeriod"), timePeriod },
+ { MDDS_ASCII("top10"), top10 },
+ { MDDS_ASCII("uniqueValues"), uniqueValues }
+};
+
+cond_format_operator_map::entry cond_format_operator_entries[] =
+{
+ { MDDS_ASCII("beginsWith"), operator_beginsWith },
+ { MDDS_ASCII("between"), operator_between },
+ { MDDS_ASCII("containsText"), operator_containsText },
+ { MDDS_ASCII("endsWith"), operator_endsWith },
+ { MDDS_ASCII("equal"), operator_equal },
+ { MDDS_ASCII("greaterThan"), operator_greaterThan },
+ { MDDS_ASCII("greaterThanOrEqual"), operator_greaterThanOrEqual },
+ { MDDS_ASCII("lessThan"), operator_lessThan },
+ { MDDS_ASCII("lessThanOrEqual"), operator_lessThanOrEqual },
+ { MDDS_ASCII("notBetween"), operator_notBetween },
+ { MDDS_ASCII("notContains"), operator_notContains },
+ { MDDS_ASCII("notEqual"), operator_notEqual }
+};
+
+cond_format_date_map::entry cond_format_date_entries[] =
+{
+ { MDDS_ASCII("last7Days"), date_last7Days },
+ { MDDS_ASCII("lastMonth"), date_lastMonth },
+ { MDDS_ASCII("lastWeek"), date_lastWeek },
+ { MDDS_ASCII("nextMonth"), date_nextMonth },
+ { MDDS_ASCII("thisMonth"), date_thisMonth },
+ { MDDS_ASCII("thisWeek"), date_thisWeek },
+ { MDDS_ASCII("today"), date_today },
+ { MDDS_ASCII("tomorrow"), date_tomorrow },
+ { MDDS_ASCII("yesterday"), date_yesterday }
+};
+
+cond_format_boolean_map::entry cond_format_boolean_entries[] =
+{
+ { MDDS_ASCII("0"), boolean_false },
+ { MDDS_ASCII("1"), boolean_true },
+ { MDDS_ASCII("false"), boolean_true },
+ { MDDS_ASCII("true"), boolean_false }
+};
+
+bool parse_boolean_flag(const xml_token_attr_t& attr, bool default_value)
+{
+ static const cond_format_boolean_map boolean_map(cond_format_boolean_entries, sizeof(cond_format_boolean_entries)/sizeof(cond_format_boolean_entries[0]), boolean_default);
+ xlsx_cond_format_boolean val = boolean_map.find(attr.value.data(), attr.value.size());
+ switch (val)
+ {
+ case boolean_default:
+ return default_value;
+ case boolean_true:
+ return true;
+ case boolean_false:
+ return false;
+ }
+
+ return default_value;
+}
+
+struct cfRule_attr_parser
+{
+
+ cfRule_attr_parser(ss::iface::import_conditional_format& cond_format):
+ m_cond_format(cond_format),
+ m_type(none),
+ m_operator(operator_default),
+ m_date(date_default),
+ m_above_average(true),
+ m_equal_average(false),
+ m_percent(false),
+ m_bottom(false)
+ {
+ }
+
+ void operator()(const xml_token_attr_t& attr)
+ {
+ switch(attr.name)
+ {
+ case XML_type:
+ {
+ cond_format_type_map type_map(cond_format_type_entries, sizeof(cond_format_type_entries)/sizeof(cond_format_type_entries[0]), none);
+ m_type = type_map.find(attr.value.data(), attr.value.size());
+ }
+ break;
+ case XML_dxfId:
+ {
+ // TODO: actually we need to translate between dxf id and xf id
+ size_t dxf_id = to_long(attr.value);
+ m_cond_format.set_xf_id(dxf_id);
+ }
+ break;
+ case XML_aboveAverage:
+ {
+ m_above_average = parse_boolean_flag(attr, true);
+ }
+ break;
+ case XML_percent:
+ m_percent = parse_boolean_flag(attr, false);
+ break;
+ case XML_bottom:
+ m_bottom = parse_boolean_flag(attr, false);
+ break;
+ case XML_operator:
+ {
+ cond_format_operator_map operator_map(cond_format_operator_entries, sizeof(cond_format_operator_entries)/sizeof(cond_format_operator_entries[0]), operator_default);
+ m_operator = operator_map.find(attr.value.data(), attr.value.size());
+ }
+ break;
+ case XML_text:
+ // do we need to worry about the transient flag here?
+ m_text = attr.value;
+ break;
+ case XML_timePeriod:
+ {
+ cond_format_date_map date_map(cond_format_date_entries, sizeof(cond_format_date_entries)/sizeof(cond_format_date_entries[0]), date_default);
+ m_date = date_map.find(attr.value.data(), attr.value.size());
+ }
+ break;
+ case XML_rank:
+ // do we need to worry about the transient flag here?
+ m_rank = attr.value;
+ break;
+ case XML_stdDev:
+ // do we need to worry about the transient flag here?
+ m_std_dev = attr.value;
+ break;
+ case XML_equalAverage:
+ m_equal_average = parse_boolean_flag(attr, false);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void set_type()
+ {
+ switch (m_type)
+ {
+ case expression:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::expression);
+ break;
+ case cellIs:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::expression);
+ switch (m_operator)
+ {
+ case operator_beginsWith:
+ m_cond_format.set_operator(ss::condition_operator_t::begins_with);
+ break;
+ case operator_between:
+ m_cond_format.set_operator(ss::condition_operator_t::between);
+ break;
+ case operator_containsText:
+ m_cond_format.set_operator(ss::condition_operator_t::contains);
+ break;
+ case operator_endsWith:
+ m_cond_format.set_operator(ss::condition_operator_t::ends_with);
+ break;
+ case operator_equal:
+ m_cond_format.set_operator(ss::condition_operator_t::equal);
+ break;
+ case operator_greaterThan:
+ m_cond_format.set_operator(ss::condition_operator_t::greater);
+ break;
+ case operator_greaterThanOrEqual:
+ m_cond_format.set_operator(ss::condition_operator_t::greater_equal);
+ break;
+ case operator_lessThan:
+ m_cond_format.set_operator(ss::condition_operator_t::less);
+ break;
+ case operator_lessThanOrEqual:
+ m_cond_format.set_operator(ss::condition_operator_t::less_equal);
+ break;
+ case operator_notBetween:
+ m_cond_format.set_operator(ss::condition_operator_t::not_between);
+ break;
+ case operator_notContains:
+ m_cond_format.set_operator(ss::condition_operator_t::not_contains);
+ break;
+ case operator_notEqual:
+ m_cond_format.set_operator(ss::condition_operator_t::not_equal);
+ break;
+ default:
+ break;
+ }
+ break;
+ case colorScale:
+ m_cond_format.set_type(ss::conditional_format_t::colorscale);
+ break;
+ case dataBar:
+ m_cond_format.set_type(ss::conditional_format_t::databar);
+ break;
+ case iconSet:
+ m_cond_format.set_type(ss::conditional_format_t::iconset);
+ break;
+ case top10:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ if (m_bottom)
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::bottom_n);
+ }
+ else
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::top_n);
+ }
+ m_cond_format.set_formula(m_rank);
+ break;
+ case uniqueValues:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::unique);
+ break;
+ case duplicateValues:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::duplicate);
+ break;
+ case containsText:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::contains);
+ m_cond_format.set_formula(m_text);
+ break;
+ case notContainsText:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::not_contains);
+ m_cond_format.set_formula(m_text);
+ break;
+ case beginsWith:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::begins_with);
+ m_cond_format.set_formula(m_text);
+ break;
+ case endsWith:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::ends_with);
+ m_cond_format.set_formula(m_text);
+ break;
+ case containsBlanks:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::contains_blanks);
+ break;
+ case containsErrors:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::contains_error);
+ break;
+ case notContainsErrors:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ m_cond_format.set_operator(ss::condition_operator_t::contains_no_error);
+ break;
+ case timePeriod:
+ m_cond_format.set_type(ss::conditional_format_t::date);
+ switch (m_date)
+ {
+ case date_last7Days:
+ m_cond_format.set_date(ss::condition_date_t::last_7_days);
+ break;
+ case date_lastMonth:
+ m_cond_format.set_date(ss::condition_date_t::last_month);
+ break;
+ case date_lastWeek:
+ m_cond_format.set_date(ss::condition_date_t::last_week);
+ break;
+ case date_nextMonth:
+ m_cond_format.set_date(ss::condition_date_t::next_month);
+ break;
+ case date_thisMonth:
+ m_cond_format.set_date(ss::condition_date_t::this_month);
+ break;
+ case date_thisWeek:
+ m_cond_format.set_date(ss::condition_date_t::this_week);
+ break;
+ case date_today:
+ m_cond_format.set_date(ss::condition_date_t::today);
+ break;
+ case date_tomorrow:
+ m_cond_format.set_date(ss::condition_date_t::tomorrow);
+ break;
+ case date_yesterday:
+ m_cond_format.set_date(ss::condition_date_t::yesterday);
+ break;
+ default:
+ break;
+ }
+ break;
+ case aboveAverage:
+ m_cond_format.set_type(ss::conditional_format_t::condition);
+ if (!m_std_dev.empty())
+ {
+ // TODO: we need a way to mark that as std dev in the interfaces
+ m_cond_format.set_formula(m_std_dev);
+ }
+ if (m_above_average)
+ {
+ if (m_equal_average)
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::above_equal_average);
+ }
+ else
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::above_average);
+ }
+ }
+ else
+ {
+ if (m_equal_average)
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::below_equal_average);
+ }
+ else
+ {
+ m_cond_format.set_operator(ss::condition_operator_t::below_average);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+private:
+ ss::iface::import_conditional_format& m_cond_format;
+ xlsx_cond_format_type m_type;
+ xlsx_cond_format_operator m_operator;
+ xlsx_cond_format_date m_date;
+ bool m_above_average;
+ bool m_equal_average;
+ bool m_percent;
+ bool m_bottom;
+ std::string_view m_text;
+ std::string_view m_std_dev;
+ std::string_view m_rank;
+};
+
+struct conditional_formatting_attr_parser
+{
+ conditional_formatting_attr_parser(ss::iface::import_conditional_format* cond_format):
+ m_cond_format(cond_format)
+ {
+ }
+
+ void operator()(const xml_token_attr_t& attr)
+ {
+ switch (attr.name)
+ {
+ case XML_sqref:
+ m_cond_format->set_range(attr.value);
+ break;
+ }
+ }
+
+private:
+ ss::iface::import_conditional_format* m_cond_format;
+};
+
+enum xlsx_cond_format_cfvo_type
+{
+ cfvo_default = 0,
+ cfvo_num,
+ cfvo_percent,
+ cfvo_max,
+ cfvo_min,
+ cfvo_formula,
+ cfvo_percentile
+};
+
+typedef mdds::sorted_string_map<xlsx_cond_format_cfvo_type> cond_format_cfvo_type_map;
+
+cond_format_cfvo_type_map::entry cond_format_cfvo_entries[] =
+{
+ { MDDS_ASCII("num"), cfvo_num },
+ { MDDS_ASCII("percent"), cfvo_percent },
+ { MDDS_ASCII("max"), cfvo_max },
+ { MDDS_ASCII("min"), cfvo_min },
+ { MDDS_ASCII("formula"), cfvo_formula },
+ { MDDS_ASCII("percentile"), cfvo_percentile },
+};
+
+}
+
+struct cfvo_values
+{
+ cfvo_values():
+ m_include_equal(true),
+ m_type(cfvo_default)
+ {
+ }
+
+ bool m_include_equal;
+ xlsx_cond_format_cfvo_type m_type;
+ std::string_view m_value;
+};
+
+namespace {
+
+struct cfvo_attr_parser
+{
+ cfvo_attr_parser(string_pool& pool):
+ m_string_pool(pool)
+ {
+ }
+
+ void operator()(const xml_token_attr_t& attr)
+ {
+ switch (attr.name)
+ {
+ case XML_gte:
+ m_values.m_include_equal = parse_boolean_flag(attr, true);
+ break;
+ case XML_type:
+ {
+ cond_format_cfvo_type_map cfvo_type_map(cond_format_cfvo_entries, sizeof(cond_format_cfvo_entries)/sizeof(cond_format_cfvo_entries[0]), cfvo_default);
+ m_values.m_type = cfvo_type_map.find(attr.value.data(), attr.value.size());
+ }
+ break;
+ case XML_val:
+ if (attr.transient)
+ {
+ m_values.m_value = m_string_pool.intern(attr.value).first;
+ }
+ else
+ {
+ m_values.m_value = attr.value;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ cfvo_values get_values()
+ {
+ return m_values;
+ }
+
+private:
+ cfvo_values m_values;
+ string_pool& m_string_pool;
+};
+
+struct data_bar_attr_parser
+{
+ data_bar_attr_parser():
+ m_show_value(true),
+ m_min_length(10),
+ m_max_length(90)
+ {
+ }
+
+ void operator()(const xml_token_attr_t& attr)
+ {
+ switch (attr.name)
+ {
+ case XML_showValue:
+ m_show_value = parse_boolean_flag(attr, true);
+ break;
+ case XML_maxLength:
+ m_max_length = to_long(attr.value);
+ break;
+ case XML_minLength:
+ m_min_length = to_long(attr.value);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void import_data(ss::iface::import_conditional_format& cond_format)
+ {
+ cond_format.set_show_value(m_show_value);
+ cond_format.set_min_databar_length(m_min_length);
+ cond_format.set_max_databar_length(m_max_length);
+ }
+
+private:
+ bool m_show_value;
+ size_t m_min_length;
+ size_t m_max_length;
+};
+
+struct icon_set_attr_parser
+{
+ icon_set_attr_parser():
+ m_reverse(false),
+ m_percent(true),
+ m_show_value(true),
+ icon_name("3Arrows")
+ {
+ }
+
+ void operator()(const xml_token_attr_t& attr)
+ {
+ switch (attr.name)
+ {
+ case XML_iconSet:
+ icon_name = attr.value;
+ break;
+ case XML_percent:
+ m_percent = parse_boolean_flag(attr, true);
+ break;
+ case XML_reverse:
+ m_reverse = parse_boolean_flag(attr, false);
+ break;
+ case XML_showValue:
+ m_show_value = parse_boolean_flag(attr, true);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void import_data(ss::iface::import_conditional_format& cond_format)
+ {
+ cond_format.set_show_value(m_show_value);
+ cond_format.set_iconset_reverse(m_reverse);
+ cond_format.set_icon_name(icon_name);
+ }
+
+private:
+ bool m_reverse;
+ bool m_percent;
+ bool m_show_value;
+ std::string_view icon_name;
+};
+
+}
+
+xlsx_conditional_format_context::xlsx_conditional_format_context(
+ session_context& session_cxt, const tokens& tokens,
+ ss::iface::import_conditional_format* import_cond_format):
+ xml_context_base(session_cxt, tokens),
+ m_cond_format(import_cond_format)
+{
+}
+
+xlsx_conditional_format_context::~xlsx_conditional_format_context()
+{
+}
+
+xml_context_base* xlsx_conditional_format_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_conditional_format_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_conditional_format_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ switch (name)
+ {
+ case XML_conditionalFormatting:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ if (m_cond_format)
+ std::for_each(attrs.begin(), attrs.end(), conditional_formatting_attr_parser(m_cond_format));
+ break;
+ }
+ case XML_cfRule:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_conditionalFormatting);
+ if (m_cond_format)
+ {
+ cfRule_attr_parser parser = std::for_each(attrs.begin(), attrs.end(), cfRule_attr_parser(*m_cond_format));
+ parser.set_type();
+ }
+ break;
+ }
+ case XML_cfvo:
+ {
+ cfvo_attr_parser parser = std::for_each(attrs.begin(), attrs.end(), cfvo_attr_parser(m_pool));
+ m_cfvo_values.push_back(parser.get_values());
+ break;
+ }
+ case XML_dataBar:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cfRule);
+ data_bar_attr_parser parser = std::for_each(attrs.begin(), attrs.end(), data_bar_attr_parser());
+ if (m_cond_format)
+ parser.import_data(*m_cond_format);
+ break;
+ }
+ case XML_iconSet:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cfRule);
+ icon_set_attr_parser parser = std::for_each(attrs.begin(), attrs.end(), icon_set_attr_parser());
+ if (m_cond_format)
+ parser.import_data(*m_cond_format);
+ break;
+ }
+ case XML_color:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ {
+ argb_color color;
+ if (to_rgb(attr.value, color.alpha, color.red, color.green, color.blue))
+ m_colors.push_back(color);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ break;
+ }
+ case XML_formula:
+ break;
+ case XML_colorScale:
+ break;
+ default:
+ warn_unhandled();
+ }
+}
+
+namespace {
+
+void import_cfvo(const cfvo_values& values, ss::iface::import_conditional_format& cond_format)
+{
+ if (!values.m_value.empty())
+ cond_format.set_formula(values.m_value);
+
+ switch (values.m_type)
+ {
+ case cfvo_num:
+ cond_format.set_condition_type(ss::condition_type_t::value);
+ break;
+ case cfvo_percent:
+ cond_format.set_condition_type(ss::condition_type_t::percent);
+ break;
+ case cfvo_max:
+ cond_format.set_condition_type(ss::condition_type_t::max);
+ break;
+ case cfvo_min:
+ cond_format.set_condition_type(ss::condition_type_t::min);
+ break;
+ case cfvo_formula:
+ cond_format.set_condition_type(ss::condition_type_t::formula);
+ break;
+ case cfvo_percentile:
+ cond_format.set_condition_type(ss::condition_type_t::percentile);
+ break;
+ default:;
+ }
+}
+
+}
+
+bool xlsx_conditional_format_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ switch (name)
+ {
+ case XML_conditionalFormatting:
+ {
+ if (m_cond_format)
+ m_cond_format->commit_format();
+ break;
+ }
+ case XML_cfRule:
+ {
+ if (m_cond_format)
+ m_cond_format->commit_entry();
+ m_cfvo_values.clear();
+ m_colors.clear();
+ break;
+ }
+ case XML_cfvo:
+ break;
+ case XML_color:
+ break;
+ case XML_formula:
+ {
+ if (m_cond_format)
+ {
+ m_cond_format->set_formula(m_cur_str);
+ m_cond_format->commit_condition();
+ }
+ break;
+ }
+ case XML_dataBar:
+ {
+ if (m_colors.size() != 1)
+ throw general_error("invalid dataBar record");
+
+ if (m_cfvo_values.size() != 2)
+ throw general_error("invalid dataBar record");
+
+ if (m_cond_format)
+ {
+ argb_color& color = m_colors[0];
+ m_cond_format->set_databar_color_positive(color.alpha, color.red,
+ color.green, color.blue);
+ m_cond_format->set_databar_color_negative(color.alpha, color.red,
+ color.green, color.blue);
+
+ for (const auto& cfvo : m_cfvo_values)
+ {
+ import_cfvo(cfvo, *m_cond_format);
+ m_cond_format->commit_condition();
+ }
+ }
+ break;
+ }
+ case XML_iconSet:
+ {
+ if (m_cfvo_values.size() < 2)
+ throw general_error("invalid iconSet record");
+
+ if (m_cond_format)
+ {
+ for (const auto& cfvo : m_cfvo_values)
+ {
+ import_cfvo(cfvo, *m_cond_format);
+ m_cond_format->commit_condition();
+ }
+ }
+ break;
+ }
+ case XML_colorScale:
+ {
+ if (m_cfvo_values.size() < 2)
+ throw general_error("invalid colorScale record");
+
+ if (m_cfvo_values.size() != m_colors.size())
+ throw general_error("invalid colorScale record");
+
+ if (m_cond_format)
+ {
+ std::vector<argb_color>::const_iterator itrColor = m_colors.begin();
+ for (std::vector<cfvo_values>::const_iterator itr = m_cfvo_values.begin(); itr != m_cfvo_values.end(); ++itr, ++itrColor)
+ {
+ import_cfvo(*itr, *m_cond_format);
+ m_cond_format->set_color(itrColor->alpha, itrColor->red,
+ itrColor->green, itrColor->blue);
+ m_cond_format->commit_condition();
+ }
+ }
+ break;
+ }
+ }
+
+ m_cur_str = std::string_view{};
+ return pop_stack(ns, name);
+}
+
+void xlsx_conditional_format_context::characters(std::string_view str, bool transient)
+{
+ m_cur_str = str;
+ if (transient)
+ m_cur_str = m_pool.intern(m_cur_str).first;
+}
+
+void xlsx_conditional_format_context::reset()
+{
+ m_pool.clear();
+ m_cur_str = std::string_view{};
+ m_cfvo_values.clear();
+ m_colors.clear();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_conditional_format_context.hpp b/src/liborcus/xlsx_conditional_format_context.hpp
new file mode 100644
index 0000000..f03d53d
--- /dev/null
+++ b/src/liborcus/xlsx_conditional_format_context.hpp
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_CONDITIONAL_FORMAT_CONTEXT_HPP
+#define ORCUS_XLSX_CONDITIONAL_FORMAT_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "ooxml_types.hpp"
+#include "xlsx_types.hpp"
+
+#include "orcus/spreadsheet/types.hpp"
+#include "orcus/string_pool.hpp"
+
+namespace orcus {
+
+struct session_context;
+
+namespace spreadsheet { namespace iface {
+ class import_conditional_format;
+} }
+
+struct cfvo_values;
+
+struct argb_color
+{
+ spreadsheet::color_elem_t alpha;
+ spreadsheet::color_elem_t red;
+ spreadsheet::color_elem_t green;
+ spreadsheet::color_elem_t blue;
+};
+
+class xlsx_conditional_format_context : public xml_context_base
+{
+public:
+
+ xlsx_conditional_format_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_conditional_format* import_cond_format);
+ virtual ~xlsx_conditional_format_context() override;
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs) override;
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+ virtual void characters(std::string_view str, bool transient) override;
+
+ void reset();
+
+private:
+ spreadsheet::iface::import_conditional_format* m_cond_format;
+
+ string_pool m_pool;
+ std::string_view m_cur_str;
+
+ std::vector<cfvo_values> m_cfvo_values;
+ std::vector<argb_color> m_colors;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_drawing_context.cpp b/src/liborcus/xlsx_drawing_context.cpp
new file mode 100644
index 0000000..606cd62
--- /dev/null
+++ b/src/liborcus/xlsx_drawing_context.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_drawing_context.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_global.hpp"
+
+#include "orcus/measurement.hpp"
+
+#include <iostream>
+
+using namespace std;
+
+namespace orcus {
+
+xlsx_drawing_context::xlsx_drawing_context(session_context& cxt, const tokens& tkns) :
+ xml_context_base(cxt, tkns),
+ m_col(-1), m_row(-1), m_col_offset(-1), m_row_offset(-1)
+{
+ init_ooxml_context(*this);
+}
+
+xlsx_drawing_context::~xlsx_drawing_context() {}
+
+xml_context_base* xlsx_drawing_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_drawing_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_drawing_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& /*attrs*/)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_ooxml_xdr)
+ {
+ switch (name)
+ {
+ case XML_oneCellAnchor:
+ case XML_twoCellAnchor:
+ {
+ xml_element_expected(parent, NS_ooxml_xdr, XML_wsDr);
+ reset();
+ break;
+ }
+ case XML_from:
+ case XML_sp:
+ case XML_clientData:
+ {
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xdr, XML_absoluteAnchor },
+ { NS_ooxml_xdr, XML_grpSp },
+ { NS_ooxml_xdr, XML_oneCellAnchor },
+ { NS_ooxml_xdr, XML_twoCellAnchor },
+ };
+ xml_element_expected(parent, expected);
+ break;
+ }
+ case XML_to:
+ {
+ xml_element_expected(parent, NS_ooxml_xdr, XML_twoCellAnchor);
+ break;
+ }
+ case XML_col:
+ case XML_colOff:
+ case XML_row:
+ case XML_rowOff:
+ {
+ xml_elem_stack_t expected;
+ expected.emplace_back(NS_ooxml_xdr, XML_from);
+ expected.emplace_back(NS_ooxml_xdr, XML_to);
+ xml_element_expected(parent, expected);
+ break;
+ }
+ case XML_nvSpPr:
+ case XML_style:
+ case XML_txBody:
+ {
+ const xml_elem_stack_t expected = {
+ { NS_ooxml_xdr, XML_cxnSp },
+ { NS_ooxml_xdr, XML_sp },
+ };
+ xml_element_expected(parent, expected);
+ break;
+ }
+ case XML_spPr:
+ {
+ const xml_elem_stack_t expected = {
+ { NS_ooxml_xdr, XML_cxnSp },
+ { NS_ooxml_xdr, XML_sp },
+ { NS_ooxml_xdr, XML_pic },
+ };
+ xml_element_expected(parent, expected);
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else if (ns == NS_ooxml_a)
+ {
+ warn_unhandled();
+ }
+ else
+ warn_unhandled();
+}
+
+bool xlsx_drawing_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xdr)
+ {
+ switch (name)
+ {
+ case XML_twoCellAnchor:
+ case XML_oneCellAnchor:
+ if (get_config().debug)
+ cout << "col: " << m_col << "; row: " << m_row << "; col offset: " << m_col_offset << "; row offset: " << m_row_offset << endl;
+ break;
+ default:
+ ;
+ }
+ }
+ else if (ns == NS_ooxml_a)
+ {
+
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_drawing_context::characters(std::string_view str, bool /*transient*/)
+{
+ xml_token_pair_t elem = get_current_element();
+ if (elem.first == NS_ooxml_xdr)
+ {
+ switch (elem.second)
+ {
+ case XML_col:
+ m_col = to_long(str);
+ break;
+ case XML_row:
+ m_row = to_long(str);
+ break;
+ case XML_colOff:
+ m_col_offset = to_long(str);
+ break;
+ case XML_rowOff:
+ m_row_offset = to_long(str);
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+void xlsx_drawing_context::reset()
+{
+ m_col = -1;
+ m_row = -1;
+ m_col_offset = -1;
+ m_row_offset = -1;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_drawing_context.hpp b/src/liborcus/xlsx_drawing_context.hpp
new file mode 100644
index 0000000..5089326
--- /dev/null
+++ b/src/liborcus/xlsx_drawing_context.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XLSX_DRAWING_CONTEXT_HPP
+#define INCLUDED_ORCUS_XLSX_DRAWING_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+
+namespace orcus {
+
+struct session_context;
+class tokens;
+
+class xlsx_drawing_context : public xml_context_base
+{
+ long m_col;
+ long m_row;
+ long m_col_offset;
+ long m_row_offset;
+
+public:
+ xlsx_drawing_context(session_context& cxt, const tokens& tkns);
+
+ virtual ~xlsx_drawing_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+
+ virtual void characters(std::string_view str, bool transient);
+
+private:
+ void reset();
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_handler.cpp b/src/liborcus/xlsx_handler.cpp
new file mode 100644
index 0000000..e013bde
--- /dev/null
+++ b/src/liborcus/xlsx_handler.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_handler.hpp"
+#include "xlsx_sheet_context.hpp"
+#include "xlsx_table_context.hpp"
+#include "xlsx_pivot_context.hpp"
+#include "xlsx_drawing_context.hpp"
+
+#include <iostream>
+
+using namespace std;
+
+namespace orcus {
+
+xlsx_sheet_xml_handler::xlsx_sheet_xml_handler(
+ session_context& session_cxt, const tokens& t,
+ spreadsheet::sheet_t sheet_id,
+ spreadsheet::iface::import_reference_resolver& resolver,
+ spreadsheet::iface::import_sheet& sheet) :
+ xml_stream_handler(session_cxt, t, std::make_unique<xlsx_sheet_context>(session_cxt, t, sheet_id, resolver, sheet))
+{
+}
+
+xlsx_sheet_xml_handler::~xlsx_sheet_xml_handler()
+{
+}
+
+void xlsx_sheet_xml_handler::pop_rel_extras(opc_rel_extras_t& other)
+{
+ xlsx_sheet_context& cxt = static_cast<xlsx_sheet_context&>(get_root_context());
+ cxt.pop_rel_extras(other);
+}
+
+xlsx_table_xml_handler::xlsx_table_xml_handler(
+ session_context& session_cxt, const tokens& t,
+ spreadsheet::iface::import_table& table,
+ spreadsheet::iface::import_reference_resolver& resolver) :
+ xml_stream_handler(session_cxt, t, std::make_unique<xlsx_table_context>(session_cxt, t, table, resolver))
+{
+}
+
+xlsx_pivot_cache_def_xml_handler::xlsx_pivot_cache_def_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::iface::import_pivot_cache_definition& pcache,
+ spreadsheet::pivot_cache_id_t pcache_id) :
+ xml_stream_handler(cxt, t, std::make_unique<xlsx_pivot_cache_def_context>(cxt, t, pcache, pcache_id)) {}
+
+opc_rel_extras_t xlsx_pivot_cache_def_xml_handler::pop_rel_extras()
+{
+ xlsx_pivot_cache_def_context& cxt =
+ static_cast<xlsx_pivot_cache_def_context&>(get_root_context());
+
+ return cxt.pop_rel_extras();
+}
+
+xlsx_pivot_cache_rec_xml_handler::xlsx_pivot_cache_rec_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::iface::import_pivot_cache_records& pc_records) :
+ xml_stream_handler(cxt, t, std::make_unique<xlsx_pivot_cache_rec_context>(cxt, t, pc_records)) {}
+
+xlsx_pivot_table_xml_handler::xlsx_pivot_table_xml_handler(
+ session_context& cxt, const tokens& t) :
+ xml_stream_handler(cxt, t, std::make_unique<xlsx_pivot_table_context>(cxt, t)) {}
+
+xlsx_drawing_xml_handler::xlsx_drawing_xml_handler(
+ session_context& cxt, const tokens& t) :
+ xml_stream_handler(cxt, t, std::make_unique<xlsx_drawing_context>(cxt, t)) {}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_handler.hpp b/src/liborcus/xlsx_handler.hpp
new file mode 100644
index 0000000..81676c5
--- /dev/null
+++ b/src/liborcus/xlsx_handler.hpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XLSX_HANDLER_HPP
+#define INCLUDED_ORCUS_XLSX_HANDLER_HPP
+
+#include "xml_stream_handler.hpp"
+#include "xml_context_base.hpp"
+
+#include "orcus/spreadsheet/types.hpp"
+
+#include <string>
+#include <vector>
+
+namespace orcus {
+
+struct session_context;
+struct opc_rel_extras_t;
+
+namespace spreadsheet { namespace iface {
+
+class import_sheet;
+class import_table;
+class import_reference_resolver;
+class import_pivot_cache_definition;
+class import_pivot_cache_records;
+
+}}
+
+class xlsx_sheet_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_sheet_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::sheet_t sheet_id,
+ spreadsheet::iface::import_reference_resolver& resolver,
+ spreadsheet::iface::import_sheet& sheet);
+
+ virtual ~xlsx_sheet_xml_handler();
+
+ void pop_rel_extras(opc_rel_extras_t& other);
+};
+
+class xlsx_table_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_table_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::iface::import_table& table,
+ spreadsheet::iface::import_reference_resolver& resolver);
+};
+
+class xlsx_pivot_cache_def_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_pivot_cache_def_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::iface::import_pivot_cache_definition& pcache,
+ spreadsheet::pivot_cache_id_t pcache_id);
+
+ opc_rel_extras_t pop_rel_extras();
+};
+
+class xlsx_pivot_cache_rec_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_pivot_cache_rec_xml_handler(
+ session_context& cxt, const tokens& t,
+ spreadsheet::iface::import_pivot_cache_records& pc_records);
+};
+
+class xlsx_pivot_table_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_pivot_table_xml_handler(session_context& cxt, const tokens& t);
+};
+
+class xlsx_drawing_xml_handler : public xml_stream_handler
+{
+public:
+ xlsx_drawing_xml_handler(session_context& cxt, const tokens& t);
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_helper.cpp b/src/liborcus/xlsx_helper.cpp
new file mode 100644
index 0000000..9559d2b
--- /dev/null
+++ b/src/liborcus/xlsx_helper.cpp
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_helper.hpp"
+
+namespace orcus {
+
+bool to_rgb(
+ std::string_view ps, spreadsheet::color_elem_t& alpha,
+ spreadsheet::color_elem_t& red, spreadsheet::color_elem_t& green, spreadsheet::color_elem_t& blue)
+{
+ // RGB string is a 8-character string representing 32-bit hexadecimal
+ // number e.g. 'FF004A12' (alpha - red - green - blue)
+ size_t n = ps.size();
+ if (n != 8)
+ return false;
+
+ unsigned long v = strtoul(ps.data(), nullptr, 16);
+ blue = (0x000000FF & v);
+ green = (0x000000FF & (v >> 8));
+ red = (0x000000FF & (v >> 16));
+ alpha = (0x000000FF & (v >> 24));
+
+ return true;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_helper.hpp b/src/liborcus/xlsx_helper.hpp
new file mode 100644
index 0000000..1643db1
--- /dev/null
+++ b/src/liborcus/xlsx_helper.hpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/spreadsheet/types.hpp>
+
+namespace orcus {
+
+bool to_rgb(std::string_view ps, spreadsheet::color_elem_t& alpha,
+ spreadsheet::color_elem_t& red, spreadsheet::color_elem_t& gree,
+ spreadsheet::color_elem_t& blue);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_pivot_context.cpp b/src/liborcus/xlsx_pivot_context.cpp
new file mode 100644
index 0000000..026914d
--- /dev/null
+++ b/src/liborcus/xlsx_pivot_context.cpp
@@ -0,0 +1,1734 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_pivot_context.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "xml_context_global.hpp"
+#include "session_context.hpp"
+#include "xlsx_types.hpp"
+
+#include "orcus/measurement.hpp"
+#include "orcus/spreadsheet/import_interface_pivot.hpp"
+
+#include <iostream>
+#include <optional>
+#include <mdds/sorted_string_map.hpp>
+
+using std::cout;
+using std::endl;
+
+namespace orcus {
+
+namespace {
+
+namespace pc_source {
+
+using map_type = mdds::sorted_string_map<xlsx_pivot_cache_def_context::source_type, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "consolidation", xlsx_pivot_cache_def_context::source_type::consolidation },
+ { "external", xlsx_pivot_cache_def_context::source_type::external },
+ { "scenario", xlsx_pivot_cache_def_context::source_type::scenario },
+ { "worksheet", xlsx_pivot_cache_def_context::source_type::worksheet },
+};
+
+const map_type& get()
+{
+ static const map_type map(
+ entries, std::size(entries),
+ xlsx_pivot_cache_def_context::source_type::unknown);
+
+ return map;
+}
+
+} // namespace pc_source
+
+}
+
+xlsx_pivot_cache_def_context::xlsx_pivot_cache_def_context(
+ session_context& cxt, const tokens& tokens,
+ spreadsheet::iface::import_pivot_cache_definition& pcache,
+ spreadsheet::pivot_cache_id_t pcache_id) :
+ xml_context_base(cxt, tokens), m_pcache(pcache), m_pcache_id(pcache_id) {}
+
+xml_context_base* xlsx_pivot_cache_def_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_pivot_cache_def_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns != NS_ooxml_xlsx)
+ return;
+
+ switch (name)
+ {
+ case XML_pivotCacheDefinition:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+
+ std::string_view refreshed_by;
+ std::string_view rid;
+ long record_count = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (!attr.ns || attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_refreshedBy:
+ refreshed_by = attr.value;
+ break;
+ case XML_recordCount:
+ record_count = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_ooxml_r)
+ {
+ switch (attr.name)
+ {
+ case XML_id:
+ // relation id for its cache record.
+ rid = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "pivot cache definition" << endl;
+ cout << "refreshed by: " << refreshed_by << endl;
+ cout << "record count: " << record_count << endl;
+ cout << "rid: " << rid << endl;
+ }
+
+ if (!rid.empty())
+ {
+ // The rid string here must be persistent beyond the current
+ // context.
+ rid = get_session_context().spool.intern(rid).first;
+
+ m_pcache_info.data.insert(
+ opc_rel_extras_t::map_type::value_type(
+ rid, std::make_unique<xlsx_rel_pivot_cache_record_info>(m_pcache_id)));
+ }
+
+ break;
+ }
+ case XML_cacheSource:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotCacheDefinition);
+
+ std::string_view source_type_s;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_type:
+ m_source_type = pc_source::get().find(attr.value);
+ source_type_s = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ cout << "type: " << source_type_s << endl;
+
+ break;
+ }
+ case XML_worksheetSource:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cacheSource);
+ if (m_source_type != source_type::worksheet)
+ throw xml_structure_error(
+ "worksheetSource element encountered while the source type is not worksheet.");
+
+ std::string_view ref, sheet_name, table_name;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_ref:
+ ref = attr.value;
+ break;
+ case XML_sheet:
+ sheet_name = attr.value;
+ break;
+ case XML_name:
+ table_name = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ cout << "table: " << table_name << endl;
+ cout << "ref: " << ref << endl;
+ cout << "sheet: " << sheet_name << endl;
+ }
+
+ if (!table_name.empty())
+ m_pcache.set_worksheet_source(table_name);
+ else
+ m_pcache.set_worksheet_source(ref, sheet_name);
+ break;
+ }
+ case XML_cacheFields:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotCacheDefinition);
+ single_long_attr_getter func(NS_ooxml_xlsx, XML_count);
+ long field_count = for_each(attrs.begin(), attrs.end(), func).get_value();
+
+ if (get_config().debug)
+ cout << "field count: " << field_count << endl;
+
+ if (field_count < 0)
+ throw xml_structure_error("field count of a pivot cache must be positive.");
+
+ m_pcache.set_field_count(field_count);
+ break;
+ }
+ case XML_cacheField:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cacheFields);
+
+ std::string_view field_name;
+ long numfmt_id = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ field_name = attr.value;
+ break;
+ case XML_numFmtId:
+ numfmt_id = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ // TODO : Handle number format ID here.
+ m_pcache.set_field_name(field_name);
+
+ if (get_config().debug)
+ {
+ cout << "* name: " << field_name << endl;
+ cout << " number format id: " << numfmt_id << endl;
+ }
+ break;
+ }
+ case XML_fieldGroup:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cacheField);
+ long group_parent = -1;
+ long group_base = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_par:
+ group_parent = to_long(attr.value);
+ break;
+ case XML_base:
+ group_base = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ if (group_parent >= 0)
+ cout << " * group parent index: " << group_parent << endl;
+ if (group_base >= 0)
+ cout << " * group base index: " << group_base << endl;
+ }
+
+ if (group_base >= 0)
+ {
+ // This is a group field.
+ m_pcache_field_group = m_pcache.start_field_group(group_base);
+ }
+ break;
+ }
+ case XML_discretePr:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_fieldGroup);
+
+ long count = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_count:
+ count = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ cout << " * group child member count: " << count << endl;
+
+ break;
+ }
+ case XML_rangePr:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_fieldGroup);
+
+ bool auto_start = true;
+ bool auto_end = true;
+ double start = 0.0;
+ double end = 0.0;
+ double interval = 1.0;
+
+ std::optional<date_time_t> start_date;
+ std::optional<date_time_t> end_date;
+
+ // Default group-by type appears to be 'range'.
+ spreadsheet::pivot_cache_group_by_t group_by =
+ spreadsheet::pivot_cache_group_by_t::range;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_autoStart:
+ auto_start = to_bool(attr.value);
+ break;
+ case XML_autoEnd:
+ auto_end = to_bool(attr.value);
+ break;
+ case XML_startNum:
+ start = to_double(attr.value);
+ break;
+ case XML_endNum:
+ end = to_double(attr.value);
+ break;
+ case XML_groupInterval:
+ interval = to_double(attr.value);
+ break;
+ case XML_startDate:
+ start_date = date_time_t::from_chars(attr.value);
+ break;
+ case XML_endDate:
+ end_date = date_time_t::from_chars(attr.value);
+ break;
+ case XML_groupBy:
+ group_by = spreadsheet::to_pivot_cache_group_by_enum(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (m_pcache_field_group)
+ {
+ // Pass the values to the interface.
+ m_pcache_field_group->set_range_grouping_type(group_by);
+ m_pcache_field_group->set_range_auto_start(auto_start);
+ m_pcache_field_group->set_range_auto_end(auto_end);
+ m_pcache_field_group->set_range_start_number(start);
+ m_pcache_field_group->set_range_end_number(end);
+ m_pcache_field_group->set_range_interval(interval);
+
+ if (start_date)
+ m_pcache_field_group->set_range_start_date(*start_date);
+ if (end_date)
+ m_pcache_field_group->set_range_end_date(*end_date);
+ }
+
+ if (get_config().debug)
+ {
+ cout << " auto start: " << auto_start << endl;
+ cout << " auto end: " << auto_end << endl;
+ cout << " start: " << start << endl;
+ cout << " end: " << end << endl;
+ cout << " interval: " << interval << endl;
+
+ if (start_date)
+ cout << "start date: " << *start_date << endl;
+ if (end_date)
+ cout << "end date: " << *end_date << endl;
+ }
+
+ break;
+ }
+ case XML_sharedItems:
+ {
+ start_element_shared_items(parent, attrs);
+ break;
+ }
+ case XML_groupItems:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_fieldGroup);
+
+ long count = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_count:
+ count = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ cout << " * group member count: " << count << endl;
+
+ break;
+ }
+ case XML_s:
+ {
+ start_element_s(parent, attrs);
+ break;
+ }
+ case XML_n:
+ {
+ start_element_n(parent, attrs);
+ break;
+ }
+ case XML_d:
+ {
+ start_element_d(parent, attrs);
+ break;
+ }
+ case XML_e:
+ {
+ start_element_e(parent, attrs);
+ break;
+ }
+ case XML_x:
+ {
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_discretePr },
+ { NS_ooxml_xlsx, XML_reference },
+ };
+ xml_element_expected(parent, expected);
+
+ long index = -1;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_v:
+ index = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (index < 0)
+ throw xml_structure_error("element 'x' without a required attribute 'v'.");
+
+ if (get_config().debug)
+ cout << " * index = " << index << endl;
+
+ if (m_pcache_field_group)
+ m_pcache_field_group->link_base_to_group_items(index);
+
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+}
+
+bool xlsx_pivot_cache_def_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_pivotCacheDefinition:
+ {
+ m_pcache.commit();
+ break;
+ }
+ case XML_cacheField:
+ {
+ m_pcache.commit_field();
+ m_pcache_field_group = nullptr;
+ break;
+ }
+ case XML_discretePr:
+ {
+ break;
+ }
+ case XML_fieldGroup:
+ {
+ if (m_pcache_field_group)
+ m_pcache_field_group->commit();
+ break;
+ }
+ case XML_s:
+ end_element_s();
+ break;
+ case XML_n:
+ end_element_n();
+ break;
+ case XML_d:
+ end_element_d();
+ break;
+ case XML_e:
+ end_element_e();
+ break;
+ default:
+ ;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void xlsx_pivot_cache_def_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+opc_rel_extras_t xlsx_pivot_cache_def_context::pop_rel_extras()
+{
+ return std::move(m_pcache_info);
+}
+
+void xlsx_pivot_cache_def_context::start_element_s(
+ const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs)
+{
+ if (parent.first != NS_ooxml_xlsx)
+ {
+ warn_unhandled();
+ return;
+ }
+
+ std::string_view value;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_v:
+ value = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ // regular (non-group) field member name.
+
+ if (get_config().debug)
+ cout << " * field member: " << value << endl;
+
+ m_field_item_used = true;
+ m_pcache.set_field_item_string(value);
+ break;
+ }
+ case XML_groupItems:
+ {
+ // group field member name.
+
+ if (get_config().debug)
+ cout << " * group field member: " << value << endl;
+
+ m_field_item_used = true;
+ if (m_pcache_field_group)
+ m_pcache_field_group->set_field_item_string(value);
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+}
+
+void xlsx_pivot_cache_def_context::end_element_s()
+{
+ const xml_token_pair_t& parent = get_parent_element();
+ if (parent.first != NS_ooxml_xlsx)
+ return;
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ if (m_field_item_used)
+ m_pcache.commit_field_item();
+ break;
+ }
+ case XML_groupItems:
+ {
+ if (m_pcache_field_group && m_field_item_used)
+ m_pcache_field_group->commit_field_item();
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::start_element_n(
+ const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs)
+{
+ if (parent.first != NS_ooxml_xlsx)
+ {
+ warn_unhandled();
+ return;
+ }
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ // numeric item of a cache field.
+ double value = 0.0;
+ m_field_item_used = true;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_v:
+ value = to_double(attr.value);
+ break;
+ case XML_u:
+ // flag for unused item.
+ m_field_item_used = !to_bool(attr.value);
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ cout << " * n: " << value;
+ if (!m_field_item_used)
+ cout << " (unused)";
+ cout << endl;
+
+ }
+
+ if (m_field_item_used)
+ m_pcache.set_field_item_numeric(value);
+
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+}
+
+void xlsx_pivot_cache_def_context::end_element_n()
+{
+ const xml_token_pair_t& parent = get_parent_element();
+ if (parent.first != NS_ooxml_xlsx)
+ return;
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ if (m_field_item_used)
+ m_pcache.commit_field_item();
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::start_element_d(
+ const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs)
+{
+ if (parent.first != NS_ooxml_xlsx)
+ {
+ warn_unhandled();
+ return;
+ }
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ // date item of a cache field.
+ date_time_t dt;
+ m_field_item_used = true;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_v:
+ dt = date_time_t::from_chars(attr.value);
+ break;
+ case XML_u:
+ // flag for unused item.
+ m_field_item_used = !to_bool(attr.value);
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ cout << " * d: " << dt;
+ if (!m_field_item_used)
+ cout << " (unused)";
+ cout << endl;
+
+ }
+
+ if (m_field_item_used)
+ m_pcache.set_field_item_date_time(dt);
+
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::end_element_d()
+{
+ const xml_token_pair_t& parent = get_parent_element();
+ if (parent.first != NS_ooxml_xlsx)
+ return;
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ if (m_field_item_used)
+ m_pcache.commit_field_item();
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::start_element_e(
+ const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs)
+{
+ if (parent.first != NS_ooxml_xlsx)
+ {
+ warn_unhandled();
+ return;
+ }
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ // error value item of a cache field.
+ spreadsheet::error_value_t ev = spreadsheet::error_value_t::unknown;
+ m_field_item_used = true;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_v:
+ ev = spreadsheet::to_error_value_enum(attr.value);
+ break;
+ case XML_u:
+ // flag for unused item.
+ m_field_item_used = !to_bool(attr.value);
+ default:
+ ;
+ }
+ }
+ );
+
+ if (get_config().debug)
+ {
+ cout << " * e: " << ev;
+ if (!m_field_item_used)
+ cout << " (unused)";
+ cout << endl;
+ }
+
+ if (m_field_item_used)
+ m_pcache.set_field_item_error(ev);
+
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::end_element_e()
+{
+ const xml_token_pair_t& parent = get_parent_element();
+ if (parent.first != NS_ooxml_xlsx)
+ return;
+
+ switch (parent.second)
+ {
+ case XML_sharedItems:
+ {
+ if (m_field_item_used)
+ m_pcache.commit_field_item();
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+void xlsx_pivot_cache_def_context::start_element_shared_items(
+ const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs)
+{
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cacheField);
+
+ // If "semi-mixed types" is set, the field contains text values and at
+ // least one other type.
+ bool semi_mixed_types = true;
+
+ bool has_non_date = true;
+ bool has_date = false;
+ bool has_string = true;
+ bool has_blank = false;
+
+ // If "mixed types" is set, the field contains more than one data types.
+ bool mixed_types = false;
+
+ bool has_number = false;
+ bool has_integer = false;
+ bool has_long_text = false;
+
+ long count = -1;
+ std::optional<double> min_value;
+ std::optional<double> max_value;
+ std::optional<date_time_t> min_date;
+ std::optional<date_time_t> max_date;
+
+ for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_count:
+ count = to_long(attr.value);
+ break;
+ case XML_containsMixedTypes:
+ mixed_types = to_bool(attr.value);
+ break;
+ case XML_containsSemiMixedTypes:
+ semi_mixed_types = to_bool(attr.value);
+ break;
+ case XML_containsNonDate:
+ has_non_date = to_bool(attr.value);
+ break;
+ case XML_containsString:
+ has_string = to_bool(attr.value);
+ break;
+ case XML_containsBlank:
+ has_blank = to_bool(attr.value);
+ break;
+ case XML_containsNumber:
+ has_number = to_bool(attr.value);
+ break;
+ case XML_containsInteger:
+ has_integer = to_bool(attr.value);
+ break;
+ case XML_minValue:
+ min_value = to_double(attr.value);
+ break;
+ case XML_maxValue:
+ max_value = to_double(attr.value);
+ break;
+ case XML_minDate:
+ min_date = date_time_t::from_chars(attr.value);
+ break;
+ case XML_maxDate:
+ max_date = date_time_t::from_chars(attr.value);
+ break;
+ case XML_longText:
+ has_long_text = to_bool(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ if (min_value)
+ m_pcache.set_field_min_value(*min_value);
+
+ if (max_value)
+ m_pcache.set_field_max_value(*max_value);
+
+ if (min_date)
+ m_pcache.set_field_min_date(*min_date);
+
+ if (max_date)
+ m_pcache.set_field_max_date(*max_date);
+
+ if (get_config().debug)
+ {
+ cout << " contains semi-mixed types: " << semi_mixed_types << endl;
+ cout << " contains non-date: " << has_non_date << endl;
+ cout << " contains date: " << has_date << endl;
+ cout << " contains string: " << has_string << endl;
+ cout << " contains blank: " << has_blank << endl;
+ cout << " contains mixed types: " << mixed_types << endl;
+ cout << " contains number: " << has_number << endl;
+ cout << " contains integer: " << has_integer << endl;
+ cout << " contains long text: " << has_long_text << endl;
+ cout << " count: " << count << endl;
+
+ if (min_value)
+ cout << " min value: " << *min_value << endl;
+ if (max_value)
+ cout << " max value: " << *max_value << endl;
+ if (min_date)
+ cout << " min date: " << *min_date << endl;
+ if (max_date)
+ cout << " max date: " << *max_date << endl;
+ }
+}
+
+xlsx_pivot_cache_rec_context::xlsx_pivot_cache_rec_context(
+ session_context& cxt, const tokens& tokens,
+ spreadsheet::iface::import_pivot_cache_records& pc_records) :
+ xml_context_base(cxt, tokens),
+ m_pc_records(pc_records) {}
+
+xml_context_base* xlsx_pivot_cache_rec_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_pivot_cache_rec_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns != NS_ooxml_xlsx)
+ return;
+
+ switch (name)
+ {
+ case XML_pivotCacheRecords:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ long count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "pivot cache record (count: " << count << ")" << endl;
+ }
+
+ m_pc_records.set_record_count(count);
+ break;
+ }
+ case XML_r: // record
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotCacheRecords);
+ if (get_config().debug)
+ cout << "* record" << endl;
+
+ break;
+ case XML_s: // character value
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_r);
+
+ std::string_view cv = single_attr_getter::get(attrs, NS_ooxml_xlsx, XML_v);
+
+ if (get_config().debug)
+ cout << " * s = '" << cv << "'" << endl;
+
+ m_pc_records.append_record_value_character(cv);
+ break;
+ }
+ case XML_x: // shared item index
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_r);
+ long v = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_v);
+ if (get_config().debug)
+ cout << " * x = " << v << endl;
+
+ m_pc_records.append_record_value_shared_item(v);
+ break;
+ }
+ case XML_n: // numeric
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_r);
+ double val = single_double_attr_getter::get(attrs, NS_ooxml_xlsx, XML_v);
+ if (get_config().debug)
+ cout << " * n = " << val << endl;
+
+ m_pc_records.append_record_value_numeric(val);
+ break;
+ }
+ case XML_e: // error value
+ {
+ std::string_view cv = single_attr_getter::get(attrs, NS_ooxml_xlsx, XML_v);
+
+ if (get_config().debug)
+ cout << " * e = " << cv << endl;
+
+ break;
+ }
+ case XML_b: // boolean
+ case XML_d: // date time
+ case XML_m: // no value
+ default:
+ warn_unhandled();
+ }
+}
+
+bool xlsx_pivot_cache_rec_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_pivotCacheRecords:
+ m_pc_records.commit();
+ break;
+ case XML_r: // record
+ m_pc_records.commit_record();
+ break;
+ default:
+ ;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+xlsx_pivot_table_context::xlsx_pivot_table_context(session_context& cxt, const tokens& tokens) :
+ xml_context_base(cxt, tokens) {}
+
+xml_context_base* xlsx_pivot_table_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_pivot_table_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_pivotTableDefinition:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ if (get_config().debug)
+ cout << "---" << endl;
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ long v = 0;
+ bool b = false;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ if (get_config().debug)
+ cout << "name: " << attr.value << endl;
+ break;
+ case XML_cacheId:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "cache ID: " << v << endl;
+ break;
+ case XML_applyNumberFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply number formats: " << b << endl;
+ break;
+ case XML_applyBorderFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply border formats: " << b << endl;
+ break;
+ case XML_applyFontFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply font formats: " << b << endl;
+ break;
+ case XML_applyPatternFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply pattern formats: " << b << endl;
+ break;
+ case XML_applyAlignmentFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply alignment formats: " << b << endl;
+ break;
+ case XML_applyWidthHeightFormats:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "apply width/height formats: " << b << endl;
+ break;
+ case XML_dataCaption:
+ if (get_config().debug)
+ cout << "data caption: " << attr.value << endl;
+ break;
+ case XML_updatedVersion:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "updated version: " << v << endl;
+ break;
+ case XML_minRefreshableVersion:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "minimum refreshable version: " << v << endl;
+ break;
+ case XML_showCalcMbrs:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show calc members (?): " << b << endl;
+ break;
+ case XML_useAutoFormatting:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "use auto formatting: " << b << endl;
+ break;
+ case XML_itemPrintTitles:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "item print titles (?): " << b << endl;
+ break;
+ case XML_createdVersion:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "created version: " << v << endl;
+ break;
+ case XML_indent:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "indent: " << b << endl;
+ break;
+ case XML_compact:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "compact: " << b << endl;
+ break;
+ case XML_compactData:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "compact data: " << b << endl;
+ break;
+ case XML_outline:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "outline: " << b << endl;
+ break;
+ case XML_outlineData:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "outline data: " << b << endl;
+ break;
+ case XML_gridDropZones:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "grid drop zones: " << b << endl;
+ break;
+ case XML_multipleFieldFilters:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "multiple field filters: " << b << endl;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ break;
+ case XML_location:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ long v = -1;
+ switch (attr.name)
+ {
+ case XML_ref:
+ if (get_config().debug)
+ cout << "ref: " << attr.value << endl;
+ break;
+ case XML_firstHeaderRow:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "first header row: " << v << endl;
+ break;
+ case XML_firstDataRow:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "first data row: " << v << endl;
+ break;
+ case XML_firstDataCol:
+ v = to_long(attr.value);
+ if (get_config().debug)
+ cout << "first data column: " << v << endl;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ break;
+ case XML_pivotFields:
+ {
+ // pivotFields and its child elements represent the visual
+ // appearances of the fields inside pivot table.
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ cout << "field count: " << count << endl;
+ }
+ break;
+ case XML_pivotField:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotFields);
+
+ if (get_config().debug)
+ cout << "---" << endl;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_axis:
+ if (get_config().debug)
+ cout << " * axis: " << attr.value << endl;
+ break;
+ case XML_compact:
+ {
+ bool b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << " * compact: " << b << endl;
+ }
+ break;
+ case XML_outline:
+ {
+ bool b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << " * outline: " << b << endl;
+ }
+ break;
+ case XML_showAll:
+ {
+ bool b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << " * show all: " << b << endl;
+ }
+ break;
+ case XML_dataField:
+ {
+ bool b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << " * data field: " << b << endl;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ break;
+ case XML_items:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotField);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ cout << " * item count: " << count << endl;
+ }
+ break;
+ case XML_item:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_items);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_x:
+ {
+ // field item index as defined in the pivot cache.
+ long idx = to_long(attr.value);
+ if (get_config().debug)
+ cout << " * x = " << idx << endl;
+ }
+ break;
+ case XML_t:
+ {
+ // When the <item> element has attribute 't', it's subtotal or
+ // some sort of function item. See 3.18.45 ST_ItemType
+ // (PivotItem Type) for possible values.
+ if (get_config().debug)
+ cout << " * type = " << attr.value << endl;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ break;
+ case XML_rowFields:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "row field count: " << count << endl;
+ }
+ }
+ break;
+ case XML_colFields:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "column field count: " << count << endl;
+ }
+ }
+ break;
+ case XML_pageFields:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "page field count: " << count << endl;
+ }
+ }
+ break;
+ case XML_pageField:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pageFields);
+
+ if (get_config().debug)
+ cout << " * page field:";
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_fld:
+ {
+ long fld = to_long(attr.value);
+ if (get_config().debug)
+ cout << "field index = " << fld << "; ";
+ break;
+ }
+ case XML_item:
+ {
+ long item = to_long(attr.value);
+ if (get_config().debug)
+ cout << "item index = " << item << "; ";
+ break;
+ }
+ case XML_hier:
+ {
+ long hier = to_long(attr.value);
+ // -1 if not applicable.
+ if (get_config().debug)
+ cout << "OLAP hierarchy index = " << hier << "; ";
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ if (get_config().debug)
+ cout << endl;
+ break;
+ }
+ case XML_field:
+ {
+ xml_elem_stack_t expected;
+ expected.reserve(3);
+ expected.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_rowFields));
+ expected.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_colFields));
+ xml_element_expected(parent, expected);
+
+ // Index into the list of <pivotField> collection which is
+ // given earlier under the <pivotFields> element. The value
+ // of -2 represents a special field that displays the list of
+ // data fields when the pivot table contains more than one
+ // data field.
+ long idx = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_x);
+ if (get_config().debug)
+ cout << " * x = " << idx << endl;
+ }
+ break;
+ case XML_dataFields:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "data field count: " << count << endl;
+ }
+ }
+ break;
+ case XML_dataField:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_dataFields);
+
+ if (get_config().debug)
+ cout << " * data field: ";
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ {
+ if (get_config().debug)
+ cout << "name = " << attr.value << "; ";
+ break;
+ }
+ case XML_fld:
+ {
+ long fld = to_long(attr.value);
+ if (get_config().debug)
+ cout << "field = " << fld << "; ";
+ break;
+ }
+ case XML_baseField:
+ {
+ long fld = to_long(attr.value);
+ if (get_config().debug)
+ cout << "base field = " << fld << "; ";
+ break;
+ }
+ case XML_baseItem:
+ {
+ long fld = to_long(attr.value);
+ if (get_config().debug)
+ cout << "base item = " << fld << "; ";
+ break;
+ }
+ case XML_subtotal:
+ {
+ if (get_config().debug)
+ cout << "subtotal = " << attr.value << "; ";
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ if (get_config().debug)
+ cout << endl;
+ }
+ break;
+ case XML_rowItems:
+ {
+ // <rowItems> structure describes the displayed content of
+ // cells in the row field area. Each <i> child element
+ // represents a single row.
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "row item count: " << count << endl;
+ }
+ }
+ break;
+ case XML_colItems:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+ size_t count = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "column item count: " << count << endl;
+ }
+ }
+ break;
+ case XML_i:
+ {
+ xml_elem_stack_t expected;
+ expected.reserve(2);
+ expected.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_rowItems));
+ expected.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_colItems));
+ xml_element_expected(parent, expected);
+
+ if (get_config().debug)
+ cout << "---" << endl;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_t:
+ {
+ // total or subtotal function type.
+ if (get_config().debug)
+ cout << " * type = " << attr.value << endl;
+ }
+ break;
+ case XML_r:
+ {
+ // "repeated item count" which basically is the number of
+ // blank cells that occur after the preivous non-empty cell on
+ // the same row (in the classic layout mode).
+ long v = to_long(attr.value);
+ if (get_config().debug)
+ cout << " * repeat item count = " << v << endl;
+ }
+ break;
+ case XML_i:
+ {
+ // zero-based data field index in case of multiple data fields.
+ long v = to_long(attr.value);
+ if (get_config().debug)
+ cout << " * data field index = " << v << endl;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ break;
+ case XML_x:
+ {
+ if (parent.first != NS_ooxml_xlsx)
+ {
+ warn_unhandled();
+ break;
+ }
+
+ if (parent.second == XML_i)
+ {
+ long idx = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_v);
+ if (idx < 0)
+ // 0 is default when not set.
+ idx = 0;
+
+ if (get_config().debug)
+ cout << " * v = " << idx << endl;
+ break;
+ }
+
+ warn_unhandled();
+ }
+ break;
+ case XML_pivotTableStyleInfo:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotTableDefinition);
+
+ if (get_config().debug)
+ {
+ cout << "---" << endl;
+ cout << "* style info: ";
+ }
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ bool b = false;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ if (get_config().debug)
+ cout << "name='" << attr.value << "'; ";
+ break;
+ case XML_showRowHeaders:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show row headers=" << b << "; ";
+ break;
+ case XML_showColHeaders:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show column headers=" << b << "; ";
+ break;
+ case XML_showRowStripes:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show row stripes=" << b << "; ";
+ break;
+ case XML_showColStripes:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show column stripes=" << b << "; ";
+ break;
+ case XML_showLastColumn:
+ b = to_bool(attr.value);
+ if (get_config().debug)
+ cout << "show last column=" << b << "; ";
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (get_config().debug)
+ cout << endl;
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool xlsx_pivot_table_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void xlsx_pivot_table_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_pivot_context.hpp b/src/liborcus/xlsx_pivot_context.hpp
new file mode 100644
index 0000000..f9610ba
--- /dev/null
+++ b/src/liborcus/xlsx_pivot_context.hpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_PIVOT_CONTEXT_HPP
+#define ORCUS_XLSX_PIVOT_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "ooxml_types.hpp"
+#include "orcus/spreadsheet/types.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_pivot_cache_definition;
+class import_pivot_cache_field_group;
+class import_pivot_cache_records;
+
+}}
+
+/**
+ * Base context for pivotCacheDefinition[n].xml part, which defines the
+ * structure of a pivot cache.
+ */
+class xlsx_pivot_cache_def_context : public xml_context_base
+{
+public:
+ enum class source_type {
+ unknown = 0,
+ worksheet,
+ external,
+ consolidation,
+ scenario
+ };
+
+private:
+ spreadsheet::iface::import_pivot_cache_definition& m_pcache;
+ spreadsheet::pivot_cache_id_t m_pcache_id;
+ spreadsheet::iface::import_pivot_cache_field_group* m_pcache_field_group = nullptr;
+ source_type m_source_type = source_type::unknown;
+ bool m_field_item_used = true;
+
+ opc_rel_extras_t m_pcache_info;
+
+public:
+ xlsx_pivot_cache_def_context(
+ session_context& cxt, const tokens& tokens,
+ spreadsheet::iface::import_pivot_cache_definition& pcache,
+ spreadsheet::pivot_cache_id_t pcache_id);
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ opc_rel_extras_t pop_rel_extras();
+
+private:
+ void start_element_s(const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs);
+ void end_element_s();
+
+ void start_element_n(const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs);
+ void end_element_n();
+
+ void start_element_d(const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs);
+ void end_element_d();
+
+ void start_element_e(const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs);
+ void end_element_e();
+
+ void start_element_shared_items(const xml_token_pair_t& parent, const std::vector<xml_token_attr_t>& attrs);
+};
+
+/**
+ * Context for pivotCacheRecords[n].xml part, which contains the records in
+ * a pivot cache.
+ */
+class xlsx_pivot_cache_rec_context : public xml_context_base
+{
+ spreadsheet::iface::import_pivot_cache_records& m_pc_records;
+
+public:
+ xlsx_pivot_cache_rec_context(
+ session_context& cxt, const tokens& tokens,
+ spreadsheet::iface::import_pivot_cache_records& pc_records);
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+};
+
+/**
+ * Context for pivotTable[n].xml part which defines the structure of a pivot
+ * table model.
+ */
+class xlsx_pivot_table_context : public xml_context_base
+{
+public:
+ xlsx_pivot_table_context(session_context& cxt, const tokens& tokens);
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_revision_context.cpp b/src/liborcus/xlsx_revision_context.cpp
new file mode 100644
index 0000000..637659f
--- /dev/null
+++ b/src/liborcus/xlsx_revision_context.cpp
@@ -0,0 +1,578 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_revision_context.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "session_context.hpp"
+#include "xml_context_global.hpp"
+
+#include "orcus/measurement.hpp"
+#include "orcus/string_pool.hpp"
+
+#include <iostream>
+#include <limits>
+
+using namespace std;
+
+namespace orcus {
+
+namespace {
+
+class headers_attr_parser
+{
+ std::string_view m_guid;
+ long m_highest_revid;
+ long m_version;
+ bool m_disk_revisions;
+
+public:
+ headers_attr_parser() : m_highest_revid(-1), m_version(-1), m_disk_revisions(false) {}
+
+ std::string_view get_last_guid() const { return m_guid; }
+ long get_highest_revid() const { return m_highest_revid; }
+ long get_version() const { return m_version; }
+ bool is_disk_revisions() const { return m_disk_revisions; }
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns != NS_ooxml_xlsx)
+ // All attributes are in the xlsx namespace.
+ return;
+
+ switch (attr.name)
+ {
+ case XML_guid:
+ // guid should never be transient as it's not supposed to contain any encoded characters.
+ // TODO : We should convert guid to a numeric value here.
+ m_guid = attr.value;
+ break;
+ case XML_diskRevisions:
+ m_disk_revisions = to_long(attr.value) != 0;
+ break;
+ case XML_revisionId:
+ m_highest_revid = to_long(attr.value);
+ break;
+ case XML_version:
+ m_version = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+};
+
+class header_attr_parser
+{
+ string_pool* m_pool;
+
+ std::string_view m_guid;
+ std::string_view m_username;
+ std::string_view m_rid;
+
+ date_time_t m_date_time;
+ long m_next_sheet_id;
+ long m_min_revid;
+ long m_max_revid;
+
+public:
+ header_attr_parser(string_pool& pool) :
+ m_pool(&pool), m_next_sheet_id(-1), m_min_revid(-1), m_max_revid(-1) {}
+
+ std::string_view get_guid() const { return m_guid; }
+ std::string_view get_username() const { return m_username; }
+ std::string_view get_rid() const { return m_rid; }
+ date_time_t get_date_time() const { return m_date_time; }
+ long get_next_sheet_id() const { return m_next_sheet_id; }
+ long get_min_revid() const { return m_min_revid; }
+ long get_max_revid() const { return m_max_revid; }
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_guid:
+ m_guid = attr.value;
+ break;
+ case XML_dateTime:
+ m_date_time = date_time_t::from_chars(attr.value);
+ break;
+ case XML_maxSheetId:
+ m_next_sheet_id = to_long(attr.value);
+ break;
+ case XML_userName:
+ m_username = attr.value;
+ if (attr.transient)
+ m_username = m_pool->intern(m_username).first;
+ break;
+ case XML_minRId:
+ m_min_revid = to_long(attr.value);
+ break;
+ case XML_maxRId:
+ m_max_revid = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_ooxml_r && attr.name == XML_id)
+ {
+ // Pick up a rel id here.
+ if (attr.transient)
+ // Rel ID's should never be transient.
+ return;
+
+ m_rid = attr.value;
+ }
+ }
+};
+
+}
+
+xlsx_revheaders_context::xlsx_revheaders_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens) {}
+
+xlsx_revheaders_context::~xlsx_revheaders_context() {}
+
+xml_context_base* xlsx_revheaders_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_revheaders_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_revheaders_context::start_element(xmlns_id_t ns, xml_token_t name, const vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_headers:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ headers_attr_parser func;
+ func = for_each(attrs.begin(), attrs.end(), func);
+ cout << "* last guid: " << func.get_last_guid() << endl;
+ cout << "* highest revision ID: " << func.get_highest_revid() << endl;
+ cout << "* version: " << func.get_version() << endl;
+ cout << "* disk revisions: " << func.is_disk_revisions() << endl;
+ }
+ break;
+ case XML_header:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_headers);
+ header_attr_parser func(get_session_context().spool);
+ func = for_each(attrs.begin(), attrs.end(), func);
+ cout << "* revision header (guid:" << func.get_guid() << ")" << endl;
+ cout << " - timestamp: " << func.get_date_time().to_string() << endl;
+ cout << " - user name: " << func.get_username() << endl;
+
+ if (func.get_min_revid() != -1 && func.get_max_revid() != -1)
+ cout << " - revision range: " << func.get_min_revid() << "-" << func.get_max_revid() << endl;
+
+ long next_sheet = func.get_next_sheet_id();
+ if (next_sheet != -1)
+ cout << " - next available sheet: " << (next_sheet - 1) << endl;
+
+ cout << " - revision log rid: " << func.get_rid() << endl;
+ // TODO : Intern the rid here when passing it to the revision log stream.
+ }
+ break;
+ case XML_sheetIdMap:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_header);
+ m_cur_sheet_ids.clear();
+ long n = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_count);
+ if (n > 0)
+ m_cur_sheet_ids.reserve(n);
+ }
+ break;
+ case XML_sheetId:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_sheetIdMap);
+ long val = single_long_attr_getter::get(attrs, NS_ooxml_xlsx, XML_val);
+ if (val > 0)
+ m_cur_sheet_ids.push_back(val-1); // convert from 1-based to 0-based.
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+}
+
+bool xlsx_revheaders_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_sheetIdMap:
+ {
+ cout << " - sheet indices: ";
+ for (size_t i = 0; i < m_cur_sheet_ids.size(); ++i)
+ cout << m_cur_sheet_ids[i] << " ";
+ cout << endl;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_revheaders_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+namespace {
+
+class rcc_attr_parser
+{
+ long m_revision_id;
+ long m_sheet_id;
+
+public:
+ rcc_attr_parser() : m_revision_id(-1), m_sheet_id(-1) {}
+
+ long get_revision_id() const { return m_revision_id; }
+ long get_sheet_id() const { return m_sheet_id; }
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_rId:
+ // revision ID
+ m_revision_id = to_long(attr.value);
+ break;
+ case XML_sId:
+ // sheet ID
+ m_sheet_id = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+};
+
+class rrc_attr_parser
+{
+ long m_revision_id;
+ long m_sheet_id;
+
+ std::string_view m_ref;
+ xlsx_rev_row_column_action_t m_action_type;
+
+ bool m_end_of_list;
+
+public:
+ rrc_attr_parser() : m_revision_id(-1), m_sheet_id(-1),
+ m_action_type(xlsx_rev_rca_unknown), m_end_of_list(false) {}
+
+ long get_revision_id() const { return m_revision_id; }
+ long get_sheet_id() const { return m_sheet_id; }
+ bool is_end_of_list() const { return m_end_of_list; }
+ std::string_view get_ref() const { return m_ref; }
+ xlsx_rev_row_column_action_t get_action_type() const { return m_action_type; }
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_rId:
+ // revision ID
+ m_revision_id = to_long(attr.value);
+ break;
+ case XML_sId:
+ // sheet ID
+ m_sheet_id = to_long(attr.value);
+ break;
+ case XML_eol:
+ m_end_of_list = to_long(attr.value) > 0;
+ break;
+ case XML_ref:
+ if (!attr.transient)
+ m_ref = attr.value;
+ break;
+ case XML_action:
+ m_action_type = to_xlsx_rev_row_column_action_type(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+};
+
+class cell_data_attr_parser
+{
+ std::string_view m_ref;
+ xlsx_cell_t m_type;
+
+public:
+ cell_data_attr_parser() : m_type(xlsx_ct_numeric) {}
+
+ std::string_view get_ref() const { return m_ref; }
+ xlsx_cell_t get_cell_type() const { return m_type; }
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_r:
+ if (!attr.transient)
+ m_ref = attr.value;
+ break;
+ case XML_t:
+ m_type = to_xlsx_cell_type(attr.value);
+ default:
+ ;
+ }
+ }
+};
+
+}
+
+xlsx_revlog_context::xlsx_revlog_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens),
+ m_cur_value(std::numeric_limits<double>::quiet_NaN()),
+ m_cur_cell_type(xlsx_ct_unknown), m_cur_formula(false)
+{
+}
+
+xlsx_revlog_context::~xlsx_revlog_context() {}
+
+xml_context_base* xlsx_revlog_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_revlog_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_revlog_context::start_element(xmlns_id_t ns, xml_token_t name, const vector<xml_token_attr_t>& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_revisions:
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ break;
+ case XML_raf:
+ // revision auto format
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rcc:
+ {
+ // revision cell change
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ rcc_attr_parser func;
+ func = for_each(attrs.begin(), attrs.end(), func);
+ cout << "* revision id: " << func.get_revision_id() << " type: cell change" << endl;
+ cout << " - sheet index: " << func.get_sheet_id() << endl;
+ m_cur_cell_type = xlsx_ct_unknown;
+ }
+ break;
+ case XML_rcft:
+ // revision merge conflict
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rcmt:
+ // revision cell comment
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rcv:
+ // revision custom view
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rdn:
+ // revision defined name
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rfmt:
+ {
+ // revision format
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_revisions },
+ { NS_ooxml_xlsx, XML_rm },
+ { NS_ooxml_xlsx, XML_rrc },
+ };
+ xml_element_expected(parent, expected);
+ break;
+ }
+ case XML_ris:
+ // revision insert sheet
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rm:
+ // revision cell move
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rqt:
+ // revision query table
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_rrc:
+ {
+ // revision row column insert delete
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ rrc_attr_parser func;
+ func = for_each(attrs.begin(), attrs.end(), func);
+ cout << "* revision id: " << func.get_revision_id() << " type: row column insert delete" << endl;
+ cout << " - sheet index: " << func.get_sheet_id() << endl;
+ cout << " - action type: " << to_string(func.get_action_type()) << endl;
+ cout << " - range: " << func.get_ref() << endl;
+ cout << " - end of list: " << (func.is_end_of_list() ? "true":"false") << endl;
+ }
+ break;
+ case XML_rsnm:
+ // revision sheet name
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_revisions);
+ break;
+ case XML_oc:
+ // old cell data
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rcc);
+ break;
+ case XML_nc:
+ {
+ // new cell data
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rcc);
+ cell_data_attr_parser func;
+ func = for_each(attrs.begin(), attrs.end(), func);
+ m_cur_cell_type = func.get_cell_type();
+
+ m_cur_formula = false;
+ m_cur_value = 0.0;
+ m_cur_string = std::string_view{};
+
+ cout << " - new cell position: " << func.get_ref() << endl;
+ cout << " - new cell type: " << to_string(m_cur_cell_type) << endl;
+ }
+ break;
+ case XML_f:
+ {
+ xml_elem_stack_t elems;
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_oc));
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_nc));
+ xml_element_expected(parent, elems);
+ }
+ break;
+ case XML_v:
+ {
+ xml_elem_stack_t elems;
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_oc));
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_nc));
+ xml_element_expected(parent, elems);
+ }
+ break;
+ case XML_is:
+ {
+ xml_elem_stack_t elems;
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_oc));
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_nc));
+ xml_element_expected(parent, elems);
+ }
+ break;
+ case XML_t:
+ {
+ xml_elem_stack_t elems;
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_is));
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_r));
+ xml_element_expected(parent, elems);
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+}
+
+bool xlsx_revlog_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_nc:
+ {
+ cout << " - new cell value: ";
+ switch (m_cur_cell_type)
+ {
+ case xlsx_ct_boolean:
+ if (m_cur_value != 0.0)
+ cout << "true";
+ else
+ cout << "false";
+ break;
+ case xlsx_ct_numeric:
+ if (m_cur_formula)
+ cout << m_cur_string;
+ else
+ cout << m_cur_value;
+ break;
+ case xlsx_ct_inline_string:
+ cout << m_cur_string;
+ break;
+ default:
+ ;
+ }
+ cout << endl;
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_revlog_context::characters(std::string_view str, bool transient)
+{
+ xml_token_pair_t elem = get_current_element();
+ if (elem.first == NS_ooxml_xlsx)
+ {
+ switch (elem.second)
+ {
+ case XML_v:
+ m_cur_value = to_double(str);
+ break;
+ case XML_f:
+ m_cur_formula = true;
+ // fall through to get the string.
+ case XML_t:
+ m_cur_string = str;
+ if (transient)
+ m_cur_string = get_session_context().spool.intern(m_cur_string).first;
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_revision_context.hpp b/src/liborcus/xlsx_revision_context.hpp
new file mode 100644
index 0000000..a560e07
--- /dev/null
+++ b/src/liborcus/xlsx_revision_context.hpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_REVHEADERS_CONTEXT_HPP
+#define ORCUS_XLSX_REVHEADERS_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "xlsx_types.hpp"
+
+namespace orcus {
+
+class xlsx_revheaders_context : public xml_context_base
+{
+ std::vector<long> m_cur_sheet_ids; /// current sheet ID's.
+public:
+ xlsx_revheaders_context(session_context& session_cxt, const tokens& tokens);
+ virtual ~xlsx_revheaders_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+};
+
+class xlsx_revlog_context : public xml_context_base
+{
+ double m_cur_value;
+ std::string_view m_cur_string;
+ xlsx_cell_t m_cur_cell_type;
+
+ bool m_cur_formula;
+
+public:
+ xlsx_revlog_context(session_context& session_cxt, const tokens& tokens);
+ virtual ~xlsx_revlog_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_session_data.cpp b/src/liborcus/xlsx_session_data.cpp
new file mode 100644
index 0000000..599a136
--- /dev/null
+++ b/src/liborcus/xlsx_session_data.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_session_data.hpp"
+
+namespace orcus {
+
+xlsx_session_data::formula::formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column,
+ std::string_view _exp) :
+ sheet(_sheet), exp(_exp)
+{
+ ref.column = _column;
+ ref.row = _row;
+}
+
+xlsx_session_data::array_formula::array_formula(
+ spreadsheet::sheet_t _sheet, const spreadsheet::range_t& _ref, std::string_view _exp) :
+ sheet(_sheet),
+ ref(_ref),
+ exp(_exp),
+ results(
+ std::make_shared<range_formula_results>(
+ ref.last.row-ref.first.row+1,
+ ref.last.column-ref.first.column+1))
+{
+}
+
+xlsx_session_data::shared_formula::shared_formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column, size_t _identifier) :
+ sheet(_sheet), row(_row), column(_column), identifier(_identifier), master(false) {}
+
+xlsx_session_data::shared_formula::shared_formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column,
+ size_t _identifier, std::string_view _formula) :
+ sheet(_sheet), row(_row), column(_column),
+ identifier(_identifier), formula(_formula), master(true) {}
+
+xlsx_session_data::~xlsx_session_data() = default;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_session_data.hpp b/src/liborcus/xlsx_session_data.hpp
new file mode 100644
index 0000000..af254d0
--- /dev/null
+++ b/src/liborcus/xlsx_session_data.hpp
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XLSX_SESSION_DATA_HPP
+#define INCLUDED_ORCUS_XLSX_SESSION_DATA_HPP
+
+#include "session_context.hpp"
+#include "formula_result.hpp"
+
+#include "orcus/spreadsheet/types.hpp"
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <unordered_map>
+
+namespace orcus {
+
+/**
+ * Collection of global data that need to be persistent across different
+ * parts during a single import session.
+ */
+struct xlsx_session_data : public session_context::custom_data
+{
+ struct formula
+ {
+ spreadsheet::sheet_t sheet;
+ spreadsheet::address_t ref;
+ std::string exp;
+
+ formula_result result;
+
+ formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column,
+ std::string_view _exp);
+ };
+
+ struct array_formula
+ {
+ spreadsheet::sheet_t sheet;
+ spreadsheet::range_t ref;
+ std::string exp;
+
+ std::shared_ptr<range_formula_results> results;
+
+ array_formula(
+ spreadsheet::sheet_t sheet, const spreadsheet::range_t& ref,
+ std::string_view exp);
+ };
+
+ struct shared_formula
+ {
+ spreadsheet::sheet_t sheet;
+ spreadsheet::row_t row;
+ spreadsheet::col_t column;
+ size_t identifier;
+ std::string formula;
+ bool master;
+
+ formula_result result;
+
+ shared_formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column,
+ size_t _identifier);
+
+ shared_formula(
+ spreadsheet::sheet_t _sheet, spreadsheet::row_t _row, spreadsheet::col_t _column,
+ size_t _identifier, std::string_view _formula);
+ };
+
+ typedef std::vector<std::unique_ptr<formula>> formulas_type;
+ typedef std::vector<std::unique_ptr<array_formula>> array_formulas_type;
+ typedef std::vector<std::unique_ptr<shared_formula>> shared_formulas_type;
+ typedef std::unordered_map<std::string_view, spreadsheet::sheet_t> sheet_name_map_type;
+
+ formulas_type m_formulas;
+ array_formulas_type m_array_formulas;
+ shared_formulas_type m_shared_formulas;
+ string_pool m_formula_result_strings;
+
+ virtual ~xlsx_session_data();
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_shared_strings_context.cpp b/src/liborcus/xlsx_shared_strings_context.cpp
new file mode 100644
index 0000000..29fac3e
--- /dev/null
+++ b/src/liborcus/xlsx_shared_strings_context.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_shared_strings_context.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "xlsx_helper.hpp"
+#include "xml_context_global.hpp"
+
+#include <orcus/spreadsheet/import_interface.hpp>
+#include <orcus/measurement.hpp>
+
+#include <optional>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+class shared_strings_root_attr_parser
+{
+public:
+ shared_strings_root_attr_parser() : m_count(0), m_unique_count(0) {}
+
+ void operator() (const xml_token_attr_t &attr)
+ {
+ switch (attr.name)
+ {
+ case XML_count:
+ m_count = to_long(attr.value);
+ break;
+ case XML_uniqueCount:
+ m_unique_count = to_long(attr.value);
+ break;
+ }
+ }
+
+ shared_strings_root_attr_parser& operator= (const shared_strings_root_attr_parser& r)
+ {
+ m_count = r.m_count;
+ m_unique_count = r.m_unique_count;
+ return *this;
+ }
+
+ size_t get_count() const { return m_count; }
+ size_t get_unique_count() const { return m_unique_count; }
+private:
+ size_t m_count;
+ size_t m_unique_count;
+};
+
+}
+
+xlsx_shared_strings_context::xlsx_shared_strings_context(session_context& session_cxt, const tokens& tokens, spreadsheet::iface::import_shared_strings* strings) :
+ xml_context_base(session_cxt, tokens), mp_strings(strings), m_in_segments(false) {}
+
+xlsx_shared_strings_context::~xlsx_shared_strings_context() {}
+
+void xlsx_shared_strings_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ switch (name)
+ {
+ case XML_sst:
+ {
+ // root element for the shared string part.
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+
+ shared_strings_root_attr_parser func;
+ func = for_each(attrs.begin(), attrs.end(), func);
+
+ if (get_config().debug)
+ std::cout << "count: " << func.get_count() << " unique count: " << func.get_unique_count() << std::endl;
+ }
+ break;
+ case XML_si:
+ // single shared string entry.
+ m_in_segments = false;
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_sst);
+ break;
+ case XML_r:
+ // rich text run
+ m_in_segments = true;
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_si);
+ break;
+ case XML_rPr:
+ // rich text run property
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_r);
+ break;
+ case XML_b:
+ // bold
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ break;
+ case XML_i:
+ // italic
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ break;
+ case XML_sz:
+ {
+ // font size
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ std::string_view s = for_each(attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_val)).get_value();
+ double point = to_double(s);
+ mp_strings->set_segment_font_size(point);
+ }
+ break;
+ case XML_color:
+ {
+ // font color
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+
+ std::optional<std::string_view> rgb;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ rgb = attr.value;
+ break;
+ case XML_theme:
+ // TODO : handle this.
+ break;
+ }
+ }
+
+ if (rgb)
+ {
+ ss::color_elem_t alpha;
+ ss::color_elem_t red;
+ ss::color_elem_t green;
+ ss::color_elem_t blue;
+ if (to_rgb(*rgb, alpha, red, green, blue))
+ mp_strings->set_segment_font_color(alpha, red, green, blue);
+ }
+ }
+ break;
+ case XML_rFont:
+ {
+ // font
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ std::string_view font = for_each(attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_val)).get_value();
+ mp_strings->set_segment_font_name(font);
+ }
+ break;
+ case XML_family:
+ // font family
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ break;
+ case XML_scheme:
+ // font scheme
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_rPr);
+ break;
+ case XML_t:
+ {
+ // actual text stored as its content.
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_r },
+ { NS_ooxml_xlsx, XML_rPh },
+ { NS_ooxml_xlsx, XML_si },
+ };
+ xml_element_expected(parent, expected);
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+}
+
+bool xlsx_shared_strings_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ switch (name)
+ {
+ case XML_t:
+ break;
+ case XML_b:
+ mp_strings->set_segment_bold(true);
+ break;
+ case XML_i:
+ mp_strings->set_segment_italic(true);
+ break;
+ case XML_r:
+ mp_strings->append_segment(m_cur_str);
+ break;
+ case XML_si:
+ {
+ if (m_in_segments)
+ // commit all formatted segments.
+ mp_strings->commit_segments();
+ else
+ {
+ // unformatted text should only have one text segment.
+ mp_strings->append(m_cur_str);
+ }
+ }
+ break;
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_shared_strings_context::characters(std::string_view str, bool transient)
+{
+ xml_token_pair_t cur_token = get_current_element();
+ if (cur_token.first == NS_ooxml_xlsx && cur_token.second == XML_t)
+ {
+ m_cur_str = str;
+
+ // In case the string contains carriage returns (CRs), remove them.
+ m_cell_buffer.reset();
+ const char* p = m_cur_str.data();
+ const char* p_end = p + m_cur_str.size();
+ const char* p0 = nullptr;
+
+ for (; p != p_end; ++p)
+ {
+ if (!p0)
+ p0 = p;
+
+ if (*p == 0x0D)
+ {
+ // Append the segment up to this CR, and skip the CR.
+ m_cell_buffer.append(p0, std::distance(p0, p));
+ p0 = nullptr;
+ }
+ }
+
+ if (!m_cell_buffer.empty())
+ {
+ // This string contains at least one CR.
+
+ if (p0)
+ // Append the tail end.
+ m_cell_buffer.append(p0, std::distance(p0, p));
+
+ m_cur_str = m_pool.intern(m_cell_buffer.str()).first;
+ transient = false;
+ }
+
+ if (transient)
+ m_cur_str = m_pool.intern(m_cur_str).first;
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_shared_strings_context.hpp b/src/liborcus/xlsx_shared_strings_context.hpp
new file mode 100644
index 0000000..b10d9fd
--- /dev/null
+++ b/src/liborcus/xlsx_shared_strings_context.hpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <orcus/spreadsheet/types.hpp>
+#include <orcus/string_pool.hpp>
+#include <orcus/cell_buffer.hpp>
+
+#include "xml_context_base.hpp"
+#include "xlsx_types.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+ class import_shared_strings;
+}}
+
+/**
+ * Context for xl/sharedStrings.xml part.
+ */
+class xlsx_shared_strings_context : public xml_context_base
+{
+public:
+ xlsx_shared_strings_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_shared_strings* strings);
+ virtual ~xlsx_shared_strings_context();
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+private:
+ spreadsheet::iface::import_shared_strings* mp_strings = nullptr;
+ string_pool m_pool;
+ cell_buffer m_cell_buffer;
+ std::string_view m_cur_str;
+ bool m_in_segments;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_sheet_context.cpp b/src/liborcus/xlsx_sheet_context.cpp
new file mode 100644
index 0000000..1363c51
--- /dev/null
+++ b/src/liborcus/xlsx_sheet_context.cpp
@@ -0,0 +1,943 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_sheet_context.hpp"
+#include "xlsx_session_data.hpp"
+#include "xlsx_types.hpp"
+#include "ooxml_global.hpp"
+#include "ooxml_schemas.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "xml_context_global.hpp"
+#include "orcus/exception.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+#include "orcus/spreadsheet/import_interface_view.hpp"
+#include "orcus/measurement.hpp"
+
+#include <mdds/sorted_string_map.hpp>
+
+#include <algorithm>
+#include <sstream>
+#include <vector>
+#include <optional>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace sheet_pane {
+
+using map_type = mdds::sorted_string_map<ss::sheet_pane_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "bottomLeft", ss::sheet_pane_t::bottom_left },
+ { "bottomRight", ss::sheet_pane_t::bottom_right },
+ { "topLeft", ss::sheet_pane_t::top_left },
+ { "topRight", ss::sheet_pane_t::top_right },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::sheet_pane_t::unspecified);
+ return mt;
+}
+
+}
+
+namespace pane_state {
+
+using map_type = mdds::sorted_string_map<ss::pane_state_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "frozen", ss::pane_state_t::frozen },
+ { "frozenSplit", ss::pane_state_t::frozen_split },
+ { "split", ss::pane_state_t::split },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::pane_state_t::unspecified);
+ return mt;
+}
+
+} // namespace pane_state
+
+namespace formula_type {
+
+using map_type = mdds::sorted_string_map<ss::formula_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "array", ss::formula_t::array },
+ { "dataTable", ss::formula_t::data_table },
+ { "normal", ss::formula_t::normal },
+ { "shared", ss::formula_t::shared },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::formula_t::unknown);
+ return mt;
+}
+
+} // namespace formula_type
+
+} // anonymous namespace
+
+xlsx_sheet_context::formula::formula() :
+ type(ss::formula_t::unknown),
+ str(),
+ data_table_ref1(),
+ data_table_ref2(),
+ shared_id(-1),
+ data_table_2d(false),
+ data_table_row_based(false),
+ data_table_ref1_deleted(false),
+ data_table_ref2_deleted(false)
+{
+ ref.first.column = -1;
+ ref.first.row = -1;
+ ref.last = ref.first;
+}
+
+void xlsx_sheet_context::formula::reset()
+{
+ *this = formula();
+}
+
+xlsx_sheet_context::xlsx_sheet_context(
+ session_context& session_cxt, const tokens& tokens, ss::sheet_t sheet_id,
+ ss::iface::import_reference_resolver& resolver,
+ ss::iface::import_sheet& sheet) :
+ xml_context_base(session_cxt, tokens),
+ m_resolver(resolver),
+ m_sheet(sheet),
+ m_sheet_id(sheet_id),
+ m_cur_row(-1),
+ m_cur_col(-1),
+ m_cur_cell_type(xlsx_ct_numeric),
+ m_cur_cell_xf(0),
+ m_cxt_autofilter(session_cxt, tokens, m_resolver),
+ m_cxt_cond_format(session_cxt, tokens, m_sheet.get_conditional_format())
+{
+ register_child(&m_cxt_autofilter);
+ register_child(&m_cxt_cond_format);
+
+ init_ooxml_context(*this);
+}
+
+xlsx_sheet_context::~xlsx_sheet_context()
+{
+}
+
+xml_context_base* xlsx_sheet_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx && name == XML_autoFilter)
+ {
+ m_cxt_autofilter.reset();
+ return &m_cxt_autofilter;
+ }
+ else if (ns == NS_ooxml_xlsx && name == XML_conditionalFormatting)
+ {
+ m_cxt_cond_format.reset();
+ return &m_cxt_cond_format;
+ }
+ return nullptr;
+}
+
+void xlsx_sheet_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (!child)
+ return;
+
+ if (ns == NS_ooxml_xlsx && name == XML_autoFilter)
+ {
+ ss::iface::import_auto_filter* af = m_sheet.get_auto_filter();
+ if (!af)
+ return;
+
+ const xlsx_autofilter_context& cxt = static_cast<const xlsx_autofilter_context&>(*child);
+ cxt.push_to_model(*af);
+ }
+}
+
+void xlsx_sheet_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_worksheet:
+ {
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+ break;
+ }
+ case XML_cols:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_col:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_cols);
+ start_element_col(attrs);
+ break;
+ }
+ case XML_dimension:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_mergeCells:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_mergeCell:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_mergeCells);
+
+ ss::iface::import_sheet_properties* sheet_props = m_sheet.get_sheet_properties();
+ if (sheet_props)
+ {
+ // ref contains merged range in A1 reference style.
+ std::string_view ref = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_ref)).get_value();
+
+ ss::src_range_t range = m_resolver.resolve_range(ref);
+ sheet_props->set_merge_cell_range(to_rc_range(range));
+ }
+ break;
+ }
+ case XML_pageMargins:
+ {
+ xml_elem_stack_t elems;
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_worksheet));
+ elems.push_back(xml_token_pair_t(NS_ooxml_xlsx, XML_customSheetView));
+ xml_element_expected(parent, elems);
+ break;
+ }
+ case XML_sheetViews:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_sheetView:
+ start_element_sheet_view(parent, attrs);
+ break;
+ case XML_selection:
+ start_element_selection(parent, attrs);
+ break;
+ case XML_pane:
+ start_element_pane(parent, attrs);
+ break;
+ case XML_sheetData:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_sheetFormatPr:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_row:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_sheetData);
+ start_element_row(attrs);
+ break;
+ }
+ case XML_c:
+ {
+ start_element_cell(parent, attrs);
+ break;
+ }
+ case XML_f:
+ start_element_formula(parent, attrs);
+ break;
+ case XML_v:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_c);
+ break;
+ case XML_tableParts:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_worksheet);
+ break;
+ case XML_tablePart:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_tableParts);
+
+ // The rid string must be pooled to the session context's string
+ // pool as it is used long after thet sheet context is deleted.
+ single_attr_getter func(get_session_context().spool, NS_ooxml_r, XML_id);
+ std::string_view rid = for_each(attrs.begin(), attrs.end(), func).get_value();
+
+ std::unique_ptr<xlsx_rel_table_info> p(new xlsx_rel_table_info);
+ p->sheet_interface = &m_sheet;
+ m_rel_extras.data.insert(
+ opc_rel_extras_t::map_type::value_type(rid, std::move(p)));
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool xlsx_sheet_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_c:
+ end_element_cell();
+ break;
+ case XML_f:
+ m_cur_formula.str = m_cur_str;
+ break;
+ case XML_v:
+ m_cur_value = m_cur_str;
+ break;
+ default:
+ ;
+ }
+ }
+
+ m_cur_str = std::string_view{};
+ return pop_stack(ns, name);
+}
+
+void xlsx_sheet_context::characters(std::string_view str, bool transient)
+{
+ m_cur_str = intern_in_context(str, transient);
+}
+
+void xlsx_sheet_context::start_element_formula(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ const xml_elem_set_t expected = {
+ { NS_ooxml_xlsx, XML_c },
+ { NS_mso_x14, XML_cfRule },
+ };
+ xml_element_expected(parent, expected);
+
+ m_cur_formula.reset();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_t:
+ m_cur_formula.type = formula_type::get().find(attr.value);
+ break;
+ case XML_ref:
+ m_cur_formula.ref = to_rc_range(m_resolver.resolve_range(attr.value));
+ break;
+ case XML_si:
+ m_cur_formula.shared_id = to_long(attr.value);
+ break;
+ case XML_dt2D:
+ m_cur_formula.data_table_2d = to_long(attr.value) != 0;
+ break;
+ case XML_dtr:
+ m_cur_formula.data_table_row_based = to_long(attr.value) != 0;
+ break;
+ case XML_del1:
+ m_cur_formula.data_table_ref1_deleted = to_long(attr.value) != 0;
+ break;
+ case XML_del2:
+ m_cur_formula.data_table_ref2_deleted = to_long(attr.value) != 0;
+ break;
+ case XML_r1:
+ m_cur_formula.data_table_ref1 = intern_in_context(attr);
+ break;
+ case XML_r2:
+ m_cur_formula.data_table_ref2 = intern_in_context(attr);
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+void xlsx_sheet_context::start_element_sheet_view(
+ const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_sheetViews);
+
+ ss::iface::import_sheet_view* view = m_sheet.get_sheet_view();
+ if (!view)
+ return;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (!attr.ns || attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_tabSelected:
+ {
+ bool v = to_bool(attr.value);
+ if (v)
+ // This sheet is active.
+ view->set_sheet_active();
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ }
+}
+
+void xlsx_sheet_context::start_element_selection(
+ const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_elem_stack_t elems;
+ elems.emplace_back(NS_ooxml_xlsx, XML_sheetView);
+ elems.emplace_back(NS_ooxml_xlsx, XML_customSheetView);
+ xml_element_expected(parent, elems);
+
+ ss::iface::import_sheet_view* view = m_sheet.get_sheet_view();
+ if (!view)
+ return;
+
+ // example: <selection pane="topRight" activeCell="H2" sqref="H2:L2"/>
+
+ ss::sheet_pane_t pane = ss::sheet_pane_t::unspecified;
+ ss::range_t range;
+ range.first.column = -1;
+ range.first.row = -1;
+ range.last = range.first;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (!attr.ns || attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_pane:
+ {
+ pane = sheet_pane::get().find(attr.value);
+ break;
+ }
+ case XML_activeCell:
+ // Single cell where the cursor is. Ignore this for now.
+ break;
+ case XML_sqref:
+ {
+ // Single cell address for a non-range cursor, or range
+ // address if a range selection is present.
+ range = to_rc_range(m_resolver.resolve_range(attr.value));
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ }
+
+ if (pane == ss::sheet_pane_t::unspecified)
+ pane = ss::sheet_pane_t::top_left;
+
+ view->set_selected_range(pane, range);
+}
+
+void xlsx_sheet_context::start_element_pane(
+ const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xml_elem_stack_t elems;
+ elems.emplace_back(NS_ooxml_xlsx, XML_sheetView);
+ elems.emplace_back(NS_ooxml_xlsx, XML_customSheetView);
+ xml_element_expected(parent, elems);
+
+ ss::iface::import_sheet_view* view = m_sheet.get_sheet_view();
+ if (!view)
+ return;
+
+ // <pane xSplit="4" ySplit="8" topLeftCell="E9" activePane="bottomRight" state="frozen"/>
+
+ double xsplit = 0.0, ysplit = 0.0;
+ ss::address_t top_left_cell;
+ ss::sheet_pane_t active_pane = ss::sheet_pane_t::unspecified;
+ ss::pane_state_t pane_state = ss::pane_state_t::unspecified;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_xSplit:
+ xsplit = to_double(attr.value);
+ break;
+ case XML_ySplit:
+ ysplit = to_double(attr.value);
+ break;
+ case XML_topLeftCell:
+ top_left_cell = to_rc_address(m_resolver.resolve_address(attr.value));
+ break;
+ case XML_activePane:
+ active_pane = sheet_pane::get().find(attr.value);
+ break;
+ case XML_state:
+ pane_state = pane_state::get().find(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (active_pane == ss::sheet_pane_t::unspecified)
+ active_pane = ss::sheet_pane_t::top_left;
+
+ if (pane_state == ss::pane_state_t::unspecified)
+ pane_state = ss::pane_state_t::split;
+
+ switch (pane_state)
+ {
+ case ss::pane_state_t::frozen:
+ view->set_frozen_pane(xsplit, ysplit, top_left_cell, active_pane);
+ break;
+ case ss::pane_state_t::split:
+ view->set_split_pane(xsplit, ysplit, top_left_cell, active_pane);
+ break;
+ case ss::pane_state_t::frozen_split:
+ warn("FIXME: frozen-split state not yet handled.");
+ break;
+ default:
+ ;
+ }
+}
+
+void xlsx_sheet_context::start_element_cell(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs)
+{
+ xlsx_cell_t cell_type = xlsx_ct_numeric;
+ ss::address_t address;
+ address.column = 0;
+ address.row = 0;
+ size_t xf = 0;
+ bool contains_address = false;
+
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_row);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_r:
+ // cell address in A1 notation.
+ address = to_rc_address(
+ m_resolver.resolve_address(attr.value));
+
+ contains_address = true;
+ break;
+ case XML_t:
+ // cell type
+ cell_type = to_xlsx_cell_type(attr.value);
+ break;
+ case XML_s:
+ // cell style
+ xf = to_long(attr.value);
+ break;
+ }
+ }
+
+ if (contains_address)
+ {
+ if (m_cur_row != address.row)
+ {
+ std::ostringstream os;
+ os << "row numbers differ! (current=" << m_cur_row << ")";
+ throw xml_structure_error(os.str());
+ }
+
+ m_cur_col = address.column;
+ }
+ else
+ {
+ ++m_cur_col;
+ }
+
+ m_cur_cell_type = cell_type;
+ m_cur_cell_xf = xf;
+}
+
+void xlsx_sheet_context::start_element_col(const xml_token_attrs_t& attrs)
+{
+ long col_min = 0; // 1-based
+ long col_max = 0; // 1-based
+ bool col_hidden = false;
+ std::optional<double> col_width;
+ std::optional<std::size_t> xfid;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.value.empty())
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_min:
+ col_min = to_long(attr.value);
+ break;
+ case XML_max:
+ col_max = to_long(attr.value);
+ break;
+ case XML_width:
+ col_width = to_double(attr.value);
+ break;
+ case XML_hidden:
+ col_hidden = to_long(attr.value);
+ break;
+ case XML_style:
+ xfid = to_long(attr.value);
+ break;
+ }
+ }
+
+ if (!col_min || !col_max || col_min > col_max)
+ {
+ std::ostringstream os;
+ os << "column element has invalid column indices: (min=" << col_min << "; max=" << col_max << ")";
+ warn(os.str());
+ return;
+ }
+
+ if (xfid)
+ m_sheet.set_column_format(col_min - 1, col_max - col_min + 1, *xfid);
+
+ ss::iface::import_sheet_properties* sheet_props = m_sheet.get_sheet_properties();
+ if (sheet_props)
+ {
+ if (col_width)
+ sheet_props->set_column_width(
+ col_min - 1, col_max - col_min + 1, *col_width, length_unit_t::xlsx_column_digit);
+
+ sheet_props->set_column_hidden(col_min - 1, col_max - col_min + 1, col_hidden);
+ }
+}
+
+void xlsx_sheet_context::start_element_row(const xml_token_attrs_t& attrs)
+{
+ std::optional<ss::row_t> row;
+ length_t height;
+ bool hidden = false;
+ bool custom_format = false;
+ std::optional<std::size_t> xfid;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_r:
+ {
+ // row index
+ long this_row = to_long(attr.value);
+ if (!this_row)
+ throw xml_structure_error("row number can never be zero!");
+
+ this_row -= 1; // from 1-based to 0-based.
+ row = this_row;
+ break;
+ }
+ case XML_ht:
+ {
+ height.value = to_double(attr.value);
+ height.unit = length_unit_t::point;
+ break;
+ }
+ case XML_hidden:
+ hidden = to_long(attr.value) != 0;
+ break;
+ case XML_s:
+ xfid = to_long(attr.value);
+ break;
+ case XML_customFormat:
+ custom_format = to_bool(attr.value);
+ break;
+ }
+ }
+
+ if (row)
+ m_cur_row = *row;
+ else
+ ++m_cur_row;
+
+ m_cur_col = -1;
+
+ if (custom_format && xfid)
+ // The specs say we only honor this style id only when the custom format is set.
+ m_sheet.set_row_format(m_cur_row, *xfid);
+
+ ss::iface::import_sheet_properties* sheet_props = m_sheet.get_sheet_properties();
+ if (sheet_props)
+ {
+ if (height.unit != length_unit_t::unknown)
+ sheet_props->set_row_height(m_cur_row, height.value, height.unit);
+
+ sheet_props->set_row_hidden(m_cur_row, hidden);
+ }
+}
+
+void xlsx_sheet_context::end_element_cell()
+{
+ session_context& cxt = get_session_context();
+ auto& session_data = cxt.get_data<xlsx_session_data>();
+
+ bool array_formula_result = handle_array_formula_result(session_data);
+
+ if (array_formula_result)
+ {
+ // Do nothing.
+ }
+ else if (!m_cur_formula.str.empty())
+ {
+ if (m_cur_formula.type == ss::formula_t::shared && m_cur_formula.shared_id >= 0)
+ {
+ // shared formula expression
+ session_data.m_shared_formulas.push_back(
+ std::make_unique<xlsx_session_data::shared_formula>(
+ m_sheet_id, m_cur_row, m_cur_col, m_cur_formula.shared_id,
+ m_cur_formula.str
+ )
+ );
+
+ xlsx_session_data::shared_formula& f = *session_data.m_shared_formulas.back();
+ push_raw_cell_result(f.result, session_data);
+ }
+ else if (m_cur_formula.type == ss::formula_t::array)
+ {
+ // array formula expression
+ session_data.m_array_formulas.push_back(
+ std::make_unique<xlsx_session_data::array_formula>(
+ m_sheet_id, m_cur_formula.ref, m_cur_formula.str
+ )
+ );
+
+ xlsx_session_data::array_formula& af = *session_data.m_array_formulas.back();
+ push_raw_cell_result(*af.results, 0, 0, session_data);
+ m_array_formula_results.push_back(std::make_pair(m_cur_formula.ref, af.results));
+ }
+ else
+ {
+ // normal (non-shared) formula expression
+ session_data.m_formulas.push_back(
+ std::make_unique<xlsx_session_data::formula>(
+ m_sheet_id, m_cur_row, m_cur_col, m_cur_formula.str
+ )
+ );
+
+ xlsx_session_data::formula& f = *session_data.m_formulas.back();
+ push_raw_cell_result(f.result, session_data);
+ }
+ }
+ else if (m_cur_formula.type == ss::formula_t::shared && m_cur_formula.shared_id >= 0)
+ {
+ // shared formula without formula expression
+ session_data.m_shared_formulas.push_back(
+ std::make_unique<xlsx_session_data::shared_formula>(
+ m_sheet_id, m_cur_row, m_cur_col, m_cur_formula.shared_id));
+
+ xlsx_session_data::shared_formula& f = *session_data.m_shared_formulas.back();
+ push_raw_cell_result(f.result, session_data);
+ }
+ else if (m_cur_formula.type == ss::formula_t::data_table)
+ {
+ // Import data table.
+ ss::iface::import_data_table* dt = m_sheet.get_data_table();
+ if (dt)
+ {
+ if (m_cur_formula.data_table_2d)
+ {
+ dt->set_type(ss::data_table_type_t::both);
+ dt->set_range(m_cur_formula.ref);
+ dt->set_first_reference(
+ m_cur_formula.data_table_ref1,
+ m_cur_formula.data_table_ref1_deleted);
+ dt->set_second_reference(
+ m_cur_formula.data_table_ref2,
+ m_cur_formula.data_table_ref2_deleted);
+ }
+ else if (m_cur_formula.data_table_row_based)
+ {
+ dt->set_type(ss::data_table_type_t::row);
+ dt->set_range(m_cur_formula.ref);
+ dt->set_first_reference(
+ m_cur_formula.data_table_ref1,
+ m_cur_formula.data_table_ref1_deleted);
+ }
+ else
+ {
+ dt->set_type(ss::data_table_type_t::column);
+ dt->set_range(m_cur_formula.ref);
+ dt->set_first_reference(
+ m_cur_formula.data_table_ref1,
+ m_cur_formula.data_table_ref1_deleted);
+ }
+ dt->commit();
+ }
+
+ push_raw_cell_value();
+ }
+ else if (!m_cur_value.empty())
+ {
+ push_raw_cell_value();
+ }
+
+ if (m_cur_cell_xf)
+ m_sheet.set_format(m_cur_row, m_cur_col, m_cur_cell_xf);
+
+ // reset cell related parameters.
+ m_cur_value = std::string_view{};
+ m_cur_formula.reset();
+ m_cur_cell_xf = 0;
+ m_cur_cell_type = xlsx_ct_numeric;
+}
+
+void xlsx_sheet_context::push_raw_cell_value()
+{
+ if (m_cur_value.empty())
+ return;
+
+ switch (m_cur_cell_type)
+ {
+ case xlsx_ct_shared_string:
+ {
+ // string cell
+ size_t str_id = to_long(m_cur_value);
+ m_sheet.set_string(m_cur_row, m_cur_col, str_id);
+ }
+ break;
+ case xlsx_ct_numeric:
+ {
+ // value cell
+ double val = to_double(m_cur_value);
+ m_sheet.set_value(m_cur_row, m_cur_col, val);
+ }
+ break;
+ case xlsx_ct_boolean:
+ {
+ // boolean cell
+ bool val = to_long(m_cur_value) != 0;
+ m_sheet.set_bool(m_cur_row, m_cur_col, val);
+ }
+ break;
+ default:
+ warn("unhanlded cell content type");
+ }
+}
+
+void xlsx_sheet_context::push_raw_cell_result(
+ range_formula_results& res, size_t row_offset, size_t col_offset, xlsx_session_data& /*session_data*/) const
+{
+ if (m_cur_value.empty())
+ return;
+
+ switch (m_cur_cell_type)
+ {
+ case xlsx_ct_numeric:
+ {
+ // value cell
+ double val = to_double(m_cur_value);
+ res.set(row_offset, col_offset, val);
+ break;
+ }
+ case xlsx_ct_boolean:
+ {
+ // boolean cell
+ bool val = to_long(m_cur_value) != 0;
+ res.set(row_offset, col_offset, val);
+ break;
+ }
+ default:
+ warn("unhanlded cell content type");
+ }
+}
+
+void xlsx_sheet_context::push_raw_cell_result(formula_result& res, xlsx_session_data& session_data) const
+{
+ switch (m_cur_cell_type)
+ {
+ case xlsx_ct_numeric:
+ res.type = formula_result::result_type::numeric;
+ res.value_numeric = to_double(m_cur_value);
+ break;
+ case xlsx_ct_formula_string:
+ {
+ std::string_view interned = session_data.m_formula_result_strings.intern(m_cur_value).first;
+ res.type = formula_result::result_type::string;
+ res.value_string.p = interned.data();
+ res.value_string.n = interned.size();
+ break;
+ }
+ default:
+ {
+ std::ostringstream os;
+ os << "unhandled cached formula result (type=" << m_cur_cell_type << ")";
+ warn(os.str().data());
+ }
+ }
+}
+
+bool xlsx_sheet_context::handle_array_formula_result(xlsx_session_data& session_data)
+{
+ // See if the current cell is within an array formula range.
+ auto it = m_array_formula_results.begin(), ite = m_array_formula_results.end();
+
+ while (it != ite)
+ {
+ const ss::range_t& ref = it->first;
+
+ if (ref.last.row < m_cur_row)
+ {
+ // If this result range lies above the current row, delete it as
+ // we no longer have use for it.
+
+ m_array_formula_results.erase(it++);
+ continue;
+ }
+
+ if (m_cur_col < ref.first.column || ref.last.column < m_cur_col || m_cur_row < ref.first.row || ref.last.row < m_cur_row)
+ {
+ // This cell is not within this array formula range. Move on to
+ // the next one.
+ ++it;
+ continue;
+ }
+
+ size_t row_offset = m_cur_row - ref.first.row;
+ size_t col_offset = m_cur_col - ref.first.column;
+ range_formula_results& res = *it->second;
+ push_raw_cell_result(res, row_offset, col_offset, session_data);
+
+ return true;
+ }
+
+ return false;
+}
+
+std::string_view xlsx_sheet_context::intern_in_context(const xml_token_attr_t& attr)
+{
+ return intern_in_context(attr.value, attr.transient);
+}
+
+std::string_view xlsx_sheet_context::intern_in_context(const std::string_view& str, bool transient)
+{
+ if (transient)
+ return m_pool.intern(str).first;
+
+ return str;
+}
+
+void xlsx_sheet_context::pop_rel_extras(opc_rel_extras_t& other)
+{
+ m_rel_extras.swap(other);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_sheet_context.hpp b/src/liborcus/xlsx_sheet_context.hpp
new file mode 100644
index 0000000..c91382d
--- /dev/null
+++ b/src/liborcus/xlsx_sheet_context.hpp
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_SHEET_CONTEXT_HPP
+#define ORCUS_XLSX_SHEET_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "ooxml_types.hpp"
+#include "xlsx_types.hpp"
+#include "xlsx_autofilter_context.hpp"
+#include "xlsx_conditional_format_context.hpp"
+
+#include "orcus/spreadsheet/types.hpp"
+#include "orcus/string_pool.hpp"
+
+#include <list>
+
+namespace orcus {
+
+struct session_context;
+struct formula_result;
+struct xlsx_session_data;
+class range_formula_results;
+
+namespace spreadsheet { namespace iface {
+
+class import_sheet;
+class import_reference_resolver;
+
+}}
+
+/**
+ * Top-level context for xl/worksheets/sheet<num>.xml.
+ */
+class xlsx_sheet_context : public xml_context_base
+{
+public:
+
+ struct formula
+ {
+ spreadsheet::formula_t type;
+ spreadsheet::range_t ref; /// formula reference range
+ std::string_view str; /// formula expression string
+ std::string_view data_table_ref1;
+ std::string_view data_table_ref2;
+ int shared_id;
+ bool data_table_2d:1;
+ bool data_table_row_based:1;
+ bool data_table_ref1_deleted:1;
+ bool data_table_ref2_deleted:1;
+ formula();
+
+ void reset();
+ };
+
+ using array_formula_pair_type = std::pair<spreadsheet::range_t, std::shared_ptr<range_formula_results>>;
+ using array_formula_results_type = std::list<array_formula_pair_type>;
+
+ xlsx_sheet_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::sheet_t sheet_id,
+ spreadsheet::iface::import_reference_resolver& resolver,
+ spreadsheet::iface::import_sheet& sheet);
+ virtual ~xlsx_sheet_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ void pop_rel_extras(opc_rel_extras_t& other);
+
+private:
+ void start_element_formula(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_element_sheet_view(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_element_selection(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_element_pane(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_element_cell(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs);
+ void start_element_col(const xml_token_attrs_t& attrs);
+ void start_element_row(const xml_token_attrs_t& attrs);
+
+ void end_element_cell();
+ void push_raw_cell_value();
+ void push_raw_cell_result(range_formula_results& res, size_t row_offset, size_t col_offset, xlsx_session_data& session_data) const;
+ void push_raw_cell_result(formula_result& res, xlsx_session_data& session_data) const;
+
+ /**
+ * See if the current cell is a part of an array formula, and if so, store
+ * its value as a cached result.
+ *
+ * @return true if this is part of an array formula, false otherwise.
+ */
+ bool handle_array_formula_result(xlsx_session_data& session_data);
+
+ /**
+ * Potentially intern a transient attribute string value for the duration
+ * of the current sheet context.
+ */
+ std::string_view intern_in_context(const xml_token_attr_t& attr);
+
+ /**
+ * Potentially intern a transient string value for the duration of the
+ * current sheet context.
+ */
+ std::string_view intern_in_context(const std::string_view& str, bool transient);
+
+private:
+ spreadsheet::iface::import_reference_resolver& m_resolver;
+ spreadsheet::iface::import_sheet& m_sheet; /// sheet model instance for the loaded document.
+ string_pool m_pool;
+ spreadsheet::sheet_t m_sheet_id; /// ID of this sheet.
+ spreadsheet::row_t m_cur_row;
+ spreadsheet::col_t m_cur_col;
+ xlsx_cell_t m_cur_cell_type;
+ size_t m_cur_cell_xf;
+ std::string_view m_cur_str;
+ std::string_view m_cur_value;
+ formula m_cur_formula;
+
+ array_formula_results_type m_array_formula_results;
+
+ /**
+ * Extra data to pass on to subsequent parts via relations.
+ */
+ opc_rel_extras_t m_rel_extras;
+
+ xlsx_autofilter_context m_cxt_autofilter;
+ xlsx_conditional_format_context m_cxt_cond_format;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_sheet_context_test.cpp b/src/liborcus/xlsx_sheet_context_test.cpp
new file mode 100644
index 0000000..20492b5
--- /dev/null
+++ b/src/liborcus/xlsx_sheet_context_test.cpp
@@ -0,0 +1,281 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#include "mock_spreadsheet.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_tokens.hpp"
+#include "ooxml_schemas.hpp"
+#include "xlsx_sheet_context.hpp"
+#include "ooxml_token_constants.hpp"
+#include "xlsx_session_data.hpp"
+#include "orcus/types.hpp"
+#include "orcus/config.hpp"
+
+using namespace orcus;
+using namespace std;
+using namespace orcus::spreadsheet;
+using namespace orcus::spreadsheet::mock;
+
+namespace {
+
+class mock_ref_resolver : public import_reference_resolver
+{
+ virtual src_address_t resolve_address(std::string_view) override
+ {
+ src_address_t ret;
+ ret.sheet = 0;
+ ret.row = 0;
+ ret.column = 0;
+
+ return ret;
+ }
+
+ virtual src_range_t resolve_range(std::string_view) override
+ {
+ src_range_t ret;
+ ret.first.sheet = 0;
+ ret.first.row = 0;
+ ret.first.column = 0;
+ ret.last.sheet = 0;
+ ret.last.row = 0;
+ ret.last.column = 0;
+
+ return ret;
+ }
+};
+
+class mock_array_formula : public import_array_formula
+{
+public:
+ virtual void set_range(const range_t& range) override
+ {
+ assert(range.first.row == 2);
+ assert(range.first.column == 1);
+ assert(range.last.row == 3);
+ assert(range.last.column == 1);
+ }
+
+ virtual void set_formula(formula_grammar_t grammar, std::string_view formula) override
+ {
+ assert(grammar == formula_grammar_t::xlsx);
+ assert(formula == "A1:A2");
+ }
+
+ virtual void set_result_bool(row_t, col_t, bool) override
+ {
+ }
+
+ virtual void set_result_empty(row_t, col_t) override
+ {
+ }
+
+ virtual void set_result_string(row_t, col_t, std::string_view) override
+ {
+ }
+
+ virtual void set_result_value(row_t, col_t, double) override
+ {
+ }
+
+ virtual void commit() override
+ {
+ }
+};
+
+class mock_sheet : public import_sheet
+{
+ mock_array_formula m_array_formula;
+
+public:
+ virtual void set_value(row_t row, col_t col, double val) override
+ {
+ assert(row == -1);
+ assert(col == 0);
+ assert(val == 5.0);
+ }
+
+ virtual void set_bool(row_t row, col_t col, bool val) override
+ {
+ assert(row == -1);
+ assert(col == 0);
+ assert(val == true);
+ }
+
+ virtual iface::import_array_formula* get_array_formula() override
+ {
+ return &m_array_formula;
+ }
+};
+
+class mock_sheet_properties : public import_sheet_properties
+{
+public:
+ void set_column_hidden(col_t col, col_t col_span, bool hidden)
+ {
+ assert(col == 1);
+ assert(col_span == 1);
+ assert(hidden);
+ }
+
+ void set_row_hidden(row_t row, bool hidden)
+ {
+ assert(row == 3);
+ assert(hidden);
+ }
+};
+
+class mock_sheet2 : public import_sheet
+{
+public:
+ virtual import_sheet_properties* get_sheet_properties()
+ {
+ return &m_sheet_prop;
+ }
+
+private:
+ mock_sheet_properties m_sheet_prop;
+};
+
+void test_cell_value()
+{
+ mock_sheet sheet;
+ mock_ref_resolver resolver;
+ session_context cxt(std::make_unique<xlsx_session_data>());
+ config opt(format_t::xlsx);
+ opt.structure_check = false;
+
+ orcus::xlsx_sheet_context context(cxt, orcus::ooxml_tokens, 0, resolver, sheet);
+ context.set_config(opt);
+
+ orcus::xmlns_id_t ns = NS_ooxml_xlsx;
+ orcus::xml_token_t elem = XML_c;
+ orcus::xml_token_attrs_t attrs;
+ context.start_element(ns, elem, attrs);
+
+ {
+ xml_token_attrs_t val_attrs;
+ context.start_element(ns, XML_v, val_attrs);
+ context.characters("5", false);
+ context.end_element(ns, XML_v);
+ }
+
+ context.end_element(ns, elem);
+}
+
+void test_cell_bool()
+{
+ mock_sheet sheet;
+ mock_ref_resolver resolver;
+ session_context cxt(std::make_unique<xlsx_session_data>());
+ config opt(format_t::xlsx);
+ opt.structure_check = false;
+
+ orcus::xlsx_sheet_context context(cxt, orcus::ooxml_tokens, 0, resolver, sheet);
+ context.set_config(opt);
+
+ orcus::xmlns_id_t ns = NS_ooxml_xlsx;
+ orcus::xml_token_t elem = XML_c;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(xml_token_attr_t(NS_ooxml_xlsx, XML_t, "b", false));
+ context.start_element(ns, elem, attrs);
+
+ {
+ xml_token_attrs_t val_attrs;
+ context.start_element(ns, XML_v, val_attrs);
+ context.characters("1", false);
+ context.end_element(ns, XML_v);
+ }
+
+ context.end_element(ns, elem);
+}
+
+void test_array_formula()
+{
+ mock_sheet sheet;
+ mock_ref_resolver resolver;
+ session_context cxt(std::make_unique<xlsx_session_data>());
+ config opt(format_t::xlsx);
+ opt.structure_check = false;
+
+ orcus::xlsx_sheet_context context(cxt, orcus::ooxml_tokens, 0, resolver, sheet);
+ context.set_config(opt);
+
+ orcus::xmlns_id_t ns = NS_ooxml_xlsx;
+ orcus::xml_token_t elem = XML_c;
+ orcus::xml_token_attrs_t attrs;
+ context.start_element(ns, elem, attrs);
+
+ {
+ xml_token_attrs_t formula_attrs;
+ formula_attrs.push_back(xml_token_attr_t(NS_ooxml_xlsx, XML_t, "array", false));
+ formula_attrs.push_back(xml_token_attr_t(NS_ooxml_xlsx, XML_ref, "B3:B4", false));
+ context.start_element(ns, XML_f, formula_attrs);
+ context.characters("A1:A2", false);
+ context.end_element(ns, XML_f);
+ }
+ {
+ xml_token_attrs_t val_attrs;
+ context.start_element(ns, XML_v, val_attrs);
+ context.characters("5", false);
+ context.end_element(ns, XML_v);
+ }
+
+ context.end_element(ns, elem);
+}
+
+void test_hidden_col()
+{
+ mock_sheet2 sheet;
+ mock_ref_resolver resolver;
+ session_context cxt(std::make_unique<xlsx_session_data>());
+ config opt(format_t::xlsx);
+ opt.structure_check = false;
+
+ orcus::xlsx_sheet_context context(cxt, orcus::ooxml_tokens, 0, resolver, sheet);
+ context.set_config(opt);
+
+ orcus::xmlns_id_t ns = NS_ooxml_xlsx;
+ orcus::xml_token_t elem = XML_col;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(orcus::xml_token_attr_t(ns, XML_min, "2", false));
+ attrs.push_back(orcus::xml_token_attr_t(ns, XML_max, "2", false));
+ attrs.push_back(orcus::xml_token_attr_t(ns, XML_hidden, "1", false));
+ context.start_element(ns, elem, attrs);
+ context.end_element(ns, elem);
+}
+
+void test_hidden_row()
+{
+ mock_sheet2 sheet;
+ mock_ref_resolver resolver;
+ session_context cxt(std::make_unique<xlsx_session_data>());
+ config opt(format_t::xlsx);
+ opt.structure_check = false;
+
+ orcus::xlsx_sheet_context context(cxt, orcus::ooxml_tokens, 0, resolver, sheet);
+ context.set_config(opt);
+
+ orcus::xmlns_id_t ns = NS_ooxml_xlsx;
+ orcus::xml_token_t elem = XML_row;
+ orcus::xml_token_attrs_t attrs;
+ attrs.push_back(orcus::xml_token_attr_t(ns, XML_r, "4", false));
+ attrs.push_back(orcus::xml_token_attr_t(ns, XML_hidden, "1", false));
+ context.start_element(ns, elem, attrs);
+ context.end_element(ns, elem);
+}
+
+}
+
+int main()
+{
+ test_cell_value();
+ test_cell_bool();
+ test_array_formula();
+ test_hidden_col();
+ test_hidden_row();
+ return 0;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_styles_context.cpp b/src/liborcus/xlsx_styles_context.cpp
new file mode 100644
index 0000000..29454b1
--- /dev/null
+++ b/src/liborcus/xlsx_styles_context.cpp
@@ -0,0 +1,1055 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_styles_context.hpp"
+#include "impl_utils.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "xlsx_helper.hpp"
+#include "xml_context_global.hpp"
+
+#include <orcus/tokens.hpp>
+#include <orcus/measurement.hpp>
+#include <orcus/spreadsheet/import_interface_styles.hpp>
+
+#include <mdds/sorted_string_map.hpp>
+#include <mdds/global.hpp>
+
+#include <optional>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+namespace border_style {
+
+using map_type = mdds::sorted_string_map<ss::border_style_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "dashDot", ss::border_style_t::dash_dot },
+ { "dashDotDot", ss::border_style_t::dash_dot_dot },
+ { "dashed", ss::border_style_t::dashed },
+ { "dotted", ss::border_style_t::dotted },
+ { "double", ss::border_style_t::double_border },
+ { "hair", ss::border_style_t::hair },
+ { "medium", ss::border_style_t::medium },
+ { "mediumDashDot", ss::border_style_t::medium_dash_dot },
+ { "mediumDashDotDot", ss::border_style_t::medium_dash_dot_dot },
+ { "mediumDashed", ss::border_style_t::medium_dashed },
+ { "none", ss::border_style_t::none },
+ { "slantDashDot", ss::border_style_t::slant_dash_dot },
+ { "thick", ss::border_style_t::thick },
+ { "thin", ss::border_style_t::thin }
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::border_style_t::none);
+ return mt;
+}
+
+} // border_style namespace
+
+namespace fill_pattern {
+
+using map_type = mdds::sorted_string_map<ss::fill_pattern_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "darkDown", ss::fill_pattern_t::dark_down },
+ { "darkGray", ss::fill_pattern_t::dark_gray },
+ { "darkGrid", ss::fill_pattern_t::dark_grid },
+ { "darkHorizontal", ss::fill_pattern_t::dark_horizontal },
+ { "darkTrellis", ss::fill_pattern_t::dark_trellis },
+ { "darkUp", ss::fill_pattern_t::dark_up },
+ { "darkVertical", ss::fill_pattern_t::dark_vertical },
+ { "gray0625", ss::fill_pattern_t::gray_0625 },
+ { "gray125", ss::fill_pattern_t::gray_125 },
+ { "lightDown", ss::fill_pattern_t::light_down },
+ { "lightGray", ss::fill_pattern_t::light_gray },
+ { "lightGrid", ss::fill_pattern_t::light_grid },
+ { "lightHorizontal", ss::fill_pattern_t::light_horizontal },
+ { "lightTrellis", ss::fill_pattern_t::light_trellis },
+ { "lightUp", ss::fill_pattern_t::light_up },
+ { "lightVertical", ss::fill_pattern_t::light_vertical },
+ { "mediumGray", ss::fill_pattern_t::medium_gray },
+ { "none", ss::fill_pattern_t::none },
+ { "solid", ss::fill_pattern_t::solid },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::fill_pattern_t::none);
+ return mt;
+}
+
+} // fill_pattern namespace
+
+namespace underline {
+
+using map_type = mdds::sorted_string_map<ss::underline_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "double", ss::underline_t::double_line },
+ { "doubleAccounting", ss::underline_t::double_accounting },
+ { "none", ss::underline_t::none },
+ { "single", ss::underline_t::single_line },
+ { "singleAccounting", ss::underline_t::single_accounting },
+};
+
+const map_type& get()
+{
+ static const map_type mt(entries, std::size(entries), ss::underline_t::none);
+ return mt;
+}
+
+} // namespace underline
+
+class border_attr_parser
+{
+ ss::border_direction_t m_dir;
+ ss::iface::import_border_style& m_border_style;
+public:
+ border_attr_parser(ss::border_direction_t dir, ss::iface::import_border_style& style) :
+ m_dir(dir), m_border_style(style) {}
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ switch (attr.name)
+ {
+ case XML_style:
+ {
+ m_border_style.set_style(m_dir,
+ border_style::get().find(attr.value.data(), attr.value.size()));
+ break;
+ }
+ }
+ }
+};
+
+std::optional<std::size_t> extract_count(const xml_token_attrs_t& attrs)
+{
+ std::optional<std::size_t> count;
+
+ for (const auto& attr : attrs)
+ {
+ if (attr.ns)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_count:
+ {
+ const char* p_end = nullptr;
+ long v = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end && v >= 0)
+ count = v;
+ break;
+ }
+ }
+ }
+
+ return count;
+}
+
+} // anonymous namespace
+
+xlsx_styles_context::xlsx_styles_context(session_context& session_cxt, const tokens& tokens, ss::iface::import_styles* styles) :
+ xml_context_base(session_cxt, tokens),
+ mp_styles(styles),
+ m_diagonal_up(false), m_diagonal_down(false),
+ m_cur_border_dir(ss::border_direction_t::unknown)
+{
+ static const xml_element_validator::rule rules[] = {
+ // parent element -> child element
+ { XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN, NS_ooxml_xlsx, XML_styleSheet }, // root element
+ { NS_ooxml_xlsx, XML_border, NS_ooxml_xlsx, XML_bottom },
+ { NS_ooxml_xlsx, XML_border, NS_ooxml_xlsx, XML_diagonal },
+ { NS_ooxml_xlsx, XML_border, NS_ooxml_xlsx, XML_left },
+ { NS_ooxml_xlsx, XML_border, NS_ooxml_xlsx, XML_right },
+ { NS_ooxml_xlsx, XML_border, NS_ooxml_xlsx, XML_top },
+ { NS_ooxml_xlsx, XML_borders, NS_ooxml_xlsx, XML_border },
+ { NS_ooxml_xlsx, XML_bottom, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_cellStyleXfs, NS_ooxml_xlsx, XML_xf },
+ { NS_ooxml_xlsx, XML_cellStyles, NS_ooxml_xlsx, XML_cellStyle },
+ { NS_ooxml_xlsx, XML_cellXfs, NS_ooxml_xlsx, XML_xf },
+ { NS_ooxml_xlsx, XML_diagonal, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_dx, NS_ooxml_xlsx, XML_fill },
+ { NS_ooxml_xlsx, XML_dxf, NS_ooxml_xlsx, XML_alignment },
+ { NS_ooxml_xlsx, XML_dxf, NS_ooxml_xlsx, XML_border },
+ { NS_ooxml_xlsx, XML_dxf, NS_ooxml_xlsx, XML_font },
+ { NS_ooxml_xlsx, XML_dxf, NS_ooxml_xlsx, XML_numFmt },
+ { NS_ooxml_xlsx, XML_dxf, NS_ooxml_xlsx, XML_protection },
+ { NS_ooxml_xlsx, XML_end, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_fill, NS_ooxml_xlsx, XML_patternFill },
+ { NS_ooxml_xlsx, XML_fills, NS_ooxml_xlsx, XML_fill },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_b },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_family },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_i },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_name },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_scheme },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_sz },
+ { NS_ooxml_xlsx, XML_font, NS_ooxml_xlsx, XML_u },
+ { NS_ooxml_xlsx, XML_fonts, NS_ooxml_xlsx, XML_font },
+ { NS_ooxml_xlsx, XML_horizontal, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_left, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_mruColors, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_numFmts, NS_ooxml_xlsx, XML_numFmt },
+ { NS_ooxml_xlsx, XML_patternFill, NS_ooxml_xlsx, XML_bgColor },
+ { NS_ooxml_xlsx, XML_patternFill, NS_ooxml_xlsx, XML_fgColor },
+ { NS_ooxml_xlsx, XML_right, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_start, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_stop, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_borders },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_cellStyleXfs },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_cellStyles },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_cellXfs },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_dxfs },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_fills },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_fonts },
+ { NS_ooxml_xlsx, XML_styleSheet, NS_ooxml_xlsx, XML_numFmts },
+ { NS_ooxml_xlsx, XML_top, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_vertical, NS_ooxml_xlsx, XML_color },
+ { NS_ooxml_xlsx, XML_xf, NS_ooxml_xlsx, XML_alignment },
+ { NS_ooxml_xlsx, XML_xf, NS_ooxml_xlsx, XML_protection },
+ };
+
+ init_element_validator(rules, std::size(rules));
+}
+
+xlsx_styles_context::~xlsx_styles_context() = default;
+
+void xlsx_styles_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_styleSheet:
+ {
+ // root element
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+ break;
+ }
+ case XML_fonts:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_count)).get_value();
+ size_t font_count = to_long(ps);
+ mp_styles->set_font_count(font_count);
+ m_font_ids.reserve(font_count);
+ break;
+ }
+ case XML_font:
+ {
+ mp_font = mp_styles->start_font_style();
+ ENSURE_INTERFACE(mp_font, import_font_style);
+ break;
+ }
+ case XML_b:
+ assert(mp_font);
+ mp_font->set_bold(true);
+ break;
+ case XML_i:
+ assert(mp_font);
+ mp_font->set_italic(true);
+ break;
+ case XML_u:
+ {
+ assert(mp_font);
+ ss::underline_t v = ss::underline_t::single_line; // default value
+
+ for (const auto& attr : attrs)
+ {
+ switch (name)
+ {
+ case XML_val:
+ v = underline::get().find(attr.value);
+ break;
+ }
+ }
+
+ mp_font->set_underline(v);
+ break;
+ }
+ case XML_sz:
+ {
+ assert(mp_font);
+ std::optional<double> font_size;
+
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_val:
+ {
+ const char* p_end = nullptr;
+ double v = to_double(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ font_size = v;
+ break;
+ }
+ }
+ }
+
+ if (font_size)
+ mp_font->set_size(*font_size);
+
+ break;
+ }
+ case XML_color:
+ {
+ if (parent.first == NS_ooxml_xlsx)
+ {
+ switch (parent.second)
+ {
+ case XML_top:
+ case XML_bottom:
+ case XML_left:
+ case XML_right:
+ case XML_diagonal:
+ // This color is for a border.
+ start_border_color(attrs);
+ break;
+ case XML_font:
+ start_font_color(attrs);
+ default:
+ ;
+ }
+ }
+ break;
+ }
+ case XML_name:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_val)).get_value();
+ mp_font->set_name(ps);
+ break;
+ }
+ case XML_fills:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_count)).get_value();
+ size_t fill_count = to_long(ps);
+ mp_styles->set_fill_count(fill_count);
+ m_fill_ids.reserve(fill_count);
+ break;
+ }
+ case XML_fill:
+ {
+ mp_fill = mp_styles->start_fill_style();
+ ENSURE_INTERFACE(mp_fill, import_fill_style);
+
+ break;
+ }
+ case XML_patternFill:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_patternType)).get_value();
+ assert(mp_fill);
+ mp_fill->set_pattern_type(fill_pattern::get().find(ps.data(), ps.size()));
+ break;
+ }
+ case XML_fgColor:
+ {
+ assert(mp_fill);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ {
+ ss::color_elem_t alpha;
+ ss::color_elem_t red;
+ ss::color_elem_t green;
+ ss::color_elem_t blue;
+ if (!to_rgb(attr.value, alpha, red, green, blue))
+ // invalid RGB color format.
+ continue;
+
+ mp_fill->set_fg_color(alpha, red, green, blue);
+ break;
+ }
+ case XML_indexed:
+ break;
+ default:
+ if (get_config().debug)
+ std::cerr << "warning: unknown attribute [ " << get_tokens().get_token_name(attr.name) << " ]" << std::endl;
+ }
+ }
+
+ break;
+ }
+ case XML_bgColor:
+ {
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ {
+ ss::color_elem_t alpha;
+ ss::color_elem_t red;
+ ss::color_elem_t green;
+ ss::color_elem_t blue;
+ if (!to_rgb(attr.value, alpha, red, green, blue))
+ // invalid RGB color format.
+ continue;
+
+ mp_fill->set_bg_color(alpha, red, green, blue);
+ break;
+ }
+ case XML_indexed:
+ break;
+ default:
+ if (get_config().debug)
+ std::cerr << "warning: unknown attribute [ " << get_tokens().get_token_name(attr.name) << " ]" << std::endl;
+ }
+ }
+
+ break;
+ }
+ case XML_borders:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_count)).get_value();
+ size_t border_count = to_long(ps);
+ mp_styles->set_border_count(border_count);
+ m_border_ids.reserve(border_count);
+ break;
+ }
+ case XML_border:
+ {
+ start_element_border(attrs);
+
+ mp_border = mp_styles->start_border_style();
+ ENSURE_INTERFACE(mp_border, import_border_style);
+
+ break;
+ }
+ case XML_top:
+ {
+ assert(mp_border);
+ m_cur_border_dir = ss::border_direction_t::top;
+ border_attr_parser func(ss::border_direction_t::top, *mp_border);
+ for_each(attrs.begin(), attrs.end(), func);
+ break;
+ }
+ case XML_bottom:
+ {
+ assert(mp_border);
+ m_cur_border_dir = ss::border_direction_t::bottom;
+ border_attr_parser func(ss::border_direction_t::bottom, *mp_border);
+ for_each(attrs.begin(), attrs.end(), func);
+ break;
+ }
+ case XML_left:
+ {
+ assert(mp_border);
+ m_cur_border_dir = ss::border_direction_t::left;
+ border_attr_parser func(ss::border_direction_t::left, *mp_border);
+ for_each(attrs.begin(), attrs.end(), func);
+ break;
+ }
+ case XML_right:
+ {
+ assert(mp_border);
+ m_cur_border_dir = ss::border_direction_t::right;
+ border_attr_parser func(ss::border_direction_t::right, *mp_border);
+ for_each(attrs.begin(), attrs.end(), func);
+ break;
+ }
+ case XML_diagonal:
+ {
+ start_element_diagonal(attrs);
+ break;
+ }
+ case XML_cellStyleXfs:
+ {
+ if (std::optional<std::size_t> count = extract_count(attrs); count)
+ {
+ mp_styles->set_xf_count(ss::xf_category_t::cell_style, *count);
+ m_cell_style_xf_ids.reserve(*count);
+ }
+
+ mp_xf = mp_styles->start_xf(ss::xf_category_t::cell_style);
+ ENSURE_INTERFACE(mp_xf, import_xf);
+ m_xf_type = ss::xf_category_t::cell_style;
+ break;
+ }
+ case XML_cellXfs:
+ {
+ if (std::optional<std::size_t> count = extract_count(attrs); count)
+ mp_styles->set_xf_count(ss::xf_category_t::cell, *count);
+
+ mp_xf = mp_styles->start_xf(ss::xf_category_t::cell);
+ ENSURE_INTERFACE(mp_xf, import_xf);
+ m_xf_type = ss::xf_category_t::cell;
+ break;
+ }
+ case XML_dxfs:
+ {
+ if (std::optional<std::size_t> count = extract_count(attrs); count)
+ mp_styles->set_xf_count(ss::xf_category_t::differential, *count);
+
+ mp_xf = mp_styles->start_xf(ss::xf_category_t::differential);
+ ENSURE_INTERFACE(mp_xf, import_xf);
+ m_xf_type = ss::xf_category_t::differential;
+ break;
+ }
+ case XML_cellStyles:
+ {
+ std::string_view ps = for_each(
+ attrs.begin(), attrs.end(), single_attr_getter(m_pool, NS_ooxml_xlsx, XML_count)).get_value();
+ if (!ps.empty())
+ {
+ size_t n = strtoul(ps.data(), nullptr, 10);
+ mp_styles->set_cell_style_count(n);
+ }
+ mp_cell_style = mp_styles->start_cell_style();
+ ENSURE_INTERFACE(mp_cell_style, import_cell_style);
+ break;
+ }
+ case XML_cellStyle:
+ {
+ // named cell style, some of which are built-in such as 'Normal'.
+ assert(mp_cell_style);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ mp_cell_style->set_name(attr.value);
+ break;
+ case XML_xfId:
+ {
+ // reference ID to an xf entry in cellStyleXfs
+ const char* p_end = nullptr;
+ size_t n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ {
+ if (n < m_cell_style_xf_ids.size())
+ mp_cell_style->set_xf(m_cell_style_xf_ids[n]);
+ else
+ {
+ std::ostringstream os;
+ os << "out-of-bound cellStyle@xfId: id=" << n << "; count=" << m_cell_style_xf_ids.size();
+ warn(os.str());
+ }
+ }
+ break;
+ }
+ case XML_builtinId:
+ {
+ size_t n = to_long(attr.value);
+ mp_cell_style->set_builtin(n);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case XML_xf:
+ {
+ start_xf(attrs);
+ break;
+ }
+ case XML_protection:
+ {
+ mp_protection = mp_styles->start_cell_protection();
+ ENSURE_INTERFACE(mp_protection, import_cell_protection);
+
+ for (const auto& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_hidden:
+ {
+ bool b = to_long(attr.value) != 0;
+ mp_protection->set_hidden(b);
+ break;
+ }
+ case XML_locked:
+ {
+ bool b = to_long(attr.value) != 0;
+ mp_protection->set_locked(b);
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ case XML_alignment:
+ {
+ assert(mp_xf);
+
+ // 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;
+ bool wrap_text = false;
+ bool shrink_to_fit = false;
+
+ 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;
+ }
+ case XML_wrapText:
+ wrap_text = to_bool(attr.value);
+ break;
+ case XML_shrinkToFit:
+ shrink_to_fit = to_bool(attr.value);
+ break;
+ }
+ }
+
+ mp_xf->set_horizontal_alignment(hor_align);
+ mp_xf->set_vertical_alignment(ver_align);
+ mp_xf->set_wrap_text(wrap_text);
+ mp_xf->set_shrink_to_fit(shrink_to_fit);
+ break;
+ }
+ case XML_numFmts:
+ {
+ std::string_view val =
+ for_each(
+ attrs.begin(), attrs.end(),
+ single_attr_getter(m_pool, NS_ooxml_xlsx, XML_count)).get_value();
+ if (!val.empty())
+ {
+ size_t n = to_long(val);
+ mp_styles->set_number_format_count(n);
+ }
+ break;
+ }
+ case XML_numFmt:
+ start_number_format(attrs);
+ break;
+ default:
+ warn_unhandled();
+ }
+ }
+ else
+ warn_unhandled();
+}
+
+bool xlsx_styles_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ switch (name)
+ {
+ case XML_font:
+ {
+ assert(mp_font);
+ std::size_t id = mp_font->commit();
+ m_font_ids.push_back(id);
+ mp_font = nullptr;
+ break;
+ }
+ case XML_fill:
+ {
+ assert(mp_fill);
+ std::size_t id = mp_fill->commit();
+ m_fill_ids.push_back(id);
+ mp_fill = nullptr;
+ break;
+ }
+ case XML_border:
+ {
+ assert(mp_border);
+ std::size_t id = mp_border->commit();
+ m_border_ids.push_back(id);
+ mp_border = nullptr;
+ break;
+ }
+ case XML_cellStyle:
+ assert(mp_cell_style);
+ mp_cell_style->commit();
+ break;
+ case XML_cellStyles:
+ assert(mp_cell_style);
+ mp_cell_style = nullptr;
+ break;
+ case XML_cellStyleXfs:
+ case XML_cellXfs:
+ case XML_dxfs:
+ assert(mp_xf);
+ mp_xf = nullptr;
+ m_xf_type = ss::xf_category_t::unknown;
+ break;
+ case XML_xf:
+ case XML_dxf:
+ {
+ assert(mp_xf);
+ std::size_t id = mp_xf->commit();
+ switch (m_xf_type)
+ {
+ break;
+ case ss::xf_category_t::cell_style:
+ // only cell style xf ID is referenced.
+ m_cell_style_xf_ids.push_back(id);
+ break;
+ case ss::xf_category_t::cell:
+ case ss::xf_category_t::differential:
+ // not used
+ break;
+ case ss::xf_category_t::unknown:
+ warn("xf entry committed while the current xf category is unknown");
+ break;
+ }
+ break;
+ }
+ case XML_protection:
+ {
+ assert(mp_protection);
+ size_t prot_id = mp_protection->commit();
+ assert(mp_xf);
+ mp_xf->set_protection(prot_id);
+ break;
+ }
+ case XML_numFmt:
+ end_number_format();
+ break;
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_styles_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+ // not used in the styles.xml part.
+}
+
+void xlsx_styles_context::start_number_format(const xml_token_attrs_t& attrs)
+{
+ if (!mp_styles)
+ return;
+
+ mp_numfmt = mp_styles->start_number_format();
+ ENSURE_INTERFACE(mp_numfmt, import_number_format);
+
+ m_cur_numfmt_id.reset();
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_numFmtId:
+ {
+ const char* p_end = nullptr;
+ long id = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end && id >= 0)
+ {
+ mp_numfmt->set_identifier(id);
+ m_cur_numfmt_id = id;
+ }
+ break;
+ }
+ case XML_formatCode:
+ {
+ mp_numfmt->set_code(attr.value);
+ break;
+ }
+ }
+ }
+}
+
+void xlsx_styles_context::start_element_border(const xml_token_attrs_t& attrs)
+{
+ bool diagonal_up = false;
+ bool diagonal_down = false;
+
+ std::for_each(attrs.begin(), attrs.end(),
+ [&diagonal_up,&diagonal_down](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_diagonalDown:
+ // top-left to bottom-right.
+ diagonal_down = to_long(attr.value) != 0;
+ break;
+ case XML_diagonalUp:
+ // bottom-left to top-right.
+ diagonal_up = to_long(attr.value) != 0;
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ m_diagonal_up = diagonal_up;
+ m_diagonal_down = diagonal_down;
+}
+
+void xlsx_styles_context::start_element_diagonal(const xml_token_attrs_t& attrs)
+{
+ assert(mp_border);
+
+ m_cur_border_dir = ss::border_direction_t::unknown;
+
+ if (m_diagonal_up)
+ {
+ m_cur_border_dir = m_diagonal_down ?
+ ss::border_direction_t::diagonal :
+ ss::border_direction_t::diagonal_bl_tr;
+ }
+ else
+ {
+ m_cur_border_dir = m_diagonal_down ?
+ ss::border_direction_t::diagonal_tl_br :
+ ss::border_direction_t::unknown;
+ }
+
+ if (m_cur_border_dir == ss::border_direction_t::unknown)
+ return;
+
+ border_attr_parser func(m_cur_border_dir, *mp_border);
+ for_each(attrs.begin(), attrs.end(), func);
+}
+
+void xlsx_styles_context::start_border_color(const xml_token_attrs_t& attrs)
+{
+ assert(mp_border);
+
+ std::optional<std::string_view> rgb;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ rgb = attr.value;
+ break;
+ case XML_theme:
+ // TODO : handle this.
+ break;
+ }
+ }
+
+ if (rgb)
+ {
+ ss::color_elem_t alpha;
+ ss::color_elem_t red;
+ ss::color_elem_t green;
+ ss::color_elem_t blue;
+
+ if (to_rgb(*rgb, alpha, red, green, blue))
+ mp_border->set_color(m_cur_border_dir, alpha, red, green, blue);
+ }
+}
+
+void xlsx_styles_context::start_font_color(const xml_token_attrs_t& attrs)
+{
+ assert(mp_font);
+
+ std::optional<std::string_view> rgb;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_rgb:
+ rgb = attr.value;
+ break;
+ case XML_theme:
+ // TODO : handle this.
+ break;
+ }
+ }
+
+ if (rgb)
+ {
+ ss::color_elem_t alpha;
+ ss::color_elem_t red;
+ ss::color_elem_t green;
+ ss::color_elem_t blue;
+ if (to_rgb(*rgb, alpha, red, green, blue))
+ mp_font->set_color(alpha, red, green, blue);
+ }
+}
+
+void xlsx_styles_context::start_xf(const xml_token_attrs_t& attrs)
+{
+ assert(mp_xf);
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ switch (attr.name)
+ {
+ case XML_borderId:
+ {
+ const char* p_end = nullptr;
+ size_t n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ {
+ if (n < m_border_ids.size())
+ mp_xf->set_border(m_border_ids[n]);
+ else
+ {
+ std::ostringstream os;
+ os << "out-of-bound borderId: id=" << n << "; count=" << m_border_ids.size();
+ warn(os.str());
+ }
+ }
+ break;
+ }
+ case XML_fillId:
+ {
+ const char* p_end = nullptr;
+ size_t n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ {
+ if (n < m_fill_ids.size())
+ mp_xf->set_fill(m_fill_ids[n]);
+ else
+ {
+ std::ostringstream os;
+ os << "out-of-bound fillId: id=" << n << "; count=" << m_fill_ids.size();
+ warn(os.str());
+ }
+ }
+ break;
+ }
+ case XML_fontId:
+ {
+ const char* p_end = nullptr;
+ size_t n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ {
+ if (n < m_font_ids.size())
+ mp_xf->set_font(m_font_ids[n]);
+ else
+ {
+ std::ostringstream os;
+ os << "out-of-bound fontId: id=" << n << "; count=" << m_font_ids.size();
+ warn(os.str());
+ }
+ }
+ break;
+ }
+ case XML_numFmtId:
+ {
+ const char* p_end = nullptr;
+ long n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end && n >= 0)
+ {
+ auto it = m_numfmt_ids.find(n);
+ if (it == m_numfmt_ids.end())
+ {
+ std::ostringstream os;
+ os << "no entry for xf@numFmtId = " << n;
+ warn(os.str());
+ }
+ else
+ mp_xf->set_number_format(it->second);
+ }
+ break;
+ }
+ case XML_xfId:
+ {
+ // reference ID to an xf entry in cellStyleXfs
+ const char* p_end = nullptr;
+ size_t n = to_long(attr.value, &p_end);
+ if (attr.value.data() < p_end)
+ {
+ if (n < m_cell_style_xf_ids.size())
+ mp_xf->set_style_xf(m_cell_style_xf_ids[n]);
+ else
+ {
+ std::ostringstream os;
+ os << "out-of-bound xf@xfId: id=" << n << "; count=" << m_cell_style_xf_ids.size();
+ warn(os.str());
+ }
+ }
+ 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;
+ }
+ }
+ }
+}
+
+void xlsx_styles_context::end_number_format()
+{
+ if (!mp_styles)
+ return;
+
+ assert(mp_numfmt);
+ std::size_t id = mp_numfmt->commit();
+ mp_numfmt = nullptr;
+
+ if (m_cur_numfmt_id)
+ {
+ auto res = m_numfmt_ids.insert_or_assign(*m_cur_numfmt_id, id);
+ if (!res.second)
+ {
+ // assigned to an existing key
+ std::ostringstream os;
+ os << "number format id of " << *m_cur_numfmt_id << " referenced multiple times";
+ warn(os.str());
+ }
+ }
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_styles_context.hpp b/src/liborcus/xlsx_styles_context.hpp
new file mode 100644
index 0000000..3cd8310
--- /dev/null
+++ b/src/liborcus/xlsx_styles_context.hpp
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+#include "xlsx_types.hpp"
+
+#include <orcus/string_pool.hpp>
+
+#include <vector>
+#include <unordered_map>
+#include <optional>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+ class import_styles;
+ class import_font_style;
+ class import_fill_style;
+ class import_border_style;
+ class import_cell_protection;
+ class import_number_format;
+ class import_xf;
+ class import_cell_style;
+}}
+
+/**
+ * Context for xl/styles.xml part. This part contains various styles used
+ * in the sheets.
+ */
+class xlsx_styles_context : public xml_context_base
+{
+public:
+ xlsx_styles_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_styles* import_styles);
+ virtual ~xlsx_styles_context();
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+private:
+ void start_number_format(const xml_token_attrs_t& attrs);
+
+ void start_element_border(const xml_token_attrs_t& attrs);
+ void start_element_diagonal(const xml_token_attrs_t& attrs);
+ void start_border_color(const xml_token_attrs_t& attrs);
+ void start_font_color(const xml_token_attrs_t& attrs);
+ void start_xf(const xml_token_attrs_t& attrs);
+
+ void end_number_format();
+
+private:
+ spreadsheet::iface::import_styles* mp_styles = nullptr;
+ spreadsheet::iface::import_font_style* mp_font = nullptr;
+ spreadsheet::iface::import_fill_style* mp_fill = nullptr;
+ 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;
+ spreadsheet::iface::import_cell_style* mp_cell_style = nullptr;
+ spreadsheet::xf_category_t m_xf_type = spreadsheet::xf_category_t::unknown;
+
+ string_pool m_pool;
+ bool m_diagonal_up;
+ bool m_diagonal_down;
+ spreadsheet::border_direction_t m_cur_border_dir;
+
+ std::vector<std::size_t> m_font_ids;
+ std::vector<std::size_t> m_fill_ids;
+ std::vector<std::size_t> m_border_ids;
+ std::vector<std::size_t> m_cell_style_xf_ids;
+ // numFmt@numFmtId values as keys
+ std::unordered_map<std::size_t, std::size_t> m_numfmt_ids;
+ std::optional<std::size_t> m_cur_numfmt_id;
+};
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_table_context.cpp b/src/liborcus/xlsx_table_context.cpp
new file mode 100644
index 0000000..06f16ce
--- /dev/null
+++ b/src/liborcus/xlsx_table_context.cpp
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_table_context.hpp"
+#include "xlsx_autofilter_context.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_global.hpp"
+#include "session_context.hpp"
+#include "xml_context_global.hpp"
+
+#include "orcus/measurement.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+
+#include <iostream>
+#include <optional>
+
+namespace ss = orcus::spreadsheet;
+
+namespace orcus {
+
+namespace {
+
+class table_column_attr_parser
+{
+ string_pool* m_pool;
+
+ long m_id;
+ std::string_view m_name;
+ std::string_view m_totals_row_label;
+ spreadsheet::totals_row_function_t m_totals_row_func;
+
+public:
+ table_column_attr_parser(string_pool* pool) :
+ m_pool(pool), m_id(-1), m_totals_row_func(spreadsheet::totals_row_function_t::none) {}
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_id:
+ m_id = to_long(attr.value);
+ break;
+ case XML_name:
+ m_name = attr.value;
+ if (attr.transient)
+ m_name = m_pool->intern(m_name).first;
+ break;
+ case XML_totalsRowLabel:
+ m_totals_row_label = attr.value;
+ if (attr.transient)
+ m_totals_row_label = m_pool->intern(m_totals_row_label).first;
+ break;
+ case XML_totalsRowFunction:
+ m_totals_row_func = spreadsheet::to_totals_row_function_enum(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+
+ long get_id() const { return m_id; }
+ std::string_view get_name() const { return m_name; }
+ std::string_view get_totals_row_label() const { return m_totals_row_label; }
+ spreadsheet::totals_row_function_t get_totals_row_function() const { return m_totals_row_func; }
+};
+
+class table_style_info_attr_parser
+{
+ spreadsheet::iface::import_table* mp_table;
+ bool m_debug;
+
+public:
+ table_style_info_attr_parser(spreadsheet::iface::import_table* table, bool debug) :
+ mp_table(table), m_debug(debug) {}
+
+ void operator() (const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ bool b = false;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ mp_table->set_style_name(attr.value);
+ if (m_debug)
+ std::cout << " * table style info (name=" << attr.value << ")" << std::endl;
+ break;
+ case XML_showFirstColumn:
+ b = to_bool(attr.value);
+ mp_table->set_style_show_first_column(b);
+ if (m_debug)
+ std::cout << " * show first column: " << b << std::endl;
+ break;
+ case XML_showLastColumn:
+ b = to_bool(attr.value);
+ mp_table->set_style_show_last_column(b);
+ if (m_debug)
+ std::cout << " * show last column: " << b << std::endl;
+ break;
+ case XML_showRowStripes:
+ b = to_bool(attr.value);
+ mp_table->set_style_show_row_stripes(b);
+ if (m_debug)
+ std::cout << " * show row stripes: " << b << std::endl;
+ break;
+ case XML_showColumnStripes:
+ b = to_bool(attr.value);
+ mp_table->set_style_show_column_stripes(b);
+ if (m_debug)
+ std::cout << " * show column stripes: " << b << std::endl;
+ break;
+ default:
+ ;
+ }
+ }
+};
+
+}
+
+xlsx_table_context::xlsx_table_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_table& table,
+ spreadsheet::iface::import_reference_resolver& resolver) :
+ xml_context_base(session_cxt, tokens), m_table(table), m_resolver(resolver),
+ m_cxt_autofilter(session_cxt, tokens, resolver)
+{
+ register_child(&m_cxt_autofilter);
+
+ init_ooxml_context(*this);
+}
+
+xlsx_table_context::~xlsx_table_context() {}
+
+xml_context_base* xlsx_table_context::create_child_context(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx && name == XML_autoFilter)
+ {
+ m_cxt_autofilter.reset();
+ return &m_cxt_autofilter;
+ }
+ return nullptr;
+}
+
+void xlsx_table_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child)
+{
+ if (ns == NS_ooxml_xlsx && name == XML_autoFilter)
+ {
+ assert(child == &m_cxt_autofilter);
+
+ spreadsheet::iface::import_auto_filter* af = m_table.get_auto_filter();
+ if (!af)
+ return;
+
+ const xlsx_autofilter_context& cxt = static_cast<const xlsx_autofilter_context&>(*child);
+ cxt.push_to_model(*af);
+ }
+}
+
+void xlsx_table_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ if (ns != NS_ooxml_xlsx)
+ return;
+
+ std::string_view str;
+
+ switch (name)
+ {
+ case XML_table:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ start_element_table(attrs);
+ break;
+ }
+ case XML_tableColumns:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_table);
+ single_long_attr_getter func(NS_ooxml_xlsx, XML_count);
+ long column_count = for_each(attrs.begin(), attrs.end(), func).get_value();
+ if (get_config().debug)
+ std::cout << " * column count: " << column_count << std::endl;
+
+ m_table.set_column_count(column_count);
+ }
+ break;
+ case XML_tableColumn:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_tableColumns);
+ table_column_attr_parser func(&get_session_context().spool);
+ func = for_each(attrs.begin(), attrs.end(), func);
+ if (get_config().debug)
+ {
+ std::cout << " * table column (id=" << func.get_id() << "; name=" << func.get_name() << ")" << std::endl;
+ std::cout << " * totals row label: " << func.get_totals_row_label() << std::endl;
+ std::cout << " * totals func: " << static_cast<int>(func.get_totals_row_function()) << std::endl;
+ }
+
+ m_table.set_column_identifier(func.get_id());
+ str = func.get_name();
+ m_table.set_column_name(str);
+ str = func.get_totals_row_label();
+ m_table.set_column_totals_row_label(str);
+ m_table.set_column_totals_row_function(func.get_totals_row_function());
+ }
+ break;
+ case XML_tableStyleInfo:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_table);
+ table_style_info_attr_parser func(&m_table, get_config().debug);
+ for_each(attrs.begin(), attrs.end(), func);
+ }
+ break;
+ default:
+ warn_unhandled();
+ }
+
+}
+
+bool xlsx_table_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_table:
+ m_table.commit();
+ break;
+ case XML_tableColumn:
+ m_table.commit_column();
+ break;
+ default:
+ ;
+ }
+ }
+
+ return pop_stack(ns, name);
+}
+
+void xlsx_table_context::start_element_table(const xml_token_attrs_t& attrs)
+{
+ long id = -1;
+ long totals_row_count = -1;
+
+ std::optional<std::string_view> name;
+ std::optional<std::string_view> display_name;
+ std::optional<std::string_view> ref;
+
+ for (const xml_token_attr_t& attr : attrs)
+ {
+ if (attr.ns)
+ continue;
+
+ switch (attr.name)
+ {
+ case XML_id:
+ id = to_long(attr.value);
+ break;
+ case XML_totalsRowCount:
+ totals_row_count = to_long(attr.value);
+ break;
+ case XML_name:
+ name = attr.value;
+ break;
+ case XML_displayName:
+ display_name = attr.value;
+ break;
+ case XML_ref:
+ ref = attr.value;
+ break;
+ }
+ }
+
+ if (get_config().debug)
+ {
+ auto str_or_not = [](const auto& v) -> std::string_view
+ {
+ return v ? *v : "-";
+ };
+
+ std::cout << "* table (range=" << str_or_not(ref)
+ << "; id=" << id
+ << "; name=" << str_or_not(name)
+ << "; display name=" << str_or_not(display_name) << ")" << std::endl;
+
+ std::cout << " * totals row count: " << totals_row_count << std::endl;
+ }
+
+ if (id >= 0)
+ m_table.set_identifier(id);
+
+ if (ref)
+ {
+ ss::range_t range = to_rc_range(m_resolver.resolve_range(*ref));
+ m_table.set_range(range);
+ }
+
+ if (name)
+ m_table.set_name(*name);
+
+ if (display_name)
+ m_table.set_display_name(*display_name);
+
+ if (totals_row_count >= 0)
+ m_table.set_totals_row_count(totals_row_count);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_table_context.hpp b/src/liborcus/xlsx_table_context.hpp
new file mode 100644
index 0000000..8b3e629
--- /dev/null
+++ b/src/liborcus/xlsx_table_context.hpp
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XLSX_TABLE_CONTEXT_HPP
+#define ORCUS_XLSX_TABLE_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "xlsx_autofilter_context.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_table;
+class import_reference_resolver;
+
+}}
+
+class xlsx_table_context : public xml_context_base
+{
+public:
+ xlsx_table_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_table& table,
+ spreadsheet::iface::import_reference_resolver& resolver);
+ virtual ~xlsx_table_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+
+private:
+ void start_element_table(const xml_token_attrs_t& attrs);
+
+private:
+ spreadsheet::iface::import_table& m_table;
+ spreadsheet::iface::import_reference_resolver& m_resolver;
+
+ xlsx_autofilter_context m_cxt_autofilter;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_types.cpp b/src/liborcus/xlsx_types.cpp
new file mode 100644
index 0000000..3c0ba2a
--- /dev/null
+++ b/src/liborcus/xlsx_types.cpp
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_types.hpp"
+
+#include <mdds/sorted_string_map.hpp>
+
+namespace orcus {
+
+namespace {
+
+constexpr std::string_view str_unknown = "unknown";
+
+namespace cell_type {
+
+using map_type = mdds::sorted_string_map<xlsx_cell_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "b", xlsx_ct_boolean },
+ { "e", xlsx_ct_error },
+ { "inlineStr", xlsx_ct_inline_string },
+ { "n", xlsx_ct_numeric },
+ { "s", xlsx_ct_shared_string },
+ { "str", xlsx_ct_formula_string }
+};
+
+const map_type& get()
+{
+ static const map_type map(entries, std::size(entries), xlsx_ct_unknown);
+ return map;
+}
+
+} // namespace cell_type
+
+namespace rca {
+
+using map_type = mdds::sorted_string_map<xlsx_rev_row_column_action_t, mdds::string_view_map_entry>;
+
+// Keys must be sorted.
+constexpr map_type::entry entries[] = {
+ { "deleteCol", xlsx_rev_rca_delete_column },
+ { "deleteRow", xlsx_rev_rca_delete_row },
+ { "insertCol", xlsx_rev_rca_insert_column },
+ { "insertRow", xlsx_rev_rca_insert_row }
+};
+
+const map_type& get()
+{
+ static const map_type map(entries, std::size(entries), xlsx_rev_rca_unknown);
+ return map;
+}
+
+} // namespace rca
+
+} // anonymous namespace
+
+xlsx_cell_t to_xlsx_cell_type(std::string_view s)
+{
+ return cell_type::get().find(s);
+}
+
+std::string_view to_string(xlsx_cell_t type)
+{
+ switch (type)
+ {
+ case xlsx_ct_boolean:
+ return cell_type::entries[0].key;
+ case xlsx_ct_error:
+ return cell_type::entries[1].key;
+ case xlsx_ct_inline_string:
+ return cell_type::entries[2].key;
+ case xlsx_ct_numeric:
+ return cell_type::entries[3].key;
+ case xlsx_ct_shared_string:
+ return cell_type::entries[4].key;
+ case xlsx_ct_formula_string:
+ return cell_type::entries[5].key;
+ default:
+ ;
+ }
+ return str_unknown;
+}
+
+xlsx_rev_row_column_action_t to_xlsx_rev_row_column_action_type(std::string_view s)
+{
+ return rca::get().find(s);
+}
+
+std::string_view to_string(xlsx_rev_row_column_action_t type)
+{
+ switch (type)
+ {
+ case xlsx_rev_rca_delete_column:
+ return rca::entries[0].key;
+ case xlsx_rev_rca_delete_row:
+ return rca::entries[1].key;
+ case xlsx_rev_rca_insert_column:
+ return rca::entries[2].key;
+ case xlsx_rev_rca_insert_row:
+ return rca::entries[3].key;
+ case xlsx_rev_rca_unknown:
+ default:
+ ;
+ }
+
+ return str_unknown;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_types.hpp b/src/liborcus/xlsx_types.hpp
new file mode 100644
index 0000000..6d61e1f
--- /dev/null
+++ b/src/liborcus/xlsx_types.hpp
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_XLSX_TYPES_HPP__
+#define __ORCUS_XLSX_TYPES_HPP__
+
+#include "ooxml_types.hpp"
+#include "orcus/spreadsheet/types.hpp"
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_sheet;
+
+}}
+
+struct xlsx_rel_sheet_info : public opc_rel_extra
+{
+ std::string_view name;
+ size_t id;
+
+ xlsx_rel_sheet_info() : id(0) {}
+
+ virtual ~xlsx_rel_sheet_info() override {}
+};
+
+struct xlsx_rel_pivot_cache_info : public opc_rel_extra
+{
+ spreadsheet::pivot_cache_id_t id;
+
+ xlsx_rel_pivot_cache_info(spreadsheet::pivot_cache_id_t _id) : id(_id) {}
+
+ virtual ~xlsx_rel_pivot_cache_info() override {}
+};
+
+/**
+ * Data to pass to the pivot cache record handler.
+ */
+struct xlsx_rel_pivot_cache_record_info : public opc_rel_extra
+{
+ spreadsheet::pivot_cache_id_t id;
+
+ xlsx_rel_pivot_cache_record_info(spreadsheet::pivot_cache_id_t _id) : id(_id) {}
+
+ virtual ~xlsx_rel_pivot_cache_record_info() override {}
+};
+
+struct xlsx_rel_table_info : public opc_rel_extra
+{
+ spreadsheet::iface::import_sheet* sheet_interface;
+
+ xlsx_rel_table_info() : sheet_interface(nullptr) {}
+
+ virtual ~xlsx_rel_table_info() override {}
+};
+
+enum xlsx_cell_t
+{
+ xlsx_ct_unknown = 0,
+ xlsx_ct_boolean,
+ xlsx_ct_error,
+ xlsx_ct_numeric,
+ xlsx_ct_inline_string,
+ xlsx_ct_shared_string,
+ xlsx_ct_formula_string,
+};
+
+xlsx_cell_t to_xlsx_cell_type(std::string_view s);
+
+std::string_view to_string(xlsx_cell_t type);
+
+enum xlsx_rev_row_column_action_t
+{
+ xlsx_rev_rca_unknown = 0,
+ xlsx_rev_rca_delete_column,
+ xlsx_rev_rca_delete_row,
+ xlsx_rev_rca_insert_column,
+ xlsx_rev_rca_insert_row
+};
+
+xlsx_rev_row_column_action_t to_xlsx_rev_row_column_action_type(std::string_view s);
+
+std::string_view to_string(xlsx_rev_row_column_action_t type);
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_workbook_context.cpp b/src/liborcus/xlsx_workbook_context.cpp
new file mode 100644
index 0000000..4980418
--- /dev/null
+++ b/src/liborcus/xlsx_workbook_context.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xlsx_workbook_context.hpp"
+#include "ooxml_global.hpp"
+#include "ooxml_schemas.hpp"
+#include "ooxml_token_constants.hpp"
+#include "ooxml_namespace_types.hpp"
+#include "session_context.hpp"
+#include "xlsx_session_data.hpp"
+
+#include "orcus/measurement.hpp"
+#include "orcus/spreadsheet/import_interface.hpp"
+
+namespace orcus {
+
+xlsx_workbook_context::xlsx_workbook_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory& factory) :
+ xml_context_base(session_cxt, tokens),
+ m_defined_name_scope(-1),
+ m_sheet_count(0),
+ m_factory(factory),
+ mp_named_exp(factory.get_named_expression())
+{
+ init_ooxml_context(*this);
+}
+
+xlsx_workbook_context::~xlsx_workbook_context() = default;
+
+xml_context_base* xlsx_workbook_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xlsx_workbook_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xlsx_workbook_context::start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs)
+{
+ xml_token_pair_t parent = push_stack(ns, name);
+ session_context& cxt = get_session_context();
+ string_pool& sp = cxt.spool;
+
+ if (ns == NS_ooxml_xlsx)
+ {
+ switch (name)
+ {
+ case XML_workbook:
+ {
+ xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN);
+ if (get_config().debug)
+ print_attrs(get_tokens(), attrs);
+
+ break;
+ }
+ case XML_sheets:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_workbook);
+ break;
+ case XML_sheet:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_sheets);
+
+ std::string_view rid;
+ xlsx_rel_sheet_info sheet;
+
+ std::for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (!attr.ns || attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_name:
+ sheet.name = sp.intern(attr.value).first;
+ break;
+ case XML_sheetId:
+ {
+ if (!attr.value.empty())
+ sheet.id = to_long(attr.value);
+ break;
+ }
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_ooxml_r && attr.name == XML_id)
+ {
+ rid = sp.intern(attr.value).first;
+ }
+ }
+ );
+
+ if (sheet.name.empty())
+ throw xml_structure_error("workbook.xml: sheet element must have a valid name element.");
+
+ // Insert the sheet here so that we have all the sheets available
+ // prior to parsing global named expressions.
+ m_factory.append_sheet(m_sheet_count++, sheet.name);
+
+ m_workbook_info.data.insert(
+ opc_rel_extras_t::map_type::value_type(
+ rid, std::make_unique<xlsx_rel_sheet_info>(sheet)));
+
+ break;
+ }
+ case XML_definedNames:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_workbook);
+ break;
+ case XML_definedName:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_definedNames);
+
+ std::for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (attr.ns && attr.ns != NS_ooxml_xlsx)
+ return;
+
+ switch (attr.name)
+ {
+ case XML_name:
+ {
+ m_defined_name = attr.value;
+ if (attr.transient)
+ {
+ m_defined_name =
+ cxt.spool.intern(m_defined_name).first;
+ }
+ break;
+ }
+ case XML_localSheetId:
+ m_defined_name_scope = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ );
+
+ break;
+ }
+ case XML_pivotCaches:
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_workbook);
+ break;
+ case XML_pivotCache:
+ {
+ xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotCaches);
+
+ std::string_view rid;
+ long cache_id = -1;
+ std::for_each(attrs.begin(), attrs.end(),
+ [&](const xml_token_attr_t& attr)
+ {
+ if (!attr.ns || attr.ns == NS_ooxml_xlsx)
+ {
+ switch (attr.name)
+ {
+ case XML_cacheId:
+ cache_id = to_long(attr.value);
+ break;
+ default:
+ ;
+ }
+ }
+ else if (attr.ns == NS_ooxml_r)
+ {
+ switch (attr.name)
+ {
+ case XML_id:
+ rid = attr.value;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ );
+
+ m_workbook_info.data.insert(
+ opc_rel_extras_t::map_type::value_type(
+ rid, std::make_unique<xlsx_rel_pivot_cache_info>(cache_id)));
+
+ break;
+ }
+ default:
+ warn_unhandled();
+ }
+ }
+}
+
+bool xlsx_workbook_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ if (ns == NS_ooxml_xlsx)
+ {
+ if (name == XML_definedName)
+ {
+ push_defined_name();
+
+ m_defined_name = std::string_view{};
+ m_defined_name_exp = std::string_view{};
+ m_defined_name_scope = -1;
+ }
+ }
+ return pop_stack(ns, name);
+}
+
+void xlsx_workbook_context::characters(std::string_view str, bool transient)
+{
+ std::string_view sv(str);
+ xml_token_pair_t cur = get_current_element();
+ string_pool& sp = get_session_context().spool;
+
+ if (cur.first == NS_ooxml_xlsx)
+ {
+ if (cur.second == XML_definedName)
+ m_defined_name_exp = transient ? sp.intern(sv).first : sv;
+ }
+}
+
+void xlsx_workbook_context::pop_workbook_info(opc_rel_extras_t& workbook_data)
+{
+ m_workbook_info.swap(workbook_data);
+}
+
+void xlsx_workbook_context::push_defined_name()
+{
+ spreadsheet::iface::import_named_expression* named_exp = mp_named_exp;
+
+ if (m_defined_name_scope >= 0)
+ {
+ // sheet local scope.
+ spreadsheet::iface::import_sheet* sheet = m_factory.get_sheet(m_defined_name_scope);
+ if (!sheet)
+ return;
+
+ named_exp = sheet->get_named_expression();
+ }
+
+ if (named_exp)
+ {
+ named_exp->set_named_expression(m_defined_name, m_defined_name_exp);
+ named_exp->commit();
+ }
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xlsx_workbook_context.hpp b/src/liborcus/xlsx_workbook_context.hpp
new file mode 100644
index 0000000..71d1958
--- /dev/null
+++ b/src/liborcus/xlsx_workbook_context.hpp
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XLSX_WORKBOOK_CONTEXT_HPP
+#define INCLUDED_ORCUS_XLSX_WORKBOOK_CONTEXT_HPP
+
+#include "xml_context_base.hpp"
+#include "orcus/spreadsheet/types.hpp"
+#include "xlsx_types.hpp"
+
+#include <unordered_map>
+
+namespace orcus {
+
+namespace spreadsheet { namespace iface {
+
+class import_factory;
+class import_named_expression;
+
+}}
+
+/**
+ * Context for xl/workbook.xml.
+ */
+class xlsx_workbook_context : public xml_context_base
+{
+public:
+ typedef std::unordered_map<std::string_view, xlsx_rel_sheet_info> sheet_info_type;
+
+ xlsx_workbook_context(
+ session_context& session_cxt, const tokens& tokens,
+ spreadsheet::iface::import_factory& factory);
+
+ virtual ~xlsx_workbook_context();
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const xml_token_attrs_t& attrs);
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name);
+ virtual void characters(std::string_view str, bool transient);
+
+ void pop_workbook_info(opc_rel_extras_t& sheets);
+
+private:
+ void push_defined_name();
+
+private:
+ opc_rel_extras_t m_workbook_info;
+ std::string_view m_defined_name;
+ std::string_view m_defined_name_exp;
+ spreadsheet::sheet_t m_defined_name_scope;
+ size_t m_sheet_count;
+ spreadsheet::iface::import_factory& m_factory;
+ spreadsheet::iface::import_named_expression* mp_named_exp;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_context_base.cpp b/src/liborcus/xml_context_base.cpp
new file mode 100644
index 0000000..4d61926
--- /dev/null
+++ b/src/liborcus/xml_context_base.cpp
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_context_base.hpp"
+#include "session_context.hpp"
+
+#include "orcus/exception.hpp"
+#include "orcus/tokens.hpp"
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+namespace orcus {
+
+namespace {
+
+void print_stack(const tokens& tokens, const xml_elem_stack_t& elem_stack, const xmlns_context* ns_cxt)
+{
+ cerr << "[ ";
+ xml_elem_stack_t::const_iterator itr, itr_beg = elem_stack.begin(), itr_end = elem_stack.end();
+ for (itr = itr_beg; itr != itr_end; ++itr)
+ {
+ if (itr != itr_beg)
+ cerr << " -> ";
+
+ xmlns_id_t ns = itr->first;
+ if (ns_cxt)
+ {
+ std::string_view alias = ns_cxt->get_alias(ns);
+ if (!alias.empty())
+ cerr << alias << ":";
+ }
+ else
+ cerr << ns << ":";
+
+ cerr << tokens.get_token_name(itr->second);
+ }
+ cerr << " ]";
+}
+
+}
+
+xml_context_base::xml_context_base(session_context& session_cxt, const tokens& tokens) :
+ m_config(format_t::unknown),
+ mp_ns_cxt(nullptr), m_session_cxt(session_cxt), m_tokens(tokens),
+ m_elem_printer(m_tokens)
+{
+}
+
+xml_context_base::~xml_context_base()
+{
+}
+
+void xml_context_base::declaration(const xml_declaration_t& /*decl*/)
+{
+}
+
+xml_context_base* xml_context_base::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xml_context_base::end_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xml_context_base::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+bool xml_context_base::evaluate_child_element(xmlns_id_t ns, xml_token_t name) const
+{
+ const xml_token_pair_t parent = get_current_element();
+
+ if (xml_element_always_allowed(parent))
+ return true;
+
+ const xml_token_pair_t child(ns, name);
+
+ xml_element_validator::result res = m_elem_validator.validate(parent, child);
+
+ if (get_config().debug)
+ {
+ switch (res)
+ {
+ case xml_element_validator::result::child_invalid:
+ {
+ std::ostringstream os;
+ print_element(os, child);
+ os << " cannot be a child element of ";
+ print_element(os, parent);
+ warn(os.str());
+ break;
+ }
+ case xml_element_validator::result::parent_unknown:
+ {
+ std::ostringstream os;
+ os << "parent ";
+ print_element(os, parent);
+ os << " does not have any rules defined (child: ";
+ print_element(os, child);
+ os << ')';
+ warn(os.str());
+ break;
+ }
+ case xml_element_validator::result::child_valid:
+ break;
+ }
+ }
+
+ return res != xml_element_validator::result::child_invalid;
+}
+
+void xml_context_base::set_ns_context(const xmlns_context* p)
+{
+ mp_ns_cxt = p;
+ m_elem_printer.set_ns_context(p);
+
+ for (auto* child : m_child_contexts)
+ child->set_ns_context(p);
+}
+
+void xml_context_base::set_config(const config& opt)
+{
+ m_config = opt;
+
+ for (auto* child : m_child_contexts)
+ child->set_config(opt);
+}
+
+void xml_context_base::set_always_allowed_elements(xml_elem_set_t elems)
+{
+ m_always_allowed_elements = std::move(elems);
+}
+
+void xml_context_base::init_element_validator(
+ const xml_element_validator::rule* rules, std::size_t n_rules)
+{
+ m_elem_validator.init(rules, n_rules);
+}
+
+session_context& xml_context_base::get_session_context()
+{
+ return m_session_cxt;
+}
+
+const session_context& xml_context_base::get_session_context() const
+{
+ return m_session_cxt;
+}
+
+const tokens& xml_context_base::get_tokens() const
+{
+ return m_tokens;
+}
+
+xml_token_pair_t xml_context_base::push_stack(xmlns_id_t ns, xml_token_t name)
+{
+ xml_token_pair_t parent = get_current_element();
+ m_stack.emplace_back(ns, name);
+ return parent;
+}
+
+bool xml_context_base::pop_stack(xmlns_id_t ns, xml_token_t name)
+{
+ const xml_token_pair_t& r = m_stack.back();
+
+ if (ns != r.first || name != r.second)
+ throw general_error("mismatched element name");
+
+ m_stack.pop_back();
+ return m_stack.empty();
+}
+
+xml_token_pair_t xml_context_base::get_current_element() const
+{
+ return m_stack.empty() ? xml_token_pair_t(XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN) : m_stack.back();
+}
+
+const xml_token_pair_t& xml_context_base::get_parent_element() const
+{
+ if (m_stack.size() < 2)
+ throw general_error("element stack has no parent element");
+
+ return m_stack[m_stack.size() - 2];
+}
+
+void xml_context_base::warn_unhandled() const
+{
+ if (!m_config.debug)
+ return;
+
+ cerr << "warning: unhandled element ";
+ print_stack(m_tokens, m_stack, mp_ns_cxt);
+ cerr << endl;
+}
+
+void xml_context_base::warn_unexpected() const
+{
+ if (!m_config.debug)
+ return;
+
+ cerr << "warning: unexpected element ";
+ print_stack(m_tokens, m_stack, mp_ns_cxt);
+ cerr << endl;
+}
+
+void xml_context_base::warn(std::string_view msg) const
+{
+ if (!m_config.debug)
+ return;
+
+ cerr << "warning: " << msg << endl;
+}
+
+void xml_context_base::xml_element_expected(
+ const xml_token_pair_t& elem, xmlns_id_t ns, xml_token_t name,
+ const string* error) const
+{
+ if (!m_config.structure_check)
+ return;
+
+ if (elem.first == ns && elem.second == name)
+ // This is an expected element. Good.
+ return;
+
+ if (m_always_allowed_elements.count(elem))
+ return;
+
+ if (error)
+ {
+ throw xml_structure_error(*error);
+ }
+
+ // Create a generic error message.
+ std::ostringstream os;
+ os << "element ";
+ print_element(os, {ns, name});
+ os << " expected, but ";
+ print_element(os, elem);
+ os << " encountered." << std::endl << std::endl;
+
+ print_current_element_stack(os);
+ throw xml_structure_error(os.str());
+}
+
+void xml_context_base::xml_element_expected(
+ const xml_token_pair_t& elem, const xml_elem_stack_t& expected_elems) const
+{
+ if (!m_config.structure_check)
+ return;
+
+ for (const xml_token_pair_t& e : expected_elems)
+ {
+ if (elem == e)
+ return;
+ }
+
+ if (m_always_allowed_elements.count(elem))
+ return;
+
+ throw_unknown_element_error(elem);
+}
+
+void xml_context_base::xml_element_expected(
+ const xml_token_pair_t& elem, const xml_elem_set_t& expected_elems) const
+{
+ if (!m_config.structure_check)
+ return;
+
+ if (expected_elems.count(elem))
+ return;
+
+ if (m_always_allowed_elements.count(elem))
+ return;
+
+ throw_unknown_element_error(elem);
+}
+
+bool xml_context_base::xml_element_always_allowed(const xml_token_pair_t& elem) const
+{
+ return m_always_allowed_elements.count(elem) > 0;
+}
+
+void xml_context_base::print_namespace(std::ostream& os, xmlns_id_t ns) const
+{
+ m_elem_printer.print_namespace(os, ns);
+}
+
+void xml_context_base::print_element(std::ostream& os, const xml_token_pair_t& elem) const
+{
+ m_elem_printer.print_element(os, elem.first, elem.second);
+}
+
+void xml_context_base::print_current_element_stack(std::ostream& os) const
+{
+ os << "current element stack:" << std::endl << std::endl;
+
+ for (const auto& [ns, name] : m_stack)
+ {
+ os << " - ";
+ print_element(os, {ns, name});
+ os << std::endl;
+ }
+}
+
+void xml_context_base::throw_unknown_element_error(const xml_token_pair_t& elem) const
+{
+ // Create a generic error message.
+ std::ostringstream os;
+ os << "unexpected element encountered: ";
+ print_element(os, elem);
+ os << std::endl << std::endl;
+
+ print_current_element_stack(os);
+ throw xml_structure_error(os.str());
+}
+
+const config& xml_context_base::get_config() const
+{
+ return m_config;
+}
+
+std::string_view xml_context_base::intern(const xml_token_attr_t& attr)
+{
+ return m_session_cxt.intern(attr);
+}
+
+std::string_view xml_context_base::intern(std::string_view s)
+{
+ return m_session_cxt.intern(s);
+}
+
+void xml_context_base::register_child(xml_context_base* child)
+{
+ assert(child);
+ m_child_contexts.push_back(child);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_context_base.hpp b/src/liborcus/xml_context_base.hpp
new file mode 100644
index 0000000..6956806
--- /dev/null
+++ b/src/liborcus/xml_context_base.hpp
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XML_CONTEXT_BASE_HPP
+#define INCLUDED_ORCUS_XML_CONTEXT_BASE_HPP
+
+#include "xml_element_validator.hpp"
+#include "xml_stream_handler.hpp"
+#include "xml_util.hpp"
+
+namespace orcus {
+
+struct session_context;
+class tokens;
+class xmlns_context;
+class xml_element_validator;
+
+class xml_context_base
+{
+public:
+ xml_context_base(const xml_context_base&) = delete;
+ xml_context_base& operator=(const xml_context_base&) = delete;
+
+ xml_context_base(session_context& session_cxt, const tokens& tokens);
+ virtual ~xml_context_base() = 0;
+
+ /**
+ * This gets called at the end of the initial XML declaration block i.e.
+ * &lt;?xml ... ?&gt;. Obviously this gets called only on the root context.
+ *
+ * @param decl XML declaration attributes
+ */
+ virtual void declaration(const xml_declaration_t& decl);
+
+ /**
+ * This method gets called by the stream handler to fetch a child context
+ * object if applicable. If the current context can handle the specified
+ * element, it should return nullptr. If the current context should spawn a
+ * new context to handle the specified element and its sub structure, then
+ * it should return a pointer to a child context.
+ *
+ * @note The caller is not responsible for managing the life cycle of the
+ * returned context object; the current context object must manage the life
+ * cycle of the context object it returns.
+ *
+ * @param ns namespace value for the element.
+ * @param name name of the element.
+ *
+ * @return pointer to the context object that should handle the specified
+ * element, or nullptr if the current context can handle the
+ * element.
+ */
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name);
+
+ /**
+ * This method gets called when the child context is about to get phased
+ * out, to give the parent context object to communicate with the child
+ * context object before it gets phased out.
+ *
+ * @param ns namespace value for the element.
+ * @param name name of the element.
+ * @param child pointer to the child context object that is about to get
+ * phased out.
+ */
+ virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child);
+
+ /**
+ * Called on the opening of each element. The implementor should call
+ * push_stack() at the beginning of this method to have the base class keep
+ * track of the element stack. Be sure to also call pop_stack() in
+ * end_element() to maintain correct element stack.
+ *
+ * @param ns namespace token
+ * @param name element name
+ * @param attrs attributes
+ */
+ virtual void start_element(xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) = 0;
+
+ /**
+ * Called on the closing of each element.
+ *
+ * @param ns namespace token
+ * @param name element name
+ *
+ * @return true if the element that's closing is the root element of the
+ * context, else return false. The implementor should simply call
+ * pop_stack() and use the returned value from it as this method's
+ * return value.
+ */
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) = 0;
+
+ /**
+ * Called when passing xml content. When the content value is transient,
+ * the value is not expected to survive beyond the scope of the callback.
+ *
+ * @param str content value.
+ * @param transient whether or not the value is transient.
+ */
+ virtual void characters(std::string_view str, bool transient);
+
+ bool evaluate_child_element(xmlns_id_t ns, xml_token_t name) const;
+
+ void set_ns_context(const xmlns_context* p);
+
+ const config& get_config() const;
+
+ void set_config(const config& opt);
+
+ void set_always_allowed_elements(xml_elem_set_t elems);
+
+protected:
+ void init_element_validator(const xml_element_validator::rule* rules, std::size_t n_rules);
+
+ session_context& get_session_context();
+ const session_context& get_session_context() const;
+ const tokens& get_tokens() const;
+ xml_token_pair_t push_stack(xmlns_id_t ns, xml_token_t name);
+ bool pop_stack(xmlns_id_t ns, xml_token_t name);
+ xml_token_pair_t get_current_stack(xmlns_id_t ns, xml_token_t name);
+ xml_token_pair_t get_current_element() const;
+
+ /**
+ * @warning Don't call this at the root element, or it will throw an
+ * exception.
+ */
+ const xml_token_pair_t& get_parent_element() const;
+ void warn_unhandled() const;
+ void warn_unexpected() const;
+ void warn(std::string_view msg) const;
+
+ /**
+ * Check if observed element equals expected element. If not, it throws an
+ * xml_structure_error exception.
+ *
+ * @param elem element observed.
+ * @param ns namespace of expected element.
+ * @param name name of expected element.
+ * @param error custom error message if needed.
+ */
+ void xml_element_expected(
+ const xml_token_pair_t& elem, xmlns_id_t ns, xml_token_t name,
+ const ::std::string* error = nullptr) const;
+
+ void xml_element_expected(
+ const xml_token_pair_t& elem, const xml_elem_stack_t& expected_elems) const;
+
+ void xml_element_expected(
+ const xml_token_pair_t& elem, const xml_elem_set_t& expected_elems) const;
+
+ bool xml_element_always_allowed(const xml_token_pair_t& elem) const;
+
+ void print_namespace(std::ostream& os, xmlns_id_t ns) const;
+
+ void print_element(std::ostream& os, const xml_token_pair_t& elem) const;
+
+ void print_current_element_stack(std::ostream& os) const;
+
+ /**
+ * Throw a viewer-friendly XML structure error with the information about an
+ * unknown element encountered.
+ *
+ * @param elem unknown element encountered.
+ */
+ void throw_unknown_element_error(const xml_token_pair_t& elem) const;
+
+ std::string_view intern(const xml_token_attr_t& attr);
+ std::string_view intern(std::string_view s);
+
+ void register_child(xml_context_base* child);
+
+private:
+ std::vector<xml_context_base*> m_child_contexts;
+
+ config m_config;
+ const xmlns_context* mp_ns_cxt;
+ session_context& m_session_cxt;
+ const tokens& m_tokens;
+ xml_element_printer m_elem_printer;
+ xml_element_validator m_elem_validator;
+ xml_elem_stack_t m_stack;
+ xml_elem_set_t m_always_allowed_elements;
+};
+
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_context_global.cpp b/src/liborcus/xml_context_global.cpp
new file mode 100644
index 0000000..5c98f07
--- /dev/null
+++ b/src/liborcus/xml_context_global.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_context_global.hpp"
+#include "orcus/string_pool.hpp"
+#include "orcus/measurement.hpp"
+
+#include <algorithm>
+
+namespace orcus {
+
+single_attr_getter::single_attr_getter(string_pool& pool, xmlns_id_t ns, xml_token_t name) :
+ m_pool(&pool), m_ns(ns), m_name(name) {}
+
+single_attr_getter::single_attr_getter(xmlns_id_t ns, xml_token_t name) :
+ m_pool(nullptr), m_ns(ns), m_name(name) {}
+
+void single_attr_getter::operator() (const xml_token_attr_t& attr)
+{
+ if (attr.name != m_name)
+ return;
+
+ if (attr.ns && attr.ns != m_ns)
+ return;
+
+ m_value = attr.value;
+ if (attr.transient && m_pool)
+ m_value = m_pool->intern(m_value).first;
+}
+
+std::string_view single_attr_getter::get_value() const
+{
+ return m_value;
+}
+
+std::string_view single_attr_getter::get(
+ const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name)
+{
+ single_attr_getter func(ns, name);
+ return std::for_each(attrs.begin(), attrs.end(), func).get_value();
+}
+
+std::string_view single_attr_getter::get(
+ const std::vector<xml_token_attr_t>& attrs, string_pool& pool, xmlns_id_t ns, xml_token_t name)
+{
+ single_attr_getter func(pool, ns, name);
+ return std::for_each(attrs.begin(), attrs.end(), func).get_value();
+}
+
+single_long_attr_getter::single_long_attr_getter(xmlns_id_t ns, xml_token_t name) :
+ m_value(-1), m_ns(ns), m_name(name) {}
+
+void single_long_attr_getter::operator() (const xml_token_attr_t& attr)
+{
+ if (attr.name != m_name)
+ return;
+
+ if (attr.ns && attr.ns != m_ns)
+ return;
+
+ m_value = to_long(attr.value);
+}
+
+long single_long_attr_getter::get_value() const
+{
+ return m_value;
+}
+
+long single_long_attr_getter::get(const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name)
+{
+ single_long_attr_getter func(ns, name);
+ return std::for_each(attrs.begin(), attrs.end(), func).get_value();
+}
+
+single_double_attr_getter::single_double_attr_getter(xmlns_id_t ns, xml_token_t name) :
+ m_value(-1.0), m_ns(ns), m_name(name) {}
+
+void single_double_attr_getter::operator() (const xml_token_attr_t& attr)
+{
+ if (attr.name != m_name)
+ return;
+
+ if (attr.ns && attr.ns != m_ns)
+ return;
+
+ m_value = to_double(attr.value);
+}
+
+double single_double_attr_getter::get_value() const
+{
+ return m_value;
+}
+
+double single_double_attr_getter::get(const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name)
+{
+ single_double_attr_getter func(ns, name);
+ return std::for_each(attrs.begin(), attrs.end(), func).get_value();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_context_global.hpp b/src/liborcus/xml_context_global.hpp
new file mode 100644
index 0000000..b05dd28
--- /dev/null
+++ b/src/liborcus/xml_context_global.hpp
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XML_CONTEXT_GLOBAL_HPP
+#define ORCUS_XML_CONTEXT_GLOBAL_HPP
+
+#include <orcus/types.hpp>
+
+#include <functional>
+
+namespace orcus {
+
+class string_pool;
+
+/**
+ * Use this just to get the value of a single attribute for a given element.
+ */
+class single_attr_getter
+{
+ string_pool* m_pool;
+ std::string_view m_value;
+ xmlns_id_t m_ns;
+ xml_token_t m_name;
+
+public:
+ single_attr_getter(xmlns_id_t ns, xml_token_t name);
+ single_attr_getter(string_pool& pool, xmlns_id_t ns, xml_token_t name);
+
+ void operator() (const xml_token_attr_t& attr);
+ std::string_view get_value() const;
+
+ static std::string_view get(const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name);
+ static std::string_view get(const std::vector<xml_token_attr_t>& attrs, string_pool& pool, xmlns_id_t ns, xml_token_t name);
+};
+
+class single_long_attr_getter
+{
+ long m_value;
+ xmlns_id_t m_ns;
+ xml_token_t m_name;
+
+public:
+ single_long_attr_getter(xmlns_id_t ns, xml_token_t name);
+ void operator() (const xml_token_attr_t& attr);
+ long get_value() const;
+
+ static long get(const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name);
+};
+
+class single_double_attr_getter
+{
+ double m_value;
+ xmlns_id_t m_ns;
+ xml_token_t m_name;
+
+public:
+ single_double_attr_getter(xmlns_id_t ns, xml_token_t name);
+ void operator() (const xml_token_attr_t& attr);
+ double get_value() const;
+
+ static double get(const std::vector<xml_token_attr_t>& attrs, xmlns_id_t ns, xml_token_t name);
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_element_types.cpp b/src/liborcus/xml_element_types.cpp
new file mode 100644
index 0000000..967b4d4
--- /dev/null
+++ b/src/liborcus/xml_element_types.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_element_types.hpp"
+
+namespace orcus {
+
+size_t xml_token_pair_hash::operator()(const xml_token_pair_t& v) const
+{
+ return std::hash<const char*>()(v.first) ^ std::hash<size_t>()(v.second);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_element_types.hpp b/src/liborcus/xml_element_types.hpp
new file mode 100644
index 0000000..2e7bc15
--- /dev/null
+++ b/src/liborcus/xml_element_types.hpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <orcus/types.hpp>
+
+namespace orcus {
+
+/**
+ * Holds a pair of XML namespace identifier and an element token. Typically
+ * used when managing the element stack inside element context classes.
+ */
+using xml_token_pair_t = std::pair<xmlns_id_t, xml_token_t>;
+
+struct xml_token_pair_hash
+{
+ size_t operator()(const xml_token_pair_t& v) const;
+};
+
+using xml_elem_stack_t = std::vector<xml_token_pair_t>;
+using xml_elem_set_t = std::unordered_set<xml_token_pair_t, xml_token_pair_hash>;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_element_validator.cpp b/src/liborcus/xml_element_validator.cpp
new file mode 100644
index 0000000..ceb632c
--- /dev/null
+++ b/src/liborcus/xml_element_validator.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_element_validator.hpp"
+
+namespace orcus {
+
+xml_element_validator::xml_element_validator()
+{
+}
+
+xml_element_validator::xml_element_validator(const rule* rules, std::size_t n_rules)
+{
+ init(rules, n_rules);
+}
+
+void xml_element_validator::init(const rule* rules, std::size_t n_rules)
+{
+ const rule* end_rules = rules + n_rules;
+
+ for (; rules != end_rules; ++rules)
+ {
+ const xml_token_pair_t parent(rules->ns_parent, rules->name_parent);
+ const xml_token_pair_t child(rules->ns_child, rules->name_child);
+
+ auto it = m_rules.find(parent);
+ if (it == m_rules.end())
+ {
+ auto res = m_rules.emplace(parent, xml_elem_set_t{});
+ it = res.first;
+ }
+
+ xml_elem_set_t& children = it->second;
+ children.insert(child);
+ }
+}
+
+xml_element_validator::result xml_element_validator::validate(
+ const xml_token_pair_t& parent, const xml_token_pair_t& child) const
+{
+ if (m_rules.empty())
+ // No rules are defined. Allow everything.
+ return result::child_valid;
+
+ auto it = m_rules.find(parent);
+ if (it == m_rules.end())
+ // No rules for this parent.
+ return result::parent_unknown;
+
+ const xml_elem_set_t& rules = it->second;
+ return rules.count(child) > 0 ? result::child_valid : result::child_invalid;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_element_validator.hpp b/src/liborcus/xml_element_validator.hpp
new file mode 100644
index 0000000..43a44e0
--- /dev/null
+++ b/src/liborcus/xml_element_validator.hpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_element_types.hpp"
+
+#include <unordered_map>
+
+namespace orcus {
+
+class xml_element_validator
+{
+ using rule_map_type = std::unordered_map<xml_token_pair_t, xml_elem_set_t, xml_token_pair_hash>;
+ rule_map_type m_rules;
+
+public:
+
+ /** represents a single parent to child mapping rule. It must be a POD. */
+ struct rule
+ {
+ const xmlns_id_t ns_parent;
+ const xml_token_t name_parent;
+ const xmlns_id_t ns_child;
+ const xml_token_t name_child;
+ };
+
+ /** validation result */
+ enum class result
+ {
+ parent_unknown, //< no rules defined for this parent
+ child_valid, //< parent allows this child
+ child_invalid //< parent does not allow this child
+ };
+
+ xml_element_validator();
+ xml_element_validator(const rule* rules, std::size_t n_rules);
+
+ void init(const rule* rules, std::size_t n_rules);
+
+ result validate(const xml_token_pair_t& parent, const xml_token_pair_t& child) const;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_empty_context.cpp b/src/liborcus/xml_empty_context.cpp
new file mode 100644
index 0000000..f39636b
--- /dev/null
+++ b/src/liborcus/xml_empty_context.cpp
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_empty_context.hpp"
+
+namespace orcus {
+
+xml_empty_context::xml_empty_context(session_context& session_cxt, const tokens& tokens) :
+ xml_context_base(session_cxt, tokens)
+{
+}
+
+xml_context_base* xml_empty_context::create_child_context(xmlns_id_t /*ns*/, xml_token_t /*name*/)
+{
+ return nullptr;
+}
+
+void xml_empty_context::end_child_context(
+ xmlns_id_t /*ns*/, xml_token_t /*name*/, xml_context_base* /*child*/)
+{
+}
+
+void xml_empty_context::start_element(
+ xmlns_id_t ns, xml_token_t name, const::std::vector<xml_token_attr_t>& /*attrs*/)
+{
+ push_stack(ns, name);
+}
+
+bool xml_empty_context::end_element(xmlns_id_t ns, xml_token_t name)
+{
+ return pop_stack(ns, name);
+}
+
+void xml_empty_context::characters(std::string_view /*str*/, bool /*transient*/)
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_empty_context.hpp b/src/liborcus/xml_empty_context.hpp
new file mode 100644
index 0000000..502e199
--- /dev/null
+++ b/src/liborcus/xml_empty_context.hpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "xml_context_base.hpp"
+
+namespace orcus {
+
+/**
+ * This context only tracks the scopes of all encountered elements but does
+ * nothing else. It is to be used when you need to ignore a whole sub
+ * structure of an XML document.
+ */
+class xml_empty_context : public xml_context_base
+{
+public:
+ xml_empty_context(session_context& session_cxt, const tokens& tokens);
+
+ virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name) override;
+
+ virtual void end_child_context(
+ xmlns_id_t ns, xml_token_t name, xml_context_base* child) override;
+
+ virtual void start_element(
+ xmlns_id_t ns, xml_token_t name, const std::vector<xml_token_attr_t>& attrs) override;
+
+ virtual bool end_element(xmlns_id_t ns, xml_token_t name) override;
+
+ virtual void characters(std::string_view str, bool transient) override;
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_map_tree.cpp b/src/liborcus/xml_map_tree.cpp
new file mode 100644
index 0000000..5d2ea72
--- /dev/null
+++ b/src/liborcus/xml_map_tree.cpp
@@ -0,0 +1,772 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_map_tree.hpp"
+#include "xpath_parser.hpp"
+
+#define ORCUS_DEBUG_XML_MAP_TREE 0
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+#include <iostream>
+#endif
+
+#include <cassert>
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+namespace orcus {
+
+namespace {
+
+template<typename T>
+void print_element_stack(std::ostream& os, const T& elem_stack)
+{
+ for (const auto& elem : elem_stack)
+ os << '/' << elem->name.name;
+}
+
+} // anonymous namespace
+
+xml_map_tree::range_field_link::range_field_link(std::string_view _xpath, std::string_view _label) :
+ xpath(_xpath), label(_label) {}
+
+xml_map_tree::element_position::element_position() :
+ open_begin(0), open_end(0), close_begin(0), close_end(0) {}
+
+xml_map_tree::cell_reference::cell_reference() {}
+
+xml_map_tree::range_reference::range_reference(const cell_position& _pos) :
+ pos(_pos), row_position(0) {}
+
+xml_map_tree::linkable::linkable(
+ xml_map_tree& parent, const xml_name_t& _name, linkable_node_type _node_type, reference_type _ref_type) :
+ name(_name), node_type(_node_type), ref_type(_ref_type)
+{
+ parent.create_ref_store(*this);
+}
+
+xml_map_tree::attribute::attribute(args_type args) :
+ linkable(std::get<0>(args), xml_name_t(std::get<1>(args)), linkable_node_type::attribute, std::get<2>(args)) {}
+
+xml_map_tree::attribute::~attribute() {}
+
+xml_map_tree::element::element(args_type args) :
+ linkable(std::get<0>(args), std::get<1>(args), linkable_node_type::element, std::get<3>(args)),
+ elem_type(std::get<2>(args)),
+ child_elements(nullptr),
+ range_parent(nullptr),
+ row_group(nullptr),
+ row_group_position(0)
+{
+ xml_map_tree& parent = std::get<0>(args);
+
+ if (elem_type == element_type::unlinked)
+ {
+ child_elements = parent.m_element_store_pool.construct();
+ return;
+ }
+
+ assert(elem_type == element_type::linked);
+}
+
+xml_map_tree::element::~element() {}
+
+xml_map_tree::element* xml_map_tree::element::get_child(const xml_name_t& _name)
+{
+ if (elem_type != element_type::unlinked)
+ return nullptr;
+
+ assert(child_elements);
+
+ auto it = std::find_if(
+ child_elements->begin(), child_elements->end(),
+ [&_name](const element* p) -> bool
+ {
+ return p->name == _name;
+ }
+ );
+
+ return it == child_elements->end() ? nullptr : *it;
+}
+
+xml_map_tree::element* xml_map_tree::element::get_or_create_child(
+ xml_map_tree& parent, const xml_name_t& _name)
+{
+ auto it = std::find_if(
+ child_elements->begin(), child_elements->end(),
+ [&_name](const element* p) -> bool
+ {
+ return p->name == _name;
+ }
+ );
+
+ if (it != child_elements->end())
+ return *it;
+
+ string_pool& sp = parent.m_names;
+
+ // Insert a new element of this name.
+ auto const nm = sp.intern(_name.name).first; // work around LLVM < 7 libc++ bug
+ child_elements->push_back(
+ parent.m_element_pool.construct(
+ element::args_type(
+ parent,
+ xml_name_t(_name.ns, nm),
+ element_type::unlinked,
+ reference_type::unknown
+ )
+ )
+ );
+
+ return child_elements->back();
+}
+
+xml_map_tree::element* xml_map_tree::element::get_or_create_linked_child(
+ xml_map_tree& parent, const xml_name_t& _name, reference_type _ref_type)
+{
+ if (!child_elements)
+ {
+ assert(elem_type == element_type::linked);
+ std::ostringstream os;
+ constexpr xml_name_t::to_string_type type = xml_name_t::use_alias;
+
+ os << "You can't add a child element under an already linked element (this='"
+ << name.to_string(parent.m_xmlns_cxt, type) << "'; child='"
+ << _name.to_string(parent.m_xmlns_cxt, type) << "')";
+
+ throw invalid_map_error(os.str());
+ }
+
+ auto it = std::find_if(
+ child_elements->begin(), child_elements->end(),
+ [&_name](const element* p) -> bool
+ {
+ return p->name == _name;
+ }
+ );
+
+ if (it != child_elements->end())
+ {
+ // Specified child element already exists. Make sure it's unlinked.
+ element* elem = *it;
+ if (elem->ref_type != reference_type::unknown || elem->elem_type != element_type::unlinked)
+ throw xpath_error("This element is already linked. You can't link the same element twice.");
+
+ elem->link_reference(parent, _ref_type);
+ return elem;
+ }
+
+ string_pool& sp = parent.m_names;
+
+ // Insert a new linked element of this name.
+ auto const nm = sp.intern(_name.name).first; // work around LLVM < 7 libc++ bug
+ child_elements->push_back(
+ parent.m_element_pool.construct(
+ element::args_type(
+ parent,
+ xml_name_t(_name.ns, nm),
+ element_type::linked,
+ _ref_type
+ )
+ )
+ );
+
+ return child_elements->back();
+}
+
+void xml_map_tree::element::link_reference(xml_map_tree& parent, reference_type _ref_type)
+{
+ if (elem_type == element_type::unlinked)
+ parent.m_element_store_pool.destroy(child_elements);
+
+ elem_type = element_type::linked;
+ ref_type = _ref_type;
+ parent.create_ref_store(*this);
+}
+
+bool xml_map_tree::element::unlinked_attribute_anchor() const
+{
+ return elem_type == element_type::unlinked && ref_type == reference_type::unknown && !attributes.empty();
+}
+
+xml_map_tree::walker::walker(const xml_map_tree& parent) :
+ m_parent(parent) {}
+xml_map_tree::walker::walker(const xml_map_tree::walker& r) :
+ m_parent(r.m_parent), m_stack(r.m_stack), m_unlinked_stack(r.m_unlinked_stack) {}
+
+void xml_map_tree::walker::reset()
+{
+ m_stack.clear();
+ m_unlinked_stack.clear();
+}
+
+xml_map_tree::element* xml_map_tree::walker::push_element(const xml_name_t& name)
+{
+ if (!m_unlinked_stack.empty())
+ {
+ // We're still in the unlinked region.
+ m_unlinked_stack.push_back(name);
+ return nullptr;
+ }
+
+ if (m_stack.empty())
+ {
+ if (!m_parent.mp_root)
+ {
+ // Tree is empty.
+ m_unlinked_stack.push_back(name);
+ return nullptr;
+ }
+
+ element* p = m_parent.mp_root;
+ if (p->name != name)
+ {
+ // Names differ.
+ m_unlinked_stack.push_back(name);
+ return nullptr;
+ }
+
+ m_stack.push_back(p);
+ return p;
+ }
+
+ if (m_stack.back()->elem_type == element_type::unlinked)
+ {
+ // Check if the current element has a child of the same name.
+ element* p = m_stack.back()->get_child(name);
+ if (p)
+ {
+ m_stack.push_back(p);
+ return p;
+ }
+ }
+
+ m_unlinked_stack.push_back(name);
+ return nullptr;
+}
+
+xml_map_tree::element* xml_map_tree::walker::pop_element(const xml_name_t& name)
+{
+ if (!m_unlinked_stack.empty())
+ {
+ // We're in the unlinked region. Pop element from the unlinked stack.
+ if (m_unlinked_stack.back() != name)
+ throw general_error("Closing element has a different name than the opening element. (unlinked stack)");
+
+ m_unlinked_stack.pop_back();
+
+ if (!m_unlinked_stack.empty())
+ // We are still in the unlinked region.
+ return nullptr;
+
+ return m_stack.empty() ? nullptr : m_stack.back();
+ }
+
+ if (m_stack.empty())
+ throw general_error("Element was popped while the stack was empty.");
+
+ if (m_stack.back()->name != name)
+ throw general_error("Closing element has a different name than the opening element. (linked stack)");
+
+ m_stack.pop_back();
+ return m_stack.empty() ? nullptr : m_stack.back();
+}
+
+xml_map_tree::xml_map_tree(xmlns_repository& xmlns_repo) :
+ m_xmlns_cxt(xmlns_repo.create_context()),
+ mp_root(nullptr),
+ m_default_ns(XMLNS_UNKNOWN_ID) {}
+
+xml_map_tree::~xml_map_tree() {}
+
+void xml_map_tree::set_namespace_alias(std::string_view alias, std::string_view uri, bool default_ns)
+{
+#if ORCUS_DEBUG_XML_MAP_TREE
+ cout << "xml_map_tree::set_namespace_alias: alias='" << alias << "', uri='" << uri << "', default=" << default_ns << endl;
+#endif
+ // We need to turn the alias string persistent because the xmlns context
+ // doesn't intern the alias strings.
+ std::string_view alias_safe = m_names.intern(alias).first;
+ xmlns_id_t ns = m_xmlns_cxt.push(alias_safe, uri);
+
+ if (default_ns)
+ m_default_ns = ns;
+}
+
+xmlns_id_t xml_map_tree::get_namespace(std::string_view alias) const
+{
+ return m_xmlns_cxt.get(alias);
+}
+
+void xml_map_tree::set_cell_link(std::string_view xpath, const cell_position& ref)
+{
+ if (xpath.empty())
+ return;
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+ cout << "xml_map_tree::set_cell_link: xpath='" << xpath << "' (ref=" << ref << ")" << endl;
+#endif
+
+ linked_node_type linked_node = get_linked_node(xpath, reference_type::cell);
+ assert(linked_node.node);
+ assert(!linked_node.elem_stack.empty());
+ cell_reference* cell_ref = nullptr;
+ switch (linked_node.node->node_type)
+ {
+ case linkable_node_type::element:
+ assert(static_cast<element*>(linked_node.node)->cell_ref);
+ cell_ref = static_cast<element*>(linked_node.node)->cell_ref;
+ break;
+ case linkable_node_type::attribute:
+ assert(static_cast<attribute*>(linked_node.node)->cell_ref);
+ cell_ref = static_cast<attribute*>(linked_node.node)->cell_ref;
+ break;
+ default:
+ throw general_error("unknown node type returned from get_element_stack call in xml_map_tree::set_cell_link().");
+ }
+
+ cell_ref->pos = ref;
+}
+
+void xml_map_tree::start_range(const cell_position& pos)
+{
+ m_cur_range_field_links.clear();
+ m_cur_range_pos = pos;
+}
+
+void xml_map_tree::append_range_field_link(std::string_view xpath, std::string_view label)
+{
+ if (xpath.empty())
+ return;
+
+ m_cur_range_field_links.emplace_back(xpath, label);
+}
+
+void xml_map_tree::insert_range_field_link(
+ range_reference& range_ref, element_list_type& range_parent, const range_field_link& field)
+{
+ linked_node_type linked_node = get_linked_node(field.xpath, reference_type::range_field);
+ if (linked_node.elem_stack.size() < 2)
+ throw xpath_error("Path of a range field link must be at least 2 levels.");
+
+ if (linked_node.node->node_type == linkable_node_type::unknown)
+ throw xpath_error("Unrecognized node type");
+
+ if (linked_node.anchor_elem)
+ linked_node.anchor_elem->linked_range_fields.push_back(range_ref.field_nodes.size());
+
+ if (!field.label.empty())
+ linked_node.node->label = intern_string(field.label);
+
+ switch (linked_node.node->node_type)
+ {
+ case linkable_node_type::element:
+ {
+ element* p = static_cast<element*>(linked_node.node);
+ assert(p && p->ref_type == reference_type::range_field && p->field_ref);
+ p->field_ref->ref = &range_ref;
+ p->field_ref->column_pos = range_ref.field_nodes.size();
+
+ range_ref.field_nodes.push_back(p);
+ break;
+ }
+ case linkable_node_type::attribute:
+ {
+ attribute* p = static_cast<attribute*>(linked_node.node);
+ assert(p && p->ref_type == reference_type::range_field && p->field_ref);
+ p->field_ref->ref = &range_ref;
+ p->field_ref->column_pos = range_ref.field_nodes.size();
+
+ range_ref.field_nodes.push_back(p);
+ break;
+ }
+ default:
+ ;
+ }
+
+ // Determine the deepest common element for all field link elements in the
+ // current range reference.
+ if (range_parent.empty())
+ {
+ // First field link in this range. Find the first row-group element
+ // going up from the linked node.
+ auto rit = linked_node.elem_stack.rbegin();
+ while (rit != linked_node.elem_stack.rend() && !(*rit)->row_group)
+ ++rit;
+
+ ++rit; // parent of the raw group
+ auto it_end = rit.base();
+
+ range_parent.assign(linked_node.elem_stack.begin(), it_end);
+ }
+ else
+ {
+ // Determine the deepest common element between the two.
+ element_list_type::iterator it_elem = linked_node.elem_stack.begin(), it_elem_end = linked_node.elem_stack.end();
+ element_list_type::iterator it_cur = range_parent.begin(), it_cur_end = range_parent.end();
+ if (*it_elem != *it_cur)
+ throw xpath_error("Two field links in the same range reference start with different root elements.");
+
+ ++it_elem;
+ ++it_cur;
+
+ for (; it_elem != it_elem_end && it_cur != it_cur_end; ++it_elem, ++it_cur)
+ {
+ if (*it_elem == *it_cur)
+ continue;
+
+ // The two elements differ. Take their parent element as the new common element.
+ range_parent.assign(linked_node.elem_stack.begin(), it_elem); // current elemnt excluded.
+ break;
+ }
+
+ if (range_parent.empty())
+ throw xpath_error("Two field links in the same range reference must at least share the first level of their paths.");
+ }
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+ print_element_stack(std::cout, range_parent);
+ std::cout << std::endl;
+#endif
+}
+
+void xml_map_tree::set_range_row_group(std::string_view xpath)
+{
+ if (xpath.empty())
+ return;
+
+ range_reference* range_ref = get_range_reference(m_cur_range_pos);
+ assert(range_ref);
+
+ element* elem = get_element(xpath);
+ assert(elem);
+ elem->row_group = range_ref;
+}
+
+void xml_map_tree::commit_range()
+{
+ if (m_cur_range_field_links.empty())
+ // Nothing to commit.
+ return;
+
+ range_reference* range_ref = get_range_reference(m_cur_range_pos);
+ assert(range_ref);
+
+ // commont parent element for this range.
+ element_list_type range_parent;
+
+ for (const range_field_link& field : m_cur_range_field_links)
+ insert_range_field_link(*range_ref, range_parent, field);
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+ cout << "parent element path for this range: ";
+ for (const element* elem : range_parent)
+ cout << "/" << elem->name.to_string(m_xmlns_cxt, xml_name_t::use_alias);
+ cout << endl;
+#endif
+
+ assert(!range_parent.empty());
+ // Mark the range parent element.
+ range_parent.back()->range_parent = range_ref;
+
+ // Set the current position invalid.
+ m_cur_range_pos.row = -1;
+ m_cur_range_pos.col = -1;
+}
+
+const xml_map_tree::linkable* xml_map_tree::get_link(std::string_view xpath) const
+{
+ if (!mp_root)
+ return nullptr;
+
+ if (xpath.empty())
+ return nullptr;
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+ cout << "xml_map_tree::get_link: xpath = '" << xpath << "'" << endl;
+#endif
+ const linkable* cur_node = mp_root;
+
+ xpath_parser parser(m_xmlns_cxt, xpath.data(), xpath.size(), m_default_ns);
+
+ // Check the root element first.
+ xpath_parser::token token = parser.next();
+ if (cur_node->name.ns != token.ns || cur_node->name.name != token.name)
+ // Root element name doesn't match.
+ return nullptr;
+
+#if ORCUS_DEBUG_XML_MAP_TREE
+ cout << "xml_map_tree::get_link: root = (ns=" << token.ns << ", name=" << token.name << ")" << endl;
+#endif
+ for (token = parser.next(); !token.name.empty(); token = parser.next())
+ {
+ if (token.attribute)
+ {
+ // The current node should be an element and should have an attribute of the same name.
+ if (cur_node->node_type != linkable_node_type::element)
+ return nullptr;
+
+ const element* elem = static_cast<const element*>(cur_node);
+ const attribute_store_type& attrs = elem->attributes;
+ auto it = std::find_if(
+ attrs.begin(), attrs.end(),
+ [&token](const attribute* p) -> bool
+ {
+ return p->name.ns == token.ns && p->name.name == token.name;
+ }
+ );
+
+ if (it == attrs.end())
+ // No such attribute exists.
+ return nullptr;
+
+ return *it;
+ }
+
+ // See if an element of this name exists below the current element.
+
+ if (cur_node->node_type != linkable_node_type::element)
+ return nullptr;
+
+ const element* elem = static_cast<const element*>(cur_node);
+ if (elem->elem_type != element_type::unlinked)
+ return nullptr;
+
+ if (!elem->child_elements)
+ return nullptr;
+
+ auto it = std::find_if(
+ elem->child_elements->begin(), elem->child_elements->end(),
+ [&token](const element* p) -> bool
+ {
+ return p->name.ns == token.ns && p->name.name == token.name;
+ }
+ );
+
+ if (it == elem->child_elements->end())
+ // No such child element exists.
+ return nullptr;
+
+ cur_node = *it;
+ }
+
+ if (cur_node->node_type != linkable_node_type::element || static_cast<const element*>(cur_node)->elem_type == element_type::unlinked)
+ // Non-leaf elements are not links.
+ return nullptr;
+
+ return cur_node;
+}
+
+xml_map_tree::walker xml_map_tree::get_tree_walker() const
+{
+ return walker(*this);
+}
+
+xml_map_tree::range_ref_map_type& xml_map_tree::get_range_references()
+{
+ return m_field_refs;
+}
+
+std::string_view xml_map_tree::intern_string(std::string_view str) const
+{
+ return m_names.intern(str).first;
+}
+
+xml_map_tree::range_reference* xml_map_tree::get_range_reference(const cell_position& pos)
+{
+ range_ref_map_type::iterator it = m_field_refs.lower_bound(pos);
+ if (it == m_field_refs.end() || m_field_refs.key_comp()(pos, it->first))
+ {
+ // This reference does not exist yet. Insert a new one.
+
+ // Make sure the sheet name string is persistent.
+ cell_position pos_safe = pos;
+ pos_safe.sheet = m_names.intern(pos.sheet).first;
+
+ it = m_field_refs.insert(
+ it, range_ref_map_type::value_type(
+ pos_safe,
+ m_range_reference_pool.construct(pos_safe)));
+ }
+
+ return it->second;
+}
+
+void xml_map_tree::create_ref_store(linkable& node)
+{
+ switch (node.ref_type)
+ {
+ case xml_map_tree::reference_type::cell:
+ node.cell_ref = m_cell_reference_pool.construct();
+ break;
+ case xml_map_tree::reference_type::range_field:
+ node.field_ref = m_field_in_range_pool.construct();
+ break;
+ case xml_map_tree::reference_type::unknown:
+ break;
+ }
+}
+
+xml_map_tree::linked_node_type xml_map_tree::get_linked_node(std::string_view xpath, reference_type ref_type)
+{
+ linked_node_type ret;
+
+ assert(!xpath.empty());
+ xpath_parser parser(m_xmlns_cxt, xpath.data(), xpath.size(), m_default_ns);
+
+ // Get the root element first.
+ xpath_parser::token token = parser.next();
+ if (mp_root)
+ {
+ // Make sure the root element's names are the same.
+ if (mp_root->name.ns != token.ns || mp_root->name.name != token.name)
+ throw xpath_error("path begins with inconsistent root level name.");
+ }
+ else
+ {
+ // First time the root element is encountered.
+ if (token.attribute)
+ throw xpath_error("root element cannot be an attribute.");
+
+ auto const nm = m_names.intern(token.name).first; // work around LLVM < 7 libc++ bug
+ mp_root = m_element_pool.construct(
+ element::args_type(
+ *this,
+ xml_name_t(token.ns, nm),
+ element_type::unlinked,
+ reference_type::unknown
+ )
+ );
+ }
+
+ ret.elem_stack.push_back(mp_root);
+ element* cur_element = ret.elem_stack.back();
+ assert(cur_element);
+ assert(cur_element->child_elements);
+
+ element* row_group_elem = nullptr;
+
+ token = parser.next();
+ for (xpath_parser::token token_next = parser.next(); !token_next.name.empty(); token_next = parser.next())
+ {
+ // Check if the current element contains a child element of the same name.
+ if (token.attribute)
+ throw xpath_error("attribute must always be at the end of the path.");
+
+ cur_element = cur_element->get_or_create_child(*this, {token.ns, token.name});
+ ret.elem_stack.push_back(cur_element);
+ token = token_next;
+
+ if (cur_element->row_group)
+ row_group_elem = cur_element;
+ }
+
+ assert(cur_element);
+
+ // Insert a leaf node.
+
+ if (token.attribute)
+ {
+ // This is an attribute. Insert it into the current element.
+ attribute_store_type& attrs = cur_element->attributes;
+
+ // Check if an attribute of the same name already exists.
+ auto it = std::find_if(
+ attrs.begin(), attrs.end(),
+ [&token](const attribute* p) -> bool
+ {
+ return p->name.ns == token.ns && p->name.name == token.name;
+ }
+ );
+
+ if (it != attrs.end())
+ throw xpath_error("This attribute is already linked. You can't link the same attribute twice.");
+
+ auto const nm = m_names.intern(token.name).first; // work around LLVM < 7 libc++ bug
+ attribute* p = m_attribute_pool.construct(
+ attribute::args_type(
+ *this,
+ xml_name_t(token.ns, nm),
+ ref_type
+ )
+ );
+
+ attrs.push_back(p);
+ ret.node = attrs.back();
+ }
+ else
+ {
+ element* elem = cur_element->get_or_create_linked_child(*this, {token.ns, token.name}, ref_type);
+ ret.elem_stack.push_back(elem);
+ ret.node = elem;
+
+ if (elem->row_group)
+ row_group_elem = elem;
+ }
+
+ ret.anchor_elem = row_group_elem;
+ return ret;
+}
+
+xml_map_tree::element* xml_map_tree::get_element(std::string_view xpath)
+{
+ assert(!xpath.empty());
+ xpath_parser parser(m_xmlns_cxt, xpath.data(), xpath.size(), m_default_ns);
+
+ // Get the root element first.
+ xpath_parser::token token = parser.next();
+ if (mp_root)
+ {
+ // Make sure the root element's names are the same.
+ if (mp_root->name.ns != token.ns || mp_root->name.name != token.name)
+ throw xpath_error("path begins with inconsistent root level name.");
+ }
+ else
+ {
+ // First time the root element is encountered.
+ if (token.attribute)
+ throw xpath_error("root element cannot be an attribute.");
+
+ auto const nm = m_names.intern(token.name).first; // work around LLVM < 7 libc++ bug
+ mp_root = m_element_pool.construct(
+ element::args_type(
+ *this,
+ xml_name_t(token.ns, nm),
+ element_type::unlinked,
+ reference_type::unknown
+ )
+ );
+ }
+
+ element* cur_element = mp_root;
+ assert(cur_element->child_elements);
+
+ for (token = parser.next(); !token.name.empty(); token = parser.next())
+ {
+ // Check if the current element contains a child element of the same name.
+ if (token.attribute)
+ throw xpath_error("attribute was not expected.");
+
+ cur_element = cur_element->get_or_create_child(*this, {token.ns, token.name});
+ }
+
+ assert(cur_element);
+ return cur_element;
+}
+
+std::ostream& operator<< (std::ostream& os, const xml_map_tree::linkable& link)
+{
+ if (!link.ns_alias.empty())
+ os << link.ns_alias << ':';
+ os << link.name.name;
+ return os;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_map_tree.hpp b/src/liborcus/xml_map_tree.hpp
new file mode 100644
index 0000000..841df0d
--- /dev/null
+++ b/src/liborcus/xml_map_tree.hpp
@@ -0,0 +1,316 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XML_MAP_TREE_HPP
+#define INCLUDED_ORCUS_XML_MAP_TREE_HPP
+
+#include "orcus/spreadsheet/types.hpp"
+#include "orcus/exception.hpp"
+#include "orcus/types.hpp"
+#include "orcus/xml_namespace.hpp"
+#include "orcus/string_pool.hpp"
+
+#include "spreadsheet_impl_types.hpp"
+
+#include <ostream>
+#include <map>
+#include <vector>
+#include <deque>
+#include <memory>
+
+#include <boost/pool/object_pool.hpp>
+
+namespace orcus {
+
+class xmlns_repository;
+
+/**
+ * Tree structure representing XML-to-sheet mapping rules for mapped XML
+ * import. This structure only contains linked elements and attributes and
+ * their parent elements; it does not contain the entire structure of the
+ * imported XML.
+ */
+class xml_map_tree
+{
+ struct range_field_link
+ {
+ std::string_view xpath;
+ std::string_view label;
+
+ range_field_link(std::string_view _xpath, std::string_view _label);
+ };
+
+public:
+ /**
+ * A single cell position. Used both for single cell as well as range
+ * links. For a range link, this represents the upper-left cell of a
+ * range.
+ */
+ using cell_position = spreadsheet::detail::cell_position_t;
+
+ /**
+ * Positions of opening and closing elements in xml stream.
+ */
+ struct element_position
+ {
+ std::ptrdiff_t open_begin;
+ std::ptrdiff_t open_end;
+ std::ptrdiff_t close_begin;
+ std::ptrdiff_t close_end;
+
+ element_position();
+ };
+
+ struct cell_reference
+ {
+ cell_position pos;
+
+ cell_reference(const cell_reference&) = delete;
+ cell_reference& operator=(const cell_reference&) = delete;
+
+ cell_reference();
+ };
+
+ struct element;
+ struct linkable;
+ using element_store_type = std::deque<element*>;
+ using element_list_type = std::vector<element*>;
+ using const_element_list_type = std::vector<const element*>;
+
+ struct range_reference
+ {
+ cell_position pos;
+
+ /**
+ * List of elements comprising the fields, in order of appearance from
+ * left to right.
+ */
+ std::vector<const linkable*> field_nodes;
+
+ /**
+ * Total number of rows comprising data. This does not include the
+ * label row at the top.
+ */
+ spreadsheet::row_t row_position;
+
+ range_reference(const range_reference&) = delete;
+ range_reference& operator=(const range_reference&) = delete;
+
+ range_reference(const cell_position& _pos);
+
+ void reset();
+ };
+
+ struct field_in_range
+ {
+ range_reference* ref = nullptr;
+ spreadsheet::col_t column_pos = -1;
+ };
+
+ typedef std::map<cell_position, range_reference*> range_ref_map_type;
+
+ enum class linkable_node_type { unknown, element, attribute };
+ enum class reference_type { unknown, cell, range_field };
+ enum class element_type { unknown, linked, unlinked };
+
+ struct linkable
+ {
+ xml_name_t name;
+ linkable_node_type node_type;
+ reference_type ref_type;
+
+ union
+ {
+ cell_reference* cell_ref = nullptr;
+ field_in_range* field_ref;
+ };
+
+ std::string_view label; // custom header label
+ mutable std::string_view ns_alias; // namespace alias used in the content stream.
+
+ linkable(const linkable&) = delete;
+ linkable& operator=(const linkable&) = delete;
+
+ linkable(xml_map_tree& parent, const xml_name_t& _name, linkable_node_type _node_type, reference_type _ref_type);
+ };
+
+ struct attribute : public linkable
+ {
+ using args_type = std::tuple<xml_map_tree&, const xml_name_t&, reference_type>;
+
+ attribute(args_type args);
+ ~attribute();
+ };
+
+ using attribute_store_type = std::deque<attribute*>;
+
+ struct element : public linkable
+ {
+ element_type elem_type;
+ element_store_type* child_elements;
+
+ mutable element_position stream_pos; // position of this element in the content stream
+
+ attribute_store_type attributes;
+
+ /**
+ * Points to a range reference instance of which this element is a
+ * parent. nullptr if this element is not a parent element of any range
+ * reference.
+ */
+ range_reference* range_parent;
+
+ /**
+ * The element is a row-group element (element that defines a row
+ * boundary) if this value is not null. If this is not null, it
+ * points to the range_reference instance it belongs to.
+ */
+ range_reference* row_group;
+
+ spreadsheet::row_t row_group_position;
+
+ std::vector<spreadsheet::col_t> linked_range_fields;
+
+ using args_type = std::tuple<xml_map_tree&, const xml_name_t&, element_type, reference_type>;
+
+ element(args_type args);
+ ~element();
+
+ element* get_child(const xml_name_t& _name);
+
+ element* get_or_create_child(
+ xml_map_tree& parent, const xml_name_t& _name);
+
+ element* get_or_create_linked_child(
+ xml_map_tree& parent, const xml_name_t& _name, reference_type _ref_type);
+
+ void link_reference(xml_map_tree& parent, reference_type _ref_type);
+
+ /**
+ * Unlinked attribute anchor is an element that's not linked but has
+ * one or more attributes that are linked.
+ *
+ * @return true if the element is an unlinked attribute anchor, false
+ * otherwise.
+ */
+ bool unlinked_attribute_anchor() const;
+ };
+
+ friend struct linkable;
+
+public:
+
+ /**
+ * Wrapper class to allow walking through the element tree.
+ */
+ class walker
+ {
+ typedef std::vector<element*> ref_element_stack_type;
+ typedef std::vector<xml_name_t> name_stack_type;
+ const xml_map_tree& m_parent;
+ ref_element_stack_type m_stack;
+ name_stack_type m_unlinked_stack;
+ public:
+ walker(const xml_map_tree& parent);
+ walker(const walker& r);
+
+ void reset();
+ element* push_element(const xml_name_t& name);
+ element* pop_element(const xml_name_t& name);
+ };
+
+ xml_map_tree() = delete;
+ xml_map_tree(const xml_map_tree&) = delete;
+ xml_map_tree& operator=(const xml_map_tree&) = delete;
+
+ xml_map_tree(xmlns_repository& xmlns_repo);
+ ~xml_map_tree();
+
+ void set_namespace_alias(std::string_view alias, std::string_view uri, bool default_ns);
+ xmlns_id_t get_namespace(std::string_view alias) const;
+
+ void set_cell_link(std::string_view xpath, const cell_position& ref);
+
+ void start_range(const cell_position& pos);
+ void append_range_field_link(std::string_view xpath, std::string_view label);
+ void set_range_row_group(std::string_view xpath);
+ void commit_range();
+
+ const linkable* get_link(std::string_view xpath) const;
+
+ walker get_tree_walker() const;
+
+ range_ref_map_type& get_range_references();
+
+ std::string_view intern_string(std::string_view str) const;
+
+private:
+ void insert_range_field_link(
+ range_reference& range_ref, element_list_type& range_parent, const range_field_link& field);
+
+ range_reference* get_range_reference(const cell_position& pos);
+
+ void create_ref_store(linkable& node);
+
+ struct linked_node_type
+ {
+ element_list_type elem_stack;
+ linkable* node = nullptr;
+ element* anchor_elem = nullptr;
+ };
+
+ /**
+ * Get a linked node (element or attribute) referenced by the specified
+ * xpath.
+ *
+ * @param xpath path to the linked node.
+ * @param type type of reference, either a cell or a range field.
+ */
+ linked_node_type get_linked_node(std::string_view xpath, reference_type type);
+
+ element* get_element(std::string_view xpath);
+
+private:
+
+ using range_field_links = std::vector<range_field_link>;
+
+ xmlns_context m_xmlns_cxt;
+
+ /**
+ * Stores field links to insert into the current range reference.
+ */
+ range_field_links m_cur_range_field_links;
+
+ cell_position m_cur_range_pos;
+
+ /**
+ * All range references present in the tree. This container manages the
+ * life cycles of stored range references.
+ */
+ range_ref_map_type m_field_refs;
+
+ /** pool of element names. */
+ mutable string_pool m_names;
+
+ boost::object_pool<element_store_type> m_element_store_pool;
+ boost::object_pool<cell_reference> m_cell_reference_pool;
+ boost::object_pool<range_reference> m_range_reference_pool;
+ boost::object_pool<field_in_range> m_field_in_range_pool;
+ boost::object_pool<attribute> m_attribute_pool;
+ boost::object_pool<element> m_element_pool;
+
+ element* mp_root;
+
+ xmlns_id_t m_default_ns;
+};
+
+std::ostream& operator<< (std::ostream& os, const xml_map_tree::linkable& link);
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_map_tree_test.cpp b/src/liborcus/xml_map_tree_test.cpp
new file mode 100644
index 0000000..f3523f1
--- /dev/null
+++ b/src/liborcus/xml_map_tree_test.cpp
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "test_global.hpp"
+#include "xml_map_tree.hpp"
+#include "orcus/xml_namespace.hpp"
+
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+
+using namespace orcus;
+
+void test_path_insertion()
+{
+ ORCUS_TEST_FUNC_SCOPE;
+
+ xmlns_repository repo;
+ xml_map_tree tree(repo);
+ xml_map_tree::cell_position ref;
+ ref.sheet = std::string_view{"test"};
+ ref.row = 2;
+ ref.col = 1;
+
+ // Single cell links
+ tree.set_cell_link("/data/elem1", ref);
+ const xml_map_tree::linkable* p0 = tree.get_link("/data/elem1");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ const xml_map_tree::element* p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p->ref_type == xml_map_tree::reference_type::cell);
+ assert(p->cell_ref->pos.sheet == "test");
+ assert(p->cell_ref->pos.row == 2);
+ assert(p->cell_ref->pos.col == 1);
+
+ const xml_map_tree::element* elem1 = p;
+
+ ref.row = 3;
+ ref.col = 2;
+ tree.set_cell_link("/data/elem2", ref);
+ p0 = tree.get_link("/data/elem2");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p && p->ref_type == xml_map_tree::reference_type::cell);
+ assert(p->cell_ref->pos.sheet == "test");
+ assert(p->cell_ref->pos.row == 3);
+ assert(p->cell_ref->pos.col == 2);
+
+ // The link in elem1 should be unchanged.
+ p0 = tree.get_link("/data/elem1");
+ assert(p0 == elem1);
+
+ ref.sheet = std::string_view{"test2"};
+ ref.row = 10;
+ ref.col = 5;
+ tree.set_cell_link("/data/meta/title", ref);
+ p0 = tree.get_link("/data/meta/title");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p && p->ref_type == xml_map_tree::reference_type::cell);
+ assert(p->cell_ref->pos.sheet == "test2");
+ assert(p->cell_ref->pos.row == 10);
+ assert(p->cell_ref->pos.col == 5);
+
+ // Range field links
+ ref.row = 5;
+ ref.col = 0;
+ ref.sheet = std::string_view{"test3"};
+ tree.start_range(ref);
+ tree.append_range_field_link("/data/entries/entry/id", std::string_view{});
+ tree.append_range_field_link("/data/entries/entry/name", std::string_view{});
+ tree.append_range_field_link("/data/entries/entry/score", std::string_view{});
+ tree.set_range_row_group("/data/entries/entry");
+ tree.commit_range();
+ p0 = tree.get_link("/data/entries/entry/id");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p && p->ref_type == xml_map_tree::reference_type::range_field);
+ assert(p->field_ref->ref->pos.sheet == "test3");
+ assert(p->field_ref->ref->pos.row == 5);
+ assert(p->field_ref->ref->pos.col == 0);
+ assert(p->field_ref->column_pos == 0);
+
+ p0 = tree.get_link("/data/entries/entry/name");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p && p->ref_type == xml_map_tree::reference_type::range_field);
+ assert(p->field_ref->ref->pos.sheet == "test3");
+ assert(p->field_ref->ref->pos.row == 5);
+ assert(p->field_ref->ref->pos.col == 0);
+ assert(p->field_ref->column_pos == 1);
+
+ p0 = tree.get_link("/data/entries/entry/score");
+ assert(p0 && p0->node_type == xml_map_tree::linkable_node_type::element);
+ p = static_cast<const xml_map_tree::element*>(p0);
+ assert(p && p->ref_type == xml_map_tree::reference_type::range_field);
+ assert(p->field_ref->ref->pos.sheet == "test3");
+ assert(p->field_ref->ref->pos.row == 5);
+ assert(p->field_ref->ref->pos.col == 0);
+ assert(p->field_ref->column_pos == 2);
+}
+
+void test_attr_path_insertion()
+{
+ ORCUS_TEST_FUNC_SCOPE;
+
+ xmlns_repository repo;
+ xml_map_tree tree(repo);
+ xml_map_tree::cell_position ref;
+ ref.sheet = std::string_view{"test"};
+ ref.row = 2;
+ ref.col = 3;
+
+ // 'attr1' is an attribute of 'elem'.
+ tree.set_cell_link("/root/elem/@attr1", ref);
+ const xml_map_tree::linkable* p = tree.get_link("/root/elem/@attr1");
+ assert(p && p->node_type == xml_map_tree::linkable_node_type::attribute);
+ const xml_map_tree::attribute* attr = static_cast<const xml_map_tree::attribute*>(p);
+ assert(attr->ref_type == xml_map_tree::reference_type::cell);
+ assert(attr->cell_ref->pos.sheet == "test");
+ assert(attr->cell_ref->pos.row == 2);
+ assert(attr->cell_ref->pos.col == 3);
+
+ // Insert another attribute in the same element.
+ ref.sheet = std::string_view{"test2"};
+ ref.row = 11;
+ ref.col = 4;
+ tree.set_cell_link("/root/elem/@attr2", ref);
+ p = tree.get_link("/root/elem/@attr2");
+ assert(p && p->node_type == xml_map_tree::linkable_node_type::attribute);
+ attr = static_cast<const xml_map_tree::attribute*>(p);
+ assert(attr->ref_type == xml_map_tree::reference_type::cell);
+ assert(attr->cell_ref->pos.sheet == "test2");
+ assert(attr->cell_ref->pos.row == 11);
+ assert(attr->cell_ref->pos.col == 4);
+
+ // At this point, /root/elem is not linked.
+ p = tree.get_link("/root/elem");
+ assert(!p);
+
+ // Now, link /root/elem.
+ ref.sheet = std::string_view{"test3"};
+ ref.row = 4;
+ ref.col = 6;
+ tree.set_cell_link("/root/elem", ref);
+ p = tree.get_link("/root/elem");
+ assert(p && p->node_type == xml_map_tree::linkable_node_type::element);
+ const xml_map_tree::element* elem = static_cast<const xml_map_tree::element*>(p);
+ assert(elem->elem_type == xml_map_tree::element_type::linked);
+ assert(elem->ref_type == xml_map_tree::reference_type::cell);
+ assert(elem->cell_ref->pos.sheet == "test3");
+ assert(elem->cell_ref->pos.row == 4);
+ assert(elem->cell_ref->pos.col == 6);
+}
+
+void test_tree_walk()
+{
+ ORCUS_TEST_FUNC_SCOPE;
+
+ xmlns_repository repo;
+ xml_map_tree tree(repo);
+ xml_map_tree::cell_position ref;
+ ref.sheet = std::string_view{"test"};
+ ref.row = 2;
+ ref.col = 1;
+
+ tree.set_cell_link("/data/header/title", ref);
+ xml_map_tree::walker walker = tree.get_tree_walker();
+ walker.reset();
+
+ // Root element.
+ const xml_map_tree::element* elem = walker.push_element({XMLNS_UNKNOWN_ID, "data"});
+ assert(elem);
+ assert(elem->name.name == "data");
+ assert(elem->elem_type == xml_map_tree::element_type::unlinked);
+
+ elem = walker.push_element({XMLNS_UNKNOWN_ID, "header"});
+ assert(elem);
+ assert(elem->name.name == "header");
+ assert(elem->elem_type == xml_map_tree::element_type::unlinked);
+
+ elem = walker.push_element({XMLNS_UNKNOWN_ID, "title"});
+ assert(elem);
+ assert(elem->name.name == "title");
+ assert(elem->ref_type == xml_map_tree::reference_type::cell);
+
+ elem = walker.pop_element({XMLNS_UNKNOWN_ID, "title"});
+ assert(elem);
+ assert(elem->name.name == "header");
+ assert(elem->elem_type == xml_map_tree::element_type::unlinked);
+
+ elem = walker.pop_element({XMLNS_UNKNOWN_ID, "header"});
+ assert(elem);
+ assert(elem->name.name == "data");
+ assert(elem->elem_type == xml_map_tree::element_type::unlinked);
+
+ elem = walker.pop_element({XMLNS_UNKNOWN_ID, "data"});
+ assert(!elem);
+}
+
+void test_tree_walk_namespace()
+{
+ ORCUS_TEST_FUNC_SCOPE;
+
+ xmlns_repository repo;
+ xml_map_tree tree(repo);
+ xml_map_tree::cell_position ref;
+ ref.sheet = std::string_view{"data"};
+ ref.row = 1;
+ ref.col = 2;
+
+ tree.set_namespace_alias("a", "http://some-namespace", false);
+ tree.set_namespace_alias("skip", "http://namespace-to-skip", false);
+ tree.set_cell_link("/a:table/a:title", ref);
+ tree.start_range(ref);
+ ref.row = 2;
+ ref.col = 0;
+ tree.append_range_field_link("/a:table/a:rows/a:row/a:city", std::string_view{});
+ ++ref.col;
+ tree.append_range_field_link("/a:table/a:rows/a:row/a:population", std::string_view{});
+ ++ref.col;
+ tree.append_range_field_link("/a:table/a:rows/a:row/a:year", std::string_view{});
+ tree.set_range_row_group("/a:table/a:rows/a:row");
+ tree.commit_range();
+
+ xmlns_id_t ns_a = tree.get_namespace("a");
+ assert(ns_a != XMLNS_UNKNOWN_ID);
+ xmlns_id_t ns_skip = tree.get_namespace("skip");
+ assert(ns_skip != XMLNS_UNKNOWN_ID);
+
+ xml_map_tree::walker walker = tree.get_tree_walker();
+ walker.reset();
+
+ // Root element. This is not linked.
+ const xml_map_tree::element* elem = walker.push_element({ns_a, "table"});
+ assert(elem);
+ assert(elem->name.ns == ns_a);
+ assert(elem->name.name == "table");
+ assert(elem->node_type == xml_map_tree::linkable_node_type::element);
+ assert(elem->elem_type == xml_map_tree::element_type::unlinked);
+ assert(elem->ref_type == xml_map_tree::reference_type::unknown);
+
+ // Intentionally push a foreign element.
+ const xml_map_tree::element* elem_old = elem;
+ elem = walker.push_element({ns_skip, "foo"});
+ assert(!elem);
+ elem = walker.pop_element({ns_skip, "foo"});
+ assert(elem == elem_old);
+
+ // Push a foreign element and a valid element under it. A valid element
+ // placed under a foreign element should be invalid.
+ elem_old = elem;
+ elem = walker.push_element({ns_skip, "foo"});
+ assert(!elem);
+ elem = walker.push_element({ns_a, "title"});
+ assert(!elem);
+ elem = walker.pop_element({ns_a, "title"});
+ assert(!elem);
+ elem = walker.pop_element({ns_skip, "foo"});
+ assert(elem == elem_old);
+}
+
+int main()
+{
+ test_path_insertion();
+ test_attr_path_insertion();
+ test_tree_walk();
+ test_tree_walk_namespace();
+ return EXIT_SUCCESS;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_simple_stream_handler.cpp b/src/liborcus/xml_simple_stream_handler.cpp
new file mode 100644
index 0000000..1ee7c1d
--- /dev/null
+++ b/src/liborcus/xml_simple_stream_handler.cpp
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_simple_stream_handler.hpp"
+#include "xml_context_base.hpp"
+
+#include <cassert>
+
+namespace orcus {
+
+xml_simple_stream_handler::xml_simple_stream_handler(
+ session_context& session_cxt, const tokens& t, std::unique_ptr<xml_context_base> context) :
+ xml_stream_handler(session_cxt, t, std::move(context))
+{
+}
+
+xml_simple_stream_handler::~xml_simple_stream_handler()
+{
+}
+
+xml_context_base& xml_simple_stream_handler::get_context()
+{
+ return get_current_context();
+}
+
+void xml_simple_stream_handler::start_document()
+{
+}
+
+void xml_simple_stream_handler::end_document()
+{
+}
+
+void xml_simple_stream_handler::start_element(const xml_token_element_t& elem)
+{
+ get_current_context().start_element(elem.ns, elem.name, elem.attrs);
+}
+
+void xml_simple_stream_handler::end_element(const xml_token_element_t& elem)
+{
+ get_current_context().end_element(elem.ns, elem.name);
+}
+
+void xml_simple_stream_handler::characters(std::string_view str, bool transient)
+{
+ get_current_context().characters(str, transient);
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_simple_stream_handler.hpp b/src/liborcus/xml_simple_stream_handler.hpp
new file mode 100644
index 0000000..186e7d3
--- /dev/null
+++ b/src/liborcus/xml_simple_stream_handler.hpp
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef __ORCUS_XML_SIMPLE_HANDLER_HPP__
+#define __ORCUS_XML_SIMPLE_HANDLER_HPP__
+
+#include "xml_stream_handler.hpp"
+
+namespace orcus {
+
+class xml_context_base;
+
+/**
+ * Simple stream handler that only uses a single context instance.
+ */
+class xml_simple_stream_handler : public xml_stream_handler
+{
+public:
+ xml_simple_stream_handler(
+ session_context& session_cxt, const tokens& t, std::unique_ptr<xml_context_base> context);
+ virtual ~xml_simple_stream_handler() override;
+
+ xml_context_base& get_context();
+
+ virtual void start_document() override;
+ virtual void end_document() override;
+
+ virtual void start_element(const xml_token_element_t& elem) override;
+ virtual void end_element(const xml_token_element_t& elem) override;
+ virtual void characters(std::string_view str, bool transient) override;
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_stream_handler.cpp b/src/liborcus/xml_stream_handler.cpp
new file mode 100644
index 0000000..859a08f
--- /dev/null
+++ b/src/liborcus/xml_stream_handler.cpp
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_stream_handler.hpp"
+#include "xml_context_base.hpp"
+#include "xml_empty_context.hpp"
+
+#include "orcus/exception.hpp"
+
+#include <iostream>
+
+namespace orcus {
+
+xml_stream_handler::xml_stream_handler(
+ session_context& session_cxt, const tokens& t, std::unique_ptr<xml_context_base> root_context) :
+ m_session_cxt(session_cxt),
+ m_tokens(t),
+ m_config(format_t::unknown),
+ m_elem_printer(m_tokens),
+ mp_root_context(std::move(root_context)),
+ mp_invalid_context(std::make_unique<xml_empty_context>(session_cxt, t))
+{
+ assert(mp_root_context);
+ m_context_stack.push_back(mp_root_context.get());
+}
+
+xml_stream_handler::~xml_stream_handler()
+{
+}
+
+void xml_stream_handler::start_document()
+{
+}
+
+void xml_stream_handler::end_document()
+{
+}
+
+void xml_stream_handler::declaration(const xml_declaration_t& decl)
+{
+ get_current_context().declaration(decl);
+}
+
+void xml_stream_handler::start_element(const xml_token_element_t& elem)
+{
+ xml_context_base& cur = get_current_context();
+ if (cur.evaluate_child_element(elem.ns, elem.name))
+ {
+ // new child element is valid against parent element.
+ xml_context_base* p = cur.create_child_context(elem.ns, elem.name);
+ if (p)
+ m_context_stack.push_back(p);
+ }
+ else
+ {
+ // new child element is not valid for the current element. Ignore the
+ // whole sub structure.
+ m_context_stack.push_back(&get_invalid_context());
+
+ if (m_config.debug)
+ {
+ // TODO: print the top element of the sub structure being ignored.
+ std::cerr << "warning: ignoring the whole sub-structure below ";
+ m_elem_printer.print_element(std::cerr, elem.ns, elem.name);
+ std::cerr << std::endl;
+ }
+ }
+
+ get_current_context().start_element(elem.ns, elem.name, elem.attrs);
+}
+
+void xml_stream_handler::end_element(const xml_token_element_t& elem)
+{
+ bool ended = get_current_context().end_element(elem.ns, elem.name);
+
+ if (ended)
+ {
+ size_t n = m_context_stack.size();
+
+ if (n > 1)
+ {
+ // Call end_child_context of the parent context to provide a way for
+ // the two adjacent contexts to communicate with each other.
+ context_stack_type::reverse_iterator itr_cur = m_context_stack.rbegin();
+ context_stack_type::reverse_iterator itr_par = itr_cur + 1;
+ (*itr_par)->end_child_context(elem.ns, elem.name, *itr_cur);
+ }
+
+ m_context_stack.pop_back();
+ }
+}
+
+void xml_stream_handler::characters(std::string_view str, bool transient)
+{
+ get_current_context().characters(str, transient);
+}
+
+void xml_stream_handler::set_ns_context(const xmlns_context* p)
+{
+ for (auto* context : m_context_stack)
+ context->set_ns_context(p);
+
+ mp_invalid_context->set_ns_context(p);
+ m_elem_printer.set_ns_context(p);
+}
+
+void xml_stream_handler::set_config(const config& opt)
+{
+ m_config = opt;
+ for (auto* context : m_context_stack)
+ context->set_config(m_config);
+
+ mp_invalid_context->set_config(m_config);
+}
+
+xml_context_base& xml_stream_handler::get_current_context()
+{
+ if (m_context_stack.empty())
+ return *mp_root_context;
+
+ return *m_context_stack.back();
+}
+
+xml_context_base& xml_stream_handler::get_root_context()
+{
+ return *mp_root_context;
+}
+
+xml_context_base& xml_stream_handler::get_invalid_context()
+{
+ return *mp_invalid_context;
+}
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_stream_handler.hpp b/src/liborcus/xml_stream_handler.hpp
new file mode 100644
index 0000000..2b09c95
--- /dev/null
+++ b/src/liborcus/xml_stream_handler.hpp
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ORCUS_XML_STREAM_HANDLER_HPP
+#define ORCUS_XML_STREAM_HANDLER_HPP
+
+#include <orcus/sax_token_parser.hpp>
+#include <orcus/config.hpp>
+
+#include "xml_util.hpp"
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace orcus {
+
+class xml_context_base;
+class xmlns_context;
+struct session_context;
+
+class xml_stream_handler
+{
+ session_context& m_session_cxt;
+ const tokens& m_tokens;
+
+ config m_config;
+ xml_element_printer m_elem_printer;
+ std::unique_ptr<xml_context_base> mp_root_context;
+ std::unique_ptr<xml_context_base> mp_invalid_context;
+ typedef std::vector<xml_context_base*> context_stack_type;
+ context_stack_type m_context_stack;
+
+public:
+ xml_stream_handler() = delete;
+ xml_stream_handler(const xml_stream_handler&) = delete;
+
+ xml_stream_handler(session_context& session_cxt, const tokens& t, std::unique_ptr<xml_context_base> root_context);
+ virtual ~xml_stream_handler();
+
+ virtual void start_document();
+ virtual void end_document();
+
+ virtual void declaration(const xml_declaration_t& decl);
+ virtual void start_element(const xml_token_element_t& elem);
+ virtual void end_element(const xml_token_element_t& elem);
+ virtual void characters(std::string_view str, bool transient);
+
+ void set_ns_context(const xmlns_context* p);
+ void set_config(const config& opt);
+
+protected:
+ xml_context_base& get_current_context();
+ xml_context_base& get_root_context();
+ xml_context_base& get_invalid_context();
+};
+
+}
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_stream_parser.cpp b/src/liborcus/xml_stream_parser.cpp
new file mode 100644
index 0000000..895821c
--- /dev/null
+++ b/src/liborcus/xml_stream_parser.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_stream_parser.hpp"
+#include "xml_stream_handler.hpp"
+
+#include "orcus/tokens.hpp"
+
+#include "orcus/threaded_sax_token_parser.hpp"
+#include "orcus/sax_token_parser.hpp"
+
+#include <iostream>
+#include <vector>
+#include <sstream>
+
+using namespace std;
+
+namespace orcus {
+
+xml_stream_parser_base::xml_stream_parser_base(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size) :
+ m_config(opt),
+ m_ns_cxt(ns_repo.create_context()),
+ m_tokens(tokens),
+ mp_handler(nullptr),
+ m_content(content),
+ m_size(size)
+{
+}
+
+xml_stream_parser_base::~xml_stream_parser_base()
+{
+}
+
+void xml_stream_parser_base::set_handler(xml_stream_handler* handler)
+{
+ mp_handler = handler;
+ if (mp_handler)
+ {
+ mp_handler->set_ns_context(&m_ns_cxt);
+ mp_handler->set_config(m_config);
+ }
+}
+
+xml_stream_handler* xml_stream_parser_base::get_handler() const
+{
+ return mp_handler;
+}
+
+xml_stream_parser::xml_stream_parser(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size) :
+ xml_stream_parser_base(opt, ns_repo, tokens, content, size) {}
+
+xml_stream_parser::~xml_stream_parser() {}
+
+void xml_stream_parser::parse()
+{
+ if (!mp_handler)
+ return;
+
+ sax_token_parser<xml_stream_handler> sax({m_content, m_size}, m_tokens, m_ns_cxt, *mp_handler);
+ sax.parse();
+}
+
+threaded_xml_stream_parser::threaded_xml_stream_parser(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size) :
+ xml_stream_parser_base(opt, ns_repo, tokens, content, size) {}
+
+threaded_xml_stream_parser::~threaded_xml_stream_parser() {}
+
+void threaded_xml_stream_parser::parse()
+{
+ if (!mp_handler)
+ return;
+
+ threaded_sax_token_parser<xml_stream_handler> sax(m_content, m_size, m_tokens, m_ns_cxt, *mp_handler, 1000);
+ sax.parse();
+
+ sax.swap_string_pool(m_pool);
+}
+
+void threaded_xml_stream_parser::swap_string_pool(string_pool& pool)
+{
+ m_pool.swap(pool);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_stream_parser.hpp b/src/liborcus/xml_stream_parser.hpp
new file mode 100644
index 0000000..0b75222
--- /dev/null
+++ b/src/liborcus/xml_stream_parser.hpp
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XMLPARSER_HPP
+#define INCLUDED_ORCUS_XMLPARSER_HPP
+
+#include <cstdlib>
+#include <string>
+#include <exception>
+
+#include "orcus/xml_namespace.hpp"
+#include "orcus/string_pool.hpp"
+
+namespace orcus {
+
+struct config;
+
+class xml_stream_handler;
+class tokens;
+
+/**
+ * This class does NOT store the stream content which is just a pointer to
+ * the first char of the content stream. Make sure you finish parsing while
+ * the content pointer is valid.
+ */
+class xml_stream_parser_base
+{
+public:
+ xml_stream_parser_base() = delete;
+
+ virtual void parse() = 0;
+
+ void set_handler(xml_stream_handler* handler);
+ xml_stream_handler* get_handler() const;
+
+protected:
+ xml_stream_parser_base(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size);
+ virtual ~xml_stream_parser_base();
+
+ const config& m_config;
+ xmlns_context m_ns_cxt;
+ const tokens& m_tokens;
+ xml_stream_handler* mp_handler;
+ const char* m_content;
+ size_t m_size;
+};
+
+class xml_stream_parser : public xml_stream_parser_base
+{
+public:
+ xml_stream_parser(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size);
+ virtual ~xml_stream_parser() override;
+
+ virtual void parse() override;
+};
+
+class threaded_xml_stream_parser : public xml_stream_parser_base
+{
+ string_pool m_pool;
+
+public:
+ threaded_xml_stream_parser(
+ const config& opt,
+ xmlns_repository& ns_repo, const tokens& tokens, const char* content, size_t size);
+ virtual ~threaded_xml_stream_parser() override;
+
+ virtual void parse() override;
+
+ void swap_string_pool(string_pool& pool);
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_structure_mapper.cpp b/src/liborcus/xml_structure_mapper.cpp
new file mode 100644
index 0000000..1242947
--- /dev/null
+++ b/src/liborcus/xml_structure_mapper.cpp
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_structure_mapper.hpp"
+
+namespace orcus { namespace detail {
+
+xml_structure_mapper::xml_structure_mapper(
+ xml_structure_tree::range_handler_type rh, const xml_structure_tree::walker& walker) :
+ m_range_handler(std::move(rh)),
+ m_walker(walker),
+ m_repeat_count(0)
+{
+}
+
+void xml_structure_mapper::run()
+{
+ reset();
+ traverse();
+}
+
+void xml_structure_mapper::reset()
+{
+ m_cur_elem = m_walker.root();
+ m_repeat_count = 0;
+}
+
+void xml_structure_mapper::traverse()
+{
+ auto elem = m_cur_elem;
+ const bool row_group = elem.repeat;
+
+ if (row_group)
+ {
+ ++m_repeat_count;
+ m_current_range.row_groups.push_back(m_walker.get_path());
+ }
+
+ xml_structure_tree::entity_names_type children = m_walker.get_children();
+
+ if (m_repeat_count)
+ {
+ std::string path = m_walker.get_path();
+
+ xml_structure_tree::entity_names_type attr_names = m_walker.get_attributes();
+ for (const auto& attr_name : attr_names)
+ {
+ std::string attr_path = path + "/@" + m_walker.to_string(attr_name);
+ m_current_range.paths.push_back(attr_path);
+ }
+
+ if (children.empty() && elem.has_content)
+ // Only add leaf elements to the range, and only those with contents.
+ m_current_range.paths.push_back(path);
+ }
+
+ for (const auto& child_name : children)
+ {
+ m_cur_elem = m_walker.descend(child_name);
+ traverse();
+ m_cur_elem = m_walker.ascend();
+ }
+
+ if (row_group)
+ {
+ --m_repeat_count;
+
+ if (!m_repeat_count)
+ push_range();
+ }
+}
+
+void xml_structure_mapper::push_range()
+{
+ m_range_handler(std::move(m_current_range));
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_structure_mapper.hpp b/src/liborcus/xml_structure_mapper.hpp
new file mode 100644
index 0000000..aae4bfa
--- /dev/null
+++ b/src/liborcus/xml_structure_mapper.hpp
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_XML_STRUCTURE_MAPPER_HPP
+#define INCLUDED_XML_STRUCTURE_MAPPER_HPP
+
+#include "orcus/xml_structure_tree.hpp"
+
+namespace orcus { namespace detail {
+
+class xml_structure_mapper
+{
+ xml_table_range_t m_current_range;
+
+ xml_structure_tree::range_handler_type m_range_handler;
+ xml_structure_tree::walker m_walker;
+ xml_structure_tree::element m_cur_elem;
+ size_t m_repeat_count;
+
+ void reset();
+
+ void traverse();
+
+ void push_range();
+
+public:
+ xml_structure_mapper(xml_structure_tree::range_handler_type rh, const xml_structure_tree::walker& walker);
+
+ void run();
+};
+
+}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_structure_tree.cpp b/src/liborcus/xml_structure_tree.cpp
new file mode 100644
index 0000000..dbdb029
--- /dev/null
+++ b/src/liborcus/xml_structure_tree.cpp
@@ -0,0 +1,625 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/xml_structure_tree.hpp>
+#include <orcus/sax_ns_parser.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <orcus/exception.hpp>
+#include <orcus/string_pool.hpp>
+
+#include "string_helper.hpp"
+#include "xml_structure_mapper.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cstdio>
+#include <memory>
+
+#include <unordered_map>
+#include <unordered_set>
+
+namespace orcus {
+
+namespace {
+
+/** Element properties. */
+struct elem_prop
+{
+ using element_store_type = std::unordered_map<
+ xml_structure_tree::entity_name, std::unique_ptr<elem_prop>, xml_structure_tree::entity_name::hash>;
+
+ using attribute_names_type = std::unordered_set<
+ xml_structure_tree::entity_name, xml_structure_tree::entity_name::hash>;
+
+ element_store_type child_elements;
+ attribute_names_type attributes;
+
+ /** Store child element names in order of appearance. */
+ xml_structure_tree::entity_names_type child_element_names;
+
+ /** Store attribute names in order of appearance. */
+ xml_structure_tree::entity_names_type attribute_names;
+
+ size_t appearance_order;
+
+ size_t in_scope_count;
+
+ /**
+ * When true, this element is the base element of repeated structures.
+ * This flag is set only with the base element; none of the child
+ * elements below the base element have this flag set.
+ */
+ bool repeat;
+
+ bool has_content;
+
+ elem_prop(const elem_prop&) = delete;
+ elem_prop& operator=(const elem_prop&) = delete;
+
+ elem_prop() :
+ appearance_order(0),
+ in_scope_count(1),
+ repeat(false),
+ has_content(false) {}
+
+ elem_prop(size_t _appearance_order) :
+ appearance_order(_appearance_order),
+ in_scope_count(1),
+ repeat(false),
+ has_content(false) {}
+};
+
+struct root
+{
+ xml_structure_tree::entity_name name;
+ elem_prop prop;
+};
+
+struct element_ref
+{
+ xml_structure_tree::entity_name name;
+ elem_prop* prop;
+
+ element_ref() : prop(nullptr) {}
+ element_ref(xml_structure_tree::entity_name _name, elem_prop* _prop) :
+ name(_name), prop(_prop) {}
+};
+
+typedef std::vector<element_ref> elements_type;
+
+class xml_sax_handler
+{
+ string_pool& m_pool;
+ std::unique_ptr<root> mp_root;
+ elements_type m_stack;
+ xml_structure_tree::entity_names_type m_attrs;
+
+private:
+ void merge_attributes(elem_prop& prop)
+ {
+ xml_structure_tree::entity_names_type::const_iterator it = m_attrs.begin(), it_end = m_attrs.end();
+ for (; it != it_end; ++it)
+ {
+ if (prop.attributes.find(*it) == prop.attributes.end())
+ {
+ // New attribute. Insert it.
+ prop.attributes.insert(*it);
+ prop.attribute_names.push_back(*it);
+ }
+ }
+
+ m_attrs.clear();
+ }
+
+public:
+ xml_sax_handler(string_pool& pool) :
+ m_pool(pool), mp_root(nullptr) {}
+
+ void doctype(const sax::doctype_declaration&) {}
+
+ void start_declaration(std::string_view /*name*/)
+ {
+ }
+
+ void end_declaration(std::string_view /*name*/)
+ {
+ m_attrs.clear();
+ }
+
+ void start_element(const sax_ns_parser_element& elem)
+ {
+ if (!mp_root)
+ {
+ // This is a root element.
+ mp_root.reset(new root);
+ mp_root->name.ns = elem.ns;
+ mp_root->name.name = m_pool.intern(elem.name).first;
+ element_ref ref(mp_root->name, &mp_root->prop);
+ merge_attributes(mp_root->prop);
+ m_stack.push_back(ref);
+ return;
+ }
+
+ // See if the current element already has a child element of the same name.
+ assert(!m_stack.empty());
+ element_ref& current = m_stack.back();
+ xml_structure_tree::entity_name key(elem.ns, elem.name);
+ auto it = current.prop->child_elements.find(key);
+ if (it != current.prop->child_elements.end())
+ {
+ // Recurring element. Set its repeat flag only when it occurs
+ // multiple times in the same scope.
+ ++it->second->in_scope_count;
+ if (it->second->in_scope_count > 1)
+ it->second->repeat = true;
+
+ element_ref ref(it->first, it->second.get());
+ merge_attributes(*it->second);
+ m_stack.push_back(ref);
+ return;
+ }
+
+ // New element.
+ size_t order = current.prop->child_elements.size();
+ key.name = m_pool.intern(key.name).first;
+ auto r = current.prop->child_elements.insert(
+ std::make_pair(key, std::make_unique<elem_prop>(order)));
+
+ if (!r.second)
+ throw general_error("Insertion failed");
+
+ current.prop->child_element_names.push_back(key);
+
+ it = r.first;
+ element_ref ref(it->first, it->second.get());
+ merge_attributes(*it->second);
+ m_stack.push_back(ref);
+ }
+
+ void end_element(const sax_ns_parser_element& /*elem*/)
+ {
+ if (m_stack.empty())
+ throw general_error("Element stack is empty.");
+
+ const element_ref& current = m_stack.back();
+
+ // Reset the in-scope count of all child elements to 0 before ending
+ // the current scope.
+ for (auto& [name, p] : current.prop->child_elements)
+ p->in_scope_count = 0;
+
+ m_stack.pop_back();
+ }
+
+ void characters(std::string_view, bool)
+ {
+ if (m_stack.empty())
+ return;
+
+ element_ref& current = m_stack.back();
+ current.prop->has_content = true;
+ }
+
+ void attribute(std::string_view, std::string_view)
+ {
+ // Attribute for declaration. We don't handle this.
+ }
+
+ void attribute(const sax_ns_parser_attribute& attr)
+ {
+ m_attrs.push_back(xml_structure_tree::entity_name(attr.ns, attr.name));
+ }
+
+ std::unique_ptr<root> release_root_element()
+ {
+ return std::move(mp_root);
+ }
+};
+
+struct sort_by_appearance
+{
+ bool operator() (const element_ref& left, const element_ref& right) const
+ {
+ return left.prop->appearance_order < right.prop->appearance_order;
+ }
+};
+
+struct scope
+{
+ xml_structure_tree::entity_name name;
+ elements_type elements;
+ elements_type::const_iterator current_pos;
+ bool repeat:1;
+
+ scope(const scope&) = delete;
+ scope& operator=(const scope&) = delete;
+
+ scope(const xml_structure_tree::entity_name& _name, bool _repeat, const element_ref& _elem) :
+ name(_name), repeat(_repeat)
+ {
+ elements.push_back(_elem);
+ current_pos = elements.begin();
+ }
+
+ scope(const xml_structure_tree::entity_name& _name, bool _repeat) :
+ name(_name), repeat(_repeat) {}
+};
+
+typedef std::vector<std::unique_ptr<scope>> scopes_type;
+
+void print_scope(std::ostream& os, const scopes_type& scopes, const xmlns_context& cxt)
+{
+ if (scopes.empty())
+ throw general_error("scope stack shouldn't be empty while dumping tree.");
+
+ // Skip the first scope which is root.
+ scopes_type::const_iterator it = scopes.begin(), it_end = scopes.end();
+ for (++it; it != it_end; ++it)
+ {
+ os << "/";
+ size_t num_id = cxt.get_index((*it)->name.ns);
+ if (num_id != INDEX_NOT_FOUND)
+ os << "ns" << num_id << ":";
+ os << (*it)->name.name;
+ if ((*it)->repeat)
+ os << "[*]";
+ }
+}
+
+}
+
+xml_table_range_t::xml_table_range_t() {}
+
+xml_table_range_t::~xml_table_range_t() {}
+
+struct xml_structure_tree::impl
+{
+ string_pool m_pool;
+ xmlns_context& m_xmlns_cxt;
+ std::unique_ptr<root> mp_root;
+
+ impl(const impl&) = delete;
+ impl& operator=(const impl&) = delete;
+
+ impl(xmlns_context& xmlns_cxt) : m_xmlns_cxt(xmlns_cxt) {}
+ ~impl() {}
+
+ std::string to_string(const xml_structure_tree::entity_name& name) const
+ {
+ std::ostringstream ss;
+ if (m_xmlns_cxt.get_index(name.ns) != INDEX_NOT_FOUND)
+ ss << m_xmlns_cxt.get_short_name(name.ns) << ":";
+ ss << name.name;
+ return ss.str();
+ }
+};
+
+struct xml_structure_tree::walker_impl
+{
+ const xml_structure_tree::impl& m_parent_impl;
+ root* mp_root; /// Root element of the authoritative tree.
+ element_ref m_cur_elem;
+ std::vector<element_ref> m_scopes;
+
+ walker_impl& operator=(const walker_impl&) = delete;
+
+ walker_impl(const xml_structure_tree::impl& parent_impl) :
+ m_parent_impl(parent_impl), mp_root(parent_impl.mp_root.get()) {}
+
+ walker_impl(const walker_impl& r) :
+ m_parent_impl(r.m_parent_impl), mp_root(r.mp_root), m_cur_elem(r.m_cur_elem), m_scopes(r.m_scopes) {}
+};
+
+xml_structure_tree::entity_name::entity_name() :
+ ns(XMLNS_UNKNOWN_ID) {}
+
+xml_structure_tree::entity_name::entity_name(xmlns_id_t _ns, std::string_view _name) :
+ ns(_ns), name(_name) {}
+
+bool xml_structure_tree::entity_name::operator< (const entity_name& r) const
+{
+ if (ns != r.ns)
+ return ns < r.ns;
+
+ return name < r.name;
+}
+
+bool xml_structure_tree::entity_name::operator== (const entity_name& r) const
+{
+ return ns == r.ns && name == r.name;
+}
+
+size_t xml_structure_tree::entity_name::hash::operator() (const entity_name& val) const
+{
+ size_t n = reinterpret_cast<size_t>(val.ns);
+ n += std::hash<std::string_view>{}(val.name);
+ return n;
+}
+
+xml_structure_tree::element::element() :
+ repeat(false), has_content(false) {}
+
+xml_structure_tree::element::element(const entity_name& _name, bool _repeat, bool _has_content) :
+ name(_name), repeat(_repeat), has_content(_has_content) {}
+
+xml_structure_tree::walker::walker(const xml_structure_tree::impl& parent_impl) :
+ mp_impl(std::make_unique<walker_impl>(parent_impl))
+{
+}
+
+xml_structure_tree::walker::walker(const walker& r) :
+ mp_impl(std::make_unique<walker_impl>(*r.mp_impl))
+{
+}
+
+xml_structure_tree::walker::~walker() {}
+
+xml_structure_tree::walker& xml_structure_tree::walker::operator= (const walker& r)
+{
+ mp_impl->mp_root = r.mp_impl->mp_root;
+ return *this;
+}
+
+xml_structure_tree::element xml_structure_tree::walker::root()
+{
+ if (!mp_impl->mp_root)
+ throw general_error("Tree is empty.");
+
+ mp_impl->m_scopes.clear();
+
+ // Set the current element to root.
+ element_ref ref(mp_impl->mp_root->name, &mp_impl->mp_root->prop);
+ mp_impl->m_cur_elem = ref;
+ mp_impl->m_scopes.push_back(ref);
+ return xml_structure_tree::element(ref.name, false, ref.prop->has_content);
+}
+
+xml_structure_tree::element xml_structure_tree::walker::descend(const entity_name& name)
+{
+ if (mp_impl->m_scopes.empty())
+ throw general_error("Scope is empty.");
+
+ assert(mp_impl->m_scopes.back().prop);
+ const auto& child_elems = mp_impl->m_scopes.back().prop->child_elements;
+ auto it = child_elems.find(name);
+
+ if (it == child_elems.end())
+ throw general_error("Specified child element does not exist.");
+
+ // Push this new child element onto the stack.
+ element_ref ref(name, it->second.get());
+ mp_impl->m_scopes.push_back(ref);
+
+ return element(name, it->second->repeat, it->second->has_content);
+}
+
+xml_structure_tree::element xml_structure_tree::walker::ascend()
+{
+ if (mp_impl->m_scopes.empty())
+ throw general_error("Scope is empty.");
+
+ if (mp_impl->m_scopes.size() == 1)
+ throw general_error("You can't ascend from the root element.");
+
+ mp_impl->m_scopes.pop_back();
+ const element_ref& ref = mp_impl->m_scopes.back();
+ return element(ref.name, ref.prop->repeat, ref.prop->has_content);
+}
+
+xml_structure_tree::entity_names_type xml_structure_tree::walker::get_children()
+{
+ if (mp_impl->m_scopes.empty())
+ throw general_error("Scope is empty.");
+
+ entity_names_type names;
+ assert(mp_impl->m_scopes.back().prop);
+ const elem_prop& prop = *mp_impl->m_scopes.back().prop;
+ names.assign(prop.child_element_names.begin(), prop.child_element_names.end());
+ return names;
+}
+
+xml_structure_tree::entity_names_type xml_structure_tree::walker::get_attributes()
+{
+ if (mp_impl->m_scopes.empty())
+ throw general_error("Scope is empty.");
+
+ entity_names_type names;
+ assert(mp_impl->m_scopes.back().prop);
+ const elem_prop& prop = *mp_impl->m_scopes.back().prop;
+ names.assign(prop.attribute_names.begin(), prop.attribute_names.end());
+ return names;
+}
+
+size_t xml_structure_tree::walker::get_xmlns_index(xmlns_id_t ns) const
+{
+ return mp_impl->m_parent_impl.m_xmlns_cxt.get_index(ns);
+}
+
+std::string xml_structure_tree::walker::get_xmlns_short_name(xmlns_id_t ns) const
+{
+ return mp_impl->m_parent_impl.m_xmlns_cxt.get_short_name(ns);
+}
+
+std::string xml_structure_tree::walker::to_string(const entity_name& name) const
+{
+ return mp_impl->m_parent_impl.to_string(name);
+}
+
+std::string xml_structure_tree::walker::get_path() const
+{
+ std::ostringstream ss;
+ for (auto& element : mp_impl->m_scopes)
+ {
+ ss << "/" << mp_impl->m_parent_impl.to_string(element.name);
+ }
+
+ return ss.str();
+}
+
+xml_structure_tree::element xml_structure_tree::walker::move_to(const std::string& path)
+{
+ auto parts = string_helper::split_string(path, '/');
+ if (parts.empty())
+ throw general_error("invalid format for path");
+
+ // string_helper::split_string will create an empty first element due to leading '/'
+ if (parts[0] != "")
+ {
+ throw general_error("invalid format for path");
+ }
+ else
+ {
+ parts.erase(parts.begin());
+ }
+
+ if (parts.empty())
+ throw general_error("invalid format for path");
+
+ element_ref root_ref(mp_impl->mp_root->name, &mp_impl->mp_root->prop);
+ if (mp_impl->m_parent_impl.to_string(root_ref.name) != parts[0])
+ throw general_error("path does not match any element");
+
+ std::vector<element_ref> scopes;
+ scopes.push_back(root_ref);
+
+ for (size_t i = 1; i < parts.size(); ++i)
+ {
+ const elem_prop& prop = *scopes.back().prop;
+ bool found = false;
+ for (auto& child : prop.child_elements)
+ {
+ if (mp_impl->m_parent_impl.to_string(child.first) == parts[i])
+ {
+ scopes.emplace_back(child.first, child.second.get());
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ throw general_error("path does not match any element");
+ }
+
+ std::swap(mp_impl->m_scopes, scopes);
+ const element_ref& ref = mp_impl->m_scopes.back();
+ return element(ref.name, ref.prop->repeat, ref.prop->has_content);
+}
+
+xml_structure_tree::xml_structure_tree(xmlns_context& xmlns_cxt) :
+ mp_impl(std::make_unique<impl>(xmlns_cxt)) {}
+
+xml_structure_tree::xml_structure_tree(xml_structure_tree&& other) :
+ mp_impl(std::move(other.mp_impl))
+{
+ other.mp_impl = std::make_unique<impl>(mp_impl->m_xmlns_cxt);
+}
+
+xml_structure_tree::~xml_structure_tree() {}
+
+void xml_structure_tree::parse(std::string_view s)
+{
+ xml_sax_handler hdl(mp_impl->m_pool);
+ sax_ns_parser<xml_sax_handler> parser(s, mp_impl->m_xmlns_cxt, hdl);
+ parser.parse();
+ mp_impl->mp_root = hdl.release_root_element();
+}
+
+void xml_structure_tree::dump_compact(std::ostream& os) const
+{
+ if (!mp_impl->mp_root)
+ return;
+
+ scopes_type scopes;
+ const xmlns_context& cxt = mp_impl->m_xmlns_cxt;
+
+ // Dump all namespaces first.
+ cxt.dump(os);
+
+ element_ref ref(mp_impl->mp_root->name, &mp_impl->mp_root->prop);
+ scopes.push_back(std::make_unique<scope>(entity_name(), false, ref));
+ while (!scopes.empty())
+ {
+ bool new_scope = false;
+
+ // Iterate through all elements in the current scope.
+ scope& cur_scope = *scopes.back();
+ for (; cur_scope.current_pos != cur_scope.elements.end(); ++cur_scope.current_pos)
+ {
+ const element_ref& this_elem = *cur_scope.current_pos;
+ std::ostringstream ss;
+ print_scope(ss, scopes, cxt);
+
+ ss << "/";
+ size_t num_id = cxt.get_index(this_elem.name.ns);
+ if (num_id != INDEX_NOT_FOUND)
+ ss << "ns" << num_id << ":";
+ ss << this_elem.name.name;
+ if (this_elem.prop->repeat)
+ ss << "[*]";
+
+ std::string elem_name = ss.str();
+ os << elem_name << std::endl;
+
+ // Print all attributes that belong to this element.
+ for (const entity_name& attr : this_elem.prop->attribute_names)
+ os << elem_name << "/@" << mp_impl->to_string(attr) << std::endl;
+
+ if (this_elem.prop->child_elements.empty())
+ continue;
+
+ // This element has child elements. Push a new scope and populate
+ // it with all child elements.
+ elements_type elems;
+ for (const auto& entry : this_elem.prop->child_elements)
+ {
+ ref.name = entry.first;
+ ref.prop = entry.second.get();
+ elems.push_back(ref);
+ }
+
+ // Sort the elements by order of appearance.
+ std::sort(elems.begin(), elems.end(), sort_by_appearance());
+
+ assert(!elems.empty());
+
+ // Push a new scope, and restart the loop with the new scope.
+ ++cur_scope.current_pos;
+ scopes.push_back(std::make_unique<scope>(this_elem.name, this_elem.prop->repeat));
+ scope& child_scope = *scopes.back();
+ child_scope.elements.swap(elems);
+ child_scope.current_pos = child_scope.elements.begin();
+
+ new_scope = true;
+ break;
+ }
+
+ if (new_scope)
+ continue;
+
+ scopes.pop_back();
+ }
+}
+
+xml_structure_tree::walker xml_structure_tree::get_walker() const
+{
+ return walker(*mp_impl);
+}
+
+void xml_structure_tree::process_ranges(range_handler_type rh) const
+{
+ detail::xml_structure_mapper mapper(rh, get_walker());
+ mapper.run();
+}
+
+void xml_structure_tree::swap(xml_structure_tree& other)
+{
+ mp_impl.swap(other.mp_impl);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_structure_tree_test.cpp b/src/liborcus/xml_structure_tree_test.cpp
new file mode 100644
index 0000000..ba8b550
--- /dev/null
+++ b/src/liborcus/xml_structure_tree_test.cpp
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <orcus/xml_structure_tree.hpp>
+#include <orcus/xml_namespace.hpp>
+#include <orcus/stream.hpp>
+#include <orcus/parser_global.hpp>
+
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include "filesystem_env.hpp"
+
+using namespace std;
+using namespace orcus;
+
+const fs::path test_base_dir(SRCDIR"/test/xml-structure");
+
+std::vector<fs::path> base_dirs = {
+ test_base_dir / "basic-1/",
+ test_base_dir / "basic-2/",
+ test_base_dir / "basic-3/",
+ test_base_dir / "attribute-1/",
+ test_base_dir / "nested-repeat-1/",
+ test_base_dir / "namespace-default/"
+};
+
+struct loaded_tree
+{
+ xmlns_context cxt;
+ file_content strm;
+ xml_structure_tree tree;
+
+ loaded_tree(xmlns_repository& repo) :
+ cxt(repo.create_context()),
+ tree(cxt) {}
+
+ loaded_tree(const loaded_tree&) = delete;
+};
+
+std::unique_ptr<loaded_tree> load_tree(xmlns_repository& repo, fs::path& filepath)
+{
+ auto ret = std::make_unique<loaded_tree>(repo);
+ ret->strm.load(filepath.string().data());
+ assert(!ret->strm.empty());
+ xml_structure_tree tree(ret->cxt);
+ tree.parse(ret->strm.str());
+ ret->tree.swap(tree);
+
+ return ret;
+}
+
+void test_basic()
+{
+ xmlns_repository xmlns_repo;
+
+ for (const fs::path& base_dir : base_dirs)
+ {
+ fs::path filepath = base_dir / "input.xml";
+ cout << filepath << endl;
+ auto lt = load_tree(xmlns_repo, filepath);
+
+ std::ostringstream os;
+ lt->tree.dump_compact(os);
+ string data_content = os.str();
+ cout << "--" << endl;
+ cout << data_content;
+
+ // Check the dump content against known datum.
+ filepath = base_dir / "check.txt";
+ file_content strm_check(filepath.string().data());
+ assert(!strm_check.empty());
+
+ // They should be identical, plus or minus leading/trailing whitespaces.
+ std::string_view s1(data_content.data(), data_content.size());
+ std::string_view s2 = strm_check.str();
+ assert(trim(s1) == trim(s2));
+ }
+}
+
+void test_walker()
+{
+ xmlns_repository xmlns_repo;
+
+ {
+ fs::path filepath = base_dirs[0] / "input.xml";
+ auto lt = load_tree(xmlns_repo, filepath);
+
+ // Get walker from the tree.
+ xml_structure_tree::entity_names_type elem_names;
+ xml_structure_tree::walker wkr = lt->tree.get_walker();
+
+ // Root element.
+ xml_structure_tree::element elem = wkr.root();
+ assert(elem.name.name == "root");
+ assert(!elem.repeat);
+
+ // Get names of child elements. There should only one one and it should be 'entry'.
+ elem_names = wkr.get_children();
+ assert(elem_names.size() == 1);
+ xml_structure_tree::entity_name elem_name = elem_names.front();
+ assert(elem_name.name == "entry");
+
+ // Descend into 'entry'.
+ elem = wkr.descend(elem_name);
+ assert(elem.name.name == "entry");
+ assert(elem.repeat);
+
+ // Element 'entry' should have 2 child elements 'name' and 'id' in this order.
+ elem_names = wkr.get_children();
+ assert(elem_names.size() == 2);
+ assert(elem_names[0].name == "name");
+ assert(elem_names[1].name == "id");
+
+ // Descend into 'name'.
+ elem_name = elem_names[0];
+ elem = wkr.descend(elem_name);
+ assert(elem.name.name == "name");
+ assert(!elem.repeat);
+
+ // This is a leaf element. It should have no child elements.
+ xml_structure_tree::entity_names_type test_names = wkr.get_children();
+ assert(test_names.empty());
+
+ // Move up to 'entry'.
+ elem = wkr.ascend();
+ assert(elem.name.name == "entry");
+ assert(elem.repeat);
+
+ // Move down to 'id'.
+ elem = wkr.descend(elem_names[1]);
+ assert(elem.name.name == "id");
+ assert(!elem.repeat);
+
+ // Move up to 'entry' again.
+ elem = wkr.ascend();
+ assert(elem.name.name == "entry");
+ assert(elem.repeat);
+
+ // Move up to 'root'.
+ elem = wkr.ascend();
+ assert(elem.name.name == "root");
+ assert(!elem.repeat);
+ }
+
+ {
+ fs::path filepath = base_dirs[3] / "input.xml"; // attribute-1
+ auto lt = load_tree(xmlns_repo, filepath);
+
+ // Get walker from the tree.
+ xml_structure_tree::entity_names_type elem_names;
+ xml_structure_tree::walker wkr = lt->tree.get_walker();
+
+ // Root element.
+ xml_structure_tree::element elem = wkr.root();
+ assert(elem.name.name == "root");
+ assert(!elem.repeat);
+
+ // Check attributes of root, which should have 'version' and 'type' in this order.
+ xml_structure_tree::entity_names_type names = wkr.get_attributes();
+ assert(names.size() == 2);
+ assert(names[0].name == "version");
+ assert(names[1].name == "type");
+
+ // Root element should have only one child element 'entry'.
+ names = wkr.get_children();
+ assert(names.size() == 1);
+ assert(names[0].name == "entry");
+ elem = wkr.descend(names[0]);
+ assert(elem.name.name == "entry");
+ assert(elem.repeat);
+
+ // The 'entry' element should have 3 attributes 'attr1', 'attr2', and 'attr3'.
+ names = wkr.get_attributes();
+ assert(names.size() == 3);
+ assert(names[0].name == "attr1");
+ assert(names[1].name == "attr2");
+ assert(names[2].name == "attr3");
+ }
+}
+
+void test_walker_path()
+{
+ fs::path filepath = base_dirs[0] / "input.xml";
+ xmlns_repository xmlns_repo;
+ auto lt = load_tree(xmlns_repo, filepath);
+
+ // Get walker from the tree.
+ xml_structure_tree::entity_names_type elem_names;
+ xml_structure_tree::walker wkr = lt->tree.get_walker();
+ wkr.root();
+ assert("/root" == wkr.get_path());
+
+ elem_names = wkr.get_children();
+ xml_structure_tree::entity_name elem_name = elem_names.front();
+ wkr.descend(elem_name);
+ assert("/root/entry" == wkr.get_path());
+
+ xml_structure_tree::element element = wkr.move_to("/root/entry");
+ assert(element.name.name == "entry");
+
+ try
+ {
+ wkr.move_to("/root/not-there");
+ assert(false);
+ }
+ catch (...)
+ {
+ }
+
+ try
+ {
+ wkr.move_to("something_different");
+ assert(false);
+ }
+ catch (...)
+ {
+ }
+
+ try
+ {
+ wkr.move_to("/non-exist");
+ assert(false);
+ }
+ catch (...)
+ {
+ }
+}
+
+void test_element_contents()
+{
+ xmlns_repository xmlns_repo;
+
+ {
+ fs::path filepath = test_base_dir / "attribute-1" / "input.xml";
+ auto lt = load_tree(xmlns_repo, filepath);
+ auto wkr = lt->tree.get_walker();
+ auto elem = wkr.move_to("/root/entry");
+ assert(wkr.to_string(elem.name) == "entry");
+ assert(elem.repeat);
+ assert(!elem.has_content);
+ }
+
+ {
+ fs::path filepath = test_base_dir / "basic-1" / "input.xml";
+ auto lt = load_tree(xmlns_repo, filepath);
+ auto wkr = lt->tree.get_walker();
+ auto elem = wkr.move_to("/root/entry/name");
+ assert(wkr.to_string(elem.name) == "name");
+ assert(!elem.repeat);
+ assert(elem.has_content);
+
+ elem = wkr.move_to("/root/entry/id");
+ assert(wkr.to_string(elem.name) == "id");
+ assert(!elem.repeat);
+ assert(elem.has_content);
+ }
+
+ {
+ fs::path filepath = test_base_dir / "nested-repeat-1" / "input.xml";
+ auto lt = load_tree(xmlns_repo, filepath);
+ auto wkr = lt->tree.get_walker();
+ auto elem = wkr.move_to("/root/mode/insert/command");
+ assert(wkr.to_string(elem.name) == "command");
+ assert(!elem.repeat);
+ assert(!elem.has_content);
+ }
+}
+
+int main()
+{
+ test_basic();
+ test_walker();
+ test_walker_path();
+ test_element_contents();
+
+ return EXIT_SUCCESS;
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_util.cpp b/src/liborcus/xml_util.cpp
new file mode 100644
index 0000000..7c15adf
--- /dev/null
+++ b/src/liborcus/xml_util.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xml_util.hpp"
+
+#include <orcus/xml_namespace.hpp>
+#include <orcus/tokens.hpp>
+
+#include <sstream>
+#include <iostream>
+
+namespace orcus {
+
+xml_element_printer::xml_element_printer(const tokens& t) :
+ m_tokens(t)
+{
+}
+
+void xml_element_printer::set_ns_context(const xmlns_context* ns_cxt)
+{
+ mp_ns_cxt = ns_cxt;
+}
+
+void xml_element_printer::print_namespace(std::ostream& os, xmlns_id_t ns) const
+{
+ if (mp_ns_cxt)
+ {
+ std::string_view alias = mp_ns_cxt->get_alias(ns);
+ if (!alias.empty())
+ os << alias;
+ else
+ os << mp_ns_cxt->get_short_name(ns);
+ }
+ else
+ os << ns;
+}
+
+void xml_element_printer::print_element(std::ostream& os, xmlns_id_t ns, xml_token_t name) const
+{
+ os << '<';
+
+ std::ostringstream os_ns;
+ print_namespace(os_ns, ns);
+ std::string ns_str = os_ns.str();
+
+ if (!ns_str.empty())
+ os << ns_str << ':';
+
+ os << m_tokens.get_token_name(name) << '>';
+}
+
+void print_attrs(const tokens& tokens, const xml_token_attrs_t& attrs)
+{
+ for (const auto& attr : attrs)
+ {
+ std::cout << " ";
+ if (attr.ns != XMLNS_UNKNOWN_ID)
+ std::cout << attr.ns << ":";
+
+ std::cout << tokens.get_token_name(attr.name) << " = \"" << attr.value << "\"" << std::endl;
+ }
+}
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xml_util.hpp b/src/liborcus/xml_util.hpp
new file mode 100644
index 0000000..1021ccf
--- /dev/null
+++ b/src/liborcus/xml_util.hpp
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <orcus/types.hpp>
+
+#include <ostream>
+
+namespace orcus {
+
+class tokens;
+class xmlns_context;
+
+class xml_element_printer
+{
+ const tokens& m_tokens;
+ const xmlns_context* mp_ns_cxt = nullptr;
+
+public:
+ xml_element_printer(const tokens& t);
+
+ void set_ns_context(const xmlns_context* ns_cxt);
+
+ void print_namespace(std::ostream& os, xmlns_id_t ns) const;
+
+ void print_element(std::ostream& os, xmlns_id_t ns, xml_token_t name) const;
+};
+
+void print_element(std::ostream& os, const tokens& t, xmlns_id_t ns, xml_token_t name);
+
+/**
+ * Print attributes to stdout for debugging purposes.
+ */
+void print_attrs(const tokens& tokens, const xml_token_attrs_t& attrs);
+
+} // namespace orcus
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xpath_parser.cpp b/src/liborcus/xpath_parser.cpp
new file mode 100644
index 0000000..306b367
--- /dev/null
+++ b/src/liborcus/xpath_parser.cpp
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xpath_parser.hpp"
+#include "orcus/exception.hpp"
+#include "orcus/xml_namespace.hpp"
+
+#define ORCUS_DEBUG_XPATH_PARSER 0
+
+namespace orcus {
+
+xpath_parser::token::token(xmlns_id_t _ns, std::string_view _name, bool _attribute) :
+ ns(_ns), name(_name), attribute(_attribute)
+{
+#if ORCUS_DEBUG_XPATH_PARSER
+ cout << "xpath_parser::token: (ns='" << (ns ? ns : "none") << "', name='" << name << "', attribute=" << attribute << ")" << endl;
+#endif
+}
+
+xpath_parser::token::token() : ns(XMLNS_UNKNOWN_ID), attribute(false) {}
+xpath_parser::token::token(const token& r) : ns(r.ns), name(r.name), attribute(r.attribute) {}
+
+xpath_parser::xpath_parser(const xmlns_context& cxt, const char* p, size_t n, xmlns_id_t default_ns) :
+ m_cxt(cxt),
+ mp_char(p),
+ mp_end(p+n),
+ m_default_ns(default_ns)
+{
+ if (!n)
+ throw xpath_error("empty path");
+
+ if (*p != '/')
+ throw xpath_error("first character must be '/'.");
+
+ ++mp_char;
+}
+
+xpath_parser::token xpath_parser::next()
+{
+ if (mp_char == mp_end)
+ return token();
+
+ const char* p0 = nullptr;
+ size_t len = 0;
+ xmlns_id_t ns = m_default_ns;
+
+ bool attribute = *mp_char == '@';
+ if (attribute)
+ ++mp_char;
+
+ for (; mp_char != mp_end; ++mp_char, ++len)
+ {
+ if (!p0)
+ {
+ p0 = mp_char;
+ len = 0;
+ }
+
+ switch (*mp_char)
+ {
+ case '/':
+ {
+ ++mp_char; // skip the '/'.
+ return token(ns, std::string_view(p0, len), attribute);
+ }
+ case ':':
+ {
+ // What comes before ':' is a namespace. Reset the name and
+ // convert the namespace to a proper ID.
+ std::string_view ns_name(p0, len);
+ ns = m_cxt.get(ns_name);
+ p0 = nullptr; // reset the name.
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ // '/' has never been encountered. It must be the last name in the path.
+ return token(ns, std::string_view(p0, len), attribute);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xpath_parser.hpp b/src/liborcus/xpath_parser.hpp
new file mode 100644
index 0000000..211d749
--- /dev/null
+++ b/src/liborcus/xpath_parser.hpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_ORCUS_XPATH_PARSER_HPP
+#define INCLUDED_ORCUS_XPATH_PARSER_HPP
+
+#include <orcus/types.hpp>
+
+namespace orcus {
+
+class xmlns_context;
+
+class xpath_parser
+{
+ const xmlns_context& m_cxt;
+ const char* mp_char;
+ const char* mp_end;
+
+ xmlns_id_t m_default_ns;
+
+ enum class token_type { element, attribute };
+
+public:
+
+ struct token
+ {
+ xmlns_id_t ns;
+ std::string_view name;
+ bool attribute;
+
+ token(xmlns_id_t _ns, std::string_view _name, bool _attribute);
+ token();
+ token(const token& r);
+ };
+
+ xpath_parser(const xmlns_context& cxt, const char* p, size_t n, xmlns_id_t default_ns);
+
+ token next();
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/xpath_parser_test.cpp b/src/liborcus/xpath_parser_test.cpp
new file mode 100644
index 0000000..26e7d6b
--- /dev/null
+++ b/src/liborcus/xpath_parser_test.cpp
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "xpath_parser.hpp"
+#include "orcus/xml_namespace.hpp"
+
+#include <iostream>
+#include <cassert>
+
+using namespace orcus;
+
+void test_elements()
+{
+ xmlns_repository repo;
+ xmlns_context cxt = repo.create_context();
+
+ std::string_view path("/A/B/C");
+
+ xpath_parser parser(cxt, path.data(), path.size(), XMLNS_UNKNOWN_ID);
+ auto token = parser.next();
+ assert(token.name == "A");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name == "B");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name == "C");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name.empty());
+}
+
+void test_attributes()
+{
+ xmlns_repository repo;
+ xmlns_context cxt = repo.create_context();
+
+ std::string_view path("/A/B/C/@foo");
+
+ xpath_parser parser(cxt, path.data(), path.size(), XMLNS_UNKNOWN_ID);
+ auto token = parser.next();
+ assert(token.name == "A");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name == "B");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name == "C");
+ assert(!token.attribute);
+
+ token = parser.next();
+ assert(token.name == "foo");
+ assert(token.attribute);
+}
+
+int main()
+{
+ test_elements();
+ test_attributes();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/src/liborcus/yaml_document_tree.cpp b/src/liborcus/yaml_document_tree.cpp
new file mode 100644
index 0000000..1bd37a8
--- /dev/null
+++ b/src/liborcus/yaml_document_tree.cpp
@@ -0,0 +1,856 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/yaml_document_tree.hpp"
+#include "orcus/yaml_parser.hpp"
+
+#include "json_util.hpp"
+
+#include <vector>
+#include <memory>
+#include <unordered_map>
+#include <algorithm>
+#include <iostream>
+
+#include <boost/current_function.hpp>
+
+#define ORCUS_DEBUG_YAML_TREE 0
+
+#if ORCUS_DEBUG_YAML_TREE
+#include <iostream>
+#endif
+
+namespace orcus { namespace yaml {
+
+document_error::document_error(const std::string& msg) :
+ general_error("yaml_document_error", msg) {}
+
+document_error::~document_error() = default;
+
+struct yaml_value
+{
+ node_t type;
+ yaml_value* parent;
+
+ yaml_value() : type(node_t::unset), parent(nullptr) {}
+ yaml_value(node_t _type) : type(_type), parent(nullptr) {}
+ virtual ~yaml_value() {}
+
+ virtual size_t get_hash() const
+ {
+ return reinterpret_cast<size_t>(this);
+ }
+
+ virtual std::string print() const
+ {
+ std::ostringstream os;
+ os << "type: ";
+ switch (type)
+ {
+ case node_t::unset:
+ os << "unset";
+ break;
+ case node_t::string:
+ os << "string";
+ break;
+ case node_t::number:
+ os << "number";
+ break;
+ case node_t::map:
+ os << "map";
+ break;
+ case node_t::sequence:
+ os << "sequence";
+ break;
+ case node_t::boolean_true:
+ os << "true";
+ break;
+ case node_t::boolean_false:
+ os << "false";
+ break;
+ case node_t::null:
+ os << "null";
+ break;
+ }
+ return os.str();
+ }
+
+ struct hash
+ {
+ size_t operator() (const yaml_value& v) const
+ {
+ return v.get_hash();
+ }
+ };
+};
+
+namespace {
+
+struct yaml_value_string : public yaml_value
+{
+ std::string value_string;
+
+ yaml_value_string() : yaml_value(node_t::string) {}
+ yaml_value_string(std::string_view s) : yaml_value(node_t::string), value_string(s) {}
+ virtual ~yaml_value_string() {}
+
+ virtual std::string print() const
+ {
+ std::ostringstream os;
+ os << "type: string, value: " << value_string;
+ return os.str();
+ }
+};
+
+struct yaml_value_number : public yaml_value
+{
+ double value_number;
+
+ yaml_value_number(double num) : yaml_value(node_t::number), value_number(num) {}
+ virtual ~yaml_value_number() {}
+
+ virtual std::string print() const
+ {
+ std::ostringstream os;
+ os << "type: number, value: " << value_number;
+ return os.str();
+ }
+};
+
+struct yaml_value_sequence : public yaml_value
+{
+ std::vector<std::unique_ptr<yaml_value>> value_sequence;
+
+ yaml_value_sequence() : yaml_value(node_t::sequence) {}
+ virtual ~yaml_value_sequence() {}
+};
+
+struct yaml_value_map : public yaml_value
+{
+ std::vector<std::unique_ptr<yaml_value>> key_order; // owns the key instances.
+ std::unordered_map<const yaml_value*, std::unique_ptr<yaml_value>> value_map;
+
+ yaml_value_map() : yaml_value(node_t::map) {}
+ virtual ~yaml_value_map() {}
+};
+
+struct parser_stack
+{
+ std::unique_ptr<yaml_value> key;
+ yaml_value* node;
+
+ parser_stack(yaml_value* _node) : node(_node) {}
+ parser_stack(const parser_stack&) = delete;
+ parser_stack(parser_stack&& r) : key(std::move(r.key)), node(r.node) {}
+};
+
+typedef std::unique_ptr<yaml_value> document_root_type;
+
+class handler
+{
+ std::vector<document_root_type> m_docs;
+
+ std::vector<parser_stack> m_stack;
+ std::vector<parser_stack> m_key_stack;
+
+ document_root_type m_root;
+ document_root_type m_key_root;
+
+ bool m_in_document;
+
+#if ORCUS_DEBUG_YAML_TREE
+ void print_stack()
+ {
+ std::ostringstream os;
+ os << '(';
+ for (auto i = m_stack.begin(), ie = m_stack.end(); i != ie; ++i)
+ os << i->node->print() << ',';
+ os << ')';
+ std::cout << os.str() << std::endl;
+ }
+#endif
+
+ yaml_value* push_value(std::unique_ptr<yaml_value>&& value)
+ {
+ assert(!m_stack.empty());
+ parser_stack& cur = m_stack.back();
+
+ switch (cur.node->type)
+ {
+ case node_t::sequence:
+ {
+ yaml_value_sequence* yvs = static_cast<yaml_value_sequence*>(cur.node);
+ value->parent = yvs;
+ yvs->value_sequence.push_back(std::move(value));
+ return yvs->value_sequence.back().get();
+ }
+ case node_t::map:
+ {
+ yaml_value_map* yvm = static_cast<yaml_value_map*>(cur.node);
+ value->parent = yvm;
+
+ yvm->key_order.push_back(std::move(cur.key));
+
+ auto r = yvm->value_map.insert(
+ std::make_pair(
+ yvm->key_order.back().get(), std::move(value)));
+
+ return r.first->second.get();
+ }
+ default:
+ break;
+ }
+
+ std::ostringstream os;
+ os << BOOST_CURRENT_FUNCTION << ": unstackable YAML value type (" << cur.node->print() << ").";
+ throw document_error(os.str());
+ }
+
+public:
+ handler() : m_in_document(false) {}
+
+ void begin_parse()
+ {
+ }
+
+ void end_parse()
+ {
+ }
+
+ void begin_document()
+ {
+ assert(!m_in_document);
+ m_in_document = true;
+ m_root.reset();
+ }
+
+ void end_document()
+ {
+ assert(m_stack.empty());
+ m_in_document = false;
+ m_docs.push_back(std::move(m_root));
+ }
+
+ void begin_sequence()
+ {
+ assert(m_in_document);
+
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value_sequence>());
+ assert(yv && yv->type == node_t::sequence);
+ m_stack.push_back(parser_stack(yv));
+ }
+ else
+ {
+ m_root = std::make_unique<yaml_value_sequence>();
+ m_stack.push_back(parser_stack(m_root.get()));
+ }
+ }
+
+ void end_sequence()
+ {
+ assert(!m_stack.empty());
+ m_stack.pop_back();
+ }
+
+ void begin_map()
+ {
+ assert(m_in_document);
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value_map>());
+ assert(yv && yv->type == node_t::map);
+ m_stack.push_back(parser_stack(yv));
+ }
+ else
+ {
+ m_root = std::make_unique<yaml_value_map>();
+ m_stack.push_back(parser_stack(m_root.get()));
+ }
+ }
+
+ void begin_map_key()
+ {
+ assert(!m_key_root);
+ assert(m_key_stack.empty());
+ m_key_root.swap(m_root);
+ m_key_stack.swap(m_stack);
+ }
+
+ void end_map_key()
+ {
+ m_key_root.swap(m_root);
+ m_key_stack.swap(m_stack);
+
+ assert(!m_stack.empty());
+ parser_stack& cur = m_stack.back();
+ cur.key.swap(m_key_root);
+ m_key_stack.clear();
+ m_key_root.reset();
+ }
+
+ void end_map()
+ {
+ assert(!m_stack.empty());
+ m_stack.pop_back();
+ }
+
+ void string(std::string_view v)
+ {
+ assert(m_in_document);
+
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value_string>(v));
+ assert(yv && yv->type == node_t::string);
+ }
+ else
+ m_root = std::make_unique<yaml_value_string>(v);
+ }
+
+ void number(double val)
+ {
+ assert(m_in_document);
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value_number>(val));
+ assert(yv && yv->type == node_t::number);
+ }
+ else
+ m_root = std::make_unique<yaml_value_number>(val);
+ }
+
+ void boolean_true()
+ {
+ assert(m_in_document);
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value>(node_t::boolean_true));
+ assert(yv && yv->type == node_t::boolean_true);
+ }
+ else
+ m_root = std::make_unique<yaml_value>(node_t::boolean_true);
+ }
+
+ void boolean_false()
+ {
+ assert(m_in_document);
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value>(node_t::boolean_false));
+ assert(yv && yv->type == node_t::boolean_false);
+ }
+ else
+ m_root = std::make_unique<yaml_value>(node_t::boolean_false);
+ }
+
+ void null()
+ {
+ assert(m_in_document);
+ if (m_root)
+ {
+ yaml_value* yv = push_value(std::make_unique<yaml_value>(node_t::null));
+ assert(yv && yv->type == node_t::null);
+ }
+ else
+ m_root = std::make_unique<yaml_value>(node_t::null);
+ }
+
+ void swap(std::vector<document_root_type>& docs)
+ {
+ m_docs.swap(docs);
+ }
+};
+
+} // anonymous namespace
+
+struct document_tree::impl
+{
+ std::vector<document_root_type> m_docs;
+};
+
+struct const_node::impl
+{
+ const yaml_value* m_node;
+
+ impl(const yaml_value* yv) : m_node(yv) {}
+};
+
+const_node::const_node(const yaml_value* yv) : mp_impl(std::make_unique<impl>(yv)) {}
+const_node::const_node(const const_node& other) : mp_impl(std::make_unique<impl>(other.mp_impl->m_node)) {}
+const_node::const_node(const_node&& rhs) : mp_impl(std::move(rhs.mp_impl)) {}
+const_node::~const_node() {}
+
+const_node& const_node::operator=(const const_node& other)
+{
+ if (this == &other)
+ return *this;
+
+ const_node tmp(other);
+ mp_impl.swap(tmp.mp_impl);
+ return *this;
+}
+
+uintptr_t const_node::identity() const
+{
+ return reinterpret_cast<uintptr_t>(mp_impl->m_node);
+}
+
+node_t const_node::type() const
+{
+ return mp_impl->m_node->type;
+}
+
+size_t const_node::child_count() const
+{
+ switch (mp_impl->m_node->type)
+ {
+ case node_t::map:
+ return static_cast<const yaml_value_map*>(mp_impl->m_node)->value_map.size();
+ case node_t::sequence:
+ return static_cast<const yaml_value_sequence*>(mp_impl->m_node)->value_sequence.size();
+ case node_t::string:
+ case node_t::number:
+ case node_t::boolean_true:
+ case node_t::boolean_false:
+ case node_t::null:
+ case node_t::unset:
+ default:
+ ;
+ }
+ return 0;
+}
+
+std::vector<const_node> const_node::keys() const
+{
+ if (mp_impl->m_node->type != node_t::map)
+ throw document_error("node::keys: this node is not of map type.");
+
+ const yaml_value_map* yvm = static_cast<const yaml_value_map*>(mp_impl->m_node);
+ std::vector<const_node> keys;
+ std::for_each(yvm->key_order.begin(), yvm->key_order.end(),
+ [&](const std::unique_ptr<yaml_value>& key)
+ {
+ keys.push_back(const_node(key.get()));
+ }
+ );
+
+ return keys;
+}
+
+const_node const_node::key(size_t index) const
+{
+ if (mp_impl->m_node->type != node_t::map)
+ throw document_error("node::key: this node is not of map type.");
+
+ const yaml_value_map* yvm = static_cast<const yaml_value_map*>(mp_impl->m_node);
+ if (index >= yvm->key_order.size())
+ throw std::out_of_range("node::key: index is out-of-range.");
+
+ return const_node(yvm->key_order[index].get());
+}
+
+const_node const_node::child(size_t index) const
+{
+ switch (mp_impl->m_node->type)
+ {
+ case node_t::map:
+ {
+ const yaml_value_map* yvm = static_cast<const yaml_value_map*>(mp_impl->m_node);
+ if (index >= yvm->key_order.size())
+ throw std::out_of_range("node::child: index is out-of-range");
+
+ const yaml_value* key = yvm->key_order[index].get();
+ auto it = yvm->value_map.find(key);
+ assert(it != yvm->value_map.end());
+ return const_node(it->second.get());
+ }
+ break;
+ case node_t::sequence:
+ {
+ const yaml_value_sequence* yvs = static_cast<const yaml_value_sequence*>(mp_impl->m_node);
+ if (index >= yvs->value_sequence.size())
+ throw std::out_of_range("node::child: index is out-of-range");
+
+ return const_node(yvs->value_sequence[index].get());
+ }
+ break;
+ case node_t::string:
+ case node_t::number:
+ case node_t::boolean_true:
+ case node_t::boolean_false:
+ case node_t::null:
+ case node_t::unset:
+ default:
+ throw document_error("node::child: this node cannot have child nodes.");
+ }
+}
+
+const_node const_node::child(const const_node& key) const
+{
+ if (mp_impl->m_node->type != node_t::map)
+ throw document_error("node::child: this node is not of map type.");
+
+ const yaml_value_map* yvm = static_cast<const yaml_value_map*>(mp_impl->m_node);
+ auto it = yvm->value_map.find(key.mp_impl->m_node);
+ if (it == yvm->value_map.end())
+ throw document_error("node::child: this map does not have the specified key.");
+
+ return const_node(it->second.get());
+}
+
+const_node const_node::parent() const
+{
+ if (!mp_impl->m_node->parent)
+ throw document_error("node::parent: this node has no parent.");
+
+ return const_node(mp_impl->m_node->parent);
+}
+
+std::string_view const_node::string_value() const
+{
+ if (mp_impl->m_node->type != node_t::string)
+ throw document_error("node::key: current node is not of string type.");
+
+ const yaml_value_string* yvs = static_cast<const yaml_value_string*>(mp_impl->m_node);
+ return yvs->value_string;
+}
+
+double const_node::numeric_value() const
+{
+ if (mp_impl->m_node->type != node_t::number)
+ throw document_error("node::key: current node is not of numeric type.");
+
+ const yaml_value_number* yvn = static_cast<const yaml_value_number*>(mp_impl->m_node);
+ return yvn->value_number;
+}
+
+document_tree::document_tree() :
+ mp_impl(std::make_unique<impl>()) {}
+
+document_tree::document_tree(document_tree&& other) :
+ mp_impl(std::move(other.mp_impl)) {}
+
+document_tree::~document_tree() {}
+
+void document_tree::load(std::string_view s)
+{
+ handler hdl;
+ yaml_parser<handler> parser(s, hdl);
+ parser.parse();
+ hdl.swap(mp_impl->m_docs);
+}
+
+size_t document_tree::get_document_count() const
+{
+ return mp_impl->m_docs.size();
+}
+
+const_node document_tree::get_document_root(size_t index) const
+{
+ return const_node(mp_impl->m_docs[index].get());
+}
+
+namespace {
+
+const char* indent = " ";
+const char* kw_true = "true";
+const char* kw_false = "false";
+const char* kw_tilde = "~";
+const char* kw_null = "null";
+
+const char quote = '"';
+
+void dump_indent(std::ostringstream& os, size_t scope)
+{
+ for (size_t i = 0; i < scope; ++i)
+ os << indent;
+}
+
+bool needs_quoting(const std::string& s)
+{
+ // See if it contains certain characters...
+ for (auto it = s.begin(), ite = s.end(); it != ite; ++it)
+ if (is_in(*it, "#'"))
+ return true;
+
+ // See if the whole string is parsed as a number.
+ const char* p = s.data();
+ const char* p_end = p + s.size();
+ double v;
+ p = parse_numeric(p, p_end, v);
+ if (p == p_end)
+ return true;
+
+ return false;
+}
+
+void dump_yaml_string(std::ostringstream& os, const std::string& s)
+{
+ if (needs_quoting(s))
+ os << quote << s << quote;
+ else
+ os << s;
+}
+
+void dump_yaml_map(std::ostringstream& os, const yaml_value& node, size_t scope);
+void dump_yaml_sequence(std::ostringstream& os, const yaml_value& node, size_t scope);
+
+void dump_yaml_node(std::ostringstream& os, const yaml_value& node, size_t scope)
+{
+ switch (node.type)
+ {
+ case node_t::map:
+ dump_yaml_map(os, node, scope);
+ break;
+ case node_t::sequence:
+ dump_yaml_sequence(os, node, scope);
+ break;
+ case node_t::boolean_true:
+ dump_indent(os, scope);
+ os << kw_true << std::endl;
+ break;
+ case node_t::boolean_false:
+ dump_indent(os, scope);
+ os << kw_false << std::endl;
+ break;
+ case node_t::null:
+ dump_indent(os, scope);
+ os << kw_tilde << std::endl;
+ break;
+ case node_t::number:
+ dump_indent(os, scope);
+ os << static_cast<const yaml_value_number&>(node).value_number << std::endl;
+ break;
+ case node_t::string:
+ dump_indent(os, scope);
+ dump_yaml_string(os, static_cast<const yaml_value_string&>(node).value_string);
+ os << std::endl;
+ break;
+ case node_t::unset:
+ default:
+ ;
+ }
+}
+
+void dump_yaml_container_item(std::ostringstream& os, const yaml_value& node, size_t scope)
+{
+ switch (node.type)
+ {
+ case node_t::map:
+ case node_t::sequence:
+ // End the line and dump this child container in the next scope.
+ os << std::endl;
+ dump_yaml_node(os, node, scope+1);
+ break;
+ default:
+ // Dump inline.
+ os << " ";
+ dump_yaml_node(os, node, 0);
+ }
+}
+
+void dump_yaml_map(std::ostringstream& os, const yaml_value& node, size_t scope)
+{
+ const yaml_value_map& yvm = static_cast<const yaml_value_map&>(node);
+
+ std::for_each(yvm.key_order.begin(), yvm.key_order.end(),
+ [&](const std::unique_ptr<yaml_value>& pkey)
+ {
+ const yaml_value* key = pkey.get();
+
+ switch (key->type)
+ {
+ case node_t::map:
+ // TODO
+ break;
+ case node_t::sequence:
+ // TODO
+ break;
+ case node_t::boolean_true:
+ dump_indent(os, scope);
+ os << kw_true;
+ break;
+ case node_t::boolean_false:
+ dump_indent(os, scope);
+ os << kw_false;
+ break;
+ case node_t::null:
+ dump_indent(os, scope);
+ os << kw_tilde;
+ break;
+ case node_t::number:
+ dump_indent(os, scope);
+ os << static_cast<const yaml_value_number*>(key)->value_number;
+ break;
+ case node_t::string:
+ dump_indent(os, scope);
+ dump_yaml_string(os, static_cast<const yaml_value_string*>(key)->value_string);
+ break;
+ case node_t::unset:
+ default:
+ ;
+ }
+
+ os << ":";
+ auto it = yvm.value_map.find(key);
+ assert(it != yvm.value_map.end());
+ const yaml_value& value = *it->second;
+ dump_yaml_container_item(os, value, scope);
+ }
+ );
+}
+
+void dump_yaml_sequence(std::ostringstream& os, const yaml_value& node, size_t scope)
+{
+ const yaml_value_sequence& yvs = static_cast<const yaml_value_sequence&>(node);
+
+ std::for_each(yvs.value_sequence.begin(), yvs.value_sequence.end(),
+ [&](const std::unique_ptr<yaml_value>& p)
+ {
+ const yaml_value& child = *p;
+ dump_indent(os, scope);
+ os << "-";
+ dump_yaml_container_item(os, child, scope);
+ }
+ );
+}
+
+void dump_yaml_document(std::ostringstream& os, const yaml_value& root)
+{
+ os << "---" << std::endl;
+ dump_yaml_node(os, root, 0);
+}
+
+void dump_json_node(std::ostringstream& os, const yaml_value& node, size_t scope, const std::string* key);
+
+void dump_json_item(
+ std::ostringstream& os, const std::string* key, const yaml_value& val,
+ size_t scope, bool sep)
+{
+ dump_json_node(os, val, scope+1, key);
+ if (sep)
+ os << ",";
+ os << std::endl;
+}
+
+void dump_json_node(std::ostringstream& os, const yaml_value& node, size_t scope, const std::string* key = nullptr)
+{
+ dump_indent(os, scope);
+
+ if (key)
+ {
+ os << quote << *key << quote << ": ";
+ }
+
+ switch (node.type)
+ {
+ case node_t::map:
+ {
+ auto& key_order = static_cast<const yaml_value_map&>(node).key_order;
+ auto& vals = static_cast<const yaml_value_map&>(node).value_map;
+ os << "{" << std::endl;
+ size_t n = vals.size();
+
+ // Dump them based on key's original ordering.
+ size_t pos = 0;
+ for (auto it = key_order.begin(), ite = key_order.end(); it != ite; ++it, ++pos)
+ {
+ const yaml_value* this_key = it->get();
+ if (this_key->type != node_t::string)
+ throw document_error("JSON doesn't support non-string key.");
+
+ auto val_pos = vals.find(this_key);
+ assert(val_pos != vals.end());
+
+ dump_json_item(
+ os,
+ &static_cast<const yaml_value_string*>(this_key)->value_string,
+ *val_pos->second, scope, pos < (n-1));
+ }
+
+ dump_indent(os, scope);
+ os << "}";
+ }
+ break;
+ case node_t::sequence:
+ {
+ auto& vals = static_cast<const yaml_value_sequence&>(node).value_sequence;
+ os << "[" << std::endl;
+ size_t n = vals.size();
+ size_t pos = 0;
+ for (auto it = vals.begin(), ite = vals.end(); it != ite; ++it, ++pos)
+ dump_json_item(os, nullptr, **it, scope, pos < (n-1));
+
+ dump_indent(os, scope);
+ os << "]";
+ }
+ break;
+ case node_t::boolean_true:
+ os << kw_true;
+ break;
+ case node_t::boolean_false:
+ os << kw_false;
+ break;
+ case node_t::null:
+ os << kw_null;
+ break;
+ case node_t::number:
+ os << static_cast<const yaml_value_number&>(node).value_number;
+ break;
+ case node_t::string:
+ json::dump_string(os, static_cast<const yaml_value_string&>(node).value_string);
+ break;
+ case node_t::unset:
+ default:
+ ;
+ }
+}
+
+const char* warning_multiple_documents =
+"warning: this YAML file contains multiple documents. Only the first document\n"
+"will be written.";
+
+}
+
+std::string document_tree::dump_yaml() const
+{
+ std::ostringstream os;
+
+ std::for_each(
+ mp_impl->m_docs.begin(), mp_impl->m_docs.end(),
+ [&](const document_root_type& root)
+ {
+ dump_yaml_document(os, *root);
+ }
+ );
+
+ return os.str();
+}
+
+std::string document_tree::dump_json() const
+{
+ if (mp_impl->m_docs.empty())
+ return std::string();
+
+ if (mp_impl->m_docs.size() > 1)
+ std::cerr << warning_multiple_documents << std::endl;
+
+ const yaml_value& root = *mp_impl->m_docs.front();
+
+ std::ostringstream os;
+ dump_json_node(os, root, 0);
+
+ os << std::endl;
+
+ return os.str();
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/src/liborcus/yaml_document_tree_test.cpp b/src/liborcus/yaml_document_tree_test.cpp
new file mode 100644
index 0000000..cb674ea
--- /dev/null
+++ b/src/liborcus/yaml_document_tree_test.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/yaml_document_tree.hpp"
+#include "orcus/stream.hpp"
+#include "orcus/yaml_parser_base.hpp"
+
+#include <cassert>
+#include <iostream>
+#include <cmath>
+
+#include "filesystem_env.hpp"
+
+using namespace orcus;
+using namespace std;
+
+bool string_expected(const yaml::const_node& node, const char* expected)
+{
+ if (node.type() != yaml::node_t::string)
+ return false;
+
+ if (node.string_value() == expected)
+ return true;
+
+ cerr << "expected='" << expected << "', actual='" << node.string_value() << "'" << endl;
+ return false;
+}
+
+bool number_expected(
+ const yaml::const_node& node, double expected,
+ double decimal = 0.0, double exponent = 0.0)
+{
+ if (node.type() != yaml::node_t::number)
+ return false;
+
+ double actual = node.numeric_value();
+ if (!decimal || !exponent)
+ return actual == expected;
+
+ // Remove the exponent component.
+ actual /= std::pow(10.0, exponent);
+ expected /= std::pow(10.0, exponent);
+
+ // Only compare down to the specified decimal place.
+ actual *= std::pow(10.0, decimal);
+ expected *= std::pow(10.0, decimal);
+
+ actual = std::round(actual);
+ expected = std::round(expected);
+
+ return actual == expected;
+}
+
+yaml::document_tree load_doc(const char* filepath)
+{
+ cout << filepath << endl;
+ file_content strm(filepath);
+ cout << strm.str() << endl;
+ yaml::document_tree doc;
+ doc.load(strm.str());
+
+ return doc;
+}
+
+void test_yaml_invalids()
+{
+ // Get all yaml files in this directory.
+ fs::path dirpath(SRCDIR"/test/yaml/invalids/");
+ fs::directory_iterator it_end;
+
+ size_t file_count = 0;
+
+ for (fs::directory_iterator it(dirpath); it != it_end; ++it)
+ {
+ auto path = it->path();
+ if (!fs::is_regular_file(path))
+ continue;
+
+ if (path.extension().string() != ".yaml")
+ continue;
+
+ ++file_count;
+
+ file_content strm(path.string().data());
+ yaml::document_tree doc;
+
+ try
+ {
+ doc.load(strm.str());
+ assert(!"yaml::parse_error was not thrown, but expected to be.");
+ }
+ catch (const parse_error&)
+ {
+ // This is expected.
+ }
+ }
+
+ assert(file_count > 0);
+}
+
+void test_yaml_parse_basic1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/basic1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+
+ // Document root is a map node with 4 elements.
+ yaml::const_node root = doc.get_document_root(0);
+ uintptr_t root_id = root.identity();
+ assert(root.type() == yaml::node_t::map);
+ assert(root.child_count() == 4);
+
+ std::vector<yaml::const_node> keys = root.keys();
+ assert(keys.size() == 4);
+
+ yaml::const_node key = keys[0];
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "dict");
+
+ key = keys[1];
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "list");
+
+ key = keys[2];
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "number");
+
+ key = keys[3];
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "string");
+
+ // first child is a map.
+ yaml::const_node node = root.child(keys[0]);
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ key = node.key(0);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "a");
+
+ key = node.key(1);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "b");
+
+ key = node.key(2);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "c");
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1.0);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 2.0);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 2);
+ yaml::const_node child = node.child(0);
+ assert(child.type() == yaml::node_t::string);
+ assert(child.string_value() == "foo");
+ child = node.child(1);
+ assert(child.type() == yaml::node_t::string);
+ assert(child.string_value() == "bar");
+
+ // Go up to the root node.
+ node = node.parent().parent();
+ assert(node.type() == yaml::node_t::map);
+ assert(node.identity() == root_id);
+
+ node = node.child(keys[1]);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 3);
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1.0);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 2.0);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ key = node.key(0);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "a");
+
+ key = node.key(1);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "b");
+
+ key = node.key(2);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "c");
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1.1);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1.2);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1.3);
+ node = node.parent();
+
+ node = node.parent().parent(); // back to the root.
+ assert(node.identity() == root_id);
+
+ key = node.key(2);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "number");
+
+ key = node.key(3);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "string");
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 12.3);
+ node = node.parent();
+
+ node = node.child(3);
+ assert(node.type() == yaml::node_t::string);
+ assert(node.string_value() == "foo");
+ node = node.parent();
+}
+
+void test_yaml_parse_basic2()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/basic2/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 3);
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 1);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 2);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::number);
+ assert(node.numeric_value() == 3);
+ node = node.parent();
+}
+
+void test_yaml_parse_basic3()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/basic3/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 2);
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ assert(string_expected(node.key(0), "a"));
+ assert(string_expected(node.key(1), "b"));
+ assert(string_expected(node.key(2), "c"));
+
+ assert(number_expected(node.child(0), 1));
+ assert(number_expected(node.child(1), 2));
+ assert(number_expected(node.child(2), 3));
+
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ assert(string_expected(node.key(0), "d"));
+ assert(string_expected(node.key(1), "e"));
+ assert(string_expected(node.key(2), "f"));
+
+ assert(number_expected(node.child(0), 4));
+ assert(number_expected(node.child(1), 5));
+ assert(number_expected(node.child(2), 6));
+}
+
+void test_yaml_parse_null()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/null/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 6);
+
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::null);
+ node = node.parent();
+
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::null);
+ node = node.parent();
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::null);
+ node = node.parent();
+
+ node = node.child(3);
+ assert(node.type() == yaml::node_t::null);
+ node = node.parent();
+
+ node = node.child(4);
+ assert(node.type() == yaml::node_t::string);
+ assert(node.string_value() == "nULL");
+ node = node.parent();
+
+ node = node.child(5);
+ assert(node.type() == yaml::node_t::string);
+ assert(node.string_value() == "NUll");
+ node = node.parent();
+}
+
+void test_yaml_parse_boolean()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/boolean/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ yaml::const_node key = node.key(0);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "positive");
+
+ key = node.key(1);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "negative");
+
+ key = node.key(2);
+ assert(key.type() == yaml::node_t::string);
+ assert(key.string_value() == "non boolean");
+
+ // list of boolean true's.
+ node = node.child(0);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 11);
+ for (size_t i = 0; i < node.child_count(); ++i)
+ {
+ yaml::const_node child = node.child(i);
+ assert(child.type() == yaml::node_t::boolean_true);
+ }
+ node = node.parent();
+
+ // list of boolean false's.
+ node = node.child(1);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 11);
+ for (size_t i = 0; i < node.child_count(); ++i)
+ {
+ yaml::const_node child = node.child(i);
+ assert(child.type() == yaml::node_t::boolean_false);
+ }
+ node = node.parent();
+
+ // list of strings.
+ const char* values[] = {
+ "yES",
+ "nO",
+ "tRUE",
+ "faLSE",
+ "oN",
+ "oFF"
+ };
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == std::size(values));
+
+ for (size_t i = 0; i < std::size(values); ++i)
+ {
+ node = node.child(i);
+ assert(node.type() == yaml::node_t::string);
+ assert(node.string_value() == values[i]);
+ node = node.parent();
+ }
+}
+
+void test_yaml_parse_quoted_string()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/quoted-string/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 3);
+
+ assert(string_expected(node.key(0), "I am quoted: ~ "));
+ assert(string_expected(node.key(1), "list with quoted string values"));
+ assert(string_expected(node.key(2), "single quoted string values"));
+ assert(string_expected(node.child(0), "Here is another quote."));
+
+ node = node.child(1);
+
+ {
+ // list of strings.
+ const char* values[] = {
+ "1 2 3",
+ "null",
+ "true",
+ "false",
+ "#hashtag",
+ "\"quoted inside\"",
+ "'single quote inside'",
+ "Japan's finest beer"
+ };
+
+ size_t n = std::size(values);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == n);
+
+ for (size_t i = 0; i < n; ++i)
+ assert(string_expected(node.child(i), values[i]));
+ }
+
+ node = node.parent().child(2);
+
+ {
+ // list of strings.
+ const char* values[] = {
+ "8.8.8.8",
+ "'single quote inside'",
+ "prefix 'quoted' suffix",
+ "\"double quote\"",
+ "before \"quote\" after",
+ "http://www.google.com",
+ "'''",
+ " ' ' ' ",
+ "#hashtag"
+ };
+
+ size_t n = std::size(values);
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == n);
+
+ for (size_t i = 0; i < n; ++i)
+ assert(string_expected(node.child(i), values[i]));
+ }
+}
+
+void test_yaml_parse_multi_line_1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/multi-line-1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+ assert(string_expected(node, "1 2 3"));
+ assert(node.child_count() == 0);
+}
+
+void test_yaml_parse_multi_line_2()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/multi-line-2/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+ assert(string_expected(node, "1 - 2 - 3"));
+ assert(node.child_count() == 0);
+}
+
+void test_yaml_parse_literal_block_1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/literal-block-1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(string_expected(node, "line 1\n line 2\nline 3\n2 blanks follow "));
+ assert(node.child_count() == 0);
+}
+
+void test_yaml_parse_literal_block_2()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/literal-block-2/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 2);
+
+ assert(string_expected(node.key(0), "literal block"));
+ assert(string_expected(node.child(0), "line 1\n line 2\n line 3"));
+ assert(string_expected(node.key(1), "multi line"));
+ assert(string_expected(node.child(1), "line 1 line 2 line 3"));
+}
+
+void test_yaml_parse_url()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/url/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 3);
+
+ assert(string_expected(node.child(0), "http://www.google.com/"));
+ assert(string_expected(node.child(1), "mailto:joe@joe-me.com"));
+
+ node = node.child(2);
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 2);
+
+ assert(string_expected(node.key(0), "orcus-url"));
+ assert(string_expected(node.key(1), "debian-bugs"));
+ assert(string_expected(node.child(0), "http://gitlab.com/orcus/orcus"));
+ assert(string_expected(node.child(1), "mailto:submit@bugs.debian.org"));
+}
+
+void test_yaml_parse_empty_value_map_1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/empty-value-map-1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 1);
+
+ assert(string_expected(node.key(0), "key"));
+ assert(node.child(0).type() == yaml::node_t::null);
+}
+
+void test_yaml_parse_empty_value_map_2()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/empty-value-map-2/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 2);
+
+ assert(string_expected(node.key(0), "key1"));
+ assert(node.child(0).type() == yaml::node_t::null);
+ assert(string_expected(node.key(1), "key2"));
+ assert(node.child(1).type() == yaml::node_t::null);
+}
+
+void test_yaml_parse_empty_value_sequence_1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/empty-value-sequence-1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 1);
+
+ assert(node.child(0).type() == yaml::node_t::null);
+}
+
+void test_yaml_parse_empty_value_sequence_2()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/empty-value-sequence-2/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::sequence);
+ assert(node.child_count() == 2);
+
+ assert(node.child(0).type() == yaml::node_t::null);
+ assert(node.child(1).type() == yaml::node_t::null);
+}
+
+void test_yaml_map_key_1()
+{
+ yaml::document_tree doc = load_doc(SRCDIR"/test/yaml/map-key-1/input.yaml");
+
+ assert(doc.get_document_count() == 1);
+ yaml::const_node node = doc.get_document_root(0);
+
+ assert(node.type() == yaml::node_t::map);
+ assert(node.child_count() == 2);
+
+ assert(string_expected(node.key(0), "-key"));
+ assert(string_expected(node.child(0), "value"));
+ assert(string_expected(node.key(1), "key"));
+ assert(string_expected(node.child(1), "value"));
+}
+
+int main()
+{
+ test_yaml_invalids();
+ test_yaml_parse_basic1();
+ test_yaml_parse_basic2();
+ test_yaml_parse_basic3();
+ test_yaml_parse_null();
+ test_yaml_parse_boolean();
+ test_yaml_parse_quoted_string();
+ test_yaml_parse_multi_line_1();
+ test_yaml_parse_multi_line_2();
+ test_yaml_parse_literal_block_1();
+ test_yaml_parse_literal_block_2();
+ test_yaml_parse_url();
+ test_yaml_parse_empty_value_map_1();
+ test_yaml_parse_empty_value_map_2();
+ test_yaml_parse_empty_value_sequence_1();
+ test_yaml_parse_empty_value_sequence_2();
+ test_yaml_map_key_1();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+