X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata%2Fmissing-values.c;h=267d34fb9102247bec8d5e02d139640297935716;hb=d9153beacc1308b37dbaf4f64155553360aa0173;hp=61bb9bcb13c4968a4500fc4fc98ee13e2f631c1b;hpb=b40baf410822471fbdeeec553693619d60d7c7b6;p=pspp
diff --git a/src/data/missing-values.c b/src/data/missing-values.c
index 61bb9bcb13..267d34fb91 100644
--- a/src/data/missing-values.c
+++ b/src/data/missing-values.c
@@ -1,5 +1,5 @@
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009, 2011, 2013 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
@@ -15,12 +15,19 @@
along with this program. If not, see . */
#include
-#include
+
+#include "data/missing-values.h"
+
#include
#include
-#include
-#include
-#include
+
+#include "data/variable.h"
+#include "libpspp/assertion.h"
+#include "libpspp/cast.h"
+#include "libpspp/i18n.h"
+#include "libpspp/str.h"
+
+#include "gl/minmax.h"
/* Types of user-missing values.
Invisible--use access functions defined below instead. */
@@ -108,7 +115,7 @@ mv_is_acceptable (const union value *value, int width)
int i;
for (i = MV_MAX_STRING; i < width; i++)
- if (value_str (value, width)[i] != ' ')
+ if (value->s[i] != ' ')
return false;
return true;
}
@@ -155,19 +162,23 @@ mv_add_value (struct missing_values *mv, const union value *v)
NOT_REACHED ();
}
-/* Attempts to add S to the set of string missing values MV. S
- must contain exactly as many characters as MV's width.
- Returns true if successful, false if MV has no more room for
+/* Attempts to add S, which is LEN bytes long, to the set of string missing
+ values MV. Returns true if successful, false if MV has no more room for
missing values or if S is not an acceptable missing value. */
bool
-mv_add_str (struct missing_values *mv, const uint8_t s[])
+mv_add_str (struct missing_values *mv, const uint8_t s[], size_t len)
{
union value v;
bool ok;
assert (mv->width > 0);
+ while (len > mv->width)
+ if (s[--len] != ' ')
+ return false;
+
value_init (&v, mv->width);
- memcpy (value_str_rw (&v, mv->width), s, mv->width);
+ buf_copy_rpad (CHAR_CAST (char *, v.s), mv->width,
+ CHAR_CAST (char *, s), len, ' ');
ok = mv_add_value (mv, &v);
value_destroy (&v, mv->width);
@@ -413,14 +424,14 @@ is_str_user_missing (const struct missing_values *mv, const uint8_t s[])
case MVT_NONE:
return false;
case MVT_1:
- return !memcmp (value_str (&v[0], mv->width), s, mv->width);
+ return !memcmp (v[0].s, s, mv->width);
case MVT_2:
- return (!memcmp (value_str (&v[0], mv->width), s, mv->width)
- || !memcmp (value_str (&v[1], mv->width), s, mv->width));
+ return (!memcmp (v[0].s, s, mv->width)
+ || !memcmp (v[1].s, s, mv->width));
case MVT_3:
- return (!memcmp (value_str (&v[0], mv->width), s, mv->width)
- || !memcmp (value_str (&v[1], mv->width), s, mv->width)
- || !memcmp (value_str (&v[2], mv->width), s, mv->width));
+ return (!memcmp (v[0].s, s, mv->width)
+ || !memcmp (v[1].s, s, mv->width)
+ || !memcmp (v[2].s, s, mv->width));
case MVT_RANGE:
case MVT_RANGE_1:
NOT_REACHED ();
@@ -436,7 +447,7 @@ mv_is_value_missing (const struct missing_values *mv, const union value *v,
{
return (mv->width == 0
? mv_is_num_missing (mv, v->f, class)
- : mv_is_str_missing (mv, value_str (v, mv->width), class));
+ : mv_is_str_missing (mv, v->s, class));
}
/* Returns true if D is a missing value in the given CLASS in MV,
@@ -462,3 +473,67 @@ mv_is_str_missing (const struct missing_values *mv, const uint8_t s[],
assert (mv->width > 0);
return class & MV_USER && is_str_user_missing (mv, s);
}
+
+/* Like mv_is_value_missing(), this tests whether V is a missing value
+ in the given CLASS in MV. It supports the uncommon case where V
+ and MV might have different widths: the caller must specify VW, the
+ width of V. MV and VW must be both numeric or both string.
+
+ Comparison of strings of different width is done by conceptually
+ extending both strings to infinite width by appending spaces. */
+bool
+mv_is_value_missing_varwidth (const struct missing_values *mv,
+ const union value *v, int vw,
+ enum mv_class class)
+{
+ int mvw = mv->width;
+ if (mvw == vw)
+ return mv_is_value_missing (mv, v, class);
+
+ /* Make sure they're both strings. */
+ assert (mvw && vw);
+ if (!(class & MV_USER) || mv->type == MVT_NONE)
+ return false;
+
+ for (int i = 0; i < mv->type; i++)
+ if (!buf_compare_rpad (CHAR_CAST_BUG (const char *, mv->values[i].s), mvw,
+ CHAR_CAST_BUG (const char *, v->s), vw))
+ return true;
+ return false;
+}
+
+char *
+mv_to_string (const struct missing_values *mv, const char *encoding)
+{
+ struct string s = DS_EMPTY_INITIALIZER;
+ if (mv_has_range (mv))
+ {
+ double x, y;
+ mv_get_range (mv, &x, &y);
+ if (x == LOWEST)
+ ds_put_format (&s, "LOWEST THRU %.*g", DBL_DIG + 1, y);
+ else if (y == HIGHEST)
+ ds_put_format (&s, "%.*g THRU HIGHEST", DBL_DIG + 1, x);
+ else
+ ds_put_format (&s, "%.*g THRU %.*g",
+ DBL_DIG + 1, x,
+ DBL_DIG + 1, y);
+ }
+ for (size_t j = 0; j < mv_n_values (mv); j++)
+ {
+ const union value *value = mv_get_value (mv, j);
+ if (!ds_is_empty (&s))
+ ds_put_cstr (&s, "; ");
+ if (!mv->width)
+ ds_put_format (&s, "%.*g", DBL_DIG + 1, value->f);
+ else
+ {
+ char *mvs = recode_string (
+ "UTF-8", encoding, CHAR_CAST (char *, value->s),
+ MIN (mv->width, MV_MAX_STRING));
+ ds_put_format (&s, "\"%s\"", mvs);
+ free (mvs);
+ }
+ }
+ return ds_is_empty (&s) ? NULL : ds_steal_cstr (&s);
+}