1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 */ 7 8 #ifndef INCLUDED_ORCUS_SPREADSHEET_PIVOT_HPP 9 #define INCLUDED_ORCUS_SPREADSHEET_PIVOT_HPP 10 11 #include "orcus/env.hpp" 12 #include "orcus/pstring.hpp" 13 #include "orcus/types.hpp" 14 #include "orcus/spreadsheet/types.hpp" 15 16 #include <memory> 17 #include <vector> 18 #include <limits> 19 20 #include <boost/optional.hpp> 21 22 namespace ixion { 23 24 struct abs_range_t; 25 26 } 27 28 namespace orcus { 29 30 class string_pool; 31 32 namespace spreadsheet { 33 34 class document; 35 36 using pivot_cache_indices_t = std::vector<size_t>; 37 38 struct ORCUS_SPM_DLLPUBLIC pivot_cache_record_value_t 39 { 40 enum class value_type 41 { 42 unknown = 0, 43 boolean, 44 date_time, 45 character, 46 numeric, 47 blank, 48 error, 49 shared_item_index 50 }; 51 52 value_type type; 53 54 union 55 { 56 bool boolean; 57 58 struct 59 { 60 // This must point to an interned string instance. May not be 61 // null-terminated. 62 const char* p; 63 64 size_t n; // Length of the string value. 65 66 } character; 67 68 struct 69 { 70 int year; 71 int month; 72 int day; 73 int hour; 74 int minute; 75 double second; 76 77 } date_time; 78 79 double numeric; 80 81 size_t shared_item_index; 82 83 // TODO : add error value. 84 85 } value; 86 87 pivot_cache_record_value_t(); 88 pivot_cache_record_value_t(const char* cp, size_t cn); 89 pivot_cache_record_value_t(double v); 90 pivot_cache_record_value_t(size_t index); 91 92 bool operator== (const pivot_cache_record_value_t& other) const; 93 bool operator!= (const pivot_cache_record_value_t& other) const; 94 }; 95 96 using pivot_cache_record_t = std::vector<pivot_cache_record_value_t>; 97 98 struct ORCUS_SPM_DLLPUBLIC pivot_cache_item_t 99 { 100 enum class item_type 101 { 102 unknown = 0, boolean, date_time, character, numeric, blank, error 103 }; 104 105 item_type type; 106 107 union 108 { 109 struct 110 { 111 // This must point to an interned string instance. May not be 112 // null-terminated. 113 const char* p; 114 115 size_t n; // Length of the string value. 116 117 } character; 118 119 struct 120 { 121 int year; 122 int month; 123 int day; 124 int hour; 125 int minute; 126 double second; 127 128 } date_time; 129 130 double numeric; 131 132 error_value_t error; 133 134 bool boolean; 135 136 } value; 137 138 pivot_cache_item_t(); 139 pivot_cache_item_t(const char* cp, size_t cn); 140 pivot_cache_item_t(double numeric); 141 pivot_cache_item_t(bool boolean); 142 pivot_cache_item_t(const date_time_t& date_time); 143 pivot_cache_item_t(error_value_t error); 144 145 pivot_cache_item_t(const pivot_cache_item_t& other); 146 pivot_cache_item_t(pivot_cache_item_t&& other); 147 148 bool operator< (const pivot_cache_item_t& other) const; 149 bool operator== (const pivot_cache_item_t& other) const; 150 151 pivot_cache_item_t& operator= (pivot_cache_item_t other); 152 153 void swap(pivot_cache_item_t& other); 154 }; 155 156 using pivot_cache_items_t = std::vector<pivot_cache_item_t>; 157 158 /** 159 * Group data for a pivot cache field. 160 */ 161 struct ORCUS_SPM_DLLPUBLIC pivot_cache_group_data_t 162 { 163 struct ORCUS_SPM_DLLPUBLIC range_grouping_type 164 { 165 pivot_cache_group_by_t group_by = pivot_cache_group_by_t::range; 166 167 bool auto_start = true; 168 bool auto_end = true; 169 170 double start = 0.0; 171 double end = 0.0; 172 double interval = 1.0; 173 174 date_time_t start_date; 175 date_time_t end_date; 176 177 range_grouping_type() = default; 178 range_grouping_type(const range_grouping_type& other) = default; 179 }; 180 181 /** 182 * Mapping of base field member indices to the group field item indices. 183 */ 184 pivot_cache_indices_t base_to_group_indices; 185 186 boost::optional<range_grouping_type> range_grouping; 187 188 /** 189 * Individual items comprising the group. 190 */ 191 pivot_cache_items_t items; 192 193 /** 0-based index of the base field. */ 194 size_t base_field; 195 196 pivot_cache_group_data_t(size_t _base_field); 197 pivot_cache_group_data_t(const pivot_cache_group_data_t& other); 198 pivot_cache_group_data_t(pivot_cache_group_data_t&& other); 199 200 pivot_cache_group_data_t() = delete; 201 }; 202 203 struct ORCUS_SPM_DLLPUBLIC pivot_cache_field_t 204 { 205 /** 206 * Field name. It must be interned with the string pool belonging to the 207 * document. 208 */ 209 pstring name; 210 211 pivot_cache_items_t items; 212 213 boost::optional<double> min_value; 214 boost::optional<double> max_value; 215 216 boost::optional<date_time_t> min_date; 217 boost::optional<date_time_t> max_date; 218 219 std::unique_ptr<pivot_cache_group_data_t> group_data; 220 221 pivot_cache_field_t(); 222 pivot_cache_field_t(const pstring& _name); 223 pivot_cache_field_t(const pivot_cache_field_t& other); 224 pivot_cache_field_t(pivot_cache_field_t&& other); 225 }; 226 227 class ORCUS_SPM_DLLPUBLIC pivot_cache 228 { 229 struct impl; 230 std::unique_ptr<impl> mp_impl; 231 232 public: 233 using fields_type = std::vector<pivot_cache_field_t>; 234 using records_type = std::vector<pivot_cache_record_t>; 235 236 pivot_cache(pivot_cache_id_t cache_id, string_pool& sp); 237 ~pivot_cache(); 238 239 /** 240 * Bulk-insert all the fields in one step. Note that this will replace any 241 * pre-existing fields if any. 242 * 243 * @param fields field instances to move into storage. 244 */ 245 void insert_fields(fields_type fields); 246 247 void insert_records(records_type record); 248 249 size_t get_field_count() const; 250 251 /** 252 * Retrieve a field data by its index. 253 * 254 * @param index index of the field to retrieve. 255 * 256 * @return pointer to the field instance, or nullptr if the index is 257 * out-of-range. 258 */ 259 const pivot_cache_field_t* get_field(size_t index) const; 260 261 pivot_cache_id_t get_id() const; 262 263 const records_type& get_all_records() const; 264 }; 265 266 class ORCUS_SPM_DLLPUBLIC pivot_collection 267 { 268 struct impl; 269 std::unique_ptr<impl> mp_impl; 270 271 public: 272 pivot_collection(document& doc); 273 ~pivot_collection(); 274 275 /** 276 * Insert a new pivot cache associated with a worksheet source. 277 * 278 * @param sheet_name name of the sheet where the source data is. 279 * @param range range of the source data. Note that the sheet indices are 280 * not used. 281 * @param cache pivot cache instance to store. 282 */ 283 void insert_worksheet_cache( 284 const pstring& sheet_name, const ixion::abs_range_t& range, std::unique_ptr<pivot_cache>&& cache); 285 286 /** 287 * Insert a new pivot cache associated with a table name. 288 * 289 * @param table_name source table name. 290 * @param cache pivot cache instance to store. 291 */ 292 void insert_worksheet_cache(const pstring& table_name, std::unique_ptr<pivot_cache>&& cache); 293 294 /** 295 * Count the number of pivot caches currently stored. 296 * 297 * @return number of pivot caches currently stored in the document. 298 */ 299 size_t get_cache_count() const; 300 301 const pivot_cache* get_cache( 302 const pstring& sheet_name, const ixion::abs_range_t& range) const; 303 304 pivot_cache* get_cache(pivot_cache_id_t cache_id); 305 306 const pivot_cache* get_cache(pivot_cache_id_t cache_id) const; 307 }; 308 309 }} 310 311 #endif 312 313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 314