X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcasereader.c;h=ee7facb769dbf9a26dc96d717f1249a7fe44879b;hb=4c4f035bfad520dc54f0d5a9e30e36d4fb009efc;hp=1baeef5d8411b42a0612da6e20855f4c7714a87a;hpb=f5c108becd49d78f4898cab11352291f5689d24e;p=pspp-builds.git diff --git a/src/data/casereader.c b/src/data/casereader.c index 1baeef5d..ee7facb7 100644 --- a/src/data/casereader.c +++ b/src/data/casereader.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 2007 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 the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -58,19 +56,30 @@ static void insert_shim (struct casereader *); bool casereader_read (struct casereader *reader, struct ccase *c) { - if (reader->case_cnt != 0 && reader->class->read (reader, reader->aux, c)) + if (reader->case_cnt != 0) { - assert (case_get_value_cnt (c) == reader->value_cnt); + /* ->read may use casereader_swap to replace itself by + another reader and then delegate to that reader by + recursively calling casereader_read. Currently only + lazy_casereader does this and, with luck, nothing else + ever will. + + To allow this to work, however, we must decrement + case_cnt before calling ->read. If we decremented + case_cnt after calling ->read, then this would actually + drop two cases from case_cnt instead of one, and we'd + lose the last case in the casereader. */ if (reader->case_cnt != CASENUMBER_MAX) reader->case_cnt--; - return true; - } - else - { - reader->case_cnt = 0; - case_nullify (c); - return false; + if (reader->class->read (reader, reader->aux, c)) + { + assert (case_get_value_cnt (c) >= reader->value_cnt); + return true; + } } + reader->case_cnt = 0; + case_nullify (c); + return false; } /* Destroys READER. @@ -97,6 +106,8 @@ casereader_clone (const struct casereader *reader_) { struct casereader *reader = (struct casereader *) reader_; struct casereader *clone; + if ( reader == NULL ) + return NULL; if (reader->class->clone == NULL) insert_shim (reader); @@ -172,6 +183,24 @@ casereader_peek (struct casereader *reader, casenumber idx, struct ccase *c) return false; } +/* Returns true if no cases remain to be read from READER, or if + an error has occurred on READER. (A return value of false + does *not* mean that the next call to casereader_peek or + casereader_read will return true, because an error can occur + in the meantime.) */ +bool +casereader_is_empty (struct casereader *reader) +{ + struct ccase c; + if (reader->case_cnt == 0 || !casereader_peek (reader, 0, &c)) + return true; + else + { + case_destroy (&c); + return false; + } +} + /* Returns true if an I/O error or another hard error has occurred on READER, a clone of READER, or on some object on which READER's data has a dependency, false otherwise. */ @@ -311,6 +340,26 @@ casereader_create_sequential (const struct taint *taint, reader->aux = aux; return reader; } + +/* If READER is a casereader of the given CLASS, returns its + associated auxiliary data; otherwise, returns a null pointer. + + This function is intended for use from casereader + implementations, not by casereader users. Even within + casereader implementations, its usefulness is quite limited, + for at least two reasons. First, every casereader member + function already receives a pointer to the casereader's + auxiliary data. Second, a casereader's class can change + (through a call to casereader_swap) and this is in practice + quite common (e.g. any call to casereader_clone on a + casereader that does not directly support clone will cause the + casereader to be replaced by a shim caseader). */ +void * +casereader_dynamic_cast (struct casereader *reader, + const struct casereader_class *class) +{ + return reader->class == class ? reader->aux : NULL; +} /* Random-access casereader implementation. @@ -344,7 +393,7 @@ struct random_reader_shared void *aux; }; -static struct casereader_class random_reader_casereader_class; +static const struct casereader_class random_reader_casereader_class; /* Creates and returns a new random_reader with the given SHARED data and OFFSET. Inserts the new random reader into the @@ -492,7 +541,7 @@ random_reader_peek (struct casereader *reader, void *br_, } /* Casereader class for random reader. */ -static struct casereader_class random_reader_casereader_class = +static const struct casereader_class random_reader_casereader_class = { random_reader_read, random_reader_destroy, @@ -531,7 +580,7 @@ struct shim struct casereader *subreader; /* Subordinate casereader. */ }; -static struct casereader_random_class shim_class; +static const struct casereader_random_class shim_class; /* Interposes a buffering shim atop READER. */ static void @@ -540,7 +589,7 @@ insert_shim (struct casereader *reader) size_t value_cnt = casereader_get_value_cnt (reader); casenumber case_cnt = casereader_get_case_cnt (reader); struct shim *b = xmalloc (sizeof *b); - b->window = casewindow_create (value_cnt, get_workspace_cases (value_cnt)); + b->window = casewindow_create (value_cnt, settings_get_workspace_cases (value_cnt)); b->subreader = casereader_create_random (value_cnt, case_cnt, &shim_class, b); casereader_swap (reader, b->subreader); @@ -597,7 +646,7 @@ shim_advance (struct casereader *reader UNUSED, void *b_, casenumber case_cnt) } /* Class for the buffered reader. */ -static struct casereader_random_class shim_class = +static const struct casereader_random_class shim_class = { shim_read, shim_destroy,