hmap_delete (&ct->postcomputes, &pc->hmap_node);
free (pc);
}
+ hmap_destroy (&ct->postcomputes);
fmt_settings_uninit (&ct->ctables_formats);
pivot_table_look_unref (ct->look);
return strcmp (as_label, bs_label);
}
-static struct pivot_value *
-ctables_category_create_label__ (const struct ctables_category *cat,
- const struct variable *var,
- const union value *value)
+static void
+ctables_category_format_number (double number, const struct variable *var,
+ struct string *s)
{
- return (cat->type == CCT_TOTAL || cat->type == CCT_SUBTOTAL
- ? pivot_value_new_user_text (cat->total_label, SIZE_MAX)
- : pivot_value_new_var_value (var, value));
+ struct pivot_value *pv = pivot_value_new_var_value (
+ var, &(union value) { .f = number });
+ pivot_value_format (pv, NULL, s);
+ pivot_value_destroy (pv);
+}
+
+static void
+ctables_category_format_string (struct substring string,
+ const struct variable *var, struct string *out)
+{
+ int width = var_get_width (var);
+ char *s = xmalloc (width);
+ buf_copy_rpad (s, width, string.string, string.length, ' ');
+ struct pivot_value *pv = pivot_value_new_var_value (
+ var, &(union value) { .s = CHAR_CAST (uint8_t *, s) });
+ pivot_value_format (pv, NULL, out);
+ pivot_value_destroy (pv);
+ free (s);
+}
+
+static bool
+ctables_category_format_label (const struct ctables_category *cat,
+ const struct variable *var,
+ struct string *s)
+{
+ switch (cat->type)
+ {
+ case CCT_NUMBER:
+ ctables_category_format_number (cat->number, var, s);
+ return true;
+
+ case CCT_STRING:
+ ctables_category_format_string (cat->string, var, s);
+ return true;
+
+ case CCT_NRANGE:
+ ctables_category_format_number (cat->nrange[0], var, s);
+ ds_put_format (s, " THRU ");
+ ctables_category_format_number (cat->nrange[1], var, s);
+ return true;
+
+ case CCT_SRANGE:
+ ctables_category_format_string (cat->srange[0], var, s);
+ ds_put_format (s, " THRU ");
+ ctables_category_format_string (cat->srange[1], var, s);
+ return true;
+
+ case CCT_MISSING:
+ ds_put_cstr (s, "MISSING");
+ return true;
+
+ case CCT_OTHERNM:
+ ds_put_cstr (s, "OTHERNM");
+ return true;
+
+ case CCT_POSTCOMPUTE:
+ ds_put_format (s, "&%s", cat->pc->name);
+ return true;
+
+ case CCT_TOTAL:
+ case CCT_SUBTOTAL:
+ ds_put_cstr (s, cat->total_label);
+ return true;
+
+ case CCT_VALUE:
+ case CCT_LABEL:
+ case CCT_FUNCTION:
+ case CCT_EXCLUDED_MISSING:
+ return false;
+ }
+
+ return false;
}
static struct pivot_value *
ctables_postcompute_label (const struct ctables_categories *cats,
const struct ctables_category *cat,
- const struct variable *var,
- const union value *value)
+ const struct variable *var)
{
struct substring in = ss_cstr (cat->pc->label);
struct substring target = ss_cstr (")LABEL[");
goto error;
struct ctables_category *cat2 = &cats->cats[idx - 1];
- struct pivot_value *label2
- = ctables_category_create_label__ (cat2, var, value);
- char *label2_s = pivot_value_to_string_defaults (label2);
- ds_put_cstr (&out, label2_s);
- free (label2_s);
- pivot_value_destroy (label2);
+ if (!ctables_category_format_label (cat2, var, &out))
+ goto error;
}
error:
}
static struct pivot_value *
-ctables_category_create_label (const struct ctables_categories *cats,
- const struct ctables_category *cat,
- const struct variable *var,
- const union value *value)
+ctables_category_create_value_label (const struct ctables_categories *cats,
+ const struct ctables_category *cat,
+ const struct variable *var,
+ const union value *value)
{
return (cat->type == CCT_POSTCOMPUTE && cat->pc->label
- ? ctables_postcompute_label (cats, cat, var, value)
- : ctables_category_create_label__ (cat, var, value));
+ ? ctables_postcompute_label (cats, cat, var)
+ : cat->type == CCT_TOTAL || cat->type == CCT_SUBTOTAL
+ ? pivot_value_new_user_text (cat->total_label, SIZE_MAX)
+ : pivot_value_new_var_value (var, value));
}
static struct ctables_value *
case CTPO_CAT_NRANGE:
case CTPO_CAT_SRANGE:
+ case CTPO_CAT_MISSING:
+ case CTPO_CAT_OTHERNM:
{
struct ctables_cell_value cv = {
.category = ctables_find_category_for_postcompute (ctx->section->table->ctables->dict, ctx->cats, ctx->parse_format, e)
}
case CTPO_CAT_NUMBER:
- case CTPO_CAT_MISSING:
- case CTPO_CAT_OTHERNM:
case CTPO_CAT_SUBTOTAL:
case CTPO_CAT_TOTAL:
{
s = xmalloc (width);
buf_copy_rpad (s, width, e->string.string, e->string.length, ' ');
}
- struct ctables_cell_value cv = {
- .category = ctables_find_category_for_postcompute (ctx->section->table->ctables->dict, ctx->cats, ctx->parse_format, e),
- .value = { .s = CHAR_CAST (uint8_t *, s ? s : e->string.string) },
- };
- assert (cv.category != NULL);
+
+ const struct ctables_category *category
+ = ctables_find_category_for_postcompute (
+ ctx->section->table->ctables->dict,
+ ctx->cats, ctx->parse_format, e);
+ assert (category != NULL);
+
+ struct ctables_cell_value cv = { .category = category };
+ if (category->type == CCT_NUMBER)
+ cv.value.f = category->number;
+ else if (category->type == CCT_STRING)
+ cv.value.s = CHAR_CAST (uint8_t *, s ? s : e->string.string);
+ else
+ NOT_REACHED ();
+
double retval = ctables_pcexpr_evaluate_category (ctx, &cv);
free (s);
return retval;
return s;
}
+static bool
+all_hidden_vlabels (const struct ctables_table *t, enum pivot_axis_type a)
+{
+ for (size_t i = 0; i < t->stacks[a].n; i++)
+ {
+ struct ctables_nest *nest = &t->stacks[a].nests[i];
+ if (nest->n != 1 || nest->scale_idx != 0)
+ return false;
+
+ enum ctables_vlabel vlabel
+ = t->ctables->vlabels[var_get_dict_index (nest->vars[0])];
+ if (vlabel != CTVL_NONE)
+ return false;
+ }
+ return true;
+}
+
static void
ctables_table_output (struct ctables *ct, struct ctables_table *t)
{
const struct ctables_value *value = t->clabels_values[i];
const struct ctables_category *cat = ctables_categories_match (c, &value->value, var);
assert (cat != NULL);
- pivot_category_create_leaf (d->root, ctables_category_create_label (
- c, cat, t->clabels_example,
- &value->value));
+ pivot_category_create_leaf (
+ d->root, ctables_category_create_value_label (c, cat,
+ t->clabels_example,
+ &value->value));
}
}
for (size_t k = 0; k < nest->n; k++)
{
enum ctables_vlabel vlabel = ct->vlabels[var_get_dict_index (nest->vars[k])];
+ if (vlabel == CTVL_NONE && nest->scale_idx == k)
+ vlabel = CTVL_NAME;
if (vlabel != CTVL_NONE)
{
levels[n_levels++] = (struct ctables_level) {
else if (level->type == CTL_CATEGORY)
{
const struct ctables_cell_value *cv = &cell->axes[a].cvs[level->var_idx];
- label = ctables_category_create_label (
+ label = ctables_category_create_value_label (
t->categories[var_get_dict_index (var)],
cv->category, var, &cv->value);
}
free (groups);
free (levels);
free (sections);
+
}
+
+ d[a]->hide_all_labels = all_hidden_vlabels (t, a);
}
{
}
struct dictionary *dict = dataset_dict (ds);
+
+ bool splitting = dict_get_split_type (dict) == SPLIT_SEPARATE;
struct casegrouper *grouper
- = (dict_get_split_type (dict) == SPLIT_SEPARATE
+ = (splitting
? casegrouper_create_splits (input, dict)
: casegrouper_create_vars (input, NULL, 0));
struct casereader *group;
while (casegrouper_get_next_group (grouper, &group))
{
- /* Output SPLIT FILE variables. */
- struct ccase *c = casereader_peek (group, 0);
- if (c != NULL)
+ if (splitting)
{
- output_split_file_values (ds, c);
- case_unref (c);
+ struct ccase *c = casereader_peek (group, 0);
+ if (c != NULL)
+ {
+ output_split_file_values (ds, c);
+ case_unref (c);
+ }
}
bool warn_on_invalid = true;
- for (c = casereader_read (group); c;
+ for (struct ccase *c = casereader_read (group); c;
case_unref (c), c = casereader_read (group))
{
double d_weight = dict_get_case_weight (dict, c, &warn_on_invalid);