Update all #include directives to the currently preferred style.
[pspp-builds.git] / src / data / gnumeric-reader.c
index 418d63c2d05dc85f2cd993687e6b036dc7eee26c..6392f9b805d620ccbea4bf139bbbfc3c0cf3aac9 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2010, 2011 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
 
 #include <config.h>
 
-#include <libpspp/message.h>
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+
+#include "gl/minmax.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -37,31 +40,31 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
 #else
 
-#include <data/casereader-provider.h>
-#include <errno.h>
-#include <libpspp/str.h>
-#include <libpspp/i18n.h>
-#include <data/dictionary.h>
-#include <data/variable.h>
-#include <xalloc.h>
+#include "data/gnumeric-reader.h"
 
+#include <assert.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <libxml/xmlreader.h>
 #include <zlib.h>
-#include <stdbool.h>
 
-#include <data/case.h>
-#include <data/value.h>
+#include "data/case.h"
+#include "data/casereader-provider.h"
+#include "data/dictionary.h"
+#include "data/identifier.h"
+#include "data/value.h"
+#include "data/variable.h"
+#include "libpspp/i18n.h"
+#include "libpspp/str.h"
 
-#include "gnumeric-reader.h"
-#include <data/identifier.h>
-#include <assert.h>
+#include "gl/xalloc.h"
 
+/* Default width of string variables. */
+#define GNUMERIC_DEFAULT_WIDTH 8
 
 static void gnm_file_casereader_destroy (struct casereader *, void *);
 
-static bool gnm_file_casereader_read (struct casereader *, void *,
-                                     struct ccase *);
+static struct ccase *gnm_file_casereader_read (struct casereader *, void *);
 
 static const struct casereader_class gnm_file_casereader_class =
   {
@@ -169,18 +172,17 @@ struct gnumeric_reader
   int stop_row;
   int stop_col;
 
-
-  size_t value_cnt;
+  struct caseproto *proto;
   struct dictionary *dict;
-  struct ccase first_case;
+  struct ccase *first_case;
   bool used_first_case;
 };
 
 static void process_node (struct gnumeric_reader *r);
 
-#define _xml(X) (const xmlChar *)(X)
+#define _xml(X) (CHAR_CAST (const xmlChar *, X))
 
-#define _xmlchar_to_int(X) atoi((const char *)X)
+#define _xmlchar_to_int(X) (atoi(CHAR_CAST (const char *, X)))
 
 static void
 gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
@@ -193,7 +195,9 @@ gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
     xmlFreeTextReader (r->xtr);
 
   if ( ! r->used_first_case )
-    case_destroy (&r->first_case);
+    case_unref (r->first_case);
+
+  caseproto_unref (r->proto);
 
   free (r);
 }
@@ -308,66 +312,6 @@ process_node (struct gnumeric_reader *r)
 }
 
 
-
-/*
-  Change SUGGESTION until it's a valid name that can be added to DICT.
-*/
-static void
-devise_name (const struct dictionary *dict, struct string *name, int *x)
-{
-  struct string basename;
-  if ( ds_is_empty (name))
-    ds_init_cstr (&basename, "var");
-  else
-    ds_init_string (&basename, name);
-  do
-    {
-      ds_clear (name);
-      ds_put_format (name, "%s%d", ds_cstr (&basename), ++(*x));
-    }
-  while (NULL != dict_lookup_var (dict, ds_cstr (name)) );
-
-  ds_destroy (&basename);
-}
-
-/*
-   Mutate NAME of a variable, which is gauranteed to be valid for the
-   dictionary DICT.
-*/
-static void
-munge_name (const struct dictionary *dict, struct string *name)
-{
-  int x = 0;
-
-  if (! ds_is_empty (name))
-    {
-      /* Change all the invalid characters to valid ones */
-      char *s;
-
-      s = ds_data (name);
-
-      if ( !lex_is_id1 (*s))
-       *s = '@';
-
-      s++;
-
-      while (s < ds_data (name) + ds_length (name))
-       {
-         if ( !lex_is_idn (*s))
-           *s = '_';
-         s++;
-       }
-
-      assert (var_is_valid_name (ds_cstr (name), false));
-    }
-
-  while (ds_is_empty (name) || NULL != dict_lookup_var (dict, ds_cstr (name)) )
-    {
-      devise_name (dict, name, &x);
-    }
-}
-
-
 /*
    Sets the VAR of case C, to the value corresponding to the xml string XV
  */
@@ -375,29 +319,22 @@ static void
 convert_xml_string_to_value (struct ccase *c, const struct variable *var,
                             const xmlChar *xv)
 {
-  char *text;
-  int n_bytes = 0;
   union value *v = case_data_rw (c, var);
 
-  text = recode_string (CONV_UTF8_TO_PSPP, (const char *) xv, -1);
-
-  if ( text)
-    n_bytes = MIN (var_get_width (var), strlen (text));
-
-  if ( var_is_alpha (var))
-    {
-      memcpy (v->s, text, n_bytes);
-    }
+  if (xv == NULL)
+    value_set_missing (v, var_get_width (var));
+  else if ( var_is_alpha (var))
+    value_copy_str_rpad (v, var_get_width (var), xv, ' ');
   else
     {
+      const char *text = CHAR_CAST (const char *, xv);
       char *endptr;
+
       errno = 0;
       v->f = strtod (text, &endptr);
       if ( errno != 0 || endptr == text)
        v->f = SYSMIS;
     }
-
-  free (text);
 }
 
 struct var_spec
@@ -410,6 +347,7 @@ struct var_spec
 struct casereader *
 gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 {
+  unsigned long int vstart = 0;
   int ret;
   casenumber n_cases = CASENUMBER_MAX;
   int i;
@@ -422,7 +360,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
   if ( NULL == gz)
     {
-      msg (ME, _("Error opening \"%s\" for reading as a gnumeric file: %s."),
+      msg (ME, _("Error opening `%s' for reading as a Gnumeric file: %s."),
            gri->file_name, strerror (errno));
 
       goto error;
@@ -442,7 +380,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
                               &r->start_col, &r->start_row,
                               &r->stop_col, &r->stop_row))
        {
-         msg (SE, _("Invalid cell range \"%s\""),
+         msg (SE, _("Invalid cell range `%s'"),
               gri->cell_range);
          goto error;
        }
@@ -511,7 +449,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
       if ( idx  >= n_var_specs )
        {
          n_var_specs =  idx + 1 ;
-         var_spec = realloc (var_spec, sizeof (*var_spec) * n_var_specs);
+         var_spec = xrealloc (var_spec, sizeof (*var_spec) * n_var_specs);
          var_spec [idx].name = NULL;
          var_spec [idx].width = -1;
          var_spec [idx].first_value = NULL;
@@ -519,16 +457,14 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
       if ( r->node_type == XML_READER_TYPE_TEXT )
        {
-         char *text ;
          xmlChar *value = xmlTextReaderValue (r->xtr);
-
-         text = recode_string (CONV_UTF8_TO_PSPP, (const char *) value, -1);
+         const char *text  = CHAR_CAST (const char *, value);
 
          if ( r->row < r->start_row)
            {
              if ( gri->read_names )
                {
-                 var_spec [idx].name = strdup (text);
+                 var_spec [idx].name = xstrdup (text);
                }
            }
          else
@@ -537,11 +473,10 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
              if (-1 ==  var_spec [idx].width )
                var_spec [idx].width = (gri->asw == -1) ?
-                 ROUND_UP (strlen(text), MAX_SHORT_STRING) : gri->asw;
+                 ROUND_UP (strlen(text), GNUMERIC_DEFAULT_WIDTH) : gri->asw;
            }
 
          free (value);
-         free (text);
        }
       else if ( r->node_type == XML_READER_TYPE_ELEMENT
                && r->state == STATE_CELL)
@@ -563,29 +498,20 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
   /* Create the dictionary and populate it */
   *dict = r->dict = dict_create ();
 
-  r->value_cnt = 0;
+  dict_set_encoding (r->dict, CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr)));
 
   for (i = 0 ; i < n_var_specs ; ++i )
     {
-      struct string name;
+      char *name;
 
-      /* Probably no data exists for this variable, so allocate a default width */
+      /* Probably no data exists for this variable, so allocate a
+        default width */
       if ( var_spec[i].width == -1 )
-       var_spec[i].width = MAX_SHORT_STRING;
-
-      r->value_cnt += value_cnt_from_width (var_spec[i].width);
-
-      if (var_spec[i].name)
-       ds_init_cstr (&name, var_spec[i].name);
-      else
-       ds_init_empty (&name);
-
-      munge_name (r->dict, &name);
+       var_spec[i].width = GNUMERIC_DEFAULT_WIDTH;
 
-
-      dict_create_var (r->dict, ds_cstr (&name), var_spec[i].width);
-
-      ds_destroy (&name);
+      name = dict_make_unique_var_name (r->dict, var_spec[i].name, &vstart);
+      dict_create_var (r->dict, name, var_spec[i].width);
+      free (name);
     }
 
   /* Create the first case, and cache it */
@@ -593,20 +519,20 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
   if ( n_var_specs ==  0 )
     {
-      msg (MW, _("Selected sheet or range of spreadsheet \"%s\" is empty."),
+      msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
            gri->file_name);
       goto error;
     }
 
-  case_create (&r->first_case, r->value_cnt);
-  memset (case_data_rw_idx (&r->first_case, 0)->s,
-         ' ', MAX_SHORT_STRING * r->value_cnt);
+  r->proto = caseproto_ref (dict_get_proto (r->dict));
+  r->first_case = case_create (r->proto);
+  case_set_missing (r->first_case);
 
   for ( i = 0 ; i < n_var_specs ; ++i )
     {
       const struct variable *var = dict_get_var (r->dict, i);
 
-      convert_xml_string_to_value (&r->first_case, var,
+      convert_xml_string_to_value (r->first_case, var,
                                   var_spec[i].first_value);
     }
 
@@ -620,7 +546,7 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 
   return casereader_create_sequential
     (NULL,
-     r->value_cnt,
+     r->proto,
      n_cases,
      &gnm_file_casereader_class, r);
 
@@ -641,12 +567,12 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict)
 };
 
 
-/* Reads one case from READER's file into C.  Returns true only
-   if successful. */
-static bool
-gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
-                          struct ccase *c)
+/* Reads and returns one case from READER's file.  Returns a null
+   pointer on failure. */
+static struct ccase *
+gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_)
 {
+  struct ccase *c;
   int ret = 0;
 
   struct gnumeric_reader *r = r_;
@@ -654,14 +580,12 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
 
   if ( !r->used_first_case )
     {
-      *c = r->first_case;
       r->used_first_case = true;
-      return true;
+      return r->first_case;
     }
 
-  case_create (c, r->value_cnt);
-
-  memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
+  c = case_create (r->proto);
+  case_set_missing (c);
 
   while ((r->state == STATE_CELL || r->state == STATE_CELLS_START )
         && r->row == current_row && (ret = xmlTextReaderRead (r->xtr)))
@@ -672,7 +596,7 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
                                     r->col > r->stop_col))
        continue;
 
-      if ( r->col - r->start_col >= r->value_cnt)
+      if ( r->col - r->start_col >= caseproto_get_n_widths (r->proto))
        continue;
 
       if ( r->stop_row != -1 && r->row > r->stop_row)
@@ -693,7 +617,13 @@ gnm_file_casereader_read (struct casereader *reader UNUSED, void *r_,
 
     }
 
-  return (ret == 1);
+  if (ret == 1)
+    return c;
+  else
+    {
+      case_unref (c);
+      return NULL;
+    }
 }