X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata%2Fods-reader.c;h=d6ed43e8f64257db79ad48bd7fbc0ad451bfb523;hb=32b010ba3a0cfcd82f6d274a64b709777a848421;hp=ea8b9ad56b62fa279116a21703cfaf529ec747ec;hpb=39cf51da9adfebd07ca8159e188bd37201ad5790;p=pspp diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index ea8b9ad56b..d6ed43e8f6 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011, 2012 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 @@ -33,7 +33,8 @@ #if !ODF_READ_SUPPORT struct casereader * -ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) +ods_open_reader (const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts, + struct dictionary **dict) { msg (ME, _("Support for %s files was not compiled into this installation of PSPP"), "OpenDocument"); @@ -87,6 +88,8 @@ enum reader_state struct ods_reader { + struct spreadsheet spreadsheet; + xmlTextReaderPtr xtr; enum reader_state state; @@ -324,72 +327,123 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, text = xmv->value ? CHAR_CAST (const char *, xmv->value) : CHAR_CAST (const char *, xmv->text); - data_in (ss_cstr (text), "UTF-8", - fmt->type, - v, - var_get_width (var), - "UTF-8"); + free (data_in (ss_cstr (text), "UTF-8", + fmt->type, + v, + var_get_width (var), + "UTF-8")); } } -struct casereader * -ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) +/* Try to find out how many sheets there are in the "workbook" */ +static int +get_sheet_count (struct zip_reader *zreader) { - int ret = 0; - xmlChar *type = NULL; - unsigned long int vstart = 0; - casenumber n_cases = CASENUMBER_MAX; - int i; - struct var_spec *var_spec = NULL; - int n_var_specs = 0; + xmlTextReaderPtr mxtr; + struct zip_member *meta = NULL; + meta = zip_member_open (zreader, "meta.xml"); + + if ( meta == NULL) + return -1; - struct ods_reader *r = xzalloc (sizeof *r); + mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, + (xmlInputCloseCallback) zip_member_finish, + meta, NULL, NULL, XML_PARSE_RECOVER); + + while (1 == xmlTextReaderRead (mxtr)) + { + xmlChar *name = xmlTextReaderName (mxtr); + if ( 0 == xmlStrcmp (name, _xml("meta:document-statistic"))) + { + xmlChar *attr = xmlTextReaderGetAttribute (mxtr, _xml ("meta:table-count")); + + if ( attr != NULL) + { + int s = _xmlchar_to_int (attr); + return s; + } + } + } + return -1; +} + +struct spreadsheet *ods_probe (const char *filename) +{ + struct ods_reader *r; + struct string errs; + xmlTextReaderPtr xtr ; + int sheet_count; struct zip_member *content = NULL; - struct zip_reader *zreader ; - xmlChar *val_string = NULL; - r->read_names = gri->read_names; - ds_init_empty (&r->ods_errs); + struct zip_reader *zreader = NULL; - zreader = zip_reader_create (gri->file_name, &r->ods_errs); + ds_init_empty (&errs); - if ( NULL == zreader) - { - msg (ME, _("Error opening `%s' for reading as a OpenDocument spreadsheet file: %s."), - gri->file_name, ds_cstr (&r->ods_errs)); + zreader = zip_reader_create (filename, &errs); - goto error; - } + if (zreader == NULL) + return NULL; content = zip_member_open (zreader, "content.xml"); - if ( NULL == content) - { - msg (ME, _("Could not extract OpenDocument spreadsheet from file `%s': %s."), - gri->file_name, ds_cstr (&r->ods_errs)); - goto error; - } + if ( content == NULL) + goto error; zip_member_ref (content); - r->xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, + sheet_count = get_sheet_count (zreader); + + xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, (xmlInputCloseCallback) zip_member_finish, content, NULL, NULL, XML_PARSE_RECOVER); - if ( r->xtr == NULL) - { - goto error; - } + if ( xtr == NULL) + goto error; + + r = xzalloc (sizeof *r); + r->xtr = xtr; + r->spreadsheet.type = SPREADSHEET_ODS; + r->spreadsheet.n_sheets = sheet_count; + + ds_destroy (&errs); + + r->spreadsheet.file_name = filename; + return &r->spreadsheet; + + error: + zip_reader_destroy (zreader); + ds_destroy (&errs); + return NULL; +} + +struct casereader * +ods_make_reader (struct spreadsheet *spreadsheet, + const struct spreadsheet_read_info *gri, struct spreadsheet_read_options *opts) +{ + intf ret = 0; + xmlChar *type = NULL; + unsigned long int vstart = 0; + casenumber n_cases = CASENUMBER_MAX; + int i; + struct var_spec *var_spec = NULL; + int n_var_specs = 0; + + struct ods_reader *r = (struct ods_reader *) spreadsheet; + xmlChar *val_string = NULL; - if ( gri->cell_range ) + assert (r); + r->read_names = gri->read_names; + ds_init_empty (&r->ods_errs); + + if ( opts->cell_range ) { - if ( ! convert_cell_ref (gri->cell_range, + if ( ! convert_cell_ref (opts->cell_range, &r->start_col, &r->start_row, &r->stop_col, &r->stop_row)) { msg (SE, _("Invalid cell range `%s'"), - gri->cell_range); + opts->cell_range); goto error; } } @@ -402,8 +456,8 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) } r->state = STATE_INIT; - r->target_sheet = BAD_CAST gri->sheet_name; - r->target_sheet_index = gri->sheet_index; + r->target_sheet = BAD_CAST opts->sheet_name; + r->target_sheet_index = opts->sheet_index; r->row = r->col = -1; r->sheet_index = 0; @@ -411,8 +465,10 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) /* If CELLRANGE was given, then we know how many variables should be read */ if ( r->stop_col != -1 ) { + assert (var_spec == NULL); n_var_specs = r->stop_col - r->start_col + 1; var_spec = xrealloc (var_spec, sizeof (*var_spec) * n_var_specs); + memset (var_spec, '\0', sizeof (*var_spec) * n_var_specs); } @@ -428,7 +484,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) if (ret < 1) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), - gri->file_name); + spreadsheet->file_name); goto error; } @@ -460,7 +516,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1)); /* xrealloc (unlike realloc) doesn't initialise its memory to 0 */ - memset (var_spec + n_var_specs * sizeof (*var_spec), + memset (var_spec + n_var_specs, 0, (n_var_specs - idx + 1) * sizeof (*var_spec)); n_var_specs = idx + 1; @@ -511,7 +567,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) } /* Create the dictionary and populate it */ - *dict = r->dict = dict_create ( + r->spreadsheet.dict = r->dict = dict_create ( CHAR_CAST (const char *, xmlTextReaderConstEncoding (r->xtr))); for (i = 0 ; i < n_var_specs ; ++i ) @@ -543,7 +599,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) if ( n_var_specs == 0 ) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), - gri->file_name); + spreadsheet->file_name); goto error; } @@ -558,7 +614,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) convert_xml_to_value (r->first_case, var, &var_spec[i].firstval); } - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -578,7 +634,7 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) error: - zip_reader_destroy (zreader); + // zip_reader_destroy (zreader); for ( i = 0 ; i < n_var_specs ; ++i ) { @@ -590,6 +646,11 @@ ods_open_reader (struct spreadsheet_read_info *gri, struct dictionary **dict) free (var_spec); + dict_destroy (r->spreadsheet.dict); + r->spreadsheet.dict = NULL; + ods_file_casereader_destroy (NULL, r); + + return NULL; } @@ -613,7 +674,6 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_) return r->first_case; } - if ( r->state > STATE_INIT) { c = case_create (r->proto);