sys-file-writer: Simplify use of put_cmp_number(), put_cmp_string().
[pspp] / src / data / sys-file-writer.c
index 32326e13f2047142e0b8b8b247a193a8974182a9..c78e04d55f24e41ef5ecce805664c896fc15c44e 100644 (file)
@@ -78,15 +78,16 @@ struct sfm_writer
 
     /* Compression buffering.
 
-       Compressed data is output as groups of 8 1-byte opcodes
-       followed by up to 8 (depending on the opcodes) 8-byte data
-       items.  Data items and opcodes arrive at the same time but
-       must be reordered for writing to disk, thus a small amount
-       of buffering here. */
-    uint8_t opcodes[8];         /* Buffered opcodes. */
-    int opcode_cnt;             /* Number of buffered opcodes. */
-    uint8_t data[8][8];         /* Buffered data. */
-    int data_cnt;               /* Number of buffered data items. */
+       Compressed data is output as a series of 8-byte elements, with 1 to 9
+       such elements clustered together.  The first element in a cluster is 8
+       1-byte opcodes.  Some opcodes call for an additional element in the
+       cluster (hence, if there are eight such opcodes, then the cluster
+       contains a full 9 elements).
+
+       cbuf[] holds a cluster at a time. */
+    uint8_t cbuf[9][8];
+    int n_opcodes;              /* Number of opcodes in cbuf[0] so far. */
+    int n_elements;             /* Number of elements in cbuf[] so far. */
 
     /* Variables. */
     struct sfm_var *sfm_vars;   /* Variables. */
@@ -202,7 +203,8 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d,
   w->compress = opts.compress;
   w->case_cnt = 0;
 
-  w->opcode_cnt = w->data_cnt = 0;
+  w->n_opcodes = w->n_elements = 0;
+  memset (w->cbuf[0], 0, 8);
 
   /* Figure out how to map in-memory case data to on-disk case
      data.  Also count the number of segments.  Very long strings
@@ -706,7 +708,7 @@ add_role_attribute (enum var_role role, struct attrset *attrs)
       s = "0";
       break;
 
-    case ROLE_OUTPUT:
+    case ROLE_TARGET:
       s = "1";
       break;
 
@@ -1207,8 +1209,7 @@ close_writer (struct sfm_writer *w)
   if (w->file != NULL)
     {
       /* Flush buffer. */
-      if (w->opcode_cnt > 0)
-        flush_compressed (w);
+      flush_compressed (w);
       fflush (w->file);
 
       ok = !write_error (w);
@@ -1291,10 +1292,7 @@ write_case_compressed (struct sfm_writer *w, const struct ccase *c)
                    && d == (int) d)
             put_cmp_opcode (w, (int) d + COMPRESSION_BIAS);
           else
-            {
-              put_cmp_opcode (w, 253);
-              put_cmp_number (w, d);
-            }
+            put_cmp_number (w, d);
         }
       else
         {
@@ -1312,10 +1310,7 @@ write_case_compressed (struct sfm_writer *w, const struct ccase *c)
               if (!memcmp (data, "        ", chunk_size))
                 put_cmp_opcode (w, 254);
               else
-                {
-                  put_cmp_opcode (w, 253);
-                  put_cmp_string (w, data, chunk_size);
-                }
+                put_cmp_string (w, data, chunk_size);
             }
 
           /* This code deals properly with padding that is not a
@@ -1329,19 +1324,16 @@ write_case_compressed (struct sfm_writer *w, const struct ccase *c)
     }
 }
 
-/* Flushes buffered compressed opcodes and data to W.
-   The compression buffer must not be empty. */
+/* Flushes buffered compressed opcodes and data to W. */
 static void
 flush_compressed (struct sfm_writer *w)
 {
-  assert (w->opcode_cnt > 0 && w->opcode_cnt <= 8);
-
-  write_bytes (w, w->opcodes, w->opcode_cnt);
-  write_zeros (w, 8 - w->opcode_cnt);
-
-  write_bytes (w, w->data, w->data_cnt * sizeof *w->data);
-
-  w->opcode_cnt = w->data_cnt = 0;
+  if (w->n_opcodes)
+    {
+      write_bytes (w, w->cbuf, 8 * (1 + w->n_elements));
+      w->n_opcodes = w->n_elements = 0;
+      memset (w->cbuf[0], 0, 8);
+    }
 }
 
 /* Appends OPCODE to the buffered set of compression opcodes in
@@ -1349,41 +1341,32 @@ flush_compressed (struct sfm_writer *w)
 static void
 put_cmp_opcode (struct sfm_writer *w, uint8_t opcode)
 {
-  if (w->opcode_cnt >= 8)
+  if (w->n_opcodes >= 8)
     flush_compressed (w);
 
-  w->opcodes[w->opcode_cnt++] = opcode;
+  w->cbuf[0][w->n_opcodes++] = opcode;
 }
 
-/* Appends NUMBER to the buffered compression data in W.  The
-   buffer must not be full; the way to assure that is to call
-   this function only just after a call to put_cmp_opcode, which
-   will flush the buffer as necessary. */
+/* Appends NUMBER to the buffered compression data in W. */
 static void
 put_cmp_number (struct sfm_writer *w, double number)
 {
-  assert (w->opcode_cnt > 0);
-  assert (w->data_cnt < 8);
-
-  convert_double_to_output_format (number, w->data[w->data_cnt++]);
+  put_cmp_opcode (w, 253);
+  convert_double_to_output_format (number, w->cbuf[++w->n_elements]);
 }
 
 /* Appends SIZE bytes of DATA to the buffered compression data in
    W, followed by enough spaces to pad the output data to exactly
-   8 bytes (thus, SIZE must be no greater than 8).  The buffer
-   must not be full; the way to assure that is to call this
-   function only just after a call to put_cmp_opcode, which will
-   flush the buffer as necessary. */
+   8 bytes (thus, SIZE must be no greater than 8). */
 static void
 put_cmp_string (struct sfm_writer *w, const void *data, size_t size)
 {
-  assert (w->opcode_cnt > 0);
-  assert (w->data_cnt < 8);
   assert (size <= 8);
 
-  memset (w->data[w->data_cnt], w->space, 8);
-  memcpy (w->data[w->data_cnt], data, size);
-  w->data_cnt++;
+  put_cmp_opcode (w, 253);
+  w->n_elements++;
+  memset (w->cbuf[w->n_elements], w->space, 8);
+  memcpy (w->cbuf[w->n_elements], data, size);
 }
 \f
 /* Writes 32-bit integer X to the output file for writer W. */