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 struct cell_color
89 decode_spvlb_color_string (const char *s, uint8_t def)
92 if (sscanf (s, "#%2x%2x%2x", &r, &g, &b) != 3)
96 fprintf (stderr, "bad color %s\n", s);
101 return (struct cell_color) CELL_COLOR (r, g, b);
104 static struct cell_color
105 decode_spvlb_color_u32 (uint32_t x)
107 return (struct cell_color) { x >> 24, x >> 16, x >> 8, x };
110 static struct font_style *
111 decode_spvlb_font_style (const struct spvlb_font_style *in,
112 const char *encoding)
117 struct font_style *out = xmalloc (sizeof *out);
118 *out = (struct font_style) {
120 .italic = in->italic,
121 .underline = in->underline,
122 .fg[0] = decode_spvlb_color_string (in->fg_color, 0x00),
123 .bg[0] = decode_spvlb_color_string (in->bg_color, 0xff),
124 .typeface = to_utf8 (in->typeface, encoding),
125 .size = in->size / 1.33,
127 out->fg[1] = out->fg[0];
128 out->bg[1] = out->bg[0];
132 static enum table_halign
133 decode_spvlb_halign (uint32_t in)
138 return TABLE_HALIGN_CENTER;
141 return TABLE_HALIGN_LEFT;
144 return TABLE_HALIGN_RIGHT;
148 return TABLE_HALIGN_DECIMAL;
152 return TABLE_HALIGN_MIXED;
155 fprintf (stderr, "bad cell style halign %"PRIu32"\n", in);
160 static enum table_valign
161 decode_spvlb_valign (uint32_t in)
166 return TABLE_VALIGN_CENTER;
169 return TABLE_VALIGN_TOP;
172 return TABLE_VALIGN_BOTTOM;
175 fprintf (stderr, "bad cell style valign %"PRIu32"\n", in);
180 static struct cell_style *
181 decode_spvlb_cell_style (const struct spvlb_cell_style *in)
186 struct cell_style *out = xzalloc (sizeof *out);
188 out->halign = decode_spvlb_halign (in->halign);
189 out->valign = decode_spvlb_valign (in->valign);
190 out->decimal_offset = in->decimal_offset;
191 out->margin[TABLE_HORZ][0] = in->left_margin;
192 out->margin[TABLE_HORZ][1] = in->right_margin;
193 out->margin[TABLE_VERT][0] = in->top_margin;
194 out->margin[TABLE_VERT][1] = in->bottom_margin;
199 static struct pivot_value *decode_spvlb_value (const struct pivot_table *,
200 const struct spvlb_value *,
201 const char *encoding);
204 decode_spvlb_argument (const struct pivot_table *table,
205 const struct spvlb_argument *in,
206 struct pivot_argument *out,
207 const char *encoding)
212 out->values = xmalloc (sizeof *out->values);
213 out->values[0] = decode_spvlb_value (table, in->value, encoding);
217 out->n = in->n_values;
218 out->values = xnmalloc (out->n, sizeof *out->values);
219 for (size_t i = 0; i < out->n; i++)
220 out->values[i] = decode_spvlb_value (table, in->values[i], encoding);
224 static enum settings_value_show
225 decode_spvlb_value_show (uint8_t in)
229 case 0: return SETTINGS_VALUE_SHOW_DEFAULT;
230 case 1: return SETTINGS_VALUE_SHOW_VALUE;
231 case 2: return SETTINGS_VALUE_SHOW_LABEL;
232 case 3: return SETTINGS_VALUE_SHOW_BOTH;
234 fprintf (stderr, "bad value show %"PRIu8"\n", in);
239 static struct pivot_value *
240 decode_spvlb_value (const struct pivot_table *table,
241 const struct spvlb_value *in,
242 const char *encoding)
244 struct pivot_value *out = xzalloc (sizeof *out);
245 const struct spvlb_value_mod *vm;
250 vm = in->type_01.value_mod;
251 out->type = PIVOT_VALUE_NUMERIC;
252 out->numeric.x = in->type_01.x;
253 out->numeric.format = spv_decode_fmt_spec (in->type_01.format);
257 vm = in->type_02.value_mod;
258 out->type = PIVOT_VALUE_NUMERIC;
259 out->numeric.x = in->type_02.x;
260 out->numeric.format = spv_decode_fmt_spec (in->type_02.format);
261 out->numeric.var_name = to_utf8_if_nonempty (in->type_02.var_name,
263 out->numeric.value_label = to_utf8_if_nonempty (in->type_02.value_label,
265 out->numeric.show = decode_spvlb_value_show (in->type_02.show);
269 vm = in->type_03.value_mod;
270 out->type = PIVOT_VALUE_TEXT;
271 out->text.local = to_utf8 (in->type_03.local, encoding);
272 out->text.c = to_utf8 (in->type_03.c, encoding);
273 out->text.id = to_utf8 (in->type_03.id, encoding);
274 out->text.user_provided = !in->type_03.fixed;
278 vm = in->type_04.value_mod;
279 out->type = PIVOT_VALUE_STRING;
280 out->string.s = to_utf8 (in->type_04.s, encoding);
281 out->string.var_name = to_utf8 (in->type_04.var_name, encoding);
282 out->string.value_label = to_utf8_if_nonempty (in->type_04.value_label,
284 out->string.show = decode_spvlb_value_show (in->type_04.show);
288 vm = in->type_05.value_mod;
289 out->type = PIVOT_VALUE_VARIABLE;
290 out->variable.var_name = to_utf8 (in->type_05.var_name, encoding);
291 out->variable.var_label = to_utf8_if_nonempty (in->type_05.var_label,
293 out->variable.show = decode_spvlb_value_show (in->type_05.show);
297 vm = in->type_06.value_mod;
298 out->type = PIVOT_VALUE_TEXT;
299 out->text.local = to_utf8 (in->type_06.local, encoding);
300 out->text.c = to_utf8 (in->type_06.c, encoding);
301 out->text.id = to_utf8 (in->type_06.id, encoding);
302 out->text.user_provided = false;
306 vm = in->type_else.value_mod;
307 out->type = PIVOT_VALUE_TEMPLATE;
308 out->template.local = to_utf8 (in->type_else.template, encoding);
309 out->template.id = out->template.local;
310 out->template.n_args = in->type_else.n_args;
311 out->template.args = xnmalloc (in->type_else.n_args,
312 sizeof *out->template.args);
313 for (size_t i = 0; i < out->template.n_args; i++)
314 decode_spvlb_argument (table, in->type_else.args[i],
315 &out->template.args[i], encoding);
325 out->subscript = to_utf8 (vm->subscript, encoding);
329 out->footnotes = xnmalloc (vm->n_refs, sizeof *out->footnotes);
330 for (size_t i = 0; i < vm->n_refs; i++)
332 uint16_t idx = vm->refs[i];
333 if (idx < table->n_footnotes)
334 out->footnotes[out->n_footnotes++] = table->footnotes[idx];
337 fprintf (stderr, "bad footnote index: %"PRIu16" >= %zu\n",
338 idx, table->n_footnotes);
346 out->font_style = decode_spvlb_font_style (
347 vm->style_pair->font_style, encoding);
348 out->cell_style = decode_spvlb_cell_style (
349 vm->style_pair->cell_style);
352 if (vm->template_string
353 && vm->template_string->id
354 && vm->template_string->id[0]
355 && out->type == PIVOT_VALUE_TEMPLATE)
356 out->template.id = to_utf8 (vm->template_string->id, encoding);
363 decode_spvlb_area (const struct spvlb_area *in, struct area_style *out,
364 const char *encoding)
366 out->font_style.bold = (in->style & 1) != 0;
367 out->font_style.italic = (in->style & 2) != 0;
368 out->font_style.underline = in->underline;
369 out->font_style.fg[0] = decode_spvlb_color_string (in->fg_color, 0x00);
370 out->font_style.bg[0] = decode_spvlb_color_string (in->bg_color, 0xff);
371 out->font_style.typeface = to_utf8 (in->typeface, encoding);
372 out->font_style.size = in->size / 1.33;
373 out->font_style.fg[1] = (in->alternate
374 ? decode_spvlb_color_string (in->alt_fg_color, 0x00)
375 : out->font_style.fg[0]);
376 out->font_style.bg[1] = (in->alternate
377 ? decode_spvlb_color_string (in->alt_bg_color, 0xff)
378 : out->font_style.bg[0]);
379 assert (in->halign != 61453);
380 out->cell_style.halign = decode_spvlb_halign (in->halign);
381 out->cell_style.valign = decode_spvlb_valign (in->valign);
383 /* TABLE_HALIGN_DECIMAL doesn't seem to be a real halign for areas, which is
384 good because there's no way to indicate the decimal offset. Just in
386 if (out->cell_style.halign == TABLE_HALIGN_DECIMAL)
387 out->cell_style.halign = TABLE_HALIGN_MIXED;
389 out->cell_style.margin[TABLE_HORZ][0] = in->left_margin;
390 out->cell_style.margin[TABLE_HORZ][1] = in->right_margin;
391 out->cell_style.margin[TABLE_VERT][0] = in->top_margin;
392 out->cell_style.margin[TABLE_VERT][1] = in->bottom_margin;
395 static void decode_spvlb_group (const struct pivot_table *,
396 struct spvlb_category **,
399 struct pivot_category *parent,
400 struct pivot_dimension *,
401 const char *encoding);
404 decode_spvlb_categories (const struct pivot_table *table,
405 struct spvlb_category **categories,
407 struct pivot_category *parent,
408 struct pivot_dimension *dimension,
409 const char *encoding)
411 for (size_t i = 0; i < n_categories; i++)
413 const struct spvlb_category *in = categories[i];
414 if (in->group && in->group->merge)
416 decode_spvlb_categories (table, in->group->subcategories,
417 in->group->n_subcategories,
418 parent, dimension, encoding);
422 struct pivot_category *out = xzalloc (sizeof *out);
423 out->name = decode_spvlb_value (table, in->name, encoding);
424 out->parent = parent;
425 out->dimension = dimension;
428 decode_spvlb_group (table, in->group->subcategories,
429 in->group->n_subcategories,
430 true, out, dimension, encoding);
431 out->data_index = SIZE_MAX;
432 out->presentation_index = SIZE_MAX;
436 out->data_index = in->leaf->leaf_index;
437 out->presentation_index = dimension->n_leaves;
438 dimension->n_leaves++;
441 if (parent->n_subs >= parent->allocated_subs)
442 parent->subs = x2nrealloc (parent->subs, &parent->allocated_subs,
443 sizeof *parent->subs);
444 parent->subs[parent->n_subs++] = out;
449 decode_spvlb_group (const struct pivot_table *table,
450 struct spvlb_category **categories,
451 size_t n_categories, bool show_label,
452 struct pivot_category *category,
453 struct pivot_dimension *dimension,
454 const char *encoding)
456 category->subs = xcalloc (n_categories, sizeof *category->subs);
457 category->n_subs = 0;
458 category->allocated_subs = 0;
459 category->show_label = show_label;
461 decode_spvlb_categories (table, categories, n_categories, category,
462 dimension, encoding);
466 fill_leaves (struct pivot_category *category,
467 struct pivot_dimension *dimension)
469 if (pivot_category_is_group (category))
471 for (size_t i = 0; i < category->n_subs; i++)
472 fill_leaves (category->subs[i], dimension);
476 if (category->data_index >= dimension->n_leaves)
478 fprintf (stderr, "leaf_index %zu >= n_leaves %zu\n",
479 category->data_index, dimension->n_leaves);
482 if (dimension->data_leaves[category->data_index])
484 fprintf (stderr, "two leaves with data_index %zu\n",
485 category->data_index);
488 dimension->data_leaves[category->data_index] = category;
489 dimension->presentation_leaves[category->presentation_index] = category;
493 static struct pivot_dimension *
494 decode_spvlb_dimension (const struct pivot_table *table,
495 const struct spvlb_dimension *in,
496 size_t idx, const char *encoding)
498 /* Convert most of the dimension. */
499 struct pivot_dimension *out = xzalloc (sizeof *out);
500 out->level = UINT_MAX;
501 out->top_index = idx;
502 out->hide_all_labels = in->props->hide_all_labels;
504 out->root = xzalloc (sizeof *out->root);
505 *out->root = (struct pivot_category) {
506 .name = decode_spvlb_value (table, in->name, encoding),
508 .data_index = SIZE_MAX,
509 .presentation_index = SIZE_MAX,
511 decode_spvlb_group (table, in->categories, in->n_categories,
512 !in->props->hide_dim_label, out->root, out, encoding);
514 /* Allocate and fill the array of leaves now that we know how many there
516 out->data_leaves = xcalloc (out->n_leaves, sizeof *out->data_leaves);
517 out->presentation_leaves = xcalloc (out->n_leaves,
518 sizeof *out->presentation_leaves);
519 out->allocated_leaves = out->n_leaves;
520 fill_leaves (out->root, out);
521 for (size_t i = 0; i < out->n_leaves; i++)
523 assert (out->data_leaves[i] != NULL);
524 assert (out->presentation_leaves[i] != NULL);
530 static enum table_stroke
531 decode_spvlb_stroke (uint32_t stroke_type)
535 case 0: return TABLE_STROKE_NONE;
536 case 1: return TABLE_STROKE_SOLID;
537 case 2: return TABLE_STROKE_DASHED;
538 case 3: return TABLE_STROKE_THICK;
539 case 4: return TABLE_STROKE_THIN;
540 case 5: return TABLE_STROKE_DOUBLE;
543 fprintf (stderr, "bad stroke %"PRIu32"\n", stroke_type);
549 decode_spvlb_border (const struct spvlb_border *in, struct pivot_table *table)
552 if (in->border_type >= PIVOT_N_BORDERS)
554 fprintf (stderr, "bad border type %"PRIu32"\n", in->border_type);
558 struct table_border_style *out = &table->borders[in->border_type];
559 out->stroke = decode_spvlb_stroke (in->stroke_type);
560 out->color = decode_spvlb_color_u32 (in->color);
564 decode_spvlb_axis (const uint32_t *dimension_indexes, size_t n_dimensions,
565 enum pivot_axis_type axis_type, struct pivot_table *table)
567 struct pivot_axis *axis = &table->axes[axis_type];
568 axis->dimensions = xnmalloc (n_dimensions, sizeof *axis->dimensions);
569 axis->n_dimensions = n_dimensions;
571 for (size_t i = 0; i < n_dimensions; i++)
573 uint32_t idx = dimension_indexes[i];
574 if (idx >= table->n_dimensions)
576 fprintf (stderr, "bad dimension index %"PRIu32" >= %zu",
577 idx, table->n_dimensions);
581 struct pivot_dimension *d = table->dimensions[idx];
582 if (d->level != UINT_MAX)
584 fprintf (stderr, "duplicate dimension %"PRIu32, idx);
588 axis->dimensions[i] = d;
589 d->axis_type = axis_type;
592 axis->extent *= d->n_leaves;
597 decode_data_index (uint64_t in, const struct pivot_table *table,
600 uint64_t remainder = in;
601 for (size_t i = table->n_dimensions - 1; i > 0; i--)
603 const struct pivot_dimension *d = table->dimensions[i];
606 out[i] = remainder % d->n_leaves;
607 remainder /= d->n_leaves;
612 if (remainder >= table->dimensions[0]->n_leaves)
614 fprintf (stderr, "out of range cell data index %"PRIu64, in);
621 decode_spvlb_cells (struct spvlb_cell **in, size_t n_in,
622 struct pivot_table *table, const char *encoding)
624 if (!table->n_dimensions)
627 size_t *dindexes = xnmalloc (table->n_dimensions, sizeof *dindexes);
628 for (size_t i = 0; i < n_in; i++)
630 decode_data_index (in[i]->index, table, dindexes);
631 struct pivot_value *value = decode_spvlb_value (table, in[i]->value,
633 pivot_table_put (table, dindexes, table->n_dimensions, value);
639 decode_spvlb_footnote (const struct spvlb_footnote *in, const char *encoding,
640 size_t idx, struct pivot_table *table)
642 struct pivot_value *content = decode_spvlb_value (table, in->text, encoding);
643 struct pivot_value *marker = NULL;
646 marker = decode_spvlb_value (table, in->marker, encoding);
647 if (marker->type == PIVOT_VALUE_TEXT)
648 marker->text.user_provided = false;
650 pivot_table_create_footnote__ (table, idx, marker, content);
654 decode_current_layer (uint64_t current_layer, struct pivot_table *table)
656 const struct pivot_axis *axis = &table->axes[PIVOT_AXIS_LAYER];
657 table->current_layer = xnmalloc (axis->n_dimensions,
658 sizeof *table->current_layer);
660 for (size_t i = 0; i < axis->n_dimensions; i++)
662 const struct pivot_dimension *d = axis->dimensions[i];
665 table->current_layer[i] = current_layer % d->n_leaves;
666 current_layer /= d->n_leaves;
669 table->current_layer[i] = 0;
671 if (current_layer > 0)
673 fprintf (stderr, "out of range layer data index %"PRIu64, current_layer);
679 decode_spvlb_table (const struct spvlb_table *in, struct pivot_table **outp)
681 if (in->header->version != 1 && in->header->version != 3)
682 return xasprintf ("unknown version %"PRIu32" (expected 1 or 3)",
683 in->header->version);
685 struct pivot_table *out = xzalloc (sizeof *out);
687 hmap_init (&out->cells);
689 const struct spvlb_y1 *y1 = (in->formats->x0 ? in->formats->x0->y1
690 : in->formats->x3 ? in->formats->x3->y1
692 const char *encoding;
694 encoding = y1->charset;
697 const char *dot = strchr (in->formats->locale, '.');
698 encoding = dot ? dot + 1 : "windows-1252";
701 /* Display settings. */
702 out->show_numeric_markers = !in->ts->show_alphabetic_markers;
703 out->rotate_inner_column_labels = in->header->rotate_inner_column_labels;
704 out->rotate_outer_row_labels = in->header->rotate_outer_row_labels;
705 out->row_labels_in_corner = in->ts->show_row_labels_in_corner;
706 out->show_grid_lines = in->borders->show_grid_lines;
707 out->footnote_marker_superscripts = in->ts->footnote_marker_superscripts;
708 out->omit_empty = in->ts->omit_empty;
710 const struct spvlb_x1 *x1 = in->formats->x1;
713 out->show_values = decode_spvlb_value_show (x1->show_values);
714 out->show_variables = decode_spvlb_value_show (x1->show_variables);
717 /* Column and row display settings. */
718 out->sizing[TABLE_VERT].range[0] = in->header->min_row_height;
719 out->sizing[TABLE_VERT].range[1] = in->header->max_row_height;
720 out->sizing[TABLE_HORZ].range[0] = in->header->min_col_width;
721 out->sizing[TABLE_HORZ].range[1] = in->header->max_col_width;
723 convert_widths (in->formats->widths, in->formats->n_widths,
724 &out->sizing[TABLE_HORZ].widths,
725 &out->sizing[TABLE_HORZ].n_widths);
727 const struct spvlb_x2 *x2 = in->formats->x2;
729 convert_widths (x2->row_heights, x2->n_row_heights,
730 &out->sizing[TABLE_VERT].widths,
731 &out->sizing[TABLE_VERT].n_widths);
733 convert_breakpoints (in->ts->row_breaks,
734 &out->sizing[TABLE_VERT].breaks,
735 &out->sizing[TABLE_VERT].n_breaks);
736 convert_breakpoints (in->ts->col_breaks,
737 &out->sizing[TABLE_HORZ].breaks,
738 &out->sizing[TABLE_HORZ].n_breaks);
740 convert_keeps (in->ts->row_keeps,
741 &out->sizing[TABLE_VERT].keeps,
742 &out->sizing[TABLE_VERT].n_keeps);
743 convert_keeps (in->ts->col_keeps,
744 &out->sizing[TABLE_HORZ].keeps,
745 &out->sizing[TABLE_HORZ].n_keeps);
747 out->notes = to_utf8_if_nonempty (in->ts->notes, encoding);
748 out->table_look = to_utf8_if_nonempty (in->ts->table_look, encoding);
750 /* Print settings. */
751 out->print_all_layers = in->ps->all_layers;
752 out->paginate_layers = in->ps->paginate_layers;
753 out->shrink_to_fit[TABLE_HORZ] = in->ps->fit_width;
754 out->shrink_to_fit[TABLE_VERT] = in->ps->fit_length;
755 out->top_continuation = in->ps->top_continuation;
756 out->bottom_continuation = in->ps->bottom_continuation;
757 out->continuation = xstrdup (in->ps->continuation_string);
758 out->n_orphan_lines = in->ps->n_orphan_lines;
760 /* Format settings. */
761 out->epoch = in->formats->y0->epoch;
762 out->decimal = in->formats->y0->decimal;
763 out->grouping = in->formats->y0->grouping;
764 const struct spvlb_custom_currency *cc = in->formats->custom_currency;
765 for (int i = 0; i < 5; i++)
766 if (cc && i < cc->n_ccs)
767 out->ccs[i] = xstrdup (cc->ccs[i]);
768 out->small = in->formats->x3 ? in->formats->x3->small : 0;
770 /* Command information. */
773 out->command_local = to_utf8 (y1->command_local, encoding);
774 out->command_c = to_utf8 (y1->command, encoding);
775 out->language = xstrdup (y1->language);
777 out->locale = xstrdup (y1->locale);
780 /* Source information. */
781 const struct spvlb_x3 *x3 = in->formats->x3;
784 if (x3->dataset && x3->dataset[0] && x3->dataset[0] != 4)
785 out->dataset = to_utf8 (x3->dataset, encoding);
786 out->datafile = to_utf8_if_nonempty (x3->datafile, encoding);
787 out->date = x3->date;
792 Any pivot_value might refer to footnotes, so it's important to process the
793 footnotes early to ensure that those references can be resolved. There is
794 a possible problem that a footnote might itself reference an
795 as-yet-unprocessed footnote, but that's OK because footnote references
796 don't actually look at the footnote contents but only resolve a pointer to
797 where the footnote will go later.
799 Before we really start, create all the footnotes we'll fill in. This is
800 because sometimes footnotes refer to themselves or to each other and we
801 don't want to reject those references. */
802 const struct spvlb_footnotes *fn = in->footnotes;
803 if (fn->n_footnotes > 0)
805 pivot_table_create_footnote__ (out, fn->n_footnotes - 1, NULL, NULL);
806 for (size_t i = 0; i < fn->n_footnotes; i++)
807 decode_spvlb_footnote (in->footnotes->footnotes[i], encoding, i, out);
810 /* Title and caption. */
811 out->title = decode_spvlb_value (out, in->titles->user_title, encoding);
812 out->subtype = decode_spvlb_value (out, in->titles->subtype, encoding);
813 if (in->titles->corner_text)
814 out->corner_text = decode_spvlb_value (out, in->titles->corner_text,
816 if (in->titles->caption)
817 out->caption = decode_spvlb_value (out, in->titles->caption, encoding);
820 for (size_t i = 0; i < PIVOT_N_AREAS; i++)
821 decode_spvlb_area (in->areas->areas[i], &out->areas[i], encoding);
822 for (size_t i = 0; i < PIVOT_N_BORDERS; i++)
823 decode_spvlb_border (in->borders->borders[i], out);
826 out->n_dimensions = in->dimensions->n_dims;
827 out->dimensions = xcalloc (out->n_dimensions, sizeof *out->dimensions);
828 for (size_t i = 0; i < out->n_dimensions; i++)
829 out->dimensions[i] = decode_spvlb_dimension (out, in->dimensions->dims[i],
833 size_t a = in->axes->n_layers;
834 size_t b = in->axes->n_rows;
835 size_t c = in->axes->n_columns;
836 if (size_overflow_p (xsum3 (a, b, c)) || a + b + c != out->n_dimensions)
838 fprintf (stderr, "wrong number of dimensions\n");
841 decode_spvlb_axis (in->axes->layers, in->axes->n_layers,
842 PIVOT_AXIS_LAYER, out);
843 decode_spvlb_axis (in->axes->rows, in->axes->n_rows, PIVOT_AXIS_ROW, out);
844 decode_spvlb_axis (in->axes->columns, in->axes->n_columns,
845 PIVOT_AXIS_COLUMN, out);
847 pivot_table_assign_label_depth (out);
849 decode_current_layer (in->ts->current_layer, out);
852 decode_spvlb_cells (in->cells->cells, in->cells->n_cells, out, encoding);