Fix mysterious crashes such as #7049
[ardour.git] / libs / pbd / pbd / configuration_variable.h
1 /*
2     Copyright (C) 2000-2007 Paul Davis
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 2 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, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __libpbd_configuration_variable_h__
21 #define __libpbd_configuration_variable_h__
22
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26
27 #include "pbd/xml++.h"
28 #include "pbd/convert.h"
29 #include "pbd/libpbd_visibility.h"
30
31 namespace PBD {
32
33 class LIBPBD_API ConfigVariableBase {
34   public:
35
36         ConfigVariableBase (std::string str) : _name (str) {}
37         virtual ~ConfigVariableBase() {}
38
39         std::string name () const { return _name; }
40         void add_to_node (XMLNode&);
41         bool set_from_node (XMLNode const &);
42
43         virtual std::string get_as_string () const = 0;
44         virtual void set_from_string (std::string const &) = 0;
45
46   protected:
47         std::string _name;
48
49         void notify ();
50         void miss ();
51 };
52
53 template<class T>
54 class /*LIBPBD_API*/ ConfigVariable : public ConfigVariableBase
55 {
56   public:
57
58         ConfigVariable (std::string str) : ConfigVariableBase (str) {}
59         ConfigVariable (std::string str, T val) : ConfigVariableBase (str), value (val) {}
60
61         T get() const {
62                 return value;
63         }
64
65         std::string get_as_string () const {
66                 std::ostringstream ss;
67                 ss << value;
68                 return ss.str ();
69         }
70
71         virtual bool set (T val) {
72                 if (val == value) {
73                         miss ();
74                         return false;
75                 }
76                 value = val;
77                 notify ();
78                 return true;
79         }
80
81         virtual void set_from_string (std::string const & s) {
82                 std::stringstream ss;
83                 ss << s;
84                 ss >> value;
85         }
86
87   protected:
88         virtual T get_for_save() { return value; }
89         T value;
90 };
91
92 /** Specialisation of ConfigVariable for std::string to cope with whitespace properly */
93 template<>
94 class /*LIBPBD_API*/ ConfigVariable<std::string> : public ConfigVariableBase
95 {
96   public:
97
98         ConfigVariable (std::string str) : ConfigVariableBase (str) {}
99         ConfigVariable (std::string str, std::string val) : ConfigVariableBase (str), value (val) {}
100
101         std::string get() const {
102                 return value;
103         }
104
105         std::string get_as_string () const {
106                 return value;
107         }
108
109         virtual bool set (std::string val) {
110                 if (val == value) {
111                         miss ();
112                         return false;
113                 }
114                 value = val;
115                 notify ();
116                 return true;
117         }
118
119         virtual void set_from_string (std::string const & s) {
120                 value = s;
121         }
122
123   protected:
124         virtual std::string get_for_save() { return value; }
125         std::string value;
126 };
127
128 template<>
129 class /*LIBPBD_API*/ ConfigVariable<bool> : public ConfigVariableBase
130 {
131   public:
132
133         ConfigVariable (std::string str) : ConfigVariableBase (str), value (false) {}
134         ConfigVariable (std::string str, bool val) : ConfigVariableBase (str), value (val) {}
135
136         bool get() const {
137                 return value;
138         }
139
140         std::string get_as_string () const {
141                 std::ostringstream ss;
142                 ss << value;
143                 return ss.str ();
144         }
145
146         virtual bool set (bool val) {
147                 if (val == value) {
148                         miss ();
149                         return false;
150                 }
151                 value = val;
152                 notify ();
153                 return true;
154         }
155
156         void set_from_string (std::string const & s) {
157                 value = PBD::string_is_affirmative (s);
158         }
159
160   protected:
161         virtual bool get_for_save() { return value; }
162         bool value;
163 };
164
165 template<class T>
166 class /*LIBPBD_API*/ ConfigVariableWithMutation : public ConfigVariable<T>
167 {
168   public:
169         ConfigVariableWithMutation (std::string name, T val, T (*m)(T))
170                 : ConfigVariable<T> (name, m (val)), unmutated_value (val), mutator (m) {}
171
172         bool set (T val) {
173                 if (unmutated_value != val) {
174                         unmutated_value = val;
175                         return ConfigVariable<T>::set (mutator (val));
176                 }
177                 return false;
178         }
179
180         void set_from_string (std::string const & s) {
181                 T v;
182                 std::stringstream ss;
183                 ss << s;
184                 ss >> v;
185                 set (v);
186         }
187
188   protected:
189         virtual T get_for_save() { return unmutated_value; }
190         T unmutated_value;
191         T (*mutator)(T);
192 };
193
194 template<>
195 class /*LIBPBD_API*/ ConfigVariableWithMutation<std::string> : public ConfigVariable<std::string>
196 {
197   public:
198         ConfigVariableWithMutation (std::string name, std::string val, std::string (*m)(std::string))
199                 : ConfigVariable<std::string> (name, val), mutator (m) {}
200
201         bool set (std::string val) {
202                 if (unmutated_value != val) {
203                         unmutated_value = val;
204                         return ConfigVariable<std::string>::set (mutator (val));
205                 }
206                 return false;
207         }
208
209         void set_from_string (std::string const & s) {
210                 set (s);
211         }
212
213   protected:
214         virtual std::string get_for_save() { return unmutated_value; }
215         std::string unmutated_value;
216         std::string (*mutator)(std::string);
217 };
218
219 }
220
221 #endif /* __libpbd_configuration_variable_h__ */