X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fods-reader.c;h=2ce4e7eb9ba268d188564b94a9d4dc24df0b0d42;hb=5c210c96542db2a357cf1aa6b690ef2ea88a54b1;hp=9c165f9c92e30bd305a233f7b8bf4e4e57e2a50d;hpb=2937ab5b637f5d7cc85db92aa9958707249f7392;p=pspp diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index 9c165f9c92..2ce4e7eb9b 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -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; @@ -333,63 +336,113 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, } -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.sheets = sheet_count; + + ds_destroy (&errs); + + 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 +455,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; @@ -513,7 +566,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 ) @@ -560,7 +613,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 ) { @@ -580,7 +633,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 ) { @@ -592,6 +645,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; } @@ -615,7 +673,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);