pivot-table: Add some more utility functions for pivot data structures.
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 1 Jan 2021 06:21:48 +0000 (22:21 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 2 Jan 2021 03:23:40 +0000 (19:23 -0800)
src/output/pivot-table.c
src/output/pivot-table.h

index 6029224734bdbc992f8f24ca948474b2654dcb2a..3bd0911b46e7adec6bbd8cda843f3c6d9a060360 100644 (file)
@@ -25,6 +25,7 @@
 #include "data/value.h"
 #include "data/variable.h"
 #include "data/file-name.h"
+#include "libpspp/assertion.h"
 #include "libpspp/hash-functions.h"
 #include "libpspp/i18n.h"
 #include "output/driver.h"
@@ -796,6 +797,12 @@ pivot_result_class_change (const char *s_, const struct fmt_spec *format)
 
   return rc != NULL;
 }
+
+bool
+is_pivot_result_class (const char *s)
+{
+  return pivot_result_class_find (s) != NULL;
+}
 \f
 /* Pivot tables. */
 
@@ -2039,6 +2046,78 @@ pivot_value_to_string (const struct pivot_value *value,
   return ds_steal_cstr (&s);
 }
 
+static char *
+xstrdup_if_nonnull (const char *s)
+{
+  return s ? xstrdup (s) : NULL;
+}
+
+struct pivot_value *
+pivot_value_clone (const struct pivot_value *old)
+{
+  struct pivot_value *new = xmemdup (old, sizeof *new);
+  if (old->font_style)
+    {
+      new->font_style = xmalloc (sizeof *new->font_style);
+      font_style_copy (NULL, new->font_style, old->font_style);
+    }
+  if (old->cell_style)
+    new->font_style = xmemdup (old->font_style, sizeof *new->font_style);
+  if (old->n_subscripts)
+    {
+      new->subscripts = xnmalloc (old->n_subscripts, sizeof *new->subscripts);
+      for (size_t i = 0; i < old->n_subscripts; i++)
+        new->subscripts[i] = xstrdup (old->subscripts[i]);
+    }
+  if (old->n_footnotes)
+    new->footnotes = xmemdup (old->footnotes,
+                              old->n_footnotes * sizeof *new->footnotes);
+
+  switch (new->type)
+    {
+    case PIVOT_VALUE_NUMERIC:
+      new->numeric.var_name = xstrdup_if_nonnull (new->numeric.var_name);
+      new->numeric.value_label = xstrdup_if_nonnull (new->numeric.value_label);
+      break;
+
+    case PIVOT_VALUE_STRING:
+      new->string.s = xstrdup (new->string.s);
+      new->string.var_name = xstrdup_if_nonnull (new->string.var_name);
+      new->string.value_label = xstrdup_if_nonnull (new->string.value_label);
+      break;
+
+    case PIVOT_VALUE_VARIABLE:
+      new->variable.var_name = xstrdup_if_nonnull (new->variable.var_name);
+      new->variable.var_label = xstrdup_if_nonnull (new->variable.var_label);
+      break;
+
+    case PIVOT_VALUE_TEXT:
+      new->text.local = xstrdup (old->text.local);
+      new->text.c = (old->text.c == old->text.local ? new->text.local
+                     : xstrdup (old->text.c));
+      new->text.id = (old->text.id == old->text.local ? new->text.local
+                      : old->text.id == old->text.c ? new->text.c
+                      : xstrdup (old->text.id));
+      break;
+
+    case PIVOT_VALUE_TEMPLATE:
+      new->template.local = xstrdup (old->template.local);
+      new->template.id = (old->template.id == old->template.local
+                          ? new->template.local
+                          : xstrdup (old->template.id));
+      new->template.args = xmalloc (new->template.n_args
+                                    * sizeof *new->template.args);
+      for (size_t i = 0; i < old->template.n_args; i++)
+        pivot_argument_copy (&new->template.args[i],
+                             &old->template.args[i]);
+      break;
+
+    default:
+      NOT_REACHED ();
+    }
+  return new;
+}
+
 /* Frees the data owned by V. */
 void
 pivot_value_destroy (struct pivot_value *value)
@@ -2091,6 +2170,9 @@ pivot_value_destroy (struct pivot_value *value)
             pivot_argument_uninit (&value->template.args[i]);
           free (value->template.args);
           break;
+
+        default:
+          NOT_REACHED ();
         }
       free (value);
     }
@@ -2116,16 +2198,42 @@ pivot_value_get_style (struct pivot_value *value,
 void
 pivot_value_set_style (struct pivot_value *value,
                        const struct table_area_style *area)
+{
+  pivot_value_set_font_style (value, &area->font_style);
+  pivot_value_set_cell_style (value, &area->cell_style);
+}
+
+void
+pivot_value_set_font_style (struct pivot_value *value,
+                            const struct font_style *font_style)
 {
   if (value->font_style)
     font_style_uninit (value->font_style);
   else
     value->font_style = xmalloc (sizeof *value->font_style);
-  font_style_copy (NULL, value->font_style, &area->font_style);
+  font_style_copy (NULL, value->font_style, font_style);
+}
 
+void
+pivot_value_set_cell_style (struct pivot_value *value,
+                            const struct cell_style *cell_style)
+{
   if (!value->cell_style)
     value->cell_style = xmalloc (sizeof *value->cell_style);
-  *value->cell_style = area->cell_style;
+  *value->cell_style = *cell_style;
+}
+
+void
+pivot_argument_copy (struct pivot_argument *dst,
+                     const struct pivot_argument *src)
+{
+  *dst = (struct pivot_argument) {
+    .n = src->n,
+    .values = xmalloc (src->n * sizeof *dst->values),
+  };
+
+  for (size_t i = 0; i < src->n; i++)
+    dst->values[i] = pivot_value_clone (src->values[i]);
 }
 
 /* Frees the data owned by ARG (but not ARG itself). */
index 56ca865a2d3e4eac589b36b56e5ab1bdb2117d57..a70033bf3f29fd7e0b2cc82941b168ad09ebef07 100644 (file)
@@ -361,6 +361,7 @@ void pivot_category_destroy (struct pivot_category *);
 #define PIVOT_RC_COUNT ("RC_COUNT")
 
 bool pivot_result_class_change (const char *, const struct fmt_spec *);
+bool is_pivot_result_class (const char *);
 \f
 /* Styling for a pivot table.
 
@@ -694,6 +695,10 @@ struct pivot_value
       };
   };
 
+/* Life cycle. */
+struct pivot_value *pivot_value_clone (const struct pivot_value *);
+void pivot_value_destroy (struct pivot_value *);
+
 /* Numbers resulting from calculations. */
 struct pivot_value *pivot_value_new_number (double);
 struct pivot_value *pivot_value_new_integer (double);
@@ -740,8 +745,6 @@ bool pivot_value_format_body (const struct pivot_value *,
                               enum settings_value_show show_variables,
                               struct string *);
 
-void pivot_value_destroy (struct pivot_value *);
-
 /* Styling. */
 void pivot_value_get_style (struct pivot_value *,
                             const struct font_style *base_font_style,
@@ -749,6 +752,10 @@ void pivot_value_get_style (struct pivot_value *,
                             struct table_area_style *);
 void pivot_value_set_style (struct pivot_value *,
                             const struct table_area_style *);
+void pivot_value_set_font_style (struct pivot_value *,
+                                 const struct font_style *);
+void pivot_value_set_cell_style (struct pivot_value *,
+                                 const struct cell_style *);
 
 /* Template arguments. */
 struct pivot_argument
@@ -758,6 +765,8 @@ struct pivot_argument
   };
 
 void pivot_argument_uninit (struct pivot_argument *);
+void pivot_argument_copy (struct pivot_argument *,
+                          const struct pivot_argument *);
 \f
 /* One piece of data within a pivot table. */
 struct pivot_cell