From 6462038a06640fd734b8204b8af95eb3b86fcb4c Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 29 May 2023 17:42:15 -0700 Subject: [PATCH] ods-reader: Support more than a single piece of text in a cell. This code read the first text content in the first

it found in a cell. This meant that anything more sophisticated than just

text

broke, including

textsome more

. This commit fixes it. The code here was really complicated and I didn't understand it. I simplified it a lot to use xmlTextReaderExpand(), which is a lot easier to use than a state machine at the level we need it. I also couldn't figure out how to make the existing caching logic work quite right, so I replaced it by something simpler which I think will be just fine. This updates the test by adding some bold text to a cell. Thanks to elias tsolis for reporting this bug. Bug #63443. --- src/data/ods-reader.c | 248 +++++++++++------------------ tests/language/commands/newone.ods | Bin 13038 -> 18647 bytes 2 files changed, 92 insertions(+), 156 deletions(-) diff --git a/src/data/ods-reader.c b/src/data/ods-reader.c index ae2c9579ed..db2b401ba6 100644 --- a/src/data/ods-reader.c +++ b/src/data/ods-reader.c @@ -50,11 +50,6 @@ #include "gettext.h" #define _(msgid) gettext (msgid) -/* Setting this to false can help with debugging and development. - Don't forget to set it back to true, or users will complain that - all but the smallest spreadsheets display VERY slowly. */ -static const bool use_cache = true; - static void ods_file_casereader_destroy (struct casereader *, void *); static struct ccase *ods_file_casereader_read (struct casereader *, void *); @@ -73,7 +68,6 @@ enum reader_state STATE_TABLE, /* Found the sheet that we actually want */ STATE_ROW, /* Found the start of the cell array */ STATE_CELL, /* Found a cell */ - STATE_CELL_CONTENT /* Found a the text within a cell */ }; struct state_data @@ -297,114 +291,72 @@ ods_get_sheet_n_columns (struct spreadsheet *s, int n) return r->spreadsheet.sheets[n].last_col + 1; } -static char * -ods_get_sheet_cell (struct spreadsheet *s, int n, int row, int column) +static unsigned int +cell_hash (int n, int row, int column) { - struct ods_reader *r = (struct ods_reader *) s; - struct state_data sd; + return hash_int (column, hash_int (row, hash_int (n, 0))); +} - /* See if this cell is in the cache. If it is, then use it. */ - if (use_cache) - { - struct cache_datum *lookup = NULL; - unsigned int hash = hash_int (n, 0); - hash = hash_int (row, hash); - hash = hash_int (column, hash); +static struct cache_datum * +cache_lookup (struct ods_reader *r, int n, int row, int column) +{ + unsigned int hash = cell_hash (n, row, column); - HMAP_FOR_EACH_WITH_HASH (lookup, struct cache_datum, node, hash, - &r->cache) - { - if (lookup->row == row && lookup->col == column - && lookup->sheet == n) - { - break; - } - } - if (lookup) - { - return lookup->value ? strdup (lookup->value) : NULL; - } - } + struct cache_datum *d; + HMAP_FOR_EACH_WITH_HASH (d, struct cache_datum, node, hash, &r->cache) + if (d->row == row && d->col == column && d->sheet == n) + return d; + return NULL; +} - state_data_init (r, &sd); +static void +populate_cache (struct ods_reader *r) +{ + struct state_data sd; - char *cell_content = NULL; + state_data_init (r, &sd); - int prev_col = 0; - int prev_row = 0; while (process_node (r, &sd)) { - if (sd.row > prev_row) - prev_col = 0; - - if (sd.state == STATE_CELL_CONTENT - && sd.current_sheet == n - && sd.node_type == XML_READER_TYPE_TEXT) + if (sd.state == STATE_CELL) { - /* When cell contents are encountered, copy and save it, discarding - any older content. */ - free (cell_content); - cell_content = CHAR_CAST (char *, xmlTextReaderValue (sd.xtr)); - } - if (sd.state == STATE_ROW - && sd.current_sheet == n - && sd.node_type == XML_READER_TYPE_ELEMENT) - { - /* At the start of a row, free the cell contents and set it to NULL. */ - free (cell_content); - cell_content = NULL; - } - if (sd.state == STATE_ROW - && sd.current_sheet == n - && - (sd.node_type == XML_READER_TYPE_END_ELEMENT - || - xmlTextReaderIsEmptyElement (sd.xtr))) - { - if (use_cache) + /* When cell contents are encountered, copy and save it, discarding + any older content. */ + char *cell_content = CHAR_CAST (char *, xmlNodeGetContent ( + xmlTextReaderExpand (sd.xtr))); + + for (int c = sd.col - sd.col_span; c < sd.col; ++c) { - for (int c = prev_col; c < sd.col; ++c) - { - /* See if this cell has already been cached ... */ - unsigned int hash = hash_int (sd.current_sheet, 0); - hash = hash_int (sd.row - 1, hash); - hash = hash_int (c, hash); - struct cache_datum *probe = NULL; - struct cache_datum *next; - HMAP_FOR_EACH_WITH_HASH_SAFE (probe, next, struct cache_datum, node, hash, - &r->cache) - { - if (probe->row == sd.row - 1 && probe->col == c - && probe->sheet == sd.current_sheet) - break; - probe = NULL; - } - /* If not, then cache it. */ - if (!probe) - { - struct cache_datum *cell_data = XMALLOC (struct cache_datum); - cell_data->row = sd.row - 1; - cell_data->col = c; - cell_data->sheet = sd.current_sheet; - cell_data->value = cell_content ? strdup (cell_content) : NULL; - - hmap_insert (&r->cache, &cell_data->node, hash); - } - } + if (cache_lookup (r, sd.current_sheet, sd.row, c)) + continue; + + struct cache_datum *cell_data = xmalloc (sizeof *cell_data); + *cell_data = (struct cache_datum) { + .row = sd.row - 1, + .col = c, + .sheet = sd.current_sheet, + .value = xstrdup_if_nonnull (cell_content), + }; + hmap_insert (&r->cache, &cell_data->node, + cell_hash (sd.current_sheet, sd.row - 1, c)); } - - if (sd.row == row + 1 && sd.col >= column + 1) - { - break; - } - - prev_col = sd.col; - prev_row = sd.row; + free (cell_content); } } state_data_destroy (&sd); - return cell_content; +} + +static char * +ods_get_sheet_cell (struct spreadsheet *s, int n, int row, int column) +{ + struct ods_reader *r = (struct ods_reader *) s; + + if (hmap_is_empty (&r->cache)) + populate_cache (r); + + const struct cache_datum *datum = cache_lookup (r, n, row, column); + return datum ? xstrdup_if_nonnull (datum->value) : NULL; } static void @@ -436,7 +388,10 @@ ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) static bool process_node (struct ods_reader *or, struct state_data *r) { - if (xmlTextReaderRead (r->xtr) != 1) + int ret = (r->state == STATE_CELL + ? xmlTextReaderNext (r->xtr) + : xmlTextReaderRead (r->xtr)); + if (ret != 1) return false; xmlChar *name = xmlTextReaderName (r->xtr); @@ -515,6 +470,10 @@ process_node (struct ods_reader *or, struct state_data *r) r->state = STATE_SPREADSHEET; } break; + + case STATE_CELL: + r->state = STATE_ROW; + /* Fall through. */ case STATE_ROW: if ((0 == xmlStrcasecmp (name, _xml ("table:table-cell"))) && @@ -526,12 +485,32 @@ process_node (struct ods_reader *or, struct state_data *r) r->col_span = value ? _xmlchar_to_int (value) : 1; r->col += r->col_span; + xmlFree (value); if (! xmlTextReaderIsEmptyElement (r->xtr)) - r->state = STATE_CELL; + { + assert (r->current_sheet >= 0); + assert (r->current_sheet < or->n_allocated_sheets); - xmlFree (value); - } + if (or->spreadsheet.sheets[r->current_sheet].first_row == -1) + or->spreadsheet.sheets[r->current_sheet].first_row = r->row - 1; + + if ( + (or->spreadsheet.sheets[r->current_sheet].first_col == -1) + || + (or->spreadsheet.sheets[r->current_sheet].first_col >= r->col - 1) + ) + or->spreadsheet.sheets[r->current_sheet].first_col = r->col - 1; + + if (or->spreadsheet.sheets[r->current_sheet].last_row < r->row - 1) + or->spreadsheet.sheets[r->current_sheet].last_row = r->row - 1; + + if (or->spreadsheet.sheets[r->current_sheet].last_col < r->col - 1) + or->spreadsheet.sheets[r->current_sheet].last_col = r->col - 1; + + r->state = STATE_CELL; + } + } else if ((0 == xmlStrcasecmp (name, _xml ("table:table-row"))) && (XML_READER_TYPE_END_ELEMENT == r->node_type)) @@ -539,46 +518,6 @@ process_node (struct ods_reader *or, struct state_data *r) r->state = STATE_TABLE; } break; - case STATE_CELL: - if ((0 == xmlStrcasecmp (name, _xml("text:p"))) - && - (XML_READER_TYPE_ELEMENT == r->node_type)) - { - if (! xmlTextReaderIsEmptyElement (r->xtr)) - r->state = STATE_CELL_CONTENT; - } - else if - ((0 == xmlStrcasecmp (name, _xml("table:table-cell"))) - && - (XML_READER_TYPE_END_ELEMENT == r->node_type) - ) - { - r->state = STATE_ROW; - } - break; - case STATE_CELL_CONTENT: - assert (r->current_sheet >= 0); - assert (r->current_sheet < or->n_allocated_sheets); - - if (or->spreadsheet.sheets[r->current_sheet].first_row == -1) - or->spreadsheet.sheets[r->current_sheet].first_row = r->row - 1; - - if ( - (or->spreadsheet.sheets[r->current_sheet].first_col == -1) - || - (or->spreadsheet.sheets[r->current_sheet].first_col >= r->col - 1) - ) - or->spreadsheet.sheets[r->current_sheet].first_col = r->col - 1; - - if (or->spreadsheet.sheets[r->current_sheet].last_row < r->row - 1) - or->spreadsheet.sheets[r->current_sheet].last_row = r->row - 1; - - if (or->spreadsheet.sheets[r->current_sheet].last_col < r->col - 1) - or->spreadsheet.sheets[r->current_sheet].last_col = r->col - 1; - - if (XML_READER_TYPE_END_ELEMENT == r->node_type) - r->state = STATE_CELL; - break; default: NOT_REACHED (); break; @@ -823,11 +762,10 @@ ods_make_reader (struct spreadsheet *spreadsheet, if (r->spreadsheet.stop_col != -1 && idx > r->spreadsheet.stop_col - r->spreadsheet.start_col) continue; - if (r->rsd.state == STATE_CELL_CONTENT - && - XML_READER_TYPE_TEXT == r->rsd.node_type) + if (r->rsd.state == STATE_CELL) { - xmlChar *value = xmlTextReaderValue (r->rsd.xtr); + char *value = CHAR_CAST (char *, xmlNodeGetContent ( + xmlTextReaderExpand (r->rsd.xtr))); if (idx >= n_var_specs) { var_spec = xrealloc (var_spec, sizeof (*var_spec) * (idx + 1)); @@ -843,8 +781,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, var_spec[idx - i].firstval.text = 0; var_spec[idx - i].firstval.value = 0; var_spec[idx - i].firstval.type = 0; - var_spec[idx - i].name = - strdup (CHAR_CAST (const char *, value)); + var_spec[idx - i].name = xstrdup (value); } xmlFree (value); @@ -878,8 +815,7 @@ ods_make_reader (struct spreadsheet *spreadsheet, val_string = xmlTextReaderGetAttribute (r->rsd.xtr, _xml ("office:value")); } - if (r->rsd.state == STATE_CELL_CONTENT && - XML_READER_TYPE_TEXT == r->rsd.node_type) + if (r->rsd.state == STATE_CELL) { if (idx >= n_var_specs) { @@ -895,7 +831,8 @@ ods_make_reader (struct spreadsheet *spreadsheet, for (int x = 0; x < r->rsd.col_span; ++x) { var_spec [idx - x].firstval.type = xmlStrdup (type); - var_spec [idx - x].firstval.text = xmlTextReaderValue (r->rsd.xtr); + var_spec [idx - x].firstval.text + = xmlNodeGetContent (xmlTextReaderExpand (r->rsd.xtr)); var_spec [idx - x].firstval.value = xmlStrdup (val_string); } @@ -1032,12 +969,11 @@ ods_file_casereader_read (struct casereader *reader UNUSED, void *r_) val_string = xmlTextReaderGetAttribute (r->rsd.xtr, _xml ("office:value")); } - if (r->rsd.state == STATE_CELL_CONTENT && - r->rsd.node_type == XML_READER_TYPE_TEXT) + if (r->rsd.state == STATE_CELL) { int col; struct xml_value *xmv = XZALLOC (struct xml_value); - xmv->text = xmlTextReaderValue (r->rsd.xtr); + xmv->text = xmlNodeGetContent (xmlTextReaderExpand (r->rsd.xtr)); xmv->value = val_string; val_string = NULL; xmv->type = type; @@ -1146,7 +1082,7 @@ ods_probe (const char *filename, bool report_errors) .n_sheets = -1, .spreadsheet = { .ref_cnt = 1, - .file_name = strdup (filename), + .file_name = xstrdup (filename), }, }; diff --git a/tests/language/commands/newone.ods b/tests/language/commands/newone.ods index 11926c40c7d877d3ef5c7d4db95eb9a777f4450f..d3347b2333419c6ca96613d38aae70ac83435b1d 100644 GIT binary patch literal 18647 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 literal 13038 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

9uMLFjli$nq1at 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 phm@ZK_d6WiKJ{{b*hU~B*Y -- 2.30.2