Change "union value" to dynamically allocate long strings.
[pspp-builds.git] / src / data / case-matcher.c
index 9cfc0083c2b2b4ff624989cd2b42097ddd4b5f7e..37cb4a60748a4b60e2416476a0ed629ff8f90620 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2008 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@
 struct case_matcher_input
   {
     struct subcase by_vars;
-    const struct ccase *data;
+    struct ccase **data;
     bool *is_minimal;
   };
 
@@ -55,19 +55,24 @@ case_matcher_create (void)
 
 /* Adds a new input file to case matcher CM.
    case_matcher_match() will compare the variables specified in
-   BY in case DATA and set *IS_MINIMAL appropriately.
+   BY in case *DATA and set *IS_MINIMAL appropriately.
+   (The caller may change the case that *DATA points to from one
+   call to the next.)
 
    All of the BY subcases provided to this function for a given
    CM must be conformable (see subcase_conformable()). */
 void
 case_matcher_add_input (struct case_matcher *cm, const struct subcase *by,
-                        const struct ccase *data, bool *is_minimal)
+                        struct ccase **data, bool *is_minimal)
 {
   struct case_matcher_input *input;
 
   if (cm->n_inputs == 0)
-    cm->by_values = xmalloc (subcase_get_n_values (by)
-                             * sizeof *cm->by_values);
+    {
+      cm->by_values = xmalloc (sizeof *cm->by_values
+                               * subcase_get_n_fields (by));
+      caseproto_init_values (subcase_get_proto (by), cm->by_values);
+    }
   else
     assert (subcase_conformable (by, &cm->inputs[0].by_vars));
 
@@ -88,6 +93,12 @@ case_matcher_destroy (struct case_matcher *cm)
     {
       size_t i;
 
+      if (cm->by_values != NULL)
+        {
+          caseproto_destroy_values (subcase_get_proto (&cm->inputs[0].by_vars),
+                                    cm->by_values);
+          free (cm->by_values);
+        }
       for (i = 0; i < cm->n_inputs; i++)
         {
           struct case_matcher_input *input = &cm->inputs[i];
@@ -101,7 +112,7 @@ case_matcher_destroy (struct case_matcher *cm)
 static int
 compare_BY_3way (struct case_matcher_input *a, struct case_matcher_input *b)
 {
-  return subcase_compare_3way (&a->by_vars, a->data, &b->by_vars, b->data);
+  return subcase_compare_3way (&a->by_vars, *a->data, &b->by_vars, *b->data);
 }
 
 /* Compares the values of the BY variables in all of the nonnull
@@ -121,7 +132,7 @@ case_matcher_match (struct case_matcher *cm, union value **by)
 
   min = NULL;
   for (file = cm->inputs; file < &cm->inputs[cm->n_inputs]; file++)
-    if (!case_is_null (file->data))
+    if (*file->data != NULL)
       {
         int cmp = min != NULL ? compare_BY_3way (min, file) : 1;
         if (cmp < 0)
@@ -140,7 +151,7 @@ case_matcher_match (struct case_matcher *cm, union value **by)
     {
       for (file = cm->inputs; file < min; file++)
         *file->is_minimal = false;
-      subcase_extract (&min->by_vars, min->data, cm->by_values);
+      subcase_extract (&min->by_vars, *min->data, cm->by_values);
       *by = cm->by_values;
       return true;
     }