pivot-table: Add more tests for category and dimension borders.
[pspp] / src / data / dictionary.c
index c331ea234550f461d0ad07d3ff8300a109af440e..60349bce61ec4650b8287f2e28b9bcff5973ac66 100644 (file)
@@ -179,15 +179,35 @@ dict_get_encoding (const struct dictionary *d)
   return d->encoding ;
 }
 
+/* Checks whether UTF-8 string ID is an acceptable identifier in DICT's
+   encoding.  Returns true if it is, otherwise an error message that the caller
+   must free(). */
+char * WARN_UNUSED_RESULT
+dict_id_is_valid__ (const struct dictionary *dict, const char *id)
+{
+  if (!dict->names_must_be_ids)
+    return NULL;
+  return id_is_valid__ (id, dict->encoding);
+}
+
+static bool
+error_to_bool (char *error)
+{
+  if (error)
+    {
+      free (error);
+      return false;
+    }
+  else
+    return true;
+}
+
 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
-   encoding, false otherwise.  If ISSUE_ERROR is true, issues an explanatory
-   error message on failure. */
+   encoding, false otherwise. */
 bool
-dict_id_is_valid (const struct dictionary *dict, const char *id,
-                  bool issue_error)
+dict_id_is_valid (const struct dictionary *dict, const char *id)
 {
-  return (!dict->names_must_be_ids
-          || id_is_valid (id, dict->encoding, issue_error));
+  return error_to_bool (dict_id_is_valid__ (dict, id));
 }
 
 void
@@ -259,7 +279,7 @@ dict_create (const char *encoding)
     .names_must_be_ids = true,
     .name_map = HMAP_INITIALIZER (d->name_map),
     .attributes = ATTRSET_INITIALIZER (d->attributes),
-    .split_type = SPLIT_LAYERED,
+    .split_type = SPLIT_NONE,
     .ref_cnt = 1,
   };
 
@@ -384,16 +404,19 @@ dict_unset_split_var (struct dictionary *d, struct variable *v, bool skip_callba
 }
 
 
-/* Sets N split vars SPLIT in dictionary D. */
+/* Sets N split vars SPLIT in dictionary D.  N is silently capped to a maximum
+   of MAX_SPLITS. */
 static void
 dict_set_split_vars__ (struct dictionary *d,
                        struct variable *const *split, size_t n,
                        enum split_type type, bool skip_callbacks)
 {
+  if (n > MAX_SPLITS)
+    n = MAX_SPLITS;
   assert (n == 0 || split != NULL);
 
   d->n_splits = n;
-  d->split_type = type;
+  d->split_type = type == SPLIT_NONE ? SPLIT_LAYERED : type;
   if (n > 0)
    {
     d->split = xnrealloc (d->split, n, sizeof *d->split) ;
@@ -413,6 +436,12 @@ dict_set_split_vars__ (struct dictionary *d,
     }
 }
 
+enum split_type
+dict_get_split_type (const struct dictionary *d)
+{
+  return d->split_type;
+}
+
 /* Sets N split vars SPLIT in dictionary D. */
 void
 dict_set_split_vars (struct dictionary *d,
@@ -425,7 +454,7 @@ dict_set_split_vars (struct dictionary *d,
 void
 dict_clear_split_vars (struct dictionary *d)
 {
-  dict_set_split_vars (d, NULL, 0, SPLIT_LAYERED);
+  dict_set_split_vars (d, NULL, 0, SPLIT_NONE);
 }
 \f
 
@@ -623,7 +652,7 @@ dict_clear__ (struct dictionary *d, bool skip_callbacks)
   invalidate_proto (d);
   hmap_clear (&d->name_map);
   d->next_value_idx = 0;
-  dict_set_split_vars__ (d, NULL, 0, SPLIT_LAYERED, skip_callbacks);
+  dict_set_split_vars__ (d, NULL, 0, SPLIT_NONE, skip_callbacks);
 
   if (skip_callbacks)
     {
@@ -1253,7 +1282,7 @@ dict_get_weight (const struct dictionary *d)
 }
 
 /* Returns the value of D's weighting variable in case C, except
-   that a negative weight is returned as 0.  Returns 1 if the
+   that a negative or missing weight is returned as 0.  Returns 1 if the
    dictionary is unweighted.  Will warn about missing, negative,
    or zero values if *WARN_ON_INVALID is true.  The function will
    set *WARN_ON_INVALID to false if an invalid weight is
@@ -1274,6 +1303,15 @@ dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
     }
 }
 
+/* Like dict_get_case_weight(), but additionally rounds each weight to the
+   nearest integer.  */
+double
+dict_get_rounded_case_weight (const struct dictionary *d,
+                              const struct ccase *c, bool *warn_on_invalid)
+{
+  return floor (dict_get_case_weight (d, c, warn_on_invalid) + 0.5);
+}
+
 /* Returns the format to use for weights. */
 const struct fmt_spec *
 dict_get_weight_format (const struct dictionary *d)