Independent Samples T-Test Dialog: Fix Crash
[pspp.git] / src / data / casereader-project.c
blob55a8993bab93f297bd84855caade6f9dd3fe239a
1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 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/>. */
17 #include <config.h>
19 #include "data/casereader-provider.h"
20 #include "data/subcase.h"
22 #include "gl/xalloc.h"
24 static bool
25 projection_is_no_op (const struct casereader *reader, const struct subcase *sc)
27 size_t n = subcase_get_n_fields (sc);
28 size_t i;
30 if (n != caseproto_get_n_widths (casereader_get_proto (reader)))
31 return false;
33 for (i = 0; i < n; i++)
34 if (subcase_get_case_index (sc, i) != i)
35 return false;
37 return true;
40 struct casereader_project
42 struct subcase old_sc;
43 struct subcase new_sc;
46 static struct ccase *
47 project_case (struct ccase *old, void *project_)
49 const struct casereader_project *project = project_;
50 struct ccase *new = case_create (subcase_get_proto (&project->new_sc));
51 subcase_copy (&project->old_sc, old, &project->new_sc, new);
52 case_unref (old);
53 return new;
56 static bool
57 destroy_projection (void *project_)
59 struct casereader_project *project = project_;
60 subcase_uninit (&project->old_sc);
61 subcase_uninit (&project->new_sc);
62 free (project);
63 return true;
66 /* Returns a casereader in which each row is obtained by extracting the subcase
67 SC from the corresponding row of SUBREADER. */
68 struct casereader *
69 casereader_project (struct casereader *subreader, const struct subcase *sc)
71 if (projection_is_no_op (subreader, sc))
72 return casereader_rename (subreader);
73 else
75 struct casereader_project *project = xmalloc (sizeof *project);
76 const struct caseproto *proto;
78 subcase_clone (&project->old_sc, sc);
79 proto = subcase_get_proto (&project->old_sc);
81 subcase_init_empty (&project->new_sc);
82 subcase_add_proto_always (&project->new_sc, proto);
84 static const struct casereader_translator_class class = {
85 project_case, destroy_projection,
88 return casereader_translate_stateless (subreader, proto,
89 &class, project);
93 /* Returns a casereader in which each row is obtained by extracting the value
94 with index COLUMN from the corresponding row of SUBREADER. */
95 struct casereader *
96 casereader_project_1 (struct casereader *subreader, int column)
98 const struct caseproto *subproto = casereader_get_proto (subreader);
99 struct casereader *reader;
100 struct subcase sc;
102 subcase_init (&sc, column, caseproto_get_width (subproto, column),
103 SC_ASCEND);
104 reader = casereader_project (subreader, &sc);
105 subcase_uninit (&sc);
107 return reader;