value: Get rid of value_str(), value_str_rw(), value_num().
[pspp] / src / language / data-io / matrix-data.c
index 609e5eb1fd5156365093ac9c70851ab2dbcfce5b..7676bb1de0157d45c0c74ead6f2a18c387378cc6 100644 (file)
@@ -106,16 +106,16 @@ set_varname_column (struct ccase *outcase, const struct variable *vname,
      const char *str)
 {
   int len = var_get_width (vname);
-  uint8_t *s = value_str_rw (case_data_rw (outcase, vname), len);
+  uint8_t *s = case_str_rw (outcase, vname);
 
-  strncpy ((char *) s, str, len);
+  strncpy (CHAR_CAST (char *, s), str, len);
 }
 
 static void
 blank_varname_column (struct ccase *outcase, const struct variable *vname)
 {
   int len = var_get_width (vname);
-  uint8_t *s = value_str_rw (case_data_rw (outcase, vname), len);
+  uint8_t *s = case_str_rw (outcase, vname);
 
   memset (s, ' ', len);
 }
@@ -125,8 +125,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
 {
   struct matrix_format *mformat = aux;
   const struct caseproto *proto = casereader_get_proto (casereader0);
-  struct casewriter *writer;
-  writer = autopaging_writer_create (proto);
+  struct casewriter *writer = autopaging_writer_create (proto);
   struct ccase *prev_case = NULL;
   double **matrices = NULL;
   size_t n_splits = 0;
@@ -138,20 +137,30 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
   /* Make an initial pass to populate our temporary matrix */
   struct casereader *pass0 = casereader_clone (casereader0);
   struct ccase *c;
-  unsigned int prev_split_hash = 1;
+  union value *prev_values = xcalloc (mformat->n_split_vars, sizeof *prev_values);
   int row = (mformat->triangle == LOWER && mformat->diagonal == NO_DIAGONAL) ? 1 : 0;
+  bool first_case = true;
   for (; (c = casereader_read (pass0)) != NULL; case_unref (c))
     {
       int s;
-      unsigned int split_hash = 0;
-      for (s = 0; s < mformat->n_split_vars; ++s)
+      bool match = false;
+      if (!first_case)
        {
-         const struct variable *svar = mformat->split_vars[s];
-         const union value *sv = case_data (c, svar);
-         split_hash = value_hash (sv, var_get_width (svar), split_hash);
+         match = true;
+         for (s = 0; s < mformat->n_split_vars; ++s)
+           {
+             const struct variable *svar = mformat->split_vars[s];
+             const union value *sv = case_data (c, svar);
+             if (! value_equal (prev_values + s, sv, var_get_width (svar)))
+               {
+                 match = false;
+                 break;
+               }
+           }
        }
+      first_case = false;
 
-      if (matrices == NULL || prev_split_hash != split_hash)
+      if (matrices == NULL || ! match)
        {
          row = (mformat->triangle == LOWER && mformat->diagonal == NO_DIAGONAL) ?
            1 : 0;
@@ -161,13 +170,18 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
          matrices[n_splits - 1] = xmalloc (sizeof_matrix);
        }
 
-      prev_split_hash = split_hash;
+      for (s = 0; s < mformat->n_split_vars; ++s)
+       {
+         const struct variable *svar = mformat->split_vars[s];
+         const union value *sv = case_data (c, svar);
+         value_clone (prev_values + s, sv, var_get_width (svar));
+       }
 
       int c_offset = (mformat->triangle == UPPER) ? row : 0;
       if (mformat->triangle == UPPER && mformat->diagonal == NO_DIAGONAL)
        c_offset++;
       const union value *v = case_data (c, mformat->rowtype);
-      const char *val = (const char *) value_str (v, ROWTYPE_WIDTH);
+      const char *val = CHAR_CAST (const char *, v->s);
       if (0 == strncasecmp (val, "corr    ", ROWTYPE_WIDTH) ||
          0 == strncasecmp (val, "cov     ", ROWTYPE_WIDTH))
        {
@@ -176,6 +190,9 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
              msg (SE,
                   _("There are %d variable declared but the data has at least %d matrix rows."),
                   mformat->n_continuous_vars, row + 1);
+             case_unref (c);
+             casereader_destroy (pass0);
+             free (prev_values);
              goto error;
            }
          int col;
@@ -201,6 +218,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
        }
     }
   casereader_destroy (pass0);
+  free (prev_values);
 
   /* Now make a second pass to fill in the other triangle from our
      temporary matrix */
@@ -212,8 +230,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
       int col;
       struct ccase *outcase = case_create (proto);
       union value *v = case_data_rw (outcase, mformat->rowtype);
-      uint8_t *n = value_str_rw (v, ROWTYPE_WIDTH);
-      strncpy ((char *) n, "N        ", ROWTYPE_WIDTH);
+      memcpy (v->s, "N       ", ROWTYPE_WIDTH);
       blank_varname_column (outcase, mformat->varname);
       for (col = 0; col < mformat->n_continuous_vars; ++col)
        {
@@ -225,28 +242,44 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
       casewriter_write (writer, outcase);
     }
 
-  prev_split_hash = 1;
   n_splits = 0;
+  prev_values = xcalloc (mformat->n_split_vars, sizeof *prev_values);
+  first_case = true;
   for (; (c = casereader_read (casereader0)) != NULL; prev_case = c)
     {
       int s;
-      unsigned int split_hash = 0;
-      for (s = 0; s < mformat->n_split_vars; ++s)
+      bool match = false;
+      if (!first_case)
        {
-         const struct variable *svar = mformat->split_vars[s];
-         const union value *sv = case_data (c, svar);
-         split_hash = value_hash (sv, var_get_width (svar), split_hash);
+         match = true;
+         for (s = 0; s < mformat->n_split_vars; ++s)
+           {
+             const struct variable *svar = mformat->split_vars[s];
+             const union value *sv = case_data (c, svar);
+             if (! value_equal (prev_values + s, sv, var_get_width (svar)))
+               {
+                 match = false;
+                 break;
+               }
+           }
        }
-      if (prev_split_hash != split_hash)
+      first_case = false;
+      if (! match)
        {
          n_splits++;
          row = 0;
        }
 
-      prev_split_hash = split_hash;
+      for (s = 0; s < mformat->n_split_vars; ++s)
+       {
+         const struct variable *svar = mformat->split_vars[s];
+         const union value *sv = case_data (c, svar);
+         value_clone (prev_values + s, sv, var_get_width (svar));
+       }
+
       case_unref (prev_case);
       const union value *v = case_data (c, mformat->rowtype);
-      const char *val = (const char *) value_str (v, ROWTYPE_WIDTH);
+      const char *val = CHAR_CAST (const char *, v->s);
       if (mformat->n >= 0)
        {
          if (0 == strncasecmp (val, "n       ", ROWTYPE_WIDTH) ||
@@ -324,7 +357,7 @@ preprocess (struct casereader *casereader0, const struct dictionary *dict, void
 
       casewriter_write (writer, outcase);
     }
-
+  free (prev_values);
 
   if (prev_case)
     case_unref (prev_case);
@@ -346,6 +379,7 @@ error:
     free (matrices[i]);
   free (matrices);
   casereader_destroy (casereader0);
+  casewriter_destroy (writer);
   return NULL;
 }
 
@@ -558,7 +592,8 @@ cmd_matrix (struct lexer *lexer, struct dataset *ds)
     }
   else
     {
-      data_parser_make_active_file (parser, ds, reader, dict, preprocess, &mformat);
+      data_parser_make_active_file (parser, ds, reader, dict, preprocess,
+                                   &mformat);
     }
 
   fh_unref (fh);
@@ -570,7 +605,7 @@ cmd_matrix (struct lexer *lexer, struct dataset *ds)
  error:
   data_parser_destroy (parser);
   if (!in_input_program ())
-    dict_destroy (dict);
+    dict_unref (dict);
   fh_unref (fh);
   free (encoding);
   free (mformat.split_vars);
@@ -626,4 +661,3 @@ data_list_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED)
 
   return retval;
 }
-