From a37754c18dee3d5941e5fe041b2c1fa1a3370157 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 25 Sep 2006 09:35:15 +0000 Subject: [PATCH] Added casereader_clone function. Introduced casenum_t type to enumerate and count cases. --- po/de.po | 38 ++++++++--------- po/pspp.pot | 38 ++++++++--------- src/data/ChangeLog | 7 ++++ src/data/casefile-private.h | 2 + src/data/casefile.c | 13 ++++++ src/data/casefile.h | 9 +++- src/data/fastfile.c | 42 ++++++++++++++++++- src/data/procedure.c | 4 +- src/data/transformations.h | 4 +- src/language/control/do-if.c | 4 +- src/language/control/loop.c | 6 +-- src/language/data-io/data-list.c | 2 +- src/language/data-io/get.c | 2 +- src/language/data-io/inpt-pgm.c | 6 +-- src/language/data-io/print-space.c | 2 +- src/language/data-io/print.c | 2 +- src/language/stats/autorecode.c | 2 +- src/language/stats/descriptives.c | 2 +- src/language/stats/regression.q | 6 ++- src/language/tests/casefile-test.c | 66 +++++++++++++++++++++++++++++- src/language/xforms/compute.c | 8 ++-- src/language/xforms/count.c | 2 +- src/language/xforms/recode.c | 2 +- src/language/xforms/sample.c | 2 +- src/language/xforms/select-if.c | 2 +- src/ui/flexifile.c | 21 +++++++++- tests/xforms/casefile.sh | 5 --- 27 files changed, 223 insertions(+), 76 deletions(-) diff --git a/po/de.po b/po/de.po index 145f70c6..e9998f07 100644 --- a/po/de.po +++ b/po/de.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: PSPP 0.4.2\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2006-07-30 14:13+0800\n" +"POT-Creation-Date: 2006-09-25 16:28+0800\n" "PO-Revision-Date: 2006-05-26 17:49+0800\n" "Last-Translator: John Darrington \n" "Language-Team: German \n" @@ -268,32 +268,32 @@ msgid "" "system-missing, zero, or negative. These case(s) were ignored." msgstr "" -#: src/data/fastfile.c:499 +#: src/data/fastfile.c:536 #, c-format msgid "%s: Removing temporary file: %s." msgstr "" -#: src/data/fastfile.c:623 +#: src/data/fastfile.c:660 #, c-format msgid "Error writing temporary file: %s." msgstr "" -#: src/data/fastfile.c:651 +#: src/data/fastfile.c:688 #, c-format msgid "%s: Opening temporary file: %s." msgstr "" -#: src/data/fastfile.c:695 +#: src/data/fastfile.c:732 #, c-format msgid "%s: Seeking temporary file: %s." msgstr "" -#: src/data/fastfile.c:717 +#: src/data/fastfile.c:754 #, c-format msgid "%s: Reading temporary file: %s." msgstr "" -#: src/data/fastfile.c:720 +#: src/data/fastfile.c:757 #, c-format msgid "%s: Temporary file ended unexpectedly." msgstr "" @@ -1163,24 +1163,24 @@ msgid "" msgstr "" #: src/language/data-io/data-list.c:403 src/language/data-io/data-list.c:503 -#: src/language/data-io/print.c:368 src/language/dictionary/split-file.c:84 +#: src/language/data-io/print.c:370 src/language/dictionary/split-file.c:84 #: src/language/dictionary/sys-file-info.c:144 #: src/language/dictionary/sys-file-info.c:378 #: src/language/stats/descriptives.c:894 msgid "Variable" msgstr "" -#: src/language/data-io/data-list.c:404 src/language/data-io/print.c:369 +#: src/language/data-io/data-list.c:404 src/language/data-io/print.c:371 msgid "Record" msgstr "" -#: src/language/data-io/data-list.c:405 src/language/data-io/print.c:370 +#: src/language/data-io/data-list.c:405 src/language/data-io/print.c:372 #: src/ui/gui/var-sheet.c:78 msgid "Columns" msgstr "Spalten" #: src/language/data-io/data-list.c:406 src/language/data-io/data-list.c:504 -#: src/language/data-io/print.c:371 +#: src/language/data-io/print.c:373 msgid "Format" msgstr "" @@ -1416,7 +1416,7 @@ msgstr "" msgid "COLUMN subcommand multiply specified." msgstr "" -#: src/language/data-io/inpt-pgm.c:385 +#: src/language/data-io/inpt-pgm.c:384 msgid "" "REREAD: Column numbers must be positive finite numbers. Column set to 1." msgstr "" @@ -1678,19 +1678,19 @@ msgid "" "Data fields must be listed in order of increasing record number." msgstr "" -#: src/language/data-io/print.c:246 +#: src/language/data-io/print.c:248 #, c-format msgid "Output calls for %d records but %d specified on RECORDS subcommand." msgstr "" -#: src/language/data-io/print.c:400 +#: src/language/data-io/print.c:402 #, c-format msgid "Writing %d record to %s." msgid_plural "Writing %d records to %s." msgstr[0] "" msgstr[1] "" -#: src/language/data-io/print.c:404 +#: src/language/data-io/print.c:406 #, c-format msgid "Writing %d record." msgid_plural "Writing %d records." @@ -1727,7 +1727,7 @@ msgid "No matching variables found between the source and target files." msgstr "" #: src/language/dictionary/formats.c:92 -msgid "`(' expected after variable list" +msgid "`(' expected after variable list." msgstr "" #: src/language/dictionary/formats.c:102 src/language/dictionary/numeric.c:71 @@ -4222,7 +4222,7 @@ msgstr "Alle Datei" msgid "Save Data As" msgstr "Speichern unter" -#: src/ui/gui/menu-actions.c:582 +#: src/ui/gui/menu-actions.c:500 msgid "Font Selection" msgstr "Schriftwahlung" @@ -4250,11 +4250,11 @@ msgstr "Falshe Spannweitebeschreibung" msgid "Sorry. The help system hasn't yet been implemented." msgstr "Es gibt noch nicht kein Helpsysteme. Schade!" -#: src/ui/gui/psppire-data-store.c:731 +#: src/ui/gui/psppire-data-store.c:733 msgid "var" msgstr "" -#: src/ui/gui/psppire-data-store.c:812 src/ui/gui/psppire-var-store.c:518 +#: src/ui/gui/psppire-data-store.c:814 src/ui/gui/psppire-var-store.c:518 #: src/ui/gui/psppire-var-store.c:528 src/ui/gui/psppire-var-store.c:538 #: src/ui/gui/psppire-var-store.c:735 #, c-format diff --git a/po/pspp.pot b/po/pspp.pot index 34ae5e40..74ece980 100644 --- a/po/pspp.pot +++ b/po/pspp.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n" -"POT-Creation-Date: 2006-07-30 14:13+0800\n" +"POT-Creation-Date: 2006-09-25 16:28+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -267,32 +267,32 @@ msgid "" "system-missing, zero, or negative. These case(s) were ignored." msgstr "" -#: src/data/fastfile.c:499 +#: src/data/fastfile.c:536 #, c-format msgid "%s: Removing temporary file: %s." msgstr "" -#: src/data/fastfile.c:623 +#: src/data/fastfile.c:660 #, c-format msgid "Error writing temporary file: %s." msgstr "" -#: src/data/fastfile.c:651 +#: src/data/fastfile.c:688 #, c-format msgid "%s: Opening temporary file: %s." msgstr "" -#: src/data/fastfile.c:695 +#: src/data/fastfile.c:732 #, c-format msgid "%s: Seeking temporary file: %s." msgstr "" -#: src/data/fastfile.c:717 +#: src/data/fastfile.c:754 #, c-format msgid "%s: Reading temporary file: %s." msgstr "" -#: src/data/fastfile.c:720 +#: src/data/fastfile.c:757 #, c-format msgid "%s: Temporary file ended unexpectedly." msgstr "" @@ -1162,24 +1162,24 @@ msgid "" msgstr "" #: src/language/data-io/data-list.c:403 src/language/data-io/data-list.c:503 -#: src/language/data-io/print.c:368 src/language/dictionary/split-file.c:84 +#: src/language/data-io/print.c:370 src/language/dictionary/split-file.c:84 #: src/language/dictionary/sys-file-info.c:144 #: src/language/dictionary/sys-file-info.c:378 #: src/language/stats/descriptives.c:894 msgid "Variable" msgstr "" -#: src/language/data-io/data-list.c:404 src/language/data-io/print.c:369 +#: src/language/data-io/data-list.c:404 src/language/data-io/print.c:371 msgid "Record" msgstr "" -#: src/language/data-io/data-list.c:405 src/language/data-io/print.c:370 +#: src/language/data-io/data-list.c:405 src/language/data-io/print.c:372 #: src/ui/gui/var-sheet.c:78 msgid "Columns" msgstr "" #: src/language/data-io/data-list.c:406 src/language/data-io/data-list.c:504 -#: src/language/data-io/print.c:371 +#: src/language/data-io/print.c:373 msgid "Format" msgstr "" @@ -1415,7 +1415,7 @@ msgstr "" msgid "COLUMN subcommand multiply specified." msgstr "" -#: src/language/data-io/inpt-pgm.c:385 +#: src/language/data-io/inpt-pgm.c:384 msgid "" "REREAD: Column numbers must be positive finite numbers. Column set to 1." msgstr "" @@ -1677,19 +1677,19 @@ msgid "" "Data fields must be listed in order of increasing record number." msgstr "" -#: src/language/data-io/print.c:246 +#: src/language/data-io/print.c:248 #, c-format msgid "Output calls for %d records but %d specified on RECORDS subcommand." msgstr "" -#: src/language/data-io/print.c:400 +#: src/language/data-io/print.c:402 #, c-format msgid "Writing %d record to %s." msgid_plural "Writing %d records to %s." msgstr[0] "" msgstr[1] "" -#: src/language/data-io/print.c:404 +#: src/language/data-io/print.c:406 #, c-format msgid "Writing %d record." msgid_plural "Writing %d records." @@ -1726,7 +1726,7 @@ msgid "No matching variables found between the source and target files." msgstr "" #: src/language/dictionary/formats.c:92 -msgid "`(' expected after variable list" +msgid "`(' expected after variable list." msgstr "" #: src/language/dictionary/formats.c:102 src/language/dictionary/numeric.c:71 @@ -4221,7 +4221,7 @@ msgstr "" msgid "Save Data As" msgstr "" -#: src/ui/gui/menu-actions.c:582 +#: src/ui/gui/menu-actions.c:500 msgid "Font Selection" msgstr "" @@ -4249,11 +4249,11 @@ msgstr "" msgid "Sorry. The help system hasn't yet been implemented." msgstr "" -#: src/ui/gui/psppire-data-store.c:731 +#: src/ui/gui/psppire-data-store.c:733 msgid "var" msgstr "" -#: src/ui/gui/psppire-data-store.c:812 src/ui/gui/psppire-var-store.c:518 +#: src/ui/gui/psppire-data-store.c:814 src/ui/gui/psppire-var-store.c:518 #: src/ui/gui/psppire-var-store.c:528 src/ui/gui/psppire-var-store.c:538 #: src/ui/gui/psppire-var-store.c:735 #, c-format diff --git a/src/data/ChangeLog b/src/data/ChangeLog index 30864442..795b4025 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,10 @@ +Mon Sep 25 17:11:46 WST 2006 John Darrington + + * casefile-private.h casefile.c casefile.h fastfile.c: Created new + casereader method casereader_clone. + + * procedure.c pransformations.h: Introduced new type casenum_t + Thu Sep 21 07:00:30 2006 Ben Pfaff * variable.c: (width_to_bytes) Rephrase code for clarify. diff --git a/src/data/casefile-private.h b/src/data/casefile-private.h index 6e35300b..c5902765 100644 --- a/src/data/casefile-private.h +++ b/src/data/casefile-private.h @@ -65,6 +65,8 @@ struct class_casereader unsigned long (*cnum) (const struct casereader *); void (*destroy) (struct casereader * r); + + struct casereader * (*clone) (const struct casereader *); }; diff --git a/src/data/casefile.c b/src/data/casefile.c index 95e0388c..f0e700d5 100644 --- a/src/data/casefile.c +++ b/src/data/casefile.c @@ -157,7 +157,10 @@ casereader_read_xfer (struct casereader *ffr, struct ccase *c) if ( ! read_case ) return false; if ( ffr->destructive && casefile_in_core (cf) ) + { + case_nullify (c); case_move (c, read_case); + } else case_clone (c, read_case); @@ -173,6 +176,16 @@ casereader_destroy (struct casereader *r) r->class->destroy(r); } +/* Creates a copy of R and returns it */ +struct casereader * +casereader_clone(const struct casereader *r) +{ + /* Would we ever want to clone a destructive reader ?? */ + assert ( ! r->destructive ) ; + + return r->class->clone (r); +} + /* Destroys casefile CF. */ void casefile_destroy(struct casefile *cf) diff --git a/src/data/casefile.h b/src/data/casefile.h index 1bddb2d2..9c985001 100644 --- a/src/data/casefile.h +++ b/src/data/casefile.h @@ -30,6 +30,7 @@ struct casereader; struct casefile; +/* Casereader functions */ struct casefile *casereader_get_casefile (const struct casereader *r); @@ -41,6 +42,11 @@ bool casereader_read_xfer (struct casereader *r, struct ccase *c); void casereader_destroy (struct casereader *r); +struct casereader *casereader_clone(const struct casereader *r); + + +/* Casefile functions */ + void casefile_destroy (struct casefile *cf); bool casefile_error (const struct casefile *cf); @@ -50,9 +56,8 @@ unsigned long casefile_get_case_cnt (const struct casefile *cf); size_t casefile_get_value_cnt (const struct casefile *cf); struct casereader *casefile_get_reader (const struct casefile *cf); -struct casereader *casefile_get_destructive_reader (struct casefile *cf); - +struct casereader *casefile_get_destructive_reader (struct casefile *cf); bool casefile_append (struct casefile *cf, const struct ccase *c); diff --git a/src/data/fastfile.c b/src/data/fastfile.c index 9cdba156..c789012b 100644 --- a/src/data/fastfile.c +++ b/src/data/fastfile.c @@ -86,8 +86,7 @@ also read with casereaders in this phase, but the ability to create new casereaders is curtailed. - In this phase, casereaders could still be cloned (once - we eventually implement cloning). + In this phase, casereaders could still be cloned. To transition from phase 1 or 2 to phase 3 and create a casereader, call casefile_get_destructive_reader(). @@ -287,6 +286,44 @@ fastfile_get_reader (const struct casefile *cf_) return reader; } + +/* Creates a copy of the casereader CR, and returns it */ +static struct casereader * +fastfilereader_clone (const struct casereader *cr) +{ + const struct fastfilereader *ffr = (const struct fastfilereader *) cr ; + struct fastfilereader *new_ffr = xzalloc (sizeof *new_ffr); + + struct casereader *new_reader = (struct casereader *) new_ffr; + + struct casefile *cf = casereader_get_casefile (cr); + struct fastfile *ff = (struct fastfile *) cf; + + assert (!cf->being_destroyed); + + /* Flush the buffer to disk if it's not empty. */ + if (ff->mode == WRITE && ff->storage == DISK) + flush_buffer (ff); + + ff->mode = READ; + + casereader_register (cf, new_reader, &class_reader); + + new_ffr->case_idx = ffr->case_idx ; + new_reader->destructive = cr->destructive; + new_ffr->fd = ffr->fd ; + new_ffr->buffer = ffr->buffer ; + new_ffr->buffer_pos = ffr->buffer_pos; + + if (ff->storage == DISK) + reader_open_file (new_ffr); + + return new_reader; +} + + + + /* Returns the number of `union value's in a case for CF. */ static size_t fastfile_get_value_cnt (const struct casefile *cf) @@ -748,4 +785,5 @@ static const struct class_casereader class_reader = fastfilereader_get_next_case, fastfilereader_cnum, fastfilereader_destroy, + fastfilereader_clone, }; diff --git a/src/data/procedure.c b/src/data/procedure.c index 5649a173..a779771c 100644 --- a/src/data/procedure.c +++ b/src/data/procedure.c @@ -875,7 +875,7 @@ add_case_limit_trns (void) *CASES_REMAINING. */ static int case_limit_trns_proc (void *cases_remaining_, - struct ccase *c UNUSED, int case_nr UNUSED) + struct ccase *c UNUSED, casenum_t case_nr UNUSED) { size_t *cases_remaining = cases_remaining_; if (*cases_remaining > 0) @@ -914,7 +914,7 @@ add_filter_trns (void) /* FILTER transformation. */ static int filter_trns_proc (void *filter_var_, - struct ccase *c UNUSED, int case_nr UNUSED) + struct ccase *c UNUSED, casenum_t case_nr UNUSED) { struct variable *filter_var = filter_var_; diff --git a/src/data/transformations.h b/src/data/transformations.h index 196f65dc..cc552a10 100644 --- a/src/data/transformations.h +++ b/src/data/transformations.h @@ -23,6 +23,8 @@ #include #include +typedef unsigned long casenum_t ; + /* trns_proc_func return values. */ enum trns_result { @@ -35,7 +37,7 @@ enum trns_result struct ccase; typedef void trns_finalize_func (void *); -typedef int trns_proc_func (void *, struct ccase *, int); +typedef int trns_proc_func (void *, struct ccase *, casenum_t); typedef bool trns_free_func (void *); /* Transformation chains. */ diff --git a/src/language/control/do-if.c b/src/language/control/do-if.c index 47fceee6..a0bbf793 100644 --- a/src/language/control/do-if.c +++ b/src/language/control/do-if.c @@ -238,7 +238,7 @@ do_if_finalize_func (void *do_if_ UNUSED) Checks each clause and jumps to the appropriate transformation. */ static int -do_if_trns_proc (void *do_if_, struct ccase *c, int case_num UNUSED) +do_if_trns_proc (void *do_if_, struct ccase *c, casenum_t case_num UNUSED) { struct do_if_trns *do_if = do_if_; struct clause *clause; @@ -277,7 +277,7 @@ do_if_trns_free (void *do_if_) /* Breaks out of a DO IF construct. */ static int -break_trns_proc (void *do_if_, struct ccase *c UNUSED, int case_num UNUSED) +break_trns_proc (void *do_if_, struct ccase *c UNUSED, casenum_t case_num UNUSED) { struct do_if_trns *do_if = do_if_; diff --git a/src/language/control/loop.c b/src/language/control/loop.c index f31486f6..242c936a 100644 --- a/src/language/control/loop.c +++ b/src/language/control/loop.c @@ -273,7 +273,7 @@ loop_trns_finalize (void *do_if_ UNUSED) /* Sets up LOOP for the first pass. */ static int -loop_trns_proc (void *loop_, struct ccase *c, int case_num) +loop_trns_proc (void *loop_, struct ccase *c, casenum_t case_num) { struct loop_trns *loop = loop_; @@ -325,7 +325,7 @@ loop_trns_free (void *loop_) /* Finishes a pass through the loop and starts the next. */ static int -end_loop_trns_proc (void *loop_, struct ccase *c, int case_num UNUSED) +end_loop_trns_proc (void *loop_, struct ccase *c, casenum_t case_num UNUSED) { struct loop_trns *loop = loop_; @@ -363,7 +363,7 @@ end_loop_trns_proc (void *loop_, struct ccase *c, int case_num UNUSED) /* Executes BREAK. */ static int -break_trns_proc (void *loop_, struct ccase *c UNUSED, int case_num UNUSED) +break_trns_proc (void *loop_, struct ccase *c UNUSED, casenum_t case_num UNUSED) { struct loop_trns *loop = loop_; diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index e86c91b3..39bd743e 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -771,7 +771,7 @@ data_list_trns_free (void *dls_) /* Handle DATA LIST transformation DLS, parsing data into C. */ static int -data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED) +data_list_trns_proc (void *dls_, struct ccase *c, casenum_t case_num UNUSED) { struct data_list_pgm *dls = dls_; int retval; diff --git a/src/language/data-io/get.c b/src/language/data-io/get.c index 789d259e..2bb46311 100644 --- a/src/language/data-io/get.c +++ b/src/language/data-io/get.c @@ -542,7 +542,7 @@ parse_output_trns (enum writer_type writer_type) /* Writes case C to the system file specified on XSAVE or XEXPORT. */ static int -output_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED) +output_trns_proc (void *trns_, struct ccase *c, casenum_t case_num UNUSED) { struct output_trns *t = trns_; case_writer_write_case (t->aw, c); diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index c5d6cfe7..11b63319 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.c @@ -297,7 +297,7 @@ cmd_end_case (void) /* Sends the current case as the source's output. */ int -end_case_trns_proc (void *inp_, struct ccase *c, int case_nr UNUSED) +end_case_trns_proc (void *inp_, struct ccase *c, casenum_t case_nr UNUSED) { struct input_program_pgm *inp = inp_; @@ -370,7 +370,7 @@ cmd_reread (void) /* Executes a REREAD transformation. */ static int -reread_trns_proc (void *t_, struct ccase *c, int case_num) +reread_trns_proc (void *t_, struct ccase *c, casenum_t case_num) { struct reread_trns *t = t_; @@ -416,7 +416,7 @@ cmd_end_file (void) /* Executes an END FILE transformation. */ static int end_file_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED, - int case_num UNUSED) + casenum_t case_num UNUSED) { return TRNS_END_FILE; } diff --git a/src/language/data-io/print-space.c b/src/language/data-io/print-space.c index 1388f297..7eddf99d 100644 --- a/src/language/data-io/print-space.c +++ b/src/language/data-io/print-space.c @@ -103,7 +103,7 @@ cmd_print_space (void) /* Executes a PRINT SPACE transformation. */ static int print_space_trns_proc (void *t_, struct ccase *c, - int case_num UNUSED) + casenum_t case_num UNUSED) { struct print_space_trns *trns = t_; int n; diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index 64e1e13f..87f20675 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -416,7 +416,7 @@ static void flush_records (struct print_trns *, /* Performs the transformation inside print_trns T on case C. */ static int -print_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED) +print_trns_proc (void *trns_, struct ccase *c, casenum_t case_num UNUSED) { struct print_trns *trns = trns_; struct prt_out_spec *spec; diff --git a/src/language/stats/autorecode.c b/src/language/stats/autorecode.c index 4d3513ee..f967dd3a 100644 --- a/src/language/stats/autorecode.c +++ b/src/language/stats/autorecode.c @@ -272,7 +272,7 @@ recode (const struct autorecode_pgm *arc) /* Executes an AUTORECODE transformation. */ static int -autorecode_trns_proc (void *trns_, struct ccase *c, int case_idx UNUSED) +autorecode_trns_proc (void *trns_, struct ccase *c, casenum_t case_idx UNUSED) { struct autorecode_trns *trns = trns_; size_t i; diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index eaf9bb7f..a513bc09 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -576,7 +576,7 @@ dump_z_table (struct dsc_proc *dsc) */ static int descriptives_trns_proc (void *trns_, struct ccase * c, - int case_idx UNUSED) + casenum_t case_idx UNUSED) { struct dsc_trns *t = trns_; struct dsc_z_score *z; diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q index 3706760a..83d78144 100644 --- a/src/language/stats/regression.q +++ b/src/language/stats/regression.q @@ -544,7 +544,8 @@ regression_trns_free (void *t_) Gets the predicted values. */ static int -regression_trns_pred_proc (void *t_, struct ccase *c, int case_idx UNUSED) +regression_trns_pred_proc (void *t_, struct ccase *c, + casenum_t case_idx UNUSED) { size_t i; size_t n_vals; @@ -582,7 +583,8 @@ regression_trns_pred_proc (void *t_, struct ccase *c, int case_idx UNUSED) Gets the residuals. */ static int -regression_trns_resid_proc (void *t_, struct ccase *c, int case_idx UNUSED) +regression_trns_resid_proc (void *t_, struct ccase *c, + casenum_t case_idx UNUSED) { size_t i; size_t n_vals; diff --git a/src/language/tests/casefile-test.c b/src/language/tests/casefile-test.c index a90cbfb7..a1927ddb 100644 --- a/src/language/tests/casefile-test.c +++ b/src/language/tests/casefile-test.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "xalloc.h" @@ -38,6 +39,9 @@ static void write_random_case (struct casefile *cf, size_t case_idx); static void read_and_verify_random_case (struct casefile *cf, struct casereader *reader, size_t case_idx); +static void test_casereader_clone (struct casereader *reader1, size_t case_cnt); + + static void fail_test (const char *message, ...); int @@ -63,7 +67,7 @@ cmd_debug_casefile (void) if (token != '.') return lex_end_of_command (); - for (pattern = 0; pattern < 6; pattern++) + for (pattern = 0; pattern < 7; pattern++) { const size_t *size; @@ -129,6 +133,12 @@ test_casefile (int pattern, size_t value_cnt, size_t case_cnt) for (; j < case_cnt; j++) read_and_verify_random_case (cf, r2, j); break; + case 6: + test_casereader_clone (r1, case_cnt); + test_casereader_clone (r2, case_cnt); + break; + default: + NOT_REACHED (); } if (casereader_read (r1, &c)) fail_test ("Casereader 1 not at end of file."); @@ -204,6 +214,60 @@ read_and_verify_random_case (struct casefile *cf, case_destroy (&expected_case); } +static void +test_casereader_clone (struct casereader *reader1, size_t case_cnt) +{ + size_t i; + size_t cases = 0; + struct ccase c1; + struct ccase c2; + struct casefile *src = casereader_get_casefile (reader1); + struct casereader *clone = NULL; + + size_t value_cnt = casefile_get_value_cnt (src); + + struct casefile *newfile = fastfile_create (value_cnt); + struct casereader *newreader; + + + /* Read a 3rd of the cases */ + for ( i = 0 ; i < case_cnt / 3 ; ++i ) + casereader_read (reader1, &c1); + + clone = casereader_clone (reader1); + + /* Copy all the cases into a new file */ + while( casereader_read (reader1, &c1)) + { + casefile_append (newfile, &c1); + cases ++; + } + + newreader = casefile_get_reader (newfile); + + /* Make sure that the new file's are identical to those returned from + the cloned reader */ + while( casereader_read (clone, &c1)) + { + const union value *v1; + const union value *v2; + cases --; + + if ( ! casereader_read_xfer (newreader, &c2) ) + break; + + v1 = case_data_all (&c1) ; + v2 = case_data_all (&c2) ; + + if ( 0 != memcmp (v1, v2, value_cnt * MAX_SHORT_STRING)) + fail_test ("Cloned reader read different value at case %ld", cases); + } + + if ( cases > 0 ) + fail_test ("Cloned reader reads different number of cases."); + +} + static void fail_test (const char *message, ...) { diff --git a/src/language/xforms/compute.c b/src/language/xforms/compute.c index 0bc6e4d3..5c13d2f2 100644 --- a/src/language/xforms/compute.c +++ b/src/language/xforms/compute.c @@ -110,7 +110,7 @@ cmd_compute (void) /* Handle COMPUTE or IF with numeric target variable. */ static int -compute_num (void *compute_, struct ccase *c, int case_num) +compute_num (void *compute_, struct ccase *c, casenum_t case_num) { struct compute_trns *compute = compute_; @@ -125,7 +125,7 @@ compute_num (void *compute_, struct ccase *c, int case_num) /* Handle COMPUTE or IF with numeric vector element target variable. */ static int -compute_num_vec (void *compute_, struct ccase *c, int case_num) +compute_num_vec (void *compute_, struct ccase *c, casenum_t case_num) { struct compute_trns *compute = compute_; @@ -157,7 +157,7 @@ compute_num_vec (void *compute_, struct ccase *c, int case_num) /* Handle COMPUTE or IF with string target variable. */ static int -compute_str (void *compute_, struct ccase *c, int case_num) +compute_str (void *compute_, struct ccase *c, casenum_t case_num) { struct compute_trns *compute = compute_; @@ -172,7 +172,7 @@ compute_str (void *compute_, struct ccase *c, int case_num) /* Handle COMPUTE or IF with string vector element target variable. */ static int -compute_str_vec (void *compute_, struct ccase *c, int case_num) +compute_str_vec (void *compute_, struct ccase *c, casenum_t case_num) { struct compute_trns *compute = compute_; diff --git a/src/language/xforms/count.c b/src/language/xforms/count.c index 38e3e955..8f6c8f62 100644 --- a/src/language/xforms/count.c +++ b/src/language/xforms/count.c @@ -325,7 +325,7 @@ count_string (struct criteria *crit, struct ccase *c) /* Performs the COUNT transformation T on case C. */ static int count_trns_proc (void *trns_, struct ccase *c, - int case_num UNUSED) + casenum_t case_num UNUSED) { struct count_trns *trns = trns_; struct dst_var *dv; diff --git a/src/language/xforms/recode.c b/src/language/xforms/recode.c index 03fd0bc3..05cd3d1c 100644 --- a/src/language/xforms/recode.c +++ b/src/language/xforms/recode.c @@ -622,7 +622,7 @@ find_src_string (struct recode_trns *trns, const char *value, int width) /* Performs RECODE transformation. */ static int -recode_trns_proc (void *trns_, struct ccase *c, int case_idx UNUSED) +recode_trns_proc (void *trns_, struct ccase *c, casenum_t case_idx UNUSED) { struct recode_trns *trns = trns_; size_t i; diff --git a/src/language/xforms/sample.c b/src/language/xforms/sample.c index 41b47f86..8b0650d5 100644 --- a/src/language/xforms/sample.c +++ b/src/language/xforms/sample.c @@ -119,7 +119,7 @@ cmd_sample (void) /* Executes a SAMPLE transformation. */ static int sample_trns_proc (void *t_, struct ccase *c UNUSED, - int case_num UNUSED) + casenum_t case_num UNUSED) { struct sample_trns *t = t_; double U; diff --git a/src/language/xforms/select-if.c b/src/language/xforms/select-if.c index e6dc9b4b..7acb3ec0 100644 --- a/src/language/xforms/select-if.c +++ b/src/language/xforms/select-if.c @@ -73,7 +73,7 @@ cmd_select_if (void) /* Performs the SELECT IF transformation T on case C. */ static int select_if_proc (void *t_, struct ccase *c, - int case_num) + casenum_t case_num) { struct select_if_trns *t = t_; return (expr_evaluate_num (t->e, c, case_num) == 1.0 diff --git a/src/ui/flexifile.c b/src/ui/flexifile.c index 756f67a1..9ed760b2 100644 --- a/src/ui/flexifile.c +++ b/src/ui/flexifile.c @@ -212,6 +212,24 @@ flexifile_get_reader (const struct casefile *cf_) return reader; } + +static struct casereader * +flexifilereader_clone (const struct casereader *cr) +{ + const struct flexifilereader *ffr = (const struct flexifilereader *) cr; + struct flexifilereader *new_ffr = xzalloc (sizeof *new_ffr); + struct casereader *new_reader = (struct casereader *) new_ffr; + struct casefile *cf = casereader_get_casefile (cr); + + casereader_register (cf, new_reader, CLASS_CASEREADER(&class_reader)); + + new_ffr->case_idx = ffr->case_idx ; + new_ffr->destructive = ffr->destructive ; + + return new_reader; +} + + static bool flexifile_in_core(const struct casefile *cf UNUSED) { @@ -268,7 +286,8 @@ static const struct class_flexifilereader class_reader = { flexifilereader_get_next_case, 0, /* cnum */ - flexifilereader_destroy + flexifilereader_destroy, + flexifilereader_clone } }; diff --git a/tests/xforms/casefile.sh b/tests/xforms/casefile.sh index 46e97eab..c3548572 100755 --- a/tests/xforms/casefile.sh +++ b/tests/xforms/casefile.sh @@ -66,12 +66,7 @@ perl -pi -e 's/^\s*$//g' $TEMPDIR/casefile.out diff -b $TEMPDIR/casefile.out - <