5
5
#include < regex>
6
6
#include < stdexcept>
7
7
#include < string>
8
- #include < typeinfo>
9
8
#include < typeindex>
9
+ #include < typeinfo>
10
10
#include < unordered_map>
11
11
12
12
#if !defined(_WIN32)
27
27
28
28
#endif
29
29
30
+ #include " google/protobuf/message.h"
30
31
#include " google/protobuf/stubs/strutil.h" // for UTF8Len
31
32
32
33
namespace pgv {
@@ -42,68 +43,78 @@ class UnimplementedException : public std::runtime_error {
42
43
using ValidationMsg = std::string;
43
44
44
45
class BaseValidator {
46
+ public:
47
+ /* *
48
+ * Validate/check a generic message object with a registered validator for the concrete message
49
+ * type.
50
+ * @param m supplies the message to check.
51
+ * @param err supplies the place to return error information.
52
+ * @return true if the validation passes OR there is no registered validator for the concrete
53
+ * message type. false is returned if validation explicitly fails.
54
+ */
55
+ static bool AbstractCheckMessage (const google::protobuf::Message& m, ValidationMsg* err) {
56
+ // Polymorphic lookup is used to see if there is a matching concrete validator. If so, call it.
57
+ // Otherwise return success.
58
+ auto it = abstractValidators ().find (std::type_index (typeid (m)));
59
+ if (it == abstractValidators ().end ()) {
60
+ return true ;
61
+ }
62
+ return it->second (m, err);
63
+ }
64
+
45
65
protected:
46
- static std::unordered_map<std::type_index, BaseValidator*>& validators () {
47
- static auto * validator_map = new std::unordered_map<std::type_index, BaseValidator*>();
66
+ // Used to implement AbstractCheckMessage() above. Every message that is linked into the binary
67
+ // will register itself by type_index, allowing for polymorphic lookup later.
68
+ static std::unordered_map<std::type_index,
69
+ std::function<bool (const google::protobuf::Message&, ValidationMsg*)>>&
70
+ abstractValidators () {
71
+ static auto * validator_map = new std::unordered_map<
72
+ std::type_index, std::function<bool (const google::protobuf::Message&, ValidationMsg*)>>();
48
73
return *validator_map;
49
74
}
50
75
};
51
76
52
- template <typename T>
53
- class Validator : public BaseValidator {
77
+ template <typename T> class Validator : public BaseValidator {
54
78
public:
55
- Validator (std::function<bool (const T&, ValidationMsg*)> check) : check_(check)
56
- {
57
- validators ()[std::type_index (typeid (T))] = this ;
58
- }
59
-
60
- static bool CheckMessage (const T& m, ValidationMsg* err)
61
- {
62
- // Run typeid() on the variable vs. the type to allow polymorphic lookup of the validator.
63
- auto val = static_cast <Validator<T>*>(validators ()[std::type_index (typeid (m))]);
64
- if (val) {
65
- return val->check_ (m, err);
66
- }
67
- return true ;
79
+ Validator (std::function<bool (const T&, ValidationMsg*)> check) : check_(check) {
80
+ abstractValidators ()[std::type_index (typeid (T))] = [this ](const google::protobuf::Message& m,
81
+ ValidationMsg* err) -> bool {
82
+ return check_ (dynamic_cast <const T&>(m), err);
83
+ };
68
84
}
69
85
70
86
private:
71
87
std::function<bool (const T&, ValidationMsg*)> check_;
72
88
};
73
89
74
- static inline std::string String (const ValidationMsg& msg)
75
- {
76
- return std::string (msg);
77
- }
90
+ static inline std::string String (const ValidationMsg& msg) { return std::string (msg); }
78
91
79
- static inline bool IsPrefix (const string& maybe_prefix, const string& search_in)
80
- {
92
+ static inline bool IsPrefix (const string& maybe_prefix, const string& search_in) {
81
93
return search_in.compare (0 , maybe_prefix.size (), maybe_prefix) == 0 ;
82
94
}
83
95
84
- static inline bool IsSuffix (const string& maybe_suffix, const string& search_in)
85
- {
86
- return maybe_suffix.size () <= search_in.size () && search_in.compare (search_in.size () - maybe_suffix.size (), maybe_suffix.size (), maybe_suffix) == 0 ;
96
+ static inline bool IsSuffix (const string& maybe_suffix, const string& search_in) {
97
+ return maybe_suffix.size () <= search_in.size () &&
98
+ search_in.compare (search_in.size () - maybe_suffix.size (), maybe_suffix.size (),
99
+ maybe_suffix) == 0 ;
87
100
}
88
101
89
- static inline bool Contains (const string& search_in, const string& to_find)
90
- {
102
+ static inline bool Contains (const string& search_in, const string& to_find) {
91
103
return search_in.find (to_find) != string::npos;
92
104
}
93
105
94
- static inline bool NotContains (const string& search_in, const string& to_find)
95
- {
106
+ static inline bool NotContains (const string& search_in, const string& to_find) {
96
107
return !Contains (search_in, to_find);
97
108
}
98
109
99
110
static inline bool IsIpv4 (const string& to_validate) {
100
- struct sockaddr_in sa;
101
- return !(inet_pton (AF_INET, to_validate.c_str (), &sa.sin_addr ) < 1 );
111
+ struct sockaddr_in sa;
112
+ return !(inet_pton (AF_INET, to_validate.c_str (), &sa.sin_addr ) < 1 );
102
113
}
103
114
104
115
static inline bool IsIpv6 (const string& to_validate) {
105
116
struct sockaddr_in6 sa_six;
106
- return !(inet_pton (AF_INET6, to_validate.c_str (), &sa_six.sin6_addr ) < 1 );
117
+ return !(inet_pton (AF_INET6, to_validate.c_str (), &sa_six.sin6_addr ) < 1 );
107
118
}
108
119
109
120
static inline bool IsIp (const string& to_validate) {
@@ -119,7 +130,7 @@ static inline bool IsHostname(const string& to_validate) {
119
130
const auto iter_end = std::sregex_token_iterator ();
120
131
auto iter = std::sregex_token_iterator (to_validate.begin (), to_validate.end (), dot_regex, -1 );
121
132
for (; iter != iter_end; ++iter) {
122
- const std::string & part = *iter;
133
+ const std::string& part = *iter;
123
134
if (part.empty () || part.length () > 63 ) {
124
135
return false ;
125
136
}
@@ -129,8 +140,9 @@ static inline bool IsHostname(const string& to_validate) {
129
140
if (part.at (part.length () - 1 ) == ' -' ) {
130
141
return false ;
131
142
}
132
- for (const auto &character : part) {
133
- if ((character < ' A' || character > ' Z' ) && (character < ' a' || character > ' z' ) && (character < ' 0' || character > ' 9' ) && character != ' -' ) {
143
+ for (const auto & character : part) {
144
+ if ((character < ' A' || character > ' Z' ) && (character < ' a' || character > ' z' ) &&
145
+ (character < ' 0' || character > ' 9' ) && character != ' -' ) {
134
146
return false ;
135
147
}
136
148
}
@@ -140,7 +152,7 @@ static inline bool IsHostname(const string& to_validate) {
140
152
}
141
153
142
154
static inline size_t Utf8Len (const string& narrow_string) {
143
- const char * str_char = narrow_string.c_str ();
155
+ const char * str_char = narrow_string.c_str ();
144
156
ptrdiff_t byte_len = narrow_string.length ();
145
157
size_t unicode_len = 0 ;
146
158
int char_len = 1 ;
0 commit comments