summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-04-01 11:33:21 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-04-01 11:33:21 -0400
commit494e19b3c27e6a1eb63b39c245ad4024702e883b (patch)
treeeb3980c7652ed24b402b5424c085f36827037880 /lib
parent8b95516aef0cd4bd98e2592d6f247882dc88886a (diff)
downloadverbly-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.cpp1108
-rw-r--r--lib/filter.h77
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
11namespace verbly { 11namespace 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