Implement DATASET commands.
[pspp-builds.git] / src / data / session.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include "data/session.h"
20
21 #include <assert.h>
22 #include <stdlib.h>
23
24 #include "data/dataset.h"
25 #include "libpspp/assertion.h"
26 #include "libpspp/cast.h"
27 #include "libpspp/hash-functions.h"
28 #include "libpspp/str.h"
29 #include "libpspp/hmapx.h"
30
31 #include "gl/xalloc.h"
32
33 struct session
34   {
35     struct hmapx datasets;
36     struct dataset *active;
37     char *syntax_encoding;      /* Default encoding for syntax files. */
38   };
39
40 static struct hmapx_node *session_lookup_dataset__ (const struct session *,
41                                                     const char *name);
42
43 struct session *
44 session_create (void)
45 {
46   struct session *s;
47
48   s = xmalloc (sizeof *s);
49   hmapx_init (&s->datasets);
50   s->active = NULL;
51   s->syntax_encoding = xstrdup ("Auto");
52   return s;
53 }
54
55 void
56 session_destroy (struct session *s)
57 {
58   if (s != NULL)
59     {
60       struct hmapx_node *node, *next;
61       struct dataset *ds;
62
63       s->active = NULL;
64       HMAPX_FOR_EACH_SAFE (ds, node, next, &s->datasets)
65         dataset_destroy (ds);
66       free (s->syntax_encoding);
67       free (s);
68     }
69 }
70
71 struct dataset *
72 session_active_dataset (struct session *s)
73 {
74   return s->active;
75 }
76
77 void
78 session_set_active_dataset (struct session *s, struct dataset *ds)
79 {
80   assert (ds == NULL || dataset_session (ds) == s);
81   s->active = ds;
82 }
83
84 void
85 session_add_dataset (struct session *s, struct dataset *ds)
86 {
87   struct dataset *old;
88
89   old = session_lookup_dataset (s, dataset_name (ds));
90   if (old == s->active)
91     s->active = ds;
92   if (old != NULL)
93     session_remove_dataset (s, old);
94
95   hmapx_insert (&s->datasets, ds, hash_case_string (dataset_name (ds), 0));
96   if (s->active == NULL)
97     s->active = ds;
98
99   dataset_set_session__ (ds, s);
100 }
101
102 void
103 session_remove_dataset (struct session *s, struct dataset *ds)
104 {
105   assert (ds != s->active);
106   hmapx_delete (&s->datasets, session_lookup_dataset__ (s, dataset_name (ds)));
107   dataset_set_session__ (ds, NULL);
108 }
109
110 struct dataset *
111 session_lookup_dataset (const struct session *s, const char *name)
112 {
113   struct hmapx_node *node = session_lookup_dataset__ (s, name);
114   return node != NULL ? node->data : NULL;
115 }
116
117 struct dataset *
118 session_lookup_dataset_assert (const struct session *s, const char *name)
119 {
120   struct dataset *ds = session_lookup_dataset (s, name);
121   assert (ds != NULL);
122   return ds;
123 }
124
125 void
126 session_set_default_syntax_encoding (struct session *s, const char *encoding)
127 {
128   free (s->syntax_encoding);
129   s->syntax_encoding = xstrdup (encoding);
130 }
131
132 const char *
133 session_get_default_syntax_encoding (const struct session *s)
134 {
135   return s->syntax_encoding;
136 }
137
138 size_t
139 session_n_datasets (const struct session *s)
140 {
141   return hmapx_count (&s->datasets);
142 }
143
144 void
145 session_for_each_dataset (const struct session *s,
146                           void (*cb) (struct dataset *, void *aux),
147                           void *aux)
148 {
149   struct hmapx_node *node, *next;
150   struct dataset *ds;
151
152   HMAPX_FOR_EACH_SAFE (ds, node, next, &s->datasets)
153     cb (ds, aux);
154 }
155
156 struct dataset *
157 session_get_dataset_by_seqno (const struct session *s, unsigned int seqno)
158 {
159   struct hmapx_node *node;
160   struct dataset *ds;
161
162   HMAPX_FOR_EACH (ds, node, &s->datasets)
163     if (dataset_seqno (ds) == seqno)
164       return ds;
165   return NULL;
166 }
167 \f
168 static struct hmapx_node *
169 session_lookup_dataset__ (const struct session *s_, const char *name)
170 {
171   struct session *s = CONST_CAST (struct session *, s_);
172   struct hmapx_node *node;
173   struct dataset *ds;
174
175   HMAPX_FOR_EACH_WITH_HASH (ds, node, hash_case_string (name, 0), &s->datasets)
176     if (!strcasecmp (dataset_name (ds), name))
177       return node;
178
179   return NULL;
180 }