-struct ctables_occurrence
- {
- struct hmap_node node;
- union value value;
- };
-
-struct ctables_section
- {
- /* Settings. */
- struct ctables_table *table;
- struct ctables_nest *nests[PIVOT_N_AXES];
-
- /* Data. */
- struct hmap *occurrences[PIVOT_N_AXES]; /* "struct ctables_occurrence"s. */
- struct hmap cells; /* Contains "struct ctables_cell"s. */
- struct hmap areas[N_CTATS]; /* Contains "struct ctables_area"s. */
- };
-
-static void ctables_section_uninit (struct ctables_section *);
-
-struct ctables_table
- {
- struct ctables *ctables;
- struct ctables_axis *axes[PIVOT_N_AXES];
- struct ctables_stack stacks[PIVOT_N_AXES];
- struct ctables_section *sections;
- size_t n_sections;
- enum pivot_axis_type summary_axis;
- struct ctables_summary_spec_set summary_specs;
- struct variable **sum_vars;
- size_t n_sum_vars;
-
- enum pivot_axis_type slabels_axis;
- bool slabels_visible;
-
- /* The innermost category labels for axis 'a' appear on axis label_axis[a].
-
- Most commonly, label_axis[a] == a, and in particular we always have
- label_axis{PIVOT_AXIS_LAYER] == PIVOT_AXIS_LAYER.
-
- If ROWLABELS or COLLABELS is specified, then one of
- label_axis[PIVOT_AXIS_ROW] or label_axis[PIVOT_AXIS_COLUMN] can be the
- opposite axis or PIVOT_AXIS_LAYER. Only one of them will differ.
-
- If any category labels are moved, then 'clabels_example' is one of the
- variables being moved (and it is otherwise NULL). All of the variables
- being moved have the same width, value labels, and categories, so this
- example variable can be used to find those out.
-
- The remaining members in this group are relevant only if category labels
- are moved.
-
- 'clabels_values_map' holds a "struct ctables_value" for all the values
- that appear in all of the variables in the moved categories. It is
- accumulated as the data is read. Once the data is fully read, its
- sorted values are put into 'clabels_values' and 'n_clabels_values'.
- */
- enum pivot_axis_type label_axis[PIVOT_N_AXES];
- enum pivot_axis_type clabels_from_axis;
- enum pivot_axis_type clabels_to_axis;
- const struct variable *clabels_example;
- struct hmap clabels_values_map;
- struct ctables_value **clabels_values;
- size_t n_clabels_values;
-
- /* Indexed by variable dictionary index. */
- struct ctables_categories **categories;
- size_t n_categories;
-
- double cilevel;
-
- char *caption;
- char *corner;
- char *title;
-
- struct ctables_chisq *chisq;
- struct ctables_pairwise *pairwise;
- };
-
-struct ctables_categories
- {
- size_t n_refs;
- struct ctables_category *cats;
- size_t n_cats;
- bool show_empty;
- };
-
-struct ctables_category
- {
- enum ctables_category_type
- {
- /* Explicit category lists. */
- CCT_NUMBER,
- CCT_STRING,
- CCT_NRANGE, /* Numerical range. */
- CCT_SRANGE, /* String range. */
- CCT_MISSING,
- CCT_OTHERNM,
- CCT_POSTCOMPUTE,
-
- /* Totals and subtotals. */
- CCT_SUBTOTAL,
- CCT_TOTAL,
-
- /* Implicit category lists. */
- CCT_VALUE,
- CCT_LABEL,
- CCT_FUNCTION,
-
- /* For contributing to TOTALN. */
- CCT_EXCLUDED_MISSING,
- }
- type;
-
- struct ctables_category *subtotal;
-
- bool hide;
-
- union
- {
- double number; /* CCT_NUMBER. */
- struct substring string; /* CCT_STRING, in dictionary encoding. */
- double nrange[2]; /* CCT_NRANGE. */
- struct substring srange[2]; /* CCT_SRANGE. */
-
- struct
- {
- char *total_label; /* CCT_SUBTOTAL, CCT_TOTAL. */
- bool hide_subcategories; /* CCT_SUBTOTAL. */
- };
-
- /* CCT_POSTCOMPUTE. */
- struct
- {
- const struct ctables_postcompute *pc;
- enum fmt_type parse_format;
- };
-
- /* CCT_VALUE, CCT_LABEL, CCT_FUNCTION. */
- struct
- {
- bool include_missing;
- bool sort_ascending;
-
- /* CCT_FUNCTION. */
- enum ctables_summary_function sort_function;
- bool weighted;
- enum ctables_area_type area;
- struct variable *sort_var;
- double percentile;
- };
- };
-
- /* Source location. This is null for CCT_TOTAL, CCT_VALUE, CCT_LABEL,
- CCT_FUNCTION, CCT_EXCLUDED_MISSING. */
- struct msg_location *location;
- };
-
-static void
-ctables_category_uninit (struct ctables_category *cat)
-{
- if (!cat)
- return;
-
- msg_location_destroy (cat->location);
- switch (cat->type)
- {
- case CCT_NUMBER:
- case CCT_NRANGE:
- case CCT_MISSING:
- case CCT_OTHERNM:
- case CCT_POSTCOMPUTE:
- break;
-
- case CCT_STRING:
- ss_dealloc (&cat->string);
- break;
-
- case CCT_SRANGE:
- ss_dealloc (&cat->srange[0]);
- ss_dealloc (&cat->srange[1]);
- break;
-
- case CCT_SUBTOTAL:
- case CCT_TOTAL:
- free (cat->total_label);
- break;
-
- case CCT_VALUE:
- case CCT_LABEL:
- case CCT_FUNCTION:
- break;
-
- case CCT_EXCLUDED_MISSING:
- break;
- }
-}
-
-static bool
-nullable_substring_equal (const struct substring *a,
- const struct substring *b)
-{
- return !a->string ? !b->string : b->string && ss_equals (*a, *b);