projects
/
pspp
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fewer memory leaks
[pspp]
/
src
/
data
/
ods-reader.c
diff --git
a/src/data/ods-reader.c
b/src/data/ods-reader.c
index a5ece5c504b394bde637060d603771e8bf7d7145..a36a020a0b063eb4b31ab84c94838ec071240b5c 100644
(file)
--- a/
src/data/ods-reader.c
+++ b/
src/data/ods-reader.c
@@
-67,14
+67,15
@@
ods_open_reader (const struct spreadsheet_read_options *opts,
#include "gl/xalloc.h"
static void ods_file_casereader_destroy (struct casereader *, void *);
#include "gl/xalloc.h"
static void ods_file_casereader_destroy (struct casereader *, void *);
-
static struct ccase *ods_file_casereader_read (struct casereader *, void *);
static struct ccase *ods_file_casereader_read (struct casereader *, void *);
+static struct casereader *ods_file_casereader_clone (struct casereader *, void *);
+
static const struct casereader_class ods_file_casereader_class =
{
ods_file_casereader_read,
ods_file_casereader_destroy,
static const struct casereader_class ods_file_casereader_class =
{
ods_file_casereader_read,
ods_file_casereader_destroy,
-
NULL
,
+
ods_file_casereader_clone
,
NULL,
};
NULL,
};
@@
-105,6
+106,7
@@
struct ods_reader
struct spreadsheet spreadsheet;
struct zip_reader *zreader;
xmlTextReaderPtr xtr;
struct spreadsheet spreadsheet;
struct zip_reader *zreader;
xmlTextReaderPtr xtr;
+ int ref_cnt;
enum reader_state state;
int row;
enum reader_state state;
int row;
@@
-113,16
+115,14
@@
struct ods_reader
int current_sheet;
xmlChar *current_sheet_name;
int current_sheet;
xmlChar *current_sheet_name;
-
const
xmlChar *target_sheet_name;
+ xmlChar *target_sheet_name;
int target_sheet_index;
int target_sheet_index;
-#if 1
int start_row;
int start_col;
int stop_row;
int stop_col;
int start_row;
int start_col;
int stop_row;
int stop_col;
-#endif
int col_span;
int col_span;
@@
-138,6
+138,26
@@
struct ods_reader
struct string ods_errs;
};
struct string ods_errs;
};
+void
+ods_destroy (struct spreadsheet *s)
+{
+ struct ods_reader *r = 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)
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)
{
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 (
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);
}
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)
{
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 (
struct ods_reader *or = (struct ods_reader *) s;
assert (n < s->n_sheets);
while (
- (
(or->n_allocated_sheets <= n)
(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);
}
process_node (or);
}
-
return create_cell_ref (
or->sheets[n].start_col,
or->sheets[n].start_row,
return create_cell_ref (
or->sheets[n].start_col,
or->sheets[n].start_row,
@@
-206,6
+228,16
@@
ods_get_sheet_range (struct spreadsheet *s, int n)
}
}
+static struct casereader *
+ods_file_casereader_clone (struct casereader *r_, void *s)
+{
+ struct ods_reader *r = r_;
+
+ printf ("%s:%d CLONE reffing %p %d\n", __FILE__, __LINE__, s, r->ref_cnt);
+
+ return r_;
+}
+
static void
ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
{
static void
ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
{
@@
-227,9
+259,16
@@
ods_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
caseproto_unref (r->proto);
caseproto_unref (r->proto);
- // free (r);
+ xmlFree (r->current_sheet_name);
+ xmlFree (r->target_sheet_name);
+
+ ods_destroy (r);
}
}
+
+
+
+
static void
process_node (struct ods_reader *r)
{
static void
process_node (struct ods_reader *r)
{
@@
-263,12
+302,13
@@
process_node (struct ods_reader *r)
if (r->current_sheet >= r->n_allocated_sheets)
{
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 = 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;
}
r->col = 0;
@@
-297,6
+337,8
@@
process_node (struct ods_reader *r)
if (! xmlTextReaderIsEmptyElement (r->xtr))
r->state = STATE_ROW;
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))
}
else if (0 == xmlStrcasecmp (name, _xml("table:table")) &&
(XML_READER_TYPE_END_ELEMENT == r->node_type))
@@
-305,7
+347,6
@@
process_node (struct ods_reader *r)
}
break;
case STATE_ROW:
}
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))
if ( (0 == xmlStrcasecmp (name, _xml ("table:table-cell")))
&&
(XML_READER_TYPE_ELEMENT == r->node_type))
@@
-317,10
+358,10
@@
process_node (struct ods_reader *r)
r->col_span = value ? _xmlchar_to_int (value) : 1;
r->col += r->col_span;
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;
if (! xmlTextReaderIsEmptyElement (r->xtr))
r->state = STATE_CELL;
+
+ xmlFree (value);
}
else if ( (0 == xmlStrcasecmp (name, _xml ("table:table-row")))
&&
}
else if ( (0 == xmlStrcasecmp (name, _xml ("table:table-row")))
&&
@@
-441,7
+482,7
@@
convert_xml_to_value (struct ccase *c, const struct variable *var,
if ( 0 == xmlStrcmp (xmv->type, _xml("float")))
{
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
{
}
else
{
@@
-471,7
+512,7
@@
get_sheet_count (struct zip_reader *zreader)
return -1;
mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
return -1;
mxtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
- (xmlInputCloseCallback)
zip_member_finish
,
+ (xmlInputCloseCallback)
NULL
,
meta, NULL, NULL, 0);
while (1 == xmlTextReaderRead (mxtr))
meta, NULL, NULL, 0);
while (1 == xmlTextReaderRead (mxtr))
@@
-480,14
+521,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 ( 0 == xmlStrcmp (name, _xml("meta:document-statistic")))
{
xmlChar *attr = xmlTextReaderGetAttribute (mxtr, _xml ("meta:table-count"));
-
+
if ( attr != NULL)
{
int s = _xmlchar_to_int (attr);
if ( attr != NULL)
{
int s = _xmlchar_to_int (attr);
+ xmlFreeTextReader (mxtr);
+ xmlFree (name);
+ xmlFree (attr);
return s;
}
return s;
}
+ xmlFree (attr);
}
}
+ xmlFree (name);
}
}
+
+ xmlFreeTextReader (mxtr);
return -1;
}
return -1;
}
@@
-514,9
+562,10
@@
init_reader (struct ods_reader *r, bool report_errors)
if ( content == NULL)
return false;
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,
xtr = xmlReaderForIO ((xmlInputReadCallback) zip_member_read,
(xmlInputCloseCallback) zip_member_finish,
content, NULL, NULL,
@@
-527,6
+576,10
@@
init_reader (struct ods_reader *r, bool report_errors)
r->xtr = xtr;
r->spreadsheet.type = SPREADSHEET_ODS;
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);
if (report_errors)
xmlTextReaderSetErrorHandler (xtr, ods_error_handler, r);
@@
-557,6
+610,7
@@
ods_probe (const char *filename, bool report_errors)
r = xzalloc (sizeof *r);
r->zreader = zr;
r = xzalloc (sizeof *r);
r->zreader = zr;
+ r->ref_cnt = 1;
if (! init_reader (r, report_errors))
{
if (! init_reader (r, report_errors))
{
@@
-597,12
+651,12
@@
ods_make_reader (struct spreadsheet *spreadsheet,
assert (r);
r->read_names = opts->read_names;
ds_init_empty (&r->ods_errs);
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 ( !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,
{
if ( ! convert_cell_ref (opts->cell_range,
&r->start_col, &r->start_row,
@@
-622,22
+676,14
@@
ods_make_reader (struct spreadsheet *spreadsheet,
}
r->state = STATE_INIT;
}
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;
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 */
/* 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;
{
if (1 != (ret = xmlTextReaderRead (r->xtr)))
break;
@@
-645,7
+691,6
@@
ods_make_reader (struct spreadsheet *spreadsheet,
process_node (r);
}
process_node (r);
}
-
if (ret < 1)
{
msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
if (ret < 1)
{
msg (MW, _("Selected sheet or range of spreadsheet `%s' is empty."),
@@
-673,8
+718,6
@@
ods_make_reader (struct spreadsheet *spreadsheet,
if (r->stop_col != -1 && idx > r->stop_col - r->start_col)
continue;
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)
if (r->state == STATE_CELL_CONTENT
&&
XML_READER_TYPE_TEXT == r->node_type)
@@
-688,7
+731,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
/* xrealloc (unlike realloc) doesn't initialise its memory to 0 */
memset (var_spec + n_var_specs,
0,
/* 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;
n_var_specs = idx + 1;
}
var_spec[idx].firstval.text = 0;
@@
-696,6
+739,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
var_spec[idx].firstval.type = 0;
var_spec [idx].name = strdup (CHAR_CAST (const char *, value));
var_spec[idx].firstval.type = 0;
var_spec [idx].name = strdup (CHAR_CAST (const char *, value));
+
xmlFree (value);
}
}
xmlFree (value);
}
}
@@
-707,6
+751,9
@@
ods_make_reader (struct spreadsheet *spreadsheet,
int idx;
process_node (r);
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))
/* 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
+776,17
@@
ods_make_reader (struct spreadsheet *spreadsheet,
if ( r->state == STATE_CELL_CONTENT &&
XML_READER_TYPE_TEXT == r->node_type)
{
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));
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;
}
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;
var_spec [idx].firstval.type = type;
var_spec [idx].firstval.text = xmlTextReaderValue (r->xtr);
var_spec [idx].firstval.value = val_string;
@@
-815,9
+854,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
break;
}
break;
}
- // zip_reader_destroy (zreader);
-#if 0
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec[i].firstval.type);
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec[i].firstval.type);
@@
-827,7
+864,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
}
free (var_spec);
}
free (var_spec);
-#endif
+
return casereader_create_sequential
(NULL,
return casereader_create_sequential
(NULL,
@@
-837,8
+874,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
error:
error:
- // zip_reader_destroy (zreader);
-
+#if 0
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec[i].firstval.type);
for ( i = 0 ; i < n_var_specs ; ++i )
{
free (var_spec[i].firstval.type);
@@
-851,6
+887,7
@@
ods_make_reader (struct spreadsheet *spreadsheet,
dict_destroy (r->spreadsheet.dict);
r->spreadsheet.dict = NULL;
dict_destroy (r->spreadsheet.dict);
r->spreadsheet.dict = NULL;
+#endif
ods_file_casereader_destroy (NULL, r);
ods_file_casereader_destroy (NULL, r);
@@
-921,18
+958,22
@@
ods_file_casereader_read (struct casereader *reader UNUSED, void *r_)
for (col = 0; col < r->col_span; ++col)
{
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 < 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);
}
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)
free (xmv);
}
if ( r->state <= STATE_TABLE)