1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2017, 2018 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "output/spv/spv-light-decoder.h"
26 #include "libpspp/i18n.h"
27 #include "libpspp/message.h"
28 #include "output/pivot-table.h"
29 #include "output/spv/light-binary-parser.h"
30 #include "output/spv/spv.h"
32 #include "gl/xalloc.h"
36 to_utf8 (const char *s, const char *encoding)
38 return recode_string ("UTF-8", encoding, s, strlen (s));
42 to_utf8_if_nonempty (const char *s, const char *encoding)
44 return s && s[0] ? to_utf8 (s, encoding) : NULL;
48 convert_widths (const uint32_t *in, uint32_t n, int **out, size_t *n_out)
53 *out = xnmalloc (n, sizeof **out);
54 for (size_t i = 0; i < n; i++)
60 convert_breakpoints (const struct spvlb_breakpoints *in,
61 size_t **out, size_t *n_out)
63 if (in && in->n_breaks)
65 *n_out = in->n_breaks;
66 *out = xnmalloc (in->n_breaks, sizeof *out);
67 for (size_t i = 0; i < in->n_breaks; i++)
68 (*out)[i] = in->breaks[i];
73 convert_keeps (const struct spvlb_keeps *in,
74 struct pivot_keep **out, size_t *n_out)
76 if (in && in->n_keeps)
79 *out = xnmalloc (*n_out, sizeof **out);
80 for (size_t i = 0; i < *n_out; i++)
82 (*out)[i].ofs = in->keeps[i]->offset;
83 (*out)[i].n = in->keeps[i]->n;
88 static char * WARN_UNUSED_RESULT
89 decode_spvlb_color_string (const char *s, uint8_t def,
90 struct cell_color *colorp)
95 else if (sscanf (s, "#%2x%2x%2x", &r, &g, &b) != 3)
96 return xasprintf ("bad color %s", s);
98 *colorp = (struct cell_color) CELL_COLOR (r, g, b);
102 static struct cell_color
103 decode_spvlb_color_u32 (uint32_t x)
105 return (struct cell_color) { x >> 24, x >> 16, x >> 8, x };
108 static char * WARN_UNUSED_RESULT
109 decode_spvlb_font_style (const struct spvlb_font_style *in,
110 const char *encoding, struct font_style **outp)
118 struct cell_color fg, bg;
119 char *error = decode_spvlb_color_string (in->fg_color, 0x00, &fg);
121 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg);
125 *outp = xmalloc (sizeof **outp);
126 **outp = (struct font_style) {
128 .italic = in->italic,
129 .underline = in->underline,
132 .typeface = to_utf8 (in->typeface, encoding),
133 .size = in->size / 1.33,
138 static char * WARN_UNUSED_RESULT
139 decode_spvlb_halign (uint32_t in, enum table_halign *halignp)
144 *halignp = TABLE_HALIGN_CENTER;
148 *halignp = TABLE_HALIGN_LEFT;
152 *halignp = TABLE_HALIGN_RIGHT;
157 *halignp = TABLE_HALIGN_DECIMAL;
162 *halignp = TABLE_HALIGN_MIXED;
166 return xasprintf ("bad cell style halign %"PRIu32, in);
170 static char * WARN_UNUSED_RESULT
171 decode_spvlb_valign (uint32_t in, enum table_valign *valignp)
176 *valignp = TABLE_VALIGN_CENTER;
180 *valignp = TABLE_VALIGN_TOP;
184 *valignp = TABLE_VALIGN_BOTTOM;
189 return xasprintf ("bad cell style valign %"PRIu32, in);
193 static char * WARN_UNUSED_RESULT
194 decode_spvlb_cell_style (const struct spvlb_cell_style *in,
195 struct cell_style **outp)
203 enum table_halign halign;
204 char *error = decode_spvlb_halign (in->halign, &halign);
208 enum table_valign valign;
209 error = decode_spvlb_valign (in->valign, &valign);
213 *outp = xzalloc (sizeof **outp);
214 **outp = (struct cell_style) {
217 .decimal_offset = in->decimal_offset,
219 [TABLE_HORZ] = { in->left_margin, in->right_margin },
220 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
226 static char *decode_spvlb_value (
227 const struct pivot_table *, const struct spvlb_value *,
228 const char *encoding, struct pivot_value **) WARN_UNUSED_RESULT;
230 static char * WARN_UNUSED_RESULT
231 decode_spvlb_argument (const struct pivot_table *table,
232 const struct spvlb_argument *in,
233 const char *encoding, struct pivot_argument *out)
237 struct pivot_value *value;
238 char *error = decode_spvlb_value (table, in->value, encoding, &value);
243 out->values = xmalloc (sizeof *out->values);
244 out->values[0] = value;
249 out->values = xnmalloc (in->n_values, sizeof *out->values);
250 for (size_t i = 0; i < in->n_values; i++)
252 char *error = decode_spvlb_value (table, in->values[i], encoding,
256 pivot_argument_uninit (out);
266 static char * WARN_UNUSED_RESULT
267 decode_spvlb_value_show (uint8_t in, enum settings_value_show *out)
271 case 0: *out = SETTINGS_VALUE_SHOW_DEFAULT; return NULL;
272 case 1: *out = SETTINGS_VALUE_SHOW_VALUE; return NULL;
273 case 2: *out = SETTINGS_VALUE_SHOW_LABEL; return NULL;
274 case 3: *out = SETTINGS_VALUE_SHOW_BOTH; return NULL;
276 return xasprintf ("bad value show %"PRIu8, in);
280 static char * WARN_UNUSED_RESULT
281 decode_spvlb_value (const struct pivot_table *table,
282 const struct spvlb_value *in,
283 const char *encoding, struct pivot_value **outp)
287 struct pivot_value *out = xzalloc (sizeof *out);
288 const struct spvlb_value_mod *vm;
294 vm = in->type_01.value_mod;
295 out->type = PIVOT_VALUE_NUMERIC;
296 out->numeric.x = in->type_01.x;
297 error = spv_decode_fmt_spec (in->type_01.format, &out->numeric.format);
303 vm = in->type_02.value_mod;
304 out->type = PIVOT_VALUE_NUMERIC;
305 out->numeric.x = in->type_02.x;
306 error = spv_decode_fmt_spec (in->type_02.format, &out->numeric.format);
308 error = decode_spvlb_value_show (in->type_02.show, &out->numeric.show);
311 out->numeric.var_name = to_utf8_if_nonempty (in->type_02.var_name,
313 out->numeric.value_label = to_utf8_if_nonempty (in->type_02.value_label,
318 vm = in->type_03.value_mod;
319 out->type = PIVOT_VALUE_TEXT;
320 out->text.local = to_utf8 (in->type_03.local, encoding);
321 out->text.c = to_utf8 (in->type_03.c, encoding);
322 out->text.id = to_utf8 (in->type_03.id, encoding);
323 out->text.user_provided = !in->type_03.fixed;
327 vm = in->type_04.value_mod;
328 out->type = PIVOT_VALUE_STRING;
329 error = decode_spvlb_value_show (in->type_04.show, &out->string.show);
332 out->string.s = to_utf8 (in->type_04.s, encoding);
333 out->string.var_name = to_utf8 (in->type_04.var_name, encoding);
334 out->string.value_label = to_utf8_if_nonempty (in->type_04.value_label,
339 vm = in->type_05.value_mod;
340 out->type = PIVOT_VALUE_VARIABLE;
341 error = decode_spvlb_value_show (in->type_05.show, &out->variable.show);
344 out->variable.var_name = to_utf8 (in->type_05.var_name, encoding);
345 out->variable.var_label = to_utf8_if_nonempty (in->type_05.var_label,
350 vm = in->type_06.value_mod;
351 out->type = PIVOT_VALUE_TEXT;
352 out->text.local = to_utf8 (in->type_06.local, encoding);
353 out->text.c = to_utf8 (in->type_06.c, encoding);
354 out->text.id = to_utf8 (in->type_06.id, encoding);
355 out->text.user_provided = false;
359 vm = in->type_else.value_mod;
360 out->type = PIVOT_VALUE_TEMPLATE;
361 out->template.local = to_utf8 (in->type_else.template, encoding);
362 out->template.id = out->template.local;
363 out->template.n_args = 0;
364 out->template.args = xnmalloc (in->type_else.n_args,
365 sizeof *out->template.args);
366 for (size_t i = 0; i < in->type_else.n_args; i++)
368 error = decode_spvlb_argument (table, in->type_else.args[i],
369 encoding, &out->template.args[i]);
372 pivot_value_destroy (out);
375 out->template.n_args++;
385 if (vm->n_subscripts)
387 out->n_subscripts = vm->n_subscripts;
388 out->subscripts = xnmalloc (vm->n_subscripts,
389 sizeof *out->subscripts);
390 for (size_t i = 0; i < vm->n_subscripts; i++)
391 out->subscripts[i] = to_utf8 (vm->subscripts[i], encoding);
396 out->footnotes = xnmalloc (vm->n_refs, sizeof *out->footnotes);
397 for (size_t i = 0; i < vm->n_refs; i++)
399 uint16_t idx = vm->refs[i];
400 if (idx >= table->n_footnotes)
402 pivot_value_destroy (out);
403 return xasprintf ("bad footnote index: %"PRIu16" >= %zu",
404 idx, table->n_footnotes);
407 out->footnotes[out->n_footnotes++] = table->footnotes[idx];
413 error = decode_spvlb_font_style (vm->style_pair->font_style,
414 encoding, &out->font_style);
416 error = decode_spvlb_cell_style (vm->style_pair->cell_style,
420 pivot_value_destroy (out);
425 if (vm->template_string
426 && vm->template_string->id
427 && vm->template_string->id[0]
428 && out->type == PIVOT_VALUE_TEMPLATE)
429 out->template.id = to_utf8 (vm->template_string->id, encoding);
436 static char * WARN_UNUSED_RESULT
437 decode_spvlb_area (const struct spvlb_area *in, struct table_area_style *out,
438 const char *encoding)
442 struct cell_color fg0, fg1, bg0, bg1;
443 error = decode_spvlb_color_string (in->fg_color, 0x00, &fg0);
445 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg0);
446 if (!error && in->alternate)
447 error = decode_spvlb_color_string (in->alt_fg_color, 0x00, &fg1);
448 if (!error && in->alternate)
449 error = decode_spvlb_color_string (in->alt_bg_color, 0xff, &bg1);
451 enum table_halign halign;
454 error = decode_spvlb_halign (in->halign, &halign);
456 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which
457 is good because there's no way to indicate the decimal offset. Just
459 if (!error && halign == TABLE_HALIGN_DECIMAL)
460 halign = TABLE_HALIGN_MIXED;
463 enum table_valign valign;
465 error = decode_spvlb_valign (in->valign, &valign);
470 table_area_style_uninit (out);
471 *out = (struct table_area_style) {
473 .bold = (in->style & 1) != 0,
474 .italic = (in->style & 2) != 0,
475 .underline = in->underline,
476 .fg = { fg0, in->alternate ? fg1 : fg0 },
477 .bg = { bg0, in->alternate ? bg1 : bg0 },
478 .typeface = to_utf8 (in->typeface, encoding),
479 .size = in->size / 1.33,
485 [TABLE_HORZ] = { in->left_margin, in->right_margin },
486 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
493 static char * WARN_UNUSED_RESULT
494 decode_spvlb_group (const struct pivot_table *,
495 struct spvlb_category **,
498 struct pivot_category *parent,
499 struct pivot_dimension *,
500 const char *encoding);
502 static char * WARN_UNUSED_RESULT
503 decode_spvlb_categories (const struct pivot_table *table,
504 struct spvlb_category **categories,
506 struct pivot_category *parent,
507 struct pivot_dimension *dimension,
508 const char *encoding)
510 for (size_t i = 0; i < n_categories; i++)
512 const struct spvlb_category *in = categories[i];
513 if (in->group && in->group->merge)
515 char *error = decode_spvlb_categories (
516 table, in->group->subcategories, in->group->n_subcategories,
517 parent, dimension, encoding);
524 struct pivot_value *name;
525 char *error = decode_spvlb_value (table, in->name, encoding, &name);
529 struct pivot_category *out = xzalloc (sizeof *out);
531 out->parent = parent;
532 out->dimension = dimension;
535 char *error = decode_spvlb_group (table, in->group->subcategories,
536 in->group->n_subcategories,
537 true, out, dimension, encoding);
540 pivot_category_destroy (out);
544 out->data_index = SIZE_MAX;
545 out->presentation_index = SIZE_MAX;
549 out->data_index = in->leaf->leaf_index;
550 out->presentation_index = dimension->n_leaves;
551 dimension->n_leaves++;
554 if (parent->n_subs >= parent->allocated_subs)
555 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
556 sizeof *parent->subs);
557 parent->subs[parent->n_subs++] = out;
562 static char * WARN_UNUSED_RESULT
563 decode_spvlb_group (const struct pivot_table *table,
564 struct spvlb_category **categories,
565 size_t n_categories, bool show_label,
566 struct pivot_category *category,
567 struct pivot_dimension *dimension,
568 const char *encoding)
570 category->subs = XCALLOC (n_categories, struct pivot_category *);
571 category->n_subs = 0;
572 category->allocated_subs = 0;
573 category->show_label = show_label;
575 return decode_spvlb_categories (table, categories, n_categories, category,
576 dimension, encoding);
579 static char * WARN_UNUSED_RESULT
580 fill_leaves (struct pivot_category *category,
581 struct pivot_dimension *dimension)
583 if (pivot_category_is_group (category))
585 for (size_t i = 0; i < category->n_subs; i++)
587 char *error = fill_leaves (category->subs[i], dimension);
594 if (category->data_index >= dimension->n_leaves)
595 return xasprintf ("leaf_index %zu >= n_leaves %zu",
596 category->data_index, dimension->n_leaves);
597 if (dimension->data_leaves[category->data_index])
598 return xasprintf ("two leaves with data_index %zu",
599 category->data_index);
600 dimension->data_leaves[category->data_index] = category;
601 dimension->presentation_leaves[category->presentation_index] = category;
606 static char * WARN_UNUSED_RESULT
607 decode_spvlb_dimension (const struct pivot_table *table,
608 const struct spvlb_dimension *in,
609 size_t idx, const char *encoding,
610 struct pivot_dimension **outp)
612 /* Convert most of the dimension. */
613 struct pivot_value *name;
614 char *error = decode_spvlb_value (table, in->name, encoding, &name);
618 struct pivot_dimension *out = xzalloc (sizeof *out);
619 out->level = UINT_MAX;
620 out->top_index = idx;
621 out->hide_all_labels = in->props->hide_all_labels;
623 out->root = xzalloc (sizeof *out->root);
624 *out->root = (struct pivot_category) {
627 .data_index = SIZE_MAX,
628 .presentation_index = SIZE_MAX,
630 error = decode_spvlb_group (table, in->categories, in->n_categories,
631 !in->props->hide_dim_label, out->root,
636 /* Allocate and fill the array of leaves now that we know how many there
638 out->data_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
639 out->presentation_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
640 out->allocated_leaves = out->n_leaves;
641 error = fill_leaves (out->root, out);
644 for (size_t i = 0; i < out->n_leaves; i++)
646 assert (out->data_leaves[i] != NULL);
647 assert (out->presentation_leaves[i] != NULL);
653 pivot_dimension_destroy (out);
657 static char * WARN_UNUSED_RESULT
658 decode_spvlb_stroke (uint32_t stroke_type, enum table_stroke *strokep)
660 enum table_stroke strokes[] = {
669 if (stroke_type >= sizeof strokes / sizeof *strokes)
670 return xasprintf ("bad stroke %"PRIu32, stroke_type);
672 *strokep = strokes[stroke_type];
676 static char * WARN_UNUSED_RESULT
677 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
680 if (in->border_type >= PIVOT_N_BORDERS)
681 return xasprintf ("bad border type %"PRIu32, in->border_type);
683 struct table_border_style *out = &table->look->borders[in->border_type];
684 out->color = decode_spvlb_color_u32 (in->color);
685 return decode_spvlb_stroke (in->stroke_type, &out->stroke);
688 static char * WARN_UNUSED_RESULT
689 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
690 enum pivot_axis_type axis_type, struct pivot_table *table)
692 struct pivot_axis *axis = &table->axes[axis_type];
693 axis->dimensions = XCALLOC (n_dimensions, struct pivot_dimension *);
694 axis->n_dimensions = n_dimensions;
696 for (size_t i = 0; i < n_dimensions; i++)
698 uint32_t idx = dimension_indexes[i];
699 if (idx >= table->n_dimensions)
700 return xasprintf ("bad dimension index %"PRIu32" >= %zu",
701 idx, table->n_dimensions);
703 struct pivot_dimension *d = table->dimensions[idx];
704 if (d->level != UINT_MAX)
705 return xasprintf ("duplicate dimension %"PRIu32, idx);
707 axis->dimensions[i] = d;
708 d->axis_type = axis_type;
711 axis->extent *= d->n_leaves;
718 decode_data_index (uint64_t in, const struct pivot_table *table,
721 uint64_t remainder = in;
722 for (size_t i = table->n_dimensions - 1; i > 0; i--)
724 const struct pivot_dimension *d = table->dimensions[i];
727 out[i] = remainder % d->n_leaves;
728 remainder /= d->n_leaves;
733 if (remainder >= table->dimensions[0]->n_leaves)
734 return xasprintf ("out of range cell data index %"PRIu64, in);
740 static char * WARN_UNUSED_RESULT
741 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
742 struct pivot_table *table, const char *encoding)
744 if (!table->n_dimensions)
747 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
748 for (size_t i = 0; i < n_in; i++)
750 struct pivot_value *value;
751 char *error = decode_data_index (in[i]->index, table, dindexes);
753 error = decode_spvlb_value (table, in[i]->value, encoding, &value);
759 pivot_table_put (table, dindexes, table->n_dimensions, value);
766 static char * WARN_UNUSED_RESULT
767 decode_spvlb_footnote (const struct spvlb_footnote *in, const char *encoding,
768 size_t idx, struct pivot_table *table)
770 struct pivot_value *content;
771 char *error = decode_spvlb_value (table, in->text, encoding, &content);
775 struct pivot_value *marker = NULL;
778 error = decode_spvlb_value (table, in->marker, encoding, &marker);
781 pivot_value_destroy (content);
784 if (marker->type == PIVOT_VALUE_TEXT)
785 marker->text.user_provided = false;
788 struct pivot_footnote *f = pivot_table_create_footnote__ (
789 table, idx, marker, content);
790 f->show = (int32_t) in->show > 0;
794 static char * WARN_UNUSED_RESULT
795 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
797 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
798 table->current_layer = xnmalloc (axis->n_dimensions,
799 sizeof *table->current_layer);
801 for (size_t i = 0; i < axis->n_dimensions; i++)
803 const struct pivot_dimension *d = axis->dimensions[i];
806 table->current_layer[i] = current_layer % d->n_leaves;
807 current_layer /= d->n_leaves;
810 table->current_layer[i] = 0;
812 if (current_layer > 0)
813 return xasprintf ("out of range layer data index %"PRIu64, current_layer);
817 char * WARN_UNUSED_RESULT
818 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
821 if (in->header->version != 1 && in->header->version != 3)
822 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
823 in->header->version);
826 struct pivot_table *out = xzalloc (sizeof *out);
828 hmap_init (&out->cells);
829 out->look = pivot_table_look_new_builtin_default ();
831 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
832 : in->formats->x3 ? in->formats->x3->y1
834 const char *encoding;
836 encoding = y1->charset;
839 const char *dot = strchr (in->formats->locale, '.');
840 encoding = dot ? dot + 1 : "windows-1252";
843 /* Display settings. */
844 out->look->show_numeric_markers = !in->ts->show_alphabetic_markers;
845 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
846 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
847 out->look->row_labels_in_corner = in->ts->show_row_labels_in_corner;
848 out->show_grid_lines = in->borders->show_grid_lines;
849 out->show_title = true;
850 out->show_caption = true;
851 out->look->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
852 out->look->omit_empty = in->ts->omit_empty;
854 const struct spvlb_x1 *x1 = in->formats->x1;
857 error = decode_spvlb_value_show (x1->show_values, &out->show_values);
859 error = decode_spvlb_value_show (x1->show_variables,
860 &out->show_variables);
864 out->show_caption = x1->show_caption;
865 out->show_title = x1->show_title != 10;
868 /* Column and row display settings. */
869 out->look->width_ranges[TABLE_VERT][0] = in->header->min_row_height;
870 out->look->width_ranges[TABLE_VERT][1] = in->header->max_row_height;
871 out->look->width_ranges[TABLE_HORZ][0] = in->header->min_col_width;
872 out->look->width_ranges[TABLE_HORZ][1] = in->header->max_col_width;
874 convert_widths (in->formats->widths, in->formats->n_widths,
875 &out->sizing[TABLE_HORZ].widths,
876 &out->sizing[TABLE_HORZ].n_widths);
878 const struct spvlb_x2 *x2 = in->formats->x2;
880 convert_widths (x2->row_heights, x2->n_row_heights,
881 &out->sizing[TABLE_VERT].widths,
882 &out->sizing[TABLE_VERT].n_widths);
884 convert_breakpoints (in->ts->row_breaks,
885 &out->sizing[TABLE_VERT].breaks,
886 &out->sizing[TABLE_VERT].n_breaks);
887 convert_breakpoints (in->ts->col_breaks,
888 &out->sizing[TABLE_HORZ].breaks,
889 &out->sizing[TABLE_HORZ].n_breaks);
891 convert_keeps (in->ts->row_keeps,
892 &out->sizing[TABLE_VERT].keeps,
893 &out->sizing[TABLE_VERT].n_keeps);
894 convert_keeps (in->ts->col_keeps,
895 &out->sizing[TABLE_HORZ].keeps,
896 &out->sizing[TABLE_HORZ].n_keeps);
898 out->notes = to_utf8_if_nonempty (in->ts->notes, encoding);
899 out->look->name = to_utf8_if_nonempty (in->ts->table_look, encoding);
901 /* Print settings. */
902 out->look->print_all_layers = in->ps->all_layers;
903 out->look->paginate_layers = in->ps->paginate_layers;
904 out->look->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
905 out->look->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
906 out->look->top_continuation = in->ps->top_continuation;
907 out->look->bottom_continuation = in->ps->bottom_continuation;
908 out->look->continuation = xstrdup (in->ps->continuation_string);
909 out->look->n_orphan_lines = in->ps->n_orphan_lines;
911 /* Format settings. */
912 out->epoch = in->formats->y0->epoch;
913 out->decimal = in->formats->y0->decimal;
914 out->grouping = in->formats->y0->grouping;
915 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
916 for (int i = 0; i < 5; i++)
917 if (cc && i < cc->n_ccs)
918 out->ccs[i] = xstrdup (cc->ccs[i]);
919 out->small = in->formats->x3 ? in->formats->x3->small : 0;
921 /* Command information. */
924 out->command_local = to_utf8 (y1->command_local, encoding);
925 out->command_c = to_utf8 (y1->command, encoding);
926 out->language = xstrdup (y1->language);
928 out->locale = xstrdup (y1->locale);
931 /* Source information. */
932 const struct spvlb_x3 *x3 = in->formats->x3;
935 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
936 out->dataset = to_utf8 (x3->dataset, encoding);
937 out->datafile = to_utf8_if_nonempty (x3->datafile, encoding);
938 out->date = x3->date;
943 Any pivot_value might refer to footnotes, so it's important to process the
944 footnotes early to ensure that those references can be resolved. There is
945 a possible problem that a footnote might itself reference an
946 as-yet-unprocessed footnote, but that's OK because footnote references
947 don't actually look at the footnote contents but only resolve a pointer to
948 where the footnote will go later.
950 Before we really start, create all the footnotes we'll fill in. This is
951 because sometimes footnotes refer to themselves or to each other and we
952 don't want to reject those references. */
953 const struct spvlb_footnotes *fn = in->footnotes;
954 if (fn->n_footnotes > 0)
956 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
957 for (size_t i = 0; i < fn->n_footnotes; i++)
959 error = decode_spvlb_footnote (in->footnotes->footnotes[i],
966 /* Title and caption. */
967 error = decode_spvlb_value (out, in->titles->user_title, encoding,
972 error = decode_spvlb_value (out, in->titles->subtype, encoding,
977 if (in->titles->corner_text)
979 error = decode_spvlb_value (out, in->titles->corner_text,
980 encoding, &out->corner_text);
985 if (in->titles->caption)
987 error = decode_spvlb_value (out, in->titles->caption, encoding,
995 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
997 error = decode_spvlb_area (in->areas->areas[i], &out->look->areas[i],
1002 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
1004 error = decode_spvlb_border (in->borders->borders[i], out);
1010 out->n_dimensions = in->dimensions->n_dims;
1011 out->dimensions = XCALLOC (out->n_dimensions, struct pivot_dimension *);
1012 for (size_t i = 0; i < out->n_dimensions; i++)
1014 error = decode_spvlb_dimension (out, in->dimensions->dims[i],
1015 i, encoding, &out->dimensions[i]);
1021 size_t a = in->axes->n_layers;
1022 size_t b = in->axes->n_rows;
1023 size_t c = in->axes->n_columns;
1024 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
1026 error = xasprintf ("dimensions do not sum correctly "
1027 "(%zu + %zu + %zu != %zu)",
1028 a, b, c, out->n_dimensions);
1031 error = decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
1032 PIVOT_AXIS_LAYER, out);
1035 error = decode_spvlb_axis (in->axes->rows, in->axes->n_rows,
1036 PIVOT_AXIS_ROW, out);
1039 error = decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
1040 PIVOT_AXIS_COLUMN, out);
1044 pivot_table_assign_label_depth (out);
1046 error = decode_current_layer (in->ts->current_layer, out);
1051 error = decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out,
1058 pivot_table_unref (out);