X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fcasewindow.c;h=804a58aa517cbb344fb5a8f56b9616da5e5168b4;hb=81579d9e9f994fb2908f50af41c3eb033d216e58;hp=605b22b7627769b8c3df8d52bbb5eec9875f7003;hpb=f5c108becd49d78f4898cab11352291f5689d24e;p=pspp-builds.git diff --git a/src/data/casewindow.c b/src/data/casewindow.c index 605b22b7..804a58aa 100644 --- a/src/data/casewindow.c +++ b/src/data/casewindow.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. - Copyright (C) 2007 Free Software Foundation, Inc. +/* PSPP - a program for statistical analysis. + Copyright (C) 2007, 2009, 2011 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 . */ /* This casewindow implementation in terms of an class interface is undoubtedly a form of over-abstraction. However, it works @@ -22,23 +20,23 @@ #include -#include +#include "data/casewindow.h" #include -#include -#include -#include -#include -#include +#include "data/case-tmpfile.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/deque.h" +#include "libpspp/taint.h" -#include "xalloc.h" +#include "gl/xalloc.h" /* A queue of cases. */ struct casewindow { /* Common data. */ - size_t value_cnt; /* Number of values per case. */ + struct caseproto *proto; /* Prototype of cases in window. */ casenumber max_in_core_cases; /* Max cases before dumping to disk. */ struct taint *taint; /* Taint status. */ @@ -50,11 +48,11 @@ struct casewindow /* Implementation of a casewindow. */ struct casewindow_class { - void *(*create) (struct taint *, size_t value_cnt); + void *(*create) (struct taint *, const struct caseproto *); void (*destroy) (void *aux); void (*push_head) (void *aux, struct ccase *); void (*pop_tail) (void *aux, casenumber cnt); - bool (*get_case) (void *aux, casenumber ofs, struct ccase *); + struct ccase *(*get_case) (void *aux, casenumber ofs); casenumber (*get_case_cnt) (const void *aux); }; @@ -65,28 +63,30 @@ static const struct casewindow_class casewindow_file_class; /* Creates and returns a new casewindow using the given parameters. */ static struct casewindow * -do_casewindow_create (struct taint *taint, - size_t value_cnt, casenumber max_in_core_cases) +do_casewindow_create (struct taint *taint, const struct caseproto *proto, + casenumber max_in_core_cases) { struct casewindow *cw = xmalloc (sizeof *cw); cw->class = (max_in_core_cases ? &casewindow_memory_class : &casewindow_file_class); - cw->aux = cw->class->create (taint, value_cnt); - cw->value_cnt = value_cnt; + cw->aux = cw->class->create (taint, proto); + cw->proto = caseproto_ref (proto); cw->max_in_core_cases = max_in_core_cases; cw->taint = taint; return cw; } -/* Creates and returns a new casewindow for cases with VALUE_CNT - values each. If the casewindow holds more than +/* Creates and returns a new casewindow for cases that take the + form specified by PROTO. If the casewindow holds more than MAX_IN_CORE_CASES cases at any time, its cases will be dumped - to disk; otherwise, its cases will be held in memory. */ + to disk; otherwise, its cases will be held in memory. + + The caller retains its reference to PROTO. */ struct casewindow * -casewindow_create (size_t value_cnt, casenumber max_in_core_cases) +casewindow_create (const struct caseproto *proto, casenumber max_in_core_cases) { - return do_casewindow_create (taint_create (), value_cnt, max_in_core_cases); + return do_casewindow_create (taint_create (), proto, max_in_core_cases); } /* Destroys casewindow CW. @@ -100,6 +100,7 @@ casewindow_destroy (struct casewindow *cw) { cw->class->destroy (cw->aux); ok = taint_destroy (cw->taint); + caseproto_unref (cw->proto); free (cw); } return ok; @@ -119,14 +120,14 @@ static void casewindow_to_disk (struct casewindow *old) { struct casewindow *new; - new = do_casewindow_create (taint_clone (old->taint), old->value_cnt, 0); + new = do_casewindow_create (taint_clone (old->taint), old->proto, 0); while (casewindow_get_case_cnt (old) > 0 && !casewindow_error (new)) { - struct ccase c; - if (!casewindow_get_case (old, 0, &c)) + struct ccase *c = casewindow_get_case (old, 0); + if (c == NULL) break; casewindow_pop_tail (old, 1); - casewindow_push_head (new, &c); + casewindow_push_head (new, c); } casewindow_swap (old, new); casewindow_destroy (new); @@ -149,7 +150,7 @@ casewindow_push_head (struct casewindow *cw, struct ccase *c) } } else - case_destroy (c); + case_unref (c); } /* Deletes CASE_CNT cases at the tail of casewindow CW. */ @@ -160,23 +161,19 @@ casewindow_pop_tail (struct casewindow *cw, casenumber case_cnt) cw->class->pop_tail (cw->aux, case_cnt); } -/* Copies the case that is CASE_IDX cases away from CW's tail - into C. Returns true if successful, false on an I/O error or - if CW is otherwise tainted. On failure, nullifies case C. */ -bool -casewindow_get_case (const struct casewindow *cw_, casenumber case_idx, - struct ccase *c) +/* Returns the case that is CASE_IDX cases away from CW's tail + into C, or a null pointer on an I/O error or if CW is + otherwise tainted. The caller must call case_unref() on the + returned case when it is no longer needed. */ +struct ccase * +casewindow_get_case (const struct casewindow *cw_, casenumber case_idx) { - struct casewindow *cw = (struct casewindow *) cw_; + struct casewindow *cw = CONST_CAST (struct casewindow *, cw_); assert (case_idx >= 0 && case_idx < casewindow_get_case_cnt (cw)); - if (!casewindow_error (cw)) - return cw->class->get_case (cw->aux, case_idx, c); - else - { - case_nullify (c); - return false; - } + if (casewindow_error (cw)) + return NULL; + return cw->class->get_case (cw->aux, case_idx); } /* Returns the number of cases in casewindow CW. */ @@ -186,11 +183,12 @@ casewindow_get_case_cnt (const struct casewindow *cw) return cw->class->get_case_cnt (cw->aux); } -/* Returns the number of values per case in casewindow CW. */ -size_t -casewindow_get_value_cnt (const struct casewindow *cw) +/* Returns the case prototype for the cases in casewindow CW. + The caller must not unref the returned prototype. */ +const struct caseproto * +casewindow_get_proto (const struct casewindow *cw) { - return cw->value_cnt; + return cw->proto; } /* Returns true if casewindow CW is tainted. @@ -220,11 +218,12 @@ casewindow_get_taint (const struct casewindow *cw) struct casewindow_memory { struct deque deque; - struct ccase *cases; + struct ccase **cases; }; static void * -casewindow_memory_create (struct taint *taint UNUSED, size_t value_cnt UNUSED) +casewindow_memory_create (struct taint *taint UNUSED, + const struct caseproto *proto UNUSED) { struct casewindow_memory *cwm = xmalloc (sizeof *cwm); cwm->cases = deque_init (&cwm->deque, 4, sizeof *cwm->cases); @@ -236,7 +235,7 @@ casewindow_memory_destroy (void *cwm_) { struct casewindow_memory *cwm = cwm_; while (!deque_is_empty (&cwm->deque)) - case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]); + case_unref (cwm->cases[deque_pop_front (&cwm->deque)]); free (cwm->cases); free (cwm); } @@ -247,7 +246,7 @@ casewindow_memory_push_head (void *cwm_, struct ccase *c) struct casewindow_memory *cwm = cwm_; if (deque_is_full (&cwm->deque)) cwm->cases = deque_expand (&cwm->deque, cwm->cases, sizeof *cwm->cases); - case_move (&cwm->cases[deque_push_back (&cwm->deque)], c); + cwm->cases[deque_push_back (&cwm->deque)] = c; } static void @@ -256,15 +255,14 @@ casewindow_memory_pop_tail (void *cwm_, casenumber case_cnt) struct casewindow_memory *cwm = cwm_; assert (deque_count (&cwm->deque) >= case_cnt); while (case_cnt-- > 0) - case_destroy (&cwm->cases[deque_pop_front (&cwm->deque)]); + case_unref (cwm->cases[deque_pop_front (&cwm->deque)]); } -static bool -casewindow_memory_get_case (void *cwm_, casenumber ofs, struct ccase *c) +static struct ccase * +casewindow_memory_get_case (void *cwm_, casenumber ofs) { struct casewindow_memory *cwm = cwm_; - case_clone (c, &cwm->cases[deque_front (&cwm->deque, ofs)]); - return true; + return case_ref (cwm->cases[deque_front (&cwm->deque, ofs)]); } static casenumber @@ -292,10 +290,10 @@ struct casewindow_file }; static void * -casewindow_file_create (struct taint *taint, size_t value_cnt) +casewindow_file_create (struct taint *taint, const struct caseproto *proto) { struct casewindow_file *cwf = xmalloc (sizeof *cwf); - cwf->file = case_tmpfile_create (value_cnt); + cwf->file = case_tmpfile_create (proto); cwf->head = cwf->tail = 0; taint_propagate (case_tmpfile_get_taint (cwf->file), taint); return cwf; @@ -327,11 +325,11 @@ casewindow_file_pop_tail (void *cwf_, casenumber cnt) cwf->head = cwf->tail = 0; } -static bool -casewindow_file_get_case (void *cwf_, casenumber ofs, struct ccase *c) +static struct ccase * +casewindow_file_get_case (void *cwf_, casenumber ofs) { struct casewindow_file *cwf = cwf_; - return case_tmpfile_get_case (cwf->file, cwf->tail + ofs, c); + return case_tmpfile_get_case (cwf->file, cwf->tail + ofs); } static casenumber