1 | #pragma once |
2 | |
3 | /** |
4 | * This file implements some functions that are dependent on Field type. |
5 | * Unlike SettingsCollection.h, we only have to include it once for each |
6 | * instantiation of SettingsCollection<>. |
7 | */ |
8 | |
9 | #include <Common/SettingsChanges.h> |
10 | |
11 | namespace DB |
12 | { |
13 | namespace details |
14 | { |
15 | struct SettingsCollectionUtils |
16 | { |
17 | static void serializeName(const StringRef & name, WriteBuffer & buf); |
18 | static String deserializeName(ReadBuffer & buf); |
19 | static void serializeFlag(bool flag, WriteBuffer & buf); |
20 | static bool deserializeFlag(ReadBuffer & buf); |
21 | static void skipValue(ReadBuffer & buf); |
22 | static void warningNameNotFound(const StringRef & name); |
23 | [[noreturn]] static void throwNameNotFound(const StringRef & name); |
24 | }; |
25 | } |
26 | |
27 | |
28 | template <class Derived> |
29 | size_t SettingsCollection<Derived>::MemberInfos::findIndex(const StringRef & name) const |
30 | { |
31 | auto it = by_name_map.find(name); |
32 | if (it == by_name_map.end()) |
33 | return static_cast<size_t>(-1); // npos |
34 | return it->second; |
35 | } |
36 | |
37 | |
38 | template <class Derived> |
39 | size_t SettingsCollection<Derived>::MemberInfos::findIndexStrict(const StringRef & name) const |
40 | { |
41 | auto it = by_name_map.find(name); |
42 | if (it == by_name_map.end()) |
43 | details::SettingsCollectionUtils::throwNameNotFound(name); |
44 | return it->second; |
45 | } |
46 | |
47 | |
48 | template <class Derived> |
49 | const typename SettingsCollection<Derived>::MemberInfo * SettingsCollection<Derived>::MemberInfos::find(const StringRef & name) const |
50 | { |
51 | auto it = by_name_map.find(name); |
52 | if (it == by_name_map.end()) |
53 | return nullptr; |
54 | else |
55 | return &infos[it->second]; |
56 | } |
57 | |
58 | |
59 | template <class Derived> |
60 | const typename SettingsCollection<Derived>::MemberInfo & SettingsCollection<Derived>::MemberInfos::findStrict(const StringRef & name) const |
61 | { |
62 | return infos[findIndexStrict(name)]; |
63 | } |
64 | |
65 | |
66 | template <class Derived> |
67 | void SettingsCollection<Derived>::MemberInfos::add(MemberInfo && member) |
68 | { |
69 | size_t index = infos.size(); |
70 | infos.emplace_back(member); |
71 | by_name_map.emplace(infos.back().name, index); |
72 | } |
73 | |
74 | |
75 | template <class Derived> |
76 | const typename SettingsCollection<Derived>::MemberInfos & |
77 | SettingsCollection<Derived>::members() |
78 | { |
79 | static const MemberInfos the_instance; |
80 | return the_instance; |
81 | } |
82 | |
83 | |
84 | template <class Derived> |
85 | Field SettingsCollection<Derived>::const_reference::getValue() const |
86 | { |
87 | return member->get_field(*collection); |
88 | } |
89 | |
90 | |
91 | template <class Derived> |
92 | Field SettingsCollection<Derived>::valueToCorrespondingType(size_t index, const Field & value) |
93 | { |
94 | return members()[index].value_to_corresponding_type(value); |
95 | } |
96 | |
97 | |
98 | template <class Derived> |
99 | Field SettingsCollection<Derived>::valueToCorrespondingType(const StringRef & name, const Field & value) |
100 | { |
101 | return members().findStrict(name).value_to_corresponding_type(value); |
102 | } |
103 | |
104 | |
105 | template <class Derived> |
106 | typename SettingsCollection<Derived>::iterator SettingsCollection<Derived>::find(const StringRef & name) |
107 | { |
108 | const auto * member = members().find(name); |
109 | if (member) |
110 | return iterator(castToDerived(), member); |
111 | return end(); |
112 | } |
113 | |
114 | |
115 | template <class Derived> |
116 | typename SettingsCollection<Derived>::const_iterator SettingsCollection<Derived>::find(const StringRef & name) const |
117 | { |
118 | const auto * member = members().find(name); |
119 | if (member) |
120 | return const_iterator(castToDerived(), member); |
121 | return end(); |
122 | } |
123 | |
124 | |
125 | template <class Derived> |
126 | typename SettingsCollection<Derived>::iterator SettingsCollection<Derived>::findStrict(const StringRef & name) |
127 | { |
128 | return iterator(castToDerived(), &members().findStrict(name)); |
129 | } |
130 | |
131 | |
132 | template <class Derived> |
133 | typename SettingsCollection<Derived>::const_iterator SettingsCollection<Derived>::findStrict(const StringRef & name) const |
134 | { |
135 | return const_iterator(castToDerived(), &members().findStrict(name)); |
136 | } |
137 | |
138 | |
139 | template <class Derived> |
140 | Field SettingsCollection<Derived>::get(size_t index) const |
141 | { |
142 | return (*this)[index].getValue(); |
143 | } |
144 | |
145 | |
146 | template <class Derived> |
147 | Field SettingsCollection<Derived>::get(const StringRef & name) const |
148 | { |
149 | return (*this)[name].getValue(); |
150 | } |
151 | |
152 | |
153 | template <class Derived> |
154 | bool SettingsCollection<Derived>::tryGet(const StringRef & name, Field & value) const |
155 | { |
156 | auto it = find(name); |
157 | if (it == end()) |
158 | return false; |
159 | value = it->getValue(); |
160 | return true; |
161 | } |
162 | |
163 | |
164 | template <class Derived> |
165 | bool SettingsCollection<Derived>::tryGet(const StringRef & name, String & value) const |
166 | { |
167 | auto it = find(name); |
168 | if (it == end()) |
169 | return false; |
170 | value = it->getValueAsString(); |
171 | return true; |
172 | } |
173 | |
174 | |
175 | template <class Derived> |
176 | bool SettingsCollection<Derived>::operator ==(const Derived & rhs) const |
177 | { |
178 | const auto & the_members = members(); |
179 | for (size_t i = 0; i != the_members.size(); ++i) |
180 | { |
181 | const auto & member = the_members[i]; |
182 | bool left_changed = member.is_changed(castToDerived()); |
183 | bool right_changed = member.is_changed(rhs); |
184 | if (left_changed || right_changed) |
185 | { |
186 | if (left_changed != right_changed) |
187 | return false; |
188 | if (member.get_field(castToDerived()) != member.get_field(rhs)) |
189 | return false; |
190 | } |
191 | } |
192 | return true; |
193 | } |
194 | |
195 | |
196 | template <class Derived> |
197 | SettingsChanges SettingsCollection<Derived>::changes() const |
198 | { |
199 | SettingsChanges found_changes; |
200 | const auto & the_members = members(); |
201 | for (size_t i = 0; i != the_members.size(); ++i) |
202 | { |
203 | const auto & member = the_members[i]; |
204 | if (member.is_changed(castToDerived())) |
205 | found_changes.push_back({member.name.toString(), member.get_field(castToDerived())}); |
206 | } |
207 | return found_changes; |
208 | } |
209 | |
210 | |
211 | template <class Derived> |
212 | void SettingsCollection<Derived>::applyChange(const SettingChange & change) |
213 | { |
214 | set(change.name, change.value); |
215 | } |
216 | |
217 | |
218 | template <class Derived> |
219 | void SettingsCollection<Derived>::applyChanges(const SettingsChanges & changes) |
220 | { |
221 | for (const SettingChange & change : changes) |
222 | applyChange(change); |
223 | } |
224 | |
225 | |
226 | template <class Derived> |
227 | void SettingsCollection<Derived>::copyChangesFrom(const Derived & src) |
228 | { |
229 | const auto & the_members = members(); |
230 | for (size_t i = 0; i != the_members.size(); ++i) |
231 | { |
232 | const auto & member = the_members[i]; |
233 | if (member.is_changed(src)) |
234 | member.set_field(castToDerived(), member.get_field(src)); |
235 | } |
236 | } |
237 | |
238 | |
239 | template <class Derived> |
240 | void SettingsCollection<Derived>::copyChangesTo(Derived & dest) const |
241 | { |
242 | dest.copyChangesFrom(castToDerived()); |
243 | } |
244 | |
245 | |
246 | template <class Derived> |
247 | void SettingsCollection<Derived>::serialize(WriteBuffer & buf, SettingsBinaryFormat format) const |
248 | { |
249 | const auto & the_members = members(); |
250 | for (size_t i = 0; i != the_members.size(); ++i) |
251 | { |
252 | const auto & member = the_members[i]; |
253 | if (member.is_changed(castToDerived())) |
254 | { |
255 | details::SettingsCollectionUtils::serializeName(member.name, buf); |
256 | if (format >= SettingsBinaryFormat::STRINGS) |
257 | details::SettingsCollectionUtils::serializeFlag(member.is_important, buf); |
258 | member.serialize(castToDerived(), buf, format); |
259 | } |
260 | } |
261 | details::SettingsCollectionUtils::serializeName(StringRef{} /* empty string is a marker of the end of settings */, buf); |
262 | } |
263 | |
264 | |
265 | template <class Derived> |
266 | void SettingsCollection<Derived>::deserialize(ReadBuffer & buf, SettingsBinaryFormat format) |
267 | { |
268 | const auto & the_members = members(); |
269 | while (true) |
270 | { |
271 | String name = details::SettingsCollectionUtils::deserializeName(buf); |
272 | if (name.empty() /* empty string is a marker of the end of settings */) |
273 | break; |
274 | auto * member = the_members.find(name); |
275 | bool is_important = (format >= SettingsBinaryFormat::STRINGS) ? details::SettingsCollectionUtils::deserializeFlag(buf) : true; |
276 | if (member) |
277 | { |
278 | member->deserialize(castToDerived(), buf, format); |
279 | } |
280 | else if (is_important) |
281 | { |
282 | details::SettingsCollectionUtils::throwNameNotFound(name); |
283 | } |
284 | else |
285 | { |
286 | details::SettingsCollectionUtils::warningNameNotFound(name); |
287 | details::SettingsCollectionUtils::skipValue(buf); |
288 | } |
289 | } |
290 | } |
291 | |
292 | |
293 | //-V:IMPLEMENT_SETTINGS_COLLECTION:501 |
294 | #define IMPLEMENT_SETTINGS_COLLECTION(DERIVED_CLASS_NAME, LIST_OF_SETTINGS_MACRO) \ |
295 | template<> \ |
296 | SettingsCollection<DERIVED_CLASS_NAME>::MemberInfos::MemberInfos() \ |
297 | { \ |
298 | using Derived = DERIVED_CLASS_NAME; \ |
299 | struct Functions \ |
300 | { \ |
301 | LIST_OF_SETTINGS_MACRO(IMPLEMENT_SETTINGS_COLLECTION_DEFINE_FUNCTIONS_HELPER_) \ |
302 | }; \ |
303 | constexpr int IMPORTANT = 1; \ |
304 | UNUSED(IMPORTANT); \ |
305 | LIST_OF_SETTINGS_MACRO(IMPLEMENT_SETTINGS_COLLECTION_ADD_MEMBER_INFO_HELPER_) \ |
306 | } \ |
307 | /** \ |
308 | * Instantiation should happen when all method definitions from SettingsCollectionImpl.h \ |
309 | * are accessible, so we instantiate explicitly. \ |
310 | */ \ |
311 | template class SettingsCollection<DERIVED_CLASS_NAME>; |
312 | |
313 | |
314 | #define IMPLEMENT_SETTINGS_COLLECTION_DEFINE_FUNCTIONS_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION, FLAGS) \ |
315 | static String NAME##_getString(const Derived & collection) { return collection.NAME.toString(); } \ |
316 | static Field NAME##_getField(const Derived & collection) { return collection.NAME.toField(); } \ |
317 | static void NAME##_setString(Derived & collection, const String & value) { collection.NAME.set(value); } \ |
318 | static void NAME##_setField(Derived & collection, const Field & value) { collection.NAME.set(value); } \ |
319 | static void NAME##_serialize(const Derived & collection, WriteBuffer & buf, SettingsBinaryFormat format) { collection.NAME.serialize(buf, format); } \ |
320 | static void NAME##_deserialize(Derived & collection, ReadBuffer & buf, SettingsBinaryFormat format) { collection.NAME.deserialize(buf, format); } \ |
321 | static String NAME##_valueToString(const Field & value) { TYPE temp{DEFAULT}; temp.set(value); return temp.toString(); } \ |
322 | static Field NAME##_valueToCorrespondingType(const Field & value) { TYPE temp{DEFAULT}; temp.set(value); return temp.toField(); } \ |
323 | |
324 | |
325 | #define IMPLEMENT_SETTINGS_COLLECTION_ADD_MEMBER_INFO_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION, FLAGS) \ |
326 | add({StringRef(#NAME, strlen(#NAME)), StringRef(DESCRIPTION, strlen(DESCRIPTION)), \ |
327 | FLAGS & IMPORTANT, \ |
328 | [](const Derived & d) { return d.NAME.changed; }, \ |
329 | &Functions::NAME##_getString, &Functions::NAME##_getField, \ |
330 | &Functions::NAME##_setString, &Functions::NAME##_setField, \ |
331 | &Functions::NAME##_serialize, &Functions::NAME##_deserialize, \ |
332 | &Functions::NAME##_valueToString, &Functions::NAME##_valueToCorrespondingType}); |
333 | } |
334 | |