normativeTypesCPP 6.0.2
validator.h
Go to the documentation of this file.
1/* validator.h */
2/*
3 * Copyright information and license terms for this software can be
4 * found in the file LICENSE that is included with the distribution
5 */
6#ifndef VALIDATOR_H
7#define VALIDATOR_H
8
9#include <string>
10#include <set>
11#include <algorithm>
12
13#include <pv/pvIntrospect.h>
14
15namespace epics { namespace nt {
16
23struct Result {
24 struct Error {
25 std::string path;
31
32 Error(std::string const & path, Type type)
33 : path(path), type(type) {}
34
35 bool operator==(const Error& other) const {
36 return type == other.type && path == other.path;
37 }
38
39 std::ostream& dump(std::ostream& os) const {
40 os << "Error(path=" << (path.empty() ? "<root>" : path) << ": ";
41
42 switch(type) {
43 case MissingField: os << "missing"; break;
44 case IncorrectType: os << "incorrect type"; break;
45 case IncorrectId: os << "incorrect ID"; break;
46 }
47 os << ")";
48 return os;
49 }
50 };
51
52 epics::pvData::FieldConstPtr field;
53 std::string path;
54 std::vector<Error> errors;
55
60
61 Result(const epics::pvData::FieldConstPtr& field, const std::string& path = std::string())
62 : field(field), path(path), errors(), result(Pass) {}
63
64 Result() {}
65
66 Result& operator|=(const Result& other) {
67 result = std::max(result, other.result);
68 errors.insert(errors.end(), other.errors.begin(), other.errors.end());
69 return *this;
70 }
71
77 inline bool valid(void) const {
78 return result == Pass;
79 }
80
88 template<typename T>
89 Result& is(void) {
90 if (!dynamic_cast<T const *>(field.get())) {
91 result = Fail;
93 }
94 return *this;
95 }
96
107 template<typename T>
108 Result& is(const std::string& id) {
109 T const *s = dynamic_cast<T const *>(field.get());
110 if (!s) {
111 result = Fail;
113 } else if (s->getID() != id) {
114 result = Fail;
115 errors.push_back(Error(path, Error::IncorrectId));
116 }
117 return *this;
118 }
119
131 template<Result& (*fn)(Result&)>
132 Result& has(const std::string& name) {
133 return has<epics::pvData::Field>(name, false, fn);
134 }
135
145 template<Result& (*fn)(Result&)>
146 Result& maybeHas(const std::string& name) {
147 return has<epics::pvData::Field>(name, true, fn);
148 }
149
164 template<Result& (*fn)(Result&), typename T>
165 Result& has(const std::string& name) {
166 return has<T>(name, false, fn);
167 }
168
181 template<Result& (*fn)(Result&), typename T>
182 Result& maybeHas(const std::string& name) {
183 return has<T>(name, true, fn);
184 }
185
199 template<typename T>
200 Result& has(const std::string& name) {
201 return has<T>(name, false, NULL);
202 }
203
215 template<typename T>
216 Result& maybeHas(const std::string& name) {
217 return has<T>(name, true, NULL);
218 }
219
220 std::ostream& dump(std::ostream& os) const {
221 os << "Result(valid=" << (result == Pass) << ", errors=[ ";
222
223 std::vector<Error>::const_iterator it;
224 for (it = errors.begin(); it != errors.end(); ++it) {
225 (*it).dump(os);
226 os << " ";
227 }
228 os << "])";
229 return os;
230 }
231
232private:
233 template<typename T>
234 Result& has(const std::string& name, bool optional, Result& (*check)(Result&) = NULL) {
235 epics::pvData::FieldConstPtr subField;
236
237 switch(field->getType()) {
238 case epics::pvData::structure:
239 subField = static_cast<epics::pvData::Structure const *>(field.get())->getField(name);
240 break;
241 case epics::pvData::structureArray:
242 subField = static_cast<epics::pvData::StructureArray const *>(field.get())->getStructure()->getField(name);
243 break;
244 case epics::pvData::union_:
245 subField = static_cast<epics::pvData::Union const *>(field.get())->getField(name);
246 break;
247 case epics::pvData::unionArray:
248 subField = static_cast<epics::pvData::UnionArray const *>(field.get())->getUnion()->getField(name);
249 break;
250 default:
251 // Expected a structure-like Field
252 result = Fail;
253 errors.push_back(Error(path, Error::IncorrectType));
254 return *this;
255 }
256
257 std::string subFieldPath(path.empty() ? name : path + "." + name);
258
259 if (!subField) {
260 if (!optional) {
261 result = Fail;
262 errors.push_back(Error(subFieldPath, Error::MissingField));
263 }
264 } else if (!dynamic_cast<T const *>(subField.get())) {
265 result = Fail;
266 errors.push_back(Error(subFieldPath, Error::IncorrectType));
267 } else if (check) {
268 Result r(subField, subFieldPath);
269 *this |= check(r);
270 }
271
272 return *this;
273 }
274};
275}}
276
277#endif
std::ostream & dump(std::ostream &os) const
Definition validator.h:39
Error(std::string const &path, Type type)
Definition validator.h:32
bool operator==(const Error &other) const
Definition validator.h:35
enum epics::nt::Result::Error::Type type
Validation methods for NT types.
Definition validator.h:23
Result & is(void)
Definition validator.h:89
bool valid(void) const
Definition validator.h:77
Result(const epics::pvData::FieldConstPtr &field, const std::string &path=std::string())
Definition validator.h:61
Result & maybeHas(const std::string &name)
Definition validator.h:182
Result & is(const std::string &id)
Definition validator.h:108
std::string path
Definition validator.h:53
Result & operator|=(const Result &other)
Definition validator.h:66
Result & has(const std::string &name)
Definition validator.h:132
std::vector< Error > errors
Definition validator.h:54
epics::pvData::FieldConstPtr field
Definition validator.h:52
enum epics::nt::Result::result_t result
std::ostream & dump(std::ostream &os) const
Definition validator.h:220
Result & maybeHas(const std::string &name)
Definition validator.h:146
Result & has(const std::string &name)
Definition validator.h:165