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
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
unsigned long int *start,
unsigned long int *width);
static void axis_make_available (struct axis *,
unsigned long int *start,
unsigned long int *width);
static void axis_make_available (struct axis *,
- unsigned long int start,
- unsigned long int width);
+ unsigned long int start,
+ unsigned long int width);
static unsigned long int axis_extend (struct axis *, unsigned long int width);
static unsigned long int axis_map (const struct axis *, unsigned long log_pos);
static unsigned long int axis_extend (struct axis *, unsigned long int width);
static unsigned long int axis_map (const struct axis *, unsigned long log_pos);
- {
- /* Mappings from logical to physical columns/rows. */
- struct axis *columns;
- struct axis *rows;
-
- /* Mapping from physical columns to "source_info"s. */
- struct range_map sources;
-
- /* Minimum number of columns to put in a new source when we
- need new columns and none are free. We double it whenever
- we add a new source to keep the number of file descriptors
- needed by the datasheet to a minimum, reducing the
- likelihood of running out. */
- unsigned column_min_alloc;
-
- /* Indicates corrupted data in the datasheet. */
- struct taint *taint;
- };
+{
+ /* Mappings from logical to physical columns/rows. */
+ struct axis *columns;
+ struct axis *rows;
+
+ /* Mapping from physical columns to "source_info"s. */
+ struct range_map sources;
+
+ /* Minimum number of columns to put in a new source when we
+ need new columns and none are free. We double it whenever
+ we add a new source to keep the number of file descriptors
+ needed by the datasheet to a minimum, reducing the
+ likelihood of running out. */
+ unsigned column_min_alloc;
+
+ /* Indicates corrupted data in the datasheet. */
+ struct taint *taint;
+};
static void free_source_info (struct datasheet *, struct source_info *);
static struct source_info *source_info_from_range_map (
static void free_source_info (struct datasheet *, struct source_info *);
static struct source_info *source_info_from_range_map (
static bool rw_case (struct datasheet *ds, enum rw_op op,
casenumber lrow, size_t start_column, size_t column_cnt,
union value data[]);
static bool rw_case (struct datasheet *ds, enum rw_op op,
casenumber lrow, size_t start_column, size_t column_cnt,
union value data[]);
- column_start = axis_extend (ds->columns, column_cnt);
- axis_insert (ds->columns, 0, column_start, column_cnt);
- range_map_insert (&ds->sources, column_start, column_cnt,
- &si->column_range);
+ column_start = axis_extend (ds->columns, column_cnt);
+ axis_insert (ds->columns, 0, column_start, column_cnt);
+ range_map_insert (&ds->sources, column_start, column_cnt,
+ &si->column_range);
- row_start = axis_extend (ds->rows, row_cnt);
- axis_insert (ds->rows, 0, row_start, row_cnt);
+ row_start = axis_extend (ds->rows, row_cnt);
+ axis_insert (ds->rows, 0, row_start, row_cnt);
axis_move (ds->columns, old_start, new_start, cnt);
}
axis_move (ds->columns, old_start, new_start, cnt);
}
-/* Retrieves the contents of the given ROW in datasheet DS into
- newly created case C. Returns true if successful, false on
- I/O error. */
-bool
-datasheet_get_row (const struct datasheet *ds, casenumber row, struct ccase *c)
+/* Retrieves and returns the contents of the given ROW in
+ datasheet DS. The caller owns the returned case and must
+ unref it when it is no longer needed. Returns a null pointer
+ on I/O error. */
+struct ccase *
+datasheet_get_row (const struct datasheet *ds, casenumber row)
if (rw_case ((struct datasheet *) ds, OP_READ,
row, 0, column_cnt, case_data_all_rw (c)))
if (rw_case ((struct datasheet *) ds, OP_READ,
row, 0, column_cnt, case_data_all_rw (c)))
size_t column_cnt = datasheet_get_column_cnt (ds);
bool ok = rw_case (ds, OP_WRITE, row, 0, column_cnt,
(union value *) case_data_all (c));
size_t column_cnt = datasheet_get_column_cnt (ds);
bool ok = rw_case (ds, OP_WRITE, row, 0, column_cnt,
(union value *) case_data_all (c));
-/* Inserts the CNT cases at C, which are destroyed, into
- datasheet DS just before row BEFORE. Returns true if
- successful, false on I/O error. On failure, datasheet DS is
- not modified. */
+/* Inserts the CNT cases at C into datasheet DS just before row
+ BEFORE. Returns true if successful, false on I/O error. On
+ failure, datasheet DS is not modified.
+
+ Regardless of success, this function unrefs all of the cases
+ in C. */
axis_make_available, and axis_extend functions affect the set
of available ordinates. */
struct axis
axis_make_available, and axis_extend functions affect the set
of available ordinates. */
struct axis
- {
- struct tower log_to_phy; /* Map from logical to physical ordinates;
- contains "struct axis_group"s. */
- struct range_set *available; /* Set of unused, available ordinates. */
- unsigned long int phy_size; /* Current physical length of axis. */
- };
+{
+ struct tower log_to_phy; /* Map from logical to physical ordinates;
+ contains "struct axis_group"s. */
+ struct range_set *available; /* Set of unused, available ordinates. */
+ unsigned long int phy_size; /* Current physical length of axis. */
+};
- {
- struct tower_node logical; /* Range of logical ordinates. */
- unsigned long phy_start; /* First corresponding physical ordinate. */
- };
+{
+ struct tower_node logical; /* Range of logical ordinates. */
+ unsigned long phy_start; /* First corresponding physical ordinate. */
+};
static struct axis_group *axis_group_from_tower_node (struct tower_node *);
static struct tower_node *make_axis_group (unsigned long int phy_start);
static struct axis_group *axis_group_from_tower_node (struct tower_node *);
static struct tower_node *make_axis_group (unsigned long int phy_start);
- {
- size_t columns_used; /* Number of columns in use by client. */
- struct sparse_cases *data; /* Data at top level, atop the backing. */
- struct casereader *backing; /* Backing casereader (or null). */
- casenumber backing_rows; /* Number of rows in backing (if nonnull). */
- };
+{
+ size_t columns_used; /* Number of columns in use by client. */
+ struct sparse_cases *data; /* Data at top level, atop the backing. */
+ struct casereader *backing; /* Backing casereader (or null). */
+ casenumber backing_rows; /* Number of rows in backing (if nonnull). */
+};
/* Creates and returns an empty, unbacked source with COLUMN_CNT
columns and an initial "columns_used" of 0. */
/* Creates and returns an empty, unbacked source with COLUMN_CNT
columns and an initial "columns_used" of 0. */
return sparse_cases_read (source->data, row, column, values, value_cnt);
else
{
return sparse_cases_read (source->data, row, column, values, value_cnt);
else
{
- struct ccase c;
- bool ok;
-
- assert (source->backing != NULL);
- ok = casereader_peek (source->backing, row, &c);
+ struct ccase *c = casereader_peek (source->backing, row);
+ bool ok = c != NULL;
- case_copy_out (&c, column, values, value_cnt);
- case_destroy (&c);
+ case_copy_out (c, column, values, value_cnt);
+ case_unref (c);
ok = sparse_cases_write (source->data, row, column, values, value_cnt);
else
{
ok = sparse_cases_write (source->data, row, column, values, value_cnt);
else
{
levels, so that we in fact usually write the full
contents of new, unbacked rows in multiple calls to
this function. Make this work. */
levels, so that we in fact usually write the full
contents of new, unbacked rows in multiple calls to
this function. Make this work. */
- case_copy_in (&c, column, values, value_cnt);
+ case_copy_in (c, column, values, value_cnt);
ok = sparse_cases_write (source->data, row, 0,
ok = sparse_cases_write (source->data, row, 0,
md4_process_bytes (&end, sizeof end, &ctx);
}
md4_process_bytes (&ds->column_min_alloc, sizeof ds->column_min_alloc,
md4_process_bytes (&end, sizeof end, &ctx);
}
md4_process_bytes (&ds->column_min_alloc, sizeof ds->column_min_alloc,