dictionary: Allow dict_set_documents() argument to reference old documents.
[pspp] / src / data / dictionary.c
index ceea10ed6851314aaff8f20a571fa990dce9a3f0..4fbcdf2a1e16f237b2988b10d80800a3752c7343 100644 (file)
@@ -133,7 +133,7 @@ reindex_var (struct dictionary *d, struct vardict_info *vardict, bool skip_callb
       if (old)
         {
           d->callbacks->var_changed (d, var_get_dict_index (var), VAR_TRAIT_POSITION, old, d->cb_data);
-          var_destroy (old);
+          var_unref (old);
         }
     }
 }
@@ -250,7 +250,7 @@ dict_copy_callbacks (struct dictionary *dest,
 struct dictionary *
 dict_create (const char *encoding)
 {
-  struct dictionary *d = xzalloc (sizeof *d);
+  struct dictionary *d = XZALLOC (struct dictionary);
 
   d->encoding = xstrdup (encoding);
   d->names_must_be_ids = true;
@@ -466,7 +466,7 @@ dict_delete_var__ (struct dictionary *d, struct variable *v, bool skip_callbacks
     }
 
   invalidate_proto (d);
-  var_destroy (v);
+  var_unref (v);
 }
 
 /* Deletes variable V from dictionary D and frees V.
@@ -569,7 +569,7 @@ dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
       var_clear_vardict (dv->var);
       if (d->callbacks &&  d->callbacks->var_deleted)
         d->callbacks->var_deleted (d, dv->var, vi, dv->case_index, d->cb_data);
-      var_destroy (dv->var);
+      var_unref (dv->var);
       free (dv);
     }
 }
@@ -988,7 +988,7 @@ dict_try_rename_var (struct dictionary *d, struct variable *v,
   if (d->callbacks &&  d->callbacks->var_changed)
     d->callbacks->var_changed (d, var_get_dict_index (v), VAR_TRAIT_NAME, old, d->cb_data);
 
-  var_destroy (old);
+  var_unref (old);
 
   return true;
 }
@@ -1094,6 +1094,9 @@ make_hinted_name (const struct dictionary *dict, const char *hint)
   size_t ofs;
   int mblen;
 
+  if (hint_len > ID_MAX_LEN)
+    hint_len = ID_MAX_LEN;
+
   /* The allocation size here is OK: characters that are copied directly fit
      OK, and characters that are not copied directly are replaced by a single
      '_' byte.  If u8_mbtouc() replaces bad input by 0xfffd, then that will get
@@ -1200,6 +1203,7 @@ dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
       if (hinted_name != NULL)
         return hinted_name;
     }
+
   return make_numeric_name (dict, num_start);
 }
 
@@ -1467,12 +1471,15 @@ dict_get_documents (const struct dictionary *d)
 void
 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
 {
-  size_t i;
+  /* Swap out the old documents, instead of destroying them immediately, to
+     allow the new documents to include pointers into the old ones. */
+  struct string_array old_docs = STRING_ARRAY_INITIALIZER;
+  string_array_swap (&d->documents, &old_docs);
 
-  dict_clear_documents (d);
-
-  for (i = 0; i < new_docs->n; i++)
+  for (size_t i = 0; i < new_docs->n; i++)
     dict_add_document_line (d, new_docs->strings[i], false);
+
+  string_array_destroy (&old_docs);
 }
 
 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
@@ -1795,11 +1802,14 @@ dict_var_changed (const struct variable *v, unsigned int what, struct variable *
       if (NULL == d)
        return;
 
+      if (what & (VAR_TRAIT_WIDTH | VAR_TRAIT_POSITION))
+        invalidate_proto (d);
+
       if (d->changed) d->changed (d, d->changed_data);
       if (d->callbacks && d->callbacks->var_changed)
         d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
     }
-  var_destroy (oldvar);
+  var_unref (oldvar);
 }