/
variable.h
311 lines (255 loc) · 8.23 KB
/
variable.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*
* The Doomsday Engine Project -- libcore
*
* Copyright © 2009-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @par License
* LGPL: http://www.gnu.org/licenses/lgpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
*/
#ifndef LIBCORE_VARIABLE_H
#define LIBCORE_VARIABLE_H
#include "../ISerializable"
#include "../String"
#include "../Audience"
#include "../Deletable"
#include "../CString"
namespace de {
class Value;
class ArrayValue;
class Record;
/**
* Stores a value and name identifier. Variables are typically stored in a Record.
* A variable's behavior is defined by its mode flags.
*
* @ingroup data
*/
class DE_PUBLIC Variable : public Deletable, public ISerializable
{
public:
/// There was an attempt to change the value of a read-only variable. @ingroup errors
DE_ERROR(ReadOnlyError);
/// An invalid value type was used. The mode flags denied using a value of the
/// given type with the variable. @ingroup errors
DE_ERROR(InvalidError);
/// Variable name contains invalid characters. @ingroup errors
DE_ERROR(NameError);
/// Value could not be converted to the attempted type. @ingroup errors
DE_ERROR(TypeError);
/** @name Mode Flags */
//@{
enum Flag
{
/// Variable's value cannot change.
ReadOnly = 0x1,
/// Variable cannot be serialized.
NoSerialize = 0x2,
/// NoneValue allowed as value.
AllowNone = 0x4,
/// NumberValue allowed as value.
AllowNumber = 0x8,
/// TextValue allowed as value.
AllowText = 0x10,
/// ArrayValue allowed as value.
AllowArray = 0x20,
/// DictionaryValue allowed as value.
AllowDictionary = 0x40,
/// BlockValue allowed as value.
AllowBlock = 0x80,
/// FunctionValue allowed as value.
AllowFunction = 0x100,
/// RecordValue allowed as value.
AllowRecord = 0x200,
/// RefValue allowed as value.
AllowRef = 0x400,
/// TimeValue allowed as value.
AllowTime = 0x800,
/// Automatically set when the variable's value is changed.
ValueHasChanged = 0x10000000,
/// The default mode allows reading and writing all types of values,
/// including NoneValue.
DefaultMode = AllowNone | AllowNumber | AllowText | AllowArray |
AllowDictionary | AllowBlock | AllowFunction | AllowRecord |
AllowRef | AllowTime
};
//@}
public:
/**
* Constructs a new variable.
*
* @param name Name for the variable. Any periods (.) are not allowed.
* @param initial Initial value. Variable gets ownership. If no value is given here,
* a NoneValue will be created for the variable.
* @param varMode Mode flags.
*/
Variable(const String &name = {}, Value *initial = nullptr,
Flags const &varMode = DefaultMode);
/**
* Constructs a copy of another variable.
*
* @param other Variable to copy.
*/
Variable(Variable const &other);
virtual ~Variable();
/**
* Returns the name of the variable.
*/
String const &name() const;
/**
* Sets the value of the variable.
*
* @param v New value. Variable gets ownership. Cannot be NULL.
*/
Variable &set(Value *v);
/**
* Sets the value of the variable.
*
* @param v New value. Variable gets ownership. Cannot be NULL.
*/
Variable &operator=(Value *v);
/**
* Sets the value of the variable.
*
* @param textValue Text string. A new TextValue is created.
*/
Variable &operator=(String const &textValue);
/**
* Sets the value of the variable.
*
* @param v New value. Variable takes a copy of this.
*/
Variable &set(Value const &v);
/**
* Returns the value of the variable (non-modifiable).
*/
Value const &value() const;
/**
* Returns the value of the variable.
*/
Value &value();
Value *valuePtr();
Value const *valuePtr() const;
bool operator==(const String &text) const;
/**
* Returns the value of the variable.
*/
template <typename Type>
Type &value() {
Type *v = dynamic_cast<Type *>(valuePtr());
if (!v) {
/// @throw TypeError Casting to Type failed.
throw TypeError("Variable::value",
String("Illegal type conversion to ") + typeid(Type).name());
}
return *v;
}
/**
* Returns the value of the variable.
*/
template <typename Type>
Type const &value() const {
Type const *v = dynamic_cast<Type const *>(valuePtr());
if (!v) {
/// @throw TypeError Casting to Type failed.
throw TypeError("Variable::value",
String("Illegal type conversion to ") + typeid(Type).name());
}
return *v;
}
/**
* Returns the Record that the variable references. If the variable does
* not have a RecordValue, an exception is thrown.
*
* @return Referenced Record.
*/
Record const &valueAsRecord() const;
Record &valueAsRecord();
/**
* Returns the value of the variable as an ArrayValue.
*/
ArrayValue const &array() const;
ArrayValue &array();
operator Record & ();
operator Record const & () const;
// Automatic conversion to native primitive types.
operator String () const;
operator ddouble () const;
/**
* Returns the current mode flags of the variable.
*/
Flags flags() const;
/**
* Sets the mode flags of the variable.
*
* @param flags New mode flags.
* @param operation What to do with @a flags.
*/
void setFlags(Flags const &flags, FlagOpArg operation = ReplaceFlags);
/**
* Makes the variable read-only.
*
* @return Reference to this variable.
*/
Variable &setReadOnly();
/**
* Checks that a value is valid, checking what is allowed in the mode
* flags.
*
* @param v Value to check.
*
* @return @c true, if the value is valid. @c false otherwise.
*/
bool isValid(Value const &v) const;
/**
* Verifies that a value is valid, checking against what is allowed in the
* mode flags. If not, an exception is thrown.
*
* @param v Value to test.
*/
void verifyValid(Value const &v) const;
/**
* Verifies that the variable can be assigned a new value.
*
* @param attemptedNewValue The new value that is being assigned.
*/
void verifyWritable(Value const &attemptedNewValue);
/**
* Verifies that a string is a valid name for the variable. If not,
* an exception is thrown.
*
* @param s Name to test.
*/
static void verifyName(String const &s);
// Implements ISerializable.
void operator >> (Writer &to) const;
void operator << (Reader &from);
public:
/**
* The variable is about to be deleted.
*
* @param variable Variable.
*/
DE_DEFINE_AUDIENCE2(Deletion, void variableBeingDeleted(Variable &variable))
/**
* The value of the variable has changed.
*
* @param variable Variable.
* @param newValue New value of the variable.
*/
DE_DEFINE_AUDIENCE2(Change, void variableValueChanged(Variable &variable, Value const &newValue))
DE_DEFINE_AUDIENCE2(ChangeFrom, void variableValueChangedFrom(Variable &variable, Value const &oldValue,
Value const &newValue))
private:
DE_PRIVATE(d)
};
} // namespace de
#endif /* LIBCORE_VARIABLE_H */