1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "data/lazy-casereader.h"
23 #include "data/case.h"
24 #include "data/casereader.h"
25 #include "data/casereader-provider.h"
26 #include "libpspp/assertion.h"
28 #include "gl/xalloc.h"
30 /* A lazy casereader's auxiliary data. */
31 struct lazy_casereader
33 unsigned long int serial
;
34 struct casereader
*(*callback
) (void *aux
);
38 static const struct casereader_class lazy_casereader_class
;
40 /* Creates and returns a new lazy casereader that will
41 instantiate its underlying casereader, if necessary, by
42 calling CALLBACK, passing AUX as its argument. *SERIAL is set
43 to a "serial number" that uniquely identifies the new lazy
44 casereader, for use with lazy_casereader_destroy.
46 PROTO must be the format of the cases to be read from the
49 CASE_CNT is an upper limit on the number of cases that
50 casereader_read will return from the casereader in successive
51 calls. Ordinarily, this is the actual number of cases in the
52 data source or CASENUMBER_MAX if the number of cases cannot be
53 predicted in advance. */
55 lazy_casereader_create (const struct caseproto
*proto
, casenumber case_cnt
,
56 struct casereader
*(*callback
) (void *aux
), void *aux
,
57 unsigned long int *serial
)
59 static unsigned long int next_serial
= 0;
60 struct lazy_casereader
*lc
;
61 assert (callback
!= NULL
);
62 lc
= xmalloc (sizeof *lc
);
63 *serial
= lc
->serial
= next_serial
++;
64 lc
->callback
= callback
;
66 return casereader_create_sequential (NULL
, proto
, case_cnt
,
67 &lazy_casereader_class
, lc
);
70 /* If READER is the lazy casereader that was returned by
71 lazy_casereader_create along with SERIAL, and READER was never
72 instantiated by any use of a casereader function, then this
73 function destroys READER without instantiating it, and returns
74 true. Returns false in any other case; that is, if READER is
75 not a lazy casereader, or if READER is a lazy casereader with
76 a serial number different from SERIAL, or if READER is a lazy
77 casereader that was instantiated.
79 When this function returns true, it necessarily indicates
80 that the lazy casereader was never cloned and never
83 lazy_casereader_destroy (struct casereader
*reader
, unsigned long int serial
)
85 struct lazy_casereader
*lc
;
90 lc
= casereader_dynamic_cast (reader
, &lazy_casereader_class
);
91 if (lc
== NULL
|| lc
->serial
!= serial
)
95 casereader_destroy (reader
);
99 /* Instantiates lazy casereader READER, which is associated with
102 instantiate_lazy_casereader (struct casereader
*reader
,
103 struct lazy_casereader
*lc
)
105 struct casereader
*subreader
;
107 /* Call the client-provided callback to obtain the real
108 casereader, then swap READER with that casereader. */
109 subreader
= lc
->callback (lc
->aux
);
110 casereader_swap (reader
, subreader
);
112 /* Now destroy the lazy casereader, which is no longer needed
113 since we already swapped it out. Set the callback to null
114 to prevent lazy_casereader_do_destroy from trying to
115 instantiate it again. */
117 casereader_destroy (subreader
);
120 static struct ccase
*
121 lazy_casereader_read (struct casereader
*reader
, void *lc_
)
123 struct lazy_casereader
*lc
= lc_
;
124 instantiate_lazy_casereader (reader
, lc
);
125 return casereader_read (reader
);
129 lazy_casereader_do_destroy (struct casereader
*reader UNUSED
, void *lc_
)
131 struct lazy_casereader
*lc
= lc_
;
132 if (lc
->callback
!= NULL
)
133 casereader_destroy (lc
->callback (lc
->aux
));
137 static struct casereader
*
138 lazy_casereader_clone (struct casereader
*reader
, void *lc_
)
140 struct lazy_casereader
*lc
= lc_
;
141 instantiate_lazy_casereader (reader
, lc
);
142 return casereader_clone (reader
);
145 static struct ccase
*
146 lazy_casereader_peek (struct casereader
*reader
, void *lc_
, casenumber idx
)
148 struct lazy_casereader
*lc
= lc_
;
149 instantiate_lazy_casereader (reader
, lc
);
150 return casereader_peek (reader
, idx
);
153 static const struct casereader_class lazy_casereader_class
=
155 lazy_casereader_read
,
156 lazy_casereader_do_destroy
,
157 lazy_casereader_clone
,
158 lazy_casereader_peek
,