pivot-table: Reduce size of struct pivot_value from 80 bytes to 40.
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 9 Mar 2021 02:18:48 +0000 (18:18 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 9 Mar 2021 02:18:48 +0000 (18:18 -0800)
14 files changed:
src/output/cairo-fsm.c
src/output/html.c
src/output/odt.c
src/output/output-item.c
src/output/pivot-output.c
src/output/pivot-table.c
src/output/pivot-table.h
src/output/spv/spv-legacy-decoder.c
src/output/spv/spv-light-decoder.c
src/output/spv/spv-writer.c
src/output/spv/spv.c
src/output/table.c
src/output/tex.c
tests/output/pivot-table-test.c

index d71f4d0b02f5dc76ded9d5343d0462f06cea299c..bedf3147ea281d4cba8ccd1c3b579cc052eb5844 100644 (file)
@@ -742,23 +742,23 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
                                 PANGO_UNDERLINE_SINGLE));
     }
 
-  const struct pivot_value *value = cell->value;
-  if (value->n_footnotes || value->n_subscripts)
+  const struct pivot_value_ex *ex = pivot_value_ex (cell->value);
+  if (ex->n_footnotes || ex->n_subscripts)
     {
       size_t subscript_ofs = ds_length (&body);
-      for (size_t i = 0; i < value->n_subscripts; i++)
+      for (size_t i = 0; i < ex->n_subscripts; i++)
         {
           if (i)
             ds_put_byte (&body, ',');
-          ds_put_cstr (&body, value->subscripts[i]);
+          ds_put_cstr (&body, ex->subscripts[i]);
         }
 
       size_t footnote_ofs = ds_length (&body);
       size_t n_footnotes = 0;
-      for (size_t i = 0; i < value->n_footnotes; i++)
+      for (size_t i = 0; i < ex->n_footnotes; i++)
         {
           const struct pivot_footnote *f
-            = pt->footnotes[value->footnote_indexes[i]];
+            = pt->footnotes[ex->footnote_indexes[i]];
           if (f->show)
             {
               if (n_footnotes++)
@@ -769,7 +769,7 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
 
       /* Allow footnote markers to occupy the right margin.  That way, numbers
          in the column are still aligned. */
-      if (value->n_footnotes && halign == TABLE_HALIGN_RIGHT)
+      if (ex->n_footnotes && halign == TABLE_HALIGN_RIGHT)
         {
           /* Measure the width of the footnote marker, so we know how much we
              need to make room for. */
@@ -804,10 +804,10 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
                 PANGO_ATTR_INDEX_TO_TEXT_END);
       add_attr (attrs, pango_attr_scale_new (PANGO_SCALE_SMALL),
                 subscript_ofs, PANGO_ATTR_INDEX_TO_TEXT_END);
-      if (value->n_subscripts)
+      if (ex->n_subscripts)
         add_attr (attrs, pango_attr_rise_new (-3000), subscript_ofs,
                   footnote_ofs - subscript_ofs);
-      if (value->n_footnotes)
+      if (ex->n_footnotes)
         {
           bool superscript = pt->look->footnote_marker_superscripts;
           add_attr (attrs, pango_attr_rise_new (superscript ? 3000 : -3000),
index cbb8e90c6e852d61a760b66d3e9c4605e3bf1036..60ca95e28dba029683e895dad42e0a7aac91c2a1 100644 (file)
@@ -587,26 +587,26 @@ html_put_table_cell (struct html_driver *html, const struct pivot_table *pt,
   escape_string (html->file, s, " ", "<br>");
   ds_destroy (&body);
 
-  if (cell->value->n_subscripts)
+  const struct pivot_value_ex *ex = pivot_value_ex (cell->value);
+  if (ex->n_subscripts)
     {
       fputs ("<sub>", html->file);
-      for (size_t i = 0; i < cell->value->n_subscripts; i++)
+      for (size_t i = 0; i < ex->n_subscripts; i++)
         {
           if (i)
             putc (',', html->file);
-          escape_string (html->file, cell->value->subscripts[i],
-                         "&nbsp;", "<br>");
+          escape_string (html->file, ex->subscripts[i], "&nbsp;", "<br>");
         }
       fputs ("</sub>", html->file);
     }
-  if (cell->value->n_footnotes > 0)
+  if (ex->n_footnotes > 0)
     {
       fputs ("<sup>", html->file);
       size_t n_footnotes = 0;
-      for (size_t i = 0; i < cell->value->n_footnotes; i++)
+      for (size_t i = 0; i < ex->n_footnotes; i++)
         {
           const struct pivot_footnote *f
-            = pt->footnotes[cell->value->footnote_indexes[i]];
+            = pt->footnotes[ex->footnote_indexes[i]];
           if (f->show)
             {
               if (n_footnotes++ > 0)
index ed70ecbb4cf447dfd4ec8d27d254aaf64e1aad7f..9fadc5d26ac600905a53fa4d9582454b50763dee 100644 (file)
@@ -446,8 +446,8 @@ write_table_item_cell (struct odt_driver *odt,
   xmlTextWriterWriteString (odt->content_wtr, _xml (ds_cstr (&body)));
   ds_destroy (&body);
 
-  write_footnotes (odt, pt, cell->value->footnote_indexes,
-                   cell->value->n_footnotes);
+  const struct pivot_value_ex *ex = pivot_value_ex (cell->value);
+  write_footnotes (odt, pt, ex->footnote_indexes, ex->n_footnotes);
 }
 
 static void
index a46fdf8020b9c904641c78328e30b3d7f3cef966..25cffe460090d9e05cb30a5610f737c64ba18054 100644 (file)
@@ -586,14 +586,15 @@ text_item_create_value (enum text_item_subtype subtype,
 {
   if (subtype == TEXT_ITEM_SYNTAX || subtype == TEXT_ITEM_LOG)
     {
-      if (!value->font_style)
+      struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+      if (!ex->font_style)
         {
-          value->font_style = xmalloc (sizeof *value->font_style);
-          *value->font_style = (struct font_style) FONT_STYLE_INITIALIZER;
+          ex->font_style = xmalloc (sizeof *value->ex->font_style);
+          *ex->font_style = (struct font_style) FONT_STYLE_INITIALIZER;
         }
 
-      free (value->font_style->typeface);
-      value->font_style->typeface = xstrdup ("Monospaced");
+      free (ex->font_style->typeface);
+      ex->font_style->typeface = xstrdup ("Monospaced");
     }
 
   struct output_item *item = xzalloc (sizeof *item);
@@ -652,8 +653,9 @@ text_item_append (struct output_item *dst, const struct output_item *src)
   if (ds != ss
       || (ds != TEXT_ITEM_SYNTAX && ds != TEXT_ITEM_LOG)
       || strcmp (output_item_get_label (dst), output_item_get_label (src))
-      || !nullable_font_style_equal (dc->font_style, sc->font_style)
-      || (dc->font_style && dc->font_style->markup)
+      || !nullable_font_style_equal (dc->ex ? dc->ex->font_style : NULL,
+                                     sc->ex ? sc->ex->font_style : NULL)
+      || (dc->ex && dc->ex->font_style && dc->ex->font_style->markup)
       || sc->type != PIVOT_VALUE_TEXT
       || dc->type != PIVOT_VALUE_TEXT)
     return false;
index 2fa664bffadd6f1616be3716802d85ea9e00cc1b..a170b6ee71a79e670c72c98fef1bda01c9e97b5a 100644 (file)
@@ -394,9 +394,10 @@ add_references (const struct pivot_table *pt, const struct table *table,
 
         if (x == cell.d[H][0] && y == cell.d[V][0])
           {
-            for (size_t i = 0; i < cell.value->n_footnotes; i++)
+            const struct pivot_value_ex *ex = pivot_value_ex (cell.value);
+            for (size_t i = 0; i < ex->n_footnotes; i++)
               {
-                size_t idx = cell.value->footnote_indexes[i];
+                size_t idx = ex->footnote_indexes[i];
                 assert (idx < pt->n_footnotes);
 
                 if (!refs[idx] && pt->footnotes[idx]->show)
index ad146a58ba1bdf4baccb03b79b5dd3f5a9a7f795..831440772148c916c21f1b32a27dc20cc98be912 100644 (file)
@@ -2411,7 +2411,7 @@ pivot_value_format_body (const struct pivot_value *value,
       break;
 
     case PIVOT_VALUE_TEXT:
-      if (value->font_style && value->font_style->markup)
+      if (value->ex && value->ex->font_style && value->ex->font_style->markup)
         get_text_from_markup (value->text.local, out);
       else
         ds_put_cstr (out, value->text.local);
@@ -2440,21 +2440,25 @@ pivot_value_format (const struct pivot_value *value,
 {
   bool numeric = pivot_value_format_body (value, pt, out);
 
-  if (value->n_subscripts)
+  const struct pivot_value_ex *ex = value->ex;
+  if (ex)
     {
-      for (size_t i = 0; i < value->n_subscripts; i++)
-        ds_put_format (out, "%c%s", i ? ',' : '_', value->subscripts[i]);
-    }
+      if (ex->n_subscripts)
+        {
+          for (size_t i = 0; i < ex->n_subscripts; i++)
+            ds_put_format (out, "%c%s", i ? ',' : '_', ex->subscripts[i]);
+        }
 
-  for (size_t i = 0; i < value->n_footnotes; i++)
-    {
-      ds_put_byte (out, '[');
+      for (size_t i = 0; i < ex->n_footnotes; i++)
+        {
+          ds_put_byte (out, '[');
 
-      size_t idx = value->footnote_indexes[i];
-      const struct pivot_footnote *f = pt->footnotes[idx];
-      pivot_footnote_format_marker (f, pt, out);
+          size_t idx = ex->footnote_indexes[i];
+          const struct pivot_footnote *f = pt->footnotes[idx];
+          pivot_footnote_format_marker (f, pt, out);
 
-      ds_put_byte (out, ']');
+          ds_put_byte (out, ']');
+        }
     }
 
   return numeric;
@@ -2489,22 +2493,8 @@ pivot_value_clone (const struct pivot_value *old)
     return NULL;
 
   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->cell_style = xmemdup (old->cell_style, sizeof *new->cell_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->footnote_indexes = xmemdup (
-      old->footnote_indexes, old->n_footnotes * sizeof *new->footnote_indexes);
+  if (old->ex)
+    new->ex = pivot_value_ex_clone (old->ex);
 
   switch (new->type)
     {
@@ -2557,15 +2547,7 @@ pivot_value_destroy (struct pivot_value *value)
 {
   if (value)
     {
-      font_style_uninit (value->font_style);
-      free (value->font_style);
-      free (value->cell_style);
-      free (value->footnote_indexes);
-
-      for (size_t i = 0; i < value->n_subscripts; i++)
-        free (value->subscripts[i]);
-      free (value->subscripts);
-
+      pivot_value_ex_destroy (value->ex);
       switch (value->type)
         {
         case PIVOT_VALUE_NUMERIC:
@@ -2617,12 +2599,10 @@ pivot_value_get_style (struct pivot_value *value,
                        const struct cell_style *base_cell_style,
                        struct table_area_style *area)
 {
-  font_style_copy (NULL, &area->font_style, (value->font_style
-                                             ? value->font_style
-                                             : base_font_style));
-  area->cell_style = *(value->cell_style
-                       ? value->cell_style
-                       : base_cell_style);
+  const struct pivot_value_ex *ex = pivot_value_ex (value);
+  font_style_copy (NULL, &area->font_style,
+                   ex->font_style ? ex->font_style : base_font_style);
+  area->cell_style = *(ex->cell_style ? ex->cell_style : base_cell_style);
 }
 
 /* Copies AREA into VALUE's style. */
@@ -2638,20 +2618,22 @@ 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);
+  struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+  if (ex->font_style)
+    font_style_uninit (ex->font_style);
   else
-    value->font_style = xmalloc (sizeof *value->font_style);
-  font_style_copy (NULL, value->font_style, font_style);
+    ex->font_style = xmalloc (sizeof *ex->font_style);
+  font_style_copy (NULL, ex->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 = *cell_style;
+  struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+  if (!ex->cell_style)
+    ex->cell_style = xmalloc (sizeof *ex->cell_style);
+  *ex->cell_style = *cell_style;
 }
 
 void
@@ -2879,15 +2861,18 @@ void
 pivot_value_add_footnote (struct pivot_value *v,
                           const struct pivot_footnote *footnote)
 {
+  struct pivot_value_ex *ex = pivot_value_ex_rw (v);
+
   /* Some legacy tables include numerous duplicate footnotes.  Suppress
      them. */
-  for (size_t i = 0; i < v->n_footnotes; i++)
-    if (v->footnote_indexes[i] == footnote->idx)
+  for (size_t i = 0; i < ex->n_footnotes; i++)
+    if (ex->footnote_indexes[i] == footnote->idx)
       return;
 
-  v->footnote_indexes = xrealloc (
-    v->footnote_indexes, (v->n_footnotes + 1) * sizeof *v->footnote_indexes);
-  v->footnote_indexes[v->n_footnotes++] = footnote->idx;
+  ex->footnote_indexes = xrealloc (
+    ex->footnote_indexes,
+    (ex->n_footnotes + 1) * sizeof *ex->footnote_indexes);
+  ex->footnote_indexes[ex->n_footnotes++] = footnote->idx;
   pivot_value_sort_footnotes (v);
 }
 
@@ -2908,9 +2893,9 @@ compare_footnote_indexes (const void *a_, const void *b_)
 void
 pivot_value_sort_footnotes (struct pivot_value *v)
 {
-  if (v->n_footnotes > 1)
-    qsort (v->footnote_indexes, v->n_footnotes, sizeof *v->footnote_indexes,
-           compare_footnote_indexes);
+  if (v->ex && v->ex->n_footnotes > 1)
+    qsort (v->ex->footnote_indexes, v->ex->n_footnotes,
+           sizeof *v->ex->footnote_indexes, compare_footnote_indexes);
 }
 
 /* If VALUE is a numeric value, and RC is a result class such as
@@ -2923,4 +2908,65 @@ pivot_value_set_rc (const struct pivot_table *table, struct pivot_value *value,
     pivot_table_use_rc (table, rc,
                         &value->numeric.format, &value->numeric.honor_small);
 }
+\f
+/* pivot_value_ex. */
+
+struct pivot_value_ex *
+pivot_value_ex_rw (struct pivot_value *value)
+{
+  if (!value->ex)
+    value->ex = xzalloc (sizeof *value->ex);
+  return value->ex;
+}
+
+struct pivot_value_ex *
+pivot_value_ex_clone (const struct pivot_value_ex *old)
+{
+  struct font_style *font_style = NULL;
+  if (old->font_style)
+    {
+      font_style = xmalloc (sizeof *font_style);
+      font_style_copy (NULL, font_style, old->font_style);
+    }
 
+  char **subscripts = NULL;
+  if (old->n_subscripts)
+    {
+      subscripts = xnmalloc (old->n_subscripts, sizeof *subscripts);
+      for (size_t i = 0; i < old->n_subscripts; i++)
+        subscripts[i] = xstrdup (old->subscripts[i]);
+    }
+
+  struct pivot_value_ex *new = xmalloc (sizeof *new);
+  *new = (struct pivot_value_ex) {
+    .font_style = font_style,
+    .cell_style = (old->cell_style
+                   ? xmemdup (old->cell_style, sizeof *new->cell_style)
+                   : NULL),
+    .subscripts = subscripts,
+    .n_subscripts = old->n_subscripts,
+    .footnote_indexes = (
+      old->n_footnotes
+      ? xmemdup (old->footnote_indexes,
+                 old->n_footnotes * sizeof *new->footnote_indexes)
+      : NULL),
+    .n_footnotes = old->n_footnotes
+  };
+  return new;
+}
+
+void
+pivot_value_ex_destroy (struct pivot_value_ex *ex)
+{
+  if (ex)
+    {
+      font_style_uninit (ex->font_style);
+      free (ex->font_style);
+      free (ex->cell_style);
+      free (ex->footnote_indexes);
+
+      for (size_t i = 0; i < ex->n_subscripts; i++)
+        free (ex->subscripts[i]);
+      free (ex->subscripts);
+    }
+}
index 0d6e333b06a82861350d56537c17f4dff2c9e266..eb7832542859d7f86b415822ef52e529f6ec1efb 100644 (file)
@@ -647,15 +647,7 @@ enum ATTRIBUTE ((packed)) pivot_value_type
 */
 struct pivot_value
   {
-    struct font_style *font_style;
-    struct cell_style *cell_style;
-
-    char **subscripts;
-    size_t n_subscripts;
-
-    size_t *footnote_indexes;
-    size_t n_footnotes;
-
+    struct pivot_value_ex *ex;
     union
       {
         enum pivot_value_type type;
@@ -801,6 +793,33 @@ void pivot_argument_uninit (struct pivot_argument *);
 void pivot_argument_copy (struct pivot_argument *,
                           const struct pivot_argument *);
 \f
+/* Extra styling for a pivot_value.
+
+   This is logically part of pivot_value itself.  It is broken into a separate
+   structure to save memory because it is rarely used. */
+struct pivot_value_ex
+  {
+    struct font_style *font_style;
+    struct cell_style *cell_style;
+
+    char **subscripts;
+    size_t n_subscripts;
+
+    size_t *footnote_indexes;
+    size_t n_footnotes;
+  };
+
+static inline const struct pivot_value_ex *
+pivot_value_ex (const struct pivot_value *value)
+{
+  static const struct pivot_value_ex empty_ex = { .font_style = NULL };
+  return value->ex ? value->ex : &empty_ex;
+}
+
+struct pivot_value_ex *pivot_value_ex_rw (struct pivot_value *);
+struct pivot_value_ex *pivot_value_ex_clone (const struct pivot_value_ex *);
+void pivot_value_ex_destroy (struct pivot_value_ex *);
+\f
 /* One piece of data within a pivot table. */
 struct pivot_cell
   {
index d8ddb82e31340c2fa0a8b31f31feedccc9aa669d..f5b50e2502849f3a4988e4438bb36a5b73764be0 100644 (file)
@@ -1427,11 +1427,11 @@ apply_styles_to_value (struct pivot_table *table,
 {
   if (sf)
     {
-      if (sf->reset > 0)
+      if (sf->reset > 0 && value->ex)
         {
-          free (value->footnote_indexes);
-          value->footnote_indexes = NULL;
-          value->n_footnotes = 0;
+          free (value->ex->footnote_indexes);
+          value->ex->footnote_indexes = NULL;
+          value->ex->n_footnotes = 0;
         }
 
       struct fmt_spec format = { .w = 0 };
@@ -1476,11 +1476,12 @@ apply_styles_to_value (struct pivot_table *table,
     }
   if (fg || bg)
     {
+      const struct pivot_value_ex *ex = pivot_value_ex (value);
       struct table_area_style area;
       pivot_value_get_style (
         value,
-        value->font_style ? value->font_style : &base_area_style->font_style,
-        value->cell_style ? value->cell_style : &base_area_style->cell_style,
+        ex->font_style ? ex->font_style : &base_area_style->font_style,
+        ex->cell_style ? ex->cell_style : &base_area_style->cell_style,
         &area);
       decode_spvdx_style_incremental (fg, bg, &area);
       pivot_value_set_style (value, &area);
@@ -1996,7 +1997,7 @@ decode_spvdx_table (const struct spvdx_visualization *v, const char *subtype,
 
       if (value->type == PIVOT_VALUE_NUMERIC
           && value->numeric.x == SYSMIS
-          && !value->n_footnotes)
+          && !pivot_value_ex (value)->n_footnotes)
         {
           /* Apparently, system-missing values are just empty cells? */
           pivot_value_destroy (value);
index fb0dd18d6aba1e8b8fc8db04641f5e29a8e5d615..e58d423d6768f8f98d29ac42ab3fa2a1348eeb23 100644 (file)
@@ -393,17 +393,19 @@ decode_spvlb_value (const struct pivot_table *table,
     {
       if (vm->n_subscripts)
         {
-          out->n_subscripts = vm->n_subscripts;
-          out->subscripts = xnmalloc (vm->n_subscripts,
-                                      sizeof *out->subscripts);
+          struct pivot_value_ex *ex = pivot_value_ex_rw (out);
+          ex->n_subscripts = vm->n_subscripts;
+          ex->subscripts = xnmalloc (vm->n_subscripts, sizeof *ex->subscripts);
           for (size_t i = 0; i < vm->n_subscripts; i++)
-            out->subscripts[i] = to_utf8 (vm->subscripts[i], encoding);
+            ex->subscripts[i] = to_utf8 (vm->subscripts[i], encoding);
         }
 
       if (vm->n_refs)
         {
-          out->footnote_indexes = xnmalloc (vm->n_refs,
-                                            sizeof *out->footnote_indexes);
+          struct pivot_value_ex *ex = pivot_value_ex_rw (out);
+          ex->footnote_indexes = xnmalloc (vm->n_refs,
+                                           sizeof *ex->footnote_indexes);
+
           for (size_t i = 0; i < vm->n_refs; i++)
             {
               uint16_t idx = vm->refs[i];
@@ -414,18 +416,19 @@ decode_spvlb_value (const struct pivot_table *table,
                                     idx, table->n_footnotes);
                 }
 
-              out->footnote_indexes[out->n_footnotes++] = idx;
+              ex->footnote_indexes[ex->n_footnotes++] = idx;
             }
           pivot_value_sort_footnotes (out);
         }
 
       if (vm->style_pair)
         {
+          struct pivot_value_ex *ex = pivot_value_ex_rw (out);
           error = decode_spvlb_font_style (vm->style_pair->font_style,
-                                           encoding, &out->font_style);
+                                           encoding, &ex->font_style);
           if (!error)
             error = decode_spvlb_cell_style (vm->style_pair->cell_style,
-                                             &out->cell_style);
+                                             &ex->cell_style);
           if (error)
             {
               pivot_value_destroy (out);
index 2e24a33e9b0dee848feccda520f5bbd6478abe43..bb37a05e24b103ab86be47f9e766e2a39e98fe7d 100644 (file)
@@ -558,20 +558,25 @@ static void
 put_value_mod (struct buf *buf, const struct pivot_value *value,
                const char *template)
 {
-  if (value->n_footnotes || value->n_subscripts
-      || template || value->font_style || value->cell_style)
+  if ((value->ex
+       && (value->ex->n_footnotes
+           || value->ex->n_subscripts
+           || value->ex->font_style
+           || value->ex->cell_style))
+      || template)
     {
+      const struct pivot_value_ex *ex = pivot_value_ex (value);
       put_byte (buf, 0x31);
 
       /* Footnotes. */
-      put_u32 (buf, value->n_footnotes);
-      for (size_t i = 0; i < value->n_footnotes; i++)
-        put_u16 (buf, value->footnote_indexes[i]);
+      put_u32 (buf, ex->n_footnotes);
+      for (size_t i = 0; i < ex->n_footnotes; i++)
+        put_u16 (buf, ex->footnote_indexes[i]);
 
       /* Subscripts. */
-      put_u32 (buf, value->n_subscripts);
-      for (size_t i = 0; i < value->n_subscripts; i++)
-        put_string (buf, value->subscripts[i]);
+      put_u32 (buf, ex->n_subscripts);
+      for (size_t i = 0; i < ex->n_subscripts; i++)
+        put_string (buf, ex->subscripts[i]);
 
       /* Template and style. */
       uint32_t v3_start = start_count (buf);
@@ -585,7 +590,7 @@ put_value_mod (struct buf *buf, const struct pivot_value *value,
           put_string (buf, template);
         }
       end_count_u32 (buf, template_string_start);
-      put_style_pair (buf, value->font_style, value->cell_style);
+      put_style_pair (buf, ex->font_style, ex->cell_style);
       end_count_u32 (buf, v3_start);
     }
   else
index 9b0fe17a21ea4878ccac8e1be290b6003f3d1e35..2e5dd07b2bf426a2694d91a1afd5d3558ee9e56b 100644 (file)
@@ -282,9 +282,9 @@ decode_container_text (const struct spvsx_container_text *ct)
 {
   struct font_style *font_style = xmalloc (sizeof *font_style);
   char *text = decode_embedded_html (ct->html->node_.raw, font_style);
+
   struct pivot_value *value = xmalloc (sizeof *value);
   *value = (struct pivot_value) {
-    .font_style = font_style,
     .text = {
       .type = PIVOT_VALUE_TEXT,
       .local = text,
@@ -293,6 +293,7 @@ decode_container_text (const struct spvsx_container_text *ct)
       .user_provided = true,
     },
   };
+  pivot_value_ex_rw (value)->font_style = font_style;
 
   struct output_item *item = text_item_create_value (TEXT_ITEM_LOG,
                                                      value, NULL);
index bf22d2da5af8809de3f2b5d3e7b51e8d6aab70c0..09ed509e35bfac726be760d9e2210db17f89144e 100644 (file)
@@ -527,12 +527,13 @@ table_get_cell (const struct table *t, int x, int y, struct table_cell *cell)
   else
     {
       const struct pivot_value *v = cc ? cc : &empty_value;
+      const struct pivot_value_ex *ex = pivot_value_ex (v);
       *cell = (struct table_cell) {
         .d = { [H] = { x, x + 1 }, [V] = { y, y + 1 } },
         .options = opt,
         .value = v,
-        .font_style = v->font_style ? v->font_style : &style->font_style,
-        .cell_style = v->cell_style ? v->cell_style : &style->cell_style,
+        .font_style = ex->font_style ? ex->font_style : &style->font_style,
+        .cell_style = ex->cell_style ? ex->cell_style : &style->cell_style,
       };
     }
 
index 800aa726d95f83dd271c365fb3424fedbbb57cd2..698abaa453347e04cb877fd44bc8ea19a9707362 100644 (file)
@@ -393,13 +393,12 @@ tex_submit (struct output_driver *driver, const struct output_item *item)
 static void
 tex_put_footnote_markers (struct tex_driver *tex,
                           const struct pivot_table *pt,
-                          const size_t *footnote_indexes,
-                          size_t n_footnotes)
+                          const struct pivot_value_ex *ex)
 {
   size_t n_visible = 0;
-  for (size_t i = 0; i < n_footnotes; i++)
+  for (size_t i = 0; i < ex->n_footnotes; i++)
     {
-      const struct pivot_footnote *f = pt->footnotes[footnote_indexes[i]];
+      const struct pivot_footnote *f = pt->footnotes[ex->footnote_indexes[i]];
       if (f->show)
         {
           if (!n_visible++)
@@ -423,9 +422,7 @@ tex_put_table_cell (struct tex_driver *tex, const struct pivot_table *pt,
   tex_escape_string (tex, ds_cstr (&s), false);
   ds_destroy (&s);
 
-  tex_put_footnote_markers (tex, pt,
-                            cell->value->footnote_indexes,
-                            cell->value->n_footnotes);
+  tex_put_footnote_markers (tex, pt, pivot_value_ex (cell->value));
 }
 
 static void
@@ -549,8 +546,7 @@ tex_output_table_layer (struct tex_driver *tex, const struct pivot_table *pt,
           tex_escape_string (tex, ds_cstr (&s), true);
           ds_destroy (&s);
 
-          tex_put_footnote_markers (tex, pt, cell.value->footnote_indexes,
-                                    cell.value->n_footnotes);
+          tex_put_footnote_markers (tex, pt, pivot_value_ex (cell.value));
           if (halign == TABLE_HALIGN_CENTER || halign == TABLE_HALIGN_RIGHT)
             {
               shipout (&tex->token_list, "}");
index 98336b2563f3aefd89d42ee6de5838b0cdd6df51..18e7d0499f5cd44bc6bf67cca2ebd83015ebf946 100644 (file)
@@ -598,16 +598,16 @@ read_value_option (struct lexer *lexer, const struct pivot_table *pt,
   if (lex_match_id (lexer, "SUBSCRIPTS"))
     {
       lex_match (lexer, T_EQUALS);
-      size_t allocated_subscripts = value->n_subscripts;
+
+      struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+      size_t allocated_subscripts = ex->n_subscripts;
       while (lex_token (lexer) == T_STRING)
         {
-          if (value->n_subscripts >= allocated_subscripts)
-            value->subscripts = x2nrealloc (value->subscripts,
-                                            &allocated_subscripts,
-                                            sizeof *value->subscripts);
+          if (ex->n_subscripts >= allocated_subscripts)
+            ex->subscripts = x2nrealloc (ex->subscripts, &allocated_subscripts,
+                                         sizeof *ex->subscripts);
 
-          value->subscripts[value->n_subscripts++] = xstrdup (
-            lex_tokcstr (lexer));
+          ex->subscripts[ex->n_subscripts++] = xstrdup (lex_tokcstr (lexer));
           lex_get (lexer);
         }
       return;
@@ -617,12 +617,13 @@ read_value_option (struct lexer *lexer, const struct pivot_table *pt,
     {
       lex_match (lexer, T_EQUALS);
 
-      if (!value->font_style)
+      struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+      if (!ex->font_style)
         {
-          value->font_style = xmalloc (sizeof *value->font_style);
-          font_style_copy (NULL, value->font_style, &base_style->font_style);
+          ex->font_style = xmalloc (sizeof *ex->font_style);
+          font_style_copy (NULL, ex->font_style, &base_style->font_style);
         }
-      read_font_style (lexer, value->font_style);
+      read_font_style (lexer, ex->font_style);
       return;
     }
 
@@ -630,12 +631,13 @@ read_value_option (struct lexer *lexer, const struct pivot_table *pt,
     {
       lex_match (lexer, T_EQUALS);
 
-      if (!value->cell_style)
+      struct pivot_value_ex *ex = pivot_value_ex_rw (value);
+      if (!ex->cell_style)
         {
-          value->cell_style = xmalloc (sizeof *value->cell_style);
-          *value->cell_style = base_style->cell_style;
+          ex->cell_style = xmalloc (sizeof *ex->cell_style);
+          *ex->cell_style = base_style->cell_style;
         }
-      read_cell_style (lexer, value->cell_style);
+      read_cell_style (lexer, ex->cell_style);
       return;
     }