X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcasereader.c;h=8b78645627e1243f4efb875612b97eac2666cc70;hb=c90c44ab307b3ba49f606d2bae80e6aff1e228d7;hp=3be1042d8224f2e4b97d6beb66e4dcc71adb56ee;hpb=2a802b79f217dfa51749c1f2b594c061b5d85120;p=pspp diff --git a/src/data/casereader.c b/src/data/casereader.c index 3be1042d82..8b78645627 100644 --- a/src/data/casereader.c +++ b/src/data/casereader.c @@ -56,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. @@ -311,6 +322,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, + struct casereader_class *class) +{ + return reader->class == class ? reader->aux : NULL; +} /* Random-access casereader implementation.