X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fdatasheet.c;h=64dea786877796dfdbffd2f2daa6eeb698fd4e69;hb=9e0e4996fad6563f0a1ce628b80db5c23ef8279e;hp=a11a1e596c4446106e7f9adab05a385dc307479b;hpb=c3ac5a8af9c449072c7e872ca70a78c1755ae309;p=pspp-builds.git diff --git a/src/data/datasheet.c b/src/data/datasheet.c index a11a1e59..64dea786 100644 --- a/src/data/datasheet.c +++ b/src/data/datasheet.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007, 2009 Free Software Foundation, Inc. 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 @@ -47,8 +47,8 @@ static bool axis_allocate (struct axis *, unsigned long int request, 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); @@ -105,31 +105,31 @@ static bool source_in_use (const struct source *); /* A datasheet. */ struct datasheet - { - /* 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; +}; /* Maps from a range of physical columns to a source. */ struct source_info - { - struct range_map_node column_range; - struct source *source; - }; +{ + struct range_map_node column_range; + struct source *source; +}; /* Is this operation a read or a write? */ enum rw_op @@ -140,7 +140,7 @@ enum rw_op static void free_source_info (struct datasheet *, struct source_info *); static struct source_info *source_info_from_range_map ( - struct range_map_node *); + struct range_map_node *); static bool rw_case (struct datasheet *ds, enum rw_op op, casenumber lrow, size_t start_column, size_t column_cnt, union value data[]); @@ -176,17 +176,17 @@ datasheet_create (struct casereader *reader) if ( column_cnt > 0 ) { unsigned long int column_start; - 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); } if ( row_cnt > 0 ) { unsigned long int row_start; - 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); } } @@ -389,21 +389,22 @@ datasheet_move_columns (struct datasheet *ds, 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) { size_t column_cnt = datasheet_get_column_cnt (ds); - case_create (c, column_cnt); + struct ccase *c = case_create (column_cnt); if (rw_case ((struct datasheet *) ds, OP_READ, row, 0, column_cnt, case_data_all_rw (c))) - return true; + return c; else { - case_destroy (c); - return false; + case_unref (c); + return NULL; } } @@ -417,7 +418,7 @@ datasheet_put_row (struct datasheet *ds, casenumber row, struct ccase *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)); - case_destroy (c); + case_unref (c); return ok; } @@ -445,13 +446,15 @@ datasheet_put_value (struct datasheet *ds, casenumber row, size_t column, (union value *) value); } -/* 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. */ bool datasheet_insert_rows (struct datasheet *ds, - casenumber before, struct ccase c[], + casenumber before, struct ccase *c[], casenumber cnt) { casenumber added = 0; @@ -476,10 +479,10 @@ datasheet_insert_rows (struct datasheet *ds, /* Initialize the new rows. */ for (i = 0; i < phy_cnt; i++) - if (!datasheet_put_row (ds, before + i, &c[i])) + if (!datasheet_put_row (ds, before + i, c[i])) { while (++i < cnt) - case_destroy (&c[i]); + case_unref (c[i]); datasheet_delete_rows (ds, before - added, phy_cnt + added); return false; } @@ -540,20 +543,20 @@ datasheet_make_reader (struct datasheet *ds) } /* "read" function for the datasheet random casereader. */ -static bool +static struct ccase * datasheet_reader_read (struct casereader *reader UNUSED, void *ds_, - casenumber case_idx, struct ccase *c) + casenumber case_idx) { struct datasheet *ds = ds_; - if (case_idx >= datasheet_get_row_cnt (ds)) - return false; - else if (datasheet_get_row (ds, case_idx, c)) - return true; - else + if (case_idx < datasheet_get_row_cnt (ds)) { - taint_set_taint (ds->taint); - return false; + struct ccase *c = datasheet_get_row (ds, case_idx); + if (c == NULL) + taint_set_taint (ds->taint); + return c; } + else + return NULL; } /* "destroy" function for the datasheet random casereader. */ @@ -643,19 +646,19 @@ rw_case (struct datasheet *ds, enum rw_op op, 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. */ +}; /* A mapping from logical to physical ordinates. */ struct axis_group - { - 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); @@ -693,7 +696,7 @@ axis_clone (const struct axis *old) for (node = tower_first (&old->log_to_phy); node != NULL; node = tower_next (&old->log_to_phy, node)) { - unsigned long int size = tower_node_get_height (node); + unsigned long int size = tower_node_get_size (node); struct axis_group *group = tower_data (node, struct axis_group, logical); tower_insert (&new->log_to_phy, size, make_axis_group (group->phy_start), NULL); @@ -717,7 +720,7 @@ axis_hash (const struct axis *axis, struct md4_ctx *ctx) { struct axis_group *group = tower_data (tn, struct axis_group, logical); unsigned long int phy_start = group->phy_start; - unsigned long int size = tower_node_get_height (tn); + unsigned long int size = tower_node_get_size (tn); md4_process_bytes (&phy_start, sizeof phy_start, ctx); md4_process_bytes (&size, sizeof size, ctx); @@ -921,7 +924,7 @@ split_axis (struct axis *axis, unsigned long int where) if (where > group_start) { unsigned long int size_1 = where - group_start; - unsigned long int size_2 = tower_node_get_height (group_node) - size_1; + unsigned long int size_2 = tower_node_get_size (group_node) - size_1; struct tower_node *next = tower_next (&axis->log_to_phy, group_node); struct tower_node *new = make_axis_group (group->phy_start + size_1); tower_resize (&axis->log_to_phy, group_node, size_1); @@ -961,11 +964,11 @@ merge_axis_nodes (struct axis *axis, struct tower_node *node, if (next != NULL) { struct axis_group *next_group = axis_group_from_tower_node (next); - unsigned long this_height = tower_node_get_height (node); + unsigned long this_height = tower_node_get_size (node); if (group->phy_start + this_height == next_group->phy_start) { - unsigned long next_height = tower_node_get_height (next); + unsigned long next_height = tower_node_get_size (next); tower_resize (t, node, this_height + next_height); if (other_node != NULL && *other_node == next) *other_node = tower_next (t, *other_node); @@ -979,11 +982,11 @@ merge_axis_nodes (struct axis *axis, struct tower_node *node, if (prev != NULL) { struct axis_group *prev_group = axis_group_from_tower_node (prev); - unsigned long prev_height = tower_node_get_height (prev); + unsigned long prev_height = tower_node_get_size (prev); if (prev_group->phy_start + prev_height == group->phy_start) { - unsigned long this_height = tower_node_get_height (node); + unsigned long this_height = tower_node_get_size (node); group->phy_start = prev_group->phy_start; tower_resize (t, node, this_height + prev_height); if (other_node != NULL && *other_node == prev) @@ -1007,7 +1010,7 @@ check_axis_merged (const struct axis *axis UNUSED) if (prev != NULL) { struct axis_group *prev_group = axis_group_from_tower_node (prev); - unsigned long prev_height = tower_node_get_height (prev); + unsigned long prev_height = tower_node_get_size (prev); struct axis_group *node_group = axis_group_from_tower_node (node); assert (prev_group->phy_start + prev_height != node_group->phy_start); } @@ -1016,12 +1019,12 @@ check_axis_merged (const struct axis *axis UNUSED) /* A source. */ struct source - { - 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. */ @@ -1136,15 +1139,12 @@ source_read (const struct source *source, 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; if (ok) { - case_copy_out (&c, column, values, value_cnt); - case_destroy (&c); + case_copy_out (c, column, values, value_cnt); + case_unref (c); } return ok; } @@ -1169,9 +1169,10 @@ source_write (struct source *source, ok = sparse_cases_write (source->data, row, column, values, value_cnt); else { - struct ccase c; + struct ccase *c; + if (row < source->backing_rows) - ok = casereader_peek (source->backing, row, &c); + c = case_unshare (casereader_peek (source->backing, row)); else { /* It's not one of the backed rows. Ideally, this @@ -1182,15 +1183,16 @@ source_write (struct source *source, 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_create (&c, column_cnt); - ok = true; + c = case_create (column_cnt); } + ok = c != NULL; + if (ok) { - case_copy_in (&c, column, values, value_cnt); + case_copy_in (c, column, values, value_cnt); ok = sparse_cases_write (source->data, row, 0, - case_data_all (&c), column_cnt); - case_destroy (&c); + case_data_all (c), column_cnt); + case_unref (c); } } return ok; @@ -1282,10 +1284,8 @@ hash_datasheet (const struct datasheet *ds) md4_process_bytes (&end, sizeof end, &ctx); } md4_process_bytes (&ds->column_min_alloc, sizeof ds->column_min_alloc, - &ctx); + &ctx); md4_finish_ctx (&ctx, hash); return hash[0]; } - -