Merge lp:~tapaal-dist-ctl/verifypn/ParserRefactoring_The_Correct_One into lp:~verifypn-maintainers/verifypn/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
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
=== modified file 'CTL/CertainZeroFPA.cpp'
--- CTL/CertainZeroFPA.cpp 2016-04-12 08:29:03 +0000
+++ CTL/CertainZeroFPA.cpp 2016-05-20 07:41:18 +0000
@@ -2,34 +2,12 @@
22
3namespace ctl{3namespace ctl{
44
5bool preprocessQuery(CTLTree *f) {
6
7 bool isTemporal = f->quantifier == A || f->quantifier == E;
8 if (f->quantifier == AND ||
9 f->quantifier == OR ||
10 (f->quantifier == A && f->path == U) ||
11 (f->quantifier == E && f->path == U)) {
12 //operand order guarantees subquery will be preprocessed
13 isTemporal = preprocessQuery(f->second) || isTemporal;
14 isTemporal = preprocessQuery(f->first) || isTemporal;
15 }
16 if (f->quantifier == NEG ||
17 (f->path == G && (f->quantifier == A || f->quantifier == E)) ||
18 (f->path == X && (f->quantifier == A || f->quantifier == E)) ||
19 (f->path == F && (f->quantifier == A || f->quantifier == E))) {
20 isTemporal = preprocessQuery(f->first) || isTemporal;
21 }
22 f->isTemporal = isTemporal;
23 return isTemporal;
24}
25
26bool CertainZeroFPA::search(DependencyGraph &t_graph, AbstractSearchStrategy &W)5bool CertainZeroFPA::search(DependencyGraph &t_graph, AbstractSearchStrategy &W)
27{6{
28 PriorityQueue N;7 PriorityQueue N;
298
30 Configuration &v = t_graph.initialConfiguration();9 Configuration &v = t_graph.initialConfiguration();
31 v.assignment = ZERO;10 v.assignment = ZERO;
32 preprocessQuery(v.query);
3311
34 for(Edge *e : t_graph.successors(v)){12 for(Edge *e : t_graph.successors(v)){
35 W.push(e);13 W.push(e);
@@ -48,6 +26,8 @@
48 N.pop();26 N.pop();
49 }27 }
5028
29// e->edgePrinter();
30
51 /*****************************************************************/31 /*****************************************************************/
52 /*Data handling*/32 /*Data handling*/
53 int targetONEassignments = 0;33 int targetONEassignments = 0;
@@ -156,7 +136,7 @@
156 e->processed = true;136 e->processed = true;
157 }137 }
158138
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;
160 return (v.assignment == ONE) ? true : false;140 return (v.assignment == ONE) ? true : false;
161}141}
162142
163143
=== modified file 'CTL/CertainZeroFPA.h'
--- CTL/CertainZeroFPA.h 2016-02-08 18:27:31 +0000
+++ CTL/CertainZeroFPA.h 2016-05-20 07:41:18 +0000
@@ -19,7 +19,7 @@
19private:19private:
20 struct edge_prioritizer{20 struct edge_prioritizer{
21 bool operator()(const Edge *lhs, const Edge *rhs) const {21 bool operator()(const Edge *lhs, const Edge *rhs) const {
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
23 }23 }
24 };24 };
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;
2626
=== modified file 'CTL/DependencyGraph.cpp'
--- CTL/DependencyGraph.cpp 2016-03-31 11:56:31 +0000
+++ CTL/DependencyGraph.cpp 2016-05-20 07:41:18 +0000
@@ -10,7 +10,7 @@
10 _nplaces(t_net->numberOfPlaces()),10 _nplaces(t_net->numberOfPlaces()),
11 _ntransitions(t_net->numberOfTransitions()){}11 _ntransitions(t_net->numberOfTransitions()){}
1212
13void DependencyGraph::initialize(CTLTree &t_query){13void DependencyGraph::initialize(CTLQuery &t_query){
14 if(_query != NULL)14 if(_query != NULL)
15 clear(false);15 clear(false);
16 _query = &t_query;16 _query = &t_query;
1717
=== modified file 'CTL/DependencyGraph.h'
--- CTL/DependencyGraph.h 2016-04-13 14:36:41 +0000
+++ CTL/DependencyGraph.h 2016-05-20 07:41:18 +0000
@@ -4,6 +4,7 @@
4#include "../PetriEngine/PetriNet.h"4#include "../PetriEngine/PetriNet.h"
5#include "../PetriParse/PNMLParser.h"5#include "../PetriParse/PNMLParser.h"
6#include "../CTLParser/CTLParser.h"6#include "../CTLParser/CTLParser.h"
7#include "../CTLParser/CTLQuery.h"
7#include <list>8#include <list>
8#include <iostream>9#include <iostream>
910
@@ -28,10 +29,10 @@
28 virtual int configuration_count() =0;29 virtual int configuration_count() =0;
29 virtual int marking_count() =0;30 virtual int marking_count() =0;
3031
31 void initialize(CTLTree &t_query);32 void initialize(CTLQuery &t_query);
3233
33protected:34protected:
34 CTLTree *_query = nullptr;35 CTLQuery *_query = nullptr;
35 PetriEngine::PetriNet *_petriNet;36 PetriEngine::PetriNet *_petriNet;
36 PetriEngine::MarkVal *_initialMarking;37 PetriEngine::MarkVal *_initialMarking;
37 PNMLParser::InhibitorArcList _inhibitorArcs;38 PNMLParser::InhibitorArcList _inhibitorArcs;
3839
=== modified file 'CTL/LocalFPA.h'
--- CTL/LocalFPA.h 2016-02-08 18:27:31 +0000
+++ CTL/LocalFPA.h 2016-05-20 07:41:18 +0000
@@ -19,7 +19,7 @@
19private:19private:
20 struct edge_prioritizer{20 struct edge_prioritizer{
21 bool operator()(const Edge *lhs, const Edge *rhs) const {21 bool operator()(const Edge *lhs, const Edge *rhs) const {
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
23 }23 }
24 };24 };
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;
2626
=== modified file 'CTL/OnTheFlyDG.cpp'
--- CTL/OnTheFlyDG.cpp 2016-04-14 12:15:28 +0000
+++ CTL/OnTheFlyDG.cpp 2016-05-20 07:41:18 +0000
@@ -1,6 +1,7 @@
1#include "OnTheFlyDG.h"1#include "OnTheFlyDG.h"
22
3#include <string.h>3#include <string.h>
4#include <algorithm>
45
5namespace ctl{6namespace ctl{
67
@@ -12,336 +13,322 @@
12}13}
1314
1415
15bool OnTheFlyDG::fastEval(CTLTree &query, Marking &marking) {16bool OnTheFlyDG::fastEval(CTLQuery &query, Marking &marking) {
16 assert(!query.isTemporal);17 assert(!query.IsTemporal);
17 if (query.quantifier == AND){18 if (query.GetQuantifier() == AND){
18 return fastEval(*query.first, marking) && fastEval(*query.second, marking); 19 return fastEval(*query.GetFirstChild(), marking) && fastEval(*query.GetSecondChild(), marking);
19 } else if (query.quantifier == OR){20 } else if (query.GetQuantifier() == OR){
20 return fastEval(*query.first, marking) || fastEval(*query.second, marking);21 return fastEval(*query.GetFirstChild(), marking) || fastEval(*query.GetSecondChild(), marking);
21 } else if (query.quantifier == NEG){22 } else if (query.GetQuantifier() == NEG){
22 return !fastEval(*query.first, marking);23 bool result = fastEval(*query.GetFirstChild(), marking);
23 } else { 24 return !result;
24 return evaluateQuery(query, marking);25 } else {
26 bool res = evaluateQuery(query, marking);
27 return res;
25 }28 }
26}29}
2730
28std::list<Edge *> OnTheFlyDG::successors(Configuration &v)31std::list<Edge *> OnTheFlyDG::successors(Configuration &v)
29{32{
30 std::list<Edge*> succ;33 std::list<Edge*> succ;
31 //All34 CTLType query_type = v.query->GetQueryType();
32 if(v.query->quantifier == A){35 if(query_type == EVAL){
33 //All Until36 //assert(false && "Someone told me, this was a bad place to be.");
34 if(v.query->path == U){37 if (evaluateQuery(*v.query, *v.marking)){
35 //first deal with the right side38 succ.push_back(new Edge(&v));
36 Edge *right = NULL;39 }
37 if (!v.query->second->isTemporal) {40 }
38 //right side is not temporal, eval it right now!41 else if (query_type == LOPERATOR){
39 bool valid = fastEval(*(v.query->second), *(v.marking));42 if(v.query->GetQuantifier() == NEG){
40 if (valid) { //satisfied, no need to go through successors43 Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild()));
41 succ.push_back(new Edge(&v));44 Edge* e = new Edge(&v);
42 v.Successors = succ;45 e->targets.push_back(c);
43 return succ;46 succ.push_back(e);
44 } //else: It's not valid, no need to add any edge, just add successors47 }
45 } else {48 else if(v.query->GetQuantifier() == AND){
46 //right side is temporal, we need to evaluate it as normal49 //Check if left is false
47 Configuration* c = createConfiguration(*(v.marking), *(v.query->second));50 if(!v.query->GetFirstChild()->IsTemporal){
48 right = new Edge(&v);51 if(!fastEval(*(v.query->GetFirstChild()), *v.marking))
49 right->targets.push_back(c);52 //query cannot be satisfied, return empty succ set
50 }53 return succ;
51 54 }
52 //if we got here, either right side is temporal or it is not satisfied 55
53 bool valid = false;56 //check if right is false
54 Configuration *left = NULL;57 if(!v.query->GetSecondChild()->IsTemporal){
55 if (!v.query->first->isTemporal) {58 if(!fastEval(*(v.query->GetSecondChild()), *v.marking))
56 //left side is not temporal, eval it right now!59 return succ;
57 valid = fastEval(*(v.query->first), *(v.marking));60 }
58 } else {61
59 //left side is temporal, include it in the edge62 Edge *e = new Edge(&v);
60 left = createConfiguration(*(v.marking), *(v.query->first));63
61 } 64 //If we get here, then either both propositions are true(should not be possible)
6265 //Or a temporal operator and a true proposition
63 if (valid || left != NULL) { //if left side is guaranteed to be not satisfied, skip successor generation66 //Or both are temporal
64 auto targets = nextState (*(v.marking));67 if(v.query->GetFirstChild()->IsTemporal){
6568 e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetFirstChild())));
66 if(!targets.empty()){ 69 }
67 Edge* leftEdge = new Edge(&v);70 if(v.query->GetSecondChild()->IsTemporal){
6871 e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetSecondChild())));
69 for(auto m : targets){72 }
70 Configuration* c = createConfiguration(*m, *(v.query));73 succ.push_back(e);
71 leftEdge->targets.push_back(c); 74 }
72 }75 else if(v.query->GetQuantifier() == OR){
73 if (left != NULL) {76 //Check if left is true
74 leftEdge->targets.push_back(left);77 if(!v.query->GetFirstChild()->IsTemporal){
75 } 78 if(fastEval(*(v.query->GetFirstChild()), *v.marking)){
76 succ.push_back(leftEdge);79 //query is satisfied, return
77 }80 succ.push_back(new Edge(&v));
78 } //else: Left side is not temporal and it's false, no way to succeed there... 81 v.Successors = succ;
7982 return succ;
80 if (right != NULL) {83 }
81 succ.push_back(right);84 }
82 }85
8386 if(!v.query->GetSecondChild()->IsTemporal){
8487 if(fastEval(*(v.query->GetSecondChild()), *v.marking)){
85 } //All Until end88 succ.push_back(new Edge(&v));
8689 v.Successors = succ;
87 //All Next begin90 return succ;
88 else if(v.query->path == X){91 }
89 auto targets = nextState(*v.marking);92 }
90 if (v.query->first->isTemporal) { //regular check93
91 Edge* e = new Edge(&v);94 //If we get here, either both propositions are false
92 for (auto m : targets){95 //Or one is false and one is temporal
93 Configuration* c = createConfiguration(*m, *(v.query->first));96 //Or both temporal
94 e->targets.push_back(c);97 if(v.query->GetFirstChild()->IsTemporal){
95 }98 Edge *e = new Edge(&v);
96 succ.push_back(e);99 e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetFirstChild())));
97 } else {100 succ.push_back(e);
98 bool allValid = true;101 }
99 for (auto m : targets) {102 if(v.query->GetSecondChild()->IsTemporal){
100 bool valid = fastEval(*(v.query->first), *m);103 Edge *e = new Edge(&v);
101 if (!valid) {104 e->targets.push_back(createConfiguration(*v.marking, *(v.query->GetSecondChild())));
102 allValid = false;105 succ.push_back(e);
103 break;106 }
104 }107 }
105 }108 else{
106 if (allValid) {109 assert(false && "An unknown error occoured in the loperator-part of the successor generator");
107 succ.push_back(new Edge(&v));110 }
108 v.Successors = succ;111 }
109 return succ;112 else if (query_type == PATHQEURY){
110 }113 if(v.query->GetQuantifier() == A){
111 } 114 if (v.query->GetPath() == U){
112 } //All Next End115 Edge *right = NULL;
113116 if (!v.query->GetSecondChild()->IsTemporal){
114 //All Finally start117 //right side is not temporal, eval it right now!
115 else if(v.query->path == F){118 bool valid = fastEval(*(v.query->GetSecondChild()), *(v.marking));
116 Edge *subquery = NULL;119 if (valid) { //satisfied, no need to go through successors
117 if (!v.query->first->isTemporal) {120 succ.push_back(new Edge(&v));
118 bool valid = fastEval(*(v.query->first), *(v.marking));121 v.Successors = succ;
119 if (valid) {122 return succ;
120 succ.push_back(new Edge(&v));123 }//else: It's not valid, no need to add any edge, just add successors
121 v.Successors = succ;124 }
122 return succ;125 else {
123 }126 //right side is temporal, we need to evaluate it as normal
124 } else {127 Configuration* c = createConfiguration(*(v.marking), *(v.query->GetSecondChild()));
125 subquery = new Edge(&v);128 right = new Edge(&v);
126 Configuration* c = createConfiguration(*(v.marking), *(v.query->first));129 right->targets.push_back(c);
127 subquery->targets.push_back(c);130 }
128 }131 bool valid = false;
129
130 auto targets = nextState(*(v.marking));
131
132 if(!targets.empty()){
133 Edge* e1 = new Edge(&v);
134
135 for(auto m : targets){
136 Configuration* c = createConfiguration(*m, *(v.query));
137 e1->targets.push_back(c);
138 }
139 succ.push_back(e1);
140 }
141
142 if (subquery != NULL) {
143 succ.push_back(subquery);
144 }
145
146 }//All Finally end
147 } //All end
148
149 //Exists start
150 else if (v.query->quantifier == E){
151
152 //Exists Untill start
153 if(v.query->path == U){
154 Edge *right = NULL;
155 if (v.query->second->isTemporal) {
156 Configuration* c = createConfiguration(*(v.marking), *(v.query->second));
157 right = new Edge(&v);
158 right->targets.push_back(c);
159 } else {
160 bool valid = fastEval(*(v.query->second), *(v.marking));
161 if (valid) {
162 succ.push_back(new Edge(&v));
163 v.Successors = succ;
164 return succ;
165 } // else: right condition is not satisfied, no need to add an edge
166 }
167
168 auto targets = nextState(*(v.marking));
169
170 if(!targets.empty()){
171 Configuration *left = NULL;132 Configuration *left = NULL;
172 bool valid = false;133 if (!v.query->GetFirstChild()->IsTemporal) {
173 if (v.query->first->isTemporal) {134 //left side is not temporal, eval it right now!
174 left = createConfiguration(*(v.marking), *(v.query->first));135 valid = fastEval(*(v.query->GetFirstChild()), *(v.marking));
175 } else {136 } else {
176 valid = fastEval(*(v.query->first), *(v.marking));137 //left side is temporal, include it in the edge
177 }138 left = createConfiguration(*(v.marking), *(v.query->GetFirstChild()));
178 if (left != NULL || valid) {139 }
179 for(auto m : targets) {140 if (valid || left != NULL) { //if left side is guaranteed to be not satisfied, skip successor generation
180 Edge* e = new Edge(&v);141 auto targets = nextState (*(v.marking));
181 Configuration* c1 = createConfiguration(*m, *(v.query));142
182 e->targets.push_back(c1);143 if(!targets.empty()){
144 Edge* leftEdge = new Edge(&v);
145
146 for(auto m : targets){
147 Configuration* c = createConfiguration(*m, *(v.query));
148 leftEdge->targets.push_back(c);
149 }
183 if (left != NULL) {150 if (left != NULL) {
184 e->targets.push_back(left);151 leftEdge->targets.push_back(left);
185 } 152 }
186 succ.push_back(e);153 succ.push_back(leftEdge);
187 }154 }
155 } //else: Left side is not temporal and it's false, no way to succeed there...
156
157 if (right != NULL) {
158 succ.push_back(right);
188 }159 }
189 }160 }
190 161 else if(v.query->GetPath() == F){
191 if (right != NULL) {162 Edge *subquery = NULL;
192 succ.push_back(right);163 if (!v.query->GetFirstChild()->IsTemporal) {
193 }164 bool valid = fastEval(*(v.query->GetFirstChild()), *(v.marking));
194 165 if (valid) {
195 } //Exists Until end166 succ.push_back(new Edge(&v));
196167 v.Successors = succ;
197 //Exists Next start168 return succ;
198 else if(v.query->path == X){169 }
199 auto targets = nextState(*(v.marking));
200 CTLTree* query = v.query->first;
201
202 if(!targets.empty())
203 {
204 if (query->isTemporal) { //have to check, no way to skip that
205 for(auto m : targets){
206 Edge* e = new Edge(&v);
207 Configuration* c = createConfiguration(*m, *query);
208 e->targets.push_back(c);
209 succ.push_back(e);
210 }
211 } else {170 } else {
212 for(auto m : targets) {171 subquery = new Edge(&v);
213 bool valid = fastEval(*query, *m);172 Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild()));
214 if (valid) {173 subquery->targets.push_back(c);
215 succ.push_back(new Edge(&v));174 }
216 v.Successors = succ;175
217 return succ;176 auto targets = nextState(*(v.marking));
218 } //else: It can't hold there, no need to create an edge177
178 if(!targets.empty()){
179 Edge* e1 = new Edge(&v);
180
181 for(auto m : targets){
182 Configuration* c = createConfiguration(*m, *(v.query));
183 e1->targets.push_back(c);
219 }184 }
220 }185 succ.push_back(e1);
221 }186 }
222 }//Exists Next end187
223188 if (subquery != NULL) {
224 //Exists Finally start189 succ.push_back(subquery);
225 else if(v.query->path == F){ 190 }
226 Edge *subquery = NULL;191 }
227 if (!v.query->first->isTemporal) {192 else if(v.query->GetPath() == X){
228 bool valid = fastEval(*(v.query->first), *(v.marking)); 193 auto targets = nextState(*v.marking);
229 if (valid) {194 if (v.query->GetFirstChild()->IsTemporal) { //regular check
230 succ.push_back(new Edge(&v));
231 v.Successors = succ;
232 return succ;
233 }
234 } else {
235 Configuration* c = createConfiguration(*(v.marking), *(v.query->first));
236 subquery = new Edge(&v);
237 subquery->targets.push_back(c);
238 }
239
240 auto targets = nextState(*(v.marking));
241
242 if(!targets.empty()){
243 for(auto m : targets){
244 Edge* e = new Edge(&v);195 Edge* e = new Edge(&v);
245 Configuration* c = createConfiguration(*m, *(v.query));196 for (auto m : targets){
246 e->targets.push_back(c);197 Configuration* c = createConfiguration(*m, *(v.query->GetFirstChild()));
198 e->targets.push_back(c);
199 }
247 succ.push_back(e);200 succ.push_back(e);
248 }201 } else {
249 }202 bool allValid = true;
250203 for (auto m : targets) {
251 if (subquery != NULL) {204 bool valid = fastEval(*(v.query->GetFirstChild()), *m);
252 succ.push_back(subquery);205 if (!valid) {
253 } 206 allValid = false;
254 }//Exists Finally end207 break;
255 } //Exists end208 }
256209 }
257 //And start210 if (allValid) {
258 else if (v.query->quantifier == AND){211 succ.push_back(new Edge(&v));
259212 v.Successors = succ;
260 //Check if left is false213 return succ;
261 if(!v.query->first->isTemporal){214 }
262 if(!fastEval(*(v.query->first), *v.marking))215 }
263 //query cannot be satisfied, return empty succ set216 }
264 return succ;217 else if(v.query->GetPath() == G ){
265 }218 assert(false && "Path operator G had not been translated - Parse error detected in succ()");
266219 }
267 //check if right is false220 else
268 if(!v.query->second->isTemporal){221 assert(false && "An unknown error occoured in the successor generator");
269 if(!fastEval(*(v.query->second), *v.marking))222 }
270 return succ;223 else if(v.query->GetQuantifier() == E){
271 }224 if (v.query->GetPath() == U){
272225 Edge *right = NULL;
273 Edge *e = new Edge(&v);226 if (v.query->GetSecondChild()->IsTemporal) {
274227 Configuration* c = createConfiguration(*(v.marking), *(v.query->GetSecondChild()));
275 //If we get here, then either both propositions are true(should not be possible)228 right = new Edge(&v);
276 //Or a temporal operator and a true proposition229 right->targets.push_back(c);
277 //Or both are temporal230 } else {
278 if(v.query->first->isTemporal){231 bool valid = fastEval(*(v.query->GetSecondChild()), *(v.marking));
279 e->targets.push_back(createConfiguration(*v.marking, *(v.query->first)));232 if (valid) {
280 }233 succ.push_back(new Edge(&v));
281 if(v.query->second->isTemporal){234 v.Successors = succ;
282 e->targets.push_back(createConfiguration(*v.marking, *(v.query->second)));235 return succ;
283 }236 } // else: right condition is not satisfied, no need to add an edge
284 succ.push_back(e);237 }
285 } //And end238
286239 auto targets = nextState(*(v.marking));
287 //Or start240
288 else if (v.query->quantifier == OR){241 if(!targets.empty()){
289242 Configuration *left = NULL;
290 //Check if left is true243 bool valid = false;
291 if(!v.query->first->isTemporal){244 if (v.query->GetFirstChild()->IsTemporal) {
292 if(fastEval(*(v.query->first), *v.marking)){245 left = createConfiguration(*(v.marking), *(v.query->GetFirstChild()));
293 //query is satisfied, return246 } else {
294 succ.push_back(new Edge(&v));247 valid = fastEval(*(v.query->GetFirstChild()), *(v.marking));
295 v.Successors = succ;248 }
296 return succ;249 if (left != NULL || valid) {
297 }250 for(auto m : targets) {
298 }251 Edge* e = new Edge(&v);
299252 Configuration* c1 = createConfiguration(*m, *(v.query));
300 if(!v.query->second->isTemporal){253 e->targets.push_back(c1);
301 if(fastEval(*(v.query->second), *v.marking)){254 if (left != NULL) {
302 succ.push_back(new Edge(&v));255 e->targets.push_back(left);
303 v.Successors = succ;256 }
304 return succ;257 succ.push_back(e);
305 }258 }
306 }259 }
307260 }
308 //If we get here, either both propositions are false261
309 //Or one is false and one is temporal262 if (right != NULL) {
310 //Or both temporal263 succ.push_back(right);
311 if(v.query->first->isTemporal){264 }
312 Edge *e = new Edge(&v);265 }
313 e->targets.push_back(createConfiguration(*v.marking, *(v.query->first)));266 else if(v.query->GetPath() == F){
314 succ.push_back(e);267 Edge *subquery = NULL;
315 }268 if (!v.query->GetFirstChild()->IsTemporal) {
316 if(v.query->second->isTemporal){269 bool valid = fastEval(*(v.query->GetFirstChild()), *(v.marking));
317 Edge *e = new Edge(&v);270 if (valid) {
318 e->targets.push_back(createConfiguration(*v.marking, *(v.query->second)));271 succ.push_back(new Edge(&v));
319 succ.push_back(e);272 v.Successors = succ;
320 }273 return succ;
321 } //Or end274 }
322275 } else {
323 //Negate start276 Configuration* c = createConfiguration(*(v.marking), *(v.query->GetFirstChild()));
324 else if (v.query->quantifier == NEG){277 subquery = new Edge(&v);
325 Configuration* c = createConfiguration(*(v.marking), *(v.query->first));278 subquery->targets.push_back(c);
326 Edge* e = new Edge(&v);279 }
327 e->targets.push_back(c);280
328 succ.push_back(e);281 auto targets = nextState(*(v.marking));
329 } //Negate end282
330283 if(!targets.empty()){
331 //Evaluate Query Begin284 for(auto m : targets){
332 else {285 Edge* e = new Edge(&v);
333 //We should never get here anymore.286 Configuration* c = createConfiguration(*m, *(v.query));
334 //v.configPrinter();287 e->targets.push_back(c);
335 //assert(false);288 succ.push_back(e);
336 if (evaluateQuery(*v.query, *v.marking)){289 }
337 succ.push_back(new Edge(&v));290 }
338 }291
292 if (subquery != NULL) {
293 succ.push_back(subquery);
294 }
295 }
296 else if(v.query->GetPath() == X){
297 auto targets = nextState(*(v.marking));
298 CTLQuery* query = v.query->GetFirstChild();
299
300 if(!targets.empty())
301 {
302 if (query->IsTemporal) { //have to check, no way to skip that
303 for(auto m : targets){
304 Edge* e = new Edge(&v);
305 Configuration* c = createConfiguration(*m, *query);
306 e->targets.push_back(c);
307 succ.push_back(e);
308 }
309 } else {
310 for(auto m : targets) {
311 bool valid = fastEval(*query, *m);
312 if (valid) {
313 succ.push_back(new Edge(&v));
314 v.Successors = succ;
315 return succ;
316 } //else: It can't hold there, no need to create an edge
317 }
318 }
319 }
320 }
321 else if(v.query->GetPath() == G ){
322 assert(false && "Path operator G had not been translated - Parse error detected in succ()");
323 }
324 else
325 assert(false && "An unknown error occoured in the successor generator");
326 }
327
339 }328 }
340329
341 v.Successors = succ;330 v.Successors = succ;
342 return succ;331 return succ;
343 //computedSucc += succ.size();
344 //std::cout << "-----------EDGES NOW : " << computedSucc << "\n" << std::flush;
345}332}
346333
347Configuration &OnTheFlyDG::initialConfiguration()334Configuration &OnTheFlyDG::initialConfiguration()
@@ -351,69 +338,61 @@
351 return *initial;338 return *initial;
352}339}
353340
354bool OnTheFlyDG::evaluateQuery(CTLTree &query, Marking &marking){341bool OnTheFlyDG::evaluateQuery(CTLQuery &query, Marking &marking){
355342 assert(query.GetQueryType() == EVAL);
356 bool result = false;343 EvaluateableProposition *proposition = query.GetProposition();
357344
358 if (query.a.isFireable) {345 if (proposition->GetPropositionType() == FIREABILITY) {
359 std::list<int> transistions = calculateFireableTransistions(marking);346 std::list<int> transistions = calculateFireableTransistions(marking);
360347 std::list<int>::iterator it;
361 for (auto t : transistions) {348 transistions.sort();
362 int fs_transition = 0;349
363 for(fs_transition = 0; fs_transition < query.a.firesize; fs_transition++){350 for(const auto f : proposition->GetFireset()){
364 int dpc_place = 0;351 it = std::find(transistions.begin(), transistions.end(), f);
365 int truedependencyplaces = 0;352 if(it != transistions.end()){
366 for (dpc_place = 0; dpc_place < query.a.fireset[fs_transition].sizeofdenpencyplaces; dpc_place++){353 return true;
367
368 if((query.a.fireset[fs_transition].denpencyplaces[dpc_place].intSmaller - 1) < marking[query.a.fireset[fs_transition].denpencyplaces[dpc_place].placeLarger]){
369 //std::cout<<_net->placeNames()[query->a.fireset[fs_transition].denpencyplaces[dpc_place].placeLarger]<<" is true"<<std::endl;
370 truedependencyplaces++;
371 }
372 }
373 if (truedependencyplaces == query.a.fireset[fs_transition].sizeofdenpencyplaces){
374 result = true;
375 }
376 }354 }
377 }355 }
378 return result;356 return false;
379 }357 }
380358 else if (proposition->GetPropositionType() == CARDINALITY){
381 ///std::cout<<"Evaluating cardinality... "<<std::endl;359 int first_param = GetParamValue(proposition->GetFirstParameter(), marking);
382 // t_config.configPrinter();360 int second_param = GetParamValue(proposition->GetSecondParameter(), marking);
383 // std::cout<<"Less: ";361 return EvalCardianlity(first_param, proposition->GetLoperator(), second_param);
384 int less = query.a.cardinality.intSmaller;362 }
385 int greater= query.a.cardinality.intLarger;363 else
386 if( less == -1 ){364 assert(false && "Incorrect query proposition type was attempted evaluated");
387 int i = 0;365
388 less = 0;366}
389 for (i = 0; i < query.a.cardinality.placeSmaller.sizeoftokencount; i++){367
390 int index = query.a.cardinality.placeSmaller.cardinality[i];368int OnTheFlyDG::GetParamValue(CardinalityParameter *param, Marking& marking) {
391 less += marking[index];369 if(param->isPlace){
392 // std::cout<<t_config.marking->Value()[index]<<" + ";370 int res = 0;
393 }371 for(int place : param->places_i){
394 }372 res = res + marking.Value()[place];
395// std::cout<<" = "<<less<<std::endl;373 }
396// std::cout<<"Greater: ";374 return res;
397 if (greater == -1){375 }
398 int i = 0;376 else{
399 greater = 0;377 return param->value;
400 // std::cout<<"::: Number of places: "<<query->a.cardinality.placeLarger.sizeoftokencount<<std::endl;378 }
401 for (i = 0; i < query.a.cardinality.placeLarger.sizeoftokencount; i++){379}
402 //std::cout<<"::::: i: "<<i<<std::endl;380
403 int index = query.a.cardinality.placeLarger.cardinality[i];381bool OnTheFlyDG::EvalCardianlity(int a, LoperatorType lop, int b) {
404 //std::cout<<"::::: Index: "<<index<<" - Value: "<<t_config.marking->Value()[index]<<std::endl;382 if(lop == EQ)
405 greater += marking[index];383 return a == b;
406 // std::cout<<t_config.marking->Value()[index]<<" + ";384 else if (lop == LE)
407 // std::cout<<"::::: greater: "<<greater<<std::endl;385 return a < b;
408 }386 else if (lop == LEQ)
409387 return a <= b;
410 }388 else if (lop == GR)
411 // std::cout<<" = "<<greater<<std::endl;389 return a > b;
412390 else if (lop == GRQ)
413 result = less <= greater;391 return a >= b;
414 // std::cout<<"... evaluation Done"<<std::endl;392 assert(false && "Unsupported LOperator attemped evaluated");
415 return result;393}
416}394
395
417396
418int OnTheFlyDG::indexOfPlace(char *t_place){397int OnTheFlyDG::indexOfPlace(char *t_place){
419 for (int i = 0; i < _nplaces; i++) {398 for (int i = 0; i < _nplaces; i++) {
@@ -522,7 +501,7 @@
522 }501 }
523}502}
524503
525Configuration *OnTheFlyDG::createConfiguration(Marking &t_marking, CTLTree &t_query)504Configuration *OnTheFlyDG::createConfiguration(Marking &t_marking, CTLQuery &t_query)
526{505{
527 for(Configuration* c : t_marking.successors){506 for(Configuration* c : t_marking.successors){
528 if(c->query == &t_query)507 if(c->query == &t_query)
@@ -534,7 +513,7 @@
534 newConfig->query = &t_query;513 newConfig->query = &t_query;
535514
536 //Default value is false515 //Default value is false
537 if(t_query.quantifier == NEG){516 if(t_query.GetQueryType() == LOPERATOR && t_query.GetQuantifier() == NEG){
538 newConfig->IsNegated = true;517 newConfig->IsNegated = true;
539 }518 }
540519
541520
=== modified file 'CTL/OnTheFlyDG.h'
--- CTL/OnTheFlyDG.h 2016-04-14 12:15:28 +0000
+++ CTL/OnTheFlyDG.h 2016-05-20 07:41:18 +0000
@@ -34,19 +34,22 @@
34// boost::hash<Configuration*>,34// boost::hash<Configuration*>,
35// Configuration::Configuration_Equal_To> Configurations;35// Configuration::Configuration_Equal_To> Configurations;
36 bool isCompressing() {return _compressoption;}36 bool isCompressing() {return _compressoption;}
37private:
38 int GetParamValue(CardinalityParameter *param, Marking &marking);
39 bool EvalCardianlity(int a, LoperatorType lop, int b);
37 40
38protected:41protected:
39 Marking *cached_marking = nullptr;42 Marking *cached_marking = nullptr;
40 std::vector<Marking*> cached_successors;43 std::vector<Marking*> cached_successors;
4144
42 bool evaluateQuery(CTLTree &query, Marking &marking);45 bool evaluateQuery(CTLQuery &query, Marking &marking);
43 bool _compressoption;46 bool _compressoption;
44 int indexOfPlace(char *t_place);47 int indexOfPlace(char *t_place);
45 std::vector<Marking *> nextState(Marking &t_marking);48 std::vector<Marking *> nextState(Marking &t_marking);
46 std::list<int> calculateFireableTransistions(Marking &t_marking);49 std::list<int> calculateFireableTransistions(Marking &t_marking);
47 Configuration *createConfiguration(Marking &t_marking, CTLTree &t_query);50 Configuration *createConfiguration(Marking &t_marking, CTLQuery &t_query);
48 Marking *createMarking(const Marking &t_marking, int t_transition);51 Marking *createMarking(const Marking &t_marking, int t_transition);
49 bool fastEval(CTLTree &query, Marking &marking);52 bool fastEval(CTLQuery &query, Marking &marking);
5053
51 void initCompressOption();54 void initCompressOption();
5255
5356
=== modified file 'CTL/configuration.cpp'
--- CTL/configuration.cpp 2015-12-08 07:25:27 +0000
+++ CTL/configuration.cpp 2016-05-20 07:41:18 +0000
@@ -1,8 +1,9 @@
1#include "configuration.h"1#include "configuration.h"
2#include "../CTLParser/CTLParser_v2.h"
23
3namespace ctl{4namespace ctl{
45
5Configuration::Configuration(Marking * t_marking, CTLTree * t_query){6Configuration::Configuration(Marking * t_marking, CTLQuery * t_query){
6 marking = t_marking;7 marking = t_marking;
7 query = t_query;8 query = t_query;
8}9}
@@ -36,13 +37,13 @@
3637
3738
38void Configuration::configPrinter(){39void Configuration::configPrinter(){
39 CTLParser ctlParser = CTLParser();40 CTLParser_v2 ctlParser = CTLParser_v2();
40 int i = 0;41 int i = 0;
41 std::cout << "Marking: ";42 std::cout << "Marking: ";
42 marking->print();43 marking->print();
43 std::cout << " Q: " << std::flush;44 std::cout << " Q: " << std::flush;
44 ctlParser.printQuery(query);45 std::cout << ctlParser.QueryToString(query)<<std::flush;
45 std::cout << " D: "<<query->depth << std::flush;46 std::cout << " D: "<<query->Depth << std::flush;
46 std::cout << " Assign: " << assignment << std::flush;47 std::cout << " Assign: " << assignment << std::flush;
4748
48 std::cout << " NEG: " << IsNegated << "\n" << std::flush;49 std::cout << " NEG: " << IsNegated << "\n" << std::flush;
4950
=== modified file 'CTL/configuration.h'
--- CTL/configuration.h 2016-04-12 10:22:19 +0000
+++ CTL/configuration.h 2016-05-20 07:41:18 +0000
@@ -2,6 +2,7 @@
2#define CONFIGURATION_H2#define CONFIGURATION_H
33
4#include "../CTLParser/CTLParser.h"4#include "../CTLParser/CTLParser.h"
5#include "../CTLParser/CTLQuery.h"
5#include "marking.h"6#include "marking.h"
6#include "edge.h"7#include "edge.h"
7#include <list>8#include <list>
@@ -26,7 +27,7 @@
26 };27 };
2728
28 Configuration(){}29 Configuration(){}
29 Configuration(Marking* t_marking, CTLTree* t_query);30 Configuration(Marking* t_marking, CTLQuery* t_query);
30 virtual ~Configuration();31 virtual ~Configuration();
3132
32 void removeSuccessor(Edge *t_successor);33 void removeSuccessor(Edge *t_successor);
@@ -36,7 +37,7 @@
36 bool operator!=(const Configuration &rhs) const {return !(*this == rhs);}37 bool operator!=(const Configuration &rhs) const {return !(*this == rhs);}
3738
38 Marking* marking;39 Marking* marking;
39 CTLTree* query;40 CTLQuery* query;
40 std::list<Edge*> Successors;41 std::list<Edge*> Successors;
41 std::list<Edge*> DependencySet;42 std::list<Edge*> DependencySet;
42 bool IsNegated = false;43 bool IsNegated = false;
@@ -60,7 +61,8 @@
6061
61 return result;*/62 return result;*/
62 long xorHash = ((long) t_config.query) ^ ((long) t_config.marking);63 long xorHash = ((long) t_config.query) ^ ((long) t_config.marking);
63 return (size_t) (xorHash ^ (xorHash >> 32));64 //return (size_t) (xorHash ^ (xorHash >> 32)); <-- Only works for 64bit
65 return (size_t) (xorHash ^ (xorHash >> ((sizeof(size_t)*8)/2)));
64 }66 }
65 };67 };
66 template<>68 template<>
6769
=== modified file 'CTL/edge.cpp'
--- CTL/edge.cpp 2016-01-21 11:38:51 +0000
+++ CTL/edge.cpp 2016-05-20 07:41:18 +0000
@@ -34,7 +34,7 @@
34 int beta = 1;34 int beta = 1;
35 int gamma = 1;35 int gamma = 1;
3636
37 int dist = source->query->depth;37 int dist = source->query->Depth;
38 int breath = 0;38 int breath = 0;
39 int succ = source->Successors.size();39 int succ = source->Successors.size();
4040
4141
=== added file 'CTLParser/CTLOptimizer.cpp'
--- CTLParser/CTLOptimizer.cpp 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLOptimizer.cpp 2016-05-20 07:41:18 +0000
@@ -0,0 +1,77 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLOptimizer.cpp
9 * Author: mossns
10 *
11 * Created on April 28, 2016, 1:54 PM
12 */
13
14#include "CTLOptimizer.h"
15
16CTLOptimizer::CTLOptimizer() {
17}
18
19CTLOptimizer::CTLOptimizer(const CTLOptimizer& orig) {
20}
21
22CTLOptimizer::~CTLOptimizer() {
23}
24
25CTLQuery* CTLOptimizer::Optimize(CTLQuery *query) {
26 query = OptimizeNegation(query);
27 return query;
28}
29
30CTLQuery* CTLOptimizer::OptimizeNegation(CTLQuery *query) {
31 CTLType query_type = query->GetQueryType();
32 if(query_type == EVAL){
33 return query;
34 }
35 else if (query_type == LOPERATOR){
36 if(query->GetQuantifier() != NEG){
37 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
38 query->SetSecondChild(OptimizeNegation(query->GetSecondChild()));
39 }
40 else {//Negation
41 if(query->GetFirstChild()->GetQueryType() == LOPERATOR && query->GetFirstChild()->GetQuantifier() == NEG){
42 query = query->GetFirstChild()->GetFirstChild();
43 if(query->GetQueryType() == EVAL){
44 return query;
45 }
46 else if(query->GetQueryType() == LOPERATOR){
47 if(query->GetQuantifier() != NEG){
48 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
49 query->SetSecondChild(OptimizeNegation(query->GetSecondChild()));
50 }
51 else{
52 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
53 }
54 }
55 else if (query->GetQueryType() == PATHQEURY){
56 if (query->GetPath() == U){
57 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
58 query->SetSecondChild(OptimizeNegation(query->GetSecondChild()));
59 }
60 else{
61 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
62 }
63 }
64 }
65 }
66 }
67 else if (query_type == PATHQEURY){
68 if (query->GetPath() == U){
69 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
70 query->SetSecondChild(OptimizeNegation(query->GetSecondChild()));
71 }
72 else{
73 query->SetFirstChild(OptimizeNegation(query->GetFirstChild()));
74 }
75 }
76 return query;
77}
078
=== added file 'CTLParser/CTLOptimizer.h'
--- CTLParser/CTLOptimizer.h 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLOptimizer.h 2016-05-20 07:41:18 +0000
@@ -0,0 +1,31 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLOptimizer.h
9 * Author: mossns
10 *
11 * Created on April 28, 2016, 1:54 PM
12 */
13
14#ifndef CTLOPTIMIZER_H
15#define CTLOPTIMIZER_H
16
17#include "CTLQuery.h"
18
19class CTLOptimizer {
20public:
21 CTLOptimizer();
22 CTLOptimizer(const CTLOptimizer& orig);
23 virtual ~CTLOptimizer();
24
25 CTLQuery * Optimize(CTLQuery *query);
26private:
27 CTLQuery * OptimizeNegation(CTLQuery *query);
28};
29
30#endif /* CTLOPTIMIZER_H */
31
032
=== modified file 'CTLParser/CTLParser.cpp'
--- CTLParser/CTLParser.cpp 2016-02-11 13:26:44 +0000
+++ CTLParser/CTLParser.cpp 2016-05-20 07:41:18 +0000
@@ -35,7 +35,6 @@
35 #ifdef DEBUG35 #ifdef DEBUG
36 std::cout << "Creating doc\n" << std::flush;36 std::cout << "Creating doc\n" << std::flush;
37 #endif37 #endif
38// CTLquery ctlquery;
39 xml_document<> doc;38 xml_document<> doc;
40 xml_node<> * root_node;39 xml_node<> * root_node;
41 40
4241
=== added file 'CTLParser/CTLParser_v2.cpp'
--- CTLParser/CTLParser_v2.cpp 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLParser_v2.cpp 2016-05-20 07:41:18 +0000
@@ -0,0 +1,508 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLParser_v2.cpp
9 * Author: mossns
10 *
11 * Created on April 22, 2016, 10:15 AM
12 */
13
14#include "rapidxml-1.13/rapidxml.hpp"
15#include "CTLParser_v2.h"
16#include "CTLQuery.h"
17#include "EvaluateableProposition.h"
18#include <algorithm>
19
20
21using namespace rapidxml;
22
23CTLParser_v2::CTLParser_v2() {
24}
25
26CTLParser_v2::CTLParser_v2(const CTLParser_v2& orig) {
27}
28
29CTLParser_v2::~CTLParser_v2() {
30}
31
32std::string CTLParser_v2::QueryToString(CTLQuery* query){
33 if(query->GetQuantifier() == EMPTY && query->GetPath() == pError){
34 return query->GetAtom();
35 }
36 else if (query->GetPath() == pError){
37 Quantifier q = query->GetQuantifier();
38 if (q == NEG){
39 return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")";
40 }
41 else if (q == AND || q == OR){
42 return "(" + QueryToString(query->GetFirstChild()) + query->ToString() + QueryToString(query->GetSecondChild()) + ")";
43 }
44 else assert(false && "Could not print unknown logical query operator");
45 }
46 else if(query->GetQuantifier() == A || query->GetQuantifier() == E){
47 if(query->GetPath() == U){
48 return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")Reach(" + QueryToString(query->GetSecondChild()) + ")";
49 }
50 else{
51 return query->ToString() + "(" + QueryToString(query->GetFirstChild()) + ")";
52 }
53 }
54 else assert(false && "Could not print unknown query type");
55}
56
57CTLQuery* CTLParser_v2::FormatQuery(CTLQuery* query, PetriEngine::PetriNet *net){
58 query = FillAtom(query,net);
59 query = ConvertAG(query);
60 query = ConvertEG(query);
61 IdSetting(query, 0);
62 query = TemporalSetting(query);
63 //assert(false);
64 return query;
65}
66
67CTLQuery* CTLParser_v2::TemporalSetting(CTLQuery* query) {
68 CTLType query_type = query->GetQueryType();
69 if(query_type == EVAL){
70 assert(!query->IsTemporal);
71 return query;
72 }
73 else if (query_type == LOPERATOR){
74 Quantifier quan = query->GetQuantifier();
75 if(quan != NEG){
76 query->SetFirstChild(TemporalSetting(query->GetFirstChild()));
77 query->SetSecondChild(TemporalSetting(query->GetSecondChild()));
78 query->IsTemporal = (query->GetFirstChild()->IsTemporal || query->GetSecondChild()->IsTemporal);
79 }
80 else{
81 query->SetFirstChild(TemporalSetting(query->GetFirstChild()));
82 query->IsTemporal = (query->GetFirstChild()->IsTemporal);
83 }
84 return query;
85 }
86 else if (query_type == PATHQEURY){
87 assert(query->IsTemporal);
88 if (query->GetPath() == U){
89 query->SetFirstChild(TemporalSetting(query->GetFirstChild()));
90 query->SetSecondChild(TemporalSetting(query->GetSecondChild()));
91 }
92 else{
93 query->SetFirstChild(TemporalSetting(query->GetFirstChild()));
94 }
95 return query;
96 } else {
97 //this should not happen
98 assert(false);
99 }
100}
101
102//returns next available id
103int CTLParser_v2::IdSetting(CTLQuery *query, int id)
104{
105 query->Id = id;
106 CTLType query_type = query->GetQueryType();
107 if(query_type == EVAL){
108 assert(!query->IsTemporal);
109 query->Depth = 0;
110 return id + 1;
111 }
112 else if (query_type == LOPERATOR){
113 Quantifier quan = query->GetQuantifier();
114 if(quan != NEG){
115 int afterFirst = IdSetting(query->GetFirstChild(), id + 1);
116 int afterSecond = IdSetting(query->GetSecondChild(), afterFirst);
117 query->Depth = std::max(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth) + 1;
118 return afterSecond;
119 }
120 else{
121 int afterFirst = IdSetting(query->GetFirstChild(), id + 1);
122 query->Depth = query->GetFirstChild()->Depth + 1;
123 return afterFirst;
124 }
125 }
126 else if (query_type == PATHQEURY){
127 assert(query->IsTemporal);
128 if (query->GetPath() == U){
129 int afterFirst = IdSetting(query->GetFirstChild(), id + 1);
130 int afterSecond = IdSetting(query->GetSecondChild(), afterFirst);
131 query->Depth = std::max(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth) + 1;
132 return afterSecond;
133 }
134 else{
135 int afterFirst = IdSetting(query->GetFirstChild(), id + 1);
136 query->Depth = query->GetFirstChild()->Depth + 1;
137 return afterFirst;
138 }
139 } else {
140 //this should not happen
141 assert(false);
142 }
143}
144
145
146CTLQuery* CTLParser_v2::FillAtom(CTLQuery* query, PetriEngine::PetriNet *net) {
147 CTLType query_type = query->GetQueryType();
148 if(query_type == EVAL){
149 EvaluateableProposition *proposition = new EvaluateableProposition(query->GetAtom(), net);
150 query->SetProposition(proposition);
151 return query;
152 }
153 else if (query_type == LOPERATOR){
154 Quantifier quan = query->GetQuantifier();
155 if(quan != NEG){
156 FillAtom(query->GetFirstChild(),net);
157 FillAtom(query->GetSecondChild(),net);
158 }
159 else{
160 FillAtom(query->GetFirstChild(),net);
161 }
162 return query;
163 }
164 else if (query_type == PATHQEURY){
165 if (query->GetPath() == U){
166 FillAtom(query->GetFirstChild(),net);
167 FillAtom(query->GetSecondChild(),net);
168 }
169 else{
170 FillAtom(query->GetFirstChild(),net);
171 }
172 return query;
173 }
174 else assert(false && "Could not traverse unknown query type");
175}
176
177CTLQuery* CTLParser_v2::ConvertAG(CTLQuery* query) {
178 CTLType query_type = query->GetQueryType();
179 if(query_type == EVAL){
180 return query;
181 }
182 else if (query_type == LOPERATOR){
183 Quantifier quan = query->GetQuantifier();
184 if(quan != NEG){
185 query->SetFirstChild(ConvertAG(query->GetFirstChild()));
186 query->SetSecondChild(ConvertAG(query->GetSecondChild()));
187 }
188 else{
189 query->SetFirstChild(ConvertAG(query->GetFirstChild()));
190 }
191 return query;
192 }
193 else if (query_type == PATHQEURY){
194 if (query->GetPath() == U){
195 query->SetFirstChild(ConvertAG(query->GetFirstChild()));
196 query->SetSecondChild(ConvertAG(query->GetSecondChild()));
197 }
198 else if (query->GetQuantifier() == A && query->GetPath() == G){
199
200 CTLQuery *neg_two = new CTLQuery(NEG, pError, false, "");
201 neg_two->SetFirstChild(query->GetFirstChild());
202 CTLQuery *ef_q = new CTLQuery(E, F, false, "");
203 ef_q->SetFirstChild(neg_two);
204 CTLQuery *neg_one = new CTLQuery(NEG, pError, false, "");
205 neg_one->SetFirstChild(ef_q);
206 query = neg_one;
207
208 query->SetFirstChild(ConvertAG(query->GetFirstChild()));
209 }
210 else{
211 query->SetFirstChild(ConvertAG(query->GetFirstChild()));
212 }
213 return query;
214 }
215 else assert(false && "Could not traverse unknown query type");
216}
217
218CTLQuery* CTLParser_v2::ConvertEG(CTLQuery* query) {
219 CTLType query_type = query->GetQueryType();
220 if(query_type == EVAL){
221 return query;
222 }
223 else if (query_type == LOPERATOR){
224 Quantifier quan = query->GetQuantifier();
225 if(quan != NEG){
226 query->SetFirstChild(ConvertEG(query->GetFirstChild()));
227 query->SetSecondChild(ConvertEG(query->GetSecondChild()));
228 }
229 else{
230 query->SetFirstChild(ConvertEG(query->GetFirstChild()));
231 }
232 return query;
233 }
234 else if (query_type == PATHQEURY){
235 if (query->GetPath() == U){
236 query->SetFirstChild(ConvertEG(query->GetFirstChild()));
237 query->SetSecondChild(ConvertEG(query->GetSecondChild()));
238 }
239 else if (query->GetQuantifier() == E && query->GetPath() == G){
240
241 CTLQuery *neg_two = new CTLQuery(NEG, pError, false, "");
242 neg_two->SetFirstChild(query->GetFirstChild());
243 CTLQuery *ef_q = new CTLQuery(A, F, false, "");
244 ef_q->SetFirstChild(neg_two);
245 CTLQuery *neg_one = new CTLQuery(NEG, pError, false, "");
246 neg_one->SetFirstChild(ef_q);
247 query = neg_one;
248
249 query->SetFirstChild(ConvertEG(query->GetFirstChild()));
250 }
251 else{
252 query->SetFirstChild(ConvertEG(query->GetFirstChild()));
253 }
254 return query;
255 }
256 else assert(false && "Could not traverse unknown query type");
257}
258
259
260CTLQuery * CTLParser_v2::ParseXMLQuery(std::vector<char> buffer, int query_number) {
261 #ifdef DEBUG
262 std::cout << "Creating doc\n" << std::flush;
263 #endif
264 xml_document<> doc;
265 xml_node<> * root_node;
266
267 #ifdef DEBUG
268 std::cout << "Size of Path enum: " << sizeof(Path)*8 <<"\n";
269 #endif
270 doc.parse<0>(&buffer[0]);
271
272
273#ifdef DEBUG
274 std::cout << "First node id: " << doc.first_node()->name() << std::endl;
275#endif
276
277 root_node = doc.first_node();
278
279#ifdef Analysis
280 std::cout << "\nAnalysis:: Queries:" << std::endl;
281#endif
282 int i = 1;
283 for (xml_node<> * property_node = root_node->first_node("property"); property_node; property_node = property_node->next_sibling()) {
284 if(i == query_number){
285 xml_node<> * id_node = property_node->first_node("id");
286 xml_node<> * formula_node = id_node->next_sibling("description")->next_sibling("formula");
287 CTLQuery * query = xmlToCTLquery(formula_node->first_node());
288 return query;
289 }
290 i++;
291 }
292 assert(false && "Query number did not match a property in the provided .xml file.");
293}
294
295QueryMeta* CTLParser_v2::GetQueryMetaData(std::vector<char> buffer) {
296 xml_document<> doc;
297 xml_node<> * root_node;
298 doc.parse<0>(&buffer[0]);
299 root_node = doc.first_node();
300 QueryMeta *meta_d = new QueryMeta();
301 xml_node<> * first_property_node = root_node->first_node("property");
302 xml_node<> * id_node = first_property_node->first_node("id");
303 std::string model_name(id_node->value());
304 int i = 0;
305 for (xml_node<> * property_node = root_node->first_node("property"); property_node; property_node = property_node->next_sibling()) {
306 i++;
307 }
308 meta_d->numberof_queries = i;
309 std::size_t pos = model_name.find_last_of("-0") - 1;
310 meta_d->model_name = model_name.substr(0, pos);
311 return meta_d;
312}
313
314
315CTLQuery* CTLParser_v2::xmlToCTLquery(xml_node<> * root) {
316 char *root_name = root->name();
317 char firstLetter = root_name[0];
318 CTLQuery *query;
319 if (firstLetter == 'a') {
320 //Construct all-paths
321 query = new CTLQuery(A, getPathOperator(root), false, "");
322 assert(query->GetQuantifier() == A && "Failed setting quantifier");
323 }
324 else if (firstLetter == 'e' ) {
325 //Construct exists-path
326 query = new CTLQuery(E, getPathOperator(root), false, "");
327 assert(query->GetQuantifier() == E && "Failed setting path operator");
328 }
329 else if (firstLetter == 'n' ) {
330 //Construct negation
331 query = new CTLQuery(NEG, pError, false, "");
332 assert(query->GetQuantifier() == NEG && "Failed setting negation operator");
333 }
334 else if (firstLetter == 'c' ) {
335 //Construct conjunction
336 query = new CTLQuery(AND, pError, false, "");
337 assert(query->GetQuantifier() == AND && "Failed setting and operator");
338 }
339 else if (firstLetter == 'd' ) {
340 //Construct disjunction
341 query = new CTLQuery(OR, pError, false, "");
342 assert(query->GetQuantifier() == OR && "Failed setting or operator");
343 }
344 else if (firstLetter == 'i' ) {
345 //Construct Atom
346 std::string atom_str = "";
347 if (root_name[1] == 's' ){
348 //Fireability Query File
349 atom_str = root->name();
350 atom_str = atom_str + "(";
351 root = root->first_node();
352 atom_str = atom_str + root->value();
353 for (xml_node<> * transition_node = root->next_sibling(); transition_node; transition_node = transition_node->next_sibling()) {
354 atom_str = atom_str + ", " + transition_node->value();
355 }
356 atom_str = atom_str + ")";
357 }
358 else if (root_name[1] == 'n') {
359 //Cardinality Query File
360 std::string loperator = root->name();
361 xml_node<> * par_node = root->first_node();
362 std::string first = parsePar(par_node);
363 par_node = par_node->next_sibling();
364 std::string second = parsePar(par_node);
365
366 loperator = loperator_sym(loperator);
367
368 atom_str = first + loperator + second;
369
370 }
371 else assert(false && "Incorrectly format of .xml file provided");
372 query = new CTLQuery(EMPTY, pError, true, atom_str);
373 query->Depth = 0;
374 return query;
375 }
376 else if (firstLetter == 't' ){
377 std::string atom_str = "integer-constant(0) le integer-constant(0)";
378 query = new CTLQuery(EMPTY, pError, true, atom_str);
379 query->Depth = 0;
380 return query;
381 }
382 else if (firstLetter == 'f' ){
383 std::string atom_str = "integer-constant(2) le integer-constant(0)";
384 query = new CTLQuery(EMPTY, pError, true, atom_str);
385 query->Depth = 0;
386 return query;
387 }
388 else assert(false && "Failed parsing .xml file provided. Incorrect format.");
389
390 if (query->GetPath() == U) {
391 xml_node<> * child_node = root->first_node()->first_node();
392 query->SetFirstChild(xmlToCTLquery(child_node->first_node()));
393 child_node = child_node->next_sibling();
394 query->SetSecondChild(xmlToCTLquery(child_node->first_node()));
395
396 query->Depth = (max_depth(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth)) + 1;
397 }
398 else if (query->GetQuantifier() == AND || query->GetQuantifier() == OR) {
399 xml_node<> * child_node = root->first_node();
400 query->SetFirstChild(xmlToCTLquery(child_node));
401 child_node = child_node->next_sibling();
402 query->SetSecondChild(xmlToCTLquery(child_node));
403
404 query->Depth = (max_depth(query->GetFirstChild()->Depth, query->GetSecondChild()->Depth)) + 1;
405 }
406 else if (query->GetQuantifier() == NEG) {
407 query->SetFirstChild(xmlToCTLquery(root->first_node()));
408 query->Depth = query->GetFirstChild()->Depth + 1;
409 }
410 else if (query->GetPath() == pError){
411 assert(false && "Failed setting Path operator");
412 }
413 else if (query->GetQueryType() == PATHQEURY) {
414 query->SetFirstChild(xmlToCTLquery(root->first_node()->first_node()));
415 query->Depth = query->GetFirstChild()->Depth + 1;
416 }
417 else{
418 assert(false && "Attemting to give atom children - ERROR");
419 }
420
421 return query;
422}
423
424Path CTLParser_v2::getPathOperator(xml_node<> * quantifyer_node){
425 char path_firstLetter = quantifyer_node->first_node()->name()[0];
426 if(path_firstLetter == 'f')
427 return F;
428 else if (path_firstLetter == 'g')
429 return G;
430 else if (path_firstLetter == 'n')
431 return X;
432 else if (path_firstLetter == 'u')
433 return U;
434 else assert(false && "Failed parsing path operator. Incorrect format.");
435}
436
437std::string CTLParser_v2::parsePar(xml_node<> * parameter){
438 std::string parameter_str = parameter->name();
439 parameter_str = parameter_str + "(";
440
441 if (parameter->name()[0] == 't'){
442 xml_node<> * place_node = parameter->first_node();
443 parameter_str = parameter_str + place_node->value();
444 for(place_node = place_node->next_sibling(); place_node; place_node = place_node->next_sibling()){
445 parameter_str = parameter_str + ", " + place_node->value();
446 }
447 parameter_str = parameter_str + ")";
448 }
449
450 else if(parameter->name()[0] == 'i'){
451 parameter_str = parameter_str + parameter->value() + ")";
452 }
453 else assert(false && "Failed parsing cardinality parameter. Incorrect format.");
454 return parameter_str;
455}
456
457/*
458 for (xml_node<> * transition_node = root->next_sibling(); transition_node; transition_node = transition_node->next_sibling()) {
459 atom_str = atom_str + ", " + transition_node->value();
460 }
461 atom_str = atom_str + ")";
462 */
463
464int CTLParser_v2::max_depth(int a, int b){
465 if(a < b) return b; return a;
466}
467
468std::string CTLParser_v2::loperator_sym(std::string loperator){
469 if(loperator.compare("integer-le") == 0){
470 return " le ";
471 }
472 else if(loperator.compare("integer-ge")){
473 return " ge ";
474 }
475 else if(loperator.compare("integer-eq")){
476 return " eq ";
477 }
478 else return " " + loperator + " ";
479}
480
481CTLQuery * CTLParser_v2::CopyQuery(CTLQuery *source){
482 if(source->GetQueryType() == EVAL){
483 return new CTLQuery(EMPTY, pError, true, source->GetAtom());
484 }
485 else if(source->GetQueryType() == LOPERATOR){
486 CTLQuery *dest = new CTLQuery(source->GetQuantifier(), pError, false, "");
487 if(source->GetQuantifier() != NEG){
488 dest->SetFirstChild(CopyQuery(source->GetFirstChild()));
489 dest->SetSecondChild(CopyQuery(source->GetSecondChild()));
490 }
491 else {
492 dest->SetFirstChild(CopyQuery(source->GetFirstChild()));
493 }
494 return dest;
495 }
496 else if(source->GetQueryType() == PATHQEURY){
497 CTLQuery *dest = new CTLQuery(source->GetQuantifier(), source->GetPath(), false, "");
498 if(source->GetPath() == U){
499 dest->SetFirstChild(CopyQuery(source->GetFirstChild()));
500 dest->SetSecondChild(CopyQuery(source->GetSecondChild()));
501 }
502 else{
503 dest->SetFirstChild(CopyQuery(source->GetFirstChild()));
504 }
505 return dest;
506 }
507 else assert(false && "ERROR::: Copying query failed");
508}
0509
=== added file 'CTLParser/CTLParser_v2.h'
--- CTLParser/CTLParser_v2.h 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLParser_v2.h 2016-05-20 07:41:18 +0000
@@ -0,0 +1,56 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLParser_v2.h
9 * Author: mossns
10 *
11 * Created on April 22, 2016, 10:15 AM
12 */
13
14#ifndef CTLPARSER_V2_H
15#define CTLPARSER_V2_H
16
17#include "rapidxml-1.13/rapidxml.hpp"
18#include <vector>
19#include <string>
20#include <stdio.h>
21#include "CTLQuery.h"
22
23struct QueryMeta{
24 int numberof_queries = 0;
25 std::string model_name;
26
27};
28
29class CTLParser_v2 {
30public:
31 CTLParser_v2();
32 CTLParser_v2(const CTLParser_v2& orig);
33 virtual ~CTLParser_v2();
34 CTLQuery * ParseXMLQuery(std::vector<char> buffer, int query_number);
35 CTLQuery* FormatQuery(CTLQuery* query, PetriEngine::PetriNet *net);
36 std::string QueryToString(CTLQuery* query);
37 QueryMeta * GetQueryMetaData(std::vector<char> buffer);
38private:
39 CTLQuery* xmlToCTLquery(rapidxml::xml_node<> * root);
40 std::string parsePar(rapidxml::xml_node<> * parameter);
41 Path getPathOperator(rapidxml::xml_node<> * quantifyer_node);
42 int max_depth(int a, int b);
43 std::string loperator_sym(std::string loperator);
44 CTLQuery * CopyQuery(CTLQuery *source);
45
46 CTLQuery* FillAtom(CTLQuery* query, PetriEngine::PetriNet *net);
47 CTLQuery* ConvertAG(CTLQuery* query);
48 CTLQuery* ConvertEG(CTLQuery* query);
49 CTLQuery* TemporalSetting(CTLQuery* query);
50 int IdSetting(CTLQuery* query, int id);
51 QueryMeta *_meta;
52
53};
54
55#endif /* CTLPARSER_V2_H */
56
057
=== added file 'CTLParser/CTLQuery.cpp'
--- CTLParser/CTLQuery.cpp 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLQuery.cpp 2016-05-20 07:41:18 +0000
@@ -0,0 +1,159 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLQuery.cpp
9 * Author: mossns
10 *
11 * Created on April 22, 2016, 7:57 AM
12 */
13
14#include <string.h>
15
16#include "CTLQuery.h"
17#include "CTLParser.h"
18
19CTLQuery::CTLQuery(Quantifier q, Path p, bool isAtom, std::string atom_str) {
20 if(isAtom){
21 assert(q == EMPTY);
22 assert(p == pError);
23 assert(atom_str.compare("") != 0);
24
25 _hasAtom = true;
26 _hasQuantifier = false;
27 _hasPath = false;
28 _q = q;
29 _path = p;
30 _a = atom_str;
31 IsTemporal = false;
32 }
33 else if(q == AND || q == OR || q == NEG){
34 assert(p == pError);
35 _hasAtom = false;
36 _hasQuantifier = true;
37 _hasPath = false;
38 _q = q;
39 _path = p;
40 _a = "";
41 IsTemporal = false;
42 }
43 else{
44 assert(q != EMPTY);
45 assert(p != pError);
46 _hasAtom = false;
47 _hasQuantifier = true;
48 _hasPath = true;
49 _q = q;
50 _path = p;
51 _a = "";
52 IsTemporal = true;
53 }
54
55}
56
57CTLQuery::~CTLQuery() {
58}
59
60CTLType CTLQuery::GetQueryType(){
61 if(_hasAtom)
62 return EVAL;
63 else if(_path != pError)
64 return PATHQEURY;
65 else if(_q == AND || _q == OR || _q == NEG)
66 return LOPERATOR;
67 return TYPE_ERROR;
68}
69
70CTLQuery* CTLQuery::GetFirstChild(){
71 if(_hasAtom){
72 std::cout<<"Query " << ToString() << " does not have child"<<std::endl;
73 throw 20;
74 }
75 return _firstchild;
76}
77
78CTLQuery* CTLQuery::GetSecondChild(){
79 assert(!_hasAtom && "Query does not have children");
80 assert(!(_path == F || _path == G || _path == X) && "Query does not have second child");
81 assert(!(_q == NEG) && "Query does not have second child");
82 return _secondchild;
83}
84
85void CTLQuery::SetFirstChild(CTLQuery *q){
86 _firstchild = q;
87}
88
89void CTLQuery::SetSecondChild(CTLQuery *q){
90 _secondchild = q;
91}
92
93Quantifier CTLQuery::GetQuantifier(){
94 return _q;
95}
96
97Path CTLQuery::GetPath(){
98 return _path;
99}
100
101std::string CTLQuery::GetAtom(){
102 return _a;
103}
104
105EvaluateableProposition* CTLQuery::GetProposition(){
106 assert(_hasAtom && "Query does not have proposition");
107 return _proposition;
108}
109
110void CTLQuery::SetProposition(EvaluateableProposition *p){
111 assert(_hasAtom && "Query does not have proposition");
112 _proposition = p;
113}
114
115std::string CTLQuery::ToString(){
116 if(_hasAtom){
117 return _a;
118 }
119 else if(_q == AND){
120 return " & ";
121 }
122 else if(_q == OR){
123 return " | ";
124 }
125 else if(_q == NEG){
126 return "!";
127 }
128 else if(_q == A || _q == E){
129 std::string quanti = "";
130 if (_q == A){
131 quanti = "A";
132 }
133 else quanti = "E";
134 if(_path == F){
135 return quanti + "F";
136 }
137 else if(_path == G){
138 return quanti + "G";
139 }
140 else if(_path == X){
141 return quanti + "X";
142 }
143 else if(_path == U){
144
145 return quanti.append("U");
146 }
147 else{
148 std::cout<<"::::::Error Printing: Path was empty::::"<<std::endl;
149 assert(false);
150 }
151 }
152 else{
153 std::cout<<"::::::Error Printing: Q was empty::::"<<std::endl;
154 assert(false);
155 }
156}
157
158
159
0160
=== added file 'CTLParser/CTLQuery.h'
--- CTLParser/CTLQuery.h 1970-01-01 00:00:00 +0000
+++ CTLParser/CTLQuery.h 2016-05-20 07:41:18 +0000
@@ -0,0 +1,66 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: CTLQuery.h
9 * Author: Søren Moss Nielsen
10 *
11 * Created on April 22, 2016, 7:57 AM
12 */
13
14#ifndef CTLQUERY_H
15#define CTLQUERY_H
16#include "CTLParser.h"
17#include "EvaluateableProposition.h"
18
19enum CTLType {PATHQEURY = 1, LOPERATOR = 2, EVAL = 3, TYPE_ERROR = -1};
20
21class CTLQuery {
22
23public:
24 CTLQuery(Quantifier q, Path p, bool isAtom, std::string atom_str);
25 virtual ~CTLQuery();
26
27 int Id;
28 int Depth;
29
30 CTLType GetQueryType();
31 CTLQuery* GetFirstChild();
32 CTLQuery* GetSecondChild();
33 void SetFirstChild(CTLQuery *q);
34 void SetSecondChild(CTLQuery *q);
35 std::string ToString();
36
37 Quantifier GetQuantifier();
38 Path GetPath();
39 std::string GetAtom();
40
41 EvaluateableProposition* GetProposition();
42 void SetProposition(EvaluateableProposition *p);
43
44 bool IsTemporal;
45
46
47private:
48 std::string CreateEvaluateableProposition(std::string a);
49
50 bool _hasQuantifier;
51 bool _hasPath;
52 bool _hasAtom;
53 Quantifier _q;
54 Path _path;
55 std::string _a;
56
57 CTLQuery* _firstchild;
58 CTLQuery* _secondchild;
59
60 EvaluateableProposition* _proposition;
61
62
63};
64
65#endif /* CTLQUERY_H */
66
067
=== added file 'CTLParser/EvaluateableProposition.cpp'
--- CTLParser/EvaluateableProposition.cpp 1970-01-01 00:00:00 +0000
+++ CTLParser/EvaluateableProposition.cpp 2016-05-20 07:41:18 +0000
@@ -0,0 +1,189 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: EvaluateableProposition.cpp
9 * Author: mossns
10 *
11 * Created on April 27, 2016, 2:36 PM
12 */
13
14#include <string>
15#include <stdexcept>
16#include <sstream>
17
18#include "EvaluateableProposition.h"
19#include "CTLParser.h"
20
21namespace patch
22{
23 //A replacement for the standard to string function, which we cannot use because old OS X does not have c++11
24 template < typename T > std::string to_string( const T& n )
25 {
26 std::ostringstream stm ;
27 stm << n ;
28 return stm.str() ;
29 }
30}
31
32EvaluateableProposition::EvaluateableProposition(std::string a, PetriEngine::PetriNet *net) {
33 if(a.substr(0,2).compare("in") == 0 || a.substr(0,2).compare("to") == 0){
34 _type = CARDINALITY;
35 _loperator = SetLoperator(a);
36 assert(_loperator != NOT_CARDINALITY);
37
38 size_t begin = a.find('(') + 1;
39 size_t end = a.find(')') - begin;
40 std::string first_parameter_str = a.substr(begin, end);
41 a = a.substr(a.find(')') + 1);
42
43 begin = a.find('(') + 1;
44 end = a.find(')') - begin;
45 std::string second_parameter_str = a.substr(begin, end);
46 _firstParameter = CreateParameter(first_parameter_str, net->placeNames(), net->numberOfPlaces());
47 _secondParameter = CreateParameter(second_parameter_str, net->placeNames(), net->numberOfPlaces());
48 }
49 else if(a.substr(0,2).compare("is") == 0){
50 _type = FIREABILITY;
51 _loperator = NOT_CARDINALITY;
52 size_t s_pos = a.find('(') + 1;
53 size_t e_pos = a.find(')') - 1;
54 assert(s_pos < e_pos);
55 int fire_str_length = e_pos - s_pos + 1;
56 std::string fireset_str = a.substr(s_pos, fire_str_length);
57 SetFireset(fireset_str, net->transitionNames(), net->numberOfTransitions());
58 }
59 else if(a.substr(0,2).compare("tr") == 0){
60
61 }
62 else if(a.substr(0,2).compare("fa") == 0){
63
64 }
65 else{
66 assert(false && "Atomic string proposed for proposition could not be parsed");
67 }
68}
69
70EvaluateableProposition::~EvaluateableProposition() {
71}
72
73PropositionType EvaluateableProposition::GetPropositionType(){
74 return _type;
75}
76
77LoperatorType EvaluateableProposition::GetLoperator(){
78 assert(_type == CARDINALITY && "Proposition is not a cardinality proposition");
79 return _loperator;
80}
81
82std::vector<int> EvaluateableProposition::GetFireset() {
83 assert(_type == FIREABILITY && "Proposition is not a fireability proposition");
84 return _fireset;
85}
86
87void EvaluateableProposition::SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t){
88 std::string restof_firestring = fireset_str;
89 while(restof_firestring.length() > 0){
90 size_t position = restof_firestring.find(',');
91 std::string current_t = restof_firestring.substr(0, position);
92 for(int i = 0; i < numberof_t; i++){
93 if (current_t.compare(t_names[i]) == 0){
94 _fireset.push_back(i);
95 }
96 }
97 if (position != -1)
98 restof_firestring = restof_firestring.substr(position);
99 else
100 restof_firestring = "";
101 }
102 for ( auto f : _fireset){
103 std::cout<<f<<" is id of "<< t_names[f]<<std::endl;
104 }
105}
106
107CardinalityParameter* EvaluateableProposition::CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p){
108 CardinalityParameter *param = new CardinalityParameter();
109 std::string::size_type sz;
110 char c;
111 if(sscanf(parameter_str.c_str(), "%d%c", &param->value, &c) == 1) {
112 //If string is identifier starting with a number, you will read two items.
113 //If it's an identifier starting with a character, you will read zero items.
114 //The only time when you read just one item if the whole string is just numbers.
115 param->isPlace = false;
116 } else { //error
117
118 param->isPlace = true;
119 std::vector<std::string> places_str;
120 std::size_t found = parameter_str.find(",");
121
122 while(found != parameter_str.npos){
123 std::string temp = parameter_str.substr(0, found);
124 places_str.push_back(temp);
125 parameter_str = parameter_str.substr(found + 2);
126 found = parameter_str.find(",");
127 }
128
129 places_str.push_back(parameter_str);
130
131 for(int i = 0; i < numberof_p; i++){
132 for(std::string place : places_str){
133 if(p_names[i].compare(place) == 0){
134 param->places_i.push_back(i);
135 }
136 }
137 }
138 }
139 return param;
140}
141
142LoperatorType EvaluateableProposition::SetLoperator(std::string atom_str){
143 std::string loperator_str = atom_str.substr(atom_str.find(')'));
144 loperator_str = loperator_str.substr(0, loperator_str.find('('));
145 if(loperator_str.compare(" le "))
146 return LEQ;
147 else if (loperator_str.compare(" ge "))
148 return GRQ;
149 else if (loperator_str.compare(" eq "))
150 return EQ;
151 else assert(false && "Could not parse the given logical operator");
152}
153
154std::string EvaluateableProposition::ToString() {
155 if (_type == FIREABILITY) {
156 std::string fire_str = "Fireset(";
157 for(auto f : _fireset){
158 fire_str = fire_str + " " + patch::to_string(f);
159 }
160 return fire_str + ")";
161 }
162 else if (_type == CARDINALITY){
163 std::string cardi_str = "(";
164 if(_firstParameter->isPlace)
165 cardi_str = cardi_str + "place(" + patch::to_string(_firstParameter->value) + ")";
166 else
167 cardi_str = cardi_str = patch::to_string(_firstParameter->value);
168
169 cardi_str = cardi_str + " le ";
170
171 if(_secondParameter->isPlace)
172 cardi_str = cardi_str + "place(" + patch::to_string(_secondParameter->value) + ")";
173 else
174 cardi_str = cardi_str = patch::to_string(_secondParameter->value);
175 return cardi_str + ")";
176 }
177 else
178 assert(false && "Proposition had no type");
179}
180
181CardinalityParameter* EvaluateableProposition::GetFirstParameter() {
182 assert(_type == CARDINALITY);
183 return _firstParameter;
184}
185
186CardinalityParameter* EvaluateableProposition::GetSecondParameter() {
187 assert(_type == CARDINALITY);
188 return _secondParameter;
189}
0190
=== added file 'CTLParser/EvaluateableProposition.h'
--- CTLParser/EvaluateableProposition.h 1970-01-01 00:00:00 +0000
+++ CTLParser/EvaluateableProposition.h 2016-05-20 07:41:18 +0000
@@ -0,0 +1,53 @@
1/*
2 * To change this license header, choose License Headers in Project Properties.
3 * To change this template file, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7/*
8 * File: EvaluateableProposition.h
9 * Author: mossns
10 *
11 * Created on April 27, 2016, 2:36 PM
12 */
13
14#ifndef EVALUATEABLEPROPOSITION_H
15#define EVALUATEABLEPROPOSITION_H
16#include <vector>
17#include "PetriEngine/PetriNet.h"
18
19
20enum PropositionType {CARDINALITY = 0, FIREABILITY = 1};
21enum LoperatorType {NOT_CARDINALITY = -1, EQ = 0, LE = 1, LEQ = 2, GR = 3, GRQ = 4};
22
23struct CardinalityParameter{
24 bool isPlace;
25 int value;
26 std::vector<int> places_i;
27};
28
29class EvaluateableProposition {
30public:
31 EvaluateableProposition(std::string a, PetriEngine::PetriNet *net);
32 virtual ~EvaluateableProposition();
33 PropositionType GetPropositionType();
34 LoperatorType GetLoperator();
35 std::vector<int> GetFireset();
36 std::string ToString();
37 CardinalityParameter* GetFirstParameter();
38 CardinalityParameter* GetSecondParameter();
39private:
40 void SetFireset(std::string fireset_str, std::vector<std::string> t_names, unsigned int numberof_t);
41 CardinalityParameter* CreateParameter(std::string parameter_str, std::vector<std::string> p_names, unsigned int numberof_p);
42 LoperatorType SetLoperator(std::string atom_str);
43
44 PropositionType _type;
45 LoperatorType _loperator;
46 std::vector<int> _fireset;
47 CardinalityParameter* _firstParameter;
48 CardinalityParameter* _secondParameter;
49
50};
51
52#endif /* EVALUATEABLEPROPOSITION_H */
53
054
=== added directory 'Tests/unitTesting'
=== added file 'Tests/unitTesting/catch.hpp'
--- Tests/unitTesting/catch.hpp 1970-01-01 00:00:00 +0000
+++ Tests/unitTesting/catch.hpp 2016-05-20 07:41:18 +0000
@@ -0,0 +1,10483 @@
1/*
2 * Catch v1.5.1
3 * Generated: 2016-04-28 08:12:37.387488
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
7 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 */
11#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13
14#define TWOBLUECUBES_CATCH_HPP_INCLUDED
15
16#ifdef __clang__
17# pragma clang system_header
18#elif defined __GNUC__
19# pragma GCC system_header
20#endif
21
22// #included from: internal/catch_suppress_warnings.h
23
24#ifdef __clang__
25# ifdef __ICC // icpc defines the __clang__ macro
26# pragma warning(push)
27# pragma warning(disable: 161 1682)
28# else // __ICC
29# pragma clang diagnostic ignored "-Wglobal-constructors"
30# pragma clang diagnostic ignored "-Wvariadic-macros"
31# pragma clang diagnostic ignored "-Wc99-extensions"
32# pragma clang diagnostic ignored "-Wunused-variable"
33# pragma clang diagnostic push
34# pragma clang diagnostic ignored "-Wpadded"
35# pragma clang diagnostic ignored "-Wc++98-compat"
36# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37# pragma clang diagnostic ignored "-Wswitch-enum"
38# pragma clang diagnostic ignored "-Wcovered-switch-default"
39# endif
40#elif defined __GNUC__
41# pragma GCC diagnostic ignored "-Wvariadic-macros"
42# pragma GCC diagnostic ignored "-Wunused-variable"
43# pragma GCC diagnostic push
44# pragma GCC diagnostic ignored "-Wpadded"
45#endif
46#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
47# define CATCH_IMPL
48#endif
49
50#ifdef CATCH_IMPL
51# ifndef CLARA_CONFIG_MAIN
52# define CLARA_CONFIG_MAIN_NOT_DEFINED
53# define CLARA_CONFIG_MAIN
54# endif
55#endif
56
57// #included from: internal/catch_notimplemented_exception.h
58#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
59
60// #included from: catch_common.h
61#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
62
63#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
64#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
65#ifdef CATCH_CONFIG_COUNTER
66# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
67#else
68# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
69#endif
70
71#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
72#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
73
74#include <sstream>
75#include <stdexcept>
76#include <algorithm>
77
78// #included from: catch_compiler_capabilities.h
79#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
80
81// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
82// The following features are defined:
83//
84// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
85// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
86// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
87// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
88// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
89// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
90// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
91// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
92
93// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
94
95// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
96// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
97// ****************
98// Note to maintainers: if new toggles are added please document them
99// in configuration.md, too
100// ****************
101
102// In general each macro has a _NO_<feature name> form
103// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
104// Many features, at point of detection, define an _INTERNAL_ macro, so they
105// can be combined, en-mass, with the _NO_ forms later.
106
107// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
108
109#if defined(__cplusplus) && __cplusplus >= 201103L
110# define CATCH_CPP11_OR_GREATER
111#endif
112
113#ifdef __clang__
114
115# if __has_feature(cxx_nullptr)
116# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
117# endif
118
119# if __has_feature(cxx_noexcept)
120# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
121# endif
122
123# if defined(CATCH_CPP11_OR_GREATER)
124# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
125# endif
126
127#endif // __clang__
128
129////////////////////////////////////////////////////////////////////////////////
130// Borland
131#ifdef __BORLANDC__
132
133#endif // __BORLANDC__
134
135////////////////////////////////////////////////////////////////////////////////
136// EDG
137#ifdef __EDG_VERSION__
138
139#endif // __EDG_VERSION__
140
141////////////////////////////////////////////////////////////////////////////////
142// Digital Mars
143#ifdef __DMC__
144
145#endif // __DMC__
146
147////////////////////////////////////////////////////////////////////////////////
148// GCC
149#ifdef __GNUC__
150
151# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
152# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
153# endif
154
155# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
156# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
157# endif
158
159// - otherwise more recent versions define __cplusplus >= 201103L
160// and will get picked up below
161
162#endif // __GNUC__
163
164////////////////////////////////////////////////////////////////////////////////
165// Visual C++
166#ifdef _MSC_VER
167
168#if (_MSC_VER >= 1600)
169# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
170# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
171#endif
172
173#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
174#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
175#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
176#endif
177
178#endif // _MSC_VER
179
180////////////////////////////////////////////////////////////////////////////////
181
182// Use variadic macros if the compiler supports them
183#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
184 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
185 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
186 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
187
188#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
189
190#endif
191
192// Use __COUNTER__ if the compiler supports it
193#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
194 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
195 ( defined __clang__ && __clang_major__ >= 3 )
196
197#define CATCH_INTERNAL_CONFIG_COUNTER
198
199#endif
200
201////////////////////////////////////////////////////////////////////////////////
202// C++ language feature support
203
204// catch all support for C++11
205#if defined(CATCH_CPP11_OR_GREATER)
206
207# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
208# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
209# endif
210
211# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
212# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
213# endif
214
215# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
216# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
217# endif
218
219# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
220# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
221# endif
222
223# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
224# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
225# endif
226
227# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
228# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
229# endif
230
231# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
232# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
233# endif
234
235# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
236# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
237# endif
238# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
239# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
240# endif
241
242#endif // __cplusplus >= 201103L
243
244// Now set the actual defines based on the above + anything the user has configured
245#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
246# define CATCH_CONFIG_CPP11_NULLPTR
247#endif
248#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
249# define CATCH_CONFIG_CPP11_NOEXCEPT
250#endif
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)
252# define CATCH_CONFIG_CPP11_GENERATED_METHODS
253#endif
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)
255# define CATCH_CONFIG_CPP11_IS_ENUM
256#endif
257#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
258# define CATCH_CONFIG_CPP11_TUPLE
259#endif
260#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
261# define CATCH_CONFIG_VARIADIC_MACROS
262#endif
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)
264# define CATCH_CONFIG_CPP11_LONG_LONG
265#endif
266#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
267# define CATCH_CONFIG_CPP11_OVERRIDE
268#endif
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)
270# define CATCH_CONFIG_CPP11_UNIQUE_PTR
271#endif
272#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
273# define CATCH_CONFIG_COUNTER
274#endif
275
276#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
277# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
278#endif
279
280// noexcept support:
281#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
282# define CATCH_NOEXCEPT noexcept
283# define CATCH_NOEXCEPT_IS(x) noexcept(x)
284#else
285# define CATCH_NOEXCEPT throw()
286# define CATCH_NOEXCEPT_IS(x)
287#endif
288
289// nullptr support
290#ifdef CATCH_CONFIG_CPP11_NULLPTR
291# define CATCH_NULL nullptr
292#else
293# define CATCH_NULL NULL
294#endif
295
296// override support
297#ifdef CATCH_CONFIG_CPP11_OVERRIDE
298# define CATCH_OVERRIDE override
299#else
300# define CATCH_OVERRIDE
301#endif
302
303// unique_ptr support
304#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
305# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
306#else
307# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
308#endif
309
310namespace Catch {
311
312 struct IConfig;
313
314 struct CaseSensitive { enum Choice {
315 Yes,
316 No
317 }; };
318
319 class NonCopyable {
320#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
321 NonCopyable( NonCopyable const& ) = delete;
322 NonCopyable( NonCopyable && ) = delete;
323 NonCopyable& operator = ( NonCopyable const& ) = delete;
324 NonCopyable& operator = ( NonCopyable && ) = delete;
325#else
326 NonCopyable( NonCopyable const& info );
327 NonCopyable& operator = ( NonCopyable const& );
328#endif
329
330 protected:
331 NonCopyable() {}
332 virtual ~NonCopyable();
333 };
334
335 class SafeBool {
336 public:
337 typedef void (SafeBool::*type)() const;
338
339 static type makeSafe( bool value ) {
340 return value ? &SafeBool::trueValue : 0;
341 }
342 private:
343 void trueValue() const {}
344 };
345
346 template<typename ContainerT>
347 inline void deleteAll( ContainerT& container ) {
348 typename ContainerT::const_iterator it = container.begin();
349 typename ContainerT::const_iterator itEnd = container.end();
350 for(; it != itEnd; ++it )
351 delete *it;
352 }
353 template<typename AssociativeContainerT>
354 inline void deleteAllValues( AssociativeContainerT& container ) {
355 typename AssociativeContainerT::const_iterator it = container.begin();
356 typename AssociativeContainerT::const_iterator itEnd = container.end();
357 for(; it != itEnd; ++it )
358 delete it->second;
359 }
360
361 bool startsWith( std::string const& s, std::string const& prefix );
362 bool endsWith( std::string const& s, std::string const& suffix );
363 bool contains( std::string const& s, std::string const& infix );
364 void toLowerInPlace( std::string& s );
365 std::string toLower( std::string const& s );
366 std::string trim( std::string const& str );
367 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
368
369 struct pluralise {
370 pluralise( std::size_t count, std::string const& label );
371
372 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
373
374 std::size_t m_count;
375 std::string m_label;
376 };
377
378 struct SourceLineInfo {
379
380 SourceLineInfo();
381 SourceLineInfo( char const* _file, std::size_t _line );
382 SourceLineInfo( SourceLineInfo const& other );
383# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
384 SourceLineInfo( SourceLineInfo && ) = default;
385 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
386 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
387# endif
388 bool empty() const;
389 bool operator == ( SourceLineInfo const& other ) const;
390 bool operator < ( SourceLineInfo const& other ) const;
391
392 std::string file;
393 std::size_t line;
394 };
395
396 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
397
398 // This is just here to avoid compiler warnings with macro constants and boolean literals
399 inline bool isTrue( bool value ){ return value; }
400 inline bool alwaysTrue() { return true; }
401 inline bool alwaysFalse() { return false; }
402
403 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
404
405 void seedRng( IConfig const& config );
406 unsigned int rngSeed();
407
408 // Use this in variadic streaming macros to allow
409 // >> +StreamEndStop
410 // as well as
411 // >> stuff +StreamEndStop
412 struct StreamEndStop {
413 std::string operator+() {
414 return std::string();
415 }
416 };
417 template<typename T>
418 T const& operator + ( T const& value, StreamEndStop ) {
419 return value;
420 }
421}
422
423#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
424#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
425
426#include <ostream>
427
428namespace Catch {
429
430 class NotImplementedException : public std::exception
431 {
432 public:
433 NotImplementedException( SourceLineInfo const& lineInfo );
434 NotImplementedException( NotImplementedException const& ) {}
435
436 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
437
438 virtual const char* what() const CATCH_NOEXCEPT;
439
440 private:
441 std::string m_what;
442 SourceLineInfo m_lineInfo;
443 };
444
445} // end namespace Catch
446
447///////////////////////////////////////////////////////////////////////////////
448#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
449
450// #included from: internal/catch_context.h
451#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
452
453// #included from: catch_interfaces_generators.h
454#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
455
456#include <string>
457
458namespace Catch {
459
460 struct IGeneratorInfo {
461 virtual ~IGeneratorInfo();
462 virtual bool moveNext() = 0;
463 virtual std::size_t getCurrentIndex() const = 0;
464 };
465
466 struct IGeneratorsForTest {
467 virtual ~IGeneratorsForTest();
468
469 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
470 virtual bool moveNext() = 0;
471 };
472
473 IGeneratorsForTest* createGeneratorsForTest();
474
475} // end namespace Catch
476
477// #included from: catch_ptr.hpp
478#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
479
480#ifdef __clang__
481#pragma clang diagnostic push
482#pragma clang diagnostic ignored "-Wpadded"
483#endif
484
485namespace Catch {
486
487 // An intrusive reference counting smart pointer.
488 // T must implement addRef() and release() methods
489 // typically implementing the IShared interface
490 template<typename T>
491 class Ptr {
492 public:
493 Ptr() : m_p( CATCH_NULL ){}
494 Ptr( T* p ) : m_p( p ){
495 if( m_p )
496 m_p->addRef();
497 }
498 Ptr( Ptr const& other ) : m_p( other.m_p ){
499 if( m_p )
500 m_p->addRef();
501 }
502 ~Ptr(){
503 if( m_p )
504 m_p->release();
505 }
506 void reset() {
507 if( m_p )
508 m_p->release();
509 m_p = CATCH_NULL;
510 }
511 Ptr& operator = ( T* p ){
512 Ptr temp( p );
513 swap( temp );
514 return *this;
515 }
516 Ptr& operator = ( Ptr const& other ){
517 Ptr temp( other );
518 swap( temp );
519 return *this;
520 }
521 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
522 T* get() const{ return m_p; }
523 T& operator*() const { return *m_p; }
524 T* operator->() const { return m_p; }
525 bool operator !() const { return m_p == CATCH_NULL; }
526 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
527
528 private:
529 T* m_p;
530 };
531
532 struct IShared : NonCopyable {
533 virtual ~IShared();
534 virtual void addRef() const = 0;
535 virtual void release() const = 0;
536 };
537
538 template<typename T = IShared>
539 struct SharedImpl : T {
540
541 SharedImpl() : m_rc( 0 ){}
542
543 virtual void addRef() const {
544 ++m_rc;
545 }
546 virtual void release() const {
547 if( --m_rc == 0 )
548 delete this;
549 }
550
551 mutable unsigned int m_rc;
552 };
553
554} // end namespace Catch
555
556#ifdef __clang__
557#pragma clang diagnostic pop
558#endif
559
560#include <memory>
561#include <vector>
562#include <stdlib.h>
563
564namespace Catch {
565
566 class TestCase;
567 class Stream;
568 struct IResultCapture;
569 struct IRunner;
570 struct IGeneratorsForTest;
571 struct IConfig;
572
573 struct IContext
574 {
575 virtual ~IContext();
576
577 virtual IResultCapture* getResultCapture() = 0;
578 virtual IRunner* getRunner() = 0;
579 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
580 virtual bool advanceGeneratorsForCurrentTest() = 0;
581 virtual Ptr<IConfig const> getConfig() const = 0;
582 };
583
584 struct IMutableContext : IContext
585 {
586 virtual ~IMutableContext();
587 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
588 virtual void setRunner( IRunner* runner ) = 0;
589 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
590 };
591
592 IContext& getCurrentContext();
593 IMutableContext& getCurrentMutableContext();
594 void cleanUpContext();
595 Stream createStream( std::string const& streamName );
596
597}
598
599// #included from: internal/catch_test_registry.hpp
600#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
601
602// #included from: catch_interfaces_testcase.h
603#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
604
605#include <vector>
606
607namespace Catch {
608
609 class TestSpec;
610
611 struct ITestCase : IShared {
612 virtual void invoke () const = 0;
613 protected:
614 virtual ~ITestCase();
615 };
616
617 class TestCase;
618 struct IConfig;
619
620 struct ITestCaseRegistry {
621 virtual ~ITestCaseRegistry();
622 virtual std::vector<TestCase> const& getAllTests() const = 0;
623 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
624 };
625
626 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
627 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
628 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
629
630}
631
632namespace Catch {
633
634template<typename C>
635class MethodTestCase : public SharedImpl<ITestCase> {
636
637public:
638 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
639
640 virtual void invoke() const {
641 C obj;
642 (obj.*m_method)();
643 }
644
645private:
646 virtual ~MethodTestCase() {}
647
648 void (C::*m_method)();
649};
650
651typedef void(*TestFunction)();
652
653struct NameAndDesc {
654 NameAndDesc( const char* _name = "", const char* _description= "" )
655 : name( _name ), description( _description )
656 {}
657
658 const char* name;
659 const char* description;
660};
661
662void registerTestCase
663 ( ITestCase* testCase,
664 char const* className,
665 NameAndDesc const& nameAndDesc,
666 SourceLineInfo const& lineInfo );
667
668struct AutoReg {
669
670 AutoReg
671 ( TestFunction function,
672 SourceLineInfo const& lineInfo,
673 NameAndDesc const& nameAndDesc );
674
675 template<typename C>
676 AutoReg
677 ( void (C::*method)(),
678 char const* className,
679 NameAndDesc const& nameAndDesc,
680 SourceLineInfo const& lineInfo ) {
681
682 registerTestCase
683 ( new MethodTestCase<C>( method ),
684 className,
685 nameAndDesc,
686 lineInfo );
687 }
688
689 ~AutoReg();
690
691private:
692 AutoReg( AutoReg const& );
693 void operator= ( AutoReg const& );
694};
695
696void registerTestCaseFunction
697 ( TestFunction function,
698 SourceLineInfo const& lineInfo,
699 NameAndDesc const& nameAndDesc );
700
701} // end namespace Catch
702
703#ifdef CATCH_CONFIG_VARIADIC_MACROS
704 ///////////////////////////////////////////////////////////////////////////////
705 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
706 static void TestName(); \
707 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
708 static void TestName()
709 #define INTERNAL_CATCH_TESTCASE( ... ) \
710 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
711
712 ///////////////////////////////////////////////////////////////////////////////
713 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
714 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
715
716 ///////////////////////////////////////////////////////////////////////////////
717 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
718 namespace{ \
719 struct TestName : ClassName{ \
720 void test(); \
721 }; \
722 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
723 } \
724 void TestName::test()
725 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
726 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
727
728 ///////////////////////////////////////////////////////////////////////////////
729 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
730 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
731
732#else
733 ///////////////////////////////////////////////////////////////////////////////
734 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
735 static void TestName(); \
736 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
737 static void TestName()
738 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
739 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
740
741 ///////////////////////////////////////////////////////////////////////////////
742 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
743 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
744
745 ///////////////////////////////////////////////////////////////////////////////
746 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
747 namespace{ \
748 struct TestCaseName : ClassName{ \
749 void test(); \
750 }; \
751 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
752 } \
753 void TestCaseName::test()
754 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
755 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
756
757 ///////////////////////////////////////////////////////////////////////////////
758 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
759 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
760#endif
761
762// #included from: internal/catch_capture.hpp
763#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
764
765// #included from: catch_result_builder.h
766#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
767
768// #included from: catch_result_type.h
769#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
770
771namespace Catch {
772
773 // ResultWas::OfType enum
774 struct ResultWas { enum OfType {
775 Unknown = -1,
776 Ok = 0,
777 Info = 1,
778 Warning = 2,
779
780 FailureBit = 0x10,
781
782 ExpressionFailed = FailureBit | 1,
783 ExplicitFailure = FailureBit | 2,
784
785 Exception = 0x100 | FailureBit,
786
787 ThrewException = Exception | 1,
788 DidntThrowException = Exception | 2,
789
790 FatalErrorCondition = 0x200 | FailureBit
791
792 }; };
793
794 inline bool isOk( ResultWas::OfType resultType ) {
795 return ( resultType & ResultWas::FailureBit ) == 0;
796 }
797 inline bool isJustInfo( int flags ) {
798 return flags == ResultWas::Info;
799 }
800
801 // ResultDisposition::Flags enum
802 struct ResultDisposition { enum Flags {
803 Normal = 0x01,
804
805 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
806 FalseTest = 0x04, // Prefix expression with !
807 SuppressFail = 0x08 // Failures are reported but do not fail the test
808 }; };
809
810 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
811 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
812 }
813
814 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
815 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
816 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
817
818} // end namespace Catch
819
820// #included from: catch_assertionresult.h
821#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
822
823#include <string>
824
825namespace Catch {
826
827 struct AssertionInfo
828 {
829 AssertionInfo() {}
830 AssertionInfo( std::string const& _macroName,
831 SourceLineInfo const& _lineInfo,
832 std::string const& _capturedExpression,
833 ResultDisposition::Flags _resultDisposition );
834
835 std::string macroName;
836 SourceLineInfo lineInfo;
837 std::string capturedExpression;
838 ResultDisposition::Flags resultDisposition;
839 };
840
841 struct AssertionResultData
842 {
843 AssertionResultData() : resultType( ResultWas::Unknown ) {}
844
845 std::string reconstructedExpression;
846 std::string message;
847 ResultWas::OfType resultType;
848 };
849
850 class AssertionResult {
851 public:
852 AssertionResult();
853 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
854 ~AssertionResult();
855# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
856 AssertionResult( AssertionResult const& ) = default;
857 AssertionResult( AssertionResult && ) = default;
858 AssertionResult& operator = ( AssertionResult const& ) = default;
859 AssertionResult& operator = ( AssertionResult && ) = default;
860# endif
861
862 bool isOk() const;
863 bool succeeded() const;
864 ResultWas::OfType getResultType() const;
865 bool hasExpression() const;
866 bool hasMessage() const;
867 std::string getExpression() const;
868 std::string getExpressionInMacro() const;
869 bool hasExpandedExpression() const;
870 std::string getExpandedExpression() const;
871 std::string getMessage() const;
872 SourceLineInfo getSourceInfo() const;
873 std::string getTestMacroName() const;
874
875 protected:
876 AssertionInfo m_info;
877 AssertionResultData m_resultData;
878 };
879
880} // end namespace Catch
881
882// #included from: catch_matchers.hpp
883#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
884
885namespace Catch {
886namespace Matchers {
887 namespace Impl {
888
889 namespace Generic {
890 template<typename ExpressionT> class AllOf;
891 template<typename ExpressionT> class AnyOf;
892 template<typename ExpressionT> class Not;
893 }
894
895 template<typename ExpressionT>
896 struct Matcher : SharedImpl<IShared>
897 {
898 typedef ExpressionT ExpressionType;
899
900 virtual ~Matcher() {}
901 virtual Ptr<Matcher> clone() const = 0;
902 virtual bool match( ExpressionT const& expr ) const = 0;
903 virtual std::string toString() const = 0;
904
905 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
906 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
907 Generic::Not<ExpressionT> operator ! () const;
908 };
909
910 template<typename DerivedT, typename ExpressionT>
911 struct MatcherImpl : Matcher<ExpressionT> {
912
913 virtual Ptr<Matcher<ExpressionT> > clone() const {
914 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
915 }
916 };
917
918 namespace Generic {
919 template<typename ExpressionT>
920 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
921 public:
922 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
923 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
924
925 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
926 return !m_matcher->match( expr );
927 }
928
929 virtual std::string toString() const CATCH_OVERRIDE {
930 return "not " + m_matcher->toString();
931 }
932 private:
933 Ptr< Matcher<ExpressionT> > m_matcher;
934 };
935
936 template<typename ExpressionT>
937 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
938 public:
939
940 AllOf() {}
941 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
942
943 AllOf& add( Matcher<ExpressionT> const& matcher ) {
944 m_matchers.push_back( matcher.clone() );
945 return *this;
946 }
947 virtual bool match( ExpressionT const& expr ) const
948 {
949 for( std::size_t i = 0; i < m_matchers.size(); ++i )
950 if( !m_matchers[i]->match( expr ) )
951 return false;
952 return true;
953 }
954 virtual std::string toString() const {
955 std::ostringstream oss;
956 oss << "( ";
957 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
958 if( i != 0 )
959 oss << " and ";
960 oss << m_matchers[i]->toString();
961 }
962 oss << " )";
963 return oss.str();
964 }
965
966 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
967 AllOf allOfExpr( *this );
968 allOfExpr.add( other );
969 return allOfExpr;
970 }
971
972 private:
973 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
974 };
975
976 template<typename ExpressionT>
977 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
978 public:
979
980 AnyOf() {}
981 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
982
983 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
984 m_matchers.push_back( matcher.clone() );
985 return *this;
986 }
987 virtual bool match( ExpressionT const& expr ) const
988 {
989 for( std::size_t i = 0; i < m_matchers.size(); ++i )
990 if( m_matchers[i]->match( expr ) )
991 return true;
992 return false;
993 }
994 virtual std::string toString() const {
995 std::ostringstream oss;
996 oss << "( ";
997 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
998 if( i != 0 )
999 oss << " or ";
1000 oss << m_matchers[i]->toString();
1001 }
1002 oss << " )";
1003 return oss.str();
1004 }
1005
1006 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
1007 AnyOf anyOfExpr( *this );
1008 anyOfExpr.add( other );
1009 return anyOfExpr;
1010 }
1011
1012 private:
1013 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
1014 };
1015
1016 } // namespace Generic
1017
1018 template<typename ExpressionT>
1019 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
1020 Generic::AllOf<ExpressionT> allOfExpr;
1021 allOfExpr.add( *this );
1022 allOfExpr.add( other );
1023 return allOfExpr;
1024 }
1025
1026 template<typename ExpressionT>
1027 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
1028 Generic::AnyOf<ExpressionT> anyOfExpr;
1029 anyOfExpr.add( *this );
1030 anyOfExpr.add( other );
1031 return anyOfExpr;
1032 }
1033
1034 template<typename ExpressionT>
1035 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
1036 return Generic::Not<ExpressionT>( *this );
1037 }
1038
1039 namespace StdString {
1040
1041 inline std::string makeString( std::string const& str ) { return str; }
1042 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
1043
1044 struct CasedString
1045 {
1046 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
1047 : m_caseSensitivity( caseSensitivity ),
1048 m_str( adjustString( str ) )
1049 {}
1050 std::string adjustString( std::string const& str ) const {
1051 return m_caseSensitivity == CaseSensitive::No
1052 ? toLower( str )
1053 : str;
1054
1055 }
1056 std::string toStringSuffix() const
1057 {
1058 return m_caseSensitivity == CaseSensitive::No
1059 ? " (case insensitive)"
1060 : "";
1061 }
1062 CaseSensitive::Choice m_caseSensitivity;
1063 std::string m_str;
1064 };
1065
1066 struct Equals : MatcherImpl<Equals, std::string> {
1067 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1068 : m_data( str, caseSensitivity )
1069 {}
1070 Equals( Equals const& other ) : m_data( other.m_data ){}
1071
1072 virtual ~Equals();
1073
1074 virtual bool match( std::string const& expr ) const {
1075 return m_data.m_str == m_data.adjustString( expr );;
1076 }
1077 virtual std::string toString() const {
1078 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1079 }
1080
1081 CasedString m_data;
1082 };
1083
1084 struct Contains : MatcherImpl<Contains, std::string> {
1085 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1086 : m_data( substr, caseSensitivity ){}
1087 Contains( Contains const& other ) : m_data( other.m_data ){}
1088
1089 virtual ~Contains();
1090
1091 virtual bool match( std::string const& expr ) const {
1092 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1093 }
1094 virtual std::string toString() const {
1095 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1096 }
1097
1098 CasedString m_data;
1099 };
1100
1101 struct StartsWith : MatcherImpl<StartsWith, std::string> {
1102 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1103 : m_data( substr, caseSensitivity ){}
1104
1105 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
1106
1107 virtual ~StartsWith();
1108
1109 virtual bool match( std::string const& expr ) const {
1110 return startsWith( m_data.adjustString( expr ), m_data.m_str );
1111 }
1112 virtual std::string toString() const {
1113 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1114 }
1115
1116 CasedString m_data;
1117 };
1118
1119 struct EndsWith : MatcherImpl<EndsWith, std::string> {
1120 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1121 : m_data( substr, caseSensitivity ){}
1122 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
1123
1124 virtual ~EndsWith();
1125
1126 virtual bool match( std::string const& expr ) const {
1127 return endsWith( m_data.adjustString( expr ), m_data.m_str );
1128 }
1129 virtual std::string toString() const {
1130 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1131 }
1132
1133 CasedString m_data;
1134 };
1135 } // namespace StdString
1136 } // namespace Impl
1137
1138 // The following functions create the actual matcher objects.
1139 // This allows the types to be inferred
1140 template<typename ExpressionT>
1141 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
1142 return Impl::Generic::Not<ExpressionT>( m );
1143 }
1144
1145 template<typename ExpressionT>
1146 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1147 Impl::Matcher<ExpressionT> const& m2 ) {
1148 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
1149 }
1150 template<typename ExpressionT>
1151 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1152 Impl::Matcher<ExpressionT> const& m2,
1153 Impl::Matcher<ExpressionT> const& m3 ) {
1154 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1155 }
1156 template<typename ExpressionT>
1157 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1158 Impl::Matcher<ExpressionT> const& m2 ) {
1159 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1160 }
1161 template<typename ExpressionT>
1162 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1163 Impl::Matcher<ExpressionT> const& m2,
1164 Impl::Matcher<ExpressionT> const& m3 ) {
1165 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1166 }
1167
1168 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1169 return Impl::StdString::Equals( str, caseSensitivity );
1170 }
1171 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1172 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1173 }
1174 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1175 return Impl::StdString::Contains( substr, caseSensitivity );
1176 }
1177 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1178 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1179 }
1180 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
1181 return Impl::StdString::StartsWith( substr );
1182 }
1183 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
1184 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1185 }
1186 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
1187 return Impl::StdString::EndsWith( substr );
1188 }
1189 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
1190 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1191 }
1192
1193} // namespace Matchers
1194
1195using namespace Matchers;
1196
1197} // namespace Catch
1198
1199namespace Catch {
1200
1201 struct TestFailureException{};
1202
1203 template<typename T> class ExpressionLhs;
1204
1205 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1206
1207 struct CopyableStream {
1208 CopyableStream() {}
1209 CopyableStream( CopyableStream const& other ) {
1210 oss << other.oss.str();
1211 }
1212 CopyableStream& operator=( CopyableStream const& other ) {
1213 oss.str("");
1214 oss << other.oss.str();
1215 return *this;
1216 }
1217 std::ostringstream oss;
1218 };
1219
1220 class ResultBuilder {
1221 public:
1222 ResultBuilder( char const* macroName,
1223 SourceLineInfo const& lineInfo,
1224 char const* capturedExpression,
1225 ResultDisposition::Flags resultDisposition,
1226 char const* secondArg = "" );
1227
1228 template<typename T>
1229 ExpressionLhs<T const&> operator <= ( T const& operand );
1230 ExpressionLhs<bool> operator <= ( bool value );
1231
1232 template<typename T>
1233 ResultBuilder& operator << ( T const& value ) {
1234 m_stream.oss << value;
1235 return *this;
1236 }
1237
1238 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1239 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1240
1241 ResultBuilder& setResultType( ResultWas::OfType result );
1242 ResultBuilder& setResultType( bool result );
1243 ResultBuilder& setLhs( std::string const& lhs );
1244 ResultBuilder& setRhs( std::string const& rhs );
1245 ResultBuilder& setOp( std::string const& op );
1246
1247 void endExpression();
1248
1249 std::string reconstructExpression() const;
1250 AssertionResult build() const;
1251
1252 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1253 void captureResult( ResultWas::OfType resultType );
1254 void captureExpression();
1255 void captureExpectedException( std::string const& expectedMessage );
1256 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
1257 void handleResult( AssertionResult const& result );
1258 void react();
1259 bool shouldDebugBreak() const;
1260 bool allowThrows() const;
1261
1262 private:
1263 AssertionInfo m_assertionInfo;
1264 AssertionResultData m_data;
1265 struct ExprComponents {
1266 ExprComponents() : testFalse( false ) {}
1267 bool testFalse;
1268 std::string lhs, rhs, op;
1269 } m_exprComponents;
1270 CopyableStream m_stream;
1271
1272 bool m_shouldDebugBreak;
1273 bool m_shouldThrow;
1274 };
1275
1276} // namespace Catch
1277
1278// Include after due to circular dependency:
1279// #included from: catch_expression_lhs.hpp
1280#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1281
1282// #included from: catch_evaluate.hpp
1283#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1284
1285#ifdef _MSC_VER
1286#pragma warning(push)
1287#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1288#endif
1289
1290#include <cstddef>
1291
1292namespace Catch {
1293namespace Internal {
1294
1295 enum Operator {
1296 IsEqualTo,
1297 IsNotEqualTo,
1298 IsLessThan,
1299 IsGreaterThan,
1300 IsLessThanOrEqualTo,
1301 IsGreaterThanOrEqualTo
1302 };
1303
1304 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1305 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1306 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1307 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1308 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1309 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1310 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1311
1312 template<typename T>
1313 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1314
1315// nullptr_t support based on pull request #154 from Konstantin Baumann
1316#ifdef CATCH_CONFIG_CPP11_NULLPTR
1317 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1318#endif // CATCH_CONFIG_CPP11_NULLPTR
1319
1320 // So the compare overloads can be operator agnostic we convey the operator as a template
1321 // enum, which is used to specialise an Evaluator for doing the comparison.
1322 template<typename T1, typename T2, Operator Op>
1323 class Evaluator{};
1324
1325 template<typename T1, typename T2>
1326 struct Evaluator<T1, T2, IsEqualTo> {
1327 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1328 return bool( opCast( lhs ) == opCast( rhs ) );
1329 }
1330 };
1331 template<typename T1, typename T2>
1332 struct Evaluator<T1, T2, IsNotEqualTo> {
1333 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1334 return bool( opCast( lhs ) != opCast( rhs ) );
1335 }
1336 };
1337 template<typename T1, typename T2>
1338 struct Evaluator<T1, T2, IsLessThan> {
1339 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1340 return bool( opCast( lhs ) < opCast( rhs ) );
1341 }
1342 };
1343 template<typename T1, typename T2>
1344 struct Evaluator<T1, T2, IsGreaterThan> {
1345 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1346 return bool( opCast( lhs ) > opCast( rhs ) );
1347 }
1348 };
1349 template<typename T1, typename T2>
1350 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
1351 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1352 return bool( opCast( lhs ) >= opCast( rhs ) );
1353 }
1354 };
1355 template<typename T1, typename T2>
1356 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
1357 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1358 return bool( opCast( lhs ) <= opCast( rhs ) );
1359 }
1360 };
1361
1362 template<Operator Op, typename T1, typename T2>
1363 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1364 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1365 }
1366
1367 // This level of indirection allows us to specialise for integer types
1368 // to avoid signed/ unsigned warnings
1369
1370 // "base" overload
1371 template<Operator Op, typename T1, typename T2>
1372 bool compare( T1 const& lhs, T2 const& rhs ) {
1373 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1374 }
1375
1376 // unsigned X to int
1377 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1378 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1379 }
1380 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1381 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1382 }
1383 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1384 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1385 }
1386
1387 // unsigned X to long
1388 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1389 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1390 }
1391 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1392 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1393 }
1394 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1395 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1396 }
1397
1398 // int to unsigned X
1399 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1400 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1401 }
1402 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1403 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1404 }
1405 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1406 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1407 }
1408
1409 // long to unsigned X
1410 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1411 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1412 }
1413 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1414 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1415 }
1416 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1417 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1418 }
1419
1420 // pointer to long (when comparing against NULL)
1421 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1422 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1423 }
1424 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1425 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1426 }
1427
1428 // pointer to int (when comparing against NULL)
1429 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1430 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1431 }
1432 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1433 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1434 }
1435
1436#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1437 // long long to unsigned X
1438 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1439 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1440 }
1441 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1442 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1443 }
1444 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1445 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1446 }
1447 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1448 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1449 }
1450
1451 // unsigned long long to X
1452 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1453 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1454 }
1455 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1456 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1457 }
1458 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1459 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1460 }
1461 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1462 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1463 }
1464
1465 // pointer to long long (when comparing against NULL)
1466 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1467 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1468 }
1469 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1470 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1471 }
1472#endif // CATCH_CONFIG_CPP11_LONG_LONG
1473
1474#ifdef CATCH_CONFIG_CPP11_NULLPTR
1475 // pointer to nullptr_t (when comparing against nullptr)
1476 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1477 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1478 }
1479 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1480 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1481 }
1482#endif // CATCH_CONFIG_CPP11_NULLPTR
1483
1484} // end of namespace Internal
1485} // end of namespace Catch
1486
1487#ifdef _MSC_VER
1488#pragma warning(pop)
1489#endif
1490
1491// #included from: catch_tostring.h
1492#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1493
1494#include <sstream>
1495#include <iomanip>
1496#include <limits>
1497#include <vector>
1498#include <cstddef>
1499
1500#ifdef __OBJC__
1501// #included from: catch_objc_arc.hpp
1502#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1503
1504#import <Foundation/Foundation.h>
1505
1506#ifdef __has_feature
1507#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1508#else
1509#define CATCH_ARC_ENABLED 0
1510#endif
1511
1512void arcSafeRelease( NSObject* obj );
1513id performOptionalSelector( id obj, SEL sel );
1514
1515#if !CATCH_ARC_ENABLED
1516inline void arcSafeRelease( NSObject* obj ) {
1517 [obj release];
1518}
1519inline id performOptionalSelector( id obj, SEL sel ) {
1520 if( [obj respondsToSelector: sel] )
1521 return [obj performSelector: sel];
1522 return nil;
1523}
1524#define CATCH_UNSAFE_UNRETAINED
1525#define CATCH_ARC_STRONG
1526#else
1527inline void arcSafeRelease( NSObject* ){}
1528inline id performOptionalSelector( id obj, SEL sel ) {
1529#ifdef __clang__
1530#pragma clang diagnostic push
1531#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1532#endif
1533 if( [obj respondsToSelector: sel] )
1534 return [obj performSelector: sel];
1535#ifdef __clang__
1536#pragma clang diagnostic pop
1537#endif
1538 return nil;
1539}
1540#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1541#define CATCH_ARC_STRONG __strong
1542#endif
1543
1544#endif
1545
1546#ifdef CATCH_CONFIG_CPP11_TUPLE
1547#include <tuple>
1548#endif
1549
1550#ifdef CATCH_CONFIG_CPP11_IS_ENUM
1551#include <type_traits>
1552#endif
1553
1554namespace Catch {
1555
1556// Why we're here.
1557template<typename T>
1558std::string toString( T const& value );
1559
1560// Built in overloads
1561
1562std::string toString( std::string const& value );
1563std::string toString( std::wstring const& value );
1564std::string toString( const char* const value );
1565std::string toString( char* const value );
1566std::string toString( const wchar_t* const value );
1567std::string toString( wchar_t* const value );
1568std::string toString( int value );
1569std::string toString( unsigned long value );
1570std::string toString( unsigned int value );
1571std::string toString( const double value );
1572std::string toString( const float value );
1573std::string toString( bool value );
1574std::string toString( char value );
1575std::string toString( signed char value );
1576std::string toString( unsigned char value );
1577
1578#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1579std::string toString( long long value );
1580std::string toString( unsigned long long value );
1581#endif
1582
1583#ifdef CATCH_CONFIG_CPP11_NULLPTR
1584std::string toString( std::nullptr_t );
1585#endif
1586
1587#ifdef __OBJC__
1588 std::string toString( NSString const * const& nsstring );
1589 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1590 std::string toString( NSObject* const& nsObject );
1591#endif
1592
1593namespace Detail {
1594
1595 extern const std::string unprintableString;
1596
1597 struct BorgType {
1598 template<typename T> BorgType( T const& );
1599 };
1600
1601 struct TrueType { char sizer[1]; };
1602 struct FalseType { char sizer[2]; };
1603
1604 TrueType& testStreamable( std::ostream& );
1605 FalseType testStreamable( FalseType );
1606
1607 FalseType operator<<( std::ostream const&, BorgType const& );
1608
1609 template<typename T>
1610 struct IsStreamInsertable {
1611 static std::ostream &s;
1612 static T const&t;
1613 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1614 };
1615
1616#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1617 template<typename T,
1618 bool IsEnum = std::is_enum<T>::value
1619 >
1620 struct EnumStringMaker
1621 {
1622 static std::string convert( T const& ) { return unprintableString; }
1623 };
1624
1625 template<typename T>
1626 struct EnumStringMaker<T,true>
1627 {
1628 static std::string convert( T const& v )
1629 {
1630 return ::Catch::toString(
1631 static_cast<typename std::underlying_type<T>::type>(v)
1632 );
1633 }
1634 };
1635#endif
1636 template<bool C>
1637 struct StringMakerBase {
1638#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1639 template<typename T>
1640 static std::string convert( T const& v )
1641 {
1642 return EnumStringMaker<T>::convert( v );
1643 }
1644#else
1645 template<typename T>
1646 static std::string convert( T const& ) { return unprintableString; }
1647#endif
1648 };
1649
1650 template<>
1651 struct StringMakerBase<true> {
1652 template<typename T>
1653 static std::string convert( T const& _value ) {
1654 std::ostringstream oss;
1655 oss << _value;
1656 return oss.str();
1657 }
1658 };
1659
1660 std::string rawMemoryToString( const void *object, std::size_t size );
1661
1662 template<typename T>
1663 inline std::string rawMemoryToString( const T& object ) {
1664 return rawMemoryToString( &object, sizeof(object) );
1665 }
1666
1667} // end namespace Detail
1668
1669template<typename T>
1670struct StringMaker :
1671 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1672
1673template<typename T>
1674struct StringMaker<T*> {
1675 template<typename U>
1676 static std::string convert( U* p ) {
1677 if( !p )
1678 return "NULL";
1679 else
1680 return Detail::rawMemoryToString( p );
1681 }
1682};
1683
1684template<typename R, typename C>
1685struct StringMaker<R C::*> {
1686 static std::string convert( R C::* p ) {
1687 if( !p )
1688 return "NULL";
1689 else
1690 return Detail::rawMemoryToString( p );
1691 }
1692};
1693
1694namespace Detail {
1695 template<typename InputIterator>
1696 std::string rangeToString( InputIterator first, InputIterator last );
1697}
1698
1699//template<typename T, typename Allocator>
1700//struct StringMaker<std::vector<T, Allocator> > {
1701// static std::string convert( std::vector<T,Allocator> const& v ) {
1702// return Detail::rangeToString( v.begin(), v.end() );
1703// }
1704//};
1705
1706template<typename T, typename Allocator>
1707std::string toString( std::vector<T,Allocator> const& v ) {
1708 return Detail::rangeToString( v.begin(), v.end() );
1709}
1710
1711#ifdef CATCH_CONFIG_CPP11_TUPLE
1712
1713// toString for tuples
1714namespace TupleDetail {
1715 template<
1716 typename Tuple,
1717 std::size_t N = 0,
1718 bool = (N < std::tuple_size<Tuple>::value)
1719 >
1720 struct ElementPrinter {
1721 static void print( const Tuple& tuple, std::ostream& os )
1722 {
1723 os << ( N ? ", " : " " )
1724 << Catch::toString(std::get<N>(tuple));
1725 ElementPrinter<Tuple,N+1>::print(tuple,os);
1726 }
1727 };
1728
1729 template<
1730 typename Tuple,
1731 std::size_t N
1732 >
1733 struct ElementPrinter<Tuple,N,false> {
1734 static void print( const Tuple&, std::ostream& ) {}
1735 };
1736
1737}
1738
1739template<typename ...Types>
1740struct StringMaker<std::tuple<Types...>> {
1741
1742 static std::string convert( const std::tuple<Types...>& tuple )
1743 {
1744 std::ostringstream os;
1745 os << '{';
1746 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1747 os << " }";
1748 return os.str();
1749 }
1750};
1751#endif // CATCH_CONFIG_CPP11_TUPLE
1752
1753namespace Detail {
1754 template<typename T>
1755 std::string makeString( T const& value ) {
1756 return StringMaker<T>::convert( value );
1757 }
1758} // end namespace Detail
1759
1760/// \brief converts any type to a string
1761///
1762/// The default template forwards on to ostringstream - except when an
1763/// ostringstream overload does not exist - in which case it attempts to detect
1764/// that and writes {?}.
1765/// Overload (not specialise) this template for custom typs that you don't want
1766/// to provide an ostream overload for.
1767template<typename T>
1768std::string toString( T const& value ) {
1769 return StringMaker<T>::convert( value );
1770}
1771
1772 namespace Detail {
1773 template<typename InputIterator>
1774 std::string rangeToString( InputIterator first, InputIterator last ) {
1775 std::ostringstream oss;
1776 oss << "{ ";
1777 if( first != last ) {
1778 oss << Catch::toString( *first );
1779 for( ++first ; first != last ; ++first )
1780 oss << ", " << Catch::toString( *first );
1781 }
1782 oss << " }";
1783 return oss.str();
1784 }
1785}
1786
1787} // end namespace Catch
1788
1789namespace Catch {
1790
1791// Wraps the LHS of an expression and captures the operator and RHS (if any) -
1792// wrapping them all in a ResultBuilder object
1793template<typename T>
1794class ExpressionLhs {
1795 ExpressionLhs& operator = ( ExpressionLhs const& );
1796# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1797 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
1798# endif
1799
1800public:
1801 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
1802# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1803 ExpressionLhs( ExpressionLhs const& ) = default;
1804 ExpressionLhs( ExpressionLhs && ) = default;
1805# endif
1806
1807 template<typename RhsT>
1808 ResultBuilder& operator == ( RhsT const& rhs ) {
1809 return captureExpression<Internal::IsEqualTo>( rhs );
1810 }
1811
1812 template<typename RhsT>
1813 ResultBuilder& operator != ( RhsT const& rhs ) {
1814 return captureExpression<Internal::IsNotEqualTo>( rhs );
1815 }
1816
1817 template<typename RhsT>
1818 ResultBuilder& operator < ( RhsT const& rhs ) {
1819 return captureExpression<Internal::IsLessThan>( rhs );
1820 }
1821
1822 template<typename RhsT>
1823 ResultBuilder& operator > ( RhsT const& rhs ) {
1824 return captureExpression<Internal::IsGreaterThan>( rhs );
1825 }
1826
1827 template<typename RhsT>
1828 ResultBuilder& operator <= ( RhsT const& rhs ) {
1829 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1830 }
1831
1832 template<typename RhsT>
1833 ResultBuilder& operator >= ( RhsT const& rhs ) {
1834 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1835 }
1836
1837 ResultBuilder& operator == ( bool rhs ) {
1838 return captureExpression<Internal::IsEqualTo>( rhs );
1839 }
1840
1841 ResultBuilder& operator != ( bool rhs ) {
1842 return captureExpression<Internal::IsNotEqualTo>( rhs );
1843 }
1844
1845 void endExpression() {
1846 bool value = m_lhs ? true : false;
1847 m_rb
1848 .setLhs( Catch::toString( value ) )
1849 .setResultType( value )
1850 .endExpression();
1851 }
1852
1853 // Only simple binary expressions are allowed on the LHS.
1854 // If more complex compositions are required then place the sub expression in parentheses
1855 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1856 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1857 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1858 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
1859 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1860 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1861
1862private:
1863 template<Internal::Operator Op, typename RhsT>
1864 ResultBuilder& captureExpression( RhsT const& rhs ) {
1865 return m_rb
1866 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1867 .setLhs( Catch::toString( m_lhs ) )
1868 .setRhs( Catch::toString( rhs ) )
1869 .setOp( Internal::OperatorTraits<Op>::getName() );
1870 }
1871
1872private:
1873 ResultBuilder& m_rb;
1874 T m_lhs;
1875};
1876
1877} // end namespace Catch
1878
1879
1880namespace Catch {
1881
1882 template<typename T>
1883 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1884 return ExpressionLhs<T const&>( *this, operand );
1885 }
1886
1887 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1888 return ExpressionLhs<bool>( *this, value );
1889 }
1890
1891} // namespace Catch
1892
1893// #included from: catch_message.h
1894#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1895
1896#include <string>
1897
1898namespace Catch {
1899
1900 struct MessageInfo {
1901 MessageInfo( std::string const& _macroName,
1902 SourceLineInfo const& _lineInfo,
1903 ResultWas::OfType _type );
1904
1905 std::string macroName;
1906 SourceLineInfo lineInfo;
1907 ResultWas::OfType type;
1908 std::string message;
1909 unsigned int sequence;
1910
1911 bool operator == ( MessageInfo const& other ) const {
1912 return sequence == other.sequence;
1913 }
1914 bool operator < ( MessageInfo const& other ) const {
1915 return sequence < other.sequence;
1916 }
1917 private:
1918 static unsigned int globalCount;
1919 };
1920
1921 struct MessageBuilder {
1922 MessageBuilder( std::string const& macroName,
1923 SourceLineInfo const& lineInfo,
1924 ResultWas::OfType type )
1925 : m_info( macroName, lineInfo, type )
1926 {}
1927
1928 template<typename T>
1929 MessageBuilder& operator << ( T const& value ) {
1930 m_stream << value;
1931 return *this;
1932 }
1933
1934 MessageInfo m_info;
1935 std::ostringstream m_stream;
1936 };
1937
1938 class ScopedMessage {
1939 public:
1940 ScopedMessage( MessageBuilder const& builder );
1941 ScopedMessage( ScopedMessage const& other );
1942 ~ScopedMessage();
1943
1944 MessageInfo m_info;
1945 };
1946
1947} // end namespace Catch
1948
1949// #included from: catch_interfaces_capture.h
1950#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1951
1952#include <string>
1953
1954namespace Catch {
1955
1956 class TestCase;
1957 class AssertionResult;
1958 struct AssertionInfo;
1959 struct SectionInfo;
1960 struct SectionEndInfo;
1961 struct MessageInfo;
1962 class ScopedMessageBuilder;
1963 struct Counts;
1964
1965 struct IResultCapture {
1966
1967 virtual ~IResultCapture();
1968
1969 virtual void assertionEnded( AssertionResult const& result ) = 0;
1970 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1971 Counts& assertions ) = 0;
1972 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
1973 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
1974 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1975 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1976
1977 virtual std::string getCurrentTestName() const = 0;
1978 virtual const AssertionResult* getLastResult() const = 0;
1979
1980 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
1981 };
1982
1983 IResultCapture& getResultCapture();
1984}
1985
1986// #included from: catch_debugger.h
1987#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1988
1989// #included from: catch_platform.h
1990#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1991
1992#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1993#define CATCH_PLATFORM_MAC
1994#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1995#define CATCH_PLATFORM_IPHONE
1996#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1997#define CATCH_PLATFORM_WINDOWS
1998#endif
1999
2000#include <string>
2001
2002namespace Catch{
2003
2004 bool isDebuggerActive();
2005 void writeToDebugConsole( std::string const& text );
2006}
2007
2008#ifdef CATCH_PLATFORM_MAC
2009
2010 // The following code snippet based on:
2011 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2012 #ifdef DEBUG
2013 #if defined(__ppc64__) || defined(__ppc__)
2014 #define CATCH_BREAK_INTO_DEBUGGER() \
2015 if( Catch::isDebuggerActive() ) { \
2016 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2017 : : : "memory","r0","r3","r4" ); \
2018 }
2019 #else
2020 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
2021 #endif
2022 #endif
2023
2024#elif defined(_MSC_VER)
2025 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
2026#elif defined(__MINGW32__)
2027 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2028 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
2029#endif
2030
2031#ifndef CATCH_BREAK_INTO_DEBUGGER
2032#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2033#endif
2034
2035// #included from: catch_interfaces_runner.h
2036#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2037
2038namespace Catch {
2039 class TestCase;
2040
2041 struct IRunner {
2042 virtual ~IRunner();
2043 virtual bool aborting() const = 0;
2044 };
2045}
2046
2047///////////////////////////////////////////////////////////////////////////////
2048// In the event of a failure works out if the debugger needs to be invoked
2049// and/or an exception thrown and takes appropriate action.
2050// This needs to be done as a macro so the debugger will stop in the user
2051// source code rather than in Catch library code
2052#define INTERNAL_CATCH_REACT( resultBuilder ) \
2053 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2054 resultBuilder.react();
2055
2056///////////////////////////////////////////////////////////////////////////////
2057#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2058 do { \
2059 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2060 try { \
2061 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2062 ( __catchResult <= expr ).endExpression(); \
2063 } \
2064 catch( ... ) { \
2065 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2066 } \
2067 INTERNAL_CATCH_REACT( __catchResult ) \
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
2069
2070///////////////////////////////////////////////////////////////////////////////
2071#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2072 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2073 if( Catch::getResultCapture().getLastResult()->succeeded() )
2074
2075///////////////////////////////////////////////////////////////////////////////
2076#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2077 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2078 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2079
2080///////////////////////////////////////////////////////////////////////////////
2081#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2082 do { \
2083 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2084 try { \
2085 expr; \
2086 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2087 } \
2088 catch( ... ) { \
2089 __catchResult.useActiveException( resultDisposition ); \
2090 } \
2091 INTERNAL_CATCH_REACT( __catchResult ) \
2092 } while( Catch::alwaysFalse() )
2093
2094///////////////////////////////////////////////////////////////////////////////
2095#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2096 do { \
2097 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2098 if( __catchResult.allowThrows() ) \
2099 try { \
2100 expr; \
2101 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2102 } \
2103 catch( ... ) { \
2104 __catchResult.captureExpectedException( matcher ); \
2105 } \
2106 else \
2107 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2108 INTERNAL_CATCH_REACT( __catchResult ) \
2109 } while( Catch::alwaysFalse() )
2110
2111///////////////////////////////////////////////////////////////////////////////
2112#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2113 do { \
2114 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2115 if( __catchResult.allowThrows() ) \
2116 try { \
2117 expr; \
2118 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2119 } \
2120 catch( exceptionType ) { \
2121 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2122 } \
2123 catch( ... ) { \
2124 __catchResult.useActiveException( resultDisposition ); \
2125 } \
2126 else \
2127 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2128 INTERNAL_CATCH_REACT( __catchResult ) \
2129 } while( Catch::alwaysFalse() )
2130
2131///////////////////////////////////////////////////////////////////////////////
2132#ifdef CATCH_CONFIG_VARIADIC_MACROS
2133 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2134 do { \
2135 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2136 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2137 __catchResult.captureResult( messageType ); \
2138 INTERNAL_CATCH_REACT( __catchResult ) \
2139 } while( Catch::alwaysFalse() )
2140#else
2141 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2142 do { \
2143 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2144 __catchResult << log + ::Catch::StreamEndStop(); \
2145 __catchResult.captureResult( messageType ); \
2146 INTERNAL_CATCH_REACT( __catchResult ) \
2147 } while( Catch::alwaysFalse() )
2148#endif
2149
2150///////////////////////////////////////////////////////////////////////////////
2151#define INTERNAL_CATCH_INFO( log, macroName ) \
2152 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2153
2154///////////////////////////////////////////////////////////////////////////////
2155#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2156 do { \
2157 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2158 try { \
2159 std::string matcherAsString = (matcher).toString(); \
2160 __catchResult \
2161 .setLhs( Catch::toString( arg ) ) \
2162 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2163 .setOp( "matches" ) \
2164 .setResultType( (matcher).match( arg ) ); \
2165 __catchResult.captureExpression(); \
2166 } catch( ... ) { \
2167 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2168 } \
2169 INTERNAL_CATCH_REACT( __catchResult ) \
2170 } while( Catch::alwaysFalse() )
2171
2172// #included from: internal/catch_section.h
2173#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2174
2175// #included from: catch_section_info.h
2176#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2177
2178// #included from: catch_totals.hpp
2179#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2180
2181#include <cstddef>
2182
2183namespace Catch {
2184
2185 struct Counts {
2186 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2187
2188 Counts operator - ( Counts const& other ) const {
2189 Counts diff;
2190 diff.passed = passed - other.passed;
2191 diff.failed = failed - other.failed;
2192 diff.failedButOk = failedButOk - other.failedButOk;
2193 return diff;
2194 }
2195 Counts& operator += ( Counts const& other ) {
2196 passed += other.passed;
2197 failed += other.failed;
2198 failedButOk += other.failedButOk;
2199 return *this;
2200 }
2201
2202 std::size_t total() const {
2203 return passed + failed + failedButOk;
2204 }
2205 bool allPassed() const {
2206 return failed == 0 && failedButOk == 0;
2207 }
2208 bool allOk() const {
2209 return failed == 0;
2210 }
2211
2212 std::size_t passed;
2213 std::size_t failed;
2214 std::size_t failedButOk;
2215 };
2216
2217 struct Totals {
2218
2219 Totals operator - ( Totals const& other ) const {
2220 Totals diff;
2221 diff.assertions = assertions - other.assertions;
2222 diff.testCases = testCases - other.testCases;
2223 return diff;
2224 }
2225
2226 Totals delta( Totals const& prevTotals ) const {
2227 Totals diff = *this - prevTotals;
2228 if( diff.assertions.failed > 0 )
2229 ++diff.testCases.failed;
2230 else if( diff.assertions.failedButOk > 0 )
2231 ++diff.testCases.failedButOk;
2232 else
2233 ++diff.testCases.passed;
2234 return diff;
2235 }
2236
2237 Totals& operator += ( Totals const& other ) {
2238 assertions += other.assertions;
2239 testCases += other.testCases;
2240 return *this;
2241 }
2242
2243 Counts assertions;
2244 Counts testCases;
2245 };
2246}
2247
2248namespace Catch {
2249
2250 struct SectionInfo {
2251 SectionInfo
2252 ( SourceLineInfo const& _lineInfo,
2253 std::string const& _name,
2254 std::string const& _description = std::string() );
2255
2256 std::string name;
2257 std::string description;
2258 SourceLineInfo lineInfo;
2259 };
2260
2261 struct SectionEndInfo {
2262 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2263 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2264 {}
2265
2266 SectionInfo sectionInfo;
2267 Counts prevAssertions;
2268 double durationInSeconds;
2269 };
2270
2271} // end namespace Catch
2272
2273// #included from: catch_timer.h
2274#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2275
2276#ifdef CATCH_PLATFORM_WINDOWS
2277typedef unsigned long long uint64_t;
2278#else
2279#include <stdint.h>
2280#endif
2281
2282namespace Catch {
2283
2284 class Timer {
2285 public:
2286 Timer() : m_ticks( 0 ) {}
2287 void start();
2288 unsigned int getElapsedMicroseconds() const;
2289 unsigned int getElapsedMilliseconds() const;
2290 double getElapsedSeconds() const;
2291
2292 private:
2293 uint64_t m_ticks;
2294 };
2295
2296} // namespace Catch
2297
2298#include <string>
2299
2300namespace Catch {
2301
2302 class Section : NonCopyable {
2303 public:
2304 Section( SectionInfo const& info );
2305 ~Section();
2306
2307 // This indicates whether the section should be executed or not
2308 operator bool() const;
2309
2310 private:
2311 SectionInfo m_info;
2312
2313 std::string m_name;
2314 Counts m_assertions;
2315 bool m_sectionIncluded;
2316 Timer m_timer;
2317 };
2318
2319} // end namespace Catch
2320
2321#ifdef CATCH_CONFIG_VARIADIC_MACROS
2322 #define INTERNAL_CATCH_SECTION( ... ) \
2323 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2324#else
2325 #define INTERNAL_CATCH_SECTION( name, desc ) \
2326 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2327#endif
2328
2329// #included from: internal/catch_generators.hpp
2330#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2331
2332#include <iterator>
2333#include <vector>
2334#include <string>
2335#include <stdlib.h>
2336
2337namespace Catch {
2338
2339template<typename T>
2340struct IGenerator {
2341 virtual ~IGenerator() {}
2342 virtual T getValue( std::size_t index ) const = 0;
2343 virtual std::size_t size () const = 0;
2344};
2345
2346template<typename T>
2347class BetweenGenerator : public IGenerator<T> {
2348public:
2349 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2350
2351 virtual T getValue( std::size_t index ) const {
2352 return m_from+static_cast<int>( index );
2353 }
2354
2355 virtual std::size_t size() const {
2356 return static_cast<std::size_t>( 1+m_to-m_from );
2357 }
2358
2359private:
2360
2361 T m_from;
2362 T m_to;
2363};
2364
2365template<typename T>
2366class ValuesGenerator : public IGenerator<T> {
2367public:
2368 ValuesGenerator(){}
2369
2370 void add( T value ) {
2371 m_values.push_back( value );
2372 }
2373
2374 virtual T getValue( std::size_t index ) const {
2375 return m_values[index];
2376 }
2377
2378 virtual std::size_t size() const {
2379 return m_values.size();
2380 }
2381
2382private:
2383 std::vector<T> m_values;
2384};
2385
2386template<typename T>
2387class CompositeGenerator {
2388public:
2389 CompositeGenerator() : m_totalSize( 0 ) {}
2390
2391 // *** Move semantics, similar to auto_ptr ***
2392 CompositeGenerator( CompositeGenerator& other )
2393 : m_fileInfo( other.m_fileInfo ),
2394 m_totalSize( 0 )
2395 {
2396 move( other );
2397 }
2398
2399 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2400 m_fileInfo = fileInfo;
2401 return *this;
2402 }
2403
2404 ~CompositeGenerator() {
2405 deleteAll( m_composed );
2406 }
2407
2408 operator T () const {
2409 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2410
2411 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2412 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2413 for( size_t index = 0; it != itEnd; ++it )
2414 {
2415 const IGenerator<T>* generator = *it;
2416 if( overallIndex >= index && overallIndex < index + generator->size() )
2417 {
2418 return generator->getValue( overallIndex-index );
2419 }
2420 index += generator->size();
2421 }
2422 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
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
2424 }
2425
2426 void add( const IGenerator<T>* generator ) {
2427 m_totalSize += generator->size();
2428 m_composed.push_back( generator );
2429 }
2430
2431 CompositeGenerator& then( CompositeGenerator& other ) {
2432 move( other );
2433 return *this;
2434 }
2435
2436 CompositeGenerator& then( T value ) {
2437 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2438 valuesGen->add( value );
2439 add( valuesGen );
2440 return *this;
2441 }
2442
2443private:
2444
2445 void move( CompositeGenerator& other ) {
2446 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2447 m_totalSize += other.m_totalSize;
2448 other.m_composed.clear();
2449 }
2450
2451 std::vector<const IGenerator<T>*> m_composed;
2452 std::string m_fileInfo;
2453 size_t m_totalSize;
2454};
2455
2456namespace Generators
2457{
2458 template<typename T>
2459 CompositeGenerator<T> between( T from, T to ) {
2460 CompositeGenerator<T> generators;
2461 generators.add( new BetweenGenerator<T>( from, to ) );
2462 return generators;
2463 }
2464
2465 template<typename T>
2466 CompositeGenerator<T> values( T val1, T val2 ) {
2467 CompositeGenerator<T> generators;
2468 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2469 valuesGen->add( val1 );
2470 valuesGen->add( val2 );
2471 generators.add( valuesGen );
2472 return generators;
2473 }
2474
2475 template<typename T>
2476 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2477 CompositeGenerator<T> generators;
2478 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2479 valuesGen->add( val1 );
2480 valuesGen->add( val2 );
2481 valuesGen->add( val3 );
2482 generators.add( valuesGen );
2483 return generators;
2484 }
2485
2486 template<typename T>
2487 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2488 CompositeGenerator<T> generators;
2489 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2490 valuesGen->add( val1 );
2491 valuesGen->add( val2 );
2492 valuesGen->add( val3 );
2493 valuesGen->add( val4 );
2494 generators.add( valuesGen );
2495 return generators;
2496 }
2497
2498} // end namespace Generators
2499
2500using namespace Generators;
2501
2502} // end namespace Catch
2503
2504#define INTERNAL_CATCH_LINESTR2( line ) #line
2505#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2506
2507#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2508
2509// #included from: internal/catch_interfaces_exception.h
2510#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2511
2512#include <string>
2513#include <vector>
2514
2515// #included from: catch_interfaces_registry_hub.h
2516#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2517
2518#include <string>
2519
2520namespace Catch {
2521
2522 class TestCase;
2523 struct ITestCaseRegistry;
2524 struct IExceptionTranslatorRegistry;
2525 struct IExceptionTranslator;
2526 struct IReporterRegistry;
2527 struct IReporterFactory;
2528
2529 struct IRegistryHub {
2530 virtual ~IRegistryHub();
2531
2532 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2533 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2534 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2535 };
2536
2537 struct IMutableRegistryHub {
2538 virtual ~IMutableRegistryHub();
2539 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2540 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2541 virtual void registerTest( TestCase const& testInfo ) = 0;
2542 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2543 };
2544
2545 IRegistryHub& getRegistryHub();
2546 IMutableRegistryHub& getMutableRegistryHub();
2547 void cleanUp();
2548 std::string translateActiveException();
2549
2550}
2551
2552namespace Catch {
2553
2554 typedef std::string(*exceptionTranslateFunction)();
2555
2556 struct IExceptionTranslator;
2557 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2558
2559 struct IExceptionTranslator {
2560 virtual ~IExceptionTranslator();
2561 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2562 };
2563
2564 struct IExceptionTranslatorRegistry {
2565 virtual ~IExceptionTranslatorRegistry();
2566
2567 virtual std::string translateActiveException() const = 0;
2568 };
2569
2570 class ExceptionTranslatorRegistrar {
2571 template<typename T>
2572 class ExceptionTranslator : public IExceptionTranslator {
2573 public:
2574
2575 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2576 : m_translateFunction( translateFunction )
2577 {}
2578
2579 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
2580 try {
2581 if( it == itEnd )
2582 throw;
2583 else
2584 return (*it)->translate( it+1, itEnd );
2585 }
2586 catch( T& ex ) {
2587 return m_translateFunction( ex );
2588 }
2589 }
2590
2591 protected:
2592 std::string(*m_translateFunction)( T& );
2593 };
2594
2595 public:
2596 template<typename T>
2597 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2598 getMutableRegistryHub().registerTranslator
2599 ( new ExceptionTranslator<T>( translateFunction ) );
2600 }
2601 };
2602}
2603
2604///////////////////////////////////////////////////////////////////////////////
2605#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2606 static std::string translatorName( signature ); \
2607 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2608 static std::string translatorName( signature )
2609
2610#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2611
2612// #included from: internal/catch_approx.hpp
2613#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2614
2615#include <cmath>
2616#include <limits>
2617
2618namespace Catch {
2619namespace Detail {
2620
2621 class Approx {
2622 public:
2623 explicit Approx ( double value )
2624 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2625 m_scale( 1.0 ),
2626 m_value( value )
2627 {}
2628
2629 Approx( Approx const& other )
2630 : m_epsilon( other.m_epsilon ),
2631 m_scale( other.m_scale ),
2632 m_value( other.m_value )
2633 {}
2634
2635 static Approx custom() {
2636 return Approx( 0 );
2637 }
2638
2639 Approx operator()( double value ) {
2640 Approx approx( value );
2641 approx.epsilon( m_epsilon );
2642 approx.scale( m_scale );
2643 return approx;
2644 }
2645
2646 friend bool operator == ( double lhs, Approx const& rhs ) {
2647 // Thanks to Richard Harris for his help refining this formula
2648 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2649 }
2650
2651 friend bool operator == ( Approx const& lhs, double rhs ) {
2652 return operator==( rhs, lhs );
2653 }
2654
2655 friend bool operator != ( double lhs, Approx const& rhs ) {
2656 return !operator==( lhs, rhs );
2657 }
2658
2659 friend bool operator != ( Approx const& lhs, double rhs ) {
2660 return !operator==( rhs, lhs );
2661 }
2662
2663 Approx& epsilon( double newEpsilon ) {
2664 m_epsilon = newEpsilon;
2665 return *this;
2666 }
2667
2668 Approx& scale( double newScale ) {
2669 m_scale = newScale;
2670 return *this;
2671 }
2672
2673 std::string toString() const {
2674 std::ostringstream oss;
2675 oss << "Approx( " << Catch::toString( m_value ) << " )";
2676 return oss.str();
2677 }
2678
2679 private:
2680 double m_epsilon;
2681 double m_scale;
2682 double m_value;
2683 };
2684}
2685
2686template<>
2687inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2688 return value.toString();
2689}
2690
2691} // end namespace Catch
2692
2693// #included from: internal/catch_interfaces_tag_alias_registry.h
2694#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2695
2696// #included from: catch_tag_alias.h
2697#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2698
2699#include <string>
2700
2701namespace Catch {
2702
2703 struct TagAlias {
2704 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
2705
2706 std::string tag;
2707 SourceLineInfo lineInfo;
2708 };
2709
2710 struct RegistrarForTagAliases {
2711 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
2712 };
2713
2714} // end namespace Catch
2715
2716#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2717// #included from: catch_option.hpp
2718#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2719
2720namespace Catch {
2721
2722 // An optional type
2723 template<typename T>
2724 class Option {
2725 public:
2726 Option() : nullableValue( CATCH_NULL ) {}
2727 Option( T const& _value )
2728 : nullableValue( new( storage ) T( _value ) )
2729 {}
2730 Option( Option const& _other )
2731 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
2732 {}
2733
2734 ~Option() {
2735 reset();
2736 }
2737
2738 Option& operator= ( Option const& _other ) {
2739 if( &_other != this ) {
2740 reset();
2741 if( _other )
2742 nullableValue = new( storage ) T( *_other );
2743 }
2744 return *this;
2745 }
2746 Option& operator = ( T const& _value ) {
2747 reset();
2748 nullableValue = new( storage ) T( _value );
2749 return *this;
2750 }
2751
2752 void reset() {
2753 if( nullableValue )
2754 nullableValue->~T();
2755 nullableValue = CATCH_NULL;
2756 }
2757
2758 T& operator*() { return *nullableValue; }
2759 T const& operator*() const { return *nullableValue; }
2760 T* operator->() { return nullableValue; }
2761 const T* operator->() const { return nullableValue; }
2762
2763 T valueOr( T const& defaultValue ) const {
2764 return nullableValue ? *nullableValue : defaultValue;
2765 }
2766
2767 bool some() const { return nullableValue != CATCH_NULL; }
2768 bool none() const { return nullableValue == CATCH_NULL; }
2769
2770 bool operator !() const { return nullableValue == CATCH_NULL; }
2771 operator SafeBool::type() const {
2772 return SafeBool::makeSafe( some() );
2773 }
2774
2775 private:
2776 T* nullableValue;
2777 char storage[sizeof(T)];
2778 };
2779
2780} // end namespace Catch
2781
2782namespace Catch {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches