X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fgnumeric-reader.c;h=f166ee6aba86f1a00acefb409c466e253635a574;hb=71cc988f2ad781457fd5d43f284990825fcd9a8d;hp=cc8d335b3cff0dcf9bb8c571d0a1f3e8eb8e508c;hpb=0d70c2c8ed5d4ae5b40bb98c6c31db4f8ba87d68;p=pspp-builds.git diff --git a/src/data/gnumeric-reader.c b/src/data/gnumeric-reader.c index cc8d335b..f166ee6a 100644 --- a/src/data/gnumeric-reader.c +++ b/src/data/gnumeric-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 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 @@ -19,6 +19,9 @@ #include #include +#include + +#include "minmax.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -57,13 +60,14 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict) #include #include +/* 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 struct casereader_class gnm_file_casereader_class = +static const struct casereader_class gnm_file_casereader_class = { gnm_file_casereader_read, gnm_file_casereader_destroy, @@ -169,10 +173,9 @@ 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; }; @@ -193,7 +196,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 +313,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,18 +320,17 @@ 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); + const char *text = (const char *) xv; if ( text) n_bytes = MIN (var_get_width (var), strlen (text)); if ( var_is_alpha (var)) { - memcpy (v->s, text, n_bytes); + memcpy (value_str_rw (v, var_get_width (var)), text, n_bytes); } else { @@ -396,8 +340,6 @@ convert_xml_string_to_value (struct ccase *c, const struct variable *var, if ( errno != 0 || endptr == text) v->f = SYSMIS; } - - free (text); } struct var_spec @@ -410,6 +352,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 +365,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; @@ -511,7 +454,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 +462,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 = (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 +478,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 +503,25 @@ 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, (const char *) xmlTextReaderConstEncoding (r->xtr)); for (i = 0 ; i < n_var_specs ; ++i ) { - struct string name; + char name[VAR_NAME_LEN + 1]; - /* 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; + var_spec[i].width = GNUMERIC_DEFAULT_WIDTH; - 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); - - - dict_create_var (r->dict, ds_cstr (&name), var_spec[i].width); + if ( ! dict_make_unique_var_name (r->dict, var_spec[i].name, + &vstart, name)) + { + msg (ME, _("Cannot create variable name from %s"), var_spec[i].name); + goto error; + } - ds_destroy (&name); + dict_create_var (r->dict, name, var_spec[i].width); } /* Create the first case, and cache it */ @@ -598,15 +534,15 @@ gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict) 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 +556,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 +577,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 +590,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 +606,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 +627,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; + } }