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;
188 return xasprintf ("bad cell style valign %"PRIu32, in);
192 static char * WARN_UNUSED_RESULT
193 decode_spvlb_cell_style (const struct spvlb_cell_style *in,
194 struct cell_style **outp)
202 enum table_halign halign;
203 char *error = decode_spvlb_halign (in->halign, &halign);
207 enum table_valign valign;
208 error = decode_spvlb_valign (in->valign, &valign);
212 *outp = xzalloc (sizeof **outp);
213 **outp = (struct cell_style) {
216 .decimal_offset = in->decimal_offset,
218 [TABLE_HORZ] = { in->left_margin, in->right_margin },
219 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
225 static char *decode_spvlb_value (
226 const struct pivot_table *, const struct spvlb_value *,
227 const char *encoding, struct pivot_value **) WARN_UNUSED_RESULT;
229 static char * WARN_UNUSED_RESULT
230 decode_spvlb_argument (const struct pivot_table *table,
231 const struct spvlb_argument *in,
232 const char *encoding, struct pivot_argument *out)
236 struct pivot_value *value;
237 char *error = decode_spvlb_value (table, in->value, encoding, &value);
242 out->values = xmalloc (sizeof *out->values);
243 out->values[0] = value;
248 out->values = xnmalloc (in->n_values, sizeof *out->values);
249 for (size_t i = 0; i < in->n_values; i++)
251 char *error = decode_spvlb_value (table, in->values[i], encoding,
255 pivot_argument_uninit (out);
265 static char * WARN_UNUSED_RESULT
266 decode_spvlb_value_show (uint8_t in, enum settings_value_show *out)
270 case 0: *out = SETTINGS_VALUE_SHOW_DEFAULT; return NULL;
271 case 1: *out = SETTINGS_VALUE_SHOW_VALUE; return NULL;
272 case 2: *out = SETTINGS_VALUE_SHOW_LABEL; return NULL;
273 case 3: *out = SETTINGS_VALUE_SHOW_BOTH; return NULL;
275 return xasprintf ("bad value show %"PRIu8, in);
279 static char * WARN_UNUSED_RESULT
280 decode_spvlb_value (const struct pivot_table *table,
281 const struct spvlb_value *in,
282 const char *encoding, struct pivot_value **outp)
286 struct pivot_value *out = xzalloc (sizeof *out);
287 const struct spvlb_value_mod *vm;
293 vm = in->type_01.value_mod;
294 out->type = PIVOT_VALUE_NUMERIC;
295 out->numeric.x = in->type_01.x;
296 error = spv_decode_fmt_spec (in->type_01.format, &out->numeric.format);
302 vm = in->type_02.value_mod;
303 out->type = PIVOT_VALUE_NUMERIC;
304 out->numeric.x = in->type_02.x;
305 error = spv_decode_fmt_spec (in->type_02.format, &out->numeric.format);
307 error = decode_spvlb_value_show (in->type_02.show, &out->numeric.show);
310 out->numeric.var_name = to_utf8_if_nonempty (in->type_02.var_name,
312 out->numeric.value_label = to_utf8_if_nonempty (in->type_02.value_label,
317 vm = in->type_03.value_mod;
318 out->type = PIVOT_VALUE_TEXT;
319 out->text.local = to_utf8 (in->type_03.local, encoding);
320 out->text.c = to_utf8 (in->type_03.c, encoding);
321 out->text.id = to_utf8 (in->type_03.id, encoding);
322 out->text.user_provided = !in->type_03.fixed;
326 vm = in->type_04.value_mod;
327 out->type = PIVOT_VALUE_STRING;
328 error = decode_spvlb_value_show (in->type_04.show, &out->string.show);
331 out->string.s = to_utf8 (in->type_04.s, encoding);
332 out->string.var_name = to_utf8 (in->type_04.var_name, encoding);
333 out->string.value_label = to_utf8_if_nonempty (in->type_04.value_label,
338 vm = in->type_05.value_mod;
339 out->type = PIVOT_VALUE_VARIABLE;
340 error = decode_spvlb_value_show (in->type_05.show, &out->variable.show);
343 out->variable.var_name = to_utf8 (in->type_05.var_name, encoding);
344 out->variable.var_label = to_utf8_if_nonempty (in->type_05.var_label,
349 vm = in->type_06.value_mod;
350 out->type = PIVOT_VALUE_TEXT;
351 out->text.local = to_utf8 (in->type_06.local, encoding);
352 out->text.c = to_utf8 (in->type_06.c, encoding);
353 out->text.id = to_utf8 (in->type_06.id, encoding);
354 out->text.user_provided = false;
358 vm = in->type_else.value_mod;
359 out->type = PIVOT_VALUE_TEMPLATE;
360 out->template.local = to_utf8 (in->type_else.template, encoding);
361 out->template.id = out->template.local;
362 out->template.n_args = 0;
363 out->template.args = xnmalloc (in->type_else.n_args,
364 sizeof *out->template.args);
365 for (size_t i = 0; i < in->type_else.n_args; i++)
367 error = decode_spvlb_argument (table, in->type_else.args[i],
368 encoding, &out->template.args[i]);
371 pivot_value_destroy (out);
374 out->template.n_args++;
384 if (vm->n_subscripts)
386 out->n_subscripts = vm->n_subscripts;
387 out->subscripts = xnmalloc (vm->n_subscripts,
388 sizeof *out->subscripts);
389 for (size_t i = 0; i < vm->n_subscripts; i++)
390 out->subscripts[i] = to_utf8 (vm->subscripts[i], encoding);
395 out->footnotes = xnmalloc (vm->n_refs, sizeof *out->footnotes);
396 for (size_t i = 0; i < vm->n_refs; i++)
398 uint16_t idx = vm->refs[i];
399 if (idx >= table->n_footnotes)
401 pivot_value_destroy (out);
402 return xasprintf ("bad footnote index: %"PRIu16" >= %zu",
403 idx, table->n_footnotes);
406 out->footnotes[out->n_footnotes++] = table->footnotes[idx];
412 error = decode_spvlb_font_style (vm->style_pair->font_style,
413 encoding, &out->font_style);
415 error = decode_spvlb_cell_style (vm->style_pair->cell_style,
419 pivot_value_destroy (out);
424 if (vm->template_string
425 && vm->template_string->id
426 && vm->template_string->id[0]
427 && out->type == PIVOT_VALUE_TEMPLATE)
428 out->template.id = to_utf8 (vm->template_string->id, encoding);
435 static char * WARN_UNUSED_RESULT
436 decode_spvlb_area (const struct spvlb_area *in, struct area_style *out,
437 const char *encoding)
441 struct cell_color fg0, fg1, bg0, bg1;
442 error = decode_spvlb_color_string (in->fg_color, 0x00, &fg0);
444 error = decode_spvlb_color_string (in->bg_color, 0xff, &bg0);
445 if (!error && in->alternate)
446 error = decode_spvlb_color_string (in->alt_fg_color, 0x00, &fg1);
447 if (!error && in->alternate)
448 error = decode_spvlb_color_string (in->alt_bg_color, 0xff, &bg1);
450 enum table_halign halign;
453 error = decode_spvlb_halign (in->halign, &halign);
455 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which
456 is good because there's no way to indicate the decimal offset. Just
458 if (!error && halign == TABLE_HALIGN_DECIMAL)
459 halign = TABLE_HALIGN_MIXED;
462 enum table_valign valign;
464 error = decode_spvlb_valign (in->valign, &valign);
469 *out = (struct area_style) {
471 .bold = (in->style & 1) != 0,
472 .italic = (in->style & 2) != 0,
473 .underline = in->underline,
474 .fg = { fg0, in->alternate ? fg1 : fg0 },
475 .bg = { bg0, in->alternate ? bg1 : bg0 },
476 .typeface = to_utf8 (in->typeface, encoding),
477 .size = in->size / 1.33,
483 [TABLE_HORZ] = { in->left_margin, in->right_margin },
484 [TABLE_VERT] = { in->top_margin, in->bottom_margin },
491 static char * WARN_UNUSED_RESULT
492 decode_spvlb_group (const struct pivot_table *,
493 struct spvlb_category **,
496 struct pivot_category *parent,
497 struct pivot_dimension *,
498 const char *encoding);
500 static char * WARN_UNUSED_RESULT
501 decode_spvlb_categories (const struct pivot_table *table,
502 struct spvlb_category **categories,
504 struct pivot_category *parent,
505 struct pivot_dimension *dimension,
506 const char *encoding)
508 for (size_t i = 0; i < n_categories; i++)
510 const struct spvlb_category *in = categories[i];
511 if (in->group && in->group->merge)
513 char *error = decode_spvlb_categories (
514 table, in->group->subcategories, in->group->n_subcategories,
515 parent, dimension, encoding);
522 struct pivot_value *name;
523 char *error = decode_spvlb_value (table, in->name, encoding, &name);
527 struct pivot_category *out = xzalloc (sizeof *out);
529 out->parent = parent;
530 out->dimension = dimension;
533 char *error = decode_spvlb_group (table, in->group->subcategories,
534 in->group->n_subcategories,
535 true, out, dimension, encoding);
538 pivot_category_destroy (out);
542 out->data_index = SIZE_MAX;
543 out->presentation_index = SIZE_MAX;
547 out->data_index = in->leaf->leaf_index;
548 out->presentation_index = dimension->n_leaves;
549 dimension->n_leaves++;
552 if (parent->n_subs >= parent->allocated_subs)
553 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
554 sizeof *parent->subs);
555 parent->subs[parent->n_subs++] = out;
560 static char * WARN_UNUSED_RESULT
561 decode_spvlb_group (const struct pivot_table *table,
562 struct spvlb_category **categories,
563 size_t n_categories, bool show_label,
564 struct pivot_category *category,
565 struct pivot_dimension *dimension,
566 const char *encoding)
568 category->subs = XCALLOC (n_categories, struct pivot_category *);
569 category->n_subs = 0;
570 category->allocated_subs = 0;
571 category->show_label = show_label;
573 return decode_spvlb_categories (table, categories, n_categories, category,
574 dimension, encoding);
577 static char * WARN_UNUSED_RESULT
578 fill_leaves (struct pivot_category *category,
579 struct pivot_dimension *dimension)
581 if (pivot_category_is_group (category))
583 for (size_t i = 0; i < category->n_subs; i++)
585 char *error = fill_leaves (category->subs[i], dimension);
592 if (category->data_index >= dimension->n_leaves)
593 return xasprintf ("leaf_index %zu >= n_leaves %zu",
594 category->data_index, dimension->n_leaves);
595 if (dimension->data_leaves[category->data_index])
596 return xasprintf ("two leaves with data_index %zu",
597 category->data_index);
598 dimension->data_leaves[category->data_index] = category;
599 dimension->presentation_leaves[category->presentation_index] = category;
604 static char * WARN_UNUSED_RESULT
605 decode_spvlb_dimension (const struct pivot_table *table,
606 const struct spvlb_dimension *in,
607 size_t idx, const char *encoding,
608 struct pivot_dimension **outp)
610 /* Convert most of the dimension. */
611 struct pivot_value *name;
612 char *error = decode_spvlb_value (table, in->name, encoding, &name);
616 struct pivot_dimension *out = xzalloc (sizeof *out);
617 out->level = UINT_MAX;
618 out->top_index = idx;
619 out->hide_all_labels = in->props->hide_all_labels;
621 out->root = xzalloc (sizeof *out->root);
622 *out->root = (struct pivot_category) {
625 .data_index = SIZE_MAX,
626 .presentation_index = SIZE_MAX,
628 error = decode_spvlb_group (table, in->categories, in->n_categories,
629 !in->props->hide_dim_label, out->root,
634 /* Allocate and fill the array of leaves now that we know how many there
636 out->data_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
637 out->presentation_leaves = XCALLOC (out->n_leaves, struct pivot_category *);
638 out->allocated_leaves = out->n_leaves;
639 error = fill_leaves (out->root, out);
642 for (size_t i = 0; i < out->n_leaves; i++)
644 assert (out->data_leaves[i] != NULL);
645 assert (out->presentation_leaves[i] != NULL);
651 pivot_dimension_destroy (out);
655 static char * WARN_UNUSED_RESULT
656 decode_spvlb_stroke (uint32_t stroke_type, enum table_stroke *strokep)
658 enum table_stroke strokes[] = {
667 if (stroke_type >= sizeof strokes / sizeof *strokes)
668 return xasprintf ("bad stroke %"PRIu32, stroke_type);
670 *strokep = strokes[stroke_type];
674 static char * WARN_UNUSED_RESULT
675 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
678 if (in->border_type >= PIVOT_N_BORDERS)
679 return xasprintf ("bad border type %"PRIu32, in->border_type);
681 struct table_border_style *out = &table->borders[in->border_type];
682 out->color = decode_spvlb_color_u32 (in->color);
683 return decode_spvlb_stroke (in->stroke_type, &out->stroke);
686 static char * WARN_UNUSED_RESULT
687 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
688 enum pivot_axis_type axis_type, struct pivot_table *table)
690 struct pivot_axis *axis = &table->axes[axis_type];
691 axis->dimensions = XCALLOC (n_dimensions, struct pivot_dimension *);
692 axis->n_dimensions = n_dimensions;
694 for (size_t i = 0; i < n_dimensions; i++)
696 uint32_t idx = dimension_indexes[i];
697 if (idx >= table->n_dimensions)
698 return xasprintf ("bad dimension index %"PRIu32" >= %zu",
699 idx, table->n_dimensions);
701 struct pivot_dimension *d = table->dimensions[idx];
702 if (d->level != UINT_MAX)
703 return xasprintf ("duplicate dimension %"PRIu32, idx);
705 axis->dimensions[i] = d;
706 d->axis_type = axis_type;
709 axis->extent *= d->n_leaves;
716 decode_data_index (uint64_t in, const struct pivot_table *table,
719 uint64_t remainder = in;
720 for (size_t i = table->n_dimensions - 1; i > 0; i--)
722 const struct pivot_dimension *d = table->dimensions[i];
725 out[i] = remainder % d->n_leaves;
726 remainder /= d->n_leaves;
731 if (remainder >= table->dimensions[0]->n_leaves)
732 return xasprintf ("out of range cell data index %"PRIu64, in);
738 static char * WARN_UNUSED_RESULT
739 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
740 struct pivot_table *table, const char *encoding)
742 if (!table->n_dimensions)
745 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
746 for (size_t i = 0; i < n_in; i++)
748 struct pivot_value *value;
749 char *error = decode_data_index (in[i]->index, table, dindexes);
751 error = decode_spvlb_value (table, in[i]->value, encoding, &value);
757 pivot_table_put (table, dindexes, table->n_dimensions, value);
764 static char * WARN_UNUSED_RESULT
765 decode_spvlb_footnote (const struct spvlb_footnote *in, const char *encoding,
766 size_t idx, struct pivot_table *table)
768 struct pivot_value *content;
769 char *error = decode_spvlb_value (table, in->text, encoding, &content);
773 struct pivot_value *marker = NULL;
776 error = decode_spvlb_value (table, in->marker, encoding, &marker);
779 pivot_value_destroy (content);
782 if (marker->type == PIVOT_VALUE_TEXT)
783 marker->text.user_provided = false;
786 struct pivot_footnote *f = pivot_table_create_footnote__ (
787 table, idx, marker, content);
788 f->show = (int32_t) in->show > 0;
792 static char * WARN_UNUSED_RESULT
793 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
795 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
796 table->current_layer = xnmalloc (axis->n_dimensions,
797 sizeof *table->current_layer);
799 for (size_t i = 0; i < axis->n_dimensions; i++)
801 const struct pivot_dimension *d = axis->dimensions[i];
804 table->current_layer[i] = current_layer % d->n_leaves;
805 current_layer /= d->n_leaves;
808 table->current_layer[i] = 0;
810 if (current_layer > 0)
811 return xasprintf ("out of range layer data index %"PRIu64, current_layer);
815 char * WARN_UNUSED_RESULT
816 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
819 if (in->header->version != 1 && in->header->version != 3)
820 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
821 in->header->version);
824 struct pivot_table *out = xzalloc (sizeof *out);
826 hmap_init (&out->cells);
828 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
829 : in->formats->x3 ? in->formats->x3->y1
831 const char *encoding;
833 encoding = y1->charset;
836 const char *dot = strchr (in->formats->locale, '.');
837 encoding = dot ? dot + 1 : "windows-1252";
840 /* Display settings. */
841 out->show_numeric_markers = !in->ts->show_alphabetic_markers;
842 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
843 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
844 out->row_labels_in_corner = in->ts->show_row_labels_in_corner;
845 out->show_grid_lines = in->borders->show_grid_lines;
846 out->show_caption = true;
847 out->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
848 out->omit_empty = in->ts->omit_empty;
850 const struct spvlb_x1 *x1 = in->formats->x1;
853 error = decode_spvlb_value_show (x1->show_values, &out->show_values);
855 error = decode_spvlb_value_show (x1->show_variables,
856 &out->show_variables);
860 out->show_caption = x1->show_caption;
863 /* Column and row display settings. */
864 out->sizing[TABLE_VERT].range[0] = in->header->min_row_height;
865 out->sizing[TABLE_VERT].range[1] = in->header->max_row_height;
866 out->sizing[TABLE_HORZ].range[0] = in->header->min_col_width;
867 out->sizing[TABLE_HORZ].range[1] = in->header->max_col_width;
869 convert_widths (in->formats->widths, in->formats->n_widths,
870 &out->sizing[TABLE_HORZ].widths,
871 &out->sizing[TABLE_HORZ].n_widths);
873 const struct spvlb_x2 *x2 = in->formats->x2;
875 convert_widths (x2->row_heights, x2->n_row_heights,
876 &out->sizing[TABLE_VERT].widths,
877 &out->sizing[TABLE_VERT].n_widths);
879 convert_breakpoints (in->ts->row_breaks,
880 &out->sizing[TABLE_VERT].breaks,
881 &out->sizing[TABLE_VERT].n_breaks);
882 convert_breakpoints (in->ts->col_breaks,
883 &out->sizing[TABLE_HORZ].breaks,
884 &out->sizing[TABLE_HORZ].n_breaks);
886 convert_keeps (in->ts->row_keeps,
887 &out->sizing[TABLE_VERT].keeps,
888 &out->sizing[TABLE_VERT].n_keeps);
889 convert_keeps (in->ts->col_keeps,
890 &out->sizing[TABLE_HORZ].keeps,
891 &out->sizing[TABLE_HORZ].n_keeps);
893 out->notes = to_utf8_if_nonempty (in->ts->notes, encoding);
894 out->table_look = to_utf8_if_nonempty (in->ts->table_look, encoding);
896 /* Print settings. */
897 out->print_all_layers = in->ps->all_layers;
898 out->paginate_layers = in->ps->paginate_layers;
899 out->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
900 out->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
901 out->top_continuation = in->ps->top_continuation;
902 out->bottom_continuation = in->ps->bottom_continuation;
903 out->continuation = xstrdup (in->ps->continuation_string);
904 out->n_orphan_lines = in->ps->n_orphan_lines;
906 /* Format settings. */
907 out->epoch = in->formats->y0->epoch;
908 out->decimal = in->formats->y0->decimal;
909 out->grouping = in->formats->y0->grouping;
910 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
911 for (int i = 0; i < 5; i++)
912 if (cc && i < cc->n_ccs)
913 out->ccs[i] = xstrdup (cc->ccs[i]);
914 out->small = in->formats->x3 ? in->formats->x3->small : 0;
916 /* Command information. */
919 out->command_local = to_utf8 (y1->command_local, encoding);
920 out->command_c = to_utf8 (y1->command, encoding);
921 out->language = xstrdup (y1->language);
923 out->locale = xstrdup (y1->locale);
926 /* Source information. */
927 const struct spvlb_x3 *x3 = in->formats->x3;
930 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
931 out->dataset = to_utf8 (x3->dataset, encoding);
932 out->datafile = to_utf8_if_nonempty (x3->datafile, encoding);
933 out->date = x3->date;
938 Any pivot_value might refer to footnotes, so it's important to process the
939 footnotes early to ensure that those references can be resolved. There is
940 a possible problem that a footnote might itself reference an
941 as-yet-unprocessed footnote, but that's OK because footnote references
942 don't actually look at the footnote contents but only resolve a pointer to
943 where the footnote will go later.
945 Before we really start, create all the footnotes we'll fill in. This is
946 because sometimes footnotes refer to themselves or to each other and we
947 don't want to reject those references. */
948 const struct spvlb_footnotes *fn = in->footnotes;
949 if (fn->n_footnotes > 0)
951 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
952 for (size_t i = 0; i < fn->n_footnotes; i++)
954 error = decode_spvlb_footnote (in->footnotes->footnotes[i],
961 /* Title and caption. */
962 error = decode_spvlb_value (out, in->titles->user_title, encoding,
967 error = decode_spvlb_value (out, in->titles->subtype, encoding,
972 if (in->titles->corner_text)
974 error = decode_spvlb_value (out, in->titles->corner_text,
975 encoding, &out->corner_text);
980 if (in->titles->caption)
982 error = decode_spvlb_value (out, in->titles->caption, encoding,
990 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
992 error = decode_spvlb_area (in->areas->areas[i], &out->areas[i],
997 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
999 error = decode_spvlb_border (in->borders->borders[i], out);
1005 out->n_dimensions = in->dimensions->n_dims;
1006 out->dimensions = XCALLOC (out->n_dimensions, struct pivot_dimension *);
1007 for (size_t i = 0; i < out->n_dimensions; i++)
1009 error = decode_spvlb_dimension (out, in->dimensions->dims[i],
1010 i, encoding, &out->dimensions[i]);
1016 size_t a = in->axes->n_layers;
1017 size_t b = in->axes->n_rows;
1018 size_t c = in->axes->n_columns;
1019 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
1021 error = xasprintf ("dimensions do not sum correctly "
1022 "(%zu + %zu + %zu != %zu)",
1023 a, b, c, out->n_dimensions);
1026 error = decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
1027 PIVOT_AXIS_LAYER, out);
1030 error = decode_spvlb_axis (in->axes->rows, in->axes->n_rows,
1031 PIVOT_AXIS_ROW, out);
1034 error = decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
1035 PIVOT_AXIS_COLUMN, out);
1039 pivot_table_assign_label_depth (out);
1041 error = decode_current_layer (in->ts->current_layer, out);
1046 error = decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out,
1053 pivot_table_unref (out);