gui: Fix Glib-GObject-WARNING when closing the active dataset.
[pspp] / src / data / session.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2010, 2011, 2012 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     unsigned int n_dataset_names; /* For session_generate_dataset_name(). */
39   };
40
41 static struct hmapx_node *session_lookup_dataset__ (const struct session *,
42                                                     const char *name);
43
44 struct session *
45 session_create (void)
46 {
47   struct session *s;
48
49   s = xmalloc (sizeof *s);
50   hmapx_init (&s->datasets);
51   s->active = NULL;
52   s->syntax_encoding = xstrdup ("Auto");
53   s->n_dataset_names = 0;
54   return s;
55 }
56
57 void
58 session_destroy (struct session *s)
59 {
60   if (s != NULL)
61     {
62       struct hmapx_node *node, *next;
63       struct dataset *ds;
64
65       s->active = NULL;
66       HMAPX_FOR_EACH_SAFE (ds, node, next, &s->datasets)
67         dataset_destroy (ds);
68       free (s->syntax_encoding);
69       free (s);
70     }
71 }
72
73 struct dataset *
74 session_active_dataset (struct session *s)
75 {
76   return s->active;
77 }
78
79 void
80 session_set_active_dataset (struct session *s, struct dataset *ds)
81 {
82   assert (ds == NULL || dataset_session (ds) == s);
83   s->active = ds;
84 }
85
86 void
87 session_add_dataset (struct session *s, struct dataset *ds)
88 {
89   struct dataset *old;
90
91   old = session_lookup_dataset (s, dataset_name (ds));
92   if (old == s->active)
93     s->active = ds;
94   if (old != NULL)
95     session_remove_dataset (s, old);
96
97   hmapx_insert (&s->datasets, ds, hash_case_string (dataset_name (ds), 0));
98   if (s->active == NULL)
99     s->active = ds;
100
101   dataset_set_session__ (ds, s);
102 }
103
104 void
105 session_remove_dataset (struct session *s, struct dataset *ds)
106 {
107   assert (ds != s->active);
108   hmapx_delete (&s->datasets, session_lookup_dataset__ (s, dataset_name (ds)));
109   dataset_set_session__ (ds, NULL);
110 }
111
112 struct dataset *
113 session_lookup_dataset (const struct session *s, const char *name)
114 {
115   struct hmapx_node *node = session_lookup_dataset__ (s, name);
116   return node != NULL ? node->data : NULL;
117 }
118
119 struct dataset *
120 session_lookup_dataset_assert (const struct session *s, const char *name)
121 {
122   struct dataset *ds = session_lookup_dataset (s, name);
123   assert (ds != NULL);
124   return ds;
125 }
126
127 void
128 session_set_default_syntax_encoding (struct session *s, const char *encoding)
129 {
130   free (s->syntax_encoding);
131   s->syntax_encoding = xstrdup (encoding);
132 }
133
134 const char *
135 session_get_default_syntax_encoding (const struct session *s)
136 {
137   return s->syntax_encoding;
138 }
139
140 size_t
141 session_n_datasets (const struct session *s)
142 {
143   return hmapx_count (&s->datasets);
144 }
145
146 void
147 session_for_each_dataset (const struct session *s,
148                           void (*cb) (struct dataset *, void *aux),
149                           void *aux)
150 {
151   struct hmapx_node *node, *next;
152   struct dataset *ds;
153
154   HMAPX_FOR_EACH_SAFE (ds, node, next, &s->datasets)
155     cb (ds, aux);
156 }
157
158 struct dataset *
159 session_get_dataset_by_seqno (const struct session *s, unsigned int seqno)
160 {
161   struct hmapx_node *node;
162   struct dataset *ds;
163
164   HMAPX_FOR_EACH (ds, node, &s->datasets)
165     if (dataset_seqno (ds) == seqno)
166       return ds;
167   return NULL;
168 }
169
170 /* Returns an identifier that is is not currently in use as a dataset name.
171    The caller must free the returned identifier, with free(). */
172 char *
173 session_generate_dataset_name (struct session *s)
174 {
175   for (;;)
176     {
177       char *name;
178
179       s->n_dataset_names++;
180       assert(s->n_dataset_names != 0);
181
182       name = xasprintf ("DataSet%u", s->n_dataset_names);
183       if (!session_lookup_dataset (s, name))
184         return name;
185       free (name);
186     }
187 }
188 \f
189 static struct hmapx_node *
190 session_lookup_dataset__ (const struct session *s_, const char *name)
191 {
192   struct session *s = CONST_CAST (struct session *, s_);
193   struct hmapx_node *node;
194   struct dataset *ds;
195
196   HMAPX_FOR_EACH_WITH_HASH (ds, node, hash_case_string (name, 0), &s->datasets)
197     if (!strcasecmp (dataset_name (ds), name))
198       return node;
199
200   return NULL;
201 }