X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fgnumeric-reader.c;h=56ebc3062aed3090ccf26748b8d96a105bac85dc;hb=2f7b367bf796c63c595ac837b716cce535ffd5bf;hp=522176640489c87ec57027115582cbb9bc26d617;hpb=c725a4f64718ef1ee4139c27c94b2eb6447b51b4;p=pspp-builds.git diff --git a/src/data/gnumeric-reader.c b/src/data/gnumeric-reader.c index 52217664..56ebc306 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, 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 @@ -14,54 +14,53 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - - #include -#include +#include "libpspp/message.h" +#include "libpspp/misc.h" + +#include "gl/minmax.h" #include "gettext.h" #define _(msgid) gettext (msgid) #define N_(msgid) (msgid) +#include "spreadsheet-reader.h" #if !GNM_SUPPORT struct casereader * -gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict) +gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) { - msg (ME, _("Support for Gnumeric files was not compiled into this installation of PSPP")); + msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "Gnumeric"); return NULL; } #else -#include -#include -#include -#include -#include -#include -#include +#include "data/gnumeric-reader.h" +#include +#include #include #include #include -#include - -#include -#include -#include "gnumeric-reader.h" -#include -#include +#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 "gl/xalloc.h" 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 = { @@ -71,73 +70,6 @@ static const struct casereader_class gnm_file_casereader_class = NULL, }; -/* Convert a string, which is an integer encoded in base26 - IE, A=0, B=1, ... Z=25 to the integer it represents. - ... except that in this scheme, digits with an exponent - greater than 1 are implicitly incremented by 1, so - AA = 0 + 1*26, AB = 1 + 1*26, - ABC = 2 + 2*26 + 1*26^2 .... -*/ -static int -pseudo_base26 (const char *str) -{ - int i; - int multiplier = 1; - int result = 0; - int len = strlen (str); - - for ( i = len - 1 ; i >= 0; --i) - { - int mantissa = (str[i] - 'A'); - - if ( mantissa < 0 || mantissa > 25 ) - return -1; - - if ( i != len - 1) - mantissa++; - - result += mantissa * multiplier; - - multiplier *= 26; - } - - return result; -} - - - -/* Convert a cell reference in the form "A1:B2", to - integers. A1 means column zero, row zero. - B1 means column 1 row 0. AA1 means column 26, row 0. -*/ -static bool -convert_cell_ref (const char *ref, - int *col0, int *row0, - int *coli, int *rowi) -{ - char startcol[5]; - char stopcol [5]; - - int startrow; - int stoprow; - - int n = sscanf (ref, "%4[a-zA-Z]%d:%4[a-zA-Z]%d", - startcol, &startrow, - stopcol, &stoprow); - if ( n != 4) - return false; - - str_uppercase (startcol); - *col0 = pseudo_base26 (startcol); - str_uppercase (stopcol); - *coli = pseudo_base26 (stopcol); - *row0 = startrow - 1; - *rowi = stoprow - 1 ; - - return true; -} - - enum reader_state { STATE_INIT = 0, /* Initial state */ @@ -169,18 +101,14 @@ 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 _xmlchar_to_int(X) atoi((const char *)X) static void gnm_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) @@ -193,7 +121,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); } @@ -315,29 +245,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 @@ -348,7 +271,7 @@ struct var_spec }; struct casereader * -gnumeric_open_reader (struct gnumeric_read_info *gri, struct dictionary **dict) +gnumeric_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) { unsigned long int vstart = 0; int ret; @@ -363,7 +286,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; @@ -383,7 +306,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; } @@ -452,7 +375,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; @@ -460,16 +383,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 @@ -478,11 +399,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), SPREADSHEET_DEFAULT_WIDTH) : gri->asw; } free (value); - free (text); } else if ( r->node_type == XML_READER_TYPE_ELEMENT && r->state == STATE_CELL) @@ -502,29 +422,21 @@ 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 = r->dict = dict_create ( + CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr))); for (i = 0 ; i < n_var_specs ; ++i ) { - char name[VAR_NAME_LEN + 1]; + char *name; /* 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 ( ! 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; - } + var_spec[i].width = SPREADSHEET_DEFAULT_WIDTH; + 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 */ @@ -532,20 +444,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); } @@ -559,7 +471,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); @@ -580,12 +492,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_; @@ -593,14 +505,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))) @@ -611,7 +521,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) @@ -632,7 +542,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; + } }