-
Notifications
You must be signed in to change notification settings - Fork 6
/
Value.hpp
210 lines (192 loc) · 6.05 KB
/
Value.hpp
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
/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2023 51 Degrees Mobile Experts Limited, Davidson House,
* Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
*
* This Original Work is licensed under the European Union Public Licence
* (EUPL) v.1.2 and is subject to its terms as set out below.
*
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
*
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
*
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */
#ifndef FIFTYONE_DEGREES_VALUE_HPP
#define FIFTYONE_DEGREES_VALUE_HPP
#include "Exceptions.hpp"
#include "results.h"
namespace FiftyoneDegrees {
namespace Common {
/**
* Encapsulates a value returned an instance of ResultsBase for a
* specified property. An instance contains either the value, or the
* reason which there is no value.
*
* Before retrieving the value itself, its presence should first be
* checked using the hasValue() method. The typed value can be
* returned either using the getValue() method, or more simply, by
* dereferencing (similarly to an iterator). If there is no value, then
* an exception will be thrown.
*
* ## Usage Example
* ```
* using namespace FiftyoneDegrees::Common;
* Value<string> value;
*
* // Check that there is a valid value
* if (value.hasValue()) {
* // Get the value
* string stringValue = *value;
* // Do something with the value
* // ...
* }
* else {
* // Get the reason for the value being invalid
* string message = value.getNoValueMessage();
* // Do something with the message
* // ...
* }
*
* // Or just try getting the value and catch the exception. Note that
* // this is not the recommended method.
* try {
* string stringValue = *value;
* }
* catch (exception e) {
* const char *message = e.what();
* }
* ```
*
* @tparam T the type of the value e.g. string
*/
template <class T> class Value {
public:
/**
* @name Constructors
* @{
*/
/**
* Default constructor.
*/
Value() {
this->value = T();
this->hasValueInternal = false;
}
/**
* @}
* @name Value Methods
* @{
*/
/**
* Indicates whether or not a valid value has been returned by the
* ResultsBase instance.
* @return true if there is a valid value
*/
bool hasValue() {
return hasValueInternal;
}
/**
* Indicates the reason why valid values are not available. This
* can be called if hasValue() returns false. For a more detailed
* message, call getNoValueMessage().
* @return enum indicating the reason for no valid values
*/
fiftyoneDegreesResultsNoValueReason getNoValueReason() {
return noValueReason;
}
/**
* Gets a message explaining why there is no value. Calling this if
* hasValue() returned true will result in undefined behavior.
* @return message explaining the reason for the missing value
*/
const char* getNoValueMessage() {
return noValueMessage;
}
/**
* Gets the value contained in the Value instance. If there is no
* valid value, then an exception will be thrown. To prevent an
* exception, the hasValue() method should be checked first.
* @return value
*/
T getValue() {
if (hasValueInternal) {
return value;
}
else {
switch (noValueReason) {
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_INVALID_PROPERTY:
if (noValueMessage != nullptr) {
throw InvalidPropertyException(noValueMessage);
}
else {
throw InvalidPropertyException();
}
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_TOO_MANY_VALUES:
throw TooManyValuesException();
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_DIFFERENCE:
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_NO_RESULT_FOR_PROPERTY:
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_NO_RESULTS:
case FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_UNKNOWN:
throw NoValuesAvailableException(noValueMessage);
default:
throw NoValuesAvailableException();
}
}
}
/**
* Set the value to be contained in the Value instance.
* @param targetValue the value to set
*/
void setValue(T targetValue) {
this->value = targetValue;
hasValueInternal = true;
}
/**
* Set the reason there is no value available. This will be used
* if an exception is thrown by the setValue method.
* @param reason the reason enum indicating why the value is
* missing
* @param message the message containing a fuller description on
* why the value is missing
*/
void setNoValueReason(
fiftyoneDegreesResultsNoValueReason reason,
const char *message) {
this->noValueReason = reason;
this->noValueMessage = message;
}
/**
* @}
* @name Operators
* @{
*/
/**
* Gets the value contained in the Value instance. If there is no
* valid value, then an exception will be thrown. To prevent an
* exception, the hasValue() method should be checked first.
* @return value
*/
T operator*() {
return getValue();
}
/**
* @}
*/
private:
bool hasValueInternal;
T value;
const char *noValueMessage = nullptr;
fiftyoneDegreesResultsNoValueReason noValueReason =
FIFTYONE_DEGREES_RESULTS_NO_VALUE_REASON_UNKNOWN;
};
}
}
#endif