Merge lp:~tapaal-dist-ctl/verifypn/ParserRefactoring_The_Correct_One into lp:~verifypn-maintainers/verifypn/trunk
- ParserRefactoring_The_Correct_One
- Merge into trunk
Proposed by
Søren Moss Nielsen
Status: | Merged |
---|---|
Approved by: | Jiri Srba |
Approved revision: | 114 |
Merged at revision: | 90 |
Proposed branch: | lp:~tapaal-dist-ctl/verifypn/ParserRefactoring_The_Correct_One |
Merge into: | lp:~verifypn-maintainers/verifypn/trunk |
Diff against target: |
12960 lines (+12094/-450) 22 files modified
CTL/CertainZeroFPA.cpp (+3/-23) CTL/CertainZeroFPA.h (+1/-1) CTL/DependencyGraph.cpp (+1/-1) CTL/DependencyGraph.h (+3/-2) CTL/LocalFPA.h (+1/-1) CTL/OnTheFlyDG.cpp (+352/-373) CTL/OnTheFlyDG.h (+6/-3) CTL/configuration.cpp (+5/-4) CTL/configuration.h (+5/-3) CTL/edge.cpp (+1/-1) CTLParser/CTLOptimizer.cpp (+77/-0) CTLParser/CTLOptimizer.h (+31/-0) CTLParser/CTLParser.cpp (+0/-1) CTLParser/CTLParser_v2.cpp (+508/-0) CTLParser/CTLParser_v2.h (+56/-0) CTLParser/CTLQuery.cpp (+159/-0) CTLParser/CTLQuery.h (+66/-0) CTLParser/EvaluateableProposition.cpp (+189/-0) CTLParser/EvaluateableProposition.h (+53/-0) Tests/unitTesting/catch.hpp (+10483/-0) VerifyPN.cpp (+93/-36) makefile.linux64 (+1/-1) |
To merge this branch: | bzr merge lp:~tapaal-dist-ctl/verifypn/ParserRefactoring_The_Correct_One |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jiri Srba | Approve | ||
Review via email: mp+295287@code.launchpad.net |
Commit message
Refactored parser for CTL queries.
Description of the change
The fixed requested have been implemented
To post a comment you must log in.
Revision history for this message
Jiri Srba (srba) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CTL/CertainZeroFPA.cpp' | |||
2 | --- CTL/CertainZeroFPA.cpp 2016-04-12 08:29:03 +0000 | |||
3 | +++ CTL/CertainZeroFPA.cpp 2016-05-20 07:41:18 +0000 | |||
4 | @@ -2,34 +2,12 @@ | |||
5 | 2 | 2 | ||
6 | 3 | namespace ctl{ | 3 | namespace ctl{ |
7 | 4 | 4 | ||
8 | 5 | bool preprocessQuery(CTLTree *f) { | ||
9 | 6 | |||
10 | 7 | bool isTemporal = f->quantifier == A || f->quantifier == E; | ||
11 | 8 | if (f->quantifier == AND || | ||
12 | 9 | f->quantifier == OR || | ||
13 | 10 | (f->quantifier == A && f->path == U) || | ||
14 | 11 | (f->quantifier == E && f->path == U)) { | ||
15 | 12 | //operand order guarantees subquery will be preprocessed | ||
16 | 13 | isTemporal = preprocessQuery(f->second) || isTemporal; | ||
17 | 14 | isTemporal = preprocessQuery(f->first) || isTemporal; | ||
18 | 15 | } | ||
19 | 16 | if (f->quantifier == NEG || | ||
20 | 17 | (f->path == G && (f->quantifier == A || f->quantifier == E)) || | ||
21 | 18 | (f->path == X && (f->quantifier == A || f->quantifier == E)) || | ||
22 | 19 | (f->path == F && (f->quantifier == A || f->quantifier == E))) { | ||
23 | 20 | isTemporal = preprocessQuery(f->first) || isTemporal; | ||
24 | 21 | } | ||
25 | 22 | f->isTemporal = isTemporal; | ||
26 | 23 | return isTemporal; | ||
27 | 24 | } | ||
28 | 25 | |||
29 | 26 | bool CertainZeroFPA::search(DependencyGraph &t_graph, AbstractSearchStrategy &W) | 5 | bool CertainZeroFPA::search(DependencyGraph &t_graph, AbstractSearchStrategy &W) |
30 | 27 | { | 6 | { |
31 | 28 | PriorityQueue N; | 7 | PriorityQueue N; |
32 | 29 | 8 | ||
33 | 30 | Configuration &v = t_graph.initialConfiguration(); | 9 | Configuration &v = t_graph.initialConfiguration(); |
34 | 31 | v.assignment = ZERO; | 10 | v.assignment = ZERO; |
35 | 32 | preprocessQuery(v.query); | ||
36 | 33 | 11 | ||
37 | 34 | for(Edge *e : t_graph.successors(v)){ | 12 | for(Edge *e : t_graph.successors(v)){ |
38 | 35 | W.push(e); | 13 | W.push(e); |
39 | @@ -48,6 +26,8 @@ | |||
40 | 48 | N.pop(); | 26 | N.pop(); |
41 | 49 | } | 27 | } |
42 | 50 | 28 | ||
43 | 29 | // e->edgePrinter(); | ||
44 | 30 | |||
45 | 51 | /*****************************************************************/ | 31 | /*****************************************************************/ |
46 | 52 | /*Data handling*/ | 32 | /*Data handling*/ |
47 | 53 | int targetONEassignments = 0; | 33 | int targetONEassignments = 0; |
48 | @@ -156,7 +136,7 @@ | |||
49 | 156 | e->processed = true; | 136 | e->processed = true; |
50 | 157 | } | 137 | } |
51 | 158 | 138 | ||
53 | 159 | //std::cout << "Final Assignment: " << v.assignment << " " << ((v.assignment == ONE) ? true : false) << std::endl; | 139 | // std::cout << "Final Assignment: " << v.assignment << " " << ((v.assignment == ONE) ? true : false) << std::endl; |
54 | 160 | return (v.assignment == ONE) ? true : false; | 140 | return (v.assignment == ONE) ? true : false; |
55 | 161 | } | 141 | } |
56 | 162 | 142 | ||
57 | 163 | 143 | ||
58 | === modified file 'CTL/CertainZeroFPA.h' | |||
59 | --- CTL/CertainZeroFPA.h 2016-02-08 18:27:31 +0000 | |||
60 | +++ CTL/CertainZeroFPA.h 2016-05-20 07:41:18 +0000 | |||
61 | @@ -19,7 +19,7 @@ | |||
62 | 19 | private: | 19 | private: |
63 | 20 | struct edge_prioritizer{ | 20 | struct edge_prioritizer{ |
64 | 21 | bool operator()(const Edge *lhs, const Edge *rhs) const { | 21 | bool operator()(const Edge *lhs, const Edge *rhs) const { |
66 | 22 | return (lhs->source->query->max_depth > rhs->source->query->max_depth); | 22 | return (lhs->source->query->Depth > rhs->source->query->Depth); //Changed to depth - was max depth |
67 | 23 | } | 23 | } |
68 | 24 | }; | 24 | }; |
69 | 25 | typedef std::priority_queue<Edge*, std::vector<Edge*>, ctl::CertainZeroFPA::edge_prioritizer> PriorityQueue; | 25 | typedef std::priority_queue<Edge*, std::vector<Edge*>, ctl::CertainZeroFPA::edge_prioritizer> PriorityQueue; |
70 | 26 | 26 | ||
71 | === modified file 'CTL/DependencyGraph.cpp' | |||
72 | --- CTL/DependencyGraph.cpp 2016-03-31 11:56:31 +0000 | |||
73 | +++ CTL/DependencyGraph.cpp 2016-05-20 07:41:18 +0000 | |||
74 | @@ -10,7 +10,7 @@ | |||
75 | 10 | _nplaces(t_net->numberOfPlaces()), | 10 | _nplaces(t_net->numberOfPlaces()), |
76 | 11 | _ntransitions(t_net->numberOfTransitions()){} | 11 | _ntransitions(t_net->numberOfTransitions()){} |
77 | 12 | 12 | ||
79 | 13 | void DependencyGraph::initialize(CTLTree &t_query){ | 13 | void DependencyGraph::initialize(CTLQuery &t_query){ |
80 | 14 | if(_query != NULL) | 14 | if(_query != NULL) |
81 | 15 | clear(false); | 15 | clear(false); |
82 | 16 | _query = &t_query; | 16 | _query = &t_query; |
83 | 17 | 17 | ||
84 | === modified file 'CTL/DependencyGraph.h' | |||
85 | --- CTL/DependencyGraph.h 2016-04-13 14:36:41 +0000 | |||
86 | +++ CTL/DependencyGraph.h 2016-05-20 07:41:18 +0000 | |||
87 | @@ -4,6 +4,7 @@ | |||
88 | 4 | #include "../PetriEngine/PetriNet.h" | 4 | #include "../PetriEngine/PetriNet.h" |
89 | 5 | #include "../PetriParse/PNMLParser.h" | 5 | #include "../PetriParse/PNMLParser.h" |
90 | 6 | #include "../CTLParser/CTLParser.h" | 6 | #include "../CTLParser/CTLParser.h" |
91 | 7 | #include "../CTLParser/CTLQuery.h" | ||
92 | 7 | #include <list> | 8 | #include <list> |
93 | 8 | #include <iostream> | 9 | #include <iostream> |
94 | 9 | 10 | ||
95 | @@ -28,10 +29,10 @@ | |||
96 | 28 | virtual int configuration_count() =0; | 29 | virtual int configuration_count() =0; |
97 | 29 | virtual int marking_count() =0; | 30 | virtual int marking_count() =0; |
98 | 30 | 31 | ||
100 | 31 | void initialize(CTLTree &t_query); | 32 | void initialize(CTLQuery &t_query); |
101 | 32 | 33 | ||
102 | 33 | protected: | 34 | protected: |
104 | 34 | CTLTree *_query = nullptr; | 35 | CTLQuery *_query = nullptr; |
105 | 35 | PetriEngine::PetriNet *_petriNet; | 36 | PetriEngine::PetriNet *_petriNet; |
106 | 36 | PetriEngine::MarkVal *_initialMarking; | 37 | PetriEngine::MarkVal *_initialMarking; |
107 | 37 | PNMLParser::InhibitorArcList _inhibitorArcs; | 38 | PNMLParser::InhibitorArcList _inhibitorArcs; |
108 | 38 | 39 | ||
109 | === modified file 'CTL/LocalFPA.h' | |||
110 | --- CTL/LocalFPA.h 2016-02-08 18:27:31 +0000 | |||
111 | +++ CTL/LocalFPA.h 2016-05-20 07:41:18 +0000 | |||
112 | @@ -19,7 +19,7 @@ | |||
113 | 19 | private: | 19 | private: |
114 | 20 | struct edge_prioritizer{ | 20 | struct edge_prioritizer{ |
115 | 21 | bool operator()(const Edge *lhs, const Edge *rhs) const { | 21 | bool operator()(const Edge *lhs, const Edge *rhs) const { |
117 | 22 | return (lhs->source->query->max_depth > rhs->source->query->max_depth); | 22 | return (lhs->source->query->Depth > rhs->source->query->Depth); //Changed to depth - was max depth |
118 | 23 | } | 23 | } |
119 | 24 | }; | 24 | }; |
120 | 25 | typedef std::priority_queue<Edge*, std::vector<Edge*>, ctl::LocalFPA::edge_prioritizer> PriorityQueue; | 25 | typedef std::priority_queue<Edge*, std::vector<Edge*>, ctl::LocalFPA::edge_prioritizer> PriorityQueue; |
121 | 26 | 26 | ||
122 | === modified file 'CTL/OnTheFlyDG.cpp' | |||
123 | --- CTL/OnTheFlyDG.cpp 2016-04-14 12:15:28 +0000 | |||
124 | +++ CTL/OnTheFlyDG.cpp 2016-05-20 07:41:18 +0000 | |||
125 | @@ -1,6 +1,7 @@ | |||
126 | 1 | #include "OnTheFlyDG.h" | 1 | #include "OnTheFlyDG.h" |
127 | 2 | 2 | ||
128 | 3 | #include <string.h> | 3 | #include <string.h> |
129 | 4 | #include <algorithm> | ||
130 | 4 | 5 | ||
131 | 5 | namespace ctl{ | 6 | namespace ctl{ |
132 | 6 | 7 | ||
133 | @@ -12,336 +13,322 @@ | |||
134 | 12 | } | 13 | } |
135 | 13 | 14 | ||
136 | 14 | 15 | ||
147 | 15 | bool OnTheFlyDG::fastEval(CTLTree &query, Marking &marking) { | 16 | bool OnTheFlyDG::fastEval(CTLQuery &query, Marking &marking) { |
148 | 16 | assert(!query.isTemporal); | 17 | assert(!query.IsTemporal); |
149 | 17 | if (query.quantifier == AND){ | 18 | if (query.GetQuantifier() == AND){ |
150 | 18 | return fastEval(*query.first, marking) && fastEval(*query.second, marking); | 19 | return fastEval(*query.GetFirstChild(), marking) && fastEval(*query.GetSecondChild(), marking); |
151 | 19 | } else if (query.quantifier == OR){ | 20 | } else if (query.GetQuantifier() == OR){ |
152 | 20 | return fastEval(*query.first, marking) || fastEval(*query.second, marking); | 21 | return fastEval(*query.GetFirstChild(), marking) || fastEval(*query.GetSecondChild(), marking); |
153 | 21 | } else if (query.quantifier == NEG){ | 22 | } else if (query.GetQuantifier() == NEG){ |
154 | 22 | return !fastEval(*query.first, marking); | 23 | bool result = fastEval(*query.GetFirstChild(), marking); |
155 | 23 | } else { | 24 | return !result; |
156 | 24 | return evaluateQuery(query, marking); | 25 | } else { |
157 | 26 | bool res = evaluateQuery(query, marking); | ||
158 | 27 | return res; | ||
159 | 25 | } | 28 | } |
160 | 26 | } | 29 | } |
161 | 27 | 30 | ||
162 | 28 | std::list<Edge *> OnTheFlyDG::successors(Configuration &v) | 31 | std::list<Edge *> OnTheFlyDG::successors(Configuration &v) |
163 | 29 | { | 32 | { |
164 | 30 | std::list<Edge*> succ; | 33 | std::list<Edge*> succ; |
305 | 31 | //All | 34 | CTLType query_type = v.query->GetQueryType(); |
306 | 32 | if(v.query->quantifier == A){ | 35 | if(query_type == EVAL){ |
307 | 33 | //All Until | 36 | //assert(false && "Someone told me, this was a bad place to be."); |
308 | 34 | if(v.query->path == U){ | 37 | if (evaluateQuery(*v.query, *v.marking)){ |
309 | 35 | //first deal with the right side | 38 | succ.push_back(new Edge(&v)); |
310 | 36 | Edge *right = NULL; | 39 | } |
311 | 37 | if (!v.query->second->isTemporal) { | 40 | } |
312 | 38 | //right side is not temporal, eval it right now! | 41 | else if (query_type == LOPERATOR){ |
313 | 39 | bool valid = fastEval(*(v.query->second), *(v.marking)); | 42 | if(v.query->GetQuantifier() == NEG){ |
314 | 40 | if (valid) { //satisfied, no need to go through successors | 43 | Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild())); |
315 | 41 | succ.push_back(new Edge(&v)); | 44 | Edge* e = new Edge(&v); |
316 | 42 | v.Successors = succ; | 45 | e->targets.push_back(c); |
317 | 43 | return succ; | 46 | succ.push_back(e); |
318 | 44 | } //else: It's not valid, no need to add any edge, just add successors | 47 | } |
319 | 45 | } else { | 48 | else if(v.query->GetQuantifier() == AND){ |
320 | 46 | //right side is temporal, we need to evaluate it as normal | 49 | //Check if left is false |
321 | 47 | Configuration* c = createConfiguration(*(v.marking), *(v.query->second)); | 50 | if(!v.query->GetFirstChild()->IsTemporal){ |
322 | 48 | right = new Edge(&v); | 51 | if(!fastEval(*(v.query->GetFirstChild()), *v.marking)) |
323 | 49 | right->targets.push_back(c); | 52 | //query cannot be satisfied, return empty succ set |
324 | 50 | } | 53 | return succ; |
325 | 51 | 54 | } | |
326 | 52 | //if we got here, either right side is temporal or it is not satisfied | 55 | |
327 | 53 | bool valid = false; | 56 | //check if right is false |
328 | 54 | Configuration *left = NULL; | 57 | if(!v.query->GetSecondChild()->IsTemporal){ |
329 | 55 | if (!v.query->first->isTemporal) { | 58 | if(!fastEval(*(v.query->GetSecondChild()), *v.marking)) |
330 | 56 | //left side is not temporal, eval it right now! | 59 | return succ; |
331 | 57 | valid = fastEval(*(v.query->first), *(v.marking)); | 60 | } |
332 | 58 | } else { | 61 | |
333 | 59 | //left side is temporal, include it in the edge | 62 | Edge *e = new Edge(&v); |
334 | 60 | left = createConfiguration(*(v.marking), *(v.query->first)); | 63 | |
335 | 61 | } | 64 | //If we get here, then either both propositions are true(should not be possible) |
336 | 62 | 65 | //Or a temporal operator and a true proposition | |
337 | 63 | if (valid || left != NULL) { //if left side is guaranteed to be not satisfied, skip successor generation | 66 | //Or both are temporal |
338 | 64 | auto targets = nextState (*(v.marking)); | 67 | if(v.query->GetFirstChild()->IsTemporal){ |
339 | 65 | 68 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetFirstChild()))); | |
340 | 66 | if(!targets.empty()){ | 69 | } |
341 | 67 | Edge* leftEdge = new Edge(&v); | 70 | if(v.query->GetSecondChild()->IsTemporal){ |
342 | 68 | 71 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetSecondChild()))); | |
343 | 69 | for(auto m : targets){ | 72 | } |
344 | 70 | Configuration* c = createConfiguration(*m, *(v.query)); | 73 | succ.push_back(e); |
345 | 71 | leftEdge->targets.push_back(c); | 74 | } |
346 | 72 | } | 75 | else if(v.query->GetQuantifier() == OR){ |
347 | 73 | if (left != NULL) { | 76 | //Check if left is true |
348 | 74 | leftEdge->targets.push_back(left); | 77 | if(!v.query->GetFirstChild()->IsTemporal){ |
349 | 75 | } | 78 | if(fastEval(*(v.query->GetFirstChild()), *v.marking)){ |
350 | 76 | succ.push_back(leftEdge); | 79 | //query is satisfied, return |
351 | 77 | } | 80 | succ.push_back(new Edge(&v)); |
352 | 78 | } //else: Left side is not temporal and it's false, no way to succeed there... | 81 | v.Successors = succ; |
353 | 79 | 82 | return succ; | |
354 | 80 | if (right != NULL) { | 83 | } |
355 | 81 | succ.push_back(right); | 84 | } |
356 | 82 | } | 85 | |
357 | 83 | 86 | if(!v.query->GetSecondChild()->IsTemporal){ | |
358 | 84 | 87 | if(fastEval(*(v.query->GetSecondChild()), *v.marking)){ | |
359 | 85 | } //All Until end | 88 | succ.push_back(new Edge(&v)); |
360 | 86 | 89 | v.Successors = succ; | |
361 | 87 | //All Next begin | 90 | return succ; |
362 | 88 | else if(v.query->path == X){ | 91 | } |
363 | 89 | auto targets = nextState(*v.marking); | 92 | } |
364 | 90 | if (v.query->first->isTemporal) { //regular check | 93 | |
365 | 91 | Edge* e = new Edge(&v); | 94 | //If we get here, either both propositions are false |
366 | 92 | for (auto m : targets){ | 95 | //Or one is false and one is temporal |
367 | 93 | Configuration* c = createConfiguration(*m, *(v.query->first)); | 96 | //Or both temporal |
368 | 94 | e->targets.push_back(c); | 97 | if(v.query->GetFirstChild()->IsTemporal){ |
369 | 95 | } | 98 | Edge *e = new Edge(&v); |
370 | 96 | succ.push_back(e); | 99 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetFirstChild()))); |
371 | 97 | } else { | 100 | succ.push_back(e); |
372 | 98 | bool allValid = true; | 101 | } |
373 | 99 | for (auto m : targets) { | 102 | if(v.query->GetSecondChild()->IsTemporal){ |
374 | 100 | bool valid = fastEval(*(v.query->first), *m); | 103 | Edge *e = new Edge(&v); |
375 | 101 | if (!valid) { | 104 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetSecondChild()))); |
376 | 102 | allValid = false; | 105 | succ.push_back(e); |
377 | 103 | break; | 106 | } |
378 | 104 | } | 107 | } |
379 | 105 | } | 108 | else{ |
380 | 106 | if (allValid) { | 109 | assert(false && "An unknown error occoured in the loperator-part of the successor generator"); |
381 | 107 | succ.push_back(new Edge(&v)); | 110 | } |
382 | 108 | v.Successors = succ; | 111 | } |
383 | 109 | return succ; | 112 | else if (query_type == PATHQEURY){ |
384 | 110 | } | 113 | if(v.query->GetQuantifier() == A){ |
385 | 111 | } | 114 | if (v.query->GetPath() == U){ |
386 | 112 | } //All Next End | 115 | Edge *right = NULL; |
387 | 113 | 116 | if (!v.query->GetSecondChild()->IsTemporal){ | |
388 | 114 | //All Finally start | 117 | //right side is not temporal, eval it right now! |
389 | 115 | else if(v.query->path == F){ | 118 | bool valid = fastEval(*(v.query->GetSecondChild()), *(v.marking)); |
390 | 116 | Edge *subquery = NULL; | 119 | if (valid) { //satisfied, no need to go through successors |
391 | 117 | if (!v.query->first->isTemporal) { | 120 | succ.push_back(new Edge(&v)); |
392 | 118 | bool valid = fastEval(*(v.query->first), *(v.marking)); | 121 | v.Successors = succ; |
393 | 119 | if (valid) { | 122 | return succ; |
394 | 120 | succ.push_back(new Edge(&v)); | 123 | }//else: It's not valid, no need to add any edge, just add successors |
395 | 121 | v.Successors = succ; | 124 | } |
396 | 122 | return succ; | 125 | else { |
397 | 123 | } | 126 | //right side is temporal, we need to evaluate it as normal |
398 | 124 | } else { | 127 | Configuration* c = createConfiguration(*(v.marking), *(v.query->GetSecondChild())); |
399 | 125 | subquery = new Edge(&v); | 128 | right = new Edge(&v); |
400 | 126 | Configuration* c = createConfiguration(*(v.marking), *(v.query->first)); | 129 | right->targets.push_back(c); |
401 | 127 | subquery->targets.push_back(c); | 130 | } |
402 | 128 | } | 131 | bool valid = false; |
263 | 129 | |||
264 | 130 | auto targets = nextState(*(v.marking)); | ||
265 | 131 | |||
266 | 132 | if(!targets.empty()){ | ||
267 | 133 | Edge* e1 = new Edge(&v); | ||
268 | 134 | |||
269 | 135 | for(auto m : targets){ | ||
270 | 136 | Configuration* c = createConfiguration(*m, *(v.query)); | ||
271 | 137 | e1->targets.push_back(c); | ||
272 | 138 | } | ||
273 | 139 | succ.push_back(e1); | ||
274 | 140 | } | ||
275 | 141 | |||
276 | 142 | if (subquery != NULL) { | ||
277 | 143 | succ.push_back(subquery); | ||
278 | 144 | } | ||
279 | 145 | |||
280 | 146 | }//All Finally end | ||
281 | 147 | } //All end | ||
282 | 148 | |||
283 | 149 | //Exists start | ||
284 | 150 | else if (v.query->quantifier == E){ | ||
285 | 151 | |||
286 | 152 | //Exists Untill start | ||
287 | 153 | if(v.query->path == U){ | ||
288 | 154 | Edge *right = NULL; | ||
289 | 155 | if (v.query->second->isTemporal) { | ||
290 | 156 | Configuration* c = createConfiguration(*(v.marking), *(v.query->second)); | ||
291 | 157 | right = new Edge(&v); | ||
292 | 158 | right->targets.push_back(c); | ||
293 | 159 | } else { | ||
294 | 160 | bool valid = fastEval(*(v.query->second), *(v.marking)); | ||
295 | 161 | if (valid) { | ||
296 | 162 | succ.push_back(new Edge(&v)); | ||
297 | 163 | v.Successors = succ; | ||
298 | 164 | return succ; | ||
299 | 165 | } // else: right condition is not satisfied, no need to add an edge | ||
300 | 166 | } | ||
301 | 167 | |||
302 | 168 | auto targets = nextState(*(v.marking)); | ||
303 | 169 | |||
304 | 170 | if(!targets.empty()){ | ||
403 | 171 | Configuration *left = NULL; | 132 | Configuration *left = NULL; |
407 | 172 | bool valid = false; | 133 | if (!v.query->GetFirstChild()->IsTemporal) { |
408 | 173 | if (v.query->first->isTemporal) { | 134 | //left side is not temporal, eval it right now! |
409 | 174 | left = createConfiguration(*(v.marking), *(v.query->first)); | 135 | valid = fastEval(*(v.query->GetFirstChild()), *(v.marking)); |
410 | 175 | } else { | 136 | } else { |
418 | 176 | valid = fastEval(*(v.query->first), *(v.marking)); | 137 | //left side is temporal, include it in the edge |
419 | 177 | } | 138 | left = createConfiguration(*(v.marking), *(v.query->GetFirstChild())); |
420 | 178 | if (left != NULL || valid) { | 139 | } |
421 | 179 | for(auto m : targets) { | 140 | if (valid || left != NULL) { //if left side is guaranteed to be not satisfied, skip successor generation |
422 | 180 | Edge* e = new Edge(&v); | 141 | auto targets = nextState (*(v.marking)); |
423 | 181 | Configuration* c1 = createConfiguration(*m, *(v.query)); | 142 | |
424 | 182 | e->targets.push_back(c1); | 143 | if(!targets.empty()){ |
425 | 144 | Edge* leftEdge = new Edge(&v); | ||
426 | 145 | |||
427 | 146 | for(auto m : targets){ | ||
428 | 147 | Configuration* c = createConfiguration(*m, *(v.query)); | ||
429 | 148 | leftEdge->targets.push_back(c); | ||
430 | 149 | } | ||
431 | 183 | if (left != NULL) { | 150 | if (left != NULL) { |
435 | 184 | e->targets.push_back(left); | 151 | leftEdge->targets.push_back(left); |
436 | 185 | } | 152 | } |
437 | 186 | succ.push_back(e); | 153 | succ.push_back(leftEdge); |
438 | 187 | } | 154 | } |
439 | 155 | } //else: Left side is not temporal and it's false, no way to succeed there... | ||
440 | 156 | |||
441 | 157 | if (right != NULL) { | ||
442 | 158 | succ.push_back(right); | ||
443 | 188 | } | 159 | } |
444 | 189 | } | 160 | } |
466 | 190 | 161 | else if(v.query->GetPath() == F){ | |
467 | 191 | if (right != NULL) { | 162 | Edge *subquery = NULL; |
468 | 192 | succ.push_back(right); | 163 | if (!v.query->GetFirstChild()->IsTemporal) { |
469 | 193 | } | 164 | bool valid = fastEval(*(v.query->GetFirstChild()), *(v.marking)); |
470 | 194 | 165 | if (valid) { | |
471 | 195 | } //Exists Until end | 166 | succ.push_back(new Edge(&v)); |
472 | 196 | 167 | v.Successors = succ; | |
473 | 197 | //Exists Next start | 168 | return succ; |
474 | 198 | else if(v.query->path == X){ | 169 | } |
454 | 199 | auto targets = nextState(*(v.marking)); | ||
455 | 200 | CTLTree* query = v.query->first; | ||
456 | 201 | |||
457 | 202 | if(!targets.empty()) | ||
458 | 203 | { | ||
459 | 204 | if (query->isTemporal) { //have to check, no way to skip that | ||
460 | 205 | for(auto m : targets){ | ||
461 | 206 | Edge* e = new Edge(&v); | ||
462 | 207 | Configuration* c = createConfiguration(*m, *query); | ||
463 | 208 | e->targets.push_back(c); | ||
464 | 209 | succ.push_back(e); | ||
465 | 210 | } | ||
475 | 211 | } else { | 170 | } else { |
483 | 212 | for(auto m : targets) { | 171 | subquery = new Edge(&v); |
484 | 213 | bool valid = fastEval(*query, *m); | 172 | Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild())); |
485 | 214 | if (valid) { | 173 | subquery->targets.push_back(c); |
486 | 215 | succ.push_back(new Edge(&v)); | 174 | } |
487 | 216 | v.Successors = succ; | 175 | |
488 | 217 | return succ; | 176 | auto targets = nextState(*(v.marking)); |
489 | 218 | } //else: It can't hold there, no need to create an edge | 177 | |
490 | 178 | if(!targets.empty()){ | ||
491 | 179 | Edge* e1 = new Edge(&v); | ||
492 | 180 | |||
493 | 181 | for(auto m : targets){ | ||
494 | 182 | Configuration* c = createConfiguration(*m, *(v.query)); | ||
495 | 183 | e1->targets.push_back(c); | ||
496 | 219 | } | 184 | } |
521 | 220 | } | 185 | succ.push_back(e1); |
522 | 221 | } | 186 | } |
523 | 222 | }//Exists Next end | 187 | |
524 | 223 | 188 | if (subquery != NULL) { | |
525 | 224 | //Exists Finally start | 189 | succ.push_back(subquery); |
526 | 225 | else if(v.query->path == F){ | 190 | } |
527 | 226 | Edge *subquery = NULL; | 191 | } |
528 | 227 | if (!v.query->first->isTemporal) { | 192 | else if(v.query->GetPath() == X){ |
529 | 228 | bool valid = fastEval(*(v.query->first), *(v.marking)); | 193 | auto targets = nextState(*v.marking); |
530 | 229 | if (valid) { | 194 | if (v.query->GetFirstChild()->IsTemporal) { //regular check |
507 | 230 | succ.push_back(new Edge(&v)); | ||
508 | 231 | v.Successors = succ; | ||
509 | 232 | return succ; | ||
510 | 233 | } | ||
511 | 234 | } else { | ||
512 | 235 | Configuration* c = createConfiguration(*(v.marking), *(v.query->first)); | ||
513 | 236 | subquery = new Edge(&v); | ||
514 | 237 | subquery->targets.push_back(c); | ||
515 | 238 | } | ||
516 | 239 | |||
517 | 240 | auto targets = nextState(*(v.marking)); | ||
518 | 241 | |||
519 | 242 | if(!targets.empty()){ | ||
520 | 243 | for(auto m : targets){ | ||
531 | 244 | Edge* e = new Edge(&v); | 195 | Edge* e = new Edge(&v); |
534 | 245 | Configuration* c = createConfiguration(*m, *(v.query)); | 196 | for (auto m : targets){ |
535 | 246 | e->targets.push_back(c); | 197 | Configuration* c = createConfiguration(*m, *(v.query->GetFirstChild())); |
536 | 198 | e->targets.push_back(c); | ||
537 | 199 | } | ||
538 | 247 | succ.push_back(e); | 200 | succ.push_back(e); |
630 | 248 | } | 201 | } else { |
631 | 249 | } | 202 | bool allValid = true; |
632 | 250 | 203 | for (auto m : targets) { | |
633 | 251 | if (subquery != NULL) { | 204 | bool valid = fastEval(*(v.query->GetFirstChild()), *m); |
634 | 252 | succ.push_back(subquery); | 205 | if (!valid) { |
635 | 253 | } | 206 | allValid = false; |
636 | 254 | }//Exists Finally end | 207 | break; |
637 | 255 | } //Exists end | 208 | } |
638 | 256 | 209 | } | |
639 | 257 | //And start | 210 | if (allValid) { |
640 | 258 | else if (v.query->quantifier == AND){ | 211 | succ.push_back(new Edge(&v)); |
641 | 259 | 212 | v.Successors = succ; | |
642 | 260 | //Check if left is false | 213 | return succ; |
643 | 261 | if(!v.query->first->isTemporal){ | 214 | } |
644 | 262 | if(!fastEval(*(v.query->first), *v.marking)) | 215 | } |
645 | 263 | //query cannot be satisfied, return empty succ set | 216 | } |
646 | 264 | return succ; | 217 | else if(v.query->GetPath() == G ){ |
647 | 265 | } | 218 | assert(false && "Path operator G had not been translated - Parse error detected in succ()"); |
648 | 266 | 219 | } | |
649 | 267 | //check if right is false | 220 | else |
650 | 268 | if(!v.query->second->isTemporal){ | 221 | assert(false && "An unknown error occoured in the successor generator"); |
651 | 269 | if(!fastEval(*(v.query->second), *v.marking)) | 222 | } |
652 | 270 | return succ; | 223 | else if(v.query->GetQuantifier() == E){ |
653 | 271 | } | 224 | if (v.query->GetPath() == U){ |
654 | 272 | 225 | Edge *right = NULL; | |
655 | 273 | Edge *e = new Edge(&v); | 226 | if (v.query->GetSecondChild()->IsTemporal) { |
656 | 274 | 227 | Configuration* c = createConfiguration(*(v.marking), *(v.query->GetSecondChild())); | |
657 | 275 | //If we get here, then either both propositions are true(should not be possible) | 228 | right = new Edge(&v); |
658 | 276 | //Or a temporal operator and a true proposition | 229 | right->targets.push_back(c); |
659 | 277 | //Or both are temporal | 230 | } else { |
660 | 278 | if(v.query->first->isTemporal){ | 231 | bool valid = fastEval(*(v.query->GetSecondChild()), *(v.marking)); |
661 | 279 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->first))); | 232 | if (valid) { |
662 | 280 | } | 233 | succ.push_back(new Edge(&v)); |
663 | 281 | if(v.query->second->isTemporal){ | 234 | v.Successors = succ; |
664 | 282 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->second))); | 235 | return succ; |
665 | 283 | } | 236 | } // else: right condition is not satisfied, no need to add an edge |
666 | 284 | succ.push_back(e); | 237 | } |
667 | 285 | } //And end | 238 | |
668 | 286 | 239 | auto targets = nextState(*(v.marking)); | |
669 | 287 | //Or start | 240 | |
670 | 288 | else if (v.query->quantifier == OR){ | 241 | if(!targets.empty()){ |
671 | 289 | 242 | Configuration *left = NULL; | |
672 | 290 | //Check if left is true | 243 | bool valid = false; |
673 | 291 | if(!v.query->first->isTemporal){ | 244 | if (v.query->GetFirstChild()->IsTemporal) { |
674 | 292 | if(fastEval(*(v.query->first), *v.marking)){ | 245 | left = createConfiguration(*(v.marking), *(v.query->GetFirstChild())); |
675 | 293 | //query is satisfied, return | 246 | } else { |
676 | 294 | succ.push_back(new Edge(&v)); | 247 | valid = fastEval(*(v.query->GetFirstChild()), *(v.marking)); |
677 | 295 | v.Successors = succ; | 248 | } |
678 | 296 | return succ; | 249 | if (left != NULL || valid) { |
679 | 297 | } | 250 | for(auto m : targets) { |
680 | 298 | } | 251 | Edge* e = new Edge(&v); |
681 | 299 | 252 | Configuration* c1 = createConfiguration(*m, *(v.query)); | |
682 | 300 | if(!v.query->second->isTemporal){ | 253 | e->targets.push_back(c1); |
683 | 301 | if(fastEval(*(v.query->second), *v.marking)){ | 254 | if (left != NULL) { |
684 | 302 | succ.push_back(new Edge(&v)); | 255 | e->targets.push_back(left); |
685 | 303 | v.Successors = succ; | 256 | } |
686 | 304 | return succ; | 257 | succ.push_back(e); |
687 | 305 | } | 258 | } |
688 | 306 | } | 259 | } |
689 | 307 | 260 | } | |
690 | 308 | //If we get here, either both propositions are false | 261 | |
691 | 309 | //Or one is false and one is temporal | 262 | if (right != NULL) { |
692 | 310 | //Or both temporal | 263 | succ.push_back(right); |
693 | 311 | if(v.query->first->isTemporal){ | 264 | } |
694 | 312 | Edge *e = new Edge(&v); | 265 | } |
695 | 313 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->first))); | 266 | else if(v.query->GetPath() == F){ |
696 | 314 | succ.push_back(e); | 267 | Edge *subquery = NULL; |
697 | 315 | } | 268 | if (!v.query->GetFirstChild()->IsTemporal) { |
698 | 316 | if(v.query->second->isTemporal){ | 269 | bool valid = fastEval(*(v.query->GetFirstChild()), *(v.marking)); |
699 | 317 | Edge *e = new Edge(&v); | 270 | if (valid) { |
700 | 318 | e->targets.push_back(createConfiguration(*v.marking, *(v.query->second))); | 271 | succ.push_back(new Edge(&v)); |
701 | 319 | succ.push_back(e); | 272 | v.Successors = succ; |
702 | 320 | } | 273 | return succ; |
703 | 321 | } //Or end | 274 | } |
704 | 322 | 275 | } else { | |
705 | 323 | //Negate start | 276 | Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild())); |
706 | 324 | else if (v.query->quantifier == NEG){ | 277 | subquery = new Edge(&v); |
707 | 325 | Configuration* c = createConfiguration(*(v.marking), *(v.query->first)); | 278 | subquery->targets.push_back(c); |
708 | 326 | Edge* e = new Edge(&v); | 279 | } |
709 | 327 | e->targets.push_back(c); | 280 | |
710 | 328 | succ.push_back(e); | 281 | auto targets = nextState(*(v.marking)); |
711 | 329 | } //Negate end | 282 | |
712 | 330 | 283 | if(!targets.empty()){ | |
713 | 331 | //Evaluate Query Begin | 284 | for(auto m : targets){ |
714 | 332 | else { | 285 | Edge* e = new Edge(&v); |
715 | 333 | //We should never get here anymore. | 286 | Configuration* c = createConfiguration(*m, *(v.query)); |
716 | 334 | //v.configPrinter(); | 287 | e->targets.push_back(c); |
717 | 335 | //assert(false); | 288 | succ.push_back(e); |
718 | 336 | if (evaluateQuery(*v.query, *v.marking)){ | 289 | } |
719 | 337 | succ.push_back(new Edge(&v)); | 290 | } |
720 | 338 | } | 291 | |
721 | 292 | if (subquery != NULL) { | ||
722 | 293 | succ.push_back(subquery); | ||
723 | 294 | } | ||
724 | 295 | } | ||
725 | 296 | else if(v.query->GetPath() == X){ | ||
726 | 297 | auto targets = nextState(*(v.marking)); | ||
727 | 298 | CTLQuery* query = v.query->GetFirstChild(); | ||
728 | 299 | |||
729 | 300 | if(!targets.empty()) | ||
730 | 301 | { | ||
731 | 302 | if (query->IsTemporal) { //have to check, no way to skip that | ||
732 | 303 | for(auto m : targets){ | ||
733 | 304 | Edge* e = new Edge(&v); | ||
734 | 305 | Configuration* c = createConfiguration(*m, *query); | ||
735 | 306 | e->targets.push_back(c); | ||
736 | 307 | succ.push_back(e); | ||
737 | 308 | } | ||
738 | 309 | } else { | ||
739 | 310 | for(auto m : targets) { | ||
740 | 311 | bool valid = fastEval(*query, *m); | ||
741 | 312 | if (valid) { | ||
742 | 313 | succ.push_back(new Edge(&v)); | ||
743 | 314 | v.Successors = succ; | ||
744 | 315 | return succ; | ||
745 | 316 | } //else: It can't hold there, no need to create an edge | ||
746 | 317 | } | ||
747 | 318 | } | ||
748 | 319 | } | ||
749 | 320 | } | ||
750 | 321 | else if(v.query->GetPath() == G ){ | ||
751 | 322 | assert(false && "Path operator G had not been translated - Parse error detected in succ()"); | ||
752 | 323 | } | ||
753 | 324 | else | ||
754 | 325 | assert(false && "An unknown error occoured in the successor generator"); | ||
755 | 326 | } | ||
756 | 327 | |||
757 | 339 | } | 328 | } |
759 | 340 | 329 | ||
760 | 341 | v.Successors = succ; | 330 | v.Successors = succ; |
761 | 342 | return succ; | 331 | return succ; |
762 | 343 | //computedSucc += succ.size(); | ||
763 | 344 | //std::cout << "-----------EDGES NOW : " << computedSucc << "\n" << std::flush; | ||
764 | 345 | } | 332 | } |
765 | 346 | 333 | ||
766 | 347 | Configuration &OnTheFlyDG::initialConfiguration() | 334 | Configuration &OnTheFlyDG::initialConfiguration() |
767 | @@ -351,69 +338,61 @@ | |||
768 | 351 | return *initial; | 338 | return *initial; |
769 | 352 | } | 339 | } |
770 | 353 | 340 | ||
776 | 354 | bool OnTheFlyDG::evaluateQuery(CTLTree &query, Marking &marking){ | 341 | bool OnTheFlyDG::evaluateQuery(CTLQuery &query, Marking &marking){ |
777 | 355 | 342 | assert(query.GetQueryType() == EVAL); | |
778 | 356 | bool result = false; | 343 | EvaluateableProposition *proposition = query.GetProposition(); |
779 | 357 | 344 | ||
780 | 358 | if (query.a.isFireable) { | 345 | if (proposition->GetPropositionType() == FIREABILITY) { |
781 | 359 | std::list<int> transistions = calculateFireableTransistions(marking); | 346 | std::list<int> transistions = calculateFireableTransistions(marking); |
798 | 360 | 347 | std::list<int>::iterator it; | |
799 | 361 | for (auto t : transistions) { | 348 | transistions.sort(); |
800 | 362 | int fs_transition = 0; | 349 | |
801 | 363 | for(fs_transition = 0; fs_transition < query.a.firesize; fs_transition++){ | 350 | for(const auto f : proposition->GetFireset()){ |
802 | 364 | int dpc_place = 0; | 351 | it = std::find(transistions.begin(), transistions.end(), f); |
803 | 365 | int truedependencyplaces = 0; | 352 | if(it != transistions.end()){ |
804 | 366 | for (dpc_place = 0; dpc_place < query.a.fireset[fs_transition].sizeofdenpencyplaces; dpc_place++){ | 353 | return true; |
789 | 367 | |||
790 | 368 | if((query.a.fireset[fs_transition].denpencyplaces[dpc_place].intSmaller - 1) < marking[query.a.fireset[fs_transition].denpencyplaces[dpc_place].placeLarger]){ | ||
791 | 369 | //std::cout<<_net->placeNames()[query->a.fireset[fs_transition].denpencyplaces[dpc_place].placeLarger]<<" is true"<<std::endl; | ||
792 | 370 | truedependencyplaces++; | ||
793 | 371 | } | ||
794 | 372 | } | ||
795 | 373 | if (truedependencyplaces == query.a.fireset[fs_transition].sizeofdenpencyplaces){ | ||
796 | 374 | result = true; | ||
797 | 375 | } | ||
805 | 376 | } | 354 | } |
806 | 377 | } | 355 | } |
846 | 378 | return result; | 356 | return false; |
847 | 379 | } | 357 | } |
848 | 380 | 358 | else if (proposition->GetPropositionType() == CARDINALITY){ | |
849 | 381 | ///std::cout<<"Evaluating cardinality... "<<std::endl; | 359 | int first_param = GetParamValue(proposition->GetFirstParameter(), marking); |
850 | 382 | // t_config.configPrinter(); | 360 | int second_param = GetParamValue(proposition->GetSecondParameter(), marking); |
851 | 383 | // std::cout<<"Less: "; | 361 | return EvalCardianlity(first_param, proposition->GetLoperator(), second_param); |
852 | 384 | int less = query.a.cardinality.intSmaller; | 362 | } |
853 | 385 | int greater= query.a.cardinality.intLarger; | 363 | else |
854 | 386 | if( less == -1 ){ | 364 | assert(false && "Incorrect query proposition type was attempted evaluated"); |
855 | 387 | int i = 0; | 365 | |
856 | 388 | less = 0; | 366 | } |
857 | 389 | for (i = 0; i < query.a.cardinality.placeSmaller.sizeoftokencount; i++){ | 367 | |
858 | 390 | int index = query.a.cardinality.placeSmaller.cardinality[i]; | 368 | int OnTheFlyDG::GetParamValue(CardinalityParameter *param, Marking& marking) { |
859 | 391 | less += marking[index]; | 369 | if(param->isPlace){ |
860 | 392 | // std::cout<<t_config.marking->Value()[index]<<" + "; | 370 | int res = 0; |
861 | 393 | } | 371 | for(int place : param->places_i){ |
862 | 394 | } | 372 | res = res + marking.Value()[place]; |
863 | 395 | // std::cout<<" = "<<less<<std::endl; | 373 | } |
864 | 396 | // std::cout<<"Greater: "; | 374 | return res; |
865 | 397 | if (greater == -1){ | 375 | } |
866 | 398 | int i = 0; | 376 | else{ |
867 | 399 | greater = 0; | 377 | return param->value; |
868 | 400 | // std::cout<<"::: Number of places: "<<query->a.cardinality.placeLarger.sizeoftokencount<<std::endl; | 378 | } |
869 | 401 | for (i = 0; i < query.a.cardinality.placeLarger.sizeoftokencount; i++){ | 379 | } |
870 | 402 | //std::cout<<"::::: i: "<<i<<std::endl; | 380 | |
871 | 403 | int index = query.a.cardinality.placeLarger.cardinality[i]; | 381 | bool OnTheFlyDG::EvalCardianlity(int a, LoperatorType lop, int b) { |
872 | 404 | //std::cout<<"::::: Index: "<<index<<" - Value: "<<t_config.marking->Value()[index]<<std::endl; | 382 | if(lop == EQ) |
873 | 405 | greater += marking[index]; | 383 | return a == b; |
874 | 406 | // std::cout<<t_config.marking->Value()[index]<<" + "; | 384 | else if (lop == LE) |
875 | 407 | // std::cout<<"::::: greater: "<<greater<<std::endl; | 385 | return a < b; |
876 | 408 | } | 386 | else if (lop == LEQ) |
877 | 409 | 387 | return a <= b; | |
878 | 410 | } | 388 | else if (lop == GR) |
879 | 411 | // std::cout<<" = "<<greater<<std::endl; | 389 | return a > b; |
880 | 412 | 390 | else if (lop == GRQ) | |
881 | 413 | result = less <= greater; | 391 | return a >= b; |
882 | 414 | // std::cout<<"... evaluation Done"<<std::endl; | 392 | assert(false && "Unsupported LOperator attemped evaluated"); |
883 | 415 | return result; | 393 | } |
884 | 416 | } | 394 | |
885 | 395 | |||
886 | 417 | 396 | ||
887 | 418 | int OnTheFlyDG::indexOfPlace(char *t_place){ | 397 | int OnTheFlyDG::indexOfPlace(char *t_place){ |
888 | 419 | for (int i = 0; i < _nplaces; i++) { | 398 | for (int i = 0; i < _nplaces; i++) { |
889 | @@ -522,7 +501,7 @@ | |||
890 | 522 | } | 501 | } |
891 | 523 | } | 502 | } |
892 | 524 | 503 | ||
894 | 525 | Configuration *OnTheFlyDG::createConfiguration(Marking &t_marking, CTLTree &t_query) | 504 | Configuration *OnTheFlyDG::createConfiguration(Marking &t_marking, CTLQuery &t_query) |
895 | 526 | { | 505 | { |
896 | 527 | for(Configuration* c : t_marking.successors){ | 506 | for(Configuration* c : t_marking.successors){ |
897 | 528 | if(c->query == &t_query) | 507 | if(c->query == &t_query) |
898 | @@ -534,7 +513,7 @@ | |||
899 | 534 | newConfig->query = &t_query; | 513 | newConfig->query = &t_query; |
900 | 535 | 514 | ||
901 | 536 | //Default value is false | 515 | //Default value is false |
903 | 537 | if(t_query.quantifier == NEG){ | 516 | if(t_query.GetQueryType() == LOPERATOR && t_query.GetQuantifier() == NEG){ |
904 | 538 | newConfig->IsNegated = true; | 517 | newConfig->IsNegated = true; |
905 | 539 | } | 518 | } |
906 | 540 | 519 | ||
907 | 541 | 520 | ||
908 | === modified file 'CTL/OnTheFlyDG.h' | |||
909 | --- CTL/OnTheFlyDG.h 2016-04-14 12:15:28 +0000 | |||
910 | +++ CTL/OnTheFlyDG.h 2016-05-20 07:41:18 +0000 | |||
911 | @@ -34,19 +34,22 @@ | |||
912 | 34 | // boost::hash<Configuration*>, | 34 | // boost::hash<Configuration*>, |
913 | 35 | // Configuration::Configuration_Equal_To> Configurations; | 35 | // Configuration::Configuration_Equal_To> Configurations; |
914 | 36 | bool isCompressing() {return _compressoption;} | 36 | bool isCompressing() {return _compressoption;} |
915 | 37 | private: | ||
916 | 38 | int GetParamValue(CardinalityParameter *param, Marking &marking); | ||
917 | 39 | bool EvalCardianlity(int a, LoperatorType lop, int b); | ||
918 | 37 | 40 | ||
919 | 38 | protected: | 41 | protected: |
920 | 39 | Marking *cached_marking = nullptr; | 42 | Marking *cached_marking = nullptr; |
921 | 40 | std::vector<Marking*> cached_successors; | 43 | std::vector<Marking*> cached_successors; |
922 | 41 | 44 | ||
924 | 42 | bool evaluateQuery(CTLTree &query, Marking &marking); | 45 | bool evaluateQuery(CTLQuery &query, Marking &marking); |
925 | 43 | bool _compressoption; | 46 | bool _compressoption; |
926 | 44 | int indexOfPlace(char *t_place); | 47 | int indexOfPlace(char *t_place); |
927 | 45 | std::vector<Marking *> nextState(Marking &t_marking); | 48 | std::vector<Marking *> nextState(Marking &t_marking); |
928 | 46 | std::list<int> calculateFireableTransistions(Marking &t_marking); | 49 | std::list<int> calculateFireableTransistions(Marking &t_marking); |
930 | 47 | Configuration *createConfiguration(Marking &t_marking, CTLTree &t_query); | 50 | Configuration *createConfiguration(Marking &t_marking, CTLQuery &t_query); |
931 | 48 | Marking *createMarking(const Marking &t_marking, int t_transition); | 51 | Marking *createMarking(const Marking &t_marking, int t_transition); |
933 | 49 | bool fastEval(CTLTree &query, Marking &marking); | 52 | bool fastEval(CTLQuery &query, Marking &marking); |
934 | 50 | 53 | ||
935 | 51 | void initCompressOption(); | 54 | void initCompressOption(); |
936 | 52 | 55 | ||
937 | 53 | 56 | ||
938 | === modified file 'CTL/configuration.cpp' | |||
939 | --- CTL/configuration.cpp 2015-12-08 07:25:27 +0000 | |||
940 | +++ CTL/configuration.cpp 2016-05-20 07:41:18 +0000 | |||
941 | @@ -1,8 +1,9 @@ | |||
942 | 1 | #include "configuration.h" | 1 | #include "configuration.h" |
943 | 2 | #include "../CTLParser/CTLParser_v2.h" | ||
944 | 2 | 3 | ||
945 | 3 | namespace ctl{ | 4 | namespace ctl{ |
946 | 4 | 5 | ||
948 | 5 | Configuration::Configuration(Marking * t_marking, CTLTree * t_query){ | 6 | Configuration::Configuration(Marking * t_marking, CTLQuery * t_query){ |
949 | 6 | marking = t_marking; | 7 | marking = t_marking; |
950 | 7 | query = t_query; | 8 | query = t_query; |
951 | 8 | } | 9 | } |
952 | @@ -36,13 +37,13 @@ | |||
953 | 36 | 37 | ||
954 | 37 | 38 | ||
955 | 38 | void Configuration::configPrinter(){ | 39 | void Configuration::configPrinter(){ |
957 | 39 | CTLParser ctlParser = CTLParser(); | 40 | CTLParser_v2 ctlParser = CTLParser_v2(); |
958 | 40 | int i = 0; | 41 | int i = 0; |
959 | 41 | std::cout << "Marking: "; | 42 | std::cout << "Marking: "; |
960 | 42 | marking->print(); | 43 | marking->print(); |
961 | 43 | std::cout << " Q: " << std::flush; | 44 | std::cout << " Q: " << std::flush; |
964 | 44 | ctlParser.printQuery(query); | 45 | std::cout << ctlParser.QueryToString(query)<<std::flush; |
965 | 45 | std::cout << " D: "<<query->depth << std::flush; | 46 | std::cout << " D: "<<query->Depth << std::flush; |
966 | 46 | std::cout << " Assign: " << assignment << std::flush; | 47 | std::cout << " Assign: " << assignment << std::flush; |
967 | 47 | 48 | ||
968 | 48 | std::cout << " NEG: " << IsNegated << "\n" << std::flush; | 49 | std::cout << " NEG: " << IsNegated << "\n" << std::flush; |
969 | 49 | 50 | ||
970 | === modified file 'CTL/configuration.h' | |||
971 | --- CTL/configuration.h 2016-04-12 10:22:19 +0000 | |||
972 | +++ CTL/configuration.h 2016-05-20 07:41:18 +0000 | |||
973 | @@ -2,6 +2,7 @@ | |||
974 | 2 | #define CONFIGURATION_H | 2 | #define CONFIGURATION_H |
975 | 3 | 3 | ||
976 | 4 | #include "../CTLParser/CTLParser.h" | 4 | #include "../CTLParser/CTLParser.h" |
977 | 5 | #include "../CTLParser/CTLQuery.h" | ||
978 | 5 | #include "marking.h" | 6 | #include "marking.h" |
979 | 6 | #include "edge.h" | 7 | #include "edge.h" |
980 | 7 | #include <list> | 8 | #include <list> |
981 | @@ -26,7 +27,7 @@ | |||
982 | 26 | }; | 27 | }; |
983 | 27 | 28 | ||
984 | 28 | Configuration(){} | 29 | Configuration(){} |
986 | 29 | Configuration(Marking* t_marking, CTLTree* t_query); | 30 | Configuration(Marking* t_marking, CTLQuery* t_query); |
987 | 30 | virtual ~Configuration(); | 31 | virtual ~Configuration(); |
988 | 31 | 32 | ||
989 | 32 | void removeSuccessor(Edge *t_successor); | 33 | void removeSuccessor(Edge *t_successor); |
990 | @@ -36,7 +37,7 @@ | |||
991 | 36 | bool operator!=(const Configuration &rhs) const {return !(*this == rhs);} | 37 | bool operator!=(const Configuration &rhs) const {return !(*this == rhs);} |
992 | 37 | 38 | ||
993 | 38 | Marking* marking; | 39 | Marking* marking; |
995 | 39 | CTLTree* query; | 40 | CTLQuery* query; |
996 | 40 | std::list<Edge*> Successors; | 41 | std::list<Edge*> Successors; |
997 | 41 | std::list<Edge*> DependencySet; | 42 | std::list<Edge*> DependencySet; |
998 | 42 | bool IsNegated = false; | 43 | bool IsNegated = false; |
999 | @@ -60,7 +61,8 @@ | |||
1000 | 60 | 61 | ||
1001 | 61 | return result;*/ | 62 | return result;*/ |
1002 | 62 | long xorHash = ((long) t_config.query) ^ ((long) t_config.marking); | 63 | long xorHash = ((long) t_config.query) ^ ((long) t_config.marking); |
1004 | 63 | return (size_t) (xorHash ^ (xorHash >> 32)); | 64 | //return (size_t) (xorHash ^ (xorHash >> 32)); <-- Only works for 64bit |
1005 | 65 | return (size_t) (xorHash ^ (xorHash >> ((sizeof(size_t)*8)/2))); | ||
1006 | 64 | } | 66 | } |
1007 | 65 | }; | 67 | }; |
1008 | 66 | template<> | 68 | template<> |
1009 | 67 | 69 | ||
1010 | === modified file 'CTL/edge.cpp' | |||
1011 | --- CTL/edge.cpp 2016-01-21 11:38:51 +0000 | |||
1012 | +++ CTL/edge.cpp 2016-05-20 07:41:18 +0000 | |||
1013 | @@ -34,7 +34,7 @@ | |||
1014 | 34 | int beta = 1; | 34 | int beta = 1; |
1015 | 35 | int gamma = 1; | 35 | int gamma = 1; |
1016 | 36 | 36 | ||
1018 | 37 | int dist = source->query->depth; | 37 | int dist = source->query->Depth; |
1019 | 38 | int breath = 0; | 38 | int breath = 0; |
1020 | 39 | int succ = source->Successors.size(); | 39 | int succ = source->Successors.size(); |
1021 | 40 | 40 | ||
1022 | 41 | 41 | ||
1023 | === added file 'CTLParser/CTLOptimizer.cpp' | |||
1024 | --- CTLParser/CTLOptimizer.cpp 1970-01-01 00:00:00 +0000 | |||
1025 | +++ CTLParser/CTLOptimizer.cpp 2016-05-20 07:41:18 +0000 | |||
1026 | @@ -0,0 +1,77 @@ | |||
1027 | 1 | /* | ||
1028 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1029 | 3 | * To change this template file, choose Tools | Templates | ||
1030 | 4 | * and open the template in the editor. | ||
1031 | 5 | */ | ||
1032 | 6 | |||
1033 | 7 | /* | ||
1034 | 8 | * File: CTLOptimizer.cpp | ||
1035 | 9 | * Author: mossns | ||
1036 | 10 | * | ||
1037 | 11 | * Created on April 28, 2016, 1:54 PM | ||
1038 | 12 | */ | ||
1039 | 13 | |||
1040 | 14 | #include "CTLOptimizer.h" | ||
1041 | 15 | |||
1042 | 16 | CTLOptimizer::CTLOptimizer() { | ||
1043 | 17 | } | ||
1044 | 18 | |||
1045 | 19 | CTLOptimizer::CTLOptimizer(const CTLOptimizer& orig) { | ||
1046 | 20 | } | ||
1047 | 21 | |||
1048 | 22 | CTLOptimizer::~CTLOptimizer() { | ||
1049 | 23 | } | ||
1050 | 24 | |||
1051 | 25 | CTLQuery* CTLOptimizer::Optimize(CTLQuery *query) { | ||
1052 | 26 | query = OptimizeNegation(query); | ||
1053 | 27 | return query; | ||
1054 | 28 | } | ||
1055 | 29 | |||
1056 | 30 | CTLQuery* CTLOptimizer::OptimizeNegation(CTLQuery *query) { | ||
1057 | 31 | CTLType query_type = query->GetQueryType(); | ||
1058 | 32 | if(query_type == EVAL){ | ||
1059 | 33 | return query; | ||
1060 | 34 | } | ||
1061 | 35 | else if (query_type == LOPERATOR){ | ||
1062 | 36 | if(query->GetQuantifier() != NEG){ | ||
1063 | 37 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1064 | 38 | query->SetSecondChild(OptimizeNegation(query->GetSecondChild())); | ||
1065 | 39 | } | ||
1066 | 40 | else {//Negation | ||
1067 | 41 | if(query->GetFirstChild()->GetQueryType() == LOPERATOR && query->GetFirstChild()->GetQuantifier() == NEG){ | ||
1068 | 42 | query = query->GetFirstChild()->GetFirstChild(); | ||
1069 | 43 | if(query->GetQueryType() == EVAL){ | ||
1070 | 44 | return query; | ||
1071 | 45 | } | ||
1072 | 46 | else if(query->GetQueryType() == LOPERATOR){ | ||
1073 | 47 | if(query->GetQuantifier() != NEG){ | ||
1074 | 48 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1075 | 49 | query->SetSecondChild(OptimizeNegation(query->GetSecondChild())); | ||
1076 | 50 | } | ||
1077 | 51 | else{ | ||
1078 | 52 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1079 | 53 | } | ||
1080 | 54 | } | ||
1081 | 55 | else if (query->GetQueryType() == PATHQEURY){ | ||
1082 | 56 | if (query->GetPath() == U){ | ||
1083 | 57 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1084 | 58 | query->SetSecondChild(OptimizeNegation(query->GetSecondChild())); | ||
1085 | 59 | } | ||
1086 | 60 | else{ | ||
1087 | 61 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1088 | 62 | } | ||
1089 | 63 | } | ||
1090 | 64 | } | ||
1091 | 65 | } | ||
1092 | 66 | } | ||
1093 | 67 | else if (query_type == PATHQEURY){ | ||
1094 | 68 | if (query->GetPath() == U){ | ||
1095 | 69 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1096 | 70 | query->SetSecondChild(OptimizeNegation(query->GetSecondChild())); | ||
1097 | 71 | } | ||
1098 | 72 | else{ | ||
1099 | 73 | query->SetFirstChild(OptimizeNegation(query->GetFirstChild())); | ||
1100 | 74 | } | ||
1101 | 75 | } | ||
1102 | 76 | return query; | ||
1103 | 77 | } | ||
1104 | 0 | 78 | ||
1105 | === added file 'CTLParser/CTLOptimizer.h' | |||
1106 | --- CTLParser/CTLOptimizer.h 1970-01-01 00:00:00 +0000 | |||
1107 | +++ CTLParser/CTLOptimizer.h 2016-05-20 07:41:18 +0000 | |||
1108 | @@ -0,0 +1,31 @@ | |||
1109 | 1 | /* | ||
1110 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1111 | 3 | * To change this template file, choose Tools | Templates | ||
1112 | 4 | * and open the template in the editor. | ||
1113 | 5 | */ | ||
1114 | 6 | |||
1115 | 7 | /* | ||
1116 | 8 | * File: CTLOptimizer.h | ||
1117 | 9 | * Author: mossns | ||
1118 | 10 | * | ||
1119 | 11 | * Created on April 28, 2016, 1:54 PM | ||
1120 | 12 | */ | ||
1121 | 13 | |||
1122 | 14 | #ifndef CTLOPTIMIZER_H | ||
1123 | 15 | #define CTLOPTIMIZER_H | ||
1124 | 16 | |||
1125 | 17 | #include "CTLQuery.h" | ||
1126 | 18 | |||
1127 | 19 | class CTLOptimizer { | ||
1128 | 20 | public: | ||
1129 | 21 | CTLOptimizer(); | ||
1130 | 22 | CTLOptimizer(const CTLOptimizer& orig); | ||
1131 | 23 | virtual ~CTLOptimizer(); | ||
1132 | 24 | |||
1133 | 25 | CTLQuery * Optimize(CTLQuery *query); | ||
1134 | 26 | private: | ||
1135 | 27 | CTLQuery * OptimizeNegation(CTLQuery *query); | ||
1136 | 28 | }; | ||
1137 | 29 | |||
1138 | 30 | #endif /* CTLOPTIMIZER_H */ | ||
1139 | 31 | |||
1140 | 0 | 32 | ||
1141 | === modified file 'CTLParser/CTLParser.cpp' | |||
1142 | --- CTLParser/CTLParser.cpp 2016-02-11 13:26:44 +0000 | |||
1143 | +++ CTLParser/CTLParser.cpp 2016-05-20 07:41:18 +0000 | |||
1144 | @@ -35,7 +35,6 @@ | |||
1145 | 35 | #ifdef DEBUG | 35 | #ifdef DEBUG |
1146 | 36 | std::cout << "Creating doc\n" << std::flush; | 36 | std::cout << "Creating doc\n" << std::flush; |
1147 | 37 | #endif | 37 | #endif |
1148 | 38 | // CTLquery ctlquery; | ||
1149 | 39 | xml_document<> doc; | 38 | xml_document<> doc; |
1150 | 40 | xml_node<> * root_node; | 39 | xml_node<> * root_node; |
1151 | 41 | 40 | ||
1152 | 42 | 41 | ||
1153 | === added file 'CTLParser/CTLParser_v2.cpp' | |||
1154 | --- CTLParser/CTLParser_v2.cpp 1970-01-01 00:00:00 +0000 | |||
1155 | +++ CTLParser/CTLParser_v2.cpp 2016-05-20 07:41:18 +0000 | |||
1156 | @@ -0,0 +1,508 @@ | |||
1157 | 1 | /* | ||
1158 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1159 | 3 | * To change this template file, choose Tools | Templates | ||
1160 | 4 | * and open the template in the editor. | ||
1161 | 5 | */ | ||
1162 | 6 | |||
1163 | 7 | /* | ||
1164 | 8 | * File: CTLParser_v2.cpp | ||
1165 | 9 | * Author: mossns | ||
1166 | 10 | * | ||
1167 | 11 | * Created on April 22, 2016, 10:15 AM | ||
1168 | 12 | */ | ||
1169 | 13 | |||
1170 | 14 | #include "rapidxml-1.13/rapidxml.hpp" | ||
1171 | 15 | #include "CTLParser_v2.h" | ||
1172 | 16 | #include "CTLQuery.h" | ||
1173 | 17 | #include "EvaluateableProposition.h" | ||
1174 | 18 | #include <algorithm> | ||
1175 | 19 | |||
1176 | 20 | |||
1177 | 21 | using namespace rapidxml; | ||
1178 | 22 | |||
1179 | 23 | CTLParser_v2::CTLParser_v2() { | ||
1180 | 24 | } | ||
1181 | 25 | |||
1182 | 26 | CTLParser_v2::CTLParser_v2(const CTLParser_v2& orig) { | ||
1183 | 27 | } | ||
1184 | 28 | |||
1185 | 29 | CTLParser_v2::~CTLParser_v2() { | ||
1186 | 30 | } | ||
1187 | 31 | |||
1188 | 32 | std::string CTLParser_v2::QueryToString(CTLQuery* query){ | ||
1189 | 33 | if(query->GetQuantifier() == EMPTY && query->GetPath() == pError){ | ||
1190 | 34 | return query->GetAtom(); | ||
1191 | 35 | } | ||
1192 | 36 | else if (query->GetPath() == pError){ | ||
1193 | 37 | Quantifier q = query->GetQuantifier(); | ||
1194 | 38 | if (q == NEG){ | ||
1195 | 39 | return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")"; | ||
1196 | 40 | } | ||
1197 | 41 | else if (q == AND || q == OR){ | ||
1198 | 42 | return "(" + QueryToString(query->GetFirstChild()) + query->ToString() + QueryToString(query->GetSecondChild()) + ")"; | ||
1199 | 43 | } | ||
1200 | 44 | else assert(false && "Could not print unknown logical query operator"); | ||
1201 | 45 | } | ||
1202 | 46 | else if(query->GetQuantifier() == A || query->GetQuantifier() == E){ | ||
1203 | 47 | if(query->GetPath() == U){ | ||
1204 | 48 | return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")Reach(" + QueryToString(query->GetSecondChild()) + ")"; | ||
1205 | 49 | } | ||
1206 | 50 | else{ | ||
1207 | 51 | return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")"; | ||
1208 | 52 | } | ||
1209 | 53 | } | ||
1210 | 54 | else assert(false && "Could not print unknown query type"); | ||
1211 | 55 | } | ||
1212 | 56 | |||
1213 | 57 | CTLQuery* CTLParser_v2::FormatQuery(CTLQuery* query, PetriEngine::PetriNet *net){ | ||
1214 | 58 | query = FillAtom(query,net); | ||
1215 | 59 | query = ConvertAG(query); | ||
1216 | 60 | query = ConvertEG(query); | ||
1217 | 61 | IdSetting(query, 0); | ||
1218 | 62 | query = TemporalSetting(query); | ||
1219 | 63 | //assert(false); | ||
1220 | 64 | return query; | ||
1221 | 65 | } | ||
1222 | 66 | |||
1223 | 67 | CTLQuery* CTLParser_v2::TemporalSetting(CTLQuery* query) { | ||
1224 | 68 | CTLType query_type = query->GetQueryType(); | ||
1225 | 69 | if(query_type == EVAL){ | ||
1226 | 70 | assert(!query->IsTemporal); | ||
1227 | 71 | return query; | ||
1228 | 72 | } | ||
1229 | 73 | else if (query_type == LOPERATOR){ | ||
1230 | 74 | Quantifier quan = query->GetQuantifier(); | ||
1231 | 75 | if(quan != NEG){ | ||
1232 | 76 | query->SetFirstChild(TemporalSetting(query->GetFirstChild())); | ||
1233 | 77 | query->SetSecondChild(TemporalSetting(query->GetSecondChild())); | ||
1234 | 78 | query->IsTemporal = (query->GetFirstChild()->IsTemporal || query->GetSecondChild()->IsTemporal); | ||
1235 | 79 | } | ||
1236 | 80 | else{ | ||
1237 | 81 | query->SetFirstChild(TemporalSetting(query->GetFirstChild())); | ||
1238 | 82 | query->IsTemporal = (query->GetFirstChild()->IsTemporal); | ||
1239 | 83 | } | ||
1240 | 84 | return query; | ||
1241 | 85 | } | ||
1242 | 86 | else if (query_type == PATHQEURY){ | ||
1243 | 87 | assert(query->IsTemporal); | ||
1244 | 88 | if (query->GetPath() == U){ | ||
1245 | 89 | query->SetFirstChild(TemporalSetting(query->GetFirstChild())); | ||
1246 | 90 | query->SetSecondChild(TemporalSetting(query->GetSecondChild())); | ||
1247 | 91 | } | ||
1248 | 92 | else{ | ||
1249 | 93 | query->SetFirstChild(TemporalSetting(query->GetFirstChild())); | ||
1250 | 94 | } | ||
1251 | 95 | return query; | ||
1252 | 96 | } else { | ||
1253 | 97 | //this should not happen | ||
1254 | 98 | assert(false); | ||
1255 | 99 | } | ||
1256 | 100 | } | ||
1257 | 101 | |||
1258 | 102 | //returns next available id | ||
1259 | 103 | int CTLParser_v2::IdSetting(CTLQuery *query, int id) | ||
1260 | 104 | { | ||
1261 | 105 | query->Id = id; | ||
1262 | 106 | CTLType query_type = query->GetQueryType(); | ||
1263 | 107 | if(query_type == EVAL){ | ||
1264 | 108 | assert(!query->IsTemporal); | ||
1265 | 109 | query->Depth = 0; | ||
1266 | 110 | return id + 1; | ||
1267 | 111 | } | ||
1268 | 112 | else if (query_type == LOPERATOR){ | ||
1269 | 113 | Quantifier quan = query->GetQuantifier(); | ||
1270 | 114 | if(quan != NEG){ | ||
1271 | 115 | int afterFirst = IdSetting(query->GetFirstChild(), id + 1); | ||
1272 | 116 | int afterSecond = IdSetting(query->GetSecondChild(), afterFirst); | ||
1273 | 117 | query->Depth = std::max(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth) + 1; | ||
1274 | 118 | return afterSecond; | ||
1275 | 119 | } | ||
1276 | 120 | else{ | ||
1277 | 121 | int afterFirst = IdSetting(query->GetFirstChild(), id + 1); | ||
1278 | 122 | query->Depth = query->GetFirstChild()->Depth + 1; | ||
1279 | 123 | return afterFirst; | ||
1280 | 124 | } | ||
1281 | 125 | } | ||
1282 | 126 | else if (query_type == PATHQEURY){ | ||
1283 | 127 | assert(query->IsTemporal); | ||
1284 | 128 | if (query->GetPath() == U){ | ||
1285 | 129 | int afterFirst = IdSetting(query->GetFirstChild(), id + 1); | ||
1286 | 130 | int afterSecond = IdSetting(query->GetSecondChild(), afterFirst); | ||
1287 | 131 | query->Depth = std::max(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth) + 1; | ||
1288 | 132 | return afterSecond; | ||
1289 | 133 | } | ||
1290 | 134 | else{ | ||
1291 | 135 | int afterFirst = IdSetting(query->GetFirstChild(), id + 1); | ||
1292 | 136 | query->Depth = query->GetFirstChild()->Depth + 1; | ||
1293 | 137 | return afterFirst; | ||
1294 | 138 | } | ||
1295 | 139 | } else { | ||
1296 | 140 | //this should not happen | ||
1297 | 141 | assert(false); | ||
1298 | 142 | } | ||
1299 | 143 | } | ||
1300 | 144 | |||
1301 | 145 | |||
1302 | 146 | CTLQuery* CTLParser_v2::FillAtom(CTLQuery* query, PetriEngine::PetriNet *net) { | ||
1303 | 147 | CTLType query_type = query->GetQueryType(); | ||
1304 | 148 | if(query_type == EVAL){ | ||
1305 | 149 | EvaluateableProposition *proposition = new EvaluateableProposition(query->GetAtom(), net); | ||
1306 | 150 | query->SetProposition(proposition); | ||
1307 | 151 | return query; | ||
1308 | 152 | } | ||
1309 | 153 | else if (query_type == LOPERATOR){ | ||
1310 | 154 | Quantifier quan = query->GetQuantifier(); | ||
1311 | 155 | if(quan != NEG){ | ||
1312 | 156 | FillAtom(query->GetFirstChild(),net); | ||
1313 | 157 | FillAtom(query->GetSecondChild(),net); | ||
1314 | 158 | } | ||
1315 | 159 | else{ | ||
1316 | 160 | FillAtom(query->GetFirstChild(),net); | ||
1317 | 161 | } | ||
1318 | 162 | return query; | ||
1319 | 163 | } | ||
1320 | 164 | else if (query_type == PATHQEURY){ | ||
1321 | 165 | if (query->GetPath() == U){ | ||
1322 | 166 | FillAtom(query->GetFirstChild(),net); | ||
1323 | 167 | FillAtom(query->GetSecondChild(),net); | ||
1324 | 168 | } | ||
1325 | 169 | else{ | ||
1326 | 170 | FillAtom(query->GetFirstChild(),net); | ||
1327 | 171 | } | ||
1328 | 172 | return query; | ||
1329 | 173 | } | ||
1330 | 174 | else assert(false && "Could not traverse unknown query type"); | ||
1331 | 175 | } | ||
1332 | 176 | |||
1333 | 177 | CTLQuery* CTLParser_v2::ConvertAG(CTLQuery* query) { | ||
1334 | 178 | CTLType query_type = query->GetQueryType(); | ||
1335 | 179 | if(query_type == EVAL){ | ||
1336 | 180 | return query; | ||
1337 | 181 | } | ||
1338 | 182 | else if (query_type == LOPERATOR){ | ||
1339 | 183 | Quantifier quan = query->GetQuantifier(); | ||
1340 | 184 | if(quan != NEG){ | ||
1341 | 185 | query->SetFirstChild(ConvertAG(query->GetFirstChild())); | ||
1342 | 186 | query->SetSecondChild(ConvertAG(query->GetSecondChild())); | ||
1343 | 187 | } | ||
1344 | 188 | else{ | ||
1345 | 189 | query->SetFirstChild(ConvertAG(query->GetFirstChild())); | ||
1346 | 190 | } | ||
1347 | 191 | return query; | ||
1348 | 192 | } | ||
1349 | 193 | else if (query_type == PATHQEURY){ | ||
1350 | 194 | if (query->GetPath() == U){ | ||
1351 | 195 | query->SetFirstChild(ConvertAG(query->GetFirstChild())); | ||
1352 | 196 | query->SetSecondChild(ConvertAG(query->GetSecondChild())); | ||
1353 | 197 | } | ||
1354 | 198 | else if (query->GetQuantifier() == A && query->GetPath() == G){ | ||
1355 | 199 | |||
1356 | 200 | CTLQuery *neg_two = new CTLQuery(NEG, pError, false, ""); | ||
1357 | 201 | neg_two->SetFirstChild(query->GetFirstChild()); | ||
1358 | 202 | CTLQuery *ef_q = new CTLQuery(E, F, false, ""); | ||
1359 | 203 | ef_q->SetFirstChild(neg_two); | ||
1360 | 204 | CTLQuery *neg_one = new CTLQuery(NEG, pError, false, ""); | ||
1361 | 205 | neg_one->SetFirstChild(ef_q); | ||
1362 | 206 | query = neg_one; | ||
1363 | 207 | |||
1364 | 208 | query->SetFirstChild(ConvertAG(query->GetFirstChild())); | ||
1365 | 209 | } | ||
1366 | 210 | else{ | ||
1367 | 211 | query->SetFirstChild(ConvertAG(query->GetFirstChild())); | ||
1368 | 212 | } | ||
1369 | 213 | return query; | ||
1370 | 214 | } | ||
1371 | 215 | else assert(false && "Could not traverse unknown query type"); | ||
1372 | 216 | } | ||
1373 | 217 | |||
1374 | 218 | CTLQuery* CTLParser_v2::ConvertEG(CTLQuery* query) { | ||
1375 | 219 | CTLType query_type = query->GetQueryType(); | ||
1376 | 220 | if(query_type == EVAL){ | ||
1377 | 221 | return query; | ||
1378 | 222 | } | ||
1379 | 223 | else if (query_type == LOPERATOR){ | ||
1380 | 224 | Quantifier quan = query->GetQuantifier(); | ||
1381 | 225 | if(quan != NEG){ | ||
1382 | 226 | query->SetFirstChild(ConvertEG(query->GetFirstChild())); | ||
1383 | 227 | query->SetSecondChild(ConvertEG(query->GetSecondChild())); | ||
1384 | 228 | } | ||
1385 | 229 | else{ | ||
1386 | 230 | query->SetFirstChild(ConvertEG(query->GetFirstChild())); | ||
1387 | 231 | } | ||
1388 | 232 | return query; | ||
1389 | 233 | } | ||
1390 | 234 | else if (query_type == PATHQEURY){ | ||
1391 | 235 | if (query->GetPath() == U){ | ||
1392 | 236 | query->SetFirstChild(ConvertEG(query->GetFirstChild())); | ||
1393 | 237 | query->SetSecondChild(ConvertEG(query->GetSecondChild())); | ||
1394 | 238 | } | ||
1395 | 239 | else if (query->GetQuantifier() == E && query->GetPath() == G){ | ||
1396 | 240 | |||
1397 | 241 | CTLQuery *neg_two = new CTLQuery(NEG, pError, false, ""); | ||
1398 | 242 | neg_two->SetFirstChild(query->GetFirstChild()); | ||
1399 | 243 | CTLQuery *ef_q = new CTLQuery(A, F, false, ""); | ||
1400 | 244 | ef_q->SetFirstChild(neg_two); | ||
1401 | 245 | CTLQuery *neg_one = new CTLQuery(NEG, pError, false, ""); | ||
1402 | 246 | neg_one->SetFirstChild(ef_q); | ||
1403 | 247 | query = neg_one; | ||
1404 | 248 | |||
1405 | 249 | query->SetFirstChild(ConvertEG(query->GetFirstChild())); | ||
1406 | 250 | } | ||
1407 | 251 | else{ | ||
1408 | 252 | query->SetFirstChild(ConvertEG(query->GetFirstChild())); | ||
1409 | 253 | } | ||
1410 | 254 | return query; | ||
1411 | 255 | } | ||
1412 | 256 | else assert(false && "Could not traverse unknown query type"); | ||
1413 | 257 | } | ||
1414 | 258 | |||
1415 | 259 | |||
1416 | 260 | CTLQuery * CTLParser_v2::ParseXMLQuery(std::vector<char> buffer, int query_number) { | ||
1417 | 261 | #ifdef DEBUG | ||
1418 | 262 | std::cout << "Creating doc\n" << std::flush; | ||
1419 | 263 | #endif | ||
1420 | 264 | xml_document<> doc; | ||
1421 | 265 | xml_node<> * root_node; | ||
1422 | 266 | |||
1423 | 267 | #ifdef DEBUG | ||
1424 | 268 | std::cout << "Size of Path enum: " << sizeof(Path)*8 <<"\n"; | ||
1425 | 269 | #endif | ||
1426 | 270 | doc.parse<0>(&buffer[0]); | ||
1427 | 271 | |||
1428 | 272 | |||
1429 | 273 | #ifdef DEBUG | ||
1430 | 274 | std::cout << "First node id: " << doc.first_node()->name() << std::endl; | ||
1431 | 275 | #endif | ||
1432 | 276 | |||
1433 | 277 | root_node = doc.first_node(); | ||
1434 | 278 | |||
1435 | 279 | #ifdef Analysis | ||
1436 | 280 | std::cout << "\nAnalysis:: Queries:" << std::endl; | ||
1437 | 281 | #endif | ||
1438 | 282 | int i = 1; | ||
1439 | 283 | for (xml_node<> * property_node = root_node->first_node("property"); property_node; property_node = property_node->next_sibling()) { | ||
1440 | 284 | if(i == query_number){ | ||
1441 | 285 | xml_node<> * id_node = property_node->first_node("id"); | ||
1442 | 286 | xml_node<> * formula_node = id_node->next_sibling("description")->next_sibling("formula"); | ||
1443 | 287 | CTLQuery * query = xmlToCTLquery(formula_node->first_node()); | ||
1444 | 288 | return query; | ||
1445 | 289 | } | ||
1446 | 290 | i++; | ||
1447 | 291 | } | ||
1448 | 292 | assert(false && "Query number did not match a property in the provided .xml file."); | ||
1449 | 293 | } | ||
1450 | 294 | |||
1451 | 295 | QueryMeta* CTLParser_v2::GetQueryMetaData(std::vector<char> buffer) { | ||
1452 | 296 | xml_document<> doc; | ||
1453 | 297 | xml_node<> * root_node; | ||
1454 | 298 | doc.parse<0>(&buffer[0]); | ||
1455 | 299 | root_node = doc.first_node(); | ||
1456 | 300 | QueryMeta *meta_d = new QueryMeta(); | ||
1457 | 301 | xml_node<> * first_property_node = root_node->first_node("property"); | ||
1458 | 302 | xml_node<> * id_node = first_property_node->first_node("id"); | ||
1459 | 303 | std::string model_name(id_node->value()); | ||
1460 | 304 | int i = 0; | ||
1461 | 305 | for (xml_node<> * property_node = root_node->first_node("property"); property_node; property_node = property_node->next_sibling()) { | ||
1462 | 306 | i++; | ||
1463 | 307 | } | ||
1464 | 308 | meta_d->numberof_queries = i; | ||
1465 | 309 | std::size_t pos = model_name.find_last_of("-0") - 1; | ||
1466 | 310 | meta_d->model_name = model_name.substr(0, pos); | ||
1467 | 311 | return meta_d; | ||
1468 | 312 | } | ||
1469 | 313 | |||
1470 | 314 | |||
1471 | 315 | CTLQuery* CTLParser_v2::xmlToCTLquery(xml_node<> * root) { | ||
1472 | 316 | char *root_name = root->name(); | ||
1473 | 317 | char firstLetter = root_name[0]; | ||
1474 | 318 | CTLQuery *query; | ||
1475 | 319 | if (firstLetter == 'a') { | ||
1476 | 320 | //Construct all-paths | ||
1477 | 321 | query = new CTLQuery(A, getPathOperator(root), false, ""); | ||
1478 | 322 | assert(query->GetQuantifier() == A && "Failed setting quantifier"); | ||
1479 | 323 | } | ||
1480 | 324 | else if (firstLetter == 'e' ) { | ||
1481 | 325 | //Construct exists-path | ||
1482 | 326 | query = new CTLQuery(E, getPathOperator(root), false, ""); | ||
1483 | 327 | assert(query->GetQuantifier() == E && "Failed setting path operator"); | ||
1484 | 328 | } | ||
1485 | 329 | else if (firstLetter == 'n' ) { | ||
1486 | 330 | //Construct negation | ||
1487 | 331 | query = new CTLQuery(NEG, pError, false, ""); | ||
1488 | 332 | assert(query->GetQuantifier() == NEG && "Failed setting negation operator"); | ||
1489 | 333 | } | ||
1490 | 334 | else if (firstLetter == 'c' ) { | ||
1491 | 335 | //Construct conjunction | ||
1492 | 336 | query = new CTLQuery(AND, pError, false, ""); | ||
1493 | 337 | assert(query->GetQuantifier() == AND && "Failed setting and operator"); | ||
1494 | 338 | } | ||
1495 | 339 | else if (firstLetter == 'd' ) { | ||
1496 | 340 | //Construct disjunction | ||
1497 | 341 | query = new CTLQuery(OR, pError, false, ""); | ||
1498 | 342 | assert(query->GetQuantifier() == OR && "Failed setting or operator"); | ||
1499 | 343 | } | ||
1500 | 344 | else if (firstLetter == 'i' ) { | ||
1501 | 345 | //Construct Atom | ||
1502 | 346 | std::string atom_str = ""; | ||
1503 | 347 | if (root_name[1] == 's' ){ | ||
1504 | 348 | //Fireability Query File | ||
1505 | 349 | atom_str = root->name(); | ||
1506 | 350 | atom_str = atom_str + "("; | ||
1507 | 351 | root = root->first_node(); | ||
1508 | 352 | atom_str = atom_str + root->value(); | ||
1509 | 353 | for (xml_node<> * transition_node = root->next_sibling(); transition_node; transition_node = transition_node->next_sibling()) { | ||
1510 | 354 | atom_str = atom_str + ", " + transition_node->value(); | ||
1511 | 355 | } | ||
1512 | 356 | atom_str = atom_str + ")"; | ||
1513 | 357 | } | ||
1514 | 358 | else if (root_name[1] == 'n') { | ||
1515 | 359 | //Cardinality Query File | ||
1516 | 360 | std::string loperator = root->name(); | ||
1517 | 361 | xml_node<> * par_node = root->first_node(); | ||
1518 | 362 | std::string first = parsePar(par_node); | ||
1519 | 363 | par_node = par_node->next_sibling(); | ||
1520 | 364 | std::string second = parsePar(par_node); | ||
1521 | 365 | |||
1522 | 366 | loperator = loperator_sym(loperator); | ||
1523 | 367 | |||
1524 | 368 | atom_str = first + loperator + second; | ||
1525 | 369 | |||
1526 | 370 | } | ||
1527 | 371 | else assert(false && "Incorrectly format of .xml file provided"); | ||
1528 | 372 | query = new CTLQuery(EMPTY, pError, true, atom_str); | ||
1529 | 373 | query->Depth = 0; | ||
1530 | 374 | return query; | ||
1531 | 375 | } | ||
1532 | 376 | else if (firstLetter == 't' ){ | ||
1533 | 377 | std::string atom_str = "integer-constant(0) le integer-constant(0)"; | ||
1534 | 378 | query = new CTLQuery(EMPTY, pError, true, atom_str); | ||
1535 | 379 | query->Depth = 0; | ||
1536 | 380 | return query; | ||
1537 | 381 | } | ||
1538 | 382 | else if (firstLetter == 'f' ){ | ||
1539 | 383 | std::string atom_str = "integer-constant(2) le integer-constant(0)"; | ||
1540 | 384 | query = new CTLQuery(EMPTY, pError, true, atom_str); | ||
1541 | 385 | query->Depth = 0; | ||
1542 | 386 | return query; | ||
1543 | 387 | } | ||
1544 | 388 | else assert(false && "Failed parsing .xml file provided. Incorrect format."); | ||
1545 | 389 | |||
1546 | 390 | if (query->GetPath() == U) { | ||
1547 | 391 | xml_node<> * child_node = root->first_node()->first_node(); | ||
1548 | 392 | query->SetFirstChild(xmlToCTLquery(child_node->first_node())); | ||
1549 | 393 | child_node = child_node->next_sibling(); | ||
1550 | 394 | query->SetSecondChild(xmlToCTLquery(child_node->first_node())); | ||
1551 | 395 | |||
1552 | 396 | query->Depth = (max_depth(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth)) + 1; | ||
1553 | 397 | } | ||
1554 | 398 | else if (query->GetQuantifier() == AND || query->GetQuantifier() == OR) { | ||
1555 | 399 | xml_node<> * child_node = root->first_node(); | ||
1556 | 400 | query->SetFirstChild(xmlToCTLquery(child_node)); | ||
1557 | 401 | child_node = child_node->next_sibling(); | ||
1558 | 402 | query->SetSecondChild(xmlToCTLquery(child_node)); | ||
1559 | 403 | |||
1560 | 404 | query->Depth = (max_depth(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth)) + 1; | ||
1561 | 405 | } | ||
1562 | 406 | else if (query->GetQuantifier() == NEG) { | ||
1563 | 407 | query->SetFirstChild(xmlToCTLquery(root->first_node())); | ||
1564 | 408 | query->Depth = query->GetFirstChild()->Depth + 1; | ||
1565 | 409 | } | ||
1566 | 410 | else if (query->GetPath() == pError){ | ||
1567 | 411 | assert(false && "Failed setting Path operator"); | ||
1568 | 412 | } | ||
1569 | 413 | else if (query->GetQueryType() == PATHQEURY) { | ||
1570 | 414 | query->SetFirstChild(xmlToCTLquery(root->first_node()->first_node())); | ||
1571 | 415 | query->Depth = query->GetFirstChild()->Depth + 1; | ||
1572 | 416 | } | ||
1573 | 417 | else{ | ||
1574 | 418 | assert(false && "Attemting to give atom children - ERROR"); | ||
1575 | 419 | } | ||
1576 | 420 | |||
1577 | 421 | return query; | ||
1578 | 422 | } | ||
1579 | 423 | |||
1580 | 424 | Path CTLParser_v2::getPathOperator(xml_node<> * quantifyer_node){ | ||
1581 | 425 | char path_firstLetter = quantifyer_node->first_node()->name()[0]; | ||
1582 | 426 | if(path_firstLetter == 'f') | ||
1583 | 427 | return F; | ||
1584 | 428 | else if (path_firstLetter == 'g') | ||
1585 | 429 | return G; | ||
1586 | 430 | else if (path_firstLetter == 'n') | ||
1587 | 431 | return X; | ||
1588 | 432 | else if (path_firstLetter == 'u') | ||
1589 | 433 | return U; | ||
1590 | 434 | else assert(false && "Failed parsing path operator. Incorrect format."); | ||
1591 | 435 | } | ||
1592 | 436 | |||
1593 | 437 | std::string CTLParser_v2::parsePar(xml_node<> * parameter){ | ||
1594 | 438 | std::string parameter_str = parameter->name(); | ||
1595 | 439 | parameter_str = parameter_str + "("; | ||
1596 | 440 | |||
1597 | 441 | if (parameter->name()[0] == 't'){ | ||
1598 | 442 | xml_node<> * place_node = parameter->first_node(); | ||
1599 | 443 | parameter_str = parameter_str + place_node->value(); | ||
1600 | 444 | for(place_node = place_node->next_sibling(); place_node; place_node = place_node->next_sibling()){ | ||
1601 | 445 | parameter_str = parameter_str + ", " + place_node->value(); | ||
1602 | 446 | } | ||
1603 | 447 | parameter_str = parameter_str + ")"; | ||
1604 | 448 | } | ||
1605 | 449 | |||
1606 | 450 | else if(parameter->name()[0] == 'i'){ | ||
1607 | 451 | parameter_str = parameter_str + parameter->value() + ")"; | ||
1608 | 452 | } | ||
1609 | 453 | else assert(false && "Failed parsing cardinality parameter. Incorrect format."); | ||
1610 | 454 | return parameter_str; | ||
1611 | 455 | } | ||
1612 | 456 | |||
1613 | 457 | /* | ||
1614 | 458 | for (xml_node<> * transition_node = root->next_sibling(); transition_node; transition_node = transition_node->next_sibling()) { | ||
1615 | 459 | atom_str = atom_str + ", " + transition_node->value(); | ||
1616 | 460 | } | ||
1617 | 461 | atom_str = atom_str + ")"; | ||
1618 | 462 | */ | ||
1619 | 463 | |||
1620 | 464 | int CTLParser_v2::max_depth(int a, int b){ | ||
1621 | 465 | if(a < b) return b; return a; | ||
1622 | 466 | } | ||
1623 | 467 | |||
1624 | 468 | std::string CTLParser_v2::loperator_sym(std::string loperator){ | ||
1625 | 469 | if(loperator.compare("integer-le") == 0){ | ||
1626 | 470 | return " le "; | ||
1627 | 471 | } | ||
1628 | 472 | else if(loperator.compare("integer-ge")){ | ||
1629 | 473 | return " ge "; | ||
1630 | 474 | } | ||
1631 | 475 | else if(loperator.compare("integer-eq")){ | ||
1632 | 476 | return " eq "; | ||
1633 | 477 | } | ||
1634 | 478 | else return " " + loperator + " "; | ||
1635 | 479 | } | ||
1636 | 480 | |||
1637 | 481 | CTLQuery * CTLParser_v2::CopyQuery(CTLQuery *source){ | ||
1638 | 482 | if(source->GetQueryType() == EVAL){ | ||
1639 | 483 | return new CTLQuery(EMPTY, pError, true, source->GetAtom()); | ||
1640 | 484 | } | ||
1641 | 485 | else if(source->GetQueryType() == LOPERATOR){ | ||
1642 | 486 | CTLQuery *dest = new CTLQuery(source->GetQuantifier(), pError, false, ""); | ||
1643 | 487 | if(source->GetQuantifier() != NEG){ | ||
1644 | 488 | dest->SetFirstChild(CopyQuery(source->GetFirstChild())); | ||
1645 | 489 | dest->SetSecondChild(CopyQuery(source->GetSecondChild())); | ||
1646 | 490 | } | ||
1647 | 491 | else { | ||
1648 | 492 | dest->SetFirstChild(CopyQuery(source->GetFirstChild())); | ||
1649 | 493 | } | ||
1650 | 494 | return dest; | ||
1651 | 495 | } | ||
1652 | 496 | else if(source->GetQueryType() == PATHQEURY){ | ||
1653 | 497 | CTLQuery *dest = new CTLQuery(source->GetQuantifier(), source->GetPath(), false, ""); | ||
1654 | 498 | if(source->GetPath() == U){ | ||
1655 | 499 | dest->SetFirstChild(CopyQuery(source->GetFirstChild())); | ||
1656 | 500 | dest->SetSecondChild(CopyQuery(source->GetSecondChild())); | ||
1657 | 501 | } | ||
1658 | 502 | else{ | ||
1659 | 503 | dest->SetFirstChild(CopyQuery(source->GetFirstChild())); | ||
1660 | 504 | } | ||
1661 | 505 | return dest; | ||
1662 | 506 | } | ||
1663 | 507 | else assert(false && "ERROR::: Copying query failed"); | ||
1664 | 508 | } | ||
1665 | 0 | 509 | ||
1666 | === added file 'CTLParser/CTLParser_v2.h' | |||
1667 | --- CTLParser/CTLParser_v2.h 1970-01-01 00:00:00 +0000 | |||
1668 | +++ CTLParser/CTLParser_v2.h 2016-05-20 07:41:18 +0000 | |||
1669 | @@ -0,0 +1,56 @@ | |||
1670 | 1 | /* | ||
1671 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1672 | 3 | * To change this template file, choose Tools | Templates | ||
1673 | 4 | * and open the template in the editor. | ||
1674 | 5 | */ | ||
1675 | 6 | |||
1676 | 7 | /* | ||
1677 | 8 | * File: CTLParser_v2.h | ||
1678 | 9 | * Author: mossns | ||
1679 | 10 | * | ||
1680 | 11 | * Created on April 22, 2016, 10:15 AM | ||
1681 | 12 | */ | ||
1682 | 13 | |||
1683 | 14 | #ifndef CTLPARSER_V2_H | ||
1684 | 15 | #define CTLPARSER_V2_H | ||
1685 | 16 | |||
1686 | 17 | #include "rapidxml-1.13/rapidxml.hpp" | ||
1687 | 18 | #include <vector> | ||
1688 | 19 | #include <string> | ||
1689 | 20 | #include <stdio.h> | ||
1690 | 21 | #include "CTLQuery.h" | ||
1691 | 22 | |||
1692 | 23 | struct QueryMeta{ | ||
1693 | 24 | int numberof_queries = 0; | ||
1694 | 25 | std::string model_name; | ||
1695 | 26 | |||
1696 | 27 | }; | ||
1697 | 28 | |||
1698 | 29 | class CTLParser_v2 { | ||
1699 | 30 | public: | ||
1700 | 31 | CTLParser_v2(); | ||
1701 | 32 | CTLParser_v2(const CTLParser_v2& orig); | ||
1702 | 33 | virtual ~CTLParser_v2(); | ||
1703 | 34 | CTLQuery * ParseXMLQuery(std::vector<char> buffer, int query_number); | ||
1704 | 35 | CTLQuery* FormatQuery(CTLQuery* query, PetriEngine::PetriNet *net); | ||
1705 | 36 | std::string QueryToString(CTLQuery* query); | ||
1706 | 37 | QueryMeta * GetQueryMetaData(std::vector<char> buffer); | ||
1707 | 38 | private: | ||
1708 | 39 | CTLQuery* xmlToCTLquery(rapidxml::xml_node<> * root); | ||
1709 | 40 | std::string parsePar(rapidxml::xml_node<> * parameter); | ||
1710 | 41 | Path getPathOperator(rapidxml::xml_node<> * quantifyer_node); | ||
1711 | 42 | int max_depth(int a, int b); | ||
1712 | 43 | std::string loperator_sym(std::string loperator); | ||
1713 | 44 | CTLQuery * CopyQuery(CTLQuery *source); | ||
1714 | 45 | |||
1715 | 46 | CTLQuery* FillAtom(CTLQuery* query, PetriEngine::PetriNet *net); | ||
1716 | 47 | CTLQuery* ConvertAG(CTLQuery* query); | ||
1717 | 48 | CTLQuery* ConvertEG(CTLQuery* query); | ||
1718 | 49 | CTLQuery* TemporalSetting(CTLQuery* query); | ||
1719 | 50 | int IdSetting(CTLQuery* query, int id); | ||
1720 | 51 | QueryMeta *_meta; | ||
1721 | 52 | |||
1722 | 53 | }; | ||
1723 | 54 | |||
1724 | 55 | #endif /* CTLPARSER_V2_H */ | ||
1725 | 56 | |||
1726 | 0 | 57 | ||
1727 | === added file 'CTLParser/CTLQuery.cpp' | |||
1728 | --- CTLParser/CTLQuery.cpp 1970-01-01 00:00:00 +0000 | |||
1729 | +++ CTLParser/CTLQuery.cpp 2016-05-20 07:41:18 +0000 | |||
1730 | @@ -0,0 +1,159 @@ | |||
1731 | 1 | /* | ||
1732 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1733 | 3 | * To change this template file, choose Tools | Templates | ||
1734 | 4 | * and open the template in the editor. | ||
1735 | 5 | */ | ||
1736 | 6 | |||
1737 | 7 | /* | ||
1738 | 8 | * File: CTLQuery.cpp | ||
1739 | 9 | * Author: mossns | ||
1740 | 10 | * | ||
1741 | 11 | * Created on April 22, 2016, 7:57 AM | ||
1742 | 12 | */ | ||
1743 | 13 | |||
1744 | 14 | #include <string.h> | ||
1745 | 15 | |||
1746 | 16 | #include "CTLQuery.h" | ||
1747 | 17 | #include "CTLParser.h" | ||
1748 | 18 | |||
1749 | 19 | CTLQuery::CTLQuery(Quantifier q, Path p, bool isAtom, std::string atom_str) { | ||
1750 | 20 | if(isAtom){ | ||
1751 | 21 | assert(q == EMPTY); | ||
1752 | 22 | assert(p == pError); | ||
1753 | 23 | assert(atom_str.compare("") != 0); | ||
1754 | 24 | |||
1755 | 25 | _hasAtom = true; | ||
1756 | 26 | _hasQuantifier = false; | ||
1757 | 27 | _hasPath = false; | ||
1758 | 28 | _q = q; | ||
1759 | 29 | _path = p; | ||
1760 | 30 | _a = atom_str; | ||
1761 | 31 | IsTemporal = false; | ||
1762 | 32 | } | ||
1763 | 33 | else if(q == AND || q == OR || q == NEG){ | ||
1764 | 34 | assert(p == pError); | ||
1765 | 35 | _hasAtom = false; | ||
1766 | 36 | _hasQuantifier = true; | ||
1767 | 37 | _hasPath = false; | ||
1768 | 38 | _q = q; | ||
1769 | 39 | _path = p; | ||
1770 | 40 | _a = ""; | ||
1771 | 41 | IsTemporal = false; | ||
1772 | 42 | } | ||
1773 | 43 | else{ | ||
1774 | 44 | assert(q != EMPTY); | ||
1775 | 45 | assert(p != pError); | ||
1776 | 46 | _hasAtom = false; | ||
1777 | 47 | _hasQuantifier = true; | ||
1778 | 48 | _hasPath = true; | ||
1779 | 49 | _q = q; | ||
1780 | 50 | _path = p; | ||
1781 | 51 | _a = ""; | ||
1782 | 52 | IsTemporal = true; | ||
1783 | 53 | } | ||
1784 | 54 | |||
1785 | 55 | } | ||
1786 | 56 | |||
1787 | 57 | CTLQuery::~CTLQuery() { | ||
1788 | 58 | } | ||
1789 | 59 | |||
1790 | 60 | CTLType CTLQuery::GetQueryType(){ | ||
1791 | 61 | if(_hasAtom) | ||
1792 | 62 | return EVAL; | ||
1793 | 63 | else if(_path != pError) | ||
1794 | 64 | return PATHQEURY; | ||
1795 | 65 | else if(_q == AND || _q == OR || _q == NEG) | ||
1796 | 66 | return LOPERATOR; | ||
1797 | 67 | return TYPE_ERROR; | ||
1798 | 68 | } | ||
1799 | 69 | |||
1800 | 70 | CTLQuery* CTLQuery::GetFirstChild(){ | ||
1801 | 71 | if(_hasAtom){ | ||
1802 | 72 | std::cout<<"Query " << ToString() << " does not have child"<<std::endl; | ||
1803 | 73 | throw 20; | ||
1804 | 74 | } | ||
1805 | 75 | return _firstchild; | ||
1806 | 76 | } | ||
1807 | 77 | |||
1808 | 78 | CTLQuery* CTLQuery::GetSecondChild(){ | ||
1809 | 79 | assert(!_hasAtom && "Query does not have children"); | ||
1810 | 80 | assert(!(_path == F || _path == G || _path == X) && "Query does not have second child"); | ||
1811 | 81 | assert(!(_q == NEG) && "Query does not have second child"); | ||
1812 | 82 | return _secondchild; | ||
1813 | 83 | } | ||
1814 | 84 | |||
1815 | 85 | void CTLQuery::SetFirstChild(CTLQuery *q){ | ||
1816 | 86 | _firstchild = q; | ||
1817 | 87 | } | ||
1818 | 88 | |||
1819 | 89 | void CTLQuery::SetSecondChild(CTLQuery *q){ | ||
1820 | 90 | _secondchild = q; | ||
1821 | 91 | } | ||
1822 | 92 | |||
1823 | 93 | Quantifier CTLQuery::GetQuantifier(){ | ||
1824 | 94 | return _q; | ||
1825 | 95 | } | ||
1826 | 96 | |||
1827 | 97 | Path CTLQuery::GetPath(){ | ||
1828 | 98 | return _path; | ||
1829 | 99 | } | ||
1830 | 100 | |||
1831 | 101 | std::string CTLQuery::GetAtom(){ | ||
1832 | 102 | return _a; | ||
1833 | 103 | } | ||
1834 | 104 | |||
1835 | 105 | EvaluateableProposition* CTLQuery::GetProposition(){ | ||
1836 | 106 | assert(_hasAtom && "Query does not have proposition"); | ||
1837 | 107 | return _proposition; | ||
1838 | 108 | } | ||
1839 | 109 | |||
1840 | 110 | void CTLQuery::SetProposition(EvaluateableProposition *p){ | ||
1841 | 111 | assert(_hasAtom && "Query does not have proposition"); | ||
1842 | 112 | _proposition = p; | ||
1843 | 113 | } | ||
1844 | 114 | |||
1845 | 115 | std::string CTLQuery::ToString(){ | ||
1846 | 116 | if(_hasAtom){ | ||
1847 | 117 | return _a; | ||
1848 | 118 | } | ||
1849 | 119 | else if(_q == AND){ | ||
1850 | 120 | return " & "; | ||
1851 | 121 | } | ||
1852 | 122 | else if(_q == OR){ | ||
1853 | 123 | return " | "; | ||
1854 | 124 | } | ||
1855 | 125 | else if(_q == NEG){ | ||
1856 | 126 | return "!"; | ||
1857 | 127 | } | ||
1858 | 128 | else if(_q == A || _q == E){ | ||
1859 | 129 | std::string quanti = ""; | ||
1860 | 130 | if (_q == A){ | ||
1861 | 131 | quanti = "A"; | ||
1862 | 132 | } | ||
1863 | 133 | else quanti = "E"; | ||
1864 | 134 | if(_path == F){ | ||
1865 | 135 | return quanti + "F"; | ||
1866 | 136 | } | ||
1867 | 137 | else if(_path == G){ | ||
1868 | 138 | return quanti + "G"; | ||
1869 | 139 | } | ||
1870 | 140 | else if(_path == X){ | ||
1871 | 141 | return quanti + "X"; | ||
1872 | 142 | } | ||
1873 | 143 | else if(_path == U){ | ||
1874 | 144 | |||
1875 | 145 | return quanti.append("U"); | ||
1876 | 146 | } | ||
1877 | 147 | else{ | ||
1878 | 148 | std::cout<<"::::::Error Printing: Path was empty::::"<<std::endl; | ||
1879 | 149 | assert(false); | ||
1880 | 150 | } | ||
1881 | 151 | } | ||
1882 | 152 | else{ | ||
1883 | 153 | std::cout<<"::::::Error Printing: Q was empty::::"<<std::endl; | ||
1884 | 154 | assert(false); | ||
1885 | 155 | } | ||
1886 | 156 | } | ||
1887 | 157 | |||
1888 | 158 | |||
1889 | 159 | |||
1890 | 0 | 160 | ||
1891 | === added file 'CTLParser/CTLQuery.h' | |||
1892 | --- CTLParser/CTLQuery.h 1970-01-01 00:00:00 +0000 | |||
1893 | +++ CTLParser/CTLQuery.h 2016-05-20 07:41:18 +0000 | |||
1894 | @@ -0,0 +1,66 @@ | |||
1895 | 1 | /* | ||
1896 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1897 | 3 | * To change this template file, choose Tools | Templates | ||
1898 | 4 | * and open the template in the editor. | ||
1899 | 5 | */ | ||
1900 | 6 | |||
1901 | 7 | /* | ||
1902 | 8 | * File: CTLQuery.h | ||
1903 | 9 | * Author: Søren Moss Nielsen | ||
1904 | 10 | * | ||
1905 | 11 | * Created on April 22, 2016, 7:57 AM | ||
1906 | 12 | */ | ||
1907 | 13 | |||
1908 | 14 | #ifndef CTLQUERY_H | ||
1909 | 15 | #define CTLQUERY_H | ||
1910 | 16 | #include "CTLParser.h" | ||
1911 | 17 | #include "EvaluateableProposition.h" | ||
1912 | 18 | |||
1913 | 19 | enum CTLType {PATHQEURY = 1, LOPERATOR = 2, EVAL = 3, TYPE_ERROR = -1}; | ||
1914 | 20 | |||
1915 | 21 | class CTLQuery { | ||
1916 | 22 | |||
1917 | 23 | public: | ||
1918 | 24 | CTLQuery(Quantifier q, Path p, bool isAtom, std::string atom_str); | ||
1919 | 25 | virtual ~CTLQuery(); | ||
1920 | 26 | |||
1921 | 27 | int Id; | ||
1922 | 28 | int Depth; | ||
1923 | 29 | |||
1924 | 30 | CTLType GetQueryType(); | ||
1925 | 31 | CTLQuery* GetFirstChild(); | ||
1926 | 32 | CTLQuery* GetSecondChild(); | ||
1927 | 33 | void SetFirstChild(CTLQuery *q); | ||
1928 | 34 | void SetSecondChild(CTLQuery *q); | ||
1929 | 35 | std::string ToString(); | ||
1930 | 36 | |||
1931 | 37 | Quantifier GetQuantifier(); | ||
1932 | 38 | Path GetPath(); | ||
1933 | 39 | std::string GetAtom(); | ||
1934 | 40 | |||
1935 | 41 | EvaluateableProposition* GetProposition(); | ||
1936 | 42 | void SetProposition(EvaluateableProposition *p); | ||
1937 | 43 | |||
1938 | 44 | bool IsTemporal; | ||
1939 | 45 | |||
1940 | 46 | |||
1941 | 47 | private: | ||
1942 | 48 | std::string CreateEvaluateableProposition(std::string a); | ||
1943 | 49 | |||
1944 | 50 | bool _hasQuantifier; | ||
1945 | 51 | bool _hasPath; | ||
1946 | 52 | bool _hasAtom; | ||
1947 | 53 | Quantifier _q; | ||
1948 | 54 | Path _path; | ||
1949 | 55 | std::string _a; | ||
1950 | 56 | |||
1951 | 57 | CTLQuery* _firstchild; | ||
1952 | 58 | CTLQuery* _secondchild; | ||
1953 | 59 | |||
1954 | 60 | EvaluateableProposition* _proposition; | ||
1955 | 61 | |||
1956 | 62 | |||
1957 | 63 | }; | ||
1958 | 64 | |||
1959 | 65 | #endif /* CTLQUERY_H */ | ||
1960 | 66 | |||
1961 | 0 | 67 | ||
1962 | === added file 'CTLParser/EvaluateableProposition.cpp' | |||
1963 | --- CTLParser/EvaluateableProposition.cpp 1970-01-01 00:00:00 +0000 | |||
1964 | +++ CTLParser/EvaluateableProposition.cpp 2016-05-20 07:41:18 +0000 | |||
1965 | @@ -0,0 +1,189 @@ | |||
1966 | 1 | /* | ||
1967 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
1968 | 3 | * To change this template file, choose Tools | Templates | ||
1969 | 4 | * and open the template in the editor. | ||
1970 | 5 | */ | ||
1971 | 6 | |||
1972 | 7 | /* | ||
1973 | 8 | * File: EvaluateableProposition.cpp | ||
1974 | 9 | * Author: mossns | ||
1975 | 10 | * | ||
1976 | 11 | * Created on April 27, 2016, 2:36 PM | ||
1977 | 12 | */ | ||
1978 | 13 | |||
1979 | 14 | #include <string> | ||
1980 | 15 | #include <stdexcept> | ||
1981 | 16 | #include <sstream> | ||
1982 | 17 | |||
1983 | 18 | #include "EvaluateableProposition.h" | ||
1984 | 19 | #include "CTLParser.h" | ||
1985 | 20 | |||
1986 | 21 | namespace patch | ||
1987 | 22 | { | ||
1988 | 23 | //A replacement for the standard to string function, which we cannot use because old OS X does not have c++11 | ||
1989 | 24 | template < typename T > std::string to_string( const T& n ) | ||
1990 | 25 | { | ||
1991 | 26 | std::ostringstream stm ; | ||
1992 | 27 | stm << n ; | ||
1993 | 28 | return stm.str() ; | ||
1994 | 29 | } | ||
1995 | 30 | } | ||
1996 | 31 | |||
1997 | 32 | EvaluateableProposition::EvaluateableProposition(std::string a, PetriEngine::PetriNet *net) { | ||
1998 | 33 | if(a.substr(0,2).compare("in") == 0 || a.substr(0,2).compare("to") == 0){ | ||
1999 | 34 | _type = CARDINALITY; | ||
2000 | 35 | _loperator = SetLoperator(a); | ||
2001 | 36 | assert(_loperator != NOT_CARDINALITY); | ||
2002 | 37 | |||
2003 | 38 | size_t begin = a.find('(') + 1; | ||
2004 | 39 | size_t end = a.find(')') - begin; | ||
2005 | 40 | std::string first_parameter_str = a.substr(begin, end); | ||
2006 | 41 | a = a.substr(a.find(')') + 1); | ||
2007 | 42 | |||
2008 | 43 | begin = a.find('(') + 1; | ||
2009 | 44 | end = a.find(')') - begin; | ||
2010 | 45 | std::string second_parameter_str = a.substr(begin, end); | ||
2011 | 46 | _firstParameter = CreateParameter(first_parameter_str, net->placeNames(), net->numberOfPlaces()); | ||
2012 | 47 | _secondParameter = CreateParameter(second_parameter_str, net->placeNames(), net->numberOfPlaces()); | ||
2013 | 48 | } | ||
2014 | 49 | else if(a.substr(0,2).compare("is") == 0){ | ||
2015 | 50 | _type = FIREABILITY; | ||
2016 | 51 | _loperator = NOT_CARDINALITY; | ||
2017 | 52 | size_t s_pos = a.find('(') + 1; | ||
2018 | 53 | size_t e_pos = a.find(')') - 1; | ||
2019 | 54 | assert(s_pos < e_pos); | ||
2020 | 55 | int fire_str_length = e_pos - s_pos + 1; | ||
2021 | 56 | std::string fireset_str = a.substr(s_pos, fire_str_length); | ||
2022 | 57 | SetFireset(fireset_str, net->transitionNames(), net->numberOfTransitions()); | ||
2023 | 58 | } | ||
2024 | 59 | else if(a.substr(0,2).compare("tr") == 0){ | ||
2025 | 60 | |||
2026 | 61 | } | ||
2027 | 62 | else if(a.substr(0,2).compare("fa") == 0){ | ||
2028 | 63 | |||
2029 | 64 | } | ||
2030 | 65 | else{ | ||
2031 | 66 | assert(false && "Atomic string proposed for proposition could not be parsed"); | ||
2032 | 67 | } | ||
2033 | 68 | } | ||
2034 | 69 | |||
2035 | 70 | EvaluateableProposition::~EvaluateableProposition() { | ||
2036 | 71 | } | ||
2037 | 72 | |||
2038 | 73 | PropositionType EvaluateableProposition::GetPropositionType(){ | ||
2039 | 74 | return _type; | ||
2040 | 75 | } | ||
2041 | 76 | |||
2042 | 77 | LoperatorType EvaluateableProposition::GetLoperator(){ | ||
2043 | 78 | assert(_type == CARDINALITY && "Proposition is not a cardinality proposition"); | ||
2044 | 79 | return _loperator; | ||
2045 | 80 | } | ||
2046 | 81 | |||
2047 | 82 | std::vector<int> EvaluateableProposition::GetFireset() { | ||
2048 | 83 | assert(_type == FIREABILITY && "Proposition is not a fireability proposition"); | ||
2049 | 84 | return _fireset; | ||
2050 | 85 | } | ||
2051 | 86 | |||
2052 | 87 | void EvaluateableProposition::SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t){ | ||
2053 | 88 | std::string restof_firestring = fireset_str; | ||
2054 | 89 | while(restof_firestring.length() > 0){ | ||
2055 | 90 | size_t position = restof_firestring.find(','); | ||
2056 | 91 | std::string current_t = restof_firestring.substr(0, position); | ||
2057 | 92 | for(int i = 0; i < numberof_t; i++){ | ||
2058 | 93 | if (current_t.compare(t_names[i]) == 0){ | ||
2059 | 94 | _fireset.push_back(i); | ||
2060 | 95 | } | ||
2061 | 96 | } | ||
2062 | 97 | if (position != -1) | ||
2063 | 98 | restof_firestring = restof_firestring.substr(position); | ||
2064 | 99 | else | ||
2065 | 100 | restof_firestring = ""; | ||
2066 | 101 | } | ||
2067 | 102 | for ( auto f : _fireset){ | ||
2068 | 103 | std::cout<<f<<" is id of "<< t_names[f]<<std::endl; | ||
2069 | 104 | } | ||
2070 | 105 | } | ||
2071 | 106 | |||
2072 | 107 | CardinalityParameter* EvaluateableProposition::CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p){ | ||
2073 | 108 | CardinalityParameter *param = new CardinalityParameter(); | ||
2074 | 109 | std::string::size_type sz; | ||
2075 | 110 | char c; | ||
2076 | 111 | if(sscanf(parameter_str.c_str(), "%d%c", ¶m->value, &c) == 1) { | ||
2077 | 112 | //If string is identifier starting with a number, you will read two items. | ||
2078 | 113 | //If it's an identifier starting with a character, you will read zero items. | ||
2079 | 114 | //The only time when you read just one item if the whole string is just numbers. | ||
2080 | 115 | param->isPlace = false; | ||
2081 | 116 | } else { //error | ||
2082 | 117 | |||
2083 | 118 | param->isPlace = true; | ||
2084 | 119 | std::vector<std::string> places_str; | ||
2085 | 120 | std::size_t found = parameter_str.find(","); | ||
2086 | 121 | |||
2087 | 122 | while(found != parameter_str.npos){ | ||
2088 | 123 | std::string temp = parameter_str.substr(0, found); | ||
2089 | 124 | places_str.push_back(temp); | ||
2090 | 125 | parameter_str = parameter_str.substr(found + 2); | ||
2091 | 126 | found = parameter_str.find(","); | ||
2092 | 127 | } | ||
2093 | 128 | |||
2094 | 129 | places_str.push_back(parameter_str); | ||
2095 | 130 | |||
2096 | 131 | for(int i = 0; i < numberof_p; i++){ | ||
2097 | 132 | for(std::string place : places_str){ | ||
2098 | 133 | if(p_names[i].compare(place) == 0){ | ||
2099 | 134 | param->places_i.push_back(i); | ||
2100 | 135 | } | ||
2101 | 136 | } | ||
2102 | 137 | } | ||
2103 | 138 | } | ||
2104 | 139 | return param; | ||
2105 | 140 | } | ||
2106 | 141 | |||
2107 | 142 | LoperatorType EvaluateableProposition::SetLoperator(std::string atom_str){ | ||
2108 | 143 | std::string loperator_str = atom_str.substr(atom_str.find(')')); | ||
2109 | 144 | loperator_str = loperator_str.substr(0, loperator_str.find('(')); | ||
2110 | 145 | if(loperator_str.compare(" le ")) | ||
2111 | 146 | return LEQ; | ||
2112 | 147 | else if (loperator_str.compare(" ge ")) | ||
2113 | 148 | return GRQ; | ||
2114 | 149 | else if (loperator_str.compare(" eq ")) | ||
2115 | 150 | return EQ; | ||
2116 | 151 | else assert(false && "Could not parse the given logical operator"); | ||
2117 | 152 | } | ||
2118 | 153 | |||
2119 | 154 | std::string EvaluateableProposition::ToString() { | ||
2120 | 155 | if (_type == FIREABILITY) { | ||
2121 | 156 | std::string fire_str = "Fireset("; | ||
2122 | 157 | for(auto f : _fireset){ | ||
2123 | 158 | fire_str = fire_str + " " + patch::to_string(f); | ||
2124 | 159 | } | ||
2125 | 160 | return fire_str + ")"; | ||
2126 | 161 | } | ||
2127 | 162 | else if (_type == CARDINALITY){ | ||
2128 | 163 | std::string cardi_str = "("; | ||
2129 | 164 | if(_firstParameter->isPlace) | ||
2130 | 165 | cardi_str = cardi_str + "place(" + patch::to_string(_firstParameter->value) + ")"; | ||
2131 | 166 | else | ||
2132 | 167 | cardi_str = cardi_str = patch::to_string(_firstParameter->value); | ||
2133 | 168 | |||
2134 | 169 | cardi_str = cardi_str + " le "; | ||
2135 | 170 | |||
2136 | 171 | if(_secondParameter->isPlace) | ||
2137 | 172 | cardi_str = cardi_str + "place(" + patch::to_string(_secondParameter->value) + ")"; | ||
2138 | 173 | else | ||
2139 | 174 | cardi_str = cardi_str = patch::to_string(_secondParameter->value); | ||
2140 | 175 | return cardi_str + ")"; | ||
2141 | 176 | } | ||
2142 | 177 | else | ||
2143 | 178 | assert(false && "Proposition had no type"); | ||
2144 | 179 | } | ||
2145 | 180 | |||
2146 | 181 | CardinalityParameter* EvaluateableProposition::GetFirstParameter() { | ||
2147 | 182 | assert(_type == CARDINALITY); | ||
2148 | 183 | return _firstParameter; | ||
2149 | 184 | } | ||
2150 | 185 | |||
2151 | 186 | CardinalityParameter* EvaluateableProposition::GetSecondParameter() { | ||
2152 | 187 | assert(_type == CARDINALITY); | ||
2153 | 188 | return _secondParameter; | ||
2154 | 189 | } | ||
2155 | 0 | 190 | ||
2156 | === added file 'CTLParser/EvaluateableProposition.h' | |||
2157 | --- CTLParser/EvaluateableProposition.h 1970-01-01 00:00:00 +0000 | |||
2158 | +++ CTLParser/EvaluateableProposition.h 2016-05-20 07:41:18 +0000 | |||
2159 | @@ -0,0 +1,53 @@ | |||
2160 | 1 | /* | ||
2161 | 2 | * To change this license header, choose License Headers in Project Properties. | ||
2162 | 3 | * To change this template file, choose Tools | Templates | ||
2163 | 4 | * and open the template in the editor. | ||
2164 | 5 | */ | ||
2165 | 6 | |||
2166 | 7 | /* | ||
2167 | 8 | * File: EvaluateableProposition.h | ||
2168 | 9 | * Author: mossns | ||
2169 | 10 | * | ||
2170 | 11 | * Created on April 27, 2016, 2:36 PM | ||
2171 | 12 | */ | ||
2172 | 13 | |||
2173 | 14 | #ifndef EVALUATEABLEPROPOSITION_H | ||
2174 | 15 | #define EVALUATEABLEPROPOSITION_H | ||
2175 | 16 | #include <vector> | ||
2176 | 17 | #include "PetriEngine/PetriNet.h" | ||
2177 | 18 | |||
2178 | 19 | |||
2179 | 20 | enum PropositionType {CARDINALITY = 0, FIREABILITY = 1}; | ||
2180 | 21 | enum LoperatorType {NOT_CARDINALITY = -1, EQ = 0, LE = 1, LEQ = 2, GR = 3, GRQ = 4}; | ||
2181 | 22 | |||
2182 | 23 | struct CardinalityParameter{ | ||
2183 | 24 | bool isPlace; | ||
2184 | 25 | int value; | ||
2185 | 26 | std::vector<int> places_i; | ||
2186 | 27 | }; | ||
2187 | 28 | |||
2188 | 29 | class EvaluateableProposition { | ||
2189 | 30 | public: | ||
2190 | 31 | EvaluateableProposition(std::string a, PetriEngine::PetriNet *net); | ||
2191 | 32 | virtual ~EvaluateableProposition(); | ||
2192 | 33 | PropositionType GetPropositionType(); | ||
2193 | 34 | LoperatorType GetLoperator(); | ||
2194 | 35 | std::vector<int> GetFireset(); | ||
2195 | 36 | std::string ToString(); | ||
2196 | 37 | CardinalityParameter* GetFirstParameter(); | ||
2197 | 38 | CardinalityParameter* GetSecondParameter(); | ||
2198 | 39 | private: | ||
2199 | 40 | void SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t); | ||
2200 | 41 | CardinalityParameter* CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p); | ||
2201 | 42 | LoperatorType SetLoperator(std::string atom_str); | ||
2202 | 43 | |||
2203 | 44 | PropositionType _type; | ||
2204 | 45 | LoperatorType _loperator; | ||
2205 | 46 | std::vector<int> _fireset; | ||
2206 | 47 | CardinalityParameter* _firstParameter; | ||
2207 | 48 | CardinalityParameter* _secondParameter; | ||
2208 | 49 | |||
2209 | 50 | }; | ||
2210 | 51 | |||
2211 | 52 | #endif /* EVALUATEABLEPROPOSITION_H */ | ||
2212 | 53 | |||
2213 | 0 | 54 | ||
2214 | === added directory 'Tests/unitTesting' | |||
2215 | === added file 'Tests/unitTesting/catch.hpp' | |||
2216 | --- Tests/unitTesting/catch.hpp 1970-01-01 00:00:00 +0000 | |||
2217 | +++ Tests/unitTesting/catch.hpp 2016-05-20 07:41:18 +0000 | |||
2218 | @@ -0,0 +1,10483 @@ | |||
2219 | 1 | /* | ||
2220 | 2 | * Catch v1.5.1 | ||
2221 | 3 | * Generated: 2016-04-28 08:12:37.387488 | ||
2222 | 4 | * ---------------------------------------------------------- | ||
2223 | 5 | * This file has been merged from multiple headers. Please don't edit it directly | ||
2224 | 6 | * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. | ||
2225 | 7 | * | ||
2226 | 8 | * Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
2227 | 9 | * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
2228 | 10 | */ | ||
2229 | 11 | #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED | ||
2230 | 12 | #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED | ||
2231 | 13 | |||
2232 | 14 | #define TWOBLUECUBES_CATCH_HPP_INCLUDED | ||
2233 | 15 | |||
2234 | 16 | #ifdef __clang__ | ||
2235 | 17 | # pragma clang system_header | ||
2236 | 18 | #elif defined __GNUC__ | ||
2237 | 19 | # pragma GCC system_header | ||
2238 | 20 | #endif | ||
2239 | 21 | |||
2240 | 22 | // #included from: internal/catch_suppress_warnings.h | ||
2241 | 23 | |||
2242 | 24 | #ifdef __clang__ | ||
2243 | 25 | # ifdef __ICC // icpc defines the __clang__ macro | ||
2244 | 26 | # pragma warning(push) | ||
2245 | 27 | # pragma warning(disable: 161 1682) | ||
2246 | 28 | # else // __ICC | ||
2247 | 29 | # pragma clang diagnostic ignored "-Wglobal-constructors" | ||
2248 | 30 | # pragma clang diagnostic ignored "-Wvariadic-macros" | ||
2249 | 31 | # pragma clang diagnostic ignored "-Wc99-extensions" | ||
2250 | 32 | # pragma clang diagnostic ignored "-Wunused-variable" | ||
2251 | 33 | # pragma clang diagnostic push | ||
2252 | 34 | # pragma clang diagnostic ignored "-Wpadded" | ||
2253 | 35 | # pragma clang diagnostic ignored "-Wc++98-compat" | ||
2254 | 36 | # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" | ||
2255 | 37 | # pragma clang diagnostic ignored "-Wswitch-enum" | ||
2256 | 38 | # pragma clang diagnostic ignored "-Wcovered-switch-default" | ||
2257 | 39 | # endif | ||
2258 | 40 | #elif defined __GNUC__ | ||
2259 | 41 | # pragma GCC diagnostic ignored "-Wvariadic-macros" | ||
2260 | 42 | # pragma GCC diagnostic ignored "-Wunused-variable" | ||
2261 | 43 | # pragma GCC diagnostic push | ||
2262 | 44 | # pragma GCC diagnostic ignored "-Wpadded" | ||
2263 | 45 | #endif | ||
2264 | 46 | #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) | ||
2265 | 47 | # define CATCH_IMPL | ||
2266 | 48 | #endif | ||
2267 | 49 | |||
2268 | 50 | #ifdef CATCH_IMPL | ||
2269 | 51 | # ifndef CLARA_CONFIG_MAIN | ||
2270 | 52 | # define CLARA_CONFIG_MAIN_NOT_DEFINED | ||
2271 | 53 | # define CLARA_CONFIG_MAIN | ||
2272 | 54 | # endif | ||
2273 | 55 | #endif | ||
2274 | 56 | |||
2275 | 57 | // #included from: internal/catch_notimplemented_exception.h | ||
2276 | 58 | #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED | ||
2277 | 59 | |||
2278 | 60 | // #included from: catch_common.h | ||
2279 | 61 | #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED | ||
2280 | 62 | |||
2281 | 63 | #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line | ||
2282 | 64 | #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) | ||
2283 | 65 | #ifdef CATCH_CONFIG_COUNTER | ||
2284 | 66 | # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) | ||
2285 | 67 | #else | ||
2286 | 68 | # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) | ||
2287 | 69 | #endif | ||
2288 | 70 | |||
2289 | 71 | #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr | ||
2290 | 72 | #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) | ||
2291 | 73 | |||
2292 | 74 | #include <sstream> | ||
2293 | 75 | #include <stdexcept> | ||
2294 | 76 | #include <algorithm> | ||
2295 | 77 | |||
2296 | 78 | // #included from: catch_compiler_capabilities.h | ||
2297 | 79 | #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED | ||
2298 | 80 | |||
2299 | 81 | // Detect a number of compiler features - mostly C++11/14 conformance - by compiler | ||
2300 | 82 | // The following features are defined: | ||
2301 | 83 | // | ||
2302 | 84 | // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? | ||
2303 | 85 | // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? | ||
2304 | 86 | // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods | ||
2305 | 87 | // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? | ||
2306 | 88 | // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported | ||
2307 | 89 | // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? | ||
2308 | 90 | // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? | ||
2309 | 91 | // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) | ||
2310 | 92 | |||
2311 | 93 | // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? | ||
2312 | 94 | |||
2313 | 95 | // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? | ||
2314 | 96 | // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? | ||
2315 | 97 | // **************** | ||
2316 | 98 | // Note to maintainers: if new toggles are added please document them | ||
2317 | 99 | // in configuration.md, too | ||
2318 | 100 | // **************** | ||
2319 | 101 | |||
2320 | 102 | // In general each macro has a _NO_<feature name> form | ||
2321 | 103 | // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. | ||
2322 | 104 | // Many features, at point of detection, define an _INTERNAL_ macro, so they | ||
2323 | 105 | // can be combined, en-mass, with the _NO_ forms later. | ||
2324 | 106 | |||
2325 | 107 | // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 | ||
2326 | 108 | |||
2327 | 109 | #if defined(__cplusplus) && __cplusplus >= 201103L | ||
2328 | 110 | # define CATCH_CPP11_OR_GREATER | ||
2329 | 111 | #endif | ||
2330 | 112 | |||
2331 | 113 | #ifdef __clang__ | ||
2332 | 114 | |||
2333 | 115 | # if __has_feature(cxx_nullptr) | ||
2334 | 116 | # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR | ||
2335 | 117 | # endif | ||
2336 | 118 | |||
2337 | 119 | # if __has_feature(cxx_noexcept) | ||
2338 | 120 | # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT | ||
2339 | 121 | # endif | ||
2340 | 122 | |||
2341 | 123 | # if defined(CATCH_CPP11_OR_GREATER) | ||
2342 | 124 | # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) | ||
2343 | 125 | # endif | ||
2344 | 126 | |||
2345 | 127 | #endif // __clang__ | ||
2346 | 128 | |||
2347 | 129 | //////////////////////////////////////////////////////////////////////////////// | ||
2348 | 130 | // Borland | ||
2349 | 131 | #ifdef __BORLANDC__ | ||
2350 | 132 | |||
2351 | 133 | #endif // __BORLANDC__ | ||
2352 | 134 | |||
2353 | 135 | //////////////////////////////////////////////////////////////////////////////// | ||
2354 | 136 | // EDG | ||
2355 | 137 | #ifdef __EDG_VERSION__ | ||
2356 | 138 | |||
2357 | 139 | #endif // __EDG_VERSION__ | ||
2358 | 140 | |||
2359 | 141 | //////////////////////////////////////////////////////////////////////////////// | ||
2360 | 142 | // Digital Mars | ||
2361 | 143 | #ifdef __DMC__ | ||
2362 | 144 | |||
2363 | 145 | #endif // __DMC__ | ||
2364 | 146 | |||
2365 | 147 | //////////////////////////////////////////////////////////////////////////////// | ||
2366 | 148 | // GCC | ||
2367 | 149 | #ifdef __GNUC__ | ||
2368 | 150 | |||
2369 | 151 | # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) | ||
2370 | 152 | # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR | ||
2371 | 153 | # endif | ||
2372 | 154 | |||
2373 | 155 | # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) | ||
2374 | 156 | # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) | ||
2375 | 157 | # endif | ||
2376 | 158 | |||
2377 | 159 | // - otherwise more recent versions define __cplusplus >= 201103L | ||
2378 | 160 | // and will get picked up below | ||
2379 | 161 | |||
2380 | 162 | #endif // __GNUC__ | ||
2381 | 163 | |||
2382 | 164 | //////////////////////////////////////////////////////////////////////////////// | ||
2383 | 165 | // Visual C++ | ||
2384 | 166 | #ifdef _MSC_VER | ||
2385 | 167 | |||
2386 | 168 | #if (_MSC_VER >= 1600) | ||
2387 | 169 | # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR | ||
2388 | 170 | # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR | ||
2389 | 171 | #endif | ||
2390 | 172 | |||
2391 | 173 | #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) | ||
2392 | 174 | #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT | ||
2393 | 175 | #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS | ||
2394 | 176 | #endif | ||
2395 | 177 | |||
2396 | 178 | #endif // _MSC_VER | ||
2397 | 179 | |||
2398 | 180 | //////////////////////////////////////////////////////////////////////////////// | ||
2399 | 181 | |||
2400 | 182 | // Use variadic macros if the compiler supports them | ||
2401 | 183 | #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ | ||
2402 | 184 | ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ | ||
2403 | 185 | ( defined __GNUC__ && __GNUC__ >= 3 ) || \ | ||
2404 | 186 | ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) | ||
2405 | 187 | |||
2406 | 188 | #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS | ||
2407 | 189 | |||
2408 | 190 | #endif | ||
2409 | 191 | |||
2410 | 192 | // Use __COUNTER__ if the compiler supports it | ||
2411 | 193 | #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ | ||
2412 | 194 | ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ | ||
2413 | 195 | ( defined __clang__ && __clang_major__ >= 3 ) | ||
2414 | 196 | |||
2415 | 197 | #define CATCH_INTERNAL_CONFIG_COUNTER | ||
2416 | 198 | |||
2417 | 199 | #endif | ||
2418 | 200 | |||
2419 | 201 | //////////////////////////////////////////////////////////////////////////////// | ||
2420 | 202 | // C++ language feature support | ||
2421 | 203 | |||
2422 | 204 | // catch all support for C++11 | ||
2423 | 205 | #if defined(CATCH_CPP11_OR_GREATER) | ||
2424 | 206 | |||
2425 | 207 | # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) | ||
2426 | 208 | # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR | ||
2427 | 209 | # endif | ||
2428 | 210 | |||
2429 | 211 | # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT | ||
2430 | 212 | # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT | ||
2431 | 213 | # endif | ||
2432 | 214 | |||
2433 | 215 | # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS | ||
2434 | 216 | # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS | ||
2435 | 217 | # endif | ||
2436 | 218 | |||
2437 | 219 | # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM | ||
2438 | 220 | # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM | ||
2439 | 221 | # endif | ||
2440 | 222 | |||
2441 | 223 | # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE | ||
2442 | 224 | # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE | ||
2443 | 225 | # endif | ||
2444 | 226 | |||
2445 | 227 | # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS | ||
2446 | 228 | # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS | ||
2447 | 229 | # endif | ||
2448 | 230 | |||
2449 | 231 | # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) | ||
2450 | 232 | # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG | ||
2451 | 233 | # endif | ||
2452 | 234 | |||
2453 | 235 | # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) | ||
2454 | 236 | # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE | ||
2455 | 237 | # endif | ||
2456 | 238 | # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) | ||
2457 | 239 | # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR | ||
2458 | 240 | # endif | ||
2459 | 241 | |||
2460 | 242 | #endif // __cplusplus >= 201103L | ||
2461 | 243 | |||
2462 | 244 | // Now set the actual defines based on the above + anything the user has configured | ||
2463 | 245 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2464 | 246 | # define CATCH_CONFIG_CPP11_NULLPTR | ||
2465 | 247 | #endif | ||
2466 | 248 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2467 | 249 | # define CATCH_CONFIG_CPP11_NOEXCEPT | ||
2468 | 250 | #endif | ||
2469 | 251 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2470 | 252 | # define CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
2471 | 253 | #endif | ||
2472 | 254 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2473 | 255 | # define CATCH_CONFIG_CPP11_IS_ENUM | ||
2474 | 256 | #endif | ||
2475 | 257 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2476 | 258 | # define CATCH_CONFIG_CPP11_TUPLE | ||
2477 | 259 | #endif | ||
2478 | 260 | #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) | ||
2479 | 261 | # define CATCH_CONFIG_VARIADIC_MACROS | ||
2480 | 262 | #endif | ||
2481 | 263 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2482 | 264 | # define CATCH_CONFIG_CPP11_LONG_LONG | ||
2483 | 265 | #endif | ||
2484 | 266 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2485 | 267 | # define CATCH_CONFIG_CPP11_OVERRIDE | ||
2486 | 268 | #endif | ||
2487 | 269 | #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) | ||
2488 | 270 | # define CATCH_CONFIG_CPP11_UNIQUE_PTR | ||
2489 | 271 | #endif | ||
2490 | 272 | #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) | ||
2491 | 273 | # define CATCH_CONFIG_COUNTER | ||
2492 | 274 | #endif | ||
2493 | 275 | |||
2494 | 276 | #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) | ||
2495 | 277 | # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS | ||
2496 | 278 | #endif | ||
2497 | 279 | |||
2498 | 280 | // noexcept support: | ||
2499 | 281 | #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) | ||
2500 | 282 | # define CATCH_NOEXCEPT noexcept | ||
2501 | 283 | # define CATCH_NOEXCEPT_IS(x) noexcept(x) | ||
2502 | 284 | #else | ||
2503 | 285 | # define CATCH_NOEXCEPT throw() | ||
2504 | 286 | # define CATCH_NOEXCEPT_IS(x) | ||
2505 | 287 | #endif | ||
2506 | 288 | |||
2507 | 289 | // nullptr support | ||
2508 | 290 | #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||
2509 | 291 | # define CATCH_NULL nullptr | ||
2510 | 292 | #else | ||
2511 | 293 | # define CATCH_NULL NULL | ||
2512 | 294 | #endif | ||
2513 | 295 | |||
2514 | 296 | // override support | ||
2515 | 297 | #ifdef CATCH_CONFIG_CPP11_OVERRIDE | ||
2516 | 298 | # define CATCH_OVERRIDE override | ||
2517 | 299 | #else | ||
2518 | 300 | # define CATCH_OVERRIDE | ||
2519 | 301 | #endif | ||
2520 | 302 | |||
2521 | 303 | // unique_ptr support | ||
2522 | 304 | #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR | ||
2523 | 305 | # define CATCH_AUTO_PTR( T ) std::unique_ptr<T> | ||
2524 | 306 | #else | ||
2525 | 307 | # define CATCH_AUTO_PTR( T ) std::auto_ptr<T> | ||
2526 | 308 | #endif | ||
2527 | 309 | |||
2528 | 310 | namespace Catch { | ||
2529 | 311 | |||
2530 | 312 | struct IConfig; | ||
2531 | 313 | |||
2532 | 314 | struct CaseSensitive { enum Choice { | ||
2533 | 315 | Yes, | ||
2534 | 316 | No | ||
2535 | 317 | }; }; | ||
2536 | 318 | |||
2537 | 319 | class NonCopyable { | ||
2538 | 320 | #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
2539 | 321 | NonCopyable( NonCopyable const& ) = delete; | ||
2540 | 322 | NonCopyable( NonCopyable && ) = delete; | ||
2541 | 323 | NonCopyable& operator = ( NonCopyable const& ) = delete; | ||
2542 | 324 | NonCopyable& operator = ( NonCopyable && ) = delete; | ||
2543 | 325 | #else | ||
2544 | 326 | NonCopyable( NonCopyable const& info ); | ||
2545 | 327 | NonCopyable& operator = ( NonCopyable const& ); | ||
2546 | 328 | #endif | ||
2547 | 329 | |||
2548 | 330 | protected: | ||
2549 | 331 | NonCopyable() {} | ||
2550 | 332 | virtual ~NonCopyable(); | ||
2551 | 333 | }; | ||
2552 | 334 | |||
2553 | 335 | class SafeBool { | ||
2554 | 336 | public: | ||
2555 | 337 | typedef void (SafeBool::*type)() const; | ||
2556 | 338 | |||
2557 | 339 | static type makeSafe( bool value ) { | ||
2558 | 340 | return value ? &SafeBool::trueValue : 0; | ||
2559 | 341 | } | ||
2560 | 342 | private: | ||
2561 | 343 | void trueValue() const {} | ||
2562 | 344 | }; | ||
2563 | 345 | |||
2564 | 346 | template<typename ContainerT> | ||
2565 | 347 | inline void deleteAll( ContainerT& container ) { | ||
2566 | 348 | typename ContainerT::const_iterator it = container.begin(); | ||
2567 | 349 | typename ContainerT::const_iterator itEnd = container.end(); | ||
2568 | 350 | for(; it != itEnd; ++it ) | ||
2569 | 351 | delete *it; | ||
2570 | 352 | } | ||
2571 | 353 | template<typename AssociativeContainerT> | ||
2572 | 354 | inline void deleteAllValues( AssociativeContainerT& container ) { | ||
2573 | 355 | typename AssociativeContainerT::const_iterator it = container.begin(); | ||
2574 | 356 | typename AssociativeContainerT::const_iterator itEnd = container.end(); | ||
2575 | 357 | for(; it != itEnd; ++it ) | ||
2576 | 358 | delete it->second; | ||
2577 | 359 | } | ||
2578 | 360 | |||
2579 | 361 | bool startsWith( std::string const& s, std::string const& prefix ); | ||
2580 | 362 | bool endsWith( std::string const& s, std::string const& suffix ); | ||
2581 | 363 | bool contains( std::string const& s, std::string const& infix ); | ||
2582 | 364 | void toLowerInPlace( std::string& s ); | ||
2583 | 365 | std::string toLower( std::string const& s ); | ||
2584 | 366 | std::string trim( std::string const& str ); | ||
2585 | 367 | bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); | ||
2586 | 368 | |||
2587 | 369 | struct pluralise { | ||
2588 | 370 | pluralise( std::size_t count, std::string const& label ); | ||
2589 | 371 | |||
2590 | 372 | friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); | ||
2591 | 373 | |||
2592 | 374 | std::size_t m_count; | ||
2593 | 375 | std::string m_label; | ||
2594 | 376 | }; | ||
2595 | 377 | |||
2596 | 378 | struct SourceLineInfo { | ||
2597 | 379 | |||
2598 | 380 | SourceLineInfo(); | ||
2599 | 381 | SourceLineInfo( char const* _file, std::size_t _line ); | ||
2600 | 382 | SourceLineInfo( SourceLineInfo const& other ); | ||
2601 | 383 | # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
2602 | 384 | SourceLineInfo( SourceLineInfo && ) = default; | ||
2603 | 385 | SourceLineInfo& operator = ( SourceLineInfo const& ) = default; | ||
2604 | 386 | SourceLineInfo& operator = ( SourceLineInfo && ) = default; | ||
2605 | 387 | # endif | ||
2606 | 388 | bool empty() const; | ||
2607 | 389 | bool operator == ( SourceLineInfo const& other ) const; | ||
2608 | 390 | bool operator < ( SourceLineInfo const& other ) const; | ||
2609 | 391 | |||
2610 | 392 | std::string file; | ||
2611 | 393 | std::size_t line; | ||
2612 | 394 | }; | ||
2613 | 395 | |||
2614 | 396 | std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); | ||
2615 | 397 | |||
2616 | 398 | // This is just here to avoid compiler warnings with macro constants and boolean literals | ||
2617 | 399 | inline bool isTrue( bool value ){ return value; } | ||
2618 | 400 | inline bool alwaysTrue() { return true; } | ||
2619 | 401 | inline bool alwaysFalse() { return false; } | ||
2620 | 402 | |||
2621 | 403 | void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); | ||
2622 | 404 | |||
2623 | 405 | void seedRng( IConfig const& config ); | ||
2624 | 406 | unsigned int rngSeed(); | ||
2625 | 407 | |||
2626 | 408 | // Use this in variadic streaming macros to allow | ||
2627 | 409 | // >> +StreamEndStop | ||
2628 | 410 | // as well as | ||
2629 | 411 | // >> stuff +StreamEndStop | ||
2630 | 412 | struct StreamEndStop { | ||
2631 | 413 | std::string operator+() { | ||
2632 | 414 | return std::string(); | ||
2633 | 415 | } | ||
2634 | 416 | }; | ||
2635 | 417 | template<typename T> | ||
2636 | 418 | T const& operator + ( T const& value, StreamEndStop ) { | ||
2637 | 419 | return value; | ||
2638 | 420 | } | ||
2639 | 421 | } | ||
2640 | 422 | |||
2641 | 423 | #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) | ||
2642 | 424 | #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); | ||
2643 | 425 | |||
2644 | 426 | #include <ostream> | ||
2645 | 427 | |||
2646 | 428 | namespace Catch { | ||
2647 | 429 | |||
2648 | 430 | class NotImplementedException : public std::exception | ||
2649 | 431 | { | ||
2650 | 432 | public: | ||
2651 | 433 | NotImplementedException( SourceLineInfo const& lineInfo ); | ||
2652 | 434 | NotImplementedException( NotImplementedException const& ) {} | ||
2653 | 435 | |||
2654 | 436 | virtual ~NotImplementedException() CATCH_NOEXCEPT {} | ||
2655 | 437 | |||
2656 | 438 | virtual const char* what() const CATCH_NOEXCEPT; | ||
2657 | 439 | |||
2658 | 440 | private: | ||
2659 | 441 | std::string m_what; | ||
2660 | 442 | SourceLineInfo m_lineInfo; | ||
2661 | 443 | }; | ||
2662 | 444 | |||
2663 | 445 | } // end namespace Catch | ||
2664 | 446 | |||
2665 | 447 | /////////////////////////////////////////////////////////////////////////////// | ||
2666 | 448 | #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) | ||
2667 | 449 | |||
2668 | 450 | // #included from: internal/catch_context.h | ||
2669 | 451 | #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED | ||
2670 | 452 | |||
2671 | 453 | // #included from: catch_interfaces_generators.h | ||
2672 | 454 | #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED | ||
2673 | 455 | |||
2674 | 456 | #include <string> | ||
2675 | 457 | |||
2676 | 458 | namespace Catch { | ||
2677 | 459 | |||
2678 | 460 | struct IGeneratorInfo { | ||
2679 | 461 | virtual ~IGeneratorInfo(); | ||
2680 | 462 | virtual bool moveNext() = 0; | ||
2681 | 463 | virtual std::size_t getCurrentIndex() const = 0; | ||
2682 | 464 | }; | ||
2683 | 465 | |||
2684 | 466 | struct IGeneratorsForTest { | ||
2685 | 467 | virtual ~IGeneratorsForTest(); | ||
2686 | 468 | |||
2687 | 469 | virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; | ||
2688 | 470 | virtual bool moveNext() = 0; | ||
2689 | 471 | }; | ||
2690 | 472 | |||
2691 | 473 | IGeneratorsForTest* createGeneratorsForTest(); | ||
2692 | 474 | |||
2693 | 475 | } // end namespace Catch | ||
2694 | 476 | |||
2695 | 477 | // #included from: catch_ptr.hpp | ||
2696 | 478 | #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED | ||
2697 | 479 | |||
2698 | 480 | #ifdef __clang__ | ||
2699 | 481 | #pragma clang diagnostic push | ||
2700 | 482 | #pragma clang diagnostic ignored "-Wpadded" | ||
2701 | 483 | #endif | ||
2702 | 484 | |||
2703 | 485 | namespace Catch { | ||
2704 | 486 | |||
2705 | 487 | // An intrusive reference counting smart pointer. | ||
2706 | 488 | // T must implement addRef() and release() methods | ||
2707 | 489 | // typically implementing the IShared interface | ||
2708 | 490 | template<typename T> | ||
2709 | 491 | class Ptr { | ||
2710 | 492 | public: | ||
2711 | 493 | Ptr() : m_p( CATCH_NULL ){} | ||
2712 | 494 | Ptr( T* p ) : m_p( p ){ | ||
2713 | 495 | if( m_p ) | ||
2714 | 496 | m_p->addRef(); | ||
2715 | 497 | } | ||
2716 | 498 | Ptr( Ptr const& other ) : m_p( other.m_p ){ | ||
2717 | 499 | if( m_p ) | ||
2718 | 500 | m_p->addRef(); | ||
2719 | 501 | } | ||
2720 | 502 | ~Ptr(){ | ||
2721 | 503 | if( m_p ) | ||
2722 | 504 | m_p->release(); | ||
2723 | 505 | } | ||
2724 | 506 | void reset() { | ||
2725 | 507 | if( m_p ) | ||
2726 | 508 | m_p->release(); | ||
2727 | 509 | m_p = CATCH_NULL; | ||
2728 | 510 | } | ||
2729 | 511 | Ptr& operator = ( T* p ){ | ||
2730 | 512 | Ptr temp( p ); | ||
2731 | 513 | swap( temp ); | ||
2732 | 514 | return *this; | ||
2733 | 515 | } | ||
2734 | 516 | Ptr& operator = ( Ptr const& other ){ | ||
2735 | 517 | Ptr temp( other ); | ||
2736 | 518 | swap( temp ); | ||
2737 | 519 | return *this; | ||
2738 | 520 | } | ||
2739 | 521 | void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } | ||
2740 | 522 | T* get() const{ return m_p; } | ||
2741 | 523 | T& operator*() const { return *m_p; } | ||
2742 | 524 | T* operator->() const { return m_p; } | ||
2743 | 525 | bool operator !() const { return m_p == CATCH_NULL; } | ||
2744 | 526 | operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } | ||
2745 | 527 | |||
2746 | 528 | private: | ||
2747 | 529 | T* m_p; | ||
2748 | 530 | }; | ||
2749 | 531 | |||
2750 | 532 | struct IShared : NonCopyable { | ||
2751 | 533 | virtual ~IShared(); | ||
2752 | 534 | virtual void addRef() const = 0; | ||
2753 | 535 | virtual void release() const = 0; | ||
2754 | 536 | }; | ||
2755 | 537 | |||
2756 | 538 | template<typename T = IShared> | ||
2757 | 539 | struct SharedImpl : T { | ||
2758 | 540 | |||
2759 | 541 | SharedImpl() : m_rc( 0 ){} | ||
2760 | 542 | |||
2761 | 543 | virtual void addRef() const { | ||
2762 | 544 | ++m_rc; | ||
2763 | 545 | } | ||
2764 | 546 | virtual void release() const { | ||
2765 | 547 | if( --m_rc == 0 ) | ||
2766 | 548 | delete this; | ||
2767 | 549 | } | ||
2768 | 550 | |||
2769 | 551 | mutable unsigned int m_rc; | ||
2770 | 552 | }; | ||
2771 | 553 | |||
2772 | 554 | } // end namespace Catch | ||
2773 | 555 | |||
2774 | 556 | #ifdef __clang__ | ||
2775 | 557 | #pragma clang diagnostic pop | ||
2776 | 558 | #endif | ||
2777 | 559 | |||
2778 | 560 | #include <memory> | ||
2779 | 561 | #include <vector> | ||
2780 | 562 | #include <stdlib.h> | ||
2781 | 563 | |||
2782 | 564 | namespace Catch { | ||
2783 | 565 | |||
2784 | 566 | class TestCase; | ||
2785 | 567 | class Stream; | ||
2786 | 568 | struct IResultCapture; | ||
2787 | 569 | struct IRunner; | ||
2788 | 570 | struct IGeneratorsForTest; | ||
2789 | 571 | struct IConfig; | ||
2790 | 572 | |||
2791 | 573 | struct IContext | ||
2792 | 574 | { | ||
2793 | 575 | virtual ~IContext(); | ||
2794 | 576 | |||
2795 | 577 | virtual IResultCapture* getResultCapture() = 0; | ||
2796 | 578 | virtual IRunner* getRunner() = 0; | ||
2797 | 579 | virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; | ||
2798 | 580 | virtual bool advanceGeneratorsForCurrentTest() = 0; | ||
2799 | 581 | virtual Ptr<IConfig const> getConfig() const = 0; | ||
2800 | 582 | }; | ||
2801 | 583 | |||
2802 | 584 | struct IMutableContext : IContext | ||
2803 | 585 | { | ||
2804 | 586 | virtual ~IMutableContext(); | ||
2805 | 587 | virtual void setResultCapture( IResultCapture* resultCapture ) = 0; | ||
2806 | 588 | virtual void setRunner( IRunner* runner ) = 0; | ||
2807 | 589 | virtual void setConfig( Ptr<IConfig const> const& config ) = 0; | ||
2808 | 590 | }; | ||
2809 | 591 | |||
2810 | 592 | IContext& getCurrentContext(); | ||
2811 | 593 | IMutableContext& getCurrentMutableContext(); | ||
2812 | 594 | void cleanUpContext(); | ||
2813 | 595 | Stream createStream( std::string const& streamName ); | ||
2814 | 596 | |||
2815 | 597 | } | ||
2816 | 598 | |||
2817 | 599 | // #included from: internal/catch_test_registry.hpp | ||
2818 | 600 | #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED | ||
2819 | 601 | |||
2820 | 602 | // #included from: catch_interfaces_testcase.h | ||
2821 | 603 | #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED | ||
2822 | 604 | |||
2823 | 605 | #include <vector> | ||
2824 | 606 | |||
2825 | 607 | namespace Catch { | ||
2826 | 608 | |||
2827 | 609 | class TestSpec; | ||
2828 | 610 | |||
2829 | 611 | struct ITestCase : IShared { | ||
2830 | 612 | virtual void invoke () const = 0; | ||
2831 | 613 | protected: | ||
2832 | 614 | virtual ~ITestCase(); | ||
2833 | 615 | }; | ||
2834 | 616 | |||
2835 | 617 | class TestCase; | ||
2836 | 618 | struct IConfig; | ||
2837 | 619 | |||
2838 | 620 | struct ITestCaseRegistry { | ||
2839 | 621 | virtual ~ITestCaseRegistry(); | ||
2840 | 622 | virtual std::vector<TestCase> const& getAllTests() const = 0; | ||
2841 | 623 | virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; | ||
2842 | 624 | }; | ||
2843 | 625 | |||
2844 | 626 | bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); | ||
2845 | 627 | std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); | ||
2846 | 628 | std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); | ||
2847 | 629 | |||
2848 | 630 | } | ||
2849 | 631 | |||
2850 | 632 | namespace Catch { | ||
2851 | 633 | |||
2852 | 634 | template<typename C> | ||
2853 | 635 | class MethodTestCase : public SharedImpl<ITestCase> { | ||
2854 | 636 | |||
2855 | 637 | public: | ||
2856 | 638 | MethodTestCase( void (C::*method)() ) : m_method( method ) {} | ||
2857 | 639 | |||
2858 | 640 | virtual void invoke() const { | ||
2859 | 641 | C obj; | ||
2860 | 642 | (obj.*m_method)(); | ||
2861 | 643 | } | ||
2862 | 644 | |||
2863 | 645 | private: | ||
2864 | 646 | virtual ~MethodTestCase() {} | ||
2865 | 647 | |||
2866 | 648 | void (C::*m_method)(); | ||
2867 | 649 | }; | ||
2868 | 650 | |||
2869 | 651 | typedef void(*TestFunction)(); | ||
2870 | 652 | |||
2871 | 653 | struct NameAndDesc { | ||
2872 | 654 | NameAndDesc( const char* _name = "", const char* _description= "" ) | ||
2873 | 655 | : name( _name ), description( _description ) | ||
2874 | 656 | {} | ||
2875 | 657 | |||
2876 | 658 | const char* name; | ||
2877 | 659 | const char* description; | ||
2878 | 660 | }; | ||
2879 | 661 | |||
2880 | 662 | void registerTestCase | ||
2881 | 663 | ( ITestCase* testCase, | ||
2882 | 664 | char const* className, | ||
2883 | 665 | NameAndDesc const& nameAndDesc, | ||
2884 | 666 | SourceLineInfo const& lineInfo ); | ||
2885 | 667 | |||
2886 | 668 | struct AutoReg { | ||
2887 | 669 | |||
2888 | 670 | AutoReg | ||
2889 | 671 | ( TestFunction function, | ||
2890 | 672 | SourceLineInfo const& lineInfo, | ||
2891 | 673 | NameAndDesc const& nameAndDesc ); | ||
2892 | 674 | |||
2893 | 675 | template<typename C> | ||
2894 | 676 | AutoReg | ||
2895 | 677 | ( void (C::*method)(), | ||
2896 | 678 | char const* className, | ||
2897 | 679 | NameAndDesc const& nameAndDesc, | ||
2898 | 680 | SourceLineInfo const& lineInfo ) { | ||
2899 | 681 | |||
2900 | 682 | registerTestCase | ||
2901 | 683 | ( new MethodTestCase<C>( method ), | ||
2902 | 684 | className, | ||
2903 | 685 | nameAndDesc, | ||
2904 | 686 | lineInfo ); | ||
2905 | 687 | } | ||
2906 | 688 | |||
2907 | 689 | ~AutoReg(); | ||
2908 | 690 | |||
2909 | 691 | private: | ||
2910 | 692 | AutoReg( AutoReg const& ); | ||
2911 | 693 | void operator= ( AutoReg const& ); | ||
2912 | 694 | }; | ||
2913 | 695 | |||
2914 | 696 | void registerTestCaseFunction | ||
2915 | 697 | ( TestFunction function, | ||
2916 | 698 | SourceLineInfo const& lineInfo, | ||
2917 | 699 | NameAndDesc const& nameAndDesc ); | ||
2918 | 700 | |||
2919 | 701 | } // end namespace Catch | ||
2920 | 702 | |||
2921 | 703 | #ifdef CATCH_CONFIG_VARIADIC_MACROS | ||
2922 | 704 | /////////////////////////////////////////////////////////////////////////////// | ||
2923 | 705 | #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ | ||
2924 | 706 | static void TestName(); \ | ||
2925 | 707 | namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ | ||
2926 | 708 | static void TestName() | ||
2927 | 709 | #define INTERNAL_CATCH_TESTCASE( ... ) \ | ||
2928 | 710 | INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) | ||
2929 | 711 | |||
2930 | 712 | /////////////////////////////////////////////////////////////////////////////// | ||
2931 | 713 | #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ | ||
2932 | 714 | namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } | ||
2933 | 715 | |||
2934 | 716 | /////////////////////////////////////////////////////////////////////////////// | ||
2935 | 717 | #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ | ||
2936 | 718 | namespace{ \ | ||
2937 | 719 | struct TestName : ClassName{ \ | ||
2938 | 720 | void test(); \ | ||
2939 | 721 | }; \ | ||
2940 | 722 | Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ | ||
2941 | 723 | } \ | ||
2942 | 724 | void TestName::test() | ||
2943 | 725 | #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ | ||
2944 | 726 | INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) | ||
2945 | 727 | |||
2946 | 728 | /////////////////////////////////////////////////////////////////////////////// | ||
2947 | 729 | #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ | ||
2948 | 730 | Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); | ||
2949 | 731 | |||
2950 | 732 | #else | ||
2951 | 733 | /////////////////////////////////////////////////////////////////////////////// | ||
2952 | 734 | #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ | ||
2953 | 735 | static void TestName(); \ | ||
2954 | 736 | namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ | ||
2955 | 737 | static void TestName() | ||
2956 | 738 | #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ | ||
2957 | 739 | INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) | ||
2958 | 740 | |||
2959 | 741 | /////////////////////////////////////////////////////////////////////////////// | ||
2960 | 742 | #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ | ||
2961 | 743 | namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } | ||
2962 | 744 | |||
2963 | 745 | /////////////////////////////////////////////////////////////////////////////// | ||
2964 | 746 | #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ | ||
2965 | 747 | namespace{ \ | ||
2966 | 748 | struct TestCaseName : ClassName{ \ | ||
2967 | 749 | void test(); \ | ||
2968 | 750 | }; \ | ||
2969 | 751 | Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ | ||
2970 | 752 | } \ | ||
2971 | 753 | void TestCaseName::test() | ||
2972 | 754 | #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ | ||
2973 | 755 | INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) | ||
2974 | 756 | |||
2975 | 757 | /////////////////////////////////////////////////////////////////////////////// | ||
2976 | 758 | #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ | ||
2977 | 759 | Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); | ||
2978 | 760 | #endif | ||
2979 | 761 | |||
2980 | 762 | // #included from: internal/catch_capture.hpp | ||
2981 | 763 | #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||
2982 | 764 | |||
2983 | 765 | // #included from: catch_result_builder.h | ||
2984 | 766 | #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED | ||
2985 | 767 | |||
2986 | 768 | // #included from: catch_result_type.h | ||
2987 | 769 | #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED | ||
2988 | 770 | |||
2989 | 771 | namespace Catch { | ||
2990 | 772 | |||
2991 | 773 | // ResultWas::OfType enum | ||
2992 | 774 | struct ResultWas { enum OfType { | ||
2993 | 775 | Unknown = -1, | ||
2994 | 776 | Ok = 0, | ||
2995 | 777 | Info = 1, | ||
2996 | 778 | Warning = 2, | ||
2997 | 779 | |||
2998 | 780 | FailureBit = 0x10, | ||
2999 | 781 | |||
3000 | 782 | ExpressionFailed = FailureBit | 1, | ||
3001 | 783 | ExplicitFailure = FailureBit | 2, | ||
3002 | 784 | |||
3003 | 785 | Exception = 0x100 | FailureBit, | ||
3004 | 786 | |||
3005 | 787 | ThrewException = Exception | 1, | ||
3006 | 788 | DidntThrowException = Exception | 2, | ||
3007 | 789 | |||
3008 | 790 | FatalErrorCondition = 0x200 | FailureBit | ||
3009 | 791 | |||
3010 | 792 | }; }; | ||
3011 | 793 | |||
3012 | 794 | inline bool isOk( ResultWas::OfType resultType ) { | ||
3013 | 795 | return ( resultType & ResultWas::FailureBit ) == 0; | ||
3014 | 796 | } | ||
3015 | 797 | inline bool isJustInfo( int flags ) { | ||
3016 | 798 | return flags == ResultWas::Info; | ||
3017 | 799 | } | ||
3018 | 800 | |||
3019 | 801 | // ResultDisposition::Flags enum | ||
3020 | 802 | struct ResultDisposition { enum Flags { | ||
3021 | 803 | Normal = 0x01, | ||
3022 | 804 | |||
3023 | 805 | ContinueOnFailure = 0x02, // Failures fail test, but execution continues | ||
3024 | 806 | FalseTest = 0x04, // Prefix expression with ! | ||
3025 | 807 | SuppressFail = 0x08 // Failures are reported but do not fail the test | ||
3026 | 808 | }; }; | ||
3027 | 809 | |||
3028 | 810 | inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { | ||
3029 | 811 | return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); | ||
3030 | 812 | } | ||
3031 | 813 | |||
3032 | 814 | inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } | ||
3033 | 815 | inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } | ||
3034 | 816 | inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } | ||
3035 | 817 | |||
3036 | 818 | } // end namespace Catch | ||
3037 | 819 | |||
3038 | 820 | // #included from: catch_assertionresult.h | ||
3039 | 821 | #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED | ||
3040 | 822 | |||
3041 | 823 | #include <string> | ||
3042 | 824 | |||
3043 | 825 | namespace Catch { | ||
3044 | 826 | |||
3045 | 827 | struct AssertionInfo | ||
3046 | 828 | { | ||
3047 | 829 | AssertionInfo() {} | ||
3048 | 830 | AssertionInfo( std::string const& _macroName, | ||
3049 | 831 | SourceLineInfo const& _lineInfo, | ||
3050 | 832 | std::string const& _capturedExpression, | ||
3051 | 833 | ResultDisposition::Flags _resultDisposition ); | ||
3052 | 834 | |||
3053 | 835 | std::string macroName; | ||
3054 | 836 | SourceLineInfo lineInfo; | ||
3055 | 837 | std::string capturedExpression; | ||
3056 | 838 | ResultDisposition::Flags resultDisposition; | ||
3057 | 839 | }; | ||
3058 | 840 | |||
3059 | 841 | struct AssertionResultData | ||
3060 | 842 | { | ||
3061 | 843 | AssertionResultData() : resultType( ResultWas::Unknown ) {} | ||
3062 | 844 | |||
3063 | 845 | std::string reconstructedExpression; | ||
3064 | 846 | std::string message; | ||
3065 | 847 | ResultWas::OfType resultType; | ||
3066 | 848 | }; | ||
3067 | 849 | |||
3068 | 850 | class AssertionResult { | ||
3069 | 851 | public: | ||
3070 | 852 | AssertionResult(); | ||
3071 | 853 | AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); | ||
3072 | 854 | ~AssertionResult(); | ||
3073 | 855 | # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
3074 | 856 | AssertionResult( AssertionResult const& ) = default; | ||
3075 | 857 | AssertionResult( AssertionResult && ) = default; | ||
3076 | 858 | AssertionResult& operator = ( AssertionResult const& ) = default; | ||
3077 | 859 | AssertionResult& operator = ( AssertionResult && ) = default; | ||
3078 | 860 | # endif | ||
3079 | 861 | |||
3080 | 862 | bool isOk() const; | ||
3081 | 863 | bool succeeded() const; | ||
3082 | 864 | ResultWas::OfType getResultType() const; | ||
3083 | 865 | bool hasExpression() const; | ||
3084 | 866 | bool hasMessage() const; | ||
3085 | 867 | std::string getExpression() const; | ||
3086 | 868 | std::string getExpressionInMacro() const; | ||
3087 | 869 | bool hasExpandedExpression() const; | ||
3088 | 870 | std::string getExpandedExpression() const; | ||
3089 | 871 | std::string getMessage() const; | ||
3090 | 872 | SourceLineInfo getSourceInfo() const; | ||
3091 | 873 | std::string getTestMacroName() const; | ||
3092 | 874 | |||
3093 | 875 | protected: | ||
3094 | 876 | AssertionInfo m_info; | ||
3095 | 877 | AssertionResultData m_resultData; | ||
3096 | 878 | }; | ||
3097 | 879 | |||
3098 | 880 | } // end namespace Catch | ||
3099 | 881 | |||
3100 | 882 | // #included from: catch_matchers.hpp | ||
3101 | 883 | #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | ||
3102 | 884 | |||
3103 | 885 | namespace Catch { | ||
3104 | 886 | namespace Matchers { | ||
3105 | 887 | namespace Impl { | ||
3106 | 888 | |||
3107 | 889 | namespace Generic { | ||
3108 | 890 | template<typename ExpressionT> class AllOf; | ||
3109 | 891 | template<typename ExpressionT> class AnyOf; | ||
3110 | 892 | template<typename ExpressionT> class Not; | ||
3111 | 893 | } | ||
3112 | 894 | |||
3113 | 895 | template<typename ExpressionT> | ||
3114 | 896 | struct Matcher : SharedImpl<IShared> | ||
3115 | 897 | { | ||
3116 | 898 | typedef ExpressionT ExpressionType; | ||
3117 | 899 | |||
3118 | 900 | virtual ~Matcher() {} | ||
3119 | 901 | virtual Ptr<Matcher> clone() const = 0; | ||
3120 | 902 | virtual bool match( ExpressionT const& expr ) const = 0; | ||
3121 | 903 | virtual std::string toString() const = 0; | ||
3122 | 904 | |||
3123 | 905 | Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const; | ||
3124 | 906 | Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const; | ||
3125 | 907 | Generic::Not<ExpressionT> operator ! () const; | ||
3126 | 908 | }; | ||
3127 | 909 | |||
3128 | 910 | template<typename DerivedT, typename ExpressionT> | ||
3129 | 911 | struct MatcherImpl : Matcher<ExpressionT> { | ||
3130 | 912 | |||
3131 | 913 | virtual Ptr<Matcher<ExpressionT> > clone() const { | ||
3132 | 914 | return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) ); | ||
3133 | 915 | } | ||
3134 | 916 | }; | ||
3135 | 917 | |||
3136 | 918 | namespace Generic { | ||
3137 | 919 | template<typename ExpressionT> | ||
3138 | 920 | class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> { | ||
3139 | 921 | public: | ||
3140 | 922 | explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {} | ||
3141 | 923 | Not( Not const& other ) : m_matcher( other.m_matcher ) {} | ||
3142 | 924 | |||
3143 | 925 | virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { | ||
3144 | 926 | return !m_matcher->match( expr ); | ||
3145 | 927 | } | ||
3146 | 928 | |||
3147 | 929 | virtual std::string toString() const CATCH_OVERRIDE { | ||
3148 | 930 | return "not " + m_matcher->toString(); | ||
3149 | 931 | } | ||
3150 | 932 | private: | ||
3151 | 933 | Ptr< Matcher<ExpressionT> > m_matcher; | ||
3152 | 934 | }; | ||
3153 | 935 | |||
3154 | 936 | template<typename ExpressionT> | ||
3155 | 937 | class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> { | ||
3156 | 938 | public: | ||
3157 | 939 | |||
3158 | 940 | AllOf() {} | ||
3159 | 941 | AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} | ||
3160 | 942 | |||
3161 | 943 | AllOf& add( Matcher<ExpressionT> const& matcher ) { | ||
3162 | 944 | m_matchers.push_back( matcher.clone() ); | ||
3163 | 945 | return *this; | ||
3164 | 946 | } | ||
3165 | 947 | virtual bool match( ExpressionT const& expr ) const | ||
3166 | 948 | { | ||
3167 | 949 | for( std::size_t i = 0; i < m_matchers.size(); ++i ) | ||
3168 | 950 | if( !m_matchers[i]->match( expr ) ) | ||
3169 | 951 | return false; | ||
3170 | 952 | return true; | ||
3171 | 953 | } | ||
3172 | 954 | virtual std::string toString() const { | ||
3173 | 955 | std::ostringstream oss; | ||
3174 | 956 | oss << "( "; | ||
3175 | 957 | for( std::size_t i = 0; i < m_matchers.size(); ++i ) { | ||
3176 | 958 | if( i != 0 ) | ||
3177 | 959 | oss << " and "; | ||
3178 | 960 | oss << m_matchers[i]->toString(); | ||
3179 | 961 | } | ||
3180 | 962 | oss << " )"; | ||
3181 | 963 | return oss.str(); | ||
3182 | 964 | } | ||
3183 | 965 | |||
3184 | 966 | AllOf operator && ( Matcher<ExpressionT> const& other ) const { | ||
3185 | 967 | AllOf allOfExpr( *this ); | ||
3186 | 968 | allOfExpr.add( other ); | ||
3187 | 969 | return allOfExpr; | ||
3188 | 970 | } | ||
3189 | 971 | |||
3190 | 972 | private: | ||
3191 | 973 | std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; | ||
3192 | 974 | }; | ||
3193 | 975 | |||
3194 | 976 | template<typename ExpressionT> | ||
3195 | 977 | class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> { | ||
3196 | 978 | public: | ||
3197 | 979 | |||
3198 | 980 | AnyOf() {} | ||
3199 | 981 | AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} | ||
3200 | 982 | |||
3201 | 983 | AnyOf& add( Matcher<ExpressionT> const& matcher ) { | ||
3202 | 984 | m_matchers.push_back( matcher.clone() ); | ||
3203 | 985 | return *this; | ||
3204 | 986 | } | ||
3205 | 987 | virtual bool match( ExpressionT const& expr ) const | ||
3206 | 988 | { | ||
3207 | 989 | for( std::size_t i = 0; i < m_matchers.size(); ++i ) | ||
3208 | 990 | if( m_matchers[i]->match( expr ) ) | ||
3209 | 991 | return true; | ||
3210 | 992 | return false; | ||
3211 | 993 | } | ||
3212 | 994 | virtual std::string toString() const { | ||
3213 | 995 | std::ostringstream oss; | ||
3214 | 996 | oss << "( "; | ||
3215 | 997 | for( std::size_t i = 0; i < m_matchers.size(); ++i ) { | ||
3216 | 998 | if( i != 0 ) | ||
3217 | 999 | oss << " or "; | ||
3218 | 1000 | oss << m_matchers[i]->toString(); | ||
3219 | 1001 | } | ||
3220 | 1002 | oss << " )"; | ||
3221 | 1003 | return oss.str(); | ||
3222 | 1004 | } | ||
3223 | 1005 | |||
3224 | 1006 | AnyOf operator || ( Matcher<ExpressionT> const& other ) const { | ||
3225 | 1007 | AnyOf anyOfExpr( *this ); | ||
3226 | 1008 | anyOfExpr.add( other ); | ||
3227 | 1009 | return anyOfExpr; | ||
3228 | 1010 | } | ||
3229 | 1011 | |||
3230 | 1012 | private: | ||
3231 | 1013 | std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; | ||
3232 | 1014 | }; | ||
3233 | 1015 | |||
3234 | 1016 | } // namespace Generic | ||
3235 | 1017 | |||
3236 | 1018 | template<typename ExpressionT> | ||
3237 | 1019 | Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const { | ||
3238 | 1020 | Generic::AllOf<ExpressionT> allOfExpr; | ||
3239 | 1021 | allOfExpr.add( *this ); | ||
3240 | 1022 | allOfExpr.add( other ); | ||
3241 | 1023 | return allOfExpr; | ||
3242 | 1024 | } | ||
3243 | 1025 | |||
3244 | 1026 | template<typename ExpressionT> | ||
3245 | 1027 | Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const { | ||
3246 | 1028 | Generic::AnyOf<ExpressionT> anyOfExpr; | ||
3247 | 1029 | anyOfExpr.add( *this ); | ||
3248 | 1030 | anyOfExpr.add( other ); | ||
3249 | 1031 | return anyOfExpr; | ||
3250 | 1032 | } | ||
3251 | 1033 | |||
3252 | 1034 | template<typename ExpressionT> | ||
3253 | 1035 | Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const { | ||
3254 | 1036 | return Generic::Not<ExpressionT>( *this ); | ||
3255 | 1037 | } | ||
3256 | 1038 | |||
3257 | 1039 | namespace StdString { | ||
3258 | 1040 | |||
3259 | 1041 | inline std::string makeString( std::string const& str ) { return str; } | ||
3260 | 1042 | inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } | ||
3261 | 1043 | |||
3262 | 1044 | struct CasedString | ||
3263 | 1045 | { | ||
3264 | 1046 | CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) | ||
3265 | 1047 | : m_caseSensitivity( caseSensitivity ), | ||
3266 | 1048 | m_str( adjustString( str ) ) | ||
3267 | 1049 | {} | ||
3268 | 1050 | std::string adjustString( std::string const& str ) const { | ||
3269 | 1051 | return m_caseSensitivity == CaseSensitive::No | ||
3270 | 1052 | ? toLower( str ) | ||
3271 | 1053 | : str; | ||
3272 | 1054 | |||
3273 | 1055 | } | ||
3274 | 1056 | std::string toStringSuffix() const | ||
3275 | 1057 | { | ||
3276 | 1058 | return m_caseSensitivity == CaseSensitive::No | ||
3277 | 1059 | ? " (case insensitive)" | ||
3278 | 1060 | : ""; | ||
3279 | 1061 | } | ||
3280 | 1062 | CaseSensitive::Choice m_caseSensitivity; | ||
3281 | 1063 | std::string m_str; | ||
3282 | 1064 | }; | ||
3283 | 1065 | |||
3284 | 1066 | struct Equals : MatcherImpl<Equals, std::string> { | ||
3285 | 1067 | Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) | ||
3286 | 1068 | : m_data( str, caseSensitivity ) | ||
3287 | 1069 | {} | ||
3288 | 1070 | Equals( Equals const& other ) : m_data( other.m_data ){} | ||
3289 | 1071 | |||
3290 | 1072 | virtual ~Equals(); | ||
3291 | 1073 | |||
3292 | 1074 | virtual bool match( std::string const& expr ) const { | ||
3293 | 1075 | return m_data.m_str == m_data.adjustString( expr );; | ||
3294 | 1076 | } | ||
3295 | 1077 | virtual std::string toString() const { | ||
3296 | 1078 | return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); | ||
3297 | 1079 | } | ||
3298 | 1080 | |||
3299 | 1081 | CasedString m_data; | ||
3300 | 1082 | }; | ||
3301 | 1083 | |||
3302 | 1084 | struct Contains : MatcherImpl<Contains, std::string> { | ||
3303 | 1085 | Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) | ||
3304 | 1086 | : m_data( substr, caseSensitivity ){} | ||
3305 | 1087 | Contains( Contains const& other ) : m_data( other.m_data ){} | ||
3306 | 1088 | |||
3307 | 1089 | virtual ~Contains(); | ||
3308 | 1090 | |||
3309 | 1091 | virtual bool match( std::string const& expr ) const { | ||
3310 | 1092 | return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; | ||
3311 | 1093 | } | ||
3312 | 1094 | virtual std::string toString() const { | ||
3313 | 1095 | return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); | ||
3314 | 1096 | } | ||
3315 | 1097 | |||
3316 | 1098 | CasedString m_data; | ||
3317 | 1099 | }; | ||
3318 | 1100 | |||
3319 | 1101 | struct StartsWith : MatcherImpl<StartsWith, std::string> { | ||
3320 | 1102 | StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) | ||
3321 | 1103 | : m_data( substr, caseSensitivity ){} | ||
3322 | 1104 | |||
3323 | 1105 | StartsWith( StartsWith const& other ) : m_data( other.m_data ){} | ||
3324 | 1106 | |||
3325 | 1107 | virtual ~StartsWith(); | ||
3326 | 1108 | |||
3327 | 1109 | virtual bool match( std::string const& expr ) const { | ||
3328 | 1110 | return startsWith( m_data.adjustString( expr ), m_data.m_str ); | ||
3329 | 1111 | } | ||
3330 | 1112 | virtual std::string toString() const { | ||
3331 | 1113 | return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); | ||
3332 | 1114 | } | ||
3333 | 1115 | |||
3334 | 1116 | CasedString m_data; | ||
3335 | 1117 | }; | ||
3336 | 1118 | |||
3337 | 1119 | struct EndsWith : MatcherImpl<EndsWith, std::string> { | ||
3338 | 1120 | EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) | ||
3339 | 1121 | : m_data( substr, caseSensitivity ){} | ||
3340 | 1122 | EndsWith( EndsWith const& other ) : m_data( other.m_data ){} | ||
3341 | 1123 | |||
3342 | 1124 | virtual ~EndsWith(); | ||
3343 | 1125 | |||
3344 | 1126 | virtual bool match( std::string const& expr ) const { | ||
3345 | 1127 | return endsWith( m_data.adjustString( expr ), m_data.m_str ); | ||
3346 | 1128 | } | ||
3347 | 1129 | virtual std::string toString() const { | ||
3348 | 1130 | return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); | ||
3349 | 1131 | } | ||
3350 | 1132 | |||
3351 | 1133 | CasedString m_data; | ||
3352 | 1134 | }; | ||
3353 | 1135 | } // namespace StdString | ||
3354 | 1136 | } // namespace Impl | ||
3355 | 1137 | |||
3356 | 1138 | // The following functions create the actual matcher objects. | ||
3357 | 1139 | // This allows the types to be inferred | ||
3358 | 1140 | template<typename ExpressionT> | ||
3359 | 1141 | inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) { | ||
3360 | 1142 | return Impl::Generic::Not<ExpressionT>( m ); | ||
3361 | 1143 | } | ||
3362 | 1144 | |||
3363 | 1145 | template<typename ExpressionT> | ||
3364 | 1146 | inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, | ||
3365 | 1147 | Impl::Matcher<ExpressionT> const& m2 ) { | ||
3366 | 1148 | return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ); | ||
3367 | 1149 | } | ||
3368 | 1150 | template<typename ExpressionT> | ||
3369 | 1151 | inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, | ||
3370 | 1152 | Impl::Matcher<ExpressionT> const& m2, | ||
3371 | 1153 | Impl::Matcher<ExpressionT> const& m3 ) { | ||
3372 | 1154 | return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); | ||
3373 | 1155 | } | ||
3374 | 1156 | template<typename ExpressionT> | ||
3375 | 1157 | inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, | ||
3376 | 1158 | Impl::Matcher<ExpressionT> const& m2 ) { | ||
3377 | 1159 | return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ); | ||
3378 | 1160 | } | ||
3379 | 1161 | template<typename ExpressionT> | ||
3380 | 1162 | inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, | ||
3381 | 1163 | Impl::Matcher<ExpressionT> const& m2, | ||
3382 | 1164 | Impl::Matcher<ExpressionT> const& m3 ) { | ||
3383 | 1165 | return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); | ||
3384 | 1166 | } | ||
3385 | 1167 | |||
3386 | 1168 | inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { | ||
3387 | 1169 | return Impl::StdString::Equals( str, caseSensitivity ); | ||
3388 | 1170 | } | ||
3389 | 1171 | inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { | ||
3390 | 1172 | return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); | ||
3391 | 1173 | } | ||
3392 | 1174 | inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { | ||
3393 | 1175 | return Impl::StdString::Contains( substr, caseSensitivity ); | ||
3394 | 1176 | } | ||
3395 | 1177 | inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { | ||
3396 | 1178 | return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); | ||
3397 | 1179 | } | ||
3398 | 1180 | inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { | ||
3399 | 1181 | return Impl::StdString::StartsWith( substr ); | ||
3400 | 1182 | } | ||
3401 | 1183 | inline Impl::StdString::StartsWith StartsWith( const char* substr ) { | ||
3402 | 1184 | return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); | ||
3403 | 1185 | } | ||
3404 | 1186 | inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { | ||
3405 | 1187 | return Impl::StdString::EndsWith( substr ); | ||
3406 | 1188 | } | ||
3407 | 1189 | inline Impl::StdString::EndsWith EndsWith( const char* substr ) { | ||
3408 | 1190 | return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); | ||
3409 | 1191 | } | ||
3410 | 1192 | |||
3411 | 1193 | } // namespace Matchers | ||
3412 | 1194 | |||
3413 | 1195 | using namespace Matchers; | ||
3414 | 1196 | |||
3415 | 1197 | } // namespace Catch | ||
3416 | 1198 | |||
3417 | 1199 | namespace Catch { | ||
3418 | 1200 | |||
3419 | 1201 | struct TestFailureException{}; | ||
3420 | 1202 | |||
3421 | 1203 | template<typename T> class ExpressionLhs; | ||
3422 | 1204 | |||
3423 | 1205 | struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; | ||
3424 | 1206 | |||
3425 | 1207 | struct CopyableStream { | ||
3426 | 1208 | CopyableStream() {} | ||
3427 | 1209 | CopyableStream( CopyableStream const& other ) { | ||
3428 | 1210 | oss << other.oss.str(); | ||
3429 | 1211 | } | ||
3430 | 1212 | CopyableStream& operator=( CopyableStream const& other ) { | ||
3431 | 1213 | oss.str(""); | ||
3432 | 1214 | oss << other.oss.str(); | ||
3433 | 1215 | return *this; | ||
3434 | 1216 | } | ||
3435 | 1217 | std::ostringstream oss; | ||
3436 | 1218 | }; | ||
3437 | 1219 | |||
3438 | 1220 | class ResultBuilder { | ||
3439 | 1221 | public: | ||
3440 | 1222 | ResultBuilder( char const* macroName, | ||
3441 | 1223 | SourceLineInfo const& lineInfo, | ||
3442 | 1224 | char const* capturedExpression, | ||
3443 | 1225 | ResultDisposition::Flags resultDisposition, | ||
3444 | 1226 | char const* secondArg = "" ); | ||
3445 | 1227 | |||
3446 | 1228 | template<typename T> | ||
3447 | 1229 | ExpressionLhs<T const&> operator <= ( T const& operand ); | ||
3448 | 1230 | ExpressionLhs<bool> operator <= ( bool value ); | ||
3449 | 1231 | |||
3450 | 1232 | template<typename T> | ||
3451 | 1233 | ResultBuilder& operator << ( T const& value ) { | ||
3452 | 1234 | m_stream.oss << value; | ||
3453 | 1235 | return *this; | ||
3454 | 1236 | } | ||
3455 | 1237 | |||
3456 | 1238 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); | ||
3457 | 1239 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); | ||
3458 | 1240 | |||
3459 | 1241 | ResultBuilder& setResultType( ResultWas::OfType result ); | ||
3460 | 1242 | ResultBuilder& setResultType( bool result ); | ||
3461 | 1243 | ResultBuilder& setLhs( std::string const& lhs ); | ||
3462 | 1244 | ResultBuilder& setRhs( std::string const& rhs ); | ||
3463 | 1245 | ResultBuilder& setOp( std::string const& op ); | ||
3464 | 1246 | |||
3465 | 1247 | void endExpression(); | ||
3466 | 1248 | |||
3467 | 1249 | std::string reconstructExpression() const; | ||
3468 | 1250 | AssertionResult build() const; | ||
3469 | 1251 | |||
3470 | 1252 | void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); | ||
3471 | 1253 | void captureResult( ResultWas::OfType resultType ); | ||
3472 | 1254 | void captureExpression(); | ||
3473 | 1255 | void captureExpectedException( std::string const& expectedMessage ); | ||
3474 | 1256 | void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ); | ||
3475 | 1257 | void handleResult( AssertionResult const& result ); | ||
3476 | 1258 | void react(); | ||
3477 | 1259 | bool shouldDebugBreak() const; | ||
3478 | 1260 | bool allowThrows() const; | ||
3479 | 1261 | |||
3480 | 1262 | private: | ||
3481 | 1263 | AssertionInfo m_assertionInfo; | ||
3482 | 1264 | AssertionResultData m_data; | ||
3483 | 1265 | struct ExprComponents { | ||
3484 | 1266 | ExprComponents() : testFalse( false ) {} | ||
3485 | 1267 | bool testFalse; | ||
3486 | 1268 | std::string lhs, rhs, op; | ||
3487 | 1269 | } m_exprComponents; | ||
3488 | 1270 | CopyableStream m_stream; | ||
3489 | 1271 | |||
3490 | 1272 | bool m_shouldDebugBreak; | ||
3491 | 1273 | bool m_shouldThrow; | ||
3492 | 1274 | }; | ||
3493 | 1275 | |||
3494 | 1276 | } // namespace Catch | ||
3495 | 1277 | |||
3496 | 1278 | // Include after due to circular dependency: | ||
3497 | 1279 | // #included from: catch_expression_lhs.hpp | ||
3498 | 1280 | #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED | ||
3499 | 1281 | |||
3500 | 1282 | // #included from: catch_evaluate.hpp | ||
3501 | 1283 | #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED | ||
3502 | 1284 | |||
3503 | 1285 | #ifdef _MSC_VER | ||
3504 | 1286 | #pragma warning(push) | ||
3505 | 1287 | #pragma warning(disable:4389) // '==' : signed/unsigned mismatch | ||
3506 | 1288 | #endif | ||
3507 | 1289 | |||
3508 | 1290 | #include <cstddef> | ||
3509 | 1291 | |||
3510 | 1292 | namespace Catch { | ||
3511 | 1293 | namespace Internal { | ||
3512 | 1294 | |||
3513 | 1295 | enum Operator { | ||
3514 | 1296 | IsEqualTo, | ||
3515 | 1297 | IsNotEqualTo, | ||
3516 | 1298 | IsLessThan, | ||
3517 | 1299 | IsGreaterThan, | ||
3518 | 1300 | IsLessThanOrEqualTo, | ||
3519 | 1301 | IsGreaterThanOrEqualTo | ||
3520 | 1302 | }; | ||
3521 | 1303 | |||
3522 | 1304 | template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; | ||
3523 | 1305 | template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; | ||
3524 | 1306 | template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; | ||
3525 | 1307 | template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; | ||
3526 | 1308 | template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; | ||
3527 | 1309 | template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; | ||
3528 | 1310 | template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; | ||
3529 | 1311 | |||
3530 | 1312 | template<typename T> | ||
3531 | 1313 | inline T& opCast(T const& t) { return const_cast<T&>(t); } | ||
3532 | 1314 | |||
3533 | 1315 | // nullptr_t support based on pull request #154 from Konstantin Baumann | ||
3534 | 1316 | #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||
3535 | 1317 | inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } | ||
3536 | 1318 | #endif // CATCH_CONFIG_CPP11_NULLPTR | ||
3537 | 1319 | |||
3538 | 1320 | // So the compare overloads can be operator agnostic we convey the operator as a template | ||
3539 | 1321 | // enum, which is used to specialise an Evaluator for doing the comparison. | ||
3540 | 1322 | template<typename T1, typename T2, Operator Op> | ||
3541 | 1323 | class Evaluator{}; | ||
3542 | 1324 | |||
3543 | 1325 | template<typename T1, typename T2> | ||
3544 | 1326 | struct Evaluator<T1, T2, IsEqualTo> { | ||
3545 | 1327 | static bool evaluate( T1 const& lhs, T2 const& rhs) { | ||
3546 | 1328 | return bool( opCast( lhs ) == opCast( rhs ) ); | ||
3547 | 1329 | } | ||
3548 | 1330 | }; | ||
3549 | 1331 | template<typename T1, typename T2> | ||
3550 | 1332 | struct Evaluator<T1, T2, IsNotEqualTo> { | ||
3551 | 1333 | static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||
3552 | 1334 | return bool( opCast( lhs ) != opCast( rhs ) ); | ||
3553 | 1335 | } | ||
3554 | 1336 | }; | ||
3555 | 1337 | template<typename T1, typename T2> | ||
3556 | 1338 | struct Evaluator<T1, T2, IsLessThan> { | ||
3557 | 1339 | static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||
3558 | 1340 | return bool( opCast( lhs ) < opCast( rhs ) ); | ||
3559 | 1341 | } | ||
3560 | 1342 | }; | ||
3561 | 1343 | template<typename T1, typename T2> | ||
3562 | 1344 | struct Evaluator<T1, T2, IsGreaterThan> { | ||
3563 | 1345 | static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||
3564 | 1346 | return bool( opCast( lhs ) > opCast( rhs ) ); | ||
3565 | 1347 | } | ||
3566 | 1348 | }; | ||
3567 | 1349 | template<typename T1, typename T2> | ||
3568 | 1350 | struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { | ||
3569 | 1351 | static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||
3570 | 1352 | return bool( opCast( lhs ) >= opCast( rhs ) ); | ||
3571 | 1353 | } | ||
3572 | 1354 | }; | ||
3573 | 1355 | template<typename T1, typename T2> | ||
3574 | 1356 | struct Evaluator<T1, T2, IsLessThanOrEqualTo> { | ||
3575 | 1357 | static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||
3576 | 1358 | return bool( opCast( lhs ) <= opCast( rhs ) ); | ||
3577 | 1359 | } | ||
3578 | 1360 | }; | ||
3579 | 1361 | |||
3580 | 1362 | template<Operator Op, typename T1, typename T2> | ||
3581 | 1363 | bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { | ||
3582 | 1364 | return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||
3583 | 1365 | } | ||
3584 | 1366 | |||
3585 | 1367 | // This level of indirection allows us to specialise for integer types | ||
3586 | 1368 | // to avoid signed/ unsigned warnings | ||
3587 | 1369 | |||
3588 | 1370 | // "base" overload | ||
3589 | 1371 | template<Operator Op, typename T1, typename T2> | ||
3590 | 1372 | bool compare( T1 const& lhs, T2 const& rhs ) { | ||
3591 | 1373 | return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); | ||
3592 | 1374 | } | ||
3593 | 1375 | |||
3594 | 1376 | // unsigned X to int | ||
3595 | 1377 | template<Operator Op> bool compare( unsigned int lhs, int rhs ) { | ||
3596 | 1378 | return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||
3597 | 1379 | } | ||
3598 | 1380 | template<Operator Op> bool compare( unsigned long lhs, int rhs ) { | ||
3599 | 1381 | return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||
3600 | 1382 | } | ||
3601 | 1383 | template<Operator Op> bool compare( unsigned char lhs, int rhs ) { | ||
3602 | 1384 | return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); | ||
3603 | 1385 | } | ||
3604 | 1386 | |||
3605 | 1387 | // unsigned X to long | ||
3606 | 1388 | template<Operator Op> bool compare( unsigned int lhs, long rhs ) { | ||
3607 | 1389 | return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||
3608 | 1390 | } | ||
3609 | 1391 | template<Operator Op> bool compare( unsigned long lhs, long rhs ) { | ||
3610 | 1392 | return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||
3611 | 1393 | } | ||
3612 | 1394 | template<Operator Op> bool compare( unsigned char lhs, long rhs ) { | ||
3613 | 1395 | return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); | ||
3614 | 1396 | } | ||
3615 | 1397 | |||
3616 | 1398 | // int to unsigned X | ||
3617 | 1399 | template<Operator Op> bool compare( int lhs, unsigned int rhs ) { | ||
3618 | 1400 | return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||
3619 | 1401 | } | ||
3620 | 1402 | template<Operator Op> bool compare( int lhs, unsigned long rhs ) { | ||
3621 | 1403 | return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||
3622 | 1404 | } | ||
3623 | 1405 | template<Operator Op> bool compare( int lhs, unsigned char rhs ) { | ||
3624 | 1406 | return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); | ||
3625 | 1407 | } | ||
3626 | 1408 | |||
3627 | 1409 | // long to unsigned X | ||
3628 | 1410 | template<Operator Op> bool compare( long lhs, unsigned int rhs ) { | ||
3629 | 1411 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3630 | 1412 | } | ||
3631 | 1413 | template<Operator Op> bool compare( long lhs, unsigned long rhs ) { | ||
3632 | 1414 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3633 | 1415 | } | ||
3634 | 1416 | template<Operator Op> bool compare( long lhs, unsigned char rhs ) { | ||
3635 | 1417 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3636 | 1418 | } | ||
3637 | 1419 | |||
3638 | 1420 | // pointer to long (when comparing against NULL) | ||
3639 | 1421 | template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { | ||
3640 | 1422 | return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||
3641 | 1423 | } | ||
3642 | 1424 | template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { | ||
3643 | 1425 | return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||
3644 | 1426 | } | ||
3645 | 1427 | |||
3646 | 1428 | // pointer to int (when comparing against NULL) | ||
3647 | 1429 | template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { | ||
3648 | 1430 | return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||
3649 | 1431 | } | ||
3650 | 1432 | template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { | ||
3651 | 1433 | return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||
3652 | 1434 | } | ||
3653 | 1435 | |||
3654 | 1436 | #ifdef CATCH_CONFIG_CPP11_LONG_LONG | ||
3655 | 1437 | // long long to unsigned X | ||
3656 | 1438 | template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { | ||
3657 | 1439 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3658 | 1440 | } | ||
3659 | 1441 | template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { | ||
3660 | 1442 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3661 | 1443 | } | ||
3662 | 1444 | template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { | ||
3663 | 1445 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3664 | 1446 | } | ||
3665 | 1447 | template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { | ||
3666 | 1448 | return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); | ||
3667 | 1449 | } | ||
3668 | 1450 | |||
3669 | 1451 | // unsigned long long to X | ||
3670 | 1452 | template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { | ||
3671 | 1453 | return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||
3672 | 1454 | } | ||
3673 | 1455 | template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { | ||
3674 | 1456 | return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||
3675 | 1457 | } | ||
3676 | 1458 | template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { | ||
3677 | 1459 | return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||
3678 | 1460 | } | ||
3679 | 1461 | template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { | ||
3680 | 1462 | return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); | ||
3681 | 1463 | } | ||
3682 | 1464 | |||
3683 | 1465 | // pointer to long long (when comparing against NULL) | ||
3684 | 1466 | template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { | ||
3685 | 1467 | return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); | ||
3686 | 1468 | } | ||
3687 | 1469 | template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { | ||
3688 | 1470 | return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); | ||
3689 | 1471 | } | ||
3690 | 1472 | #endif // CATCH_CONFIG_CPP11_LONG_LONG | ||
3691 | 1473 | |||
3692 | 1474 | #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||
3693 | 1475 | // pointer to nullptr_t (when comparing against nullptr) | ||
3694 | 1476 | template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { | ||
3695 | 1477 | return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); | ||
3696 | 1478 | } | ||
3697 | 1479 | template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { | ||
3698 | 1480 | return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); | ||
3699 | 1481 | } | ||
3700 | 1482 | #endif // CATCH_CONFIG_CPP11_NULLPTR | ||
3701 | 1483 | |||
3702 | 1484 | } // end of namespace Internal | ||
3703 | 1485 | } // end of namespace Catch | ||
3704 | 1486 | |||
3705 | 1487 | #ifdef _MSC_VER | ||
3706 | 1488 | #pragma warning(pop) | ||
3707 | 1489 | #endif | ||
3708 | 1490 | |||
3709 | 1491 | // #included from: catch_tostring.h | ||
3710 | 1492 | #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED | ||
3711 | 1493 | |||
3712 | 1494 | #include <sstream> | ||
3713 | 1495 | #include <iomanip> | ||
3714 | 1496 | #include <limits> | ||
3715 | 1497 | #include <vector> | ||
3716 | 1498 | #include <cstddef> | ||
3717 | 1499 | |||
3718 | 1500 | #ifdef __OBJC__ | ||
3719 | 1501 | // #included from: catch_objc_arc.hpp | ||
3720 | 1502 | #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED | ||
3721 | 1503 | |||
3722 | 1504 | #import <Foundation/Foundation.h> | ||
3723 | 1505 | |||
3724 | 1506 | #ifdef __has_feature | ||
3725 | 1507 | #define CATCH_ARC_ENABLED __has_feature(objc_arc) | ||
3726 | 1508 | #else | ||
3727 | 1509 | #define CATCH_ARC_ENABLED 0 | ||
3728 | 1510 | #endif | ||
3729 | 1511 | |||
3730 | 1512 | void arcSafeRelease( NSObject* obj ); | ||
3731 | 1513 | id performOptionalSelector( id obj, SEL sel ); | ||
3732 | 1514 | |||
3733 | 1515 | #if !CATCH_ARC_ENABLED | ||
3734 | 1516 | inline void arcSafeRelease( NSObject* obj ) { | ||
3735 | 1517 | [obj release]; | ||
3736 | 1518 | } | ||
3737 | 1519 | inline id performOptionalSelector( id obj, SEL sel ) { | ||
3738 | 1520 | if( [obj respondsToSelector: sel] ) | ||
3739 | 1521 | return [obj performSelector: sel]; | ||
3740 | 1522 | return nil; | ||
3741 | 1523 | } | ||
3742 | 1524 | #define CATCH_UNSAFE_UNRETAINED | ||
3743 | 1525 | #define CATCH_ARC_STRONG | ||
3744 | 1526 | #else | ||
3745 | 1527 | inline void arcSafeRelease( NSObject* ){} | ||
3746 | 1528 | inline id performOptionalSelector( id obj, SEL sel ) { | ||
3747 | 1529 | #ifdef __clang__ | ||
3748 | 1530 | #pragma clang diagnostic push | ||
3749 | 1531 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" | ||
3750 | 1532 | #endif | ||
3751 | 1533 | if( [obj respondsToSelector: sel] ) | ||
3752 | 1534 | return [obj performSelector: sel]; | ||
3753 | 1535 | #ifdef __clang__ | ||
3754 | 1536 | #pragma clang diagnostic pop | ||
3755 | 1537 | #endif | ||
3756 | 1538 | return nil; | ||
3757 | 1539 | } | ||
3758 | 1540 | #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained | ||
3759 | 1541 | #define CATCH_ARC_STRONG __strong | ||
3760 | 1542 | #endif | ||
3761 | 1543 | |||
3762 | 1544 | #endif | ||
3763 | 1545 | |||
3764 | 1546 | #ifdef CATCH_CONFIG_CPP11_TUPLE | ||
3765 | 1547 | #include <tuple> | ||
3766 | 1548 | #endif | ||
3767 | 1549 | |||
3768 | 1550 | #ifdef CATCH_CONFIG_CPP11_IS_ENUM | ||
3769 | 1551 | #include <type_traits> | ||
3770 | 1552 | #endif | ||
3771 | 1553 | |||
3772 | 1554 | namespace Catch { | ||
3773 | 1555 | |||
3774 | 1556 | // Why we're here. | ||
3775 | 1557 | template<typename T> | ||
3776 | 1558 | std::string toString( T const& value ); | ||
3777 | 1559 | |||
3778 | 1560 | // Built in overloads | ||
3779 | 1561 | |||
3780 | 1562 | std::string toString( std::string const& value ); | ||
3781 | 1563 | std::string toString( std::wstring const& value ); | ||
3782 | 1564 | std::string toString( const char* const value ); | ||
3783 | 1565 | std::string toString( char* const value ); | ||
3784 | 1566 | std::string toString( const wchar_t* const value ); | ||
3785 | 1567 | std::string toString( wchar_t* const value ); | ||
3786 | 1568 | std::string toString( int value ); | ||
3787 | 1569 | std::string toString( unsigned long value ); | ||
3788 | 1570 | std::string toString( unsigned int value ); | ||
3789 | 1571 | std::string toString( const double value ); | ||
3790 | 1572 | std::string toString( const float value ); | ||
3791 | 1573 | std::string toString( bool value ); | ||
3792 | 1574 | std::string toString( char value ); | ||
3793 | 1575 | std::string toString( signed char value ); | ||
3794 | 1576 | std::string toString( unsigned char value ); | ||
3795 | 1577 | |||
3796 | 1578 | #ifdef CATCH_CONFIG_CPP11_LONG_LONG | ||
3797 | 1579 | std::string toString( long long value ); | ||
3798 | 1580 | std::string toString( unsigned long long value ); | ||
3799 | 1581 | #endif | ||
3800 | 1582 | |||
3801 | 1583 | #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||
3802 | 1584 | std::string toString( std::nullptr_t ); | ||
3803 | 1585 | #endif | ||
3804 | 1586 | |||
3805 | 1587 | #ifdef __OBJC__ | ||
3806 | 1588 | std::string toString( NSString const * const& nsstring ); | ||
3807 | 1589 | std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); | ||
3808 | 1590 | std::string toString( NSObject* const& nsObject ); | ||
3809 | 1591 | #endif | ||
3810 | 1592 | |||
3811 | 1593 | namespace Detail { | ||
3812 | 1594 | |||
3813 | 1595 | extern const std::string unprintableString; | ||
3814 | 1596 | |||
3815 | 1597 | struct BorgType { | ||
3816 | 1598 | template<typename T> BorgType( T const& ); | ||
3817 | 1599 | }; | ||
3818 | 1600 | |||
3819 | 1601 | struct TrueType { char sizer[1]; }; | ||
3820 | 1602 | struct FalseType { char sizer[2]; }; | ||
3821 | 1603 | |||
3822 | 1604 | TrueType& testStreamable( std::ostream& ); | ||
3823 | 1605 | FalseType testStreamable( FalseType ); | ||
3824 | 1606 | |||
3825 | 1607 | FalseType operator<<( std::ostream const&, BorgType const& ); | ||
3826 | 1608 | |||
3827 | 1609 | template<typename T> | ||
3828 | 1610 | struct IsStreamInsertable { | ||
3829 | 1611 | static std::ostream &s; | ||
3830 | 1612 | static T const&t; | ||
3831 | 1613 | enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; | ||
3832 | 1614 | }; | ||
3833 | 1615 | |||
3834 | 1616 | #if defined(CATCH_CONFIG_CPP11_IS_ENUM) | ||
3835 | 1617 | template<typename T, | ||
3836 | 1618 | bool IsEnum = std::is_enum<T>::value | ||
3837 | 1619 | > | ||
3838 | 1620 | struct EnumStringMaker | ||
3839 | 1621 | { | ||
3840 | 1622 | static std::string convert( T const& ) { return unprintableString; } | ||
3841 | 1623 | }; | ||
3842 | 1624 | |||
3843 | 1625 | template<typename T> | ||
3844 | 1626 | struct EnumStringMaker<T,true> | ||
3845 | 1627 | { | ||
3846 | 1628 | static std::string convert( T const& v ) | ||
3847 | 1629 | { | ||
3848 | 1630 | return ::Catch::toString( | ||
3849 | 1631 | static_cast<typename std::underlying_type<T>::type>(v) | ||
3850 | 1632 | ); | ||
3851 | 1633 | } | ||
3852 | 1634 | }; | ||
3853 | 1635 | #endif | ||
3854 | 1636 | template<bool C> | ||
3855 | 1637 | struct StringMakerBase { | ||
3856 | 1638 | #if defined(CATCH_CONFIG_CPP11_IS_ENUM) | ||
3857 | 1639 | template<typename T> | ||
3858 | 1640 | static std::string convert( T const& v ) | ||
3859 | 1641 | { | ||
3860 | 1642 | return EnumStringMaker<T>::convert( v ); | ||
3861 | 1643 | } | ||
3862 | 1644 | #else | ||
3863 | 1645 | template<typename T> | ||
3864 | 1646 | static std::string convert( T const& ) { return unprintableString; } | ||
3865 | 1647 | #endif | ||
3866 | 1648 | }; | ||
3867 | 1649 | |||
3868 | 1650 | template<> | ||
3869 | 1651 | struct StringMakerBase<true> { | ||
3870 | 1652 | template<typename T> | ||
3871 | 1653 | static std::string convert( T const& _value ) { | ||
3872 | 1654 | std::ostringstream oss; | ||
3873 | 1655 | oss << _value; | ||
3874 | 1656 | return oss.str(); | ||
3875 | 1657 | } | ||
3876 | 1658 | }; | ||
3877 | 1659 | |||
3878 | 1660 | std::string rawMemoryToString( const void *object, std::size_t size ); | ||
3879 | 1661 | |||
3880 | 1662 | template<typename T> | ||
3881 | 1663 | inline std::string rawMemoryToString( const T& object ) { | ||
3882 | 1664 | return rawMemoryToString( &object, sizeof(object) ); | ||
3883 | 1665 | } | ||
3884 | 1666 | |||
3885 | 1667 | } // end namespace Detail | ||
3886 | 1668 | |||
3887 | 1669 | template<typename T> | ||
3888 | 1670 | struct StringMaker : | ||
3889 | 1671 | Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; | ||
3890 | 1672 | |||
3891 | 1673 | template<typename T> | ||
3892 | 1674 | struct StringMaker<T*> { | ||
3893 | 1675 | template<typename U> | ||
3894 | 1676 | static std::string convert( U* p ) { | ||
3895 | 1677 | if( !p ) | ||
3896 | 1678 | return "NULL"; | ||
3897 | 1679 | else | ||
3898 | 1680 | return Detail::rawMemoryToString( p ); | ||
3899 | 1681 | } | ||
3900 | 1682 | }; | ||
3901 | 1683 | |||
3902 | 1684 | template<typename R, typename C> | ||
3903 | 1685 | struct StringMaker<R C::*> { | ||
3904 | 1686 | static std::string convert( R C::* p ) { | ||
3905 | 1687 | if( !p ) | ||
3906 | 1688 | return "NULL"; | ||
3907 | 1689 | else | ||
3908 | 1690 | return Detail::rawMemoryToString( p ); | ||
3909 | 1691 | } | ||
3910 | 1692 | }; | ||
3911 | 1693 | |||
3912 | 1694 | namespace Detail { | ||
3913 | 1695 | template<typename InputIterator> | ||
3914 | 1696 | std::string rangeToString( InputIterator first, InputIterator last ); | ||
3915 | 1697 | } | ||
3916 | 1698 | |||
3917 | 1699 | //template<typename T, typename Allocator> | ||
3918 | 1700 | //struct StringMaker<std::vector<T, Allocator> > { | ||
3919 | 1701 | // static std::string convert( std::vector<T,Allocator> const& v ) { | ||
3920 | 1702 | // return Detail::rangeToString( v.begin(), v.end() ); | ||
3921 | 1703 | // } | ||
3922 | 1704 | //}; | ||
3923 | 1705 | |||
3924 | 1706 | template<typename T, typename Allocator> | ||
3925 | 1707 | std::string toString( std::vector<T,Allocator> const& v ) { | ||
3926 | 1708 | return Detail::rangeToString( v.begin(), v.end() ); | ||
3927 | 1709 | } | ||
3928 | 1710 | |||
3929 | 1711 | #ifdef CATCH_CONFIG_CPP11_TUPLE | ||
3930 | 1712 | |||
3931 | 1713 | // toString for tuples | ||
3932 | 1714 | namespace TupleDetail { | ||
3933 | 1715 | template< | ||
3934 | 1716 | typename Tuple, | ||
3935 | 1717 | std::size_t N = 0, | ||
3936 | 1718 | bool = (N < std::tuple_size<Tuple>::value) | ||
3937 | 1719 | > | ||
3938 | 1720 | struct ElementPrinter { | ||
3939 | 1721 | static void print( const Tuple& tuple, std::ostream& os ) | ||
3940 | 1722 | { | ||
3941 | 1723 | os << ( N ? ", " : " " ) | ||
3942 | 1724 | << Catch::toString(std::get<N>(tuple)); | ||
3943 | 1725 | ElementPrinter<Tuple,N+1>::print(tuple,os); | ||
3944 | 1726 | } | ||
3945 | 1727 | }; | ||
3946 | 1728 | |||
3947 | 1729 | template< | ||
3948 | 1730 | typename Tuple, | ||
3949 | 1731 | std::size_t N | ||
3950 | 1732 | > | ||
3951 | 1733 | struct ElementPrinter<Tuple,N,false> { | ||
3952 | 1734 | static void print( const Tuple&, std::ostream& ) {} | ||
3953 | 1735 | }; | ||
3954 | 1736 | |||
3955 | 1737 | } | ||
3956 | 1738 | |||
3957 | 1739 | template<typename ...Types> | ||
3958 | 1740 | struct StringMaker<std::tuple<Types...>> { | ||
3959 | 1741 | |||
3960 | 1742 | static std::string convert( const std::tuple<Types...>& tuple ) | ||
3961 | 1743 | { | ||
3962 | 1744 | std::ostringstream os; | ||
3963 | 1745 | os << '{'; | ||
3964 | 1746 | TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os ); | ||
3965 | 1747 | os << " }"; | ||
3966 | 1748 | return os.str(); | ||
3967 | 1749 | } | ||
3968 | 1750 | }; | ||
3969 | 1751 | #endif // CATCH_CONFIG_CPP11_TUPLE | ||
3970 | 1752 | |||
3971 | 1753 | namespace Detail { | ||
3972 | 1754 | template<typename T> | ||
3973 | 1755 | std::string makeString( T const& value ) { | ||
3974 | 1756 | return StringMaker<T>::convert( value ); | ||
3975 | 1757 | } | ||
3976 | 1758 | } // end namespace Detail | ||
3977 | 1759 | |||
3978 | 1760 | /// \brief converts any type to a string | ||
3979 | 1761 | /// | ||
3980 | 1762 | /// The default template forwards on to ostringstream - except when an | ||
3981 | 1763 | /// ostringstream overload does not exist - in which case it attempts to detect | ||
3982 | 1764 | /// that and writes {?}. | ||
3983 | 1765 | /// Overload (not specialise) this template for custom typs that you don't want | ||
3984 | 1766 | /// to provide an ostream overload for. | ||
3985 | 1767 | template<typename T> | ||
3986 | 1768 | std::string toString( T const& value ) { | ||
3987 | 1769 | return StringMaker<T>::convert( value ); | ||
3988 | 1770 | } | ||
3989 | 1771 | |||
3990 | 1772 | namespace Detail { | ||
3991 | 1773 | template<typename InputIterator> | ||
3992 | 1774 | std::string rangeToString( InputIterator first, InputIterator last ) { | ||
3993 | 1775 | std::ostringstream oss; | ||
3994 | 1776 | oss << "{ "; | ||
3995 | 1777 | if( first != last ) { | ||
3996 | 1778 | oss << Catch::toString( *first ); | ||
3997 | 1779 | for( ++first ; first != last ; ++first ) | ||
3998 | 1780 | oss << ", " << Catch::toString( *first ); | ||
3999 | 1781 | } | ||
4000 | 1782 | oss << " }"; | ||
4001 | 1783 | return oss.str(); | ||
4002 | 1784 | } | ||
4003 | 1785 | } | ||
4004 | 1786 | |||
4005 | 1787 | } // end namespace Catch | ||
4006 | 1788 | |||
4007 | 1789 | namespace Catch { | ||
4008 | 1790 | |||
4009 | 1791 | // Wraps the LHS of an expression and captures the operator and RHS (if any) - | ||
4010 | 1792 | // wrapping them all in a ResultBuilder object | ||
4011 | 1793 | template<typename T> | ||
4012 | 1794 | class ExpressionLhs { | ||
4013 | 1795 | ExpressionLhs& operator = ( ExpressionLhs const& ); | ||
4014 | 1796 | # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
4015 | 1797 | ExpressionLhs& operator = ( ExpressionLhs && ) = delete; | ||
4016 | 1798 | # endif | ||
4017 | 1799 | |||
4018 | 1800 | public: | ||
4019 | 1801 | ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} | ||
4020 | 1802 | # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS | ||
4021 | 1803 | ExpressionLhs( ExpressionLhs const& ) = default; | ||
4022 | 1804 | ExpressionLhs( ExpressionLhs && ) = default; | ||
4023 | 1805 | # endif | ||
4024 | 1806 | |||
4025 | 1807 | template<typename RhsT> | ||
4026 | 1808 | ResultBuilder& operator == ( RhsT const& rhs ) { | ||
4027 | 1809 | return captureExpression<Internal::IsEqualTo>( rhs ); | ||
4028 | 1810 | } | ||
4029 | 1811 | |||
4030 | 1812 | template<typename RhsT> | ||
4031 | 1813 | ResultBuilder& operator != ( RhsT const& rhs ) { | ||
4032 | 1814 | return captureExpression<Internal::IsNotEqualTo>( rhs ); | ||
4033 | 1815 | } | ||
4034 | 1816 | |||
4035 | 1817 | template<typename RhsT> | ||
4036 | 1818 | ResultBuilder& operator < ( RhsT const& rhs ) { | ||
4037 | 1819 | return captureExpression<Internal::IsLessThan>( rhs ); | ||
4038 | 1820 | } | ||
4039 | 1821 | |||
4040 | 1822 | template<typename RhsT> | ||
4041 | 1823 | ResultBuilder& operator > ( RhsT const& rhs ) { | ||
4042 | 1824 | return captureExpression<Internal::IsGreaterThan>( rhs ); | ||
4043 | 1825 | } | ||
4044 | 1826 | |||
4045 | 1827 | template<typename RhsT> | ||
4046 | 1828 | ResultBuilder& operator <= ( RhsT const& rhs ) { | ||
4047 | 1829 | return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); | ||
4048 | 1830 | } | ||
4049 | 1831 | |||
4050 | 1832 | template<typename RhsT> | ||
4051 | 1833 | ResultBuilder& operator >= ( RhsT const& rhs ) { | ||
4052 | 1834 | return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); | ||
4053 | 1835 | } | ||
4054 | 1836 | |||
4055 | 1837 | ResultBuilder& operator == ( bool rhs ) { | ||
4056 | 1838 | return captureExpression<Internal::IsEqualTo>( rhs ); | ||
4057 | 1839 | } | ||
4058 | 1840 | |||
4059 | 1841 | ResultBuilder& operator != ( bool rhs ) { | ||
4060 | 1842 | return captureExpression<Internal::IsNotEqualTo>( rhs ); | ||
4061 | 1843 | } | ||
4062 | 1844 | |||
4063 | 1845 | void endExpression() { | ||
4064 | 1846 | bool value = m_lhs ? true : false; | ||
4065 | 1847 | m_rb | ||
4066 | 1848 | .setLhs( Catch::toString( value ) ) | ||
4067 | 1849 | .setResultType( value ) | ||
4068 | 1850 | .endExpression(); | ||
4069 | 1851 | } | ||
4070 | 1852 | |||
4071 | 1853 | // Only simple binary expressions are allowed on the LHS. | ||
4072 | 1854 | // If more complex compositions are required then place the sub expression in parentheses | ||
4073 | 1855 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); | ||
4074 | 1856 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); | ||
4075 | 1857 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); | ||
4076 | 1858 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); | ||
4077 | 1859 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); | ||
4078 | 1860 | template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); | ||
4079 | 1861 | |||
4080 | 1862 | private: | ||
4081 | 1863 | template<Internal::Operator Op, typename RhsT> | ||
4082 | 1864 | ResultBuilder& captureExpression( RhsT const& rhs ) { | ||
4083 | 1865 | return m_rb | ||
4084 | 1866 | .setResultType( Internal::compare<Op>( m_lhs, rhs ) ) | ||
4085 | 1867 | .setLhs( Catch::toString( m_lhs ) ) | ||
4086 | 1868 | .setRhs( Catch::toString( rhs ) ) | ||
4087 | 1869 | .setOp( Internal::OperatorTraits<Op>::getName() ); | ||
4088 | 1870 | } | ||
4089 | 1871 | |||
4090 | 1872 | private: | ||
4091 | 1873 | ResultBuilder& m_rb; | ||
4092 | 1874 | T m_lhs; | ||
4093 | 1875 | }; | ||
4094 | 1876 | |||
4095 | 1877 | } // end namespace Catch | ||
4096 | 1878 | |||
4097 | 1879 | |||
4098 | 1880 | namespace Catch { | ||
4099 | 1881 | |||
4100 | 1882 | template<typename T> | ||
4101 | 1883 | inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { | ||
4102 | 1884 | return ExpressionLhs<T const&>( *this, operand ); | ||
4103 | 1885 | } | ||
4104 | 1886 | |||
4105 | 1887 | inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { | ||
4106 | 1888 | return ExpressionLhs<bool>( *this, value ); | ||
4107 | 1889 | } | ||
4108 | 1890 | |||
4109 | 1891 | } // namespace Catch | ||
4110 | 1892 | |||
4111 | 1893 | // #included from: catch_message.h | ||
4112 | 1894 | #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED | ||
4113 | 1895 | |||
4114 | 1896 | #include <string> | ||
4115 | 1897 | |||
4116 | 1898 | namespace Catch { | ||
4117 | 1899 | |||
4118 | 1900 | struct MessageInfo { | ||
4119 | 1901 | MessageInfo( std::string const& _macroName, | ||
4120 | 1902 | SourceLineInfo const& _lineInfo, | ||
4121 | 1903 | ResultWas::OfType _type ); | ||
4122 | 1904 | |||
4123 | 1905 | std::string macroName; | ||
4124 | 1906 | SourceLineInfo lineInfo; | ||
4125 | 1907 | ResultWas::OfType type; | ||
4126 | 1908 | std::string message; | ||
4127 | 1909 | unsigned int sequence; | ||
4128 | 1910 | |||
4129 | 1911 | bool operator == ( MessageInfo const& other ) const { | ||
4130 | 1912 | return sequence == other.sequence; | ||
4131 | 1913 | } | ||
4132 | 1914 | bool operator < ( MessageInfo const& other ) const { | ||
4133 | 1915 | return sequence < other.sequence; | ||
4134 | 1916 | } | ||
4135 | 1917 | private: | ||
4136 | 1918 | static unsigned int globalCount; | ||
4137 | 1919 | }; | ||
4138 | 1920 | |||
4139 | 1921 | struct MessageBuilder { | ||
4140 | 1922 | MessageBuilder( std::string const& macroName, | ||
4141 | 1923 | SourceLineInfo const& lineInfo, | ||
4142 | 1924 | ResultWas::OfType type ) | ||
4143 | 1925 | : m_info( macroName, lineInfo, type ) | ||
4144 | 1926 | {} | ||
4145 | 1927 | |||
4146 | 1928 | template<typename T> | ||
4147 | 1929 | MessageBuilder& operator << ( T const& value ) { | ||
4148 | 1930 | m_stream << value; | ||
4149 | 1931 | return *this; | ||
4150 | 1932 | } | ||
4151 | 1933 | |||
4152 | 1934 | MessageInfo m_info; | ||
4153 | 1935 | std::ostringstream m_stream; | ||
4154 | 1936 | }; | ||
4155 | 1937 | |||
4156 | 1938 | class ScopedMessage { | ||
4157 | 1939 | public: | ||
4158 | 1940 | ScopedMessage( MessageBuilder const& builder ); | ||
4159 | 1941 | ScopedMessage( ScopedMessage const& other ); | ||
4160 | 1942 | ~ScopedMessage(); | ||
4161 | 1943 | |||
4162 | 1944 | MessageInfo m_info; | ||
4163 | 1945 | }; | ||
4164 | 1946 | |||
4165 | 1947 | } // end namespace Catch | ||
4166 | 1948 | |||
4167 | 1949 | // #included from: catch_interfaces_capture.h | ||
4168 | 1950 | #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | ||
4169 | 1951 | |||
4170 | 1952 | #include <string> | ||
4171 | 1953 | |||
4172 | 1954 | namespace Catch { | ||
4173 | 1955 | |||
4174 | 1956 | class TestCase; | ||
4175 | 1957 | class AssertionResult; | ||
4176 | 1958 | struct AssertionInfo; | ||
4177 | 1959 | struct SectionInfo; | ||
4178 | 1960 | struct SectionEndInfo; | ||
4179 | 1961 | struct MessageInfo; | ||
4180 | 1962 | class ScopedMessageBuilder; | ||
4181 | 1963 | struct Counts; | ||
4182 | 1964 | |||
4183 | 1965 | struct IResultCapture { | ||
4184 | 1966 | |||
4185 | 1967 | virtual ~IResultCapture(); | ||
4186 | 1968 | |||
4187 | 1969 | virtual void assertionEnded( AssertionResult const& result ) = 0; | ||
4188 | 1970 | virtual bool sectionStarted( SectionInfo const& sectionInfo, | ||
4189 | 1971 | Counts& assertions ) = 0; | ||
4190 | 1972 | virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; | ||
4191 | 1973 | virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; | ||
4192 | 1974 | virtual void pushScopedMessage( MessageInfo const& message ) = 0; | ||
4193 | 1975 | virtual void popScopedMessage( MessageInfo const& message ) = 0; | ||
4194 | 1976 | |||
4195 | 1977 | virtual std::string getCurrentTestName() const = 0; | ||
4196 | 1978 | virtual const AssertionResult* getLastResult() const = 0; | ||
4197 | 1979 | |||
4198 | 1980 | virtual void handleFatalErrorCondition( std::string const& message ) = 0; | ||
4199 | 1981 | }; | ||
4200 | 1982 | |||
4201 | 1983 | IResultCapture& getResultCapture(); | ||
4202 | 1984 | } | ||
4203 | 1985 | |||
4204 | 1986 | // #included from: catch_debugger.h | ||
4205 | 1987 | #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED | ||
4206 | 1988 | |||
4207 | 1989 | // #included from: catch_platform.h | ||
4208 | 1990 | #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED | ||
4209 | 1991 | |||
4210 | 1992 | #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) | ||
4211 | 1993 | #define CATCH_PLATFORM_MAC | ||
4212 | 1994 | #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) | ||
4213 | 1995 | #define CATCH_PLATFORM_IPHONE | ||
4214 | 1996 | #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) | ||
4215 | 1997 | #define CATCH_PLATFORM_WINDOWS | ||
4216 | 1998 | #endif | ||
4217 | 1999 | |||
4218 | 2000 | #include <string> | ||
4219 | 2001 | |||
4220 | 2002 | namespace Catch{ | ||
4221 | 2003 | |||
4222 | 2004 | bool isDebuggerActive(); | ||
4223 | 2005 | void writeToDebugConsole( std::string const& text ); | ||
4224 | 2006 | } | ||
4225 | 2007 | |||
4226 | 2008 | #ifdef CATCH_PLATFORM_MAC | ||
4227 | 2009 | |||
4228 | 2010 | // The following code snippet based on: | ||
4229 | 2011 | // http://cocoawithlove.com/2008/03/break-into-debugger.html | ||
4230 | 2012 | #ifdef DEBUG | ||
4231 | 2013 | #if defined(__ppc64__) || defined(__ppc__) | ||
4232 | 2014 | #define CATCH_BREAK_INTO_DEBUGGER() \ | ||
4233 | 2015 | if( Catch::isDebuggerActive() ) { \ | ||
4234 | 2016 | __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ | ||
4235 | 2017 | : : : "memory","r0","r3","r4" ); \ | ||
4236 | 2018 | } | ||
4237 | 2019 | #else | ||
4238 | 2020 | #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} | ||
4239 | 2021 | #endif | ||
4240 | 2022 | #endif | ||
4241 | 2023 | |||
4242 | 2024 | #elif defined(_MSC_VER) | ||
4243 | 2025 | #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } | ||
4244 | 2026 | #elif defined(__MINGW32__) | ||
4245 | 2027 | extern "C" __declspec(dllimport) void __stdcall DebugBreak(); | ||
4246 | 2028 | #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } | ||
4247 | 2029 | #endif | ||
4248 | 2030 | |||
4249 | 2031 | #ifndef CATCH_BREAK_INTO_DEBUGGER | ||
4250 | 2032 | #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); | ||
4251 | 2033 | #endif | ||
4252 | 2034 | |||
4253 | 2035 | // #included from: catch_interfaces_runner.h | ||
4254 | 2036 | #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED | ||
4255 | 2037 | |||
4256 | 2038 | namespace Catch { | ||
4257 | 2039 | class TestCase; | ||
4258 | 2040 | |||
4259 | 2041 | struct IRunner { | ||
4260 | 2042 | virtual ~IRunner(); | ||
4261 | 2043 | virtual bool aborting() const = 0; | ||
4262 | 2044 | }; | ||
4263 | 2045 | } | ||
4264 | 2046 | |||
4265 | 2047 | /////////////////////////////////////////////////////////////////////////////// | ||
4266 | 2048 | // In the event of a failure works out if the debugger needs to be invoked | ||
4267 | 2049 | // and/or an exception thrown and takes appropriate action. | ||
4268 | 2050 | // This needs to be done as a macro so the debugger will stop in the user | ||
4269 | 2051 | // source code rather than in Catch library code | ||
4270 | 2052 | #define INTERNAL_CATCH_REACT( resultBuilder ) \ | ||
4271 | 2053 | if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ | ||
4272 | 2054 | resultBuilder.react(); | ||
4273 | 2055 | |||
4274 | 2056 | /////////////////////////////////////////////////////////////////////////////// | ||
4275 | 2057 | #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ | ||
4276 | 2058 | do { \ | ||
4277 | 2059 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ | ||
4278 | 2060 | try { \ | ||
4279 | 2061 | CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ | ||
4280 | 2062 | ( __catchResult <= expr ).endExpression(); \ | ||
4281 | 2063 | } \ | ||
4282 | 2064 | catch( ... ) { \ | ||
4283 | 2065 | __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ | ||
4284 | 2066 | } \ | ||
4285 | 2067 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4286 | 2068 | } while( Catch::isTrue( false && static_cast<bool>(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look | ||
4287 | 2069 | |||
4288 | 2070 | /////////////////////////////////////////////////////////////////////////////// | ||
4289 | 2071 | #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ | ||
4290 | 2072 | INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ | ||
4291 | 2073 | if( Catch::getResultCapture().getLastResult()->succeeded() ) | ||
4292 | 2074 | |||
4293 | 2075 | /////////////////////////////////////////////////////////////////////////////// | ||
4294 | 2076 | #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ | ||
4295 | 2077 | INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ | ||
4296 | 2078 | if( !Catch::getResultCapture().getLastResult()->succeeded() ) | ||
4297 | 2079 | |||
4298 | 2080 | /////////////////////////////////////////////////////////////////////////////// | ||
4299 | 2081 | #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ | ||
4300 | 2082 | do { \ | ||
4301 | 2083 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ | ||
4302 | 2084 | try { \ | ||
4303 | 2085 | expr; \ | ||
4304 | 2086 | __catchResult.captureResult( Catch::ResultWas::Ok ); \ | ||
4305 | 2087 | } \ | ||
4306 | 2088 | catch( ... ) { \ | ||
4307 | 2089 | __catchResult.useActiveException( resultDisposition ); \ | ||
4308 | 2090 | } \ | ||
4309 | 2091 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4310 | 2092 | } while( Catch::alwaysFalse() ) | ||
4311 | 2093 | |||
4312 | 2094 | /////////////////////////////////////////////////////////////////////////////// | ||
4313 | 2095 | #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ | ||
4314 | 2096 | do { \ | ||
4315 | 2097 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ | ||
4316 | 2098 | if( __catchResult.allowThrows() ) \ | ||
4317 | 2099 | try { \ | ||
4318 | 2100 | expr; \ | ||
4319 | 2101 | __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ | ||
4320 | 2102 | } \ | ||
4321 | 2103 | catch( ... ) { \ | ||
4322 | 2104 | __catchResult.captureExpectedException( matcher ); \ | ||
4323 | 2105 | } \ | ||
4324 | 2106 | else \ | ||
4325 | 2107 | __catchResult.captureResult( Catch::ResultWas::Ok ); \ | ||
4326 | 2108 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4327 | 2109 | } while( Catch::alwaysFalse() ) | ||
4328 | 2110 | |||
4329 | 2111 | /////////////////////////////////////////////////////////////////////////////// | ||
4330 | 2112 | #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ | ||
4331 | 2113 | do { \ | ||
4332 | 2114 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ | ||
4333 | 2115 | if( __catchResult.allowThrows() ) \ | ||
4334 | 2116 | try { \ | ||
4335 | 2117 | expr; \ | ||
4336 | 2118 | __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ | ||
4337 | 2119 | } \ | ||
4338 | 2120 | catch( exceptionType ) { \ | ||
4339 | 2121 | __catchResult.captureResult( Catch::ResultWas::Ok ); \ | ||
4340 | 2122 | } \ | ||
4341 | 2123 | catch( ... ) { \ | ||
4342 | 2124 | __catchResult.useActiveException( resultDisposition ); \ | ||
4343 | 2125 | } \ | ||
4344 | 2126 | else \ | ||
4345 | 2127 | __catchResult.captureResult( Catch::ResultWas::Ok ); \ | ||
4346 | 2128 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4347 | 2129 | } while( Catch::alwaysFalse() ) | ||
4348 | 2130 | |||
4349 | 2131 | /////////////////////////////////////////////////////////////////////////////// | ||
4350 | 2132 | #ifdef CATCH_CONFIG_VARIADIC_MACROS | ||
4351 | 2133 | #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ | ||
4352 | 2134 | do { \ | ||
4353 | 2135 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ | ||
4354 | 2136 | __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ | ||
4355 | 2137 | __catchResult.captureResult( messageType ); \ | ||
4356 | 2138 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4357 | 2139 | } while( Catch::alwaysFalse() ) | ||
4358 | 2140 | #else | ||
4359 | 2141 | #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ | ||
4360 | 2142 | do { \ | ||
4361 | 2143 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ | ||
4362 | 2144 | __catchResult << log + ::Catch::StreamEndStop(); \ | ||
4363 | 2145 | __catchResult.captureResult( messageType ); \ | ||
4364 | 2146 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4365 | 2147 | } while( Catch::alwaysFalse() ) | ||
4366 | 2148 | #endif | ||
4367 | 2149 | |||
4368 | 2150 | /////////////////////////////////////////////////////////////////////////////// | ||
4369 | 2151 | #define INTERNAL_CATCH_INFO( log, macroName ) \ | ||
4370 | 2152 | Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; | ||
4371 | 2153 | |||
4372 | 2154 | /////////////////////////////////////////////////////////////////////////////// | ||
4373 | 2155 | #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ | ||
4374 | 2156 | do { \ | ||
4375 | 2157 | Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ | ||
4376 | 2158 | try { \ | ||
4377 | 2159 | std::string matcherAsString = (matcher).toString(); \ | ||
4378 | 2160 | __catchResult \ | ||
4379 | 2161 | .setLhs( Catch::toString( arg ) ) \ | ||
4380 | 2162 | .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ | ||
4381 | 2163 | .setOp( "matches" ) \ | ||
4382 | 2164 | .setResultType( (matcher).match( arg ) ); \ | ||
4383 | 2165 | __catchResult.captureExpression(); \ | ||
4384 | 2166 | } catch( ... ) { \ | ||
4385 | 2167 | __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ | ||
4386 | 2168 | } \ | ||
4387 | 2169 | INTERNAL_CATCH_REACT( __catchResult ) \ | ||
4388 | 2170 | } while( Catch::alwaysFalse() ) | ||
4389 | 2171 | |||
4390 | 2172 | // #included from: internal/catch_section.h | ||
4391 | 2173 | #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED | ||
4392 | 2174 | |||
4393 | 2175 | // #included from: catch_section_info.h | ||
4394 | 2176 | #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED | ||
4395 | 2177 | |||
4396 | 2178 | // #included from: catch_totals.hpp | ||
4397 | 2179 | #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED | ||
4398 | 2180 | |||
4399 | 2181 | #include <cstddef> | ||
4400 | 2182 | |||
4401 | 2183 | namespace Catch { | ||
4402 | 2184 | |||
4403 | 2185 | struct Counts { | ||
4404 | 2186 | Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} | ||
4405 | 2187 | |||
4406 | 2188 | Counts operator - ( Counts const& other ) const { | ||
4407 | 2189 | Counts diff; | ||
4408 | 2190 | diff.passed = passed - other.passed; | ||
4409 | 2191 | diff.failed = failed - other.failed; | ||
4410 | 2192 | diff.failedButOk = failedButOk - other.failedButOk; | ||
4411 | 2193 | return diff; | ||
4412 | 2194 | } | ||
4413 | 2195 | Counts& operator += ( Counts const& other ) { | ||
4414 | 2196 | passed += other.passed; | ||
4415 | 2197 | failed += other.failed; | ||
4416 | 2198 | failedButOk += other.failedButOk; | ||
4417 | 2199 | return *this; | ||
4418 | 2200 | } | ||
4419 | 2201 | |||
4420 | 2202 | std::size_t total() const { | ||
4421 | 2203 | return passed + failed + failedButOk; | ||
4422 | 2204 | } | ||
4423 | 2205 | bool allPassed() const { | ||
4424 | 2206 | return failed == 0 && failedButOk == 0; | ||
4425 | 2207 | } | ||
4426 | 2208 | bool allOk() const { | ||
4427 | 2209 | return failed == 0; | ||
4428 | 2210 | } | ||
4429 | 2211 | |||
4430 | 2212 | std::size_t passed; | ||
4431 | 2213 | std::size_t failed; | ||
4432 | 2214 | std::size_t failedButOk; | ||
4433 | 2215 | }; | ||
4434 | 2216 | |||
4435 | 2217 | struct Totals { | ||
4436 | 2218 | |||
4437 | 2219 | Totals operator - ( Totals const& other ) const { | ||
4438 | 2220 | Totals diff; | ||
4439 | 2221 | diff.assertions = assertions - other.assertions; | ||
4440 | 2222 | diff.testCases = testCases - other.testCases; | ||
4441 | 2223 | return diff; | ||
4442 | 2224 | } | ||
4443 | 2225 | |||
4444 | 2226 | Totals delta( Totals const& prevTotals ) const { | ||
4445 | 2227 | Totals diff = *this - prevTotals; | ||
4446 | 2228 | if( diff.assertions.failed > 0 ) | ||
4447 | 2229 | ++diff.testCases.failed; | ||
4448 | 2230 | else if( diff.assertions.failedButOk > 0 ) | ||
4449 | 2231 | ++diff.testCases.failedButOk; | ||
4450 | 2232 | else | ||
4451 | 2233 | ++diff.testCases.passed; | ||
4452 | 2234 | return diff; | ||
4453 | 2235 | } | ||
4454 | 2236 | |||
4455 | 2237 | Totals& operator += ( Totals const& other ) { | ||
4456 | 2238 | assertions += other.assertions; | ||
4457 | 2239 | testCases += other.testCases; | ||
4458 | 2240 | return *this; | ||
4459 | 2241 | } | ||
4460 | 2242 | |||
4461 | 2243 | Counts assertions; | ||
4462 | 2244 | Counts testCases; | ||
4463 | 2245 | }; | ||
4464 | 2246 | } | ||
4465 | 2247 | |||
4466 | 2248 | namespace Catch { | ||
4467 | 2249 | |||
4468 | 2250 | struct SectionInfo { | ||
4469 | 2251 | SectionInfo | ||
4470 | 2252 | ( SourceLineInfo const& _lineInfo, | ||
4471 | 2253 | std::string const& _name, | ||
4472 | 2254 | std::string const& _description = std::string() ); | ||
4473 | 2255 | |||
4474 | 2256 | std::string name; | ||
4475 | 2257 | std::string description; | ||
4476 | 2258 | SourceLineInfo lineInfo; | ||
4477 | 2259 | }; | ||
4478 | 2260 | |||
4479 | 2261 | struct SectionEndInfo { | ||
4480 | 2262 | SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) | ||
4481 | 2263 | : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) | ||
4482 | 2264 | {} | ||
4483 | 2265 | |||
4484 | 2266 | SectionInfo sectionInfo; | ||
4485 | 2267 | Counts prevAssertions; | ||
4486 | 2268 | double durationInSeconds; | ||
4487 | 2269 | }; | ||
4488 | 2270 | |||
4489 | 2271 | } // end namespace Catch | ||
4490 | 2272 | |||
4491 | 2273 | // #included from: catch_timer.h | ||
4492 | 2274 | #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED | ||
4493 | 2275 | |||
4494 | 2276 | #ifdef CATCH_PLATFORM_WINDOWS | ||
4495 | 2277 | typedef unsigned long long uint64_t; | ||
4496 | 2278 | #else | ||
4497 | 2279 | #include <stdint.h> | ||
4498 | 2280 | #endif | ||
4499 | 2281 | |||
4500 | 2282 | namespace Catch { | ||
4501 | 2283 | |||
4502 | 2284 | class Timer { | ||
4503 | 2285 | public: | ||
4504 | 2286 | Timer() : m_ticks( 0 ) {} | ||
4505 | 2287 | void start(); | ||
4506 | 2288 | unsigned int getElapsedMicroseconds() const; | ||
4507 | 2289 | unsigned int getElapsedMilliseconds() const; | ||
4508 | 2290 | double getElapsedSeconds() const; | ||
4509 | 2291 | |||
4510 | 2292 | private: | ||
4511 | 2293 | uint64_t m_ticks; | ||
4512 | 2294 | }; | ||
4513 | 2295 | |||
4514 | 2296 | } // namespace Catch | ||
4515 | 2297 | |||
4516 | 2298 | #include <string> | ||
4517 | 2299 | |||
4518 | 2300 | namespace Catch { | ||
4519 | 2301 | |||
4520 | 2302 | class Section : NonCopyable { | ||
4521 | 2303 | public: | ||
4522 | 2304 | Section( SectionInfo const& info ); | ||
4523 | 2305 | ~Section(); | ||
4524 | 2306 | |||
4525 | 2307 | // This indicates whether the section should be executed or not | ||
4526 | 2308 | operator bool() const; | ||
4527 | 2309 | |||
4528 | 2310 | private: | ||
4529 | 2311 | SectionInfo m_info; | ||
4530 | 2312 | |||
4531 | 2313 | std::string m_name; | ||
4532 | 2314 | Counts m_assertions; | ||
4533 | 2315 | bool m_sectionIncluded; | ||
4534 | 2316 | Timer m_timer; | ||
4535 | 2317 | }; | ||
4536 | 2318 | |||
4537 | 2319 | } // end namespace Catch | ||
4538 | 2320 | |||
4539 | 2321 | #ifdef CATCH_CONFIG_VARIADIC_MACROS | ||
4540 | 2322 | #define INTERNAL_CATCH_SECTION( ... ) \ | ||
4541 | 2323 | if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) | ||
4542 | 2324 | #else | ||
4543 | 2325 | #define INTERNAL_CATCH_SECTION( name, desc ) \ | ||
4544 | 2326 | if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) | ||
4545 | 2327 | #endif | ||
4546 | 2328 | |||
4547 | 2329 | // #included from: internal/catch_generators.hpp | ||
4548 | 2330 | #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED | ||
4549 | 2331 | |||
4550 | 2332 | #include <iterator> | ||
4551 | 2333 | #include <vector> | ||
4552 | 2334 | #include <string> | ||
4553 | 2335 | #include <stdlib.h> | ||
4554 | 2336 | |||
4555 | 2337 | namespace Catch { | ||
4556 | 2338 | |||
4557 | 2339 | template<typename T> | ||
4558 | 2340 | struct IGenerator { | ||
4559 | 2341 | virtual ~IGenerator() {} | ||
4560 | 2342 | virtual T getValue( std::size_t index ) const = 0; | ||
4561 | 2343 | virtual std::size_t size () const = 0; | ||
4562 | 2344 | }; | ||
4563 | 2345 | |||
4564 | 2346 | template<typename T> | ||
4565 | 2347 | class BetweenGenerator : public IGenerator<T> { | ||
4566 | 2348 | public: | ||
4567 | 2349 | BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} | ||
4568 | 2350 | |||
4569 | 2351 | virtual T getValue( std::size_t index ) const { | ||
4570 | 2352 | return m_from+static_cast<int>( index ); | ||
4571 | 2353 | } | ||
4572 | 2354 | |||
4573 | 2355 | virtual std::size_t size() const { | ||
4574 | 2356 | return static_cast<std::size_t>( 1+m_to-m_from ); | ||
4575 | 2357 | } | ||
4576 | 2358 | |||
4577 | 2359 | private: | ||
4578 | 2360 | |||
4579 | 2361 | T m_from; | ||
4580 | 2362 | T m_to; | ||
4581 | 2363 | }; | ||
4582 | 2364 | |||
4583 | 2365 | template<typename T> | ||
4584 | 2366 | class ValuesGenerator : public IGenerator<T> { | ||
4585 | 2367 | public: | ||
4586 | 2368 | ValuesGenerator(){} | ||
4587 | 2369 | |||
4588 | 2370 | void add( T value ) { | ||
4589 | 2371 | m_values.push_back( value ); | ||
4590 | 2372 | } | ||
4591 | 2373 | |||
4592 | 2374 | virtual T getValue( std::size_t index ) const { | ||
4593 | 2375 | return m_values[index]; | ||
4594 | 2376 | } | ||
4595 | 2377 | |||
4596 | 2378 | virtual std::size_t size() const { | ||
4597 | 2379 | return m_values.size(); | ||
4598 | 2380 | } | ||
4599 | 2381 | |||
4600 | 2382 | private: | ||
4601 | 2383 | std::vector<T> m_values; | ||
4602 | 2384 | }; | ||
4603 | 2385 | |||
4604 | 2386 | template<typename T> | ||
4605 | 2387 | class CompositeGenerator { | ||
4606 | 2388 | public: | ||
4607 | 2389 | CompositeGenerator() : m_totalSize( 0 ) {} | ||
4608 | 2390 | |||
4609 | 2391 | // *** Move semantics, similar to auto_ptr *** | ||
4610 | 2392 | CompositeGenerator( CompositeGenerator& other ) | ||
4611 | 2393 | : m_fileInfo( other.m_fileInfo ), | ||
4612 | 2394 | m_totalSize( 0 ) | ||
4613 | 2395 | { | ||
4614 | 2396 | move( other ); | ||
4615 | 2397 | } | ||
4616 | 2398 | |||
4617 | 2399 | CompositeGenerator& setFileInfo( const char* fileInfo ) { | ||
4618 | 2400 | m_fileInfo = fileInfo; | ||
4619 | 2401 | return *this; | ||
4620 | 2402 | } | ||
4621 | 2403 | |||
4622 | 2404 | ~CompositeGenerator() { | ||
4623 | 2405 | deleteAll( m_composed ); | ||
4624 | 2406 | } | ||
4625 | 2407 | |||
4626 | 2408 | operator T () const { | ||
4627 | 2409 | size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); | ||
4628 | 2410 | |||
4629 | 2411 | typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); | ||
4630 | 2412 | typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); | ||
4631 | 2413 | for( size_t index = 0; it != itEnd; ++it ) | ||
4632 | 2414 | { | ||
4633 | 2415 | const IGenerator<T>* generator = *it; | ||
4634 | 2416 | if( overallIndex >= index && overallIndex < index + generator->size() ) | ||
4635 | 2417 | { | ||
4636 | 2418 | return generator->getValue( overallIndex-index ); | ||
4637 | 2419 | } | ||
4638 | 2420 | index += generator->size(); | ||
4639 | 2421 | } | ||
4640 | 2422 | CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); | ||
4641 | 2423 | return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so | ||
4642 | 2424 | } | ||
4643 | 2425 | |||
4644 | 2426 | void add( const IGenerator<T>* generator ) { | ||
4645 | 2427 | m_totalSize += generator->size(); | ||
4646 | 2428 | m_composed.push_back( generator ); | ||
4647 | 2429 | } | ||
4648 | 2430 | |||
4649 | 2431 | CompositeGenerator& then( CompositeGenerator& other ) { | ||
4650 | 2432 | move( other ); | ||
4651 | 2433 | return *this; | ||
4652 | 2434 | } | ||
4653 | 2435 | |||
4654 | 2436 | CompositeGenerator& then( T value ) { | ||
4655 | 2437 | ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||
4656 | 2438 | valuesGen->add( value ); | ||
4657 | 2439 | add( valuesGen ); | ||
4658 | 2440 | return *this; | ||
4659 | 2441 | } | ||
4660 | 2442 | |||
4661 | 2443 | private: | ||
4662 | 2444 | |||
4663 | 2445 | void move( CompositeGenerator& other ) { | ||
4664 | 2446 | std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); | ||
4665 | 2447 | m_totalSize += other.m_totalSize; | ||
4666 | 2448 | other.m_composed.clear(); | ||
4667 | 2449 | } | ||
4668 | 2450 | |||
4669 | 2451 | std::vector<const IGenerator<T>*> m_composed; | ||
4670 | 2452 | std::string m_fileInfo; | ||
4671 | 2453 | size_t m_totalSize; | ||
4672 | 2454 | }; | ||
4673 | 2455 | |||
4674 | 2456 | namespace Generators | ||
4675 | 2457 | { | ||
4676 | 2458 | template<typename T> | ||
4677 | 2459 | CompositeGenerator<T> between( T from, T to ) { | ||
4678 | 2460 | CompositeGenerator<T> generators; | ||
4679 | 2461 | generators.add( new BetweenGenerator<T>( from, to ) ); | ||
4680 | 2462 | return generators; | ||
4681 | 2463 | } | ||
4682 | 2464 | |||
4683 | 2465 | template<typename T> | ||
4684 | 2466 | CompositeGenerator<T> values( T val1, T val2 ) { | ||
4685 | 2467 | CompositeGenerator<T> generators; | ||
4686 | 2468 | ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||
4687 | 2469 | valuesGen->add( val1 ); | ||
4688 | 2470 | valuesGen->add( val2 ); | ||
4689 | 2471 | generators.add( valuesGen ); | ||
4690 | 2472 | return generators; | ||
4691 | 2473 | } | ||
4692 | 2474 | |||
4693 | 2475 | template<typename T> | ||
4694 | 2476 | CompositeGenerator<T> values( T val1, T val2, T val3 ){ | ||
4695 | 2477 | CompositeGenerator<T> generators; | ||
4696 | 2478 | ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||
4697 | 2479 | valuesGen->add( val1 ); | ||
4698 | 2480 | valuesGen->add( val2 ); | ||
4699 | 2481 | valuesGen->add( val3 ); | ||
4700 | 2482 | generators.add( valuesGen ); | ||
4701 | 2483 | return generators; | ||
4702 | 2484 | } | ||
4703 | 2485 | |||
4704 | 2486 | template<typename T> | ||
4705 | 2487 | CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { | ||
4706 | 2488 | CompositeGenerator<T> generators; | ||
4707 | 2489 | ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); | ||
4708 | 2490 | valuesGen->add( val1 ); | ||
4709 | 2491 | valuesGen->add( val2 ); | ||
4710 | 2492 | valuesGen->add( val3 ); | ||
4711 | 2493 | valuesGen->add( val4 ); | ||
4712 | 2494 | generators.add( valuesGen ); | ||
4713 | 2495 | return generators; | ||
4714 | 2496 | } | ||
4715 | 2497 | |||
4716 | 2498 | } // end namespace Generators | ||
4717 | 2499 | |||
4718 | 2500 | using namespace Generators; | ||
4719 | 2501 | |||
4720 | 2502 | } // end namespace Catch | ||
4721 | 2503 | |||
4722 | 2504 | #define INTERNAL_CATCH_LINESTR2( line ) #line | ||
4723 | 2505 | #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) | ||
4724 | 2506 | |||
4725 | 2507 | #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) | ||
4726 | 2508 | |||
4727 | 2509 | // #included from: internal/catch_interfaces_exception.h | ||
4728 | 2510 | #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED | ||
4729 | 2511 | |||
4730 | 2512 | #include <string> | ||
4731 | 2513 | #include <vector> | ||
4732 | 2514 | |||
4733 | 2515 | // #included from: catch_interfaces_registry_hub.h | ||
4734 | 2516 | #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED | ||
4735 | 2517 | |||
4736 | 2518 | #include <string> | ||
4737 | 2519 | |||
4738 | 2520 | namespace Catch { | ||
4739 | 2521 | |||
4740 | 2522 | class TestCase; | ||
4741 | 2523 | struct ITestCaseRegistry; | ||
4742 | 2524 | struct IExceptionTranslatorRegistry; | ||
4743 | 2525 | struct IExceptionTranslator; | ||
4744 | 2526 | struct IReporterRegistry; | ||
4745 | 2527 | struct IReporterFactory; | ||
4746 | 2528 | |||
4747 | 2529 | struct IRegistryHub { | ||
4748 | 2530 | virtual ~IRegistryHub(); | ||
4749 | 2531 | |||
4750 | 2532 | virtual IReporterRegistry const& getReporterRegistry() const = 0; | ||
4751 | 2533 | virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; | ||
4752 | 2534 | virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; | ||
4753 | 2535 | }; | ||
4754 | 2536 | |||
4755 | 2537 | struct IMutableRegistryHub { | ||
4756 | 2538 | virtual ~IMutableRegistryHub(); | ||
4757 | 2539 | virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; | ||
4758 | 2540 | virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; | ||
4759 | 2541 | virtual void registerTest( TestCase const& testInfo ) = 0; | ||
4760 | 2542 | virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; | ||
4761 | 2543 | }; | ||
4762 | 2544 | |||
4763 | 2545 | IRegistryHub& getRegistryHub(); | ||
4764 | 2546 | IMutableRegistryHub& getMutableRegistryHub(); | ||
4765 | 2547 | void cleanUp(); | ||
4766 | 2548 | std::string translateActiveException(); | ||
4767 | 2549 | |||
4768 | 2550 | } | ||
4769 | 2551 | |||
4770 | 2552 | namespace Catch { | ||
4771 | 2553 | |||
4772 | 2554 | typedef std::string(*exceptionTranslateFunction)(); | ||
4773 | 2555 | |||
4774 | 2556 | struct IExceptionTranslator; | ||
4775 | 2557 | typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; | ||
4776 | 2558 | |||
4777 | 2559 | struct IExceptionTranslator { | ||
4778 | 2560 | virtual ~IExceptionTranslator(); | ||
4779 | 2561 | virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; | ||
4780 | 2562 | }; | ||
4781 | 2563 | |||
4782 | 2564 | struct IExceptionTranslatorRegistry { | ||
4783 | 2565 | virtual ~IExceptionTranslatorRegistry(); | ||
4784 | 2566 | |||
4785 | 2567 | virtual std::string translateActiveException() const = 0; | ||
4786 | 2568 | }; | ||
4787 | 2569 | |||
4788 | 2570 | class ExceptionTranslatorRegistrar { | ||
4789 | 2571 | template<typename T> | ||
4790 | 2572 | class ExceptionTranslator : public IExceptionTranslator { | ||
4791 | 2573 | public: | ||
4792 | 2574 | |||
4793 | 2575 | ExceptionTranslator( std::string(*translateFunction)( T& ) ) | ||
4794 | 2576 | : m_translateFunction( translateFunction ) | ||
4795 | 2577 | {} | ||
4796 | 2578 | |||
4797 | 2579 | virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { | ||
4798 | 2580 | try { | ||
4799 | 2581 | if( it == itEnd ) | ||
4800 | 2582 | throw; | ||
4801 | 2583 | else | ||
4802 | 2584 | return (*it)->translate( it+1, itEnd ); | ||
4803 | 2585 | } | ||
4804 | 2586 | catch( T& ex ) { | ||
4805 | 2587 | return m_translateFunction( ex ); | ||
4806 | 2588 | } | ||
4807 | 2589 | } | ||
4808 | 2590 | |||
4809 | 2591 | protected: | ||
4810 | 2592 | std::string(*m_translateFunction)( T& ); | ||
4811 | 2593 | }; | ||
4812 | 2594 | |||
4813 | 2595 | public: | ||
4814 | 2596 | template<typename T> | ||
4815 | 2597 | ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { | ||
4816 | 2598 | getMutableRegistryHub().registerTranslator | ||
4817 | 2599 | ( new ExceptionTranslator<T>( translateFunction ) ); | ||
4818 | 2600 | } | ||
4819 | 2601 | }; | ||
4820 | 2602 | } | ||
4821 | 2603 | |||
4822 | 2604 | /////////////////////////////////////////////////////////////////////////////// | ||
4823 | 2605 | #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ | ||
4824 | 2606 | static std::string translatorName( signature ); \ | ||
4825 | 2607 | namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ | ||
4826 | 2608 | static std::string translatorName( signature ) | ||
4827 | 2609 | |||
4828 | 2610 | #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) | ||
4829 | 2611 | |||
4830 | 2612 | // #included from: internal/catch_approx.hpp | ||
4831 | 2613 | #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | ||
4832 | 2614 | |||
4833 | 2615 | #include <cmath> | ||
4834 | 2616 | #include <limits> | ||
4835 | 2617 | |||
4836 | 2618 | namespace Catch { | ||
4837 | 2619 | namespace Detail { | ||
4838 | 2620 | |||
4839 | 2621 | class Approx { | ||
4840 | 2622 | public: | ||
4841 | 2623 | explicit Approx ( double value ) | ||
4842 | 2624 | : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), | ||
4843 | 2625 | m_scale( 1.0 ), | ||
4844 | 2626 | m_value( value ) | ||
4845 | 2627 | {} | ||
4846 | 2628 | |||
4847 | 2629 | Approx( Approx const& other ) | ||
4848 | 2630 | : m_epsilon( other.m_epsilon ), | ||
4849 | 2631 | m_scale( other.m_scale ), | ||
4850 | 2632 | m_value( other.m_value ) | ||
4851 | 2633 | {} | ||
4852 | 2634 | |||
4853 | 2635 | static Approx custom() { | ||
4854 | 2636 | return Approx( 0 ); | ||
4855 | 2637 | } | ||
4856 | 2638 | |||
4857 | 2639 | Approx operator()( double value ) { | ||
4858 | 2640 | Approx approx( value ); | ||
4859 | 2641 | approx.epsilon( m_epsilon ); | ||
4860 | 2642 | approx.scale( m_scale ); | ||
4861 | 2643 | return approx; | ||
4862 | 2644 | } | ||
4863 | 2645 | |||
4864 | 2646 | friend bool operator == ( double lhs, Approx const& rhs ) { | ||
4865 | 2647 | // Thanks to Richard Harris for his help refining this formula | ||
4866 | 2648 | return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); | ||
4867 | 2649 | } | ||
4868 | 2650 | |||
4869 | 2651 | friend bool operator == ( Approx const& lhs, double rhs ) { | ||
4870 | 2652 | return operator==( rhs, lhs ); | ||
4871 | 2653 | } | ||
4872 | 2654 | |||
4873 | 2655 | friend bool operator != ( double lhs, Approx const& rhs ) { | ||
4874 | 2656 | return !operator==( lhs, rhs ); | ||
4875 | 2657 | } | ||
4876 | 2658 | |||
4877 | 2659 | friend bool operator != ( Approx const& lhs, double rhs ) { | ||
4878 | 2660 | return !operator==( rhs, lhs ); | ||
4879 | 2661 | } | ||
4880 | 2662 | |||
4881 | 2663 | Approx& epsilon( double newEpsilon ) { | ||
4882 | 2664 | m_epsilon = newEpsilon; | ||
4883 | 2665 | return *this; | ||
4884 | 2666 | } | ||
4885 | 2667 | |||
4886 | 2668 | Approx& scale( double newScale ) { | ||
4887 | 2669 | m_scale = newScale; | ||
4888 | 2670 | return *this; | ||
4889 | 2671 | } | ||
4890 | 2672 | |||
4891 | 2673 | std::string toString() const { | ||
4892 | 2674 | std::ostringstream oss; | ||
4893 | 2675 | oss << "Approx( " << Catch::toString( m_value ) << " )"; | ||
4894 | 2676 | return oss.str(); | ||
4895 | 2677 | } | ||
4896 | 2678 | |||
4897 | 2679 | private: | ||
4898 | 2680 | double m_epsilon; | ||
4899 | 2681 | double m_scale; | ||
4900 | 2682 | double m_value; | ||
4901 | 2683 | }; | ||
4902 | 2684 | } | ||
4903 | 2685 | |||
4904 | 2686 | template<> | ||
4905 | 2687 | inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { | ||
4906 | 2688 | return value.toString(); | ||
4907 | 2689 | } | ||
4908 | 2690 | |||
4909 | 2691 | } // end namespace Catch | ||
4910 | 2692 | |||
4911 | 2693 | // #included from: internal/catch_interfaces_tag_alias_registry.h | ||
4912 | 2694 | #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED | ||
4913 | 2695 | |||
4914 | 2696 | // #included from: catch_tag_alias.h | ||
4915 | 2697 | #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED | ||
4916 | 2698 | |||
4917 | 2699 | #include <string> | ||
4918 | 2700 | |||
4919 | 2701 | namespace Catch { | ||
4920 | 2702 | |||
4921 | 2703 | struct TagAlias { | ||
4922 | 2704 | TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} | ||
4923 | 2705 | |||
4924 | 2706 | std::string tag; | ||
4925 | 2707 | SourceLineInfo lineInfo; | ||
4926 | 2708 | }; | ||
4927 | 2709 | |||
4928 | 2710 | struct RegistrarForTagAliases { | ||
4929 | 2711 | RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); | ||
4930 | 2712 | }; | ||
4931 | 2713 | |||
4932 | 2714 | } // end namespace Catch | ||
4933 | 2715 | |||
4934 | 2716 | #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } | ||
4935 | 2717 | // #included from: catch_option.hpp | ||
4936 | 2718 | #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED | ||
4937 | 2719 | |||
4938 | 2720 | namespace Catch { | ||
4939 | 2721 | |||
4940 | 2722 | // An optional type | ||
4941 | 2723 | template<typename T> | ||
4942 | 2724 | class Option { | ||
4943 | 2725 | public: | ||
4944 | 2726 | Option() : nullableValue( CATCH_NULL ) {} | ||
4945 | 2727 | Option( T const& _value ) | ||
4946 | 2728 | : nullableValue( new( storage ) T( _value ) ) | ||
4947 | 2729 | {} | ||
4948 | 2730 | Option( Option const& _other ) | ||
4949 | 2731 | : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) | ||
4950 | 2732 | {} | ||
4951 | 2733 | |||
4952 | 2734 | ~Option() { | ||
4953 | 2735 | reset(); | ||
4954 | 2736 | } | ||
4955 | 2737 | |||
4956 | 2738 | Option& operator= ( Option const& _other ) { | ||
4957 | 2739 | if( &_other != this ) { | ||
4958 | 2740 | reset(); | ||
4959 | 2741 | if( _other ) | ||
4960 | 2742 | nullableValue = new( storage ) T( *_other ); | ||
4961 | 2743 | } | ||
4962 | 2744 | return *this; | ||
4963 | 2745 | } | ||
4964 | 2746 | Option& operator = ( T const& _value ) { | ||
4965 | 2747 | reset(); | ||
4966 | 2748 | nullableValue = new( storage ) T( _value ); | ||
4967 | 2749 | return *this; | ||
4968 | 2750 | } | ||
4969 | 2751 | |||
4970 | 2752 | void reset() { | ||
4971 | 2753 | if( nullableValue ) | ||
4972 | 2754 | nullableValue->~T(); | ||
4973 | 2755 | nullableValue = CATCH_NULL; | ||
4974 | 2756 | } | ||
4975 | 2757 | |||
4976 | 2758 | T& operator*() { return *nullableValue; } | ||
4977 | 2759 | T const& operator*() const { return *nullableValue; } | ||
4978 | 2760 | T* operator->() { return nullableValue; } | ||
4979 | 2761 | const T* operator->() const { return nullableValue; } | ||
4980 | 2762 | |||
4981 | 2763 | T valueOr( T const& defaultValue ) const { | ||
4982 | 2764 | return nullableValue ? *nullableValue : defaultValue; | ||
4983 | 2765 | } | ||
4984 | 2766 | |||
4985 | 2767 | bool some() const { return nullableValue != CATCH_NULL; } | ||
4986 | 2768 | bool none() const { return nullableValue == CATCH_NULL; } | ||
4987 | 2769 | |||
4988 | 2770 | bool operator !() const { return nullableValue == CATCH_NULL; } | ||
4989 | 2771 | operator SafeBool::type() const { | ||
4990 | 2772 | return SafeBool::makeSafe( some() ); | ||
4991 | 2773 | } | ||
4992 | 2774 | |||
4993 | 2775 | private: | ||
4994 | 2776 | T* nullableValue; | ||
4995 | 2777 | char storage[sizeof(T)]; | ||
4996 | 2778 | }; | ||
4997 | 2779 | |||
4998 | 2780 | } // end namespace Catch | ||
4999 | 2781 | |||
5000 | 2782 | namespace Catch { |
The diff has been truncated for viewing.