diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-04-01 11:33:21 -0400 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-04-01 11:33:21 -0400 |
commit | 494e19b3c27e6a1eb63b39c245ad4024702e883b (patch) | |
tree | eb3980c7652ed24b402b5424c085f36827037880 /lib | |
parent | 8b95516aef0cd4bd98e2592d6f247882dc88886a (diff) | |
download | verbly-494e19b3c27e6a1eb63b39c245ad4024702e883b.tar.gz verbly-494e19b3c27e6a1eb63b39c245ad4024702e883b.tar.bz2 verbly-494e19b3c27e6a1eb63b39c245ad4024702e883b.zip |
Converted verbly::filter to use a variant object
Diffstat (limited to 'lib')
-rw-r--r-- | lib/filter.cpp | 1108 | ||||
-rw-r--r-- | lib/filter.h | 77 |
2 files changed, 429 insertions, 756 deletions
diff --git a/lib/filter.cpp b/lib/filter.cpp index fec0fd3..592b190 100644 --- a/lib/filter.cpp +++ b/lib/filter.cpp | |||
@@ -10,497 +10,6 @@ | |||
10 | 10 | ||
11 | namespace verbly { | 11 | namespace verbly { |
12 | 12 | ||
13 | filter::filter(const filter& other) | ||
14 | { | ||
15 | type_ = other.type_; | ||
16 | |||
17 | switch (type_) | ||
18 | { | ||
19 | case type::empty: | ||
20 | { | ||
21 | break; | ||
22 | } | ||
23 | |||
24 | case type::singleton: | ||
25 | { | ||
26 | new(&singleton_.filterField) field(other.singleton_.filterField); | ||
27 | singleton_.filterType = other.singleton_.filterType; | ||
28 | |||
29 | switch (singleton_.filterType) | ||
30 | { | ||
31 | case comparison::int_equals: | ||
32 | case comparison::int_does_not_equal: | ||
33 | case comparison::int_is_at_least: | ||
34 | case comparison::int_is_greater_than: | ||
35 | case comparison::int_is_at_most: | ||
36 | case comparison::int_is_less_than: | ||
37 | { | ||
38 | singleton_.intValue = other.singleton_.intValue; | ||
39 | |||
40 | break; | ||
41 | } | ||
42 | |||
43 | case comparison::boolean_equals: | ||
44 | { | ||
45 | singleton_.boolValue = other.singleton_.boolValue; | ||
46 | |||
47 | break; | ||
48 | } | ||
49 | |||
50 | case comparison::string_equals: | ||
51 | case comparison::string_does_not_equal: | ||
52 | case comparison::string_is_like: | ||
53 | case comparison::string_is_not_like: | ||
54 | { | ||
55 | new(&singleton_.stringValue) std::string(other.singleton_.stringValue); | ||
56 | |||
57 | break; | ||
58 | } | ||
59 | |||
60 | case comparison::is_null: | ||
61 | case comparison::is_not_null: | ||
62 | { | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | case comparison::matches: | ||
67 | case comparison::does_not_match: | ||
68 | case comparison::hierarchally_matches: | ||
69 | case comparison::does_not_hierarchally_match: | ||
70 | { | ||
71 | new(&singleton_.join) std::unique_ptr<filter>(new filter(*other.singleton_.join)); | ||
72 | |||
73 | break; | ||
74 | } | ||
75 | |||
76 | case comparison::field_equals: | ||
77 | case comparison::field_does_not_equal: | ||
78 | { | ||
79 | new(&singleton_.compareField) field(other.singleton_.compareField); | ||
80 | |||
81 | break; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | break; | ||
86 | } | ||
87 | |||
88 | case type::group: | ||
89 | { | ||
90 | new(&group_.children) std::list<filter>(other.group_.children); | ||
91 | group_.orlogic = other.group_.orlogic; | ||
92 | |||
93 | break; | ||
94 | } | ||
95 | |||
96 | case type::mask: | ||
97 | { | ||
98 | new(&mask_.name) std::string(other.mask_.name); | ||
99 | mask_.internal = other.mask_.internal; | ||
100 | new(&mask_.subfilter) std::unique_ptr<filter>(new filter(*other.mask_.subfilter)); | ||
101 | |||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | filter::filter(filter&& other) : filter() | ||
108 | { | ||
109 | swap(*this, other); | ||
110 | } | ||
111 | |||
112 | filter& filter::operator=(filter other) | ||
113 | { | ||
114 | swap(*this, other); | ||
115 | |||
116 | return *this; | ||
117 | } | ||
118 | |||
119 | void swap(filter& first, filter& second) | ||
120 | { | ||
121 | using type = filter::type; | ||
122 | using comparison = filter::comparison; | ||
123 | |||
124 | type tempType = first.type_; | ||
125 | field tempField; | ||
126 | comparison tempComparison; | ||
127 | std::unique_ptr<filter> tempJoin; | ||
128 | std::string tempStringValue; | ||
129 | int tempIntValue; | ||
130 | bool tempBoolValue; | ||
131 | field tempCompareField; | ||
132 | std::list<filter> tempChildren; | ||
133 | bool tempOrlogic; | ||
134 | std::string tempMaskName; | ||
135 | bool tempMaskInternal; | ||
136 | std::unique_ptr<filter> tempMaskSubfilter; | ||
137 | |||
138 | switch (tempType) | ||
139 | { | ||
140 | case type::empty: | ||
141 | { | ||
142 | break; | ||
143 | } | ||
144 | |||
145 | case type::singleton: | ||
146 | { | ||
147 | tempField = std::move(first.singleton_.filterField); | ||
148 | tempComparison = first.singleton_.filterType; | ||
149 | |||
150 | switch (tempComparison) | ||
151 | { | ||
152 | case comparison::int_equals: | ||
153 | case comparison::int_does_not_equal: | ||
154 | case comparison::int_is_at_least: | ||
155 | case comparison::int_is_greater_than: | ||
156 | case comparison::int_is_at_most: | ||
157 | case comparison::int_is_less_than: | ||
158 | { | ||
159 | tempIntValue = first.singleton_.intValue; | ||
160 | |||
161 | break; | ||
162 | } | ||
163 | |||
164 | case comparison::boolean_equals: | ||
165 | { | ||
166 | tempBoolValue = first.singleton_.boolValue; | ||
167 | |||
168 | break; | ||
169 | } | ||
170 | |||
171 | case comparison::string_equals: | ||
172 | case comparison::string_does_not_equal: | ||
173 | case comparison::string_is_like: | ||
174 | case comparison::string_is_not_like: | ||
175 | { | ||
176 | tempStringValue = std::move(first.singleton_.stringValue); | ||
177 | |||
178 | break; | ||
179 | } | ||
180 | |||
181 | case comparison::is_null: | ||
182 | case comparison::is_not_null: | ||
183 | { | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | case comparison::matches: | ||
188 | case comparison::does_not_match: | ||
189 | case comparison::hierarchally_matches: | ||
190 | case comparison::does_not_hierarchally_match: | ||
191 | { | ||
192 | tempJoin = std::move(first.singleton_.join); | ||
193 | |||
194 | break; | ||
195 | } | ||
196 | |||
197 | case comparison::field_equals: | ||
198 | case comparison::field_does_not_equal: | ||
199 | { | ||
200 | tempCompareField = std::move(first.singleton_.compareField); | ||
201 | |||
202 | break; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | break; | ||
207 | } | ||
208 | |||
209 | case type::group: | ||
210 | { | ||
211 | tempChildren = std::move(first.group_.children); | ||
212 | tempOrlogic = first.group_.orlogic; | ||
213 | |||
214 | break; | ||
215 | } | ||
216 | |||
217 | case type::mask: | ||
218 | { | ||
219 | tempMaskName = std::move(first.mask_.name); | ||
220 | tempMaskInternal = first.mask_.internal; | ||
221 | tempMaskSubfilter = std::move(first.mask_.subfilter); | ||
222 | |||
223 | break; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | first.~filter(); | ||
228 | |||
229 | first.type_ = second.type_; | ||
230 | |||
231 | switch (first.type_) | ||
232 | { | ||
233 | case type::empty: | ||
234 | { | ||
235 | break; | ||
236 | } | ||
237 | |||
238 | case type::singleton: | ||
239 | { | ||
240 | new(&first.singleton_.filterField) field(std::move(second.singleton_.filterField)); | ||
241 | first.singleton_.filterType = second.singleton_.filterType; | ||
242 | |||
243 | switch (first.singleton_.filterType) | ||
244 | { | ||
245 | case comparison::int_equals: | ||
246 | case comparison::int_does_not_equal: | ||
247 | case comparison::int_is_at_least: | ||
248 | case comparison::int_is_greater_than: | ||
249 | case comparison::int_is_at_most: | ||
250 | case comparison::int_is_less_than: | ||
251 | { | ||
252 | first.singleton_.intValue = second.singleton_.intValue; | ||
253 | |||
254 | break; | ||
255 | } | ||
256 | |||
257 | case comparison::boolean_equals: | ||
258 | { | ||
259 | first.singleton_.boolValue = second.singleton_.boolValue; | ||
260 | |||
261 | break; | ||
262 | } | ||
263 | |||
264 | case comparison::string_equals: | ||
265 | case comparison::string_does_not_equal: | ||
266 | case comparison::string_is_like: | ||
267 | case comparison::string_is_not_like: | ||
268 | { | ||
269 | new(&first.singleton_.stringValue) std::string(std::move(second.singleton_.stringValue)); | ||
270 | |||
271 | break; | ||
272 | } | ||
273 | |||
274 | case comparison::is_null: | ||
275 | case comparison::is_not_null: | ||
276 | { | ||
277 | break; | ||
278 | } | ||
279 | |||
280 | case comparison::matches: | ||
281 | case comparison::does_not_match: | ||
282 | case comparison::hierarchally_matches: | ||
283 | case comparison::does_not_hierarchally_match: | ||
284 | { | ||
285 | new(&first.singleton_.join) std::unique_ptr<filter>(std::move(second.singleton_.join)); | ||
286 | |||
287 | break; | ||
288 | } | ||
289 | |||
290 | case comparison::field_equals: | ||
291 | case comparison::field_does_not_equal: | ||
292 | { | ||
293 | new(&first.singleton_.compareField) field(std::move(second.singleton_.compareField)); | ||
294 | |||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | break; | ||
300 | } | ||
301 | |||
302 | case type::group: | ||
303 | { | ||
304 | new(&first.group_.children) std::list<filter>(std::move(second.group_.children)); | ||
305 | first.group_.orlogic = second.group_.orlogic; | ||
306 | |||
307 | break; | ||
308 | } | ||
309 | |||
310 | case type::mask: | ||
311 | { | ||
312 | new(&first.mask_.name) std::string(std::move(second.mask_.name)); | ||
313 | first.mask_.internal = second.mask_.internal; | ||
314 | new(&first.mask_.subfilter) std::unique_ptr<filter>(std::move(second.mask_.subfilter)); | ||
315 | |||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | second.~filter(); | ||
321 | |||
322 | second.type_ = tempType; | ||
323 | |||
324 | switch (second.type_) | ||
325 | { | ||
326 | case type::empty: | ||
327 | { | ||
328 | break; | ||
329 | } | ||
330 | |||
331 | case type::singleton: | ||
332 | { | ||
333 | new(&second.singleton_.filterField) field(std::move(tempField)); | ||
334 | second.singleton_.filterType = tempComparison; | ||
335 | |||
336 | switch (second.singleton_.filterType) | ||
337 | { | ||
338 | case comparison::int_equals: | ||
339 | case comparison::int_does_not_equal: | ||
340 | case comparison::int_is_at_least: | ||
341 | case comparison::int_is_greater_than: | ||
342 | case comparison::int_is_at_most: | ||
343 | case comparison::int_is_less_than: | ||
344 | { | ||
345 | second.singleton_.intValue = tempIntValue; | ||
346 | |||
347 | break; | ||
348 | } | ||
349 | |||
350 | case comparison::boolean_equals: | ||
351 | { | ||
352 | second.singleton_.boolValue = tempBoolValue; | ||
353 | |||
354 | break; | ||
355 | } | ||
356 | |||
357 | case comparison::string_equals: | ||
358 | case comparison::string_does_not_equal: | ||
359 | case comparison::string_is_like: | ||
360 | case comparison::string_is_not_like: | ||
361 | { | ||
362 | new(&second.singleton_.stringValue) std::string(std::move(tempStringValue)); | ||
363 | |||
364 | break; | ||
365 | } | ||
366 | |||
367 | case comparison::is_null: | ||
368 | case comparison::is_not_null: | ||
369 | { | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | case comparison::matches: | ||
374 | case comparison::does_not_match: | ||
375 | case comparison::hierarchally_matches: | ||
376 | case comparison::does_not_hierarchally_match: | ||
377 | { | ||
378 | new(&second.singleton_.join) std::unique_ptr<filter>(std::move(tempJoin)); | ||
379 | |||
380 | break; | ||
381 | } | ||
382 | |||
383 | case comparison::field_equals: | ||
384 | case comparison::field_does_not_equal: | ||
385 | { | ||
386 | new(&second.singleton_.compareField) field(std::move(tempCompareField)); | ||
387 | |||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | break; | ||
393 | } | ||
394 | |||
395 | case type::group: | ||
396 | { | ||
397 | new(&second.group_.children) std::list<filter>(std::move(tempChildren)); | ||
398 | second.group_.orlogic = tempOrlogic; | ||
399 | |||
400 | break; | ||
401 | } | ||
402 | |||
403 | case type::mask: | ||
404 | { | ||
405 | new(&first.mask_.name) std::string(std::move(tempMaskName)); | ||
406 | first.mask_.internal = tempMaskInternal; | ||
407 | new(&first.mask_.subfilter) std::unique_ptr<filter>(std::move(tempMaskSubfilter)); | ||
408 | |||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | |||
414 | filter::~filter() | ||
415 | { | ||
416 | switch (type_) | ||
417 | { | ||
418 | case type::empty: | ||
419 | { | ||
420 | break; | ||
421 | } | ||
422 | |||
423 | case type::singleton: | ||
424 | { | ||
425 | singleton_.filterField.~field(); | ||
426 | |||
427 | switch (singleton_.filterType) | ||
428 | { | ||
429 | case comparison::int_equals: | ||
430 | case comparison::int_does_not_equal: | ||
431 | case comparison::int_is_at_least: | ||
432 | case comparison::int_is_greater_than: | ||
433 | case comparison::int_is_at_most: | ||
434 | case comparison::int_is_less_than: | ||
435 | case comparison::boolean_equals: | ||
436 | case comparison::is_null: | ||
437 | case comparison::is_not_null: | ||
438 | { | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | case comparison::string_equals: | ||
443 | case comparison::string_does_not_equal: | ||
444 | case comparison::string_is_like: | ||
445 | case comparison::string_is_not_like: | ||
446 | { | ||
447 | using string_type = std::string; | ||
448 | |||
449 | singleton_.stringValue.~string_type(); | ||
450 | |||
451 | break; | ||
452 | } | ||
453 | |||
454 | case comparison::matches: | ||
455 | case comparison::does_not_match: | ||
456 | case comparison::hierarchally_matches: | ||
457 | case comparison::does_not_hierarchally_match: | ||
458 | { | ||
459 | using ptr_type = std::unique_ptr<filter>; | ||
460 | |||
461 | singleton_.join.~ptr_type(); | ||
462 | |||
463 | break; | ||
464 | } | ||
465 | |||
466 | case comparison::field_equals: | ||
467 | case comparison::field_does_not_equal: | ||
468 | { | ||
469 | singleton_.compareField.~field(); | ||
470 | |||
471 | break; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | break; | ||
476 | } | ||
477 | |||
478 | case type::group: | ||
479 | { | ||
480 | using list_type = std::list<filter>; | ||
481 | |||
482 | group_.children.~list_type(); | ||
483 | |||
484 | break; | ||
485 | } | ||
486 | |||
487 | case type::mask: | ||
488 | { | ||
489 | using string_type = std::string; | ||
490 | using ptr_type = std::unique_ptr<filter>; | ||
491 | |||
492 | mask_.name.~string_type(); | ||
493 | mask_.subfilter.~ptr_type(); | ||
494 | |||
495 | break; | ||
496 | } | ||
497 | } | ||
498 | } | ||
499 | |||
500 | filter::filter() | ||
501 | { | ||
502 | } | ||
503 | |||
504 | filter::filter( | 13 | filter::filter( |
505 | field filterField, | 14 | field filterField, |
506 | comparison filterType, | 15 | comparison filterType, |
@@ -518,9 +27,12 @@ namespace verbly { | |||
518 | case comparison::int_is_at_most: | 27 | case comparison::int_is_at_most: |
519 | case comparison::int_is_less_than: | 28 | case comparison::int_is_less_than: |
520 | { | 29 | { |
521 | new(&singleton_.filterField) field(std::move(filterField)); | 30 | variant_ = singleton_type |
522 | singleton_.filterType = filterType; | 31 | { |
523 | singleton_.intValue = filterValue; | 32 | std::move(filterField), |
33 | filterType, | ||
34 | filterValue | ||
35 | }; | ||
524 | 36 | ||
525 | break; | 37 | break; |
526 | } | 38 | } |
@@ -543,7 +55,8 @@ namespace verbly { | |||
543 | } | 55 | } |
544 | } | 56 | } |
545 | } else { | 57 | } else { |
546 | throw std::domain_error("Cannot match a non-integer field against an integer value"); | 58 | throw std::domain_error( |
59 | "Cannot match a non-integer field against an integer value"); | ||
547 | } | 60 | } |
548 | } | 61 | } |
549 | 62 | ||
@@ -562,9 +75,12 @@ namespace verbly { | |||
562 | case comparison::string_is_like: | 75 | case comparison::string_is_like: |
563 | case comparison::string_is_not_like: | 76 | case comparison::string_is_not_like: |
564 | { | 77 | { |
565 | new(&singleton_.filterField) field(std::move(filterField)); | 78 | variant_ = singleton_type |
566 | singleton_.filterType = filterType; | 79 | { |
567 | new(&singleton_.stringValue) std::string(std::move(filterValue)); | 80 | std::move(filterField), |
81 | filterType, | ||
82 | std::move(filterValue) | ||
83 | }; | ||
568 | 84 | ||
569 | break; | 85 | break; |
570 | } | 86 | } |
@@ -589,7 +105,8 @@ namespace verbly { | |||
589 | } | 105 | } |
590 | } | 106 | } |
591 | } else { | 107 | } else { |
592 | throw std::domain_error("Cannot match a non-string field against an string value"); | 108 | throw std::domain_error( |
109 | "Cannot match a non-string field against an string value"); | ||
593 | } | 110 | } |
594 | } | 111 | } |
595 | 112 | ||
@@ -605,9 +122,12 @@ namespace verbly { | |||
605 | { | 122 | { |
606 | case comparison::boolean_equals: | 123 | case comparison::boolean_equals: |
607 | { | 124 | { |
608 | new(&singleton_.filterField) field(std::move(filterField)); | 125 | variant_ = singleton_type |
609 | singleton_.filterType = filterType; | 126 | { |
610 | singleton_.boolValue = filterValue; | 127 | std::move(filterField), |
128 | filterType, | ||
129 | filterValue | ||
130 | }; | ||
611 | 131 | ||
612 | break; | 132 | break; |
613 | } | 133 | } |
@@ -635,7 +155,8 @@ namespace verbly { | |||
635 | } | 155 | } |
636 | } | 156 | } |
637 | } else { | 157 | } else { |
638 | throw std::domain_error("Cannot match a non-boolean field against a boolean value"); | 158 | throw std::domain_error( |
159 | "Cannot match a non-boolean field against a boolean value"); | ||
639 | } | 160 | } |
640 | } | 161 | } |
641 | 162 | ||
@@ -651,8 +172,11 @@ namespace verbly { | |||
651 | case comparison::is_null: | 172 | case comparison::is_null: |
652 | case comparison::is_not_null: | 173 | case comparison::is_not_null: |
653 | { | 174 | { |
654 | new(&singleton_.filterField) field(std::move(filterField)); | 175 | variant_ = singleton_type |
655 | singleton_.filterType = filterType; | 176 | { |
177 | std::move(filterField), | ||
178 | filterType | ||
179 | }; | ||
656 | 180 | ||
657 | break; | 181 | break; |
658 | } | 182 | } |
@@ -675,11 +199,13 @@ namespace verbly { | |||
675 | case comparison::field_equals: | 199 | case comparison::field_equals: |
676 | case comparison::field_does_not_equal: | 200 | case comparison::field_does_not_equal: |
677 | { | 201 | { |
678 | throw std::invalid_argument("Incorrect constructor for given comparison"); | 202 | throw std::invalid_argument( |
203 | "Incorrect constructor for given comparison"); | ||
679 | } | 204 | } |
680 | } | 205 | } |
681 | } else { | 206 | } else { |
682 | throw std::domain_error("Cannot check nullity/non-nullity of non-nullable field"); | 207 | throw std::domain_error( |
208 | "Cannot check nullity/non-nullity of non-nullable field"); | ||
683 | } | 209 | } |
684 | } | 210 | } |
685 | 211 | ||
@@ -701,9 +227,12 @@ namespace verbly { | |||
701 | case comparison::matches: | 227 | case comparison::matches: |
702 | case comparison::does_not_match: | 228 | case comparison::does_not_match: |
703 | { | 229 | { |
704 | new(&singleton_.filterField) field(std::move(joinOn)); | 230 | variant_ = singleton_type |
705 | singleton_.filterType = filterType; | 231 | { |
706 | new(&singleton_.join) std::unique_ptr<filter>(new filter(std::move(joinCondition))); | 232 | std::move(joinOn), |
233 | filterType, | ||
234 | rec_filter(new filter(std::move(joinCondition))) | ||
235 | }; | ||
707 | 236 | ||
708 | break; | 237 | break; |
709 | } | 238 | } |
@@ -726,7 +255,8 @@ namespace verbly { | |||
726 | case comparison::field_equals: | 255 | case comparison::field_equals: |
727 | case comparison::field_does_not_equal: | 256 | case comparison::field_does_not_equal: |
728 | { | 257 | { |
729 | throw std::invalid_argument("Incorrect constructor for given comparison"); | 258 | throw std::invalid_argument( |
259 | "Incorrect constructor for given comparison"); | ||
730 | } | 260 | } |
731 | } | 261 | } |
732 | 262 | ||
@@ -740,9 +270,12 @@ namespace verbly { | |||
740 | case comparison::hierarchally_matches: | 270 | case comparison::hierarchally_matches: |
741 | case comparison::does_not_hierarchally_match: | 271 | case comparison::does_not_hierarchally_match: |
742 | { | 272 | { |
743 | new(&singleton_.filterField) field(std::move(joinOn)); | 273 | variant_ = singleton_type |
744 | singleton_.filterType = filterType; | 274 | { |
745 | new(&singleton_.join) std::unique_ptr<filter>(new filter(std::move(joinCondition))); | 275 | std::move(joinOn), |
276 | filterType, | ||
277 | rec_filter(new filter(std::move(joinCondition))) | ||
278 | }; | ||
746 | 279 | ||
747 | break; | 280 | break; |
748 | } | 281 | } |
@@ -765,7 +298,8 @@ namespace verbly { | |||
765 | case comparison::field_equals: | 298 | case comparison::field_equals: |
766 | case comparison::field_does_not_equal: | 299 | case comparison::field_does_not_equal: |
767 | { | 300 | { |
768 | throw std::invalid_argument("Incorrect constructor for given comparison"); | 301 | throw std::invalid_argument( |
302 | "Incorrect constructor for given comparison"); | ||
769 | } | 303 | } |
770 | } | 304 | } |
771 | 305 | ||
@@ -803,9 +337,12 @@ namespace verbly { | |||
803 | throw std::domain_error("Cannot compare join fields"); | 337 | throw std::domain_error("Cannot compare join fields"); |
804 | } | 338 | } |
805 | 339 | ||
806 | new(&singleton_.filterField) field(std::move(filterField)); | 340 | variant_ = singleton_type |
807 | singleton_.filterType = filterType; | 341 | { |
808 | new(&singleton_.compareField) field(std::move(compareField)); | 342 | std::move(filterField), |
343 | filterType, | ||
344 | std::move(compareField) | ||
345 | }; | ||
809 | 346 | ||
810 | break; | 347 | break; |
811 | } | 348 | } |
@@ -835,146 +372,155 @@ namespace verbly { | |||
835 | 372 | ||
836 | field filter::getField() const | 373 | field filter::getField() const |
837 | { | 374 | { |
838 | if (type_ == type::singleton) | 375 | if (type_ != type::singleton) |
839 | { | 376 | { |
840 | return singleton_.filterField; | ||
841 | } else { | ||
842 | throw std::domain_error("This filter does not have a field"); | 377 | throw std::domain_error("This filter does not have a field"); |
843 | } | 378 | } |
379 | |||
380 | return mpark::get<singleton_type>(variant_).filterField; | ||
844 | } | 381 | } |
845 | 382 | ||
846 | filter::comparison filter::getComparison() const | 383 | filter::comparison filter::getComparison() const |
847 | { | 384 | { |
848 | if (type_ == type::singleton) | 385 | if (type_ != type::singleton) |
849 | { | 386 | { |
850 | return singleton_.filterType; | ||
851 | } else { | ||
852 | throw std::domain_error("This filter does not have a comparison"); | 387 | throw std::domain_error("This filter does not have a comparison"); |
853 | } | 388 | } |
389 | |||
390 | return mpark::get<singleton_type>(variant_).filterType; | ||
854 | } | 391 | } |
855 | 392 | ||
856 | filter filter::getJoinCondition() const | 393 | filter filter::getJoinCondition() const |
857 | { | 394 | { |
858 | if (type_ == type::singleton) | 395 | if (type_ != type::singleton) |
859 | { | 396 | { |
860 | switch (singleton_.filterType) | 397 | throw std::domain_error("This filter does not have a join condition"); |
398 | } | ||
399 | |||
400 | const singleton_type& ss = mpark::get<singleton_type>(variant_); | ||
401 | |||
402 | switch (ss.filterType) | ||
403 | { | ||
404 | case comparison::matches: | ||
405 | case comparison::does_not_match: | ||
406 | case comparison::hierarchally_matches: | ||
407 | case comparison::does_not_hierarchally_match: | ||
861 | { | 408 | { |
862 | case comparison::matches: | 409 | return *mpark::get<rec_filter>(ss.data); |
863 | case comparison::does_not_match: | 410 | } |
864 | case comparison::hierarchally_matches: | ||
865 | case comparison::does_not_hierarchally_match: | ||
866 | { | ||
867 | return *singleton_.join; | ||
868 | } | ||
869 | 411 | ||
870 | case comparison::string_equals: | 412 | case comparison::string_equals: |
871 | case comparison::string_does_not_equal: | 413 | case comparison::string_does_not_equal: |
872 | case comparison::string_is_like: | 414 | case comparison::string_is_like: |
873 | case comparison::string_is_not_like: | 415 | case comparison::string_is_not_like: |
874 | case comparison::int_equals: | 416 | case comparison::int_equals: |
875 | case comparison::int_does_not_equal: | 417 | case comparison::int_does_not_equal: |
876 | case comparison::int_is_at_least: | 418 | case comparison::int_is_at_least: |
877 | case comparison::int_is_greater_than: | 419 | case comparison::int_is_greater_than: |
878 | case comparison::int_is_at_most: | 420 | case comparison::int_is_at_most: |
879 | case comparison::int_is_less_than: | 421 | case comparison::int_is_less_than: |
880 | case comparison::boolean_equals: | 422 | case comparison::boolean_equals: |
881 | case comparison::is_null: | 423 | case comparison::is_null: |
882 | case comparison::is_not_null: | 424 | case comparison::is_not_null: |
883 | case comparison::field_equals: | 425 | case comparison::field_equals: |
884 | case comparison::field_does_not_equal: | 426 | case comparison::field_does_not_equal: |
885 | { | 427 | { |
886 | throw std::domain_error("This filter does not have a join condition"); | 428 | throw std::domain_error("This filter does not have a join condition"); |
887 | } | ||
888 | } | 429 | } |
889 | } else { | ||
890 | throw std::domain_error("This filter does not have a join condition"); | ||
891 | } | 430 | } |
892 | } | 431 | } |
893 | 432 | ||
894 | std::string filter::getStringArgument() const | 433 | std::string filter::getStringArgument() const |
895 | { | 434 | { |
896 | if (type_ == type::singleton) | 435 | if (type_ != type::singleton) |
436 | { | ||
437 | throw std::domain_error("This filter does not have a string argument"); | ||
438 | } | ||
439 | |||
440 | const singleton_type& ss = mpark::get<singleton_type>(variant_); | ||
441 | |||
442 | switch (ss.filterType) | ||
897 | { | 443 | { |
898 | switch (singleton_.filterType) | 444 | case comparison::string_equals: |
445 | case comparison::string_does_not_equal: | ||
446 | case comparison::string_is_like: | ||
447 | case comparison::string_is_not_like: | ||
899 | { | 448 | { |
900 | case comparison::string_equals: | 449 | return mpark::get<std::string>(ss.data); |
901 | case comparison::string_does_not_equal: | 450 | } |
902 | case comparison::string_is_like: | ||
903 | case comparison::string_is_not_like: | ||
904 | { | ||
905 | return singleton_.stringValue; | ||
906 | } | ||
907 | 451 | ||
908 | case comparison::int_equals: | 452 | case comparison::int_equals: |
909 | case comparison::int_does_not_equal: | 453 | case comparison::int_does_not_equal: |
910 | case comparison::int_is_at_least: | 454 | case comparison::int_is_at_least: |
911 | case comparison::int_is_greater_than: | 455 | case comparison::int_is_greater_than: |
912 | case comparison::int_is_at_most: | 456 | case comparison::int_is_at_most: |
913 | case comparison::int_is_less_than: | 457 | case comparison::int_is_less_than: |
914 | case comparison::boolean_equals: | 458 | case comparison::boolean_equals: |
915 | case comparison::is_null: | 459 | case comparison::is_null: |
916 | case comparison::is_not_null: | 460 | case comparison::is_not_null: |
917 | case comparison::matches: | 461 | case comparison::matches: |
918 | case comparison::does_not_match: | 462 | case comparison::does_not_match: |
919 | case comparison::hierarchally_matches: | 463 | case comparison::hierarchally_matches: |
920 | case comparison::does_not_hierarchally_match: | 464 | case comparison::does_not_hierarchally_match: |
921 | case comparison::field_equals: | 465 | case comparison::field_equals: |
922 | case comparison::field_does_not_equal: | 466 | case comparison::field_does_not_equal: |
923 | { | 467 | { |
924 | throw std::domain_error("This filter does not have a string argument"); | 468 | throw std::domain_error("This filter does not have a string argument"); |
925 | } | ||
926 | } | 469 | } |
927 | } else { | ||
928 | throw std::domain_error("This filter does not have a string argument"); | ||
929 | } | 470 | } |
930 | } | 471 | } |
931 | 472 | ||
932 | int filter::getIntegerArgument() const | 473 | int filter::getIntegerArgument() const |
933 | { | 474 | { |
934 | if (type_ == type::singleton) | 475 | if (type_ != type::singleton) |
476 | { | ||
477 | throw std::domain_error("This filter does not have an integer argument"); | ||
478 | } | ||
479 | |||
480 | const singleton_type& ss = mpark::get<singleton_type>(variant_); | ||
481 | |||
482 | switch (ss.filterType) | ||
935 | { | 483 | { |
936 | switch (singleton_.filterType) | 484 | case comparison::int_equals: |
485 | case comparison::int_does_not_equal: | ||
486 | case comparison::int_is_at_least: | ||
487 | case comparison::int_is_greater_than: | ||
488 | case comparison::int_is_at_most: | ||
489 | case comparison::int_is_less_than: | ||
937 | { | 490 | { |
938 | case comparison::int_equals: | 491 | return mpark::get<int>(ss.data); |
939 | case comparison::int_does_not_equal: | 492 | } |
940 | case comparison::int_is_at_least: | ||
941 | case comparison::int_is_greater_than: | ||
942 | case comparison::int_is_at_most: | ||
943 | case comparison::int_is_less_than: | ||
944 | { | ||
945 | return singleton_.intValue; | ||
946 | } | ||
947 | 493 | ||
948 | case comparison::string_equals: | 494 | case comparison::string_equals: |
949 | case comparison::string_does_not_equal: | 495 | case comparison::string_does_not_equal: |
950 | case comparison::string_is_like: | 496 | case comparison::string_is_like: |
951 | case comparison::string_is_not_like: | 497 | case comparison::string_is_not_like: |
952 | case comparison::boolean_equals: | 498 | case comparison::boolean_equals: |
953 | case comparison::is_null: | 499 | case comparison::is_null: |
954 | case comparison::is_not_null: | 500 | case comparison::is_not_null: |
955 | case comparison::matches: | 501 | case comparison::matches: |
956 | case comparison::does_not_match: | 502 | case comparison::does_not_match: |
957 | case comparison::hierarchally_matches: | 503 | case comparison::hierarchally_matches: |
958 | case comparison::does_not_hierarchally_match: | 504 | case comparison::does_not_hierarchally_match: |
959 | case comparison::field_equals: | 505 | case comparison::field_equals: |
960 | case comparison::field_does_not_equal: | 506 | case comparison::field_does_not_equal: |
961 | { | 507 | { |
962 | throw std::domain_error("This filter does not have an integer argument"); | 508 | throw std::domain_error( |
963 | } | 509 | "This filter does not have an integer argument"); |
964 | } | 510 | } |
965 | } else { | ||
966 | throw std::domain_error("This filter does not have an integer argument"); | ||
967 | } | 511 | } |
968 | } | 512 | } |
969 | 513 | ||
970 | bool filter::getBooleanArgument() const | 514 | bool filter::getBooleanArgument() const |
971 | { | 515 | { |
972 | if ((type_ == type::singleton) && (singleton_.filterType == comparison::boolean_equals)) | 516 | if ((type_ != type::singleton) || |
517 | (mpark::get<singleton_type>(variant_).filterType != | ||
518 | comparison::boolean_equals)) | ||
973 | { | 519 | { |
974 | return singleton_.boolValue; | ||
975 | } else { | ||
976 | throw std::domain_error("This filter does not have a boolean argument"); | 520 | throw std::domain_error("This filter does not have a boolean argument"); |
977 | } | 521 | } |
522 | |||
523 | return mpark::get<bool>(mpark::get<singleton_type>(variant_).data); | ||
978 | } | 524 | } |
979 | 525 | ||
980 | field filter::getCompareField() const | 526 | field filter::getCompareField() const |
@@ -984,12 +530,14 @@ namespace verbly { | |||
984 | throw std::domain_error("This filter does not have a compare field"); | 530 | throw std::domain_error("This filter does not have a compare field"); |
985 | } | 531 | } |
986 | 532 | ||
987 | switch (singleton_.filterType) | 533 | const singleton_type& ss = mpark::get<singleton_type>(variant_); |
534 | |||
535 | switch (ss.filterType) | ||
988 | { | 536 | { |
989 | case comparison::field_equals: | 537 | case comparison::field_equals: |
990 | case comparison::field_does_not_equal: | 538 | case comparison::field_does_not_equal: |
991 | { | 539 | { |
992 | return singleton_.compareField; | 540 | return mpark::get<field>(ss.data); |
993 | 541 | ||
994 | break; | 542 | break; |
995 | } | 543 | } |
@@ -1018,20 +566,20 @@ namespace verbly { | |||
1018 | 566 | ||
1019 | } | 567 | } |
1020 | 568 | ||
1021 | filter::filter(bool orlogic) : type_(type::group) | 569 | filter::filter(bool orlogic) : |
570 | type_(type::group), | ||
571 | variant_(group_type {{}, orlogic}) | ||
1022 | { | 572 | { |
1023 | new(&group_.children) std::list<filter>(); | ||
1024 | group_.orlogic = orlogic; | ||
1025 | } | 573 | } |
1026 | 574 | ||
1027 | bool filter::getOrlogic() const | 575 | bool filter::getOrlogic() const |
1028 | { | 576 | { |
1029 | if (type_ == type::group) | 577 | if (type_ != type::group) |
1030 | { | 578 | { |
1031 | return group_.orlogic; | ||
1032 | } else { | ||
1033 | throw std::domain_error("This filter is not a group filter"); | 579 | throw std::domain_error("This filter is not a group filter"); |
1034 | } | 580 | } |
581 | |||
582 | return mpark::get<group_type>(variant_).orlogic; | ||
1035 | } | 583 | } |
1036 | 584 | ||
1037 | filter filter::operator+(filter condition) const | 585 | filter filter::operator+(filter condition) const |
@@ -1044,72 +592,77 @@ namespace verbly { | |||
1044 | 592 | ||
1045 | filter& filter::operator+=(filter condition) | 593 | filter& filter::operator+=(filter condition) |
1046 | { | 594 | { |
1047 | if (type_ == type::group) | 595 | if (type_ != type::group) |
1048 | { | 596 | { |
1049 | group_.children.push_back(std::move(condition)); | ||
1050 | |||
1051 | return *this; | ||
1052 | } else { | ||
1053 | throw std::domain_error("Children can only be added to group filters"); | 597 | throw std::domain_error("Children can only be added to group filters"); |
1054 | } | 598 | } |
599 | |||
600 | mpark::get<group_type>(variant_).children.push_back(std::move(condition)); | ||
601 | |||
602 | return *this; | ||
1055 | } | 603 | } |
1056 | 604 | ||
1057 | filter::const_iterator filter::begin() const | 605 | filter::const_iterator filter::begin() const |
1058 | { | 606 | { |
1059 | if (type_ == type::group) | 607 | if (type_ != type::group) |
1060 | { | 608 | { |
1061 | return std::begin(group_.children); | ||
1062 | } else { | ||
1063 | throw std::domain_error("This filter has no children"); | 609 | throw std::domain_error("This filter has no children"); |
1064 | } | 610 | } |
611 | |||
612 | return std::begin(mpark::get<group_type>(variant_).children); | ||
1065 | } | 613 | } |
1066 | 614 | ||
1067 | filter::const_iterator filter::end() const | 615 | filter::const_iterator filter::end() const |
1068 | { | 616 | { |
1069 | if (type_ == type::group) | 617 | if (type_ != type::group) |
1070 | { | 618 | { |
1071 | return std::end(group_.children); | ||
1072 | } else { | ||
1073 | throw std::domain_error("This filter has no children"); | 619 | throw std::domain_error("This filter has no children"); |
1074 | } | 620 | } |
621 | |||
622 | return std::end(mpark::get<group_type>(variant_).children); | ||
1075 | } | 623 | } |
1076 | 624 | ||
1077 | filter::filter(std::string name, bool internal, filter subfilter) : | 625 | filter::filter( |
1078 | type_(type::mask) | 626 | std::string name, |
627 | bool internal, | ||
628 | filter subfilter) : | ||
629 | type_(type::mask), | ||
630 | variant_(mask_type { | ||
631 | std::move(name), | ||
632 | internal, | ||
633 | rec_filter(new filter(std::move(subfilter))) | ||
634 | }) | ||
1079 | { | 635 | { |
1080 | new(&mask_.name) std::string(std::move(name)); | ||
1081 | mask_.internal = internal; | ||
1082 | new(&mask_.subfilter) std::unique_ptr<filter>(new filter(std::move(subfilter))); | ||
1083 | } | 636 | } |
1084 | 637 | ||
1085 | const std::string& filter::getMaskName() const | 638 | const std::string& filter::getMaskName() const |
1086 | { | 639 | { |
1087 | if (type_ == type::mask) | 640 | if (type_ != type::mask) |
1088 | { | 641 | { |
1089 | return mask_.name; | ||
1090 | } else { | ||
1091 | throw std::domain_error("This filter is not a mask filter"); | 642 | throw std::domain_error("This filter is not a mask filter"); |
1092 | } | 643 | } |
644 | |||
645 | return mpark::get<mask_type>(variant_).name; | ||
1093 | } | 646 | } |
1094 | 647 | ||
1095 | bool filter::isMaskInternal() const | 648 | bool filter::isMaskInternal() const |
1096 | { | 649 | { |
1097 | if (type_ == type::mask) | 650 | if (type_ != type::mask) |
1098 | { | 651 | { |
1099 | return mask_.internal; | ||
1100 | } else { | ||
1101 | throw std::domain_error("This filter is not a mask filter"); | 652 | throw std::domain_error("This filter is not a mask filter"); |
1102 | } | 653 | } |
654 | |||
655 | return mpark::get<mask_type>(variant_).internal; | ||
1103 | } | 656 | } |
1104 | 657 | ||
1105 | const filter& filter::getMaskFilter() const | 658 | const filter& filter::getMaskFilter() const |
1106 | { | 659 | { |
1107 | if (type_ == type::mask) | 660 | if (type_ != type::mask) |
1108 | { | 661 | { |
1109 | return *mask_.subfilter; | ||
1110 | } else { | ||
1111 | throw std::domain_error("This filter is not a mask filter"); | 662 | throw std::domain_error("This filter is not a mask filter"); |
1112 | } | 663 | } |
664 | |||
665 | return *mpark::get<mask_type>(variant_).subfilter; | ||
1113 | } | 666 | } |
1114 | 667 | ||
1115 | filter filter::operator!() const | 668 | filter filter::operator!() const |
@@ -1123,110 +676,169 @@ namespace verbly { | |||
1123 | 676 | ||
1124 | case type::singleton: | 677 | case type::singleton: |
1125 | { | 678 | { |
1126 | switch (singleton_.filterType) | 679 | const singleton_type& ss = mpark::get<singleton_type>(variant_); |
680 | |||
681 | switch (ss.filterType) | ||
1127 | { | 682 | { |
1128 | case comparison::int_equals: | 683 | case comparison::int_equals: |
1129 | { | 684 | { |
1130 | return filter(singleton_.filterField, comparison::int_does_not_equal, singleton_.intValue); | 685 | return filter( |
686 | ss.filterField, | ||
687 | comparison::int_does_not_equal, | ||
688 | mpark::get<int>(ss.data)); | ||
1131 | } | 689 | } |
1132 | 690 | ||
1133 | case comparison::int_does_not_equal: | 691 | case comparison::int_does_not_equal: |
1134 | { | 692 | { |
1135 | return filter(singleton_.filterField, comparison::int_equals, singleton_.intValue); | 693 | return filter( |
694 | ss.filterField, | ||
695 | comparison::int_equals, | ||
696 | mpark::get<int>(ss.data)); | ||
1136 | } | 697 | } |
1137 | 698 | ||
1138 | case comparison::int_is_at_least: | 699 | case comparison::int_is_at_least: |
1139 | { | 700 | { |
1140 | return filter(singleton_.filterField, comparison::int_is_less_than, singleton_.intValue); | 701 | return filter( |
702 | ss.filterField, | ||
703 | comparison::int_is_less_than, | ||
704 | mpark::get<int>(ss.data)); | ||
1141 | } | 705 | } |
1142 | 706 | ||
1143 | case comparison::int_is_greater_than: | 707 | case comparison::int_is_greater_than: |
1144 | { | 708 | { |
1145 | return filter(singleton_.filterField, comparison::int_is_at_most, singleton_.intValue); | 709 | return filter( |
710 | ss.filterField, | ||
711 | comparison::int_is_at_most, | ||
712 | mpark::get<int>(ss.data)); | ||
1146 | } | 713 | } |
1147 | 714 | ||
1148 | case comparison::int_is_at_most: | 715 | case comparison::int_is_at_most: |
1149 | { | 716 | { |
1150 | return filter(singleton_.filterField, comparison::int_is_greater_than, singleton_.intValue); | 717 | return filter( |
718 | ss.filterField, | ||
719 | comparison::int_is_greater_than, | ||
720 | mpark::get<int>(ss.data)); | ||
1151 | } | 721 | } |
1152 | 722 | ||
1153 | case comparison::int_is_less_than: | 723 | case comparison::int_is_less_than: |
1154 | { | 724 | { |
1155 | return filter(singleton_.filterField, comparison::int_is_at_least, singleton_.intValue); | 725 | return filter( |
726 | ss.filterField, | ||
727 | comparison::int_is_at_least, | ||
728 | mpark::get<int>(ss.data)); | ||
1156 | } | 729 | } |
1157 | 730 | ||
1158 | case comparison::boolean_equals: | 731 | case comparison::boolean_equals: |
1159 | { | 732 | { |
1160 | return filter(singleton_.filterField, comparison::boolean_equals, !singleton_.boolValue); | 733 | return filter( |
734 | ss.filterField, | ||
735 | comparison::boolean_equals, | ||
736 | !mpark::get<int>(ss.data)); | ||
1161 | } | 737 | } |
1162 | 738 | ||
1163 | case comparison::string_equals: | 739 | case comparison::string_equals: |
1164 | { | 740 | { |
1165 | return filter(singleton_.filterField, comparison::string_does_not_equal, singleton_.stringValue); | 741 | return filter( |
742 | ss.filterField, | ||
743 | comparison::string_does_not_equal, | ||
744 | mpark::get<std::string>(ss.data)); | ||
1166 | } | 745 | } |
1167 | 746 | ||
1168 | case comparison::string_does_not_equal: | 747 | case comparison::string_does_not_equal: |
1169 | { | 748 | { |
1170 | return filter(singleton_.filterField, comparison::string_equals, singleton_.stringValue); | 749 | return filter( |
750 | ss.filterField, | ||
751 | comparison::string_equals, | ||
752 | mpark::get<std::string>(ss.data)); | ||
1171 | } | 753 | } |
1172 | 754 | ||
1173 | case comparison::string_is_like: | 755 | case comparison::string_is_like: |
1174 | { | 756 | { |
1175 | return filter(singleton_.filterField, comparison::string_is_not_like, singleton_.stringValue); | 757 | return filter( |
758 | ss.filterField, | ||
759 | comparison::string_is_not_like, | ||
760 | mpark::get<std::string>(ss.data)); | ||
1176 | } | 761 | } |
1177 | 762 | ||
1178 | case comparison::string_is_not_like: | 763 | case comparison::string_is_not_like: |
1179 | { | 764 | { |
1180 | return filter(singleton_.filterField, comparison::string_is_like, singleton_.stringValue); | 765 | return filter( |
766 | ss.filterField, | ||
767 | comparison::string_is_like, | ||
768 | mpark::get<std::string>(ss.data)); | ||
1181 | } | 769 | } |
1182 | 770 | ||
1183 | case comparison::is_null: | 771 | case comparison::is_null: |
1184 | { | 772 | { |
1185 | return filter(singleton_.filterField, comparison::is_not_null); | 773 | return filter( |
774 | ss.filterField, | ||
775 | comparison::is_not_null); | ||
1186 | } | 776 | } |
1187 | 777 | ||
1188 | case comparison::is_not_null: | 778 | case comparison::is_not_null: |
1189 | { | 779 | { |
1190 | return filter(singleton_.filterField, comparison::is_null); | 780 | return filter( |
781 | ss.filterField, | ||
782 | comparison::is_null); | ||
1191 | } | 783 | } |
1192 | 784 | ||
1193 | case comparison::matches: | 785 | case comparison::matches: |
1194 | { | 786 | { |
1195 | return filter(singleton_.filterField, comparison::does_not_match, *singleton_.join); | 787 | return filter( |
788 | ss.filterField, | ||
789 | comparison::does_not_match, | ||
790 | *mpark::get<rec_filter>(ss.data)); | ||
1196 | } | 791 | } |
1197 | 792 | ||
1198 | case comparison::does_not_match: | 793 | case comparison::does_not_match: |
1199 | { | 794 | { |
1200 | return filter(singleton_.filterField, comparison::matches, *singleton_.join); | 795 | return filter( |
796 | ss.filterField, | ||
797 | comparison::matches, | ||
798 | *mpark::get<rec_filter>(ss.data)); | ||
1201 | } | 799 | } |
1202 | 800 | ||
1203 | case comparison::hierarchally_matches: | 801 | case comparison::hierarchally_matches: |
1204 | { | 802 | { |
1205 | return filter(singleton_.filterField, comparison::does_not_hierarchally_match, *singleton_.join); | 803 | return filter( |
804 | ss.filterField, | ||
805 | comparison::does_not_hierarchally_match, | ||
806 | *mpark::get<rec_filter>(ss.data)); | ||
1206 | } | 807 | } |
1207 | 808 | ||
1208 | case comparison::does_not_hierarchally_match: | 809 | case comparison::does_not_hierarchally_match: |
1209 | { | 810 | { |
1210 | return filter(singleton_.filterField, comparison::hierarchally_matches, *singleton_.join); | 811 | return filter( |
812 | ss.filterField, | ||
813 | comparison::hierarchally_matches, | ||
814 | *mpark::get<rec_filter>(ss.data)); | ||
1211 | } | 815 | } |
1212 | 816 | ||
1213 | case comparison::field_equals: | 817 | case comparison::field_equals: |
1214 | { | 818 | { |
1215 | return filter(singleton_.filterField, comparison::field_does_not_equal, singleton_.compareField); | 819 | return filter( |
820 | ss.filterField, | ||
821 | comparison::field_does_not_equal, | ||
822 | mpark::get<field>(ss.data)); | ||
1216 | } | 823 | } |
1217 | 824 | ||
1218 | case comparison::field_does_not_equal: | 825 | case comparison::field_does_not_equal: |
1219 | { | 826 | { |
1220 | return filter(singleton_.filterField, comparison::field_equals, singleton_.compareField); | 827 | return filter( |
828 | ss.filterField, | ||
829 | comparison::field_equals, | ||
830 | mpark::get<field>(ss.data)); | ||
1221 | } | 831 | } |
1222 | } | 832 | } |
1223 | } | 833 | } |
1224 | 834 | ||
1225 | case type::group: | 835 | case type::group: |
1226 | { | 836 | { |
1227 | filter result(!group_.orlogic); | 837 | const group_type& gg = mpark::get<group_type>(variant_); |
838 | |||
839 | filter result(!gg.orlogic); | ||
1228 | 840 | ||
1229 | for (const filter& child : group_.children) | 841 | for (const filter& child : gg.children) |
1230 | { | 842 | { |
1231 | result += !child; | 843 | result += !child; |
1232 | } | 844 | } |
@@ -1236,7 +848,9 @@ namespace verbly { | |||
1236 | 848 | ||
1237 | case type::mask: | 849 | case type::mask: |
1238 | { | 850 | { |
1239 | return {mask_.name, mask_.internal, !*mask_.subfilter}; | 851 | const mask_type& mm = mpark::get<mask_type>(variant_); |
852 | |||
853 | return {mm.name, mm.internal, !*mm.subfilter}; | ||
1240 | } | 854 | } |
1241 | } | 855 | } |
1242 | } | 856 | } |
@@ -1264,24 +878,35 @@ namespace verbly { | |||
1264 | case type::mask: | 878 | case type::mask: |
1265 | { | 879 | { |
1266 | filter result(false); | 880 | filter result(false); |
1267 | result.group_.children.push_back(*this); | 881 | |
1268 | result.group_.children.push_back(std::move(condition)); | 882 | group_type& gg = mpark::get<group_type>(result.variant_); |
883 | |||
884 | gg.children.push_back(*this); | ||
885 | gg.children.push_back(std::move(condition)); | ||
1269 | 886 | ||
1270 | return result; | 887 | return result; |
1271 | } | 888 | } |
1272 | 889 | ||
1273 | case type::group: | 890 | case type::group: |
1274 | { | 891 | { |
1275 | if (group_.orlogic) | 892 | const group_type& og = mpark::get<group_type>(variant_); |
893 | |||
894 | if (og.orlogic) | ||
1276 | { | 895 | { |
1277 | filter result(false); | 896 | filter result(false); |
1278 | result.group_.children.push_back(*this); | 897 | |
1279 | result.group_.children.push_back(std::move(condition)); | 898 | group_type& gg = mpark::get<group_type>(result.variant_); |
899 | |||
900 | gg.children.push_back(*this); | ||
901 | gg.children.push_back(std::move(condition)); | ||
1280 | 902 | ||
1281 | return result; | 903 | return result; |
1282 | } else { | 904 | } else { |
1283 | filter result(*this); | 905 | filter result(*this); |
1284 | result.group_.children.push_back(std::move(condition)); | 906 | |
907 | group_type& gg = mpark::get<group_type>(result.variant_); | ||
908 | |||
909 | gg.children.push_back(std::move(condition)); | ||
1285 | 910 | ||
1286 | return result; | 911 | return result; |
1287 | } | 912 | } |
@@ -1302,24 +927,35 @@ namespace verbly { | |||
1302 | case type::mask: | 927 | case type::mask: |
1303 | { | 928 | { |
1304 | filter result(true); | 929 | filter result(true); |
1305 | result.group_.children.push_back(*this); | 930 | |
1306 | result.group_.children.push_back(std::move(condition)); | 931 | group_type& gg = mpark::get<group_type>(result.variant_); |
932 | |||
933 | gg.children.push_back(*this); | ||
934 | gg.children.push_back(std::move(condition)); | ||
1307 | 935 | ||
1308 | return result; | 936 | return result; |
1309 | } | 937 | } |
1310 | 938 | ||
1311 | case type::group: | 939 | case type::group: |
1312 | { | 940 | { |
1313 | if (!group_.orlogic) | 941 | const group_type& og = mpark::get<group_type>(variant_); |
942 | |||
943 | if (!og.orlogic) | ||
1314 | { | 944 | { |
1315 | filter result(true); | 945 | filter result(true); |
1316 | result.group_.children.push_back(*this); | 946 | |
1317 | result.group_.children.push_back(std::move(condition)); | 947 | group_type& gg = mpark::get<group_type>(result.variant_); |
948 | |||
949 | gg.children.push_back(*this); | ||
950 | gg.children.push_back(std::move(condition)); | ||
1318 | 951 | ||
1319 | return result; | 952 | return result; |
1320 | } else { | 953 | } else { |
1321 | filter result(*this); | 954 | filter result(*this); |
1322 | result.group_.children.push_back(std::move(condition)); | 955 | |
956 | group_type& gg = mpark::get<group_type>(result.variant_); | ||
957 | |||
958 | gg.children.push_back(std::move(condition)); | ||
1323 | 959 | ||
1324 | return result; | 960 | return result; |
1325 | } | 961 | } |
@@ -1344,6 +980,8 @@ namespace verbly { | |||
1344 | 980 | ||
1345 | case type::singleton: | 981 | case type::singleton: |
1346 | { | 982 | { |
983 | const singleton_type& ss = mpark::get<singleton_type>(variant_); | ||
984 | |||
1347 | // First, switch on the normalized context, and then switch on the | 985 | // First, switch on the normalized context, and then switch on the |
1348 | // current context. We recursively recontextualize by using the | 986 | // current context. We recursively recontextualize by using the |
1349 | // current filter as a subquery for a join such that the context of | 987 | // current filter as a subquery for a join such that the context of |
@@ -1361,7 +999,7 @@ namespace verbly { | |||
1361 | 999 | ||
1362 | case object::notion: | 1000 | case object::notion: |
1363 | { | 1001 | { |
1364 | switch (singleton_.filterField.getObject()) | 1002 | switch (ss.filterField.getObject()) |
1365 | { | 1003 | { |
1366 | case object::undefined: | 1004 | case object::undefined: |
1367 | case object::notion: | 1005 | case object::notion: |
@@ -1382,7 +1020,7 @@ namespace verbly { | |||
1382 | 1020 | ||
1383 | case object::word: | 1021 | case object::word: |
1384 | { | 1022 | { |
1385 | switch (singleton_.filterField.getObject()) | 1023 | switch (ss.filterField.getObject()) |
1386 | { | 1024 | { |
1387 | case object::notion: | 1025 | case object::notion: |
1388 | { | 1026 | { |
@@ -1404,13 +1042,14 @@ namespace verbly { | |||
1404 | case object::form: | 1042 | case object::form: |
1405 | case object::pronunciation: | 1043 | case object::pronunciation: |
1406 | { | 1044 | { |
1407 | return (verbly::word::forms(inflection::base) %= normalize(object::form)); | 1045 | return (verbly::word::forms(inflection::base) %= |
1046 | normalize(object::form)); | ||
1408 | } | 1047 | } |
1409 | } | 1048 | } |
1410 | 1049 | ||
1411 | case object::frame: | 1050 | case object::frame: |
1412 | { | 1051 | { |
1413 | switch (singleton_.filterField.getObject()) | 1052 | switch (ss.filterField.getObject()) |
1414 | { | 1053 | { |
1415 | case object::undefined: | 1054 | case object::undefined: |
1416 | case object::frame: | 1055 | case object::frame: |
@@ -1435,7 +1074,7 @@ namespace verbly { | |||
1435 | 1074 | ||
1436 | case object::part: | 1075 | case object::part: |
1437 | { | 1076 | { |
1438 | switch (singleton_.filterField.getObject()) | 1077 | switch (ss.filterField.getObject()) |
1439 | { | 1078 | { |
1440 | case object::undefined: | 1079 | case object::undefined: |
1441 | case object::part: | 1080 | case object::part: |
@@ -1456,14 +1095,15 @@ namespace verbly { | |||
1456 | 1095 | ||
1457 | case object::form: | 1096 | case object::form: |
1458 | { | 1097 | { |
1459 | switch (singleton_.filterField.getObject()) | 1098 | switch (ss.filterField.getObject()) |
1460 | { | 1099 | { |
1461 | case object::notion: | 1100 | case object::notion: |
1462 | case object::word: | 1101 | case object::word: |
1463 | case object::frame: | 1102 | case object::frame: |
1464 | case object::part: | 1103 | case object::part: |
1465 | { | 1104 | { |
1466 | return (verbly::form::words(inflection::base) %= normalize(object::word)); | 1105 | return (verbly::form::words(inflection::base) %= |
1106 | normalize(object::word)); | ||
1467 | } | 1107 | } |
1468 | 1108 | ||
1469 | case object::undefined: | 1109 | case object::undefined: |
@@ -1474,14 +1114,15 @@ namespace verbly { | |||
1474 | 1114 | ||
1475 | case object::pronunciation: | 1115 | case object::pronunciation: |
1476 | { | 1116 | { |
1477 | return (verbly::form::pronunciations %= normalize(object::pronunciation)); | 1117 | return (verbly::form::pronunciations %= |
1118 | normalize(object::pronunciation)); | ||
1478 | } | 1119 | } |
1479 | } | 1120 | } |
1480 | } | 1121 | } |
1481 | 1122 | ||
1482 | case object::pronunciation: | 1123 | case object::pronunciation: |
1483 | { | 1124 | { |
1484 | switch (singleton_.filterField.getObject()) | 1125 | switch (ss.filterField.getObject()) |
1485 | { | 1126 | { |
1486 | case object::notion: | 1127 | case object::notion: |
1487 | case object::word: | 1128 | case object::word: |
@@ -1489,7 +1130,8 @@ namespace verbly { | |||
1489 | case object::part: | 1130 | case object::part: |
1490 | case object::form: | 1131 | case object::form: |
1491 | { | 1132 | { |
1492 | return verbly::pronunciation::forms %= normalize(object::form); | 1133 | return verbly::pronunciation::forms %= |
1134 | normalize(object::form); | ||
1493 | } | 1135 | } |
1494 | 1136 | ||
1495 | case object::undefined: | 1137 | case object::undefined: |
@@ -1505,12 +1147,14 @@ namespace verbly { | |||
1505 | 1147 | ||
1506 | case type::group: | 1148 | case type::group: |
1507 | { | 1149 | { |
1508 | filter result(group_.orlogic); | 1150 | const group_type& gg = mpark::get<group_type>(variant_); |
1151 | |||
1152 | filter result(gg.orlogic); | ||
1509 | std::map<field, filter> positiveJoins; | 1153 | std::map<field, filter> positiveJoins; |
1510 | std::map<field, filter> negativeJoins; | 1154 | std::map<field, filter> negativeJoins; |
1511 | std::map<std::tuple<std::string, bool>, filter> masks; | 1155 | std::map<std::tuple<std::string, bool>, filter> masks; |
1512 | 1156 | ||
1513 | for (const filter& child : group_.children) | 1157 | for (const filter& child : gg.children) |
1514 | { | 1158 | { |
1515 | filter normalized = child.normalize(context); | 1159 | filter normalized = child.normalize(context); |
1516 | 1160 | ||
@@ -1521,37 +1165,44 @@ namespace verbly { | |||
1521 | { | 1165 | { |
1522 | case type::singleton: | 1166 | case type::singleton: |
1523 | { | 1167 | { |
1168 | singleton_type& normSing = | ||
1169 | mpark::get<singleton_type>(normalized.variant_); | ||
1170 | |||
1524 | switch (normalized.getComparison()) | 1171 | switch (normalized.getComparison()) |
1525 | { | 1172 | { |
1526 | case comparison::matches: | 1173 | case comparison::matches: |
1527 | { | 1174 | { |
1528 | if (!positiveJoins.count(normalized.singleton_.filterField)) | 1175 | if (!positiveJoins.count(normSing.filterField)) |
1529 | { | 1176 | { |
1530 | positiveJoins[normalized.getField()] = filter(group_.orlogic); | 1177 | positiveJoins[normalized.getField()] = filter(gg.orlogic); |
1531 | } | 1178 | } |
1532 | 1179 | ||
1533 | positiveJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); | 1180 | positiveJoins.at(normalized.getField()) += |
1181 | std::move(*mpark::get<rec_filter>(normSing.data)); | ||
1534 | 1182 | ||
1535 | break; | 1183 | break; |
1536 | } | 1184 | } |
1537 | 1185 | ||
1538 | case comparison::does_not_match: | 1186 | case comparison::does_not_match: |
1539 | { | 1187 | { |
1540 | if (!negativeJoins.count(normalized.singleton_.filterField)) | 1188 | if (!negativeJoins.count(normSing.filterField)) |
1541 | { | 1189 | { |
1542 | negativeJoins[normalized.getField()] = filter(!group_.orlogic); | 1190 | negativeJoins[normalized.getField()] = |
1191 | filter(!gg.orlogic); | ||
1543 | } | 1192 | } |
1544 | 1193 | ||
1545 | negativeJoins.at(normalized.getField()) += std::move(*normalized.singleton_.join); | 1194 | negativeJoins.at(normalized.getField()) += |
1195 | std::move(*mpark::get<rec_filter>(normSing.data)); | ||
1546 | 1196 | ||
1547 | break; | 1197 | break; |
1548 | } | 1198 | } |
1549 | 1199 | ||
1550 | case comparison::hierarchally_matches: | 1200 | case comparison::hierarchally_matches: |
1551 | { | 1201 | { |
1552 | if (group_.orlogic) | 1202 | if (gg.orlogic) |
1553 | { | 1203 | { |
1554 | positiveJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); | 1204 | positiveJoins[normalized.getField()] |= |
1205 | std::move(*mpark::get<rec_filter>(normSing.data)); | ||
1555 | } else { | 1206 | } else { |
1556 | result += std::move(normalized); | 1207 | result += std::move(normalized); |
1557 | } | 1208 | } |
@@ -1561,9 +1212,10 @@ namespace verbly { | |||
1561 | 1212 | ||
1562 | case comparison::does_not_hierarchally_match: | 1213 | case comparison::does_not_hierarchally_match: |
1563 | { | 1214 | { |
1564 | if (!group_.orlogic) | 1215 | if (!gg.orlogic) |
1565 | { | 1216 | { |
1566 | negativeJoins[normalized.getField()] |= std::move(*normalized.singleton_.join); | 1217 | negativeJoins[normalized.getField()] |= |
1218 | std::move(*mpark::get<rec_filter>(normSing.data)); | ||
1567 | } else { | 1219 | } else { |
1568 | result += std::move(normalized); | 1220 | result += std::move(normalized); |
1569 | } | 1221 | } |
@@ -1606,14 +1258,20 @@ namespace verbly { | |||
1606 | 1258 | ||
1607 | case type::mask: | 1259 | case type::mask: |
1608 | { | 1260 | { |
1609 | auto maskId = std::tie(normalized.mask_.name, normalized.mask_.internal); | 1261 | mask_type& normMask = |
1262 | mpark::get<mask_type>(normalized.variant_); | ||
1263 | |||
1264 | auto maskId = | ||
1265 | std::tie( | ||
1266 | normMask.name, | ||
1267 | normMask.internal); | ||
1610 | 1268 | ||
1611 | if (!masks.count(maskId)) | 1269 | if (!masks.count(maskId)) |
1612 | { | 1270 | { |
1613 | masks[maskId] = filter(group_.orlogic); | 1271 | masks[maskId] = filter(gg.orlogic); |
1614 | } | 1272 | } |
1615 | 1273 | ||
1616 | masks.at(maskId) += std::move(*normalized.mask_.subfilter); | 1274 | masks.at(maskId) += std::move(*normMask.subfilter); |
1617 | 1275 | ||
1618 | break; | 1276 | break; |
1619 | } | 1277 | } |
@@ -1625,7 +1283,8 @@ namespace verbly { | |||
1625 | const field& joinOn = mapping.first; | 1283 | const field& joinOn = mapping.first; |
1626 | filter& joinCondition = mapping.second; | 1284 | filter& joinCondition = mapping.second; |
1627 | 1285 | ||
1628 | result += (joinOn %= joinCondition.normalize(joinOn.getJoinObject())); | 1286 | result += |
1287 | (joinOn %= joinCondition.normalize(joinOn.getJoinObject())); | ||
1629 | } | 1288 | } |
1630 | 1289 | ||
1631 | for (auto& mapping : negativeJoins) | 1290 | for (auto& mapping : negativeJoins) |
@@ -1633,7 +1292,8 @@ namespace verbly { | |||
1633 | const field& joinOn = mapping.first; | 1292 | const field& joinOn = mapping.first; |
1634 | filter& joinCondition = mapping.second; | 1293 | filter& joinCondition = mapping.second; |
1635 | 1294 | ||
1636 | result += !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); | 1295 | result += |
1296 | !(joinOn %= joinCondition.normalize(joinOn.getJoinObject())); | ||
1637 | } | 1297 | } |
1638 | 1298 | ||
1639 | for (auto& mapping : masks) | 1299 | for (auto& mapping : masks) |
@@ -1650,7 +1310,12 @@ namespace verbly { | |||
1650 | 1310 | ||
1651 | case type::mask: | 1311 | case type::mask: |
1652 | { | 1312 | { |
1653 | return {mask_.name, mask_.internal, mask_.subfilter->normalize(context)}; | 1313 | const mask_type& mm = mpark::get<mask_type>(variant_); |
1314 | |||
1315 | return { | ||
1316 | mm.name, | ||
1317 | mm.internal, | ||
1318 | mm.subfilter->normalize(context)}; | ||
1654 | } | 1319 | } |
1655 | } | 1320 | } |
1656 | } | 1321 | } |
@@ -1668,8 +1333,10 @@ namespace verbly { | |||
1668 | 1333 | ||
1669 | case type::group: | 1334 | case type::group: |
1670 | { | 1335 | { |
1671 | filter result(group_.orlogic); | 1336 | const group_type& gg = mpark::get<group_type>(variant_); |
1672 | for (const filter& child : group_.children) | 1337 | |
1338 | filter result(gg.orlogic); | ||
1339 | for (const filter& child : gg.children) | ||
1673 | { | 1340 | { |
1674 | filter compactedChild = child.compact(); | 1341 | filter compactedChild = child.compact(); |
1675 | if (compactedChild.type_ != type::empty) | 1342 | if (compactedChild.type_ != type::empty) |
@@ -1678,12 +1345,14 @@ namespace verbly { | |||
1678 | } | 1345 | } |
1679 | } | 1346 | } |
1680 | 1347 | ||
1681 | if (result.group_.children.empty()) | 1348 | group_type& resGroup = mpark::get<group_type>(result.variant_); |
1349 | |||
1350 | if (resGroup.children.empty()) | ||
1682 | { | 1351 | { |
1683 | result = {}; | 1352 | result = {}; |
1684 | } else if (result.group_.children.size() == 1) | 1353 | } else if (resGroup.children.size() == 1) |
1685 | { | 1354 | { |
1686 | filter tempChild = std::move(result.group_.children.front()); | 1355 | filter tempChild = std::move(resGroup.children.front()); |
1687 | 1356 | ||
1688 | result = std::move(tempChild); | 1357 | result = std::move(tempChild); |
1689 | } | 1358 | } |
@@ -1693,13 +1362,18 @@ namespace verbly { | |||
1693 | 1362 | ||
1694 | case type::mask: | 1363 | case type::mask: |
1695 | { | 1364 | { |
1696 | filter subfilter = mask_.subfilter->compact(); | 1365 | const mask_type& mm = mpark::get<mask_type>(variant_); |
1366 | |||
1367 | filter subfilter = mm.subfilter->compact(); | ||
1697 | 1368 | ||
1698 | if (subfilter.type_ == type::empty) | 1369 | if (subfilter.type_ == type::empty) |
1699 | { | 1370 | { |
1700 | return {}; | 1371 | return {}; |
1701 | } else { | 1372 | } else { |
1702 | return {mask_.name, mask_.internal, std::move(subfilter)}; | 1373 | return { |
1374 | mm.name, | ||
1375 | mm.internal, | ||
1376 | std::move(subfilter)}; | ||
1703 | } | 1377 | } |
1704 | } | 1378 | } |
1705 | } | 1379 | } |
diff --git a/lib/filter.h b/lib/filter.h index 942fe18..7db2773 100644 --- a/lib/filter.h +++ b/lib/filter.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <list> | 4 | #include <list> |
5 | #include <string> | 5 | #include <string> |
6 | #include <memory> | 6 | #include <memory> |
7 | #include "../vendor/hkutil/vendor/variant.hpp" | ||
8 | #include "../vendor/hkutil/hkutil/recptr.h" | ||
7 | #include "field.h" | 9 | #include "field.h" |
8 | #include "enums.h" | 10 | #include "enums.h" |
9 | 11 | ||
@@ -11,6 +13,7 @@ namespace verbly { | |||
11 | 13 | ||
12 | class filter { | 14 | class filter { |
13 | public: | 15 | public: |
16 | |||
14 | enum class type { | 17 | enum class type { |
15 | empty, | 18 | empty, |
16 | singleton, | 19 | singleton, |
@@ -40,23 +43,6 @@ namespace verbly { | |||
40 | field_does_not_equal | 43 | field_does_not_equal |
41 | }; | 44 | }; |
42 | 45 | ||
43 | // Copy and move constructors | ||
44 | |||
45 | filter(const filter& other); | ||
46 | filter(filter&& other); | ||
47 | |||
48 | // Assignment | ||
49 | |||
50 | filter& operator=(filter other); | ||
51 | |||
52 | // Swap | ||
53 | |||
54 | friend void swap(filter& first, filter& second); | ||
55 | |||
56 | // Destructor | ||
57 | |||
58 | ~filter(); | ||
59 | |||
60 | // Accessors | 46 | // Accessors |
61 | 47 | ||
62 | type getType() const | 48 | type getType() const |
@@ -66,7 +52,7 @@ namespace verbly { | |||
66 | 52 | ||
67 | // Empty | 53 | // Empty |
68 | 54 | ||
69 | filter(); | 55 | filter() = default; |
70 | 56 | ||
71 | // Singleton | 57 | // Singleton |
72 | 58 | ||
@@ -140,29 +126,42 @@ namespace verbly { | |||
140 | filter compact() const; | 126 | filter compact() const; |
141 | 127 | ||
142 | private: | 128 | private: |
143 | union { | 129 | |
144 | struct { | 130 | using rec_filter = hatkirby::recptr<filter>; |
145 | field filterField; | 131 | |
146 | comparison filterType; | 132 | struct singleton_type { |
147 | union { | 133 | field filterField; |
148 | std::unique_ptr<filter> join; | 134 | comparison filterType; |
149 | std::string stringValue; | 135 | |
150 | int intValue; | 136 | mpark::variant< |
151 | bool boolValue; | 137 | mpark::monostate, |
152 | field compareField; | 138 | rec_filter, |
153 | }; | 139 | std::string, |
154 | } singleton_; | 140 | int, |
155 | struct { | 141 | bool, |
156 | std::list<filter> children; | 142 | field> data; |
157 | bool orlogic; | 143 | }; |
158 | } group_; | 144 | |
159 | struct { | 145 | struct group_type { |
160 | std::string name; | 146 | std::list<filter> children; |
161 | bool internal; | 147 | bool orlogic; |
162 | std::unique_ptr<filter> subfilter; | ||
163 | } mask_; | ||
164 | }; | 148 | }; |
149 | |||
150 | struct mask_type { | ||
151 | std::string name; | ||
152 | bool internal; | ||
153 | rec_filter subfilter; | ||
154 | }; | ||
155 | |||
156 | using variant_type = | ||
157 | mpark::variant< | ||
158 | mpark::monostate, | ||
159 | singleton_type, | ||
160 | group_type, | ||
161 | mask_type>; | ||
162 | |||
165 | type type_ = type::empty; | 163 | type type_ = type::empty; |
164 | variant_type variant_; | ||
166 | 165 | ||
167 | }; | 166 | }; |
168 | 167 | ||