Skip to content

Commit 824fff4

Browse files
committed
working recursive subtypesIterator and supertypesIterator for EntityDescriptor
includes C++ test
1 parent ad2675f commit 824fff4

File tree

4 files changed

+308
-1
lines changed

4 files changed

+308
-1
lines changed

src/clstepcore/SubSuperIterators.h

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#ifndef SUB_SUPER_ITERATORS
2+
#define SUB_SUPER_ITERATORS
3+
4+
#include "ExpDict.h"
5+
#include "ExpDict.h"
6+
#include <queue>
7+
#include <assert.h>
8+
9+
/** abstract base class for recursive breadth-first input iterators of EntityDescriptor/EntityDescLinkNode
10+
* NOTE: due to pure virtual functions being necessary for initialization, derived class constructor must call reset(t)
11+
*/
12+
class recursiveEntDescripIterator {
13+
protected:
14+
const EntityDescriptor * startEntity;
15+
typedef struct {
16+
const EntityDescriptor * ed;
17+
unsigned int depth; ///< for debugging; records how many lists had to be traversed to find the current node
18+
} queue_pair;
19+
20+
std::deque< queue_pair > q;
21+
unsigned int position; ///< primarily used in comparisons between iterators
22+
23+
///add contents of a linked list to q
24+
void addLinkedList( const queue_pair qp ) {
25+
EntityDescLinkNode *a = listHead( qp.ed );
26+
queue_pair tmp;
27+
tmp.depth = qp.depth + 1;
28+
while( a != 0 ) {
29+
tmp.ed = nodeContent( a );
30+
q.push_back( tmp );
31+
a = ( EntityDescLinkNode * ) a->NextNode( );
32+
}
33+
}
34+
virtual EntityDescLinkNode * listHead( const EntityDescriptor * t ) const = 0; ///< returns the head of something inheriting SingleLinkList
35+
virtual EntityDescriptor * nodeContent( const EntityDescLinkNode * n ) const = 0; ///< returns the content of a SingleLinkNode
36+
37+
38+
public:
39+
recursiveEntDescripIterator( const EntityDescriptor * t = 0 ): startEntity( t ), position( 0 ) {
40+
//NOTE due to pure virtual functions, derived class constructor *must* call reset(t)
41+
}
42+
recursiveEntDescripIterator( ): startEntity( 0 ), position( 0 ) {
43+
}
44+
~recursiveEntDescripIterator( ) {
45+
}
46+
47+
void reset( const EntityDescriptor * t = 0 ) {
48+
position = 0;
49+
q.clear( );
50+
if( t ) {
51+
startEntity = t;
52+
}
53+
if( startEntity ) {
54+
queue_pair p;
55+
p.depth = 0;
56+
p.ed = startEntity;
57+
addLinkedList( p );
58+
}
59+
}
60+
61+
const EntityDescriptor * next( ) {
62+
if( q.empty( ) ) {
63+
return ( EntityDescriptor * ) 0;
64+
} else {
65+
position++;
66+
queue_pair qp = q.front( );
67+
q.pop_front( );
68+
addLinkedList( qp );
69+
return qp.ed;
70+
}
71+
}
72+
73+
const EntityDescriptor * current( ) const {
74+
if( q.empty( ) ) {
75+
return ( EntityDescriptor * ) 0;
76+
}
77+
return( q.front( ).ed );
78+
}
79+
80+
bool hasNext( ) const {
81+
return( ( (q.size( ) > 1 ) && ( q[1].ed != 0 ) ) //there is another EntityDescriptor in q
82+
|| ( nodeContent( listHead( q[0].ed ) ) != 0 ) ); //or, the only one in the queue has a non-empty list
83+
}
84+
85+
bool empty( ) const {
86+
return q.empty( );
87+
}
88+
89+
unsigned int pos( ) const {
90+
return position;
91+
}
92+
93+
unsigned int depth( ) const {
94+
return q[0].depth;
95+
}
96+
97+
const EntityDescriptor * operator *( ) const {
98+
return current( );
99+
}
100+
101+
const EntityDescriptor * operator ->( ) const {
102+
return current( );
103+
}
104+
105+
/// two iterators are not considered equal unless the startEntity pointers match and the positions match
106+
bool operator ==( const recursiveEntDescripIterator & b ) const {
107+
return( ( startEntity == b.startEntity ) && ( position == b.position ) );
108+
}
109+
110+
bool operator !=( const recursiveEntDescripIterator & b ) const {
111+
return( ( startEntity != b.startEntity ) || ( position != b.position ) );
112+
}
113+
114+
/// for inequality operators, return a Logical; LUnknown means that the startEntity pointers do not match
115+
Logical operator >( const recursiveEntDescripIterator & b ) const {
116+
if( startEntity != b.startEntity ) {
117+
return LUnknown;
118+
}
119+
if( position > b.position ) {
120+
return LTrue;
121+
} else {
122+
return LFalse;
123+
}
124+
}
125+
126+
Logical operator <( const recursiveEntDescripIterator & b ) const {
127+
if( startEntity != b.startEntity ) {
128+
return LUnknown;
129+
}
130+
if( position < b.position ) {
131+
return LTrue;
132+
} else {
133+
return LFalse;
134+
}
135+
}
136+
137+
Logical operator >=( const recursiveEntDescripIterator & b ) const {
138+
if( startEntity != b.startEntity ) {
139+
return LUnknown;
140+
}
141+
if( position >= b.position ) {
142+
return LTrue;
143+
} else {
144+
return LFalse;
145+
}
146+
}
147+
148+
Logical operator <=( const recursiveEntDescripIterator & b ) const {
149+
if( startEntity != b.startEntity ) {
150+
return LUnknown;
151+
}
152+
if( position <= b.position ) {
153+
return LTrue;
154+
} else {
155+
return LFalse;
156+
}
157+
}
158+
159+
const EntityDescriptor * operator ++( ) {
160+
return next( );
161+
}
162+
163+
const EntityDescriptor * operator ++( int ) {
164+
const EntityDescriptor * c = current( );
165+
next( );
166+
return c;
167+
}
168+
};
169+
170+
/** Recursive breadth-first input iterator for supertypes
171+
* \sa subtypesIterator
172+
*/
173+
class supertypesIterator : public recursiveEntDescripIterator {
174+
protected:
175+
EntityDescLinkNode * listHead( const EntityDescriptor * t ) const { ///< returns the head of an EntityDescriptorList
176+
if( !t ) {
177+
return 0;
178+
}
179+
return ( EntityDescLinkNode * ) t->Supertypes().GetHead();
180+
}
181+
EntityDescriptor * nodeContent( const EntityDescLinkNode * n ) const { ///< returns the content of a EntityDescLinkNode
182+
if( !n ) {
183+
return 0;
184+
}
185+
return n->EntityDesc();
186+
}
187+
public:
188+
supertypesIterator( const EntityDescriptor* t = 0 ):recursiveEntDescripIterator(t) {
189+
reset( t );
190+
}
191+
};
192+
193+
/** Recursive breadth-first input iterator for subtypes
194+
* \sa supertypesIterator
195+
*/
196+
class subtypesIterator: public recursiveEntDescripIterator{
197+
protected:
198+
EntityDescLinkNode * listHead( const EntityDescriptor * t ) const { ///< returns the head of an EntityDescriptorList
199+
if( !t ) {
200+
return 0;
201+
}
202+
return ( EntityDescLinkNode * ) t->Subtypes().GetHead();
203+
}
204+
EntityDescriptor * nodeContent( const EntityDescLinkNode * n ) const { ///< returns the content of a EntityDescLinkNode
205+
if( !n ) {
206+
return 0;
207+
}
208+
return n->EntityDesc();
209+
}
210+
public:
211+
subtypesIterator( const EntityDescriptor* t = 0 ):recursiveEntDescripIterator(t) {
212+
reset( t );
213+
}
214+
};
215+
216+
#endif //SUB_SUPER_ITERATORS

test/cpp/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
33
#c++ tests
44

55
add_subdirectory(schema_specific)
6-
# add_subdirectory(stepcore)
6+
add_subdirectory(stepcore)

test/cpp/stepcore/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
2+
#c++ tests for clstepcore
3+
4+
INCLUDE_DIRECTORIES( ${SCL_SOURCE_DIR}/src/cldai ${SCL_SOURCE_DIR}/src/cleditor ${SCL_SOURCE_DIR}/src/clutils
5+
${SCL_SOURCE_DIR}/src/clstepcore ${SCL_SOURCE_DIR}/src/base )
6+
7+
function(add_stepcore_test name libs)
8+
SCL_ADDEXEC( tst_${name} test_${name}.cc "${libs}" )
9+
add_test( NAME build_cpp_${name}
10+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
11+
COMMAND ${CMAKE_COMMAND} --build .
12+
--target tst_${name}
13+
--config $<CONFIGURATION> )
14+
add_test( NAME test_${name}
15+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
16+
COMMAND $<TARGET_FILE:tst_${name}> )
17+
set_tests_properties( build_cpp_${name} PROPERTIES LABELS cpp_stepcore DEPENDS stepcore )
18+
set_tests_properties( test_${name} PROPERTIES LABELS cpp_stepcore DEPENDS build_cpp_${name} )
19+
endfunction(add_stepcore_test name libs)
20+
21+
add_stepcore_test( "SupertypesIterator" "stepcore steputils stepeditor stepdai base" )
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//test SubtypesIterator, SupertypesIterator
2+
3+
//what about an iterator for inverse attrs?
4+
5+
//subtypesiterator shouldn't need tested separately from supertypesiterator since there is very little difference
6+
7+
#include "SubSuperIterators.h"
8+
#include "ExpDict.h"
9+
10+
int main(int /*argc*/, char** /*argv*/) {
11+
Schema * a = 0;
12+
Logical b(LFalse);
13+
char buf[20][2] = { { '\0' } };
14+
int i;
15+
EntityDescriptor * descriptors[20], ed( "ed", a, b, b );
16+
17+
//create 20 more ed's
18+
for( i = 0; i < 20; i++ ) {
19+
buf[i][0] = 'a' + i; //ed names are 1st 20 lowercase chars
20+
descriptors[i] = new EntityDescriptor(buf[i], a, b, b );
21+
}
22+
//link the ed's together
23+
ed.AddSupertype(descriptors[0]);
24+
for( i = 0; i < 10; i++ ) {
25+
descriptors[i]->AddSupertype(descriptors[i+1]);
26+
}
27+
for( i = 10; i < 20; i++ ) {
28+
descriptors[5]->AddSupertype(descriptors[i]);
29+
}
30+
31+
//print the ed's
32+
cout << "first, name " << ed.Name() << endl;
33+
supertypesIterator iter(&ed);
34+
for( ; !iter.empty(); iter++ ) {
35+
cout << "position " << iter.pos() << ", name " << iter->Name() << endl;
36+
}
37+
if( iter.pos() == 21 ) { //1 beyond the end
38+
cout << "success" << endl;
39+
exit( EXIT_SUCCESS );
40+
} else {
41+
cout << "expected 21, got " << iter.pos() << endl;
42+
exit( EXIT_FAILURE );
43+
}
44+
}
45+
/* output:
46+
*
47+
* first, name ed
48+
* position 0, name a
49+
* position 1, name b
50+
* position 2, name c
51+
* position 3, name d
52+
* position 4, name e
53+
* position 5, name f
54+
* position 6, name g
55+
* position 7, name k
56+
* position 8, name l
57+
* position 9, name m
58+
* position 10, name n
59+
* position 11, name o
60+
* position 12, name p
61+
* position 13, name q
62+
* position 14, name r
63+
* position 15, name s
64+
* position 16, name t
65+
* position 17, name h
66+
* position 18, name i
67+
* position 19, name j
68+
* position 20, name k
69+
* success
70+
*/

0 commit comments

Comments
 (0)