X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fods-reader.c;h=b3586b82ec8b7817d77f3f5dffcaf0bde6fd87f5;hb=4c5964204338f984c093f7905ce491ad8923e910;hp=a5ece5c504b394bde637060d603771e8bf7d7145;hpb=267254283291b1872c48557213266b5a714b1d10;p=pspp diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index a5ece5c504..b3586b82ec 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -67,9 +67,9 @@ ods_open_reader (const struct spreadsheet_read_options *opts, #include "gl/xalloc.h" static void ods_file_casereader_destroy (struct casereader *, void *); - static struct ccase *ods_file_casereader_read (struct casereader *, void *); + static const struct casereader_class ods_file_casereader_class = { ods_file_casereader_read, @@ -105,6 +105,7 @@ struct ods_reader struct spreadsheet spreadsheet; struct zip_reader *zreader; xmlTextReaderPtr xtr; + int ref_cnt; enum reader_state state; int row; @@ -113,16 +114,14 @@ struct ods_reader int current_sheet; xmlChar *current_sheet_name; - const xmlChar *target_sheet_name; + xmlChar *target_sheet_name; int target_sheet_index; -#if 1 int start_row; int start_col; int stop_row; int stop_col; -#endif int col_span; @@ -138,6 +137,27 @@ struct ods_reader struct string ods_errs; }; +void +ods_destroy (struct spreadsheet *s) +{ + struct ods_reader *r = (struct ods_reader *) s; + + if (--r->ref_cnt == 0) + { + int i; + + for (i = 0; i < r->n_allocated_sheets; ++i) + { + xmlFree (r->sheets[i].name); + } + + zip_reader_destroy (r->zreader); + free (r->sheets); + free (r); + } +} + + static bool reading_target_sheet (const struct ods_reader *r) @@ -161,17 +181,19 @@ static void process_node (struct ods_reader *r); const char * ods_get_sheet_name (struct spreadsheet *s, int n) { - int ret; struct ods_reader *or = (struct ods_reader *) s; assert (n < s->n_sheets); while ( - (or->n_allocated_sheets <= n) - && - (1 == (ret = xmlTextReaderRead (or->xtr))) + (or->n_allocated_sheets <= n) + || or->state != STATE_SPREADSHEET ) { + int ret = xmlTextReaderRead (or->xtr); + if ( ret != 1) + break; + process_node (or); } @@ -181,23 +203,23 @@ ods_get_sheet_name (struct spreadsheet *s, int n) char * ods_get_sheet_range (struct spreadsheet *s, int n) { - int ret = -1; struct ods_reader *or = (struct ods_reader *) s; assert (n < s->n_sheets); while ( - ( (or->n_allocated_sheets <= n) - || (or->sheets[n].stop_row == -1) ) - && - (1 == (ret = xmlTextReaderRead (or->xtr))) + || (or->sheets[n].stop_row == -1) + || or->state != STATE_SPREADSHEET ) { + int ret = xmlTextReaderRead (or->xtr); + if ( ret != 1) + break; + process_node (or); } - return create_cell_ref ( or->sheets[n].start_col, or->sheets[n].start_row, @@ -227,9 +249,16 @@ ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) caseproto_unref (r->proto); - // free (r); + xmlFree (r->current_sheet_name); + xmlFree (r->target_sheet_name); + + ods_destroy (&r->spreadsheet); } + + + + static void process_node (struct ods_reader *r) { @@ -263,12 +292,13 @@ process_node (struct ods_reader *r) if (r->current_sheet >= r->n_allocated_sheets) { + assert (r->current_sheet == r->n_allocated_sheets); r->sheets = xrealloc (r->sheets, sizeof (*r->sheets) * ++r->n_allocated_sheets); r->sheets[r->n_allocated_sheets - 1].start_col = -1; r->sheets[r->n_allocated_sheets - 1].stop_col = -1; r->sheets[r->n_allocated_sheets - 1].start_row = -1; r->sheets[r->n_allocated_sheets - 1].stop_row = -1; - r->sheets[r->n_allocated_sheets - 1].name = xmlStrdup (r->current_sheet_name); + r->sheets[r->n_allocated_sheets - 1].name = CHAR_CAST (char *, xmlStrdup (r->current_sheet_name)); } r->col = 0; @@ -297,6 +327,8 @@ process_node (struct ods_reader *r) if (! xmlTextReaderIsEmptyElement (r->xtr)) r->state = STATE_ROW; + + xmlFree (value); } else if (0 == xmlStrcasecmp (name, _xml("table:table")) && (XML_READER_TYPE_END_ELEMENT == r->node_type)) @@ -305,7 +337,6 @@ process_node (struct ods_reader *r) } break; case STATE_ROW: - // printf ("%s:%d Name is %s\n", __FILE__, __LINE__, name); if ( (0 == xmlStrcasecmp (name, _xml ("table:table-cell"))) && (XML_READER_TYPE_ELEMENT == r->node_type)) @@ -317,10 +348,10 @@ process_node (struct ods_reader *r) r->col_span = value ? _xmlchar_to_int (value) : 1; r->col += r->col_span; - // printf ("%s:%d %s\n", __FILE__, __LINE__, value); - if (! xmlTextReaderIsEmptyElement (r->xtr)) r->state = STATE_CELL; + + xmlFree (value); } else if ( (0 == xmlStrcasecmp (name, _xml ("table:table-row"))) && @@ -441,7 +472,7 @@ convert_xml_to_value (struct ccase *c, const struct variable *var, if ( 0 == xmlStrcmp (xmv->type, _xml("float"))) { - v->f = c_strtod (xmv->value, NULL); + v->f = c_strtod (CHAR_CAST (const char *, xmv->value), NULL); } else { @@ -471,7 +502,7 @@ get_sheet_count (struct zip_reader *zreader) return -1; mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, - (xmlInputCloseCallback) zip_member_finish, + (xmlInputCloseCallback) NULL, meta, NULL, NULL, 0); while (1 == xmlTextReaderRead (mxtr)) @@ -480,14 +511,21 @@ get_sheet_count (struct zip_reader *zreader) 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); + xmlFreeTextReader (mxtr); + xmlFree (name); + xmlFree (attr); return s; } + xmlFree (attr); } + xmlFree (name); } + + xmlFreeTextReader (mxtr); return -1; } @@ -514,9 +552,10 @@ init_reader (struct ods_reader *r, bool report_errors) if ( content == NULL) return false; - zip_member_ref (content); - + if (r->xtr) + xmlFreeTextReader (r->xtr); + zip_member_ref (content); xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read, (xmlInputCloseCallback) zip_member_finish, content, NULL, NULL, @@ -527,6 +566,10 @@ init_reader (struct ods_reader *r, bool report_errors) r->xtr = xtr; r->spreadsheet.type = SPREADSHEET_ODS; + r->row = 0; + r->col = 0; + r->current_sheet = 0; + r->state = STATE_INIT; if (report_errors) xmlTextReaderSetErrorHandler (xtr, ods_error_handler, r); @@ -557,6 +600,7 @@ ods_probe (const char *filename, bool report_errors) r = xzalloc (sizeof *r); r->zreader = zr; + r->ref_cnt = 1; if (! init_reader (r, report_errors)) { @@ -597,12 +641,12 @@ ods_make_reader (struct spreadsheet *spreadsheet, assert (r); r->read_names = opts->read_names; ds_init_empty (&r->ods_errs); - + ++r->ref_cnt; if ( !init_reader (r, true)) goto error; - if ( opts->cell_range ) + if (opts->cell_range) { if ( ! convert_cell_ref (opts->cell_range, &r->start_col, &r->start_row, @@ -622,22 +666,14 @@ ods_make_reader (struct spreadsheet *spreadsheet, } r->state = STATE_INIT; - r->target_sheet_name = BAD_CAST opts->sheet_name; + r->target_sheet_name = xmlStrdup (BAD_CAST opts->sheet_name); r->target_sheet_index = opts->sheet_index; r->row = r->col = 0; -#if 0 - printf ("%s:%d %d,%d %d,%d\n", __FILE__, __LINE__, - r->start_col, - r->start_row, - r->stop_col, - r->stop_row); -#endif - - /* Advance to the start of the cells for the target sheet */ - while ( ! reading_target_sheet (r) || r->state != STATE_ROW || r->row < r->start_row ) + while ( ! reading_target_sheet (r) + || r->state != STATE_ROW || r->row <= r->start_row ) { if (1 != (ret = xmlTextReaderRead (r->xtr))) break; @@ -645,7 +681,6 @@ ods_make_reader (struct spreadsheet *spreadsheet, process_node (r); } - if (ret < 1) { msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."), @@ -673,8 +708,6 @@ ods_make_reader (struct spreadsheet *spreadsheet, if (r->stop_col != -1 && idx > r->stop_col - r->start_col) continue; - // printf ("%s:%d IDX %d COL %d\n", __FILE__, __LINE__, idx, r->col); - if (r->state == STATE_CELL_CONTENT && XML_READER_TYPE_TEXT == r->node_type) @@ -688,7 +721,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, /* xrealloc (unlike realloc) doesn't initialise its memory to 0 */ memset (var_spec + n_var_specs, 0, - (n_var_specs - idx + 1) * sizeof (*var_spec)); + (idx - n_var_specs + 1) * sizeof (*var_spec)); n_var_specs = idx + 1; } var_spec[idx].firstval.text = 0; @@ -696,6 +729,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, var_spec[idx].firstval.type = 0; var_spec [idx].name = strdup (CHAR_CAST (const char *, value)); + xmlFree (value); } } @@ -707,6 +741,9 @@ ods_make_reader (struct spreadsheet *spreadsheet, int idx; process_node (r); + if ( ! reading_target_sheet (r) ) + break; + /* If the row is finished then stop for now */ if (r->state == STATE_TABLE && r->row > r->start_row + (opts->read_names ? 1 : 0)) @@ -729,25 +766,17 @@ ods_make_reader (struct spreadsheet *spreadsheet, if ( r->state == STATE_CELL_CONTENT && XML_READER_TYPE_TEXT == r->node_type) { -#if 0 - printf ("%s:%d Idx %d n_var_specs %d\n", __FILE__, __LINE__, - idx, n_var_specs); - - printf ("%s:%d Idx %d r_col %d\n", __FILE__, __LINE__, - idx, r->col); -#endif - if (idx >= n_var_specs) { var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1)); + memset (var_spec + n_var_specs, + 0, + (idx - n_var_specs + 1) * sizeof (*var_spec)); + var_spec [idx].name = NULL; n_var_specs = idx + 1; } -#if 0 - printf ("%s:%d Idx %d n_var_specs %d\n", __FILE__, __LINE__, - idx, n_var_specs); -#endif - + var_spec [idx].firstval.type = type; var_spec [idx].firstval.text = xmlTextReaderValue (r->xtr); var_spec [idx].firstval.value = val_string; @@ -815,9 +844,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, break; } - // zip_reader_destroy (zreader); -#if 0 for ( i = 0 ; i < n_var_specs ; ++i ) { free (var_spec[i].firstval.type); @@ -827,7 +854,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, } free (var_spec); -#endif + return casereader_create_sequential (NULL, @@ -837,8 +864,6 @@ ods_make_reader (struct spreadsheet *spreadsheet, error: - // zip_reader_destroy (zreader); - for ( i = 0 ; i < n_var_specs ; ++i ) { free (var_spec[i].firstval.type); @@ -853,7 +878,6 @@ ods_make_reader (struct spreadsheet *spreadsheet, r->spreadsheet.dict = NULL; ods_file_casereader_destroy (NULL, r); - return NULL; } @@ -921,18 +945,22 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_) for (col = 0; col < r->col_span; ++col) { - const int idx = r->col + col - r->start_col - 1; + const struct variable *var; + const int idx = r->col - col - r->start_col - 1; if (idx < 0) continue; if (r->stop_col != -1 && idx > r->stop_col - r->start_col ) break; + if (idx >= dict_get_var_cnt (r->dict)) + break; - const struct variable *var = dict_get_var (r->dict, idx); + var = dict_get_var (r->dict, idx); convert_xml_to_value (c, var, xmv); } - free (xmv->text); - free (xmv->value); + xmlFree (xmv->text); + xmlFree (xmv->value); + xmlFree (xmv->type); free (xmv); } if ( r->state <= STATE_TABLE)