From ea54f2647e6721b95bf17c9b457ef65991012a05 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 13 Feb 2025 21:57:07 -0500 Subject: [PATCH 1/7] Use xml_token_attrs_t type alias & add more descriptions to class docs --- src/liborcus/xlsx_pivot_context.cpp | 273 ++++++++++++++-------------- src/liborcus/xlsx_pivot_context.hpp | 25 +-- 2 files changed, 150 insertions(+), 148 deletions(-) diff --git a/src/liborcus/xlsx_pivot_context.cpp b/src/liborcus/xlsx_pivot_context.cpp index 98bd8a10..588eef9f 100644 --- a/src/liborcus/xlsx_pivot_context.cpp +++ b/src/liborcus/xlsx_pivot_context.cpp @@ -19,8 +19,7 @@ #include #include -using std::cout; -using std::endl; +namespace ss = orcus::spreadsheet; namespace orcus { @@ -53,8 +52,8 @@ const map_type& get() 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) : + ss::iface::import_pivot_cache_definition& pcache, + ss::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*/) @@ -66,7 +65,7 @@ void xlsx_pivot_cache_def_context::end_child_context(xmlns_id_t /*ns*/, xml_toke { } -void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector& attrs) +void xlsx_pivot_cache_def_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) @@ -116,11 +115,11 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name 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; + std::cout << "---" << std::endl; + std::cout << "pivot cache definition" << std::endl; + std::cout << "refreshed by: " << refreshed_by << std::endl; + std::cout << "record count: " << record_count << std::endl; + std::cout << "rid: " << rid << std::endl; } if (!rid.empty()) @@ -161,7 +160,7 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name ); if (get_config().debug) - cout << "type: " << source_type_s << endl; + std::cout << "type: " << source_type_s << std::endl; break; } @@ -199,9 +198,9 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name if (get_config().debug) { - cout << "table: " << table_name << endl; - cout << "ref: " << ref << endl; - cout << "sheet: " << sheet_name << endl; + std::cout << "table: " << table_name << std::endl; + std::cout << "ref: " << ref << std::endl; + std::cout << "sheet: " << sheet_name << std::endl; } if (!table_name.empty()) @@ -261,8 +260,8 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name if (get_config().debug) { - cout << "* name: " << field_name << endl; - cout << " number format id: " << numfmt_id << endl; + std::cout << "* name: " << field_name << std::endl; + std::cout << " number format id: " << numfmt_id << std::endl; } break; } @@ -295,9 +294,9 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name if (get_config().debug) { if (group_parent >= 0) - cout << " * group parent index: " << group_parent << endl; + std::cout << " * group parent index: " << group_parent << std::endl; if (group_base >= 0) - cout << " * group base index: " << group_base << endl; + std::cout << " * group base index: " << group_base << std::endl; } if (group_base >= 0) @@ -331,7 +330,7 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name ); if (get_config().debug) - cout << " * group child member count: " << count << endl; + std::cout << " * group child member count: " << count << std::endl; break; } @@ -349,8 +348,8 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name std::optional 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; + ss::pivot_cache_group_by_t group_by = + ss::pivot_cache_group_by_t::range; for_each(attrs.begin(), attrs.end(), [&](const xml_token_attr_t& attr) @@ -382,7 +381,7 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name end_date = date_time_t::from_chars(attr.value); break; case XML_groupBy: - group_by = spreadsheet::to_pivot_cache_group_by_enum(attr.value); + group_by = ss::to_pivot_cache_group_by_enum(attr.value); break; default: ; @@ -408,16 +407,16 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name 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; + std::cout << " auto start: " << auto_start << std::endl; + std::cout << " auto end: " << auto_end << std::endl; + std::cout << " start: " << start << std::endl; + std::cout << " end: " << end << std::endl; + std::cout << " interval: " << interval << std::endl; if (start_date) - cout << "start date: " << *start_date << endl; + std::cout << "start date: " << *start_date << std::endl; if (end_date) - cout << "end date: " << *end_date << endl; + std::cout << "end date: " << *end_date << std::endl; } break; @@ -451,7 +450,7 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name ); if (get_config().debug) - cout << " * group member count: " << count << endl; + std::cout << " * group member count: " << count << std::endl; break; } @@ -506,7 +505,7 @@ void xlsx_pivot_cache_def_context::start_element(xmlns_id_t ns, xml_token_t name throw xml_structure_error("element 'x' without a required attribute 'v'."); if (get_config().debug) - cout << " * index = " << index << endl; + std::cout << " * index = " << index << std::endl; if (m_pcache_field_group) m_pcache_field_group->link_base_to_group_items(index); @@ -575,7 +574,7 @@ opc_rel_extras_t xlsx_pivot_cache_def_context::pop_rel_extras() } void xlsx_pivot_cache_def_context::start_element_s( - const xml_token_pair_t& parent, const std::vector& attrs) + const xml_token_pair_t& parent, const xml_token_attrs_t& attrs) { if (parent.first != NS_ooxml_xlsx) { @@ -609,7 +608,7 @@ void xlsx_pivot_cache_def_context::start_element_s( // regular (non-group) field member name. if (get_config().debug) - cout << " * field member: " << value << endl; + std::cout << " * field member: " << value << std::endl; m_field_item_used = true; m_pcache.set_field_item_string(value); @@ -620,7 +619,7 @@ void xlsx_pivot_cache_def_context::start_element_s( // group field member name. if (get_config().debug) - cout << " * group field member: " << value << endl; + std::cout << " * group field member: " << value << std::endl; m_field_item_used = true; if (m_pcache_field_group) @@ -658,7 +657,7 @@ void xlsx_pivot_cache_def_context::end_element_s() } void xlsx_pivot_cache_def_context::start_element_n( - const xml_token_pair_t& parent, const std::vector& attrs) + const xml_token_pair_t& parent, const xml_token_attrs_t& attrs) { if (parent.first != NS_ooxml_xlsx) { @@ -696,10 +695,10 @@ void xlsx_pivot_cache_def_context::start_element_n( if (get_config().debug) { - cout << " * n: " << value; + std::cout << " * n: " << value; if (!m_field_item_used) - cout << " (unused)"; - cout << endl; + std::cout << " (unused)"; + std::cout << std::endl; } @@ -733,7 +732,7 @@ void xlsx_pivot_cache_def_context::end_element_n() } void xlsx_pivot_cache_def_context::start_element_d( - const xml_token_pair_t& parent, const std::vector& attrs) + const xml_token_pair_t& parent, const xml_token_attrs_t& attrs) { if (parent.first != NS_ooxml_xlsx) { @@ -771,10 +770,10 @@ void xlsx_pivot_cache_def_context::start_element_d( if (get_config().debug) { - cout << " * d: " << dt; + std::cout << " * d: " << dt; if (!m_field_item_used) - cout << " (unused)"; - cout << endl; + std::cout << " (unused)"; + std::cout << std::endl; } @@ -808,7 +807,7 @@ void xlsx_pivot_cache_def_context::end_element_d() } void xlsx_pivot_cache_def_context::start_element_e( - const xml_token_pair_t& parent, const std::vector& attrs) + const xml_token_pair_t& parent, const xml_token_attrs_t& attrs) { if (parent.first != NS_ooxml_xlsx) { @@ -821,7 +820,7 @@ void xlsx_pivot_cache_def_context::start_element_e( case XML_sharedItems: { // error value item of a cache field. - spreadsheet::error_value_t ev = spreadsheet::error_value_t::unknown; + ss::error_value_t ev = ss::error_value_t::unknown; m_field_item_used = true; for_each(attrs.begin(), attrs.end(), @@ -833,7 +832,7 @@ void xlsx_pivot_cache_def_context::start_element_e( switch (attr.name) { case XML_v: - ev = spreadsheet::to_error_value_enum(attr.value); + ev = ss::to_error_value_enum(attr.value); break; case XML_u: // flag for unused item. @@ -846,10 +845,10 @@ void xlsx_pivot_cache_def_context::start_element_e( if (get_config().debug) { - cout << " * e: " << ev; + std::cout << " * e: " << ev; if (!m_field_item_used) - cout << " (unused)"; - cout << endl; + std::cout << " (unused)"; + std::cout << std::endl; } if (m_field_item_used) @@ -882,7 +881,7 @@ void xlsx_pivot_cache_def_context::end_element_e() } void xlsx_pivot_cache_def_context::start_element_shared_items( - const xml_token_pair_t& parent, const std::vector& attrs) + const xml_token_pair_t& parent, const xml_token_attrs_t& attrs) { xml_element_expected(parent, NS_ooxml_xlsx, XML_cacheField); @@ -975,31 +974,31 @@ void xlsx_pivot_cache_def_context::start_element_shared_items( 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; + std::cout << " contains semi-mixed types: " << semi_mixed_types << std::endl; + std::cout << " contains non-date: " << has_non_date << std::endl; + std::cout << " contains date: " << has_date << std::endl; + std::cout << " contains string: " << has_string << std::endl; + std::cout << " contains blank: " << has_blank << std::endl; + std::cout << " contains mixed types: " << mixed_types << std::endl; + std::cout << " contains number: " << has_number << std::endl; + std::cout << " contains integer: " << has_integer << std::endl; + std::cout << " contains long text: " << has_long_text << std::endl; + std::cout << " count: " << count << std::endl; if (min_value) - cout << " min value: " << *min_value << endl; + std::cout << " min value: " << *min_value << std::endl; if (max_value) - cout << " max value: " << *max_value << endl; + std::cout << " max value: " << *max_value << std::endl; if (min_date) - cout << " min date: " << *min_date << endl; + std::cout << " min date: " << *min_date << std::endl; if (max_date) - cout << " max date: " << *max_date << endl; + std::cout << " max date: " << *max_date << std::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) : + ss::iface::import_pivot_cache_records& pc_records) : xml_context_base(cxt, tokens), m_pc_records(pc_records) {} @@ -1012,7 +1011,7 @@ void xlsx_pivot_cache_rec_context::end_child_context(xmlns_id_t /*ns*/, xml_toke { } -void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector& attrs) +void xlsx_pivot_cache_rec_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); @@ -1029,8 +1028,8 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name { if (get_config().debug) { - cout << "---" << endl; - cout << "pivot cache record (count: " << *count << ")" << endl; + std::cout << "---" << std::endl; + std::cout << "pivot cache record (count: " << *count << ")" << std::endl; } m_pc_records.set_record_count(*count); @@ -1040,7 +1039,7 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name case XML_r: // record xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotCacheRecords); if (get_config().debug) - cout << "* record" << endl; + std::cout << "* record" << std::endl; break; case XML_s: // character value @@ -1050,7 +1049,7 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name std::string_view cv = get_single_attr(attrs, NS_ooxml_xlsx, XML_v); if (get_config().debug) - cout << " * s = '" << cv << "'" << endl; + std::cout << " * s = '" << cv << "'" << std::endl; m_pc_records.append_record_value_character(cv); break; @@ -1061,7 +1060,7 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name if (auto v = get_single_long_attr(attrs, NS_ooxml_xlsx, XML_v); v) { if (get_config().debug) - cout << " * x = " << *v << endl; + std::cout << " * x = " << *v << std::endl; m_pc_records.append_record_value_shared_item(*v); } @@ -1078,7 +1077,7 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name throw xml_structure_error("failed to get a numeric record value in pivot cache record"); if (get_config().debug) - cout << " * n = " << *val << endl; + std::cout << " * n = " << *val << std::endl; m_pc_records.append_record_value_numeric(*val); break; @@ -1088,7 +1087,7 @@ void xlsx_pivot_cache_rec_context::start_element(xmlns_id_t ns, xml_token_t name std::string_view cv = get_single_attr(attrs, NS_ooxml_xlsx, XML_v); if (get_config().debug) - cout << " * e = " << cv << endl; + std::cout << " * e = " << cv << std::endl; break; } @@ -1132,7 +1131,7 @@ void xlsx_pivot_table_context::end_child_context(xmlns_id_t /*ns*/, xml_token_t { } -void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, const::std::vector& attrs) +void xlsx_pivot_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) @@ -1143,7 +1142,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { xml_element_expected(parent, XMLNS_UNKNOWN_ID, XML_UNKNOWN_TOKEN); if (get_config().debug) - cout << "---" << endl; + std::cout << "---" << std::endl; for (const xml_token_attr_t& attr : attrs) { if (attr.ns && attr.ns != NS_ooxml_xlsx) @@ -1156,111 +1155,111 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { case XML_name: if (get_config().debug) - cout << "name: " << attr.value << endl; + std::cout << "name: " << attr.value << std::endl; break; case XML_cacheId: v = to_long(attr.value); if (get_config().debug) - cout << "cache ID: " << v << endl; + std::cout << "cache ID: " << v << std::endl; break; case XML_applyNumberFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply number formats: " << b << endl; + std::cout << "apply number formats: " << b << std::endl; break; case XML_applyBorderFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply border formats: " << b << endl; + std::cout << "apply border formats: " << b << std::endl; break; case XML_applyFontFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply font formats: " << b << endl; + std::cout << "apply font formats: " << b << std::endl; break; case XML_applyPatternFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply pattern formats: " << b << endl; + std::cout << "apply pattern formats: " << b << std::endl; break; case XML_applyAlignmentFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply alignment formats: " << b << endl; + std::cout << "apply alignment formats: " << b << std::endl; break; case XML_applyWidthHeightFormats: b = to_bool(attr.value); if (get_config().debug) - cout << "apply width/height formats: " << b << endl; + std::cout << "apply width/height formats: " << b << std::endl; break; case XML_dataCaption: if (get_config().debug) - cout << "data caption: " << attr.value << endl; + std::cout << "data caption: " << attr.value << std::endl; break; case XML_updatedVersion: v = to_long(attr.value); if (get_config().debug) - cout << "updated version: " << v << endl; + std::cout << "updated version: " << v << std::endl; break; case XML_minRefreshableVersion: v = to_long(attr.value); if (get_config().debug) - cout << "minimum refreshable version: " << v << endl; + std::cout << "minimum refreshable version: " << v << std::endl; break; case XML_showCalcMbrs: b = to_bool(attr.value); if (get_config().debug) - cout << "show calc members (?): " << b << endl; + std::cout << "show calc members (?): " << b << std::endl; break; case XML_useAutoFormatting: b = to_bool(attr.value); if (get_config().debug) - cout << "use auto formatting: " << b << endl; + std::cout << "use auto formatting: " << b << std::endl; break; case XML_itemPrintTitles: b = to_bool(attr.value); if (get_config().debug) - cout << "item print titles (?): " << b << endl; + std::cout << "item print titles (?): " << b << std::endl; break; case XML_createdVersion: v = to_long(attr.value); if (get_config().debug) - cout << "created version: " << v << endl; + std::cout << "created version: " << v << std::endl; break; case XML_indent: b = to_bool(attr.value); if (get_config().debug) - cout << "indent: " << b << endl; + std::cout << "indent: " << b << std::endl; break; case XML_compact: b = to_bool(attr.value); if (get_config().debug) - cout << "compact: " << b << endl; + std::cout << "compact: " << b << std::endl; break; case XML_compactData: b = to_bool(attr.value); if (get_config().debug) - cout << "compact data: " << b << endl; + std::cout << "compact data: " << b << std::endl; break; case XML_outline: b = to_bool(attr.value); if (get_config().debug) - cout << "outline: " << b << endl; + std::cout << "outline: " << b << std::endl; break; case XML_outlineData: b = to_bool(attr.value); if (get_config().debug) - cout << "outline data: " << b << endl; + std::cout << "outline data: " << b << std::endl; break; case XML_gridDropZones: b = to_bool(attr.value); if (get_config().debug) - cout << "grid drop zones: " << b << endl; + std::cout << "grid drop zones: " << b << std::endl; break; case XML_multipleFieldFilters: b = to_bool(attr.value); if (get_config().debug) - cout << "multiple field filters: " << b << endl; + std::cout << "multiple field filters: " << b << std::endl; break; default: ; @@ -1282,22 +1281,22 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { case XML_ref: if (get_config().debug) - cout << "ref: " << attr.value << endl; + std::cout << "ref: " << attr.value << std::endl; break; case XML_firstHeaderRow: v = to_long(attr.value); if (get_config().debug) - cout << "first header row: " << v << endl; + std::cout << "first header row: " << v << std::endl; break; case XML_firstDataRow: v = to_long(attr.value); if (get_config().debug) - cout << "first data row: " << v << endl; + std::cout << "first data row: " << v << std::endl; break; case XML_firstDataCol: v = to_long(attr.value); if (get_config().debug) - cout << "first data column: " << v << endl; + std::cout << "first data column: " << v << std::endl; break; default: ; @@ -1322,7 +1321,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co xml_element_expected(parent, NS_ooxml_xlsx, XML_pivotFields); if (get_config().debug) - cout << "---" << endl; + std::cout << "---" << std::endl; for (const xml_token_attr_t& attr : attrs) { @@ -1333,34 +1332,34 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { case XML_axis: if (get_config().debug) - cout << " * axis: " << attr.value << endl; + std::cout << " * axis: " << attr.value << std::endl; break; case XML_compact: { bool b = to_bool(attr.value); if (get_config().debug) - cout << " * compact: " << b << endl; + std::cout << " * compact: " << b << std::endl; } break; case XML_outline: { bool b = to_bool(attr.value); if (get_config().debug) - cout << " * outline: " << b << endl; + std::cout << " * outline: " << b << std::endl; } break; case XML_showAll: { bool b = to_bool(attr.value); if (get_config().debug) - cout << " * show all: " << b << endl; + std::cout << " * show all: " << b << std::endl; } break; case XML_dataField: { bool b = to_bool(attr.value); if (get_config().debug) - cout << " * data field: " << b << endl; + std::cout << " * data field: " << b << std::endl; } break; default: @@ -1375,7 +1374,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co if (auto count = get_single_long_attr(attrs, NS_ooxml_xlsx, XML_count); count) { if (get_config().debug) - cout << " * item count: " << *count << endl; + std::cout << " * item count: " << *count << std::endl; } } break; @@ -1395,7 +1394,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co // field item index as defined in the pivot cache. long idx = to_long(attr.value); if (get_config().debug) - cout << " * x = " << idx << endl; + std::cout << " * x = " << idx << std::endl; } break; case XML_t: @@ -1404,7 +1403,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co // 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; + std::cout << " * type = " << attr.value << std::endl; } break; default: @@ -1457,7 +1456,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co xml_element_expected(parent, NS_ooxml_xlsx, XML_pageFields); if (get_config().debug) - cout << " * page field:"; + std::cout << " * page field:"; for (const xml_token_attr_t& attr : attrs) { @@ -1470,14 +1469,14 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { long fld = to_long(attr.value); if (get_config().debug) - cout << "field index = " << fld << "; "; + std::cout << "field index = " << fld << "; "; break; } case XML_item: { long item = to_long(attr.value); if (get_config().debug) - cout << "item index = " << item << "; "; + std::cout << "item index = " << item << "; "; break; } case XML_hier: @@ -1485,7 +1484,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co long hier = to_long(attr.value); // -1 if not applicable. if (get_config().debug) - cout << "OLAP hierarchy index = " << hier << "; "; + std::cout << "OLAP hierarchy index = " << hier << "; "; break; } default: @@ -1494,7 +1493,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co } if (get_config().debug) - cout << endl; + std::cout << std::endl; break; } case XML_field: @@ -1524,8 +1523,8 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { if (get_config().debug) { - cout << "---" << endl; - cout << "data field count: " << *count << endl; + std::cout << "---" << std::endl; + std::cout << "data field count: " << *count << std::endl; } } } @@ -1535,7 +1534,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co xml_element_expected(parent, NS_ooxml_xlsx, XML_dataFields); if (get_config().debug) - cout << " * data field: "; + std::cout << " * data field: "; for (const xml_token_attr_t& attr : attrs) { @@ -1547,34 +1546,34 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co case XML_name: { if (get_config().debug) - cout << "name = " << attr.value << "; "; + std::cout << "name = " << attr.value << "; "; break; } case XML_fld: { long fld = to_long(attr.value); if (get_config().debug) - cout << "field = " << fld << "; "; + std::cout << "field = " << fld << "; "; break; } case XML_baseField: { long fld = to_long(attr.value); if (get_config().debug) - cout << "base field = " << fld << "; "; + std::cout << "base field = " << fld << "; "; break; } case XML_baseItem: { long fld = to_long(attr.value); if (get_config().debug) - cout << "base item = " << fld << "; "; + std::cout << "base item = " << fld << "; "; break; } case XML_subtotal: { if (get_config().debug) - cout << "subtotal = " << attr.value << "; "; + std::cout << "subtotal = " << attr.value << "; "; break; } default: @@ -1583,7 +1582,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co } if (get_config().debug) - cout << endl; + std::cout << std::endl; } break; case XML_rowItems: @@ -1624,7 +1623,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co xml_element_expected(parent, expected); if (get_config().debug) - cout << "---" << endl; + std::cout << "---" << std::endl; for (const xml_token_attr_t& attr : attrs) { @@ -1637,7 +1636,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { // total or subtotal function type. if (get_config().debug) - cout << " * type = " << attr.value << endl; + std::cout << " * type = " << attr.value << std::endl; } break; case XML_r: @@ -1647,7 +1646,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co // the same row (in the classic layout mode). long v = to_long(attr.value); if (get_config().debug) - cout << " * repeat item count = " << v << endl; + std::cout << " * repeat item count = " << v << std::endl; } break; case XML_i: @@ -1655,7 +1654,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co // 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; + std::cout << " * data field index = " << v << std::endl; } break; default: @@ -1683,7 +1682,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co idx = 0; if (get_config().debug) - cout << " * v = " << idx << endl; + std::cout << " * v = " << idx << std::endl; break; } @@ -1696,8 +1695,8 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co if (get_config().debug) { - cout << "---" << endl; - cout << "* style info: "; + std::cout << "---" << std::endl; + std::cout << "* style info: "; } for (const xml_token_attr_t& attr : attrs) @@ -1711,32 +1710,32 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co { case XML_name: if (get_config().debug) - cout << "name='" << attr.value << "'; "; + std::cout << "name='" << attr.value << "'; "; break; case XML_showRowHeaders: b = to_bool(attr.value); if (get_config().debug) - cout << "show row headers=" << b << "; "; + std::cout << "show row headers=" << b << "; "; break; case XML_showColHeaders: b = to_bool(attr.value); if (get_config().debug) - cout << "show column headers=" << b << "; "; + std::cout << "show column headers=" << b << "; "; break; case XML_showRowStripes: b = to_bool(attr.value); if (get_config().debug) - cout << "show row stripes=" << b << "; "; + std::cout << "show row stripes=" << b << "; "; break; case XML_showColStripes: b = to_bool(attr.value); if (get_config().debug) - cout << "show column stripes=" << b << "; "; + std::cout << "show column stripes=" << b << "; "; break; case XML_showLastColumn: b = to_bool(attr.value); if (get_config().debug) - cout << "show last column=" << b << "; "; + std::cout << "show last column=" << b << "; "; break; default: ; @@ -1744,7 +1743,7 @@ void xlsx_pivot_table_context::start_element(xmlns_id_t ns, xml_token_t name, co } if (get_config().debug) - cout << endl; + std::cout << std::endl; break; } default: diff --git a/src/liborcus/xlsx_pivot_context.hpp b/src/liborcus/xlsx_pivot_context.hpp index f9610ba1..b31acb3a 100644 --- a/src/liborcus/xlsx_pivot_context.hpp +++ b/src/liborcus/xlsx_pivot_context.hpp @@ -24,7 +24,9 @@ class import_pivot_cache_records; /** * Base context for pivotCacheDefinition[n].xml part, which defines the - * structure of a pivot cache. + * high-level structure of a pivot cache with individual item values of string + * fields. Individual values of numeric fields are not stored here; + * they are stored in the pivotCacheRecords part. */ class xlsx_pivot_cache_def_context : public xml_context_base { @@ -54,31 +56,32 @@ public: 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& attrs); + 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); opc_rel_extras_t pop_rel_extras(); private: - void start_element_s(const xml_token_pair_t& parent, const std::vector& attrs); + void start_element_s(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs); void end_element_s(); - void start_element_n(const xml_token_pair_t& parent, const std::vector& attrs); + void start_element_n(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs); void end_element_n(); - void start_element_d(const xml_token_pair_t& parent, const std::vector& attrs); + void start_element_d(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs); void end_element_d(); - void start_element_e(const xml_token_pair_t& parent, const std::vector& attrs); + void start_element_e(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs); void end_element_e(); - void start_element_shared_items(const xml_token_pair_t& parent, const std::vector& attrs); + void start_element_shared_items(const xml_token_pair_t& parent, const xml_token_attrs_t& attrs); }; /** - * Context for pivotCacheRecords[n].xml part, which contains the records in - * a pivot cache. + * Context for pivotCacheRecords[n].xml part, which stores the records in + * a pivot cache. Each record consists of string value indices into the + * pivotCacheDefinition part and numeric values. */ class xlsx_pivot_cache_rec_context : public xml_context_base { @@ -91,7 +94,7 @@ public: 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& attrs); + 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); }; @@ -106,7 +109,7 @@ public: 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& attrs); + 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); }; -- GitLab From 2e683605087d822fdc05fcb9de3f4240557012b5 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 13 Feb 2025 23:54:15 -0500 Subject: [PATCH 2/7] Set up a hook for dumping internal state of stored pivot caches --- include/orcus/spreadsheet/pivot.hpp | 8 ++ src/spreadsheet/CMakeLists.txt | 2 + src/spreadsheet/Makefile.am | 4 + src/spreadsheet/debug_state_dumper_pivot.cpp | 35 ++++++ src/spreadsheet/debug_state_dumper_pivot.hpp | 28 +++++ src/spreadsheet/document.cpp | 2 + src/spreadsheet/pivot.cpp | 114 +++++-------------- src/spreadsheet/pivot_impl.cpp | 46 ++++++++ src/spreadsheet/pivot_impl.hpp | 83 ++++++++++++++ 9 files changed, 234 insertions(+), 88 deletions(-) create mode 100644 src/spreadsheet/debug_state_dumper_pivot.cpp create mode 100644 src/spreadsheet/debug_state_dumper_pivot.hpp create mode 100644 src/spreadsheet/pivot_impl.cpp create mode 100644 src/spreadsheet/pivot_impl.hpp diff --git a/include/orcus/spreadsheet/pivot.hpp b/include/orcus/spreadsheet/pivot.hpp index dee25596..9b763feb 100644 --- a/include/orcus/spreadsheet/pivot.hpp +++ b/include/orcus/spreadsheet/pivot.hpp @@ -32,6 +32,8 @@ namespace spreadsheet { class document; +namespace detail { class debug_state_dumper_pivot_cache; } + using pivot_cache_indices_t = std::vector; struct ORCUS_SPM_DLLPUBLIC pivot_cache_record_value_t @@ -167,6 +169,8 @@ struct ORCUS_SPM_DLLPUBLIC pivot_cache_field_t class ORCUS_SPM_DLLPUBLIC pivot_cache { + friend class detail::debug_state_dumper_pivot_cache; + struct impl; std::unique_ptr mp_impl; @@ -202,6 +206,8 @@ public: pivot_cache_id_t get_id() const; const records_type& get_all_records() const; + + void dump_debug_state(std::string_view outdir) const; }; class ORCUS_SPM_DLLPUBLIC pivot_collection @@ -245,6 +251,8 @@ public: pivot_cache* get_cache(pivot_cache_id_t cache_id); const pivot_cache* get_cache(pivot_cache_id_t cache_id) const; + + void dump_debug_state(std::string_view outdir) const; }; }} diff --git a/src/spreadsheet/CMakeLists.txt b/src/spreadsheet/CMakeLists.txt index b231c0c9..1d0ab509 100644 --- a/src/spreadsheet/CMakeLists.txt +++ b/src/spreadsheet/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(orcus-spreadsheet-model-${ORCUS_API_VERSION} SHARED config.cpp csv_dumper.cpp debug_state_dumper.cpp + debug_state_dumper_pivot.cpp document.cpp document_impl.cpp document_types.cpp @@ -25,6 +26,7 @@ add_library(orcus-spreadsheet-model-${ORCUS_API_VERSION} SHARED json_dumper.cpp number_format.cpp pivot.cpp + pivot_impl.cpp shared_formula.cpp shared_strings.cpp sheet.cpp diff --git a/src/spreadsheet/Makefile.am b/src/spreadsheet/Makefile.am index 8833d34e..0559b4fc 100644 --- a/src/spreadsheet/Makefile.am +++ b/src/spreadsheet/Makefile.am @@ -36,6 +36,8 @@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES = \ config.cpp \ debug_state_dumper.hpp \ debug_state_dumper.cpp \ + debug_state_dumper_pivot.hpp \ + debug_state_dumper_pivot.cpp \ document.cpp \ document_impl.hpp \ document_impl.cpp \ @@ -72,6 +74,8 @@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES = \ number_format.hpp \ number_format.cpp \ pivot.cpp \ + pivot_impl.hpp \ + pivot_impl.cpp \ shared_formula.hpp \ shared_formula.cpp \ shared_strings.cpp \ diff --git a/src/spreadsheet/debug_state_dumper_pivot.cpp b/src/spreadsheet/debug_state_dumper_pivot.cpp new file mode 100644 index 00000000..673ecf82 --- /dev/null +++ b/src/spreadsheet/debug_state_dumper_pivot.cpp @@ -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/. + */ + +#include "debug_state_dumper_pivot.hpp" +#include "pivot_impl.hpp" + +#include +#include + +namespace orcus { namespace spreadsheet { namespace detail { + +debug_state_dumper_pivot_cache::debug_state_dumper_pivot_cache(const pivot_cache::impl& store) : + m_store(store) +{ +} + +void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const +{ + fs::create_directories(outdir); + + std::ostringstream os; + os << "cache-" << m_store.m_cache_id << ".yaml"; + fs::path outpath = outdir / os.str(); + std::ofstream of{outpath.native()}; + + of << "id: " << m_store.m_cache_id << std::endl; +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/debug_state_dumper_pivot.hpp b/src/spreadsheet/debug_state_dumper_pivot.hpp new file mode 100644 index 00000000..143680c6 --- /dev/null +++ b/src/spreadsheet/debug_state_dumper_pivot.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/. + */ + +#pragma once + +#include "filesystem_env.hpp" + +#include + +namespace orcus { namespace spreadsheet { namespace detail { + +class debug_state_dumper_pivot_cache +{ + const pivot_cache::impl& m_store; + +public: + debug_state_dumper_pivot_cache(const pivot_cache::impl& store); + + void dump(const fs::path& outdir) const; +}; + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/document.cpp b/src/spreadsheet/document.cpp index f99751aa..cc97dc45 100644 --- a/src/spreadsheet/document.cpp +++ b/src/spreadsheet/document.cpp @@ -356,6 +356,8 @@ void document::dump_debug_state(const std::string& outdir) const fs::create_directories(outpath); sheet->data.dump_debug_state(outpath.string(), sheet->name); } + + mp_impl->pivots.dump_debug_state(outdir); } sheet_t document::get_sheet_index(std::string_view name) const diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp index 4bc21ee8..1b3d7340 100644 --- a/src/spreadsheet/pivot.cpp +++ b/src/spreadsheet/pivot.cpp @@ -9,11 +9,14 @@ #include "orcus/spreadsheet/document.hpp" #include "orcus/string_pool.hpp" -#include +#include "filesystem_env.hpp" +#include "pivot_impl.hpp" +#include "debug_state_dumper_pivot.hpp" #include #include #include +#include namespace orcus { namespace spreadsheet { @@ -149,22 +152,6 @@ pivot_cache_field_t::pivot_cache_field_t(pivot_cache_field_t&& other) : other.name = std::string_view{}; } -struct pivot_cache::impl -{ - pivot_cache_id_t m_cache_id; - - string_pool& m_string_pool; - - std::string_view m_src_sheet_name; - - pivot_cache::fields_type m_fields; - - pivot_cache::records_type m_records; - - impl(pivot_cache_id_t cache_id, string_pool& sp) : - m_cache_id(cache_id), m_string_pool(sp) {} -}; - pivot_cache::pivot_cache(pivot_cache_id_t cache_id, string_pool& sp) : mp_impl(std::make_unique(cache_id, sp)) {} @@ -200,73 +187,15 @@ const pivot_cache::records_type& pivot_cache::get_all_records() const return mp_impl->m_records; } -namespace { - -constexpr const ixion::sheet_t ignored_sheet = -1; - -struct worksheet_range +void pivot_cache::dump_debug_state(std::string_view outdir) const { - std::string_view sheet; /// it must be an interned string with the document. - ixion::abs_range_t range; /// sheet indices are ignored. - - worksheet_range(std::string_view _sheet, ixion::abs_range_t _range) : - sheet(std::move(_sheet)), range(std::move(_range)) - { - range.first.sheet = ignored_sheet; - range.last.sheet = ignored_sheet; - } - - bool operator== (const worksheet_range& other) const - { - return sheet == other.sheet && range == other.range; - } - - struct hash - { - std::hash ps_hasher; - ixion::abs_range_t::hash range_hasher; - - size_t operator() (const worksheet_range& v) const - { - assert(v.range.first.sheet == ignored_sheet); - assert(v.range.last.sheet == ignored_sheet); - - size_t n = ps_hasher(v.sheet); - n ^= range_hasher(v.range); - return n; - } - }; -}; - -using range_map_type = std::unordered_map, worksheet_range::hash>; -using name_map_type = std::unordered_map>; - -using caches_type = std::unordered_map>; + fs::path output_dir{outdir}; + fs::create_directories(output_dir); + detail::debug_state_dumper_pivot_cache dumper(*mp_impl); + dumper.dump(output_dir); } -struct pivot_collection::impl -{ - document& m_doc; - - range_map_type m_worksheet_range_map; /// mapping of sheet name & range pair to cache ID. - name_map_type m_table_map; /// mapping of table name to cache ID. - - caches_type m_caches; - - impl(document& doc) : m_doc(doc) {} - - void ensure_unique_cache(pivot_cache_id_t cache_id) - { - if (m_caches.count(cache_id) > 0) - { - std::ostringstream os; - os << "Pivot cache with the ID of " << cache_id << " already exists."; - throw std::invalid_argument(os.str()); - } - } -}; - pivot_collection::pivot_collection(document& doc) : mp_impl(std::make_unique(doc)) {} pivot_collection::~pivot_collection() {} @@ -283,16 +212,16 @@ void pivot_collection::insert_worksheet_cache( // overwrite the existing cache. mp_impl->m_caches[cache_id] = std::move(cache); - worksheet_range key(sheet_name, range); + detail::worksheet_range key(sheet_name, range); - range_map_type& range_map = mp_impl->m_worksheet_range_map; + auto& range_map = mp_impl->m_worksheet_range_map; auto it = range_map.find(key); if (it == range_map.end()) { // sheet name must be interned with the document it belongs to. key.sheet = mp_impl->m_doc.get_string_pool().intern(key.sheet).first; - range_map.insert(range_map_type::value_type(std::move(key), {cache_id})); + range_map.insert(detail::range_map_type::value_type(std::move(key), {cache_id})); return; } @@ -309,7 +238,7 @@ void pivot_collection::insert_worksheet_cache( mp_impl->m_caches[cache_id] = std::move(cache); - name_map_type& name_map = mp_impl->m_table_map; + auto& name_map = mp_impl->m_table_map; auto it = name_map.find(table_name); if (it == name_map.end()) @@ -317,7 +246,7 @@ void pivot_collection::insert_worksheet_cache( // First cache to be associated with this name. std::string_view table_name_interned = mp_impl->m_doc.get_string_pool().intern(table_name).first; - name_map.insert(name_map_type::value_type(table_name_interned, {cache_id})); + name_map.insert(detail::name_map_type::value_type(table_name_interned, {cache_id})); return; } @@ -333,7 +262,7 @@ size_t pivot_collection::get_cache_count() const const pivot_cache* pivot_collection::get_cache( std::string_view sheet_name, const ixion::abs_range_t& range) const { - worksheet_range wr(sheet_name, range); + detail::worksheet_range wr(sheet_name, range); auto it = mp_impl->m_worksheet_range_map.find(wr); if (it == mp_impl->m_worksheet_range_map.end()) @@ -358,12 +287,21 @@ _CacheT* get_cache_impl(_CachesT& caches, pivot_cache_id_t cache_id) pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) { - return get_cache_impl(mp_impl->m_caches, cache_id); + return get_cache_impl(mp_impl->m_caches, cache_id); } const pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) const { - return get_cache_impl(mp_impl->m_caches, cache_id); + return get_cache_impl(mp_impl->m_caches, cache_id); +} + +void pivot_collection::dump_debug_state(std::string_view outdir) const +{ + fs::path output_dir{outdir}; + output_dir /= "pivot"; + + for (const auto& [id, cache] : mp_impl->m_caches) + cache->dump_debug_state(output_dir.string()); } }} diff --git a/src/spreadsheet/pivot_impl.cpp b/src/spreadsheet/pivot_impl.cpp new file mode 100644 index 00000000..ea4e5884 --- /dev/null +++ b/src/spreadsheet/pivot_impl.cpp @@ -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/. + */ + +#include "pivot_impl.hpp" + +#include + +namespace orcus { namespace spreadsheet { + +namespace detail { + +std::size_t worksheet_range::hash::operator()(const worksheet_range& v) const +{ + assert(v.range.first.sheet == ignored_sheet); + assert(v.range.last.sheet == ignored_sheet); + + size_t n = ps_hasher(v.sheet); + n ^= range_hasher(v.range); + return n; +} + +} // namespace detail + +pivot_cache::impl::impl(pivot_cache_id_t cache_id, string_pool& sp) : + m_cache_id(cache_id), m_string_pool(sp) {} + +pivot_collection::impl::impl(document& doc) : m_doc(doc) {} + +void pivot_collection::impl::ensure_unique_cache(pivot_cache_id_t cache_id) +{ + if (m_caches.count(cache_id) > 0) + { + std::ostringstream os; + os << "Pivot cache with the ID of " << cache_id << " already exists."; + throw std::invalid_argument(os.str()); + } +} + +}} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/pivot_impl.hpp b/src/spreadsheet/pivot_impl.hpp new file mode 100644 index 00000000..e83969d4 --- /dev/null +++ b/src/spreadsheet/pivot_impl.hpp @@ -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/. + */ + +#pragma once + +#include +#include +#include + +#include + +namespace orcus { namespace spreadsheet { + +namespace detail { + +constexpr const ixion::sheet_t ignored_sheet = -1; + +struct worksheet_range +{ + std::string_view sheet; /// it must be an interned string with the document. + ixion::abs_range_t range; /// sheet indices are ignored. + + worksheet_range(std::string_view _sheet, ixion::abs_range_t _range) : + sheet(std::move(_sheet)), range(std::move(_range)) + { + range.first.sheet = ignored_sheet; + range.last.sheet = ignored_sheet; + } + + bool operator== (const worksheet_range& other) const + { + return sheet == other.sheet && range == other.range; + } + + struct hash + { + std::hash ps_hasher; + ixion::abs_range_t::hash range_hasher; + + std::size_t operator() (const worksheet_range& v) const; + }; +}; + +using range_map_type = std::unordered_map, worksheet_range::hash>; +using name_map_type = std::unordered_map>; +using caches_type = std::unordered_map>; + +} + +struct pivot_cache::impl +{ + pivot_cache_id_t m_cache_id; + + string_pool& m_string_pool; + + std::string_view m_src_sheet_name; + + pivot_cache::fields_type m_fields; + pivot_cache::records_type m_records; + + impl(pivot_cache_id_t cache_id, string_pool& sp); +}; + +struct pivot_collection::impl +{ + document& m_doc; + + detail::range_map_type m_worksheet_range_map; /// mapping of sheet name & range pair to cache ID. + detail::name_map_type m_table_map; /// mapping of table name to cache ID. + detail::caches_type m_caches; + + impl(document& doc); + + void ensure_unique_cache(pivot_cache_id_t cache_id); +}; + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- GitLab From c50bc0b3b50b884589c41dd40a6d37b672888479 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Fri, 14 Feb 2025 00:01:06 -0500 Subject: [PATCH 3/7] No more m_ prefix for struct members --- src/spreadsheet/debug_state_dumper_pivot.cpp | 4 +-- src/spreadsheet/pivot.cpp | 38 ++++++++++---------- src/spreadsheet/pivot_impl.cpp | 8 ++--- src/spreadsheet/pivot_impl.hpp | 24 ++++++------- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/spreadsheet/debug_state_dumper_pivot.cpp b/src/spreadsheet/debug_state_dumper_pivot.cpp index 673ecf82..47afebf2 100644 --- a/src/spreadsheet/debug_state_dumper_pivot.cpp +++ b/src/spreadsheet/debug_state_dumper_pivot.cpp @@ -23,11 +23,11 @@ void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const fs::create_directories(outdir); std::ostringstream os; - os << "cache-" << m_store.m_cache_id << ".yaml"; + os << "cache-" << m_store.cache_id << ".yaml"; fs::path outpath = outdir / os.str(); std::ofstream of{outpath.native()}; - of << "id: " << m_store.m_cache_id << std::endl; + of << "id: " << m_store.cache_id << std::endl; } }}} diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp index 1b3d7340..a829abb6 100644 --- a/src/spreadsheet/pivot.cpp +++ b/src/spreadsheet/pivot.cpp @@ -159,32 +159,32 @@ pivot_cache::~pivot_cache() {} void pivot_cache::insert_fields(fields_type fields) { - mp_impl->m_fields = std::move(fields); + mp_impl->fields = std::move(fields); } void pivot_cache::insert_records(records_type records) { - mp_impl->m_records = std::move(records); + mp_impl->records = std::move(records); } size_t pivot_cache::get_field_count() const { - return mp_impl->m_fields.size(); + return mp_impl->fields.size(); } const pivot_cache_field_t* pivot_cache::get_field(size_t index) const { - return index < mp_impl->m_fields.size() ? &mp_impl->m_fields[index] : nullptr; + return index < mp_impl->fields.size() ? &mp_impl->fields[index] : nullptr; } pivot_cache_id_t pivot_cache::get_id() const { - return mp_impl->m_cache_id; + return mp_impl->cache_id; } const pivot_cache::records_type& pivot_cache::get_all_records() const { - return mp_impl->m_records; + return mp_impl->records; } void pivot_cache::dump_debug_state(std::string_view outdir) const @@ -210,17 +210,17 @@ void pivot_collection::insert_worksheet_cache( // Check and see if there is already a cache for this location. If yes, // overwrite the existing cache. - mp_impl->m_caches[cache_id] = std::move(cache); + mp_impl->caches[cache_id] = std::move(cache); detail::worksheet_range key(sheet_name, range); - auto& range_map = mp_impl->m_worksheet_range_map; + auto& range_map = mp_impl->worksheet_range_map; auto it = range_map.find(key); if (it == range_map.end()) { // sheet name must be interned with the document it belongs to. - key.sheet = mp_impl->m_doc.get_string_pool().intern(key.sheet).first; + key.sheet = mp_impl->doc.get_string_pool().intern(key.sheet).first; range_map.insert(detail::range_map_type::value_type(std::move(key), {cache_id})); return; } @@ -236,16 +236,16 @@ void pivot_collection::insert_worksheet_cache( pivot_cache_id_t cache_id = cache->get_id(); mp_impl->ensure_unique_cache(cache_id); - mp_impl->m_caches[cache_id] = std::move(cache); + mp_impl->caches[cache_id] = std::move(cache); - auto& name_map = mp_impl->m_table_map; + auto& name_map = mp_impl->table_map; auto it = name_map.find(table_name); if (it == name_map.end()) { // First cache to be associated with this name. std::string_view table_name_interned = - mp_impl->m_doc.get_string_pool().intern(table_name).first; + mp_impl->doc.get_string_pool().intern(table_name).first; name_map.insert(detail::name_map_type::value_type(table_name_interned, {cache_id})); return; } @@ -256,7 +256,7 @@ void pivot_collection::insert_worksheet_cache( size_t pivot_collection::get_cache_count() const { - return mp_impl->m_caches.size(); + return mp_impl->caches.size(); } const pivot_cache* pivot_collection::get_cache( @@ -264,14 +264,14 @@ const pivot_cache* pivot_collection::get_cache( { detail::worksheet_range wr(sheet_name, range); - auto it = mp_impl->m_worksheet_range_map.find(wr); - if (it == mp_impl->m_worksheet_range_map.end()) + auto it = mp_impl->worksheet_range_map.find(wr); + if (it == mp_impl->worksheet_range_map.end()) return nullptr; // Pick the first cache ID. assert(!it->second.empty()); pivot_cache_id_t cache_id = *it->second.cbegin(); - return mp_impl->m_caches[cache_id].get(); + return mp_impl->caches[cache_id].get(); } namespace { @@ -287,12 +287,12 @@ _CacheT* get_cache_impl(_CachesT& caches, pivot_cache_id_t cache_id) pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) { - return get_cache_impl(mp_impl->m_caches, cache_id); + return get_cache_impl(mp_impl->caches, cache_id); } const pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) const { - return get_cache_impl(mp_impl->m_caches, cache_id); + return get_cache_impl(mp_impl->caches, cache_id); } void pivot_collection::dump_debug_state(std::string_view outdir) const @@ -300,7 +300,7 @@ void pivot_collection::dump_debug_state(std::string_view outdir) const fs::path output_dir{outdir}; output_dir /= "pivot"; - for (const auto& [id, cache] : mp_impl->m_caches) + for (const auto& [id, cache] : mp_impl->caches) cache->dump_debug_state(output_dir.string()); } diff --git a/src/spreadsheet/pivot_impl.cpp b/src/spreadsheet/pivot_impl.cpp index ea4e5884..272aaf0c 100644 --- a/src/spreadsheet/pivot_impl.cpp +++ b/src/spreadsheet/pivot_impl.cpp @@ -25,14 +25,14 @@ std::size_t worksheet_range::hash::operator()(const worksheet_range& v) const } // namespace detail -pivot_cache::impl::impl(pivot_cache_id_t cache_id, string_pool& sp) : - m_cache_id(cache_id), m_string_pool(sp) {} +pivot_cache::impl::impl(pivot_cache_id_t _cache_id, string_pool& sp) : + cache_id(_cache_id), str_pool(sp) {} -pivot_collection::impl::impl(document& doc) : m_doc(doc) {} +pivot_collection::impl::impl(document& _doc) : doc(_doc) {} void pivot_collection::impl::ensure_unique_cache(pivot_cache_id_t cache_id) { - if (m_caches.count(cache_id) > 0) + if (caches.count(cache_id) > 0) { std::ostringstream os; os << "Pivot cache with the ID of " << cache_id << " already exists."; diff --git a/src/spreadsheet/pivot_impl.hpp b/src/spreadsheet/pivot_impl.hpp index e83969d4..82044295 100644 --- a/src/spreadsheet/pivot_impl.hpp +++ b/src/spreadsheet/pivot_impl.hpp @@ -53,27 +53,23 @@ using caches_type = std::unordered_map Date: Wed, 19 Feb 2025 21:17:45 -0500 Subject: [PATCH 4/7] Dump the content of pivot cache fields And add any missing pieces of code to make it happen. --- bin/parse-doxygen-xml.py | 1 + include/orcus/spreadsheet/pivot.hpp | 7 +++ include/orcus/spreadsheet/types.hpp | 1 + src/enum_stream_test.cpp | 2 - src/liborcus/spreadsheet_types.cpp | 22 +++++++ src/spreadsheet/debug_state_dumper_pivot.cpp | 60 ++++++++++++++++++++ src/spreadsheet/factory_pivot.cpp | 2 + src/spreadsheet/pivot.cpp | 50 ++++++++++++++++ 8 files changed, 143 insertions(+), 2 deletions(-) diff --git a/bin/parse-doxygen-xml.py b/bin/parse-doxygen-xml.py index ad994ccb..7dfddb98 100755 --- a/bin/parse-doxygen-xml.py +++ b/bin/parse-doxygen-xml.py @@ -250,6 +250,7 @@ def create_enum_stream_test(rootdir, output_dir): "orcus::spreadsheet::border_style_t", "orcus::spreadsheet::formula_grammar_t", "orcus::spreadsheet::hor_alignment_t", + "orcus::spreadsheet::pivot_cache_group_by_t", "orcus::spreadsheet::strikethrough_style_t", "orcus::spreadsheet::strikethrough_text_t", "orcus::spreadsheet::strikethrough_type_t", diff --git a/include/orcus/spreadsheet/pivot.hpp b/include/orcus/spreadsheet/pivot.hpp index 9b763feb..d27c814e 100644 --- a/include/orcus/spreadsheet/pivot.hpp +++ b/include/orcus/spreadsheet/pivot.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace ixion { @@ -165,6 +166,10 @@ struct ORCUS_SPM_DLLPUBLIC pivot_cache_field_t pivot_cache_field_t(std::string_view _name); pivot_cache_field_t(const pivot_cache_field_t& other); pivot_cache_field_t(pivot_cache_field_t&& other); + + pivot_cache_field_t& operator=(pivot_cache_field_t other); + + void swap(pivot_cache_field_t& other) noexcept; }; class ORCUS_SPM_DLLPUBLIC pivot_cache @@ -255,6 +260,8 @@ public: void dump_debug_state(std::string_view outdir) const; }; +ORCUS_SPM_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const pivot_cache_item_t& item); + }} #endif diff --git a/include/orcus/spreadsheet/types.hpp b/include/orcus/spreadsheet/types.hpp index 3d1fb408..0d1cee86 100644 --- a/include/orcus/spreadsheet/types.hpp +++ b/include/orcus/spreadsheet/types.hpp @@ -783,6 +783,7 @@ ORCUS_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const strikethrough_ ORCUS_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const strikethrough_type_t& st); ORCUS_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const strikethrough_width_t& sw); ORCUS_DLLPUBLIC std::ostream& operator<< (std::ostream& os, const strikethrough_text_t& st); +ORCUS_DLLPUBLIC std::ostream& operator<<(std::ostream& os, pivot_cache_group_by_t v); }} diff --git a/src/enum_stream_test.cpp b/src/enum_stream_test.cpp index 3ff1f576..f1806fbc 100644 --- a/src/enum_stream_test.cpp +++ b/src/enum_stream_test.cpp @@ -712,7 +712,6 @@ void test_orcus_spreadsheet_pane_state_t() void test_orcus_spreadsheet_pivot_cache_group_by_t() { -#if 0 ORCUS_TEST_FUNC_SCOPE; { bool result = verify_stream_value(orcus::spreadsheet::pivot_cache_group_by_t::unknown, "unknown"); assert(result); } @@ -724,7 +723,6 @@ void test_orcus_spreadsheet_pivot_cache_group_by_t() { bool result = verify_stream_value(orcus::spreadsheet::pivot_cache_group_by_t::range, "range"); assert(result); } { bool result = verify_stream_value(orcus::spreadsheet::pivot_cache_group_by_t::seconds, "seconds"); assert(result); } { bool result = verify_stream_value(orcus::spreadsheet::pivot_cache_group_by_t::years, "years"); assert(result); } -#endif } void test_orcus_spreadsheet_sheet_pane_t() diff --git a/src/liborcus/spreadsheet_types.cpp b/src/liborcus/spreadsheet_types.cpp index 55408400..69260c48 100644 --- a/src/liborcus/spreadsheet_types.cpp +++ b/src/liborcus/spreadsheet_types.cpp @@ -802,6 +802,28 @@ std::ostream& operator<< (std::ostream& os, const strikethrough_text_t& st) return write_name_for_pos(os, names, std::size(names), st); } +std::ostream& operator<<(std::ostream& os, pivot_cache_group_by_t v) +{ + constexpr std::string_view values[] = { + "unknown", + "days", + "hours", + "minutes", + "months", + "quarters", + "range", + "seconds", + "years", + }; + + if (auto pos = std::size_t(v); pos < std::size(values)) + os << values[pos]; + else + os << "???"; + + return os; +} + }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/debug_state_dumper_pivot.cpp b/src/spreadsheet/debug_state_dumper_pivot.cpp index 47afebf2..422e6e22 100644 --- a/src/spreadsheet/debug_state_dumper_pivot.cpp +++ b/src/spreadsheet/debug_state_dumper_pivot.cpp @@ -28,6 +28,66 @@ void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const std::ofstream of{outpath.native()}; of << "id: " << m_store.cache_id << std::endl; + of << "fields:" << std::endl; + + for (const auto& field : m_store.fields) + { + of << " - name: " << field.name << std::endl; + + if (!field.items.empty()) + { + of << " items:" << std::endl; + for (const auto& item : field.items) + of << " - " << item << std::endl; + } + + if (field.min_value) + of << " min value: " << *field.min_value << std::endl; + + if (field.max_value) + of << " max value: " << *field.max_value << std::endl; + + if (field.min_date) + of << " min date: " << field.min_date->to_string() << std::endl; + + if (field.max_date) + of << " max date: " << field.max_date->to_string() << std::endl; + + if (field.group_data) + { + const pivot_cache_group_data_t& data = *field.group_data; + of << " group:\n"; + of << " base field index: " << data.base_field << std::endl; + + if (!data.base_to_group_indices.empty()) + { + of << " base item indices:" << std::endl; + for (auto v : data.base_to_group_indices) + of << " - " << v << std::endl; + } + + if (!data.items.empty()) + { + of << " items:" << std::endl; + for (const auto& item : data.items) + of << " - " << item << std::endl; + } + + if (data.range_grouping) + { + const auto& rg = *data.range_grouping; + of << " range grouping:" << "\n"; + of << " group by: " << rg.group_by << "\n"; + of << " auto start: " << std::boolalpha << rg.auto_start << "\n"; + of << " auto end: " << std::boolalpha << rg.auto_end << "\n"; + of << " start: " << rg.start << "\n"; + of << " end: " << rg.end << "\n"; + of << " interval: " << rg.interval << "\n"; + of << " start date: " << rg.start_date.to_string() << "\n"; + of << " end date: " << rg.end_date.to_string() << std::endl; + } + } + } } }}} diff --git a/src/spreadsheet/factory_pivot.cpp b/src/spreadsheet/factory_pivot.cpp index 2761da55..539e00d6 100644 --- a/src/spreadsheet/factory_pivot.cpp +++ b/src/spreadsheet/factory_pivot.cpp @@ -202,6 +202,7 @@ void import_pivot_cache_def::set_field_max_date(const date_time_t& dt) void import_pivot_cache_def::commit_field() { m_current_fields.push_back(std::move(m_current_field)); + m_current_field = pivot_cache_field_t(); } void import_pivot_cache_def::set_field_item_string(std::string_view value) @@ -231,6 +232,7 @@ void import_pivot_cache_def::set_field_item_error(error_value_t ev) void import_pivot_cache_def::commit_field_item() { m_current_field.items.push_back(std::move(m_current_field_item)); + m_current_field_item = pivot_cache_item_t(); } void import_pivot_cache_def::commit() diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp index a829abb6..678421e2 100644 --- a/src/spreadsheet/pivot.cpp +++ b/src/spreadsheet/pivot.cpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace orcus { namespace spreadsheet { @@ -152,6 +153,25 @@ pivot_cache_field_t::pivot_cache_field_t(pivot_cache_field_t&& other) : other.name = std::string_view{}; } +pivot_cache_field_t& pivot_cache_field_t::operator=(pivot_cache_field_t other) +{ + pivot_cache_field_t tmp(std::move(other)); + swap(tmp); + + return *this; +} + +void pivot_cache_field_t::swap(pivot_cache_field_t& other) noexcept +{ + name.swap(other.name); + items.swap(other.items); + min_value.swap(other.min_value); + max_value.swap(other.max_value); + min_date.swap(other.min_date); + max_date.swap(other.max_date); + group_data.swap(other.group_data); +} + pivot_cache::pivot_cache(pivot_cache_id_t cache_id, string_pool& sp) : mp_impl(std::make_unique(cache_id, sp)) {} @@ -304,6 +324,36 @@ void pivot_collection::dump_debug_state(std::string_view outdir) const cache->dump_debug_state(output_dir.string()); } +std::ostream& operator<<(std::ostream& os, const pivot_cache_item_t& item) +{ + switch (item.type) + { + case pivot_cache_item_t::item_type::unknown: + os << "(unknown)"; + break; + case pivot_cache_item_t::item_type::boolean: + os << std::boolalpha << std::get(item.value); + break; + case pivot_cache_item_t::item_type::date_time: + os << std::get(item.value).to_string(); + break; + case pivot_cache_item_t::item_type::character: + os << std::get(item.value); + break; + case pivot_cache_item_t::item_type::numeric: + os << std::get(item.value); + break; + case pivot_cache_item_t::item_type::blank: + os << "(blank)"; + break; + case pivot_cache_item_t::item_type::error: + os << std::get(item.value); + break; + } + + return os; +} + }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- GitLab From e430fc1bd40b2f0772af20ad33477790098650bb Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Wed, 19 Feb 2025 21:21:13 -0500 Subject: [PATCH 5/7] Move the default constructor definitions to source file --- include/orcus/spreadsheet/pivot.hpp | 4 ++-- src/spreadsheet/pivot.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/orcus/spreadsheet/pivot.hpp b/include/orcus/spreadsheet/pivot.hpp index d27c814e..787243b3 100644 --- a/include/orcus/spreadsheet/pivot.hpp +++ b/include/orcus/spreadsheet/pivot.hpp @@ -118,8 +118,8 @@ struct ORCUS_SPM_DLLPUBLIC pivot_cache_group_data_t date_time_t start_date; date_time_t end_date; - range_grouping_type() = default; - range_grouping_type(const range_grouping_type& other) = default; + range_grouping_type(); + range_grouping_type(const range_grouping_type& other); }; /** diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp index 678421e2..331c50fc 100644 --- a/src/spreadsheet/pivot.cpp +++ b/src/spreadsheet/pivot.cpp @@ -113,6 +113,9 @@ void pivot_cache_item_t::swap(pivot_cache_item_t& other) std::swap(value, other.value); } +pivot_cache_group_data_t::range_grouping_type::range_grouping_type() = default; +pivot_cache_group_data_t::range_grouping_type::range_grouping_type(const range_grouping_type& other) = default; + pivot_cache_group_data_t::pivot_cache_group_data_t(size_t _base_field) : base_field(_base_field) {} -- GitLab From a8d8af38fe3e1af0e111e5e5e7d85888c8b34f37 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Wed, 19 Feb 2025 22:05:20 -0500 Subject: [PATCH 6/7] Display base field name as well as items from base field --- src/spreadsheet/debug_state_dumper_pivot.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/spreadsheet/debug_state_dumper_pivot.cpp b/src/spreadsheet/debug_state_dumper_pivot.cpp index 422e6e22..82166d12 100644 --- a/src/spreadsheet/debug_state_dumper_pivot.cpp +++ b/src/spreadsheet/debug_state_dumper_pivot.cpp @@ -57,13 +57,27 @@ void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const { const pivot_cache_group_data_t& data = *field.group_data; of << " group:\n"; - of << " base field index: " << data.base_field << std::endl; + of << " base field:\n"; + of << " index: " << data.base_field << std::endl; + + const pivot_cache_field_t* base_field = nullptr; + + if (data.base_field < m_store.fields.size()) + { + base_field = &m_store.fields[data.base_field]; + of << " name: " << base_field->name << std::endl; + } if (!data.base_to_group_indices.empty()) { - of << " base item indices:" << std::endl; + of << " base item references:" << std::endl; for (auto v : data.base_to_group_indices) - of << " - " << v << std::endl; + { + of << " - index: " << v << std::endl; + + if (base_field && v < base_field->items.size()) + of << " item: " << base_field->items[v] << std::endl; + } } if (!data.items.empty()) -- GitLab From 3e64132c4ff38b194b5e29beea5bbb396f1dfb62 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 20 Feb 2025 21:42:44 -0500 Subject: [PATCH 7/7] Dump pivot cache records --- include/orcus/spreadsheet/pivot.hpp | 3 +- src/spreadsheet/debug_state_dumper_pivot.cpp | 31 ++++++++++++- src/spreadsheet/pivot.cpp | 49 ++++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/include/orcus/spreadsheet/pivot.hpp b/include/orcus/spreadsheet/pivot.hpp index 787243b3..64306f48 100644 --- a/include/orcus/spreadsheet/pivot.hpp +++ b/include/orcus/spreadsheet/pivot.hpp @@ -39,7 +39,7 @@ using pivot_cache_indices_t = std::vector; struct ORCUS_SPM_DLLPUBLIC pivot_cache_record_value_t { - using value_type = std::variant; + using value_type = std::variant; enum class record_type { @@ -261,6 +261,7 @@ public: }; ORCUS_SPM_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const pivot_cache_item_t& item); +ORCUS_SPM_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const pivot_cache_record_value_t& v); }} diff --git a/src/spreadsheet/debug_state_dumper_pivot.cpp b/src/spreadsheet/debug_state_dumper_pivot.cpp index 82166d12..a4f72df4 100644 --- a/src/spreadsheet/debug_state_dumper_pivot.cpp +++ b/src/spreadsheet/debug_state_dumper_pivot.cpp @@ -73,10 +73,12 @@ void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const of << " base item references:" << std::endl; for (auto v : data.base_to_group_indices) { - of << " - index: " << v << std::endl; + of << " - (" << v << ")"; if (base_field && v < base_field->items.size()) - of << " item: " << base_field->items[v] << std::endl; + of << " -> '" << base_field->items[v] << "'"; + + of << std::endl; } } @@ -102,6 +104,31 @@ void debug_state_dumper_pivot_cache::dump(const fs::path& outdir) const } } } + + of << "records:" << std::endl; + + for (const auto& record : m_store.records) + { + for (std::size_t i = 0; i < record.size(); ++i) + { + if (i == 0) + of << " - "; + else + of << " "; + + const auto& v = record[i]; + of << "- " << v; + + if (v.type == pivot_cache_record_value_t::record_type::shared_item_index && i < m_store.fields.size()) + { + auto sii = std::get(v.value); + if (sii < m_store.fields[i].items.size()) + of << " -> '" << m_store.fields[i].items[sii] << "'"; + } + + of << std::endl; + } + } } }}} diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp index 331c50fc..80c23e4b 100644 --- a/src/spreadsheet/pivot.cpp +++ b/src/spreadsheet/pivot.cpp @@ -357,6 +357,55 @@ std::ostream& operator<<(std::ostream& os, const pivot_cache_item_t& item) return os; } +std::ostream& operator<<(std::ostream& os, const pivot_cache_record_value_t& v) +{ + + switch (v.type) + { + case pivot_cache_record_value_t::record_type::unknown: + { + os << "(unknown)"; + break; + } + case pivot_cache_record_value_t::record_type::boolean: + { + os << std::boolalpha << std::get(v.value); + break; + } + case pivot_cache_record_value_t::record_type::date_time: + { + os << std::get(v.value).to_string(); + break; + } + case pivot_cache_record_value_t::record_type::character: + { + os << std::get(v.value); + break; + } + case pivot_cache_record_value_t::record_type::numeric: + { + os << std::get(v.value); + break; + } + case pivot_cache_record_value_t::record_type::blank: + { + os << "(blank)"; + break; + } + case pivot_cache_record_value_t::record_type::error: + { + os << std::get(v.value); + break; + } + case pivot_cache_record_value_t::record_type::shared_item_index: + { + os << '(' << std::get(v.value) << ')'; + break; + } + } + return os; +} + }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- GitLab