#include <stdlib.h>
#include "data/data-out.h"
+#include "data/dictionary.h"
#include "data/settings.h"
#include "data/value.h"
#include "data/variable.h"
struct pivot_table *
pivot_table_create__ (struct pivot_value *title, const char *subtype)
{
- struct pivot_table *table = XZALLOC (struct pivot_table);
- table->ref_cnt = 1;
- table->show_title = true;
- table->show_caption = true;
- table->weight_format = (struct fmt_spec) { .type = FMT_F, .w = 40 };
- table->title = title;
- table->subtype = subtype ? pivot_value_new_text (subtype) : NULL;
- table->command_c = xstrdup_if_nonempty (output_get_command_name ());
- table->look = pivot_table_look_ref (pivot_table_look_get_default ());
- table->settings = fmt_settings_copy (settings_get_fmt_settings ());
- table->small = settings_get_small ();
-
- hmap_init (&table->cells);
-
+ struct pivot_table *table = xmalloc (sizeof *table);
+ *table = (struct pivot_table) {
+ .ref_cnt = 1,
+ .show_title = true,
+ .show_caption = true,
+ .weight_format = (struct fmt_spec) { .type = FMT_F, .w = 40 },
+ .title = title,
+ .subtype = subtype ? pivot_value_new_text (subtype) : NULL,
+ .command_c = xstrdup_if_nonempty (output_get_command_name ()),
+ .look = pivot_table_look_ref (pivot_table_look_get_default ()),
+ .settings = fmt_settings_copy (settings_get_fmt_settings ()),
+ .small = settings_get_small (),
+ .cells = HMAP_INITIALIZER (table->cells),
+ };
return table;
}
return table->ref_cnt > 1;
}
+static void
+pivot_table_set_value__ (struct pivot_value **dstp, struct pivot_value *src)
+{
+ pivot_value_destroy (*dstp);
+ *dstp = src;
+}
+
+/* Changes the title of TABLE to TITLE. Takes ownership of TITLE. */
+void
+pivot_table_set_title (struct pivot_table *table, struct pivot_value *title)
+{
+ pivot_table_set_value__ (&table->title, title);
+}
+
+/* Changes the subtype of TABLE to SUBTYPE. Takes ownership of SUBTYPE. */
+void
+pivot_table_set_subtype (struct pivot_table *table, struct pivot_value *subtype)
+{
+ pivot_table_set_value__ (&table->subtype, subtype);
+}
+
+/* Changes the corner text of TABLE to CORNER_TEXT. Takes ownership of
+ CORNER_TEXT. */
+void
+pivot_table_set_corner_text (struct pivot_table *table,
+ struct pivot_value *corner_text)
+{
+ pivot_table_set_value__ (&table->corner_text, corner_text);
+}
+
+/* Changes the caption of TABLE to CAPTION. Takes ownership of CAPTION. */
+void
+pivot_table_set_caption (struct pivot_table *table, struct pivot_value *caption)
+{
+ pivot_table_set_value__ (&table->caption, caption);
+}
+
/* Swaps axes A and B in TABLE. */
void
pivot_table_swap_axes (struct pivot_table *table,
}
/* Puts VALUE in the cell in TABLE whose indexes are given by the N indexes in
- DINDEXES. N must be the number of dimensions in TABLE. Takes ownership of
- VALUE.
+ DINDEXES. The order of the indexes is the same as the order in which the
+ dimensions were created. N must be the number of dimensions in TABLE.
+ Takes ownership of VALUE.
If VALUE is a numeric value without a specified format, this function checks
each of the categories designated by DINDEXES[] and takes the format from
that pivot_value_new_variable() should be used for variable names). For
strings that are part of the PSPP user interface, such as names of
procedures, statistics, annotations, error messages, etc., use
- pivot_value_new_text().j
+ pivot_value_new_text().
- The caller retains ownership of TEXT.*/
+ The caller retains ownership of TEXT. */
struct pivot_value *
pivot_value_new_user_text (const char *text, size_t length)
{
}
/* Same as pivot_value_new_text() but its argument is a printf()-like format
- string. */
+ string. The format string should generally be enclosed in N_(). */
struct pivot_value * PRINTF_FORMAT (1, 2)
pivot_value_new_text_format (const char *format, ...)
{
free (ex);
}
}
+\f
+/* pivot_splits */
+
+struct pivot_splits_value
+ {
+ struct hmap_node hmap_node;
+ union value value;
+ int leaf;
+ };
+
+struct pivot_splits_var
+ {
+ struct pivot_dimension *dimension;
+ int width;
+ size_t idx;
+ struct fmt_spec format;
+ struct hmap values;
+ };
+
+struct pivot_splits
+ {
+ struct pivot_splits_var *vars;
+ size_t n;
+ char *encoding;
+
+ size_t dindexes[MAX_SPLITS];
+ };
+
+struct pivot_splits *
+pivot_splits_create (struct pivot_table *pt,
+ enum pivot_axis_type axis,
+ const struct dictionary *dict)
+{
+ if (dict_get_split_type (dict) != SPLIT_LAYERED)
+ return NULL;
+
+ size_t n = dict_get_n_splits (dict);
+ assert (n <= MAX_SPLITS);
+
+ const struct variable *const *vars = dict_get_split_vars (dict);
+ struct pivot_splits_var *psvars = xnmalloc (n, sizeof *psvars);
+ for (size_t i = 0; i < n; i++)
+ {
+ const struct variable *var = vars[i];
+ struct pivot_splits_var *psvar = &psvars[i];
+
+ struct pivot_dimension *d = pivot_dimension_create__ (
+ pt, axis, pivot_value_new_variable (var));
+ d->root->show_label = true;
+
+ *psvar = (struct pivot_splits_var) {
+ .width = var_get_width (var),
+ .idx = var_get_case_index (var),
+ .format = *var_get_print_format (var),
+ .values = HMAP_INITIALIZER (psvar->values),
+ .dimension = d,
+ };
+ }
+
+ struct pivot_splits *ps = xmalloc (sizeof *ps);
+ *ps = (struct pivot_splits) {
+ .vars = psvars,
+ .n = n,
+ .encoding = xstrdup (dict_get_encoding (dict)),
+ .dindexes = { [0] = SIZE_MAX },
+ };
+ return ps;
+}
+
+void
+pivot_splits_destroy (struct pivot_splits *ps)
+{
+ if (!ps)
+ return;
+
+ for (size_t i = 0; i < ps->n; i++)
+ {
+ struct pivot_splits_var *psvar = &ps->vars[i];
+ struct pivot_splits_value *psval, *next;
+ HMAP_FOR_EACH_SAFE (psval, next, struct pivot_splits_value, hmap_node,
+ &psvar->values)
+ {
+ value_destroy (&psval->value, psvar->width);
+ hmap_delete (&psvar->values, &psval->hmap_node);
+ free (psval);
+ }
+ hmap_destroy (&psvar->values);
+ }
+ free (ps->vars);
+ free (ps->encoding);
+ free (ps);
+}
+
+static struct pivot_splits_value *
+pivot_splits_value_find (struct pivot_splits_var *psvar,
+ const union value *value)
+{
+ struct pivot_splits_value *psval;
+ HMAP_FOR_EACH_WITH_HASH (psval, struct pivot_splits_value, hmap_node,
+ value_hash (value, psvar->width, 0), &psvar->values)
+ if (value_equal (&psval->value, value, psvar->width))
+ return psval;
+ return NULL;
+}
+
+void
+pivot_splits_new_split (struct pivot_splits *ps, const struct ccase *c)
+{
+ if (!ps)
+ return;
+
+ for (size_t i = ps->n - 1; i < ps->n; i--)
+ {
+ struct pivot_splits_var *psvar = &ps->vars[i];
+ const union value *value = case_data_idx (c, psvar->idx);
+ struct pivot_splits_value *psval = pivot_splits_value_find (psvar, value);
+ if (!psval)
+ {
+ psval = xmalloc (sizeof *psval);
+ hmap_insert (&psvar->values, &psval->hmap_node,
+ value_hash (value, psvar->width, 0));
+ value_clone (&psval->value, value, psvar->width);
+ psval->leaf = pivot_category_create_leaf (
+ psvar->dimension->root,
+ pivot_value_new_value (value, psvar->width, &psvar->format,
+ ps->encoding));
+ }
+
+ ps->dindexes[i] = psval->leaf;
+ }
+}
+
+size_t
+pivot_splits_get_dindexes (const struct pivot_splits *ps, size_t *dindexes)
+{
+ if (!ps)
+ return 0;
+
+ assert (ps->dindexes[0] != SIZE_MAX);
+ for (size_t i = 0; i < ps->n; i++)
+ dindexes[i] = ps->dindexes[i];
+ return ps->n;
+}
+
+void
+pivot_splits_put1 (struct pivot_splits *ps, struct pivot_table *table,
+ size_t idx1, struct pivot_value *value)
+{
+ size_t dindexes[1 + MAX_SPLITS];
+ size_t *p = dindexes;
+ *p++ = idx1;
+ p += pivot_splits_get_dindexes (ps, p);
+ pivot_table_put (table, dindexes, p - dindexes, value);
+}
+
+void
+pivot_splits_put2 (struct pivot_splits *ps, struct pivot_table *table,
+ size_t idx1, size_t idx2, struct pivot_value *value)
+{
+ size_t dindexes[2 + MAX_SPLITS];
+ size_t *p = dindexes;
+ *p++ = idx1;
+ *p++ = idx2;
+ p += pivot_splits_get_dindexes (ps, p);
+ pivot_table_put (table, dindexes, p - dindexes, value);
+}
+
+void
+pivot_splits_put3 (struct pivot_splits *ps, struct pivot_table *table,
+ size_t idx1, size_t idx2, size_t idx3,
+ struct pivot_value *value)
+{
+ size_t dindexes[3 + MAX_SPLITS];
+ size_t *p = dindexes;
+ *p++ = idx1;
+ *p++ = idx2;
+ *p++ = idx3;
+ p += pivot_splits_get_dindexes (ps, p);
+ pivot_table_put (table, dindexes, p - dindexes, value);
+}
+
+void
+pivot_splits_put4 (struct pivot_splits *ps, struct pivot_table *table,
+ size_t idx1, size_t idx2, size_t idx3, size_t idx4,
+ struct pivot_value *value)
+{
+ size_t dindexes[4 + MAX_SPLITS];
+ size_t *p = dindexes;
+ *p++ = idx1;
+ *p++ = idx2;
+ *p++ = idx3;
+ *p++ = idx4;
+ p += pivot_splits_get_dindexes (ps, p);
+ pivot_table_put (table, dindexes, p - dindexes, value);
+}