Added a dict parameter to data_in and dealt with the consequences.
authorJohn Darrington <john@darrington.wattle.id.au>
Sun, 12 Jul 2009 14:13:44 +0000 (22:13 +0800)
committerJohn Darrington <john@darrington.wattle.id.au>
Sun, 12 Jul 2009 14:13:44 +0000 (22:13 +0800)
The data_in function now takes a pointer to a struct dictionary,
which must be the dictionary with which the output value is
associated.  Data_in now ensures that the data of string values
is converted to the dictionary's encoding if necessary.

18 files changed:
perl-module/PSPP.xs
src/data/data-in.c
src/data/data-in.h
src/language/data-io/data-list.c
src/language/data-io/data-parser.c
src/language/data-io/data-parser.h
src/language/data-io/get-data.c
src/language/expressions/operations.def
src/language/lexer/value-parser.c
src/language/xforms/recode.c
src/ui/gui/find-dialog.c
src/ui/gui/helper.c
src/ui/gui/helper.h
src/ui/gui/missing-val-dialog.c
src/ui/gui/psppire-data-store.c
src/ui/gui/text-data-import-dialog.c
src/ui/gui/val-labs-dialog.c
src/ui/syntax-gen.c

index 94ca9b01834b9fd968319a75e736c4ecd1ef71be..b3ac4cdc31e84670194ede7d254315ab48deea23 100644 (file)
@@ -614,6 +614,7 @@ CODE:
       {
        struct substring ss = ss_cstr (SvPV_nolen (sv));
        if ( ! data_in (ss, LEGACY_NATIVE, ifmt->type, 0, 0, 0,
+                       sfi->dict,
                        case_data_rw (c, v),
                        var_get_width (v)) )
          {
index 7e7d087d51dcfa1ab9811715ff7354f106081bae..33e369f971da8751f78e29e76f23d230e6e0227d 100644 (file)
@@ -34,6 +34,7 @@
 #include "settings.h"
 #include "value.h"
 #include "format.h"
+#include "dictionary.h"
 
 #include <libpspp/assertion.h>
 #include <libpspp/legacy-encoding.h>
@@ -54,7 +55,7 @@
 /* Information about parsing one data field. */
 struct data_in
   {
-    const char *encoding;       /* Encoding of source. */
+    const char *src_enc;        /* Encoding of source. */
     struct substring input;     /* Source. */
     enum fmt_type format;       /* Input format. */
     int implied_decimals;       /* Number of implied decimal places. */
@@ -89,6 +90,9 @@ static int hexit_value (int c);
    representation in OUTPUT, which the caller must have
    initialized with the given WIDTH (0 for a numeric field,
    otherwise the string width).
+   Iff FORMAT is a string format, then DICT must be a pointer
+   to the dictionary associated with OUTPUT.  Otherwise, DICT
+   may be null.
 
    If no decimal point is included in a numeric format, then
    IMPLIED_DECIMALS decimal places are implied.  Specify 0 if no
@@ -103,7 +107,9 @@ static int hexit_value (int c);
 bool
 data_in (struct substring input, const char *encoding,
          enum fmt_type format, int implied_decimals,
-         int first_column, int last_column, union value *output, int width)
+         int first_column, int last_column,
+        const struct dictionary *dict,
+        union value *output, int width)
 {
   static data_in_parser_func *const handlers[FMT_NUMBER_OF_FORMATS] =
     {
@@ -112,28 +118,11 @@ data_in (struct substring input, const char *encoding,
     };
 
   struct data_in i;
-  void *copy = NULL;
+
   bool ok;
 
   assert ((width != 0) == fmt_is_string (format));
 
-  if (0 == strcmp (encoding, LEGACY_NATIVE)
-      || fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING))
-    {
-      i.input = input;
-      i.encoding = encoding;
-    }
-  else
-    {
-      char *s;
-      ss_alloc_uninit (&i.input, ss_length (input));
-
-      s = recode_string (LEGACY_NATIVE, encoding, ss_data (input), ss_length (input));
-      memcpy (ss_data (i.input), s, ss_length (input));
-      free (s);
-      i.encoding = LEGACY_NATIVE;
-      copy = ss_data (i.input);
-    }
   i.format = format;
   i.implied_decimals = implied_decimals;
 
@@ -142,21 +131,39 @@ data_in (struct substring input, const char *encoding,
 
   i.first_column = first_column;
   i.last_column = last_column;
+  i.src_enc = encoding;
 
-  if (!ss_is_empty (i.input))
+  if (ss_is_empty (input))
     {
-      ok = handlers[i.format] (&i);
-      if (!ok)
-        default_result (&i);
+      default_result (&i);
+      return true;
+    }
+
+  if (fmt_get_category (format) & ( FMT_CAT_BINARY | FMT_CAT_HEXADECIMAL | FMT_CAT_LEGACY))
+    {
+      i.input = input;
     }
   else
     {
-      default_result (&i);
-      ok = true;
+      const char *dest_encoding;
+      char *s = NULL;
+      if ( dict == NULL)
+       {
+         assert (0 == (fmt_get_category (format) & (FMT_CAT_BINARY | FMT_CAT_STRING)));
+         dest_encoding = LEGACY_NATIVE;
+       }
+      else
+       dest_encoding = dict_get_encoding (dict);
+
+      s = recode_string (dest_encoding, i.src_enc, ss_data (input), ss_length (input));
+      ss_alloc_uninit (&i.input, strlen (s));
+      memcpy (ss_data (i.input), s, ss_length (input));
+      free (s);
     }
 
-  if (copy)
-    free (copy);
+  ok = handlers[i.format] (&i);
+  if (!ok)
+    default_result (&i);
 
   return ok;
 }
@@ -617,9 +624,8 @@ parse_A (struct data_in *i)
   const char *src = ss_data (i->input);
   size_t src_size = ss_length (i->input);
 
-  char *s = recode_string (LEGACY_NATIVE, i->encoding, src, MIN (src_size, dst_size));
-  memcpy (dst, s, dst_size);
-  free (s);
+  memcpy (dst, src, MIN (src_size, dst_size));
+
   if (dst_size > src_size)
     memset (&dst[src_size], ' ', dst_size - src_size);
 
@@ -645,10 +651,10 @@ parse_AHEX (struct data_in *i)
           return false;
         }
 
-      if (0 != strcmp (i->encoding, LEGACY_NATIVE))
+      if (0 != strcmp (i->src_enc, LEGACY_NATIVE))
         {
-          hi = legacy_to_native (i->encoding, hi);
-          lo = legacy_to_native (i->encoding, lo);
+          hi = legacy_to_native (i->src_enc, hi);
+          lo = legacy_to_native (i->src_enc, lo);
         }
       if (!c_isxdigit (hi) || !c_isxdigit (lo))
        {
index 5256bb9132553b46075f4f5526c20f8e936f7e8f..3ebd5933c43b0370e29cfd279cd3b22fcdbb0b4d 100644 (file)
 
 enum fmt_type;
 union value;
+struct dictionary;
 bool data_in (struct substring input, const char *encoding,
               enum fmt_type, int implied_decimals,
               int first_column, int last_column,
+             const struct dictionary *dict,
               union value *output, int width);
 
 #endif /* data/data-in.h */
index de85748856e003928f67512b17f93e265cead03e..d43af347a701693224980ea18281eaf72d6c0e60 100644 (file)
@@ -86,7 +86,7 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds)
   bool ok;
 
   dict = in_input_program () ? dataset_dict (ds) : dict_create ();
-  parser = data_parser_create ();
+  parser = data_parser_create (dict);
   reader = NULL;
 
   table = -1;                /* Print table if nonzero, -1=undecided. */
index eab32868431bdf007aebf4b5d752ae9da843c257..8f189b1b212c6bccf497e28b68900612e6989149 100644 (file)
@@ -41,6 +41,7 @@
 /* Data parser for textual data like that read by DATA LIST. */
 struct data_parser
   {
+    const struct dictionary *dict; /*Dictionary of destination */
     enum data_parser_type type; /* Type of data to parse. */
     int skip_records;           /* Records to skip before first real data. */
     casenumber max_cases;       /* Max number of cases to read. */
@@ -79,7 +80,7 @@ static void set_any_sep (struct data_parser *parser);
 
 /* Creates and returns a new data parser. */
 struct data_parser *
-data_parser_create (void)
+data_parser_create (const struct dictionary *dict)
 {
   struct data_parser *parser = xmalloc (sizeof *parser);
 
@@ -91,6 +92,7 @@ data_parser_create (void)
   parser->fields = NULL;
   parser->field_cnt = 0;
   parser->field_allocated = 0;
+  parser->dict = dict;
 
   parser->span = true;
   parser->empty_line_has_field = false;
@@ -531,6 +533,7 @@ parse_fixed (const struct data_parser *parser, struct dfm_reader *reader,
                             f->format.w),
                  encoding, f->format.type, f->format.d,
                  f->first_column, f->first_column + f->format.w,
+                parser->dict,
                  case_data_rw_idx (c, f->case_idx),
                  fmt_var_width (&f->format));
 
@@ -574,6 +577,7 @@ parse_delimited_span (const struct data_parser *parser,
 
       data_in (s, encoding, f->format.type, 0,
                first_column, last_column,
+              parser->dict,
                case_data_rw_idx (c, f->case_idx),
                fmt_var_width (&f->format));
     }
@@ -614,6 +618,7 @@ parse_delimited_no_span (const struct data_parser *parser,
 
       data_in (s, encoding, f->format.type, 0,
                first_column, last_column,
+              parser->dict,
                case_data_rw_idx (c, f->case_idx),
                fmt_var_width (&f->format));
     }
index b250e91bb53d2d7cf7b628fd6f41cb8113f7f30b..5a53a2f64ddcc3ab5c30286f438df15158014e4a 100644 (file)
@@ -38,7 +38,7 @@ enum data_parser_type
   };
 
 /* Creating and configuring any parser. */
-struct data_parser *data_parser_create (void);
+struct data_parser *data_parser_create (const struct dictionary *dict);
 void data_parser_destroy (struct data_parser *);
 
 enum data_parser_type data_parser_get_type (const struct data_parser *);
index e4ab76a9992739c78a36f6ad2a98c4f6e0b48d83..32202babdea8848f5c3a06b6431b0db3c4b007ff 100644 (file)
@@ -271,7 +271,7 @@ static int
 parse_get_txt (struct lexer *lexer, struct dataset *ds)
 {
   struct data_parser *parser = NULL;
-  struct dictionary *dict = NULL;
+  struct dictionary *dict = dict_create ();
   struct file_handle *fh = NULL;
   struct dfm_reader *reader = NULL;
 
@@ -288,7 +288,7 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds)
   if (fh == NULL)
     goto error;
 
-  parser = data_parser_create ();
+  parser = data_parser_create (dict);
   has_type = false;
   data_parser_set_type (parser, DP_DELIMITED);
   data_parser_set_span (parser, false);
@@ -465,7 +465,7 @@ parse_get_txt (struct lexer *lexer, struct dataset *ds)
     }
   lex_match (lexer, '=');
 
-  dict = dict_create ();
+
   record = 1;
   type = data_parser_get_type (parser);
   do
index 52d4226dff60ceec92657364a2b6f227d108e11b..d283867214811ea142d83cafd39d9b69faf2a0a0 100644 (file)
@@ -573,7 +573,7 @@ string function RTRIM (string s, string c)
 function NUMBER (string s, ni_format f)
 {
   union value out;
-  data_in (ss_head (s, f->w), LEGACY_NATIVE, f->type, f->d, 0, 0, &out, 0);
+  data_in (ss_head (s, f->w), LEGACY_NATIVE, f->type, f->d, 0, 0, NULL, &out, 0);
   return out.f;
 }
 
index 2cf9cf2bb9ad71f91d6ad301c4625d6b2a7cd012..c780d86f04e95429bad3ee1004bbf2021ab89884 100644 (file)
@@ -99,8 +99,9 @@ parse_number (struct lexer *lexer, double *x, const enum fmt_type *format)
   else if (lex_token (lexer) == T_STRING && format != NULL)
     {
       union value v;
+      assert (! (fmt_get_category (*format) & ( FMT_CAT_STRING )));
       data_in (ds_ss (lex_tokstr (lexer)), LEGACY_NATIVE,
-               *format, 0, 0, 0, &v, 0);
+               *format, 0, 0, 0, NULL, &v, 0);
       lex_get (lexer);
       *x = v.f;
       if (*x == SYSMIS)
index e8a382a3d51cb739162b9ba192d24b5566c0357c..62b03ba073b9a5f6f6a1c5b282d9c26b0ce286b9 100644 (file)
@@ -83,6 +83,8 @@ struct recode_trns
   {
     struct pool *pool;
 
+
+
     /* Variable types, for convenience. */
     enum val_type src_type;     /* src_vars[*] type. */
     enum val_type dst_type;     /* dst_vars[*] type. */
@@ -90,6 +92,7 @@ struct recode_trns
     /* Variables. */
     const struct variable **src_vars;  /* Source variables. */
     const struct variable **dst_vars;  /* Destination variables. */
+    const struct dictionary *dst_dict;  /* Dictionary of dst_vars */
     char **dst_names;          /* Name of dest variables, if they're new. */
     size_t var_cnt;             /* Number of variables. */
 
@@ -540,6 +543,8 @@ create_dst_vars (struct recode_trns *trns, struct dictionary *dict)
 {
   size_t i;
 
+  trns->dst_dict = dict;
+
   for (i = 0; i < trns->var_cnt; i++)
     {
       const struct variable **var = &trns->dst_vars[i];
@@ -625,7 +630,7 @@ find_src_string (struct recode_trns *trns, const uint8_t *value,
 
             msg_disable ();
             match = data_in (ss_buffer (value, width), LEGACY_NATIVE,
-                             FMT_F, 0, 0, 0, &uv, 0);
+                             FMT_F, 0, 0, 0, trns->dst_dict,  &uv, 0);
             msg_enable ();
             out->value.f = uv.f;
             break;
index 86d295830bc2eb82a54fdf70be12e91d704434eb..f24bdbd0d87a577e54c146568dcfcc4564bc5853 100644 (file)
@@ -599,6 +599,7 @@ value_comparator_create (const struct variable *var, const char *target)
                   LEGACY_NATIVE,
                  fmt->type,
                  0, 0, 0,
+                 NULL,
                  &vc->pattern, width) )
     {
       value_destroy (&vc->pattern, width);
index 4ec4bb0c1a9601601b0e02b2f1cc2b7a185856f6..d670002a467fc741bacafd4480f63782e97ef7b6 100644 (file)
@@ -63,6 +63,7 @@ value_to_text (union value v, const PsppireDict *dict, struct fmt_spec format)
 
 gboolean
 text_to_value (const gchar *text, union value *v,
+              const PsppireDict *dict,
              struct fmt_spec format)
 {
   bool ok;
@@ -86,6 +87,7 @@ text_to_value (const gchar *text, union value *v,
 
   msg_disable ();
   ok = data_in (ss_cstr (text), LEGACY_NATIVE, format.type, 0, 0, 0,
+               dict->dict,
                 v, fmt_var_width (&format));
   msg_enable ();
 
index 2a7be4aa14266c98ec96adb51326bba1a69eda5e..f6c084d48e8373d12366b24455f45267daacd89b 100644 (file)
@@ -38,6 +38,7 @@ gchar * value_to_text (union value v, const PsppireDict *dict, struct fmt_spec f
 
 
 gboolean text_to_value (const gchar *text, union value *v,
+                       const PsppireDict *dict,
                       struct fmt_spec format);
 
 GObject *get_object_assert (GtkBuilder *builder, const gchar *name, GType type);
index 9230b8a6e58313a87a57a081931661041428d1d6..16a7f6f34ba7bde4aea39394305def0327824a57 100644 (file)
@@ -100,7 +100,8 @@ missing_val_dialog_accept (GtkWidget *w, gpointer data)
              continue;
            }
 
-         if ( text_to_value (text, &v, *write_spec))
+         if ( text_to_value (text, &v, 
+                             dialog->dict, *write_spec))
            {
              nvals++;
              mv_add_value (&dialog->mvl, &v);
@@ -126,9 +127,9 @@ missing_val_dialog_accept (GtkWidget *w, gpointer data)
       const gchar *low_text = gtk_entry_get_text (GTK_ENTRY (dialog->low));
       const gchar *high_text = gtk_entry_get_text (GTK_ENTRY (dialog->high));
 
-      if ( text_to_value (low_text, &low_val, *write_spec)
+      if ( text_to_value (low_text, &low_val, dialog->dict, *write_spec)
           &&
-          text_to_value (high_text, &high_val, *write_spec) )
+          text_to_value (high_text, &high_val, dialog->dict, *write_spec) )
        {
          if ( low_val.f > high_val.f )
            {
@@ -154,6 +155,7 @@ missing_val_dialog_accept (GtkWidget *w, gpointer data)
        {
          union value discrete_val;
          if ( !text_to_value (discrete_text, &discrete_val,
+                              dialog->dict,
                              *write_spec))
            {
              err_dialog (_("Incorrect value for variable type"),
index a97cbbb3e41e08d971ddb5dcda088a3c8a11b33b..9833fb496f8a0be6dd3145fc7bbb334fe46b341f 100644 (file)
@@ -959,7 +959,8 @@ psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
                         FALSE);
   value_init (&value, width);
   ok = (datasheet_get_value (ds->datasheet, casenum, idx, &value)
-        && data_in (input, dict_get_encoding (dict->dict), fmt->type, 0, 0, 0, &value, width)
+        && data_in (input, UTF8, fmt->type, 0, 0, 0,
+                   dict->dict, &value, width)
         && datasheet_put_value (ds->datasheet, casenum, idx, &value));
   value_destroy (&value, width);
 
index 330d284741e6cd64185f8dc3faefe86ebd705554..4baa99e014b169426e69fd978850bf27e9b9992e 100644 (file)
@@ -1748,7 +1748,9 @@ parse_field (struct import_assistant *ia,
   if (field.string != NULL)
     {
       msg_disable ();
+      /* FIXME: NULL should be replaced with the destination dictionary */
       if (!data_in (field, LEGACY_NATIVE, in->type, 0, 0, 0,
+                   NULL,
                     &val, var_get_width (var)))
         {
           char fmt_string[FMT_STRING_LEN_MAX + 1];
index 92a7fe8e0c77c7a5096e46c23cd6e45b4a2b4088..4b575d9779799b7d5850d683dd57afe17ba98a66 100644 (file)
@@ -72,6 +72,7 @@ on_label_entry_change (GtkEntry *entry, gpointer data)
   text = gtk_entry_get_text (GTK_ENTRY (dialog->value_entry));
 
   text_to_value (text, &v,
+                dialog->var_store->dict,
                *var_get_write_format (dialog->pv));
 
 
@@ -142,6 +143,7 @@ on_value_entry_change (GtkEntry *entry, gpointer data)
 
   union value v;
   text_to_value (text, &v,
+                dialog->var_store->dict,
                *var_get_write_format (dialog->pv));
 
 
@@ -268,6 +270,7 @@ on_change (GtkWidget *w, gpointer data)
   union value v;
 
   text_to_value (val_text, &v,
+                dialog->var_store->dict,
                *var_get_write_format (dialog->pv));
 
   val_labs_replace (dialog->labs, &v,
@@ -292,6 +295,7 @@ on_add (GtkWidget *w, gpointer data)
   const gchar *text = gtk_entry_get_text (GTK_ENTRY (dialog->value_entry));
 
   text_to_value (text, &v,
+                dialog->var_store->dict,
                *var_get_write_format (dialog->pv));
 
 
index f063fa3965b4c840b76ec02a91bf08733e85a27a..22e717ac965903acdb5a8b12f95e5e3dd6492832 100644 (file)
@@ -152,8 +152,9 @@ syntax_gen_number (struct string *output,
       v_in.f = number;
       s = data_out (&v_in, "FIXME",  format);
       msg_disable ();
+      /* FIXME: UTF8 encoded strings will fail here */
       ok = data_in (ss_cstr (s), LEGACY_NATIVE,
-                    format->type, false, 0, 0, &v_out, 0);
+                    format->type, false, 0, 0, NULL, &v_out, 0);
       msg_enable ();
       if (ok && v_out.f == number)
         {