-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathentnode.cc
More file actions
191 lines (170 loc) · 6.24 KB
/
entnode.cc
File metadata and controls
191 lines (170 loc) · 6.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*************************************************************************//**
* entnode.cc \class EntNode *
* *
* Description: The EntNode class is used to store a collection of entity *
* names. It stores them in alphabetical order. It is the key *
* component of the EntList classes, which are used to store *
* information on the instantiable complex entity types. This *
* file contains EntNode member function definitions. *
* *
* Created by: David Rosenfeld *
* Date: 9/18/96 *
*****************************************************************************/
#include "clstepcore/complexSupport.h"
/**
* Given a list of entity names, creates a sorted linked list of EntNodes
* corresponding to the list. A name which = "*" is a dummy trailer
* implying the list has been completed. This function first builds the
* list, then sets this to the first element, and then deletes the first
* element. This ensures that `this' points to the start of the list.
*/
EntNode::EntNode( const char ** names ) {
int j = 1, comp;
EntNode * prev, *prev2 = NULL, // prev2 - the one before prev
*newnode, *firstnode;
const char * nm;
// Create a first EntNode:
firstnode = prev = new EntNode( names[0] );
while( names[j] && *names[j] != '*' ) {
nm = names[j];
while( prev != NULL && ( comp = StrCmpIns( prev->name, nm ) ) < 0 ) {
prev2 = prev;
prev = prev->next;
}
// One exceptional case: If new name is same as prev, skip it:
if( comp != 0 ) {
// At this point, we know the new node belongs between prev2 and
// prev. prev or prev2 may = NULL if newnode belongs at the end of
// the list or before the beginning, respectively.
newnode = new EntNode( nm );
newnode->next = prev;
if( prev2 == NULL ) {
// This will be the case if the inner while was never entered.
// That happens when newnode belonged at the beginning of the
// list. If so, reset firstnode.
firstnode = newnode;
} else {
prev2->next = newnode;
}
}
// Reset for next name:
prev = firstnode;
prev2 = NULL;
j++;
}
// Finally, place the contents of firstnode in 'this', and delete first-
// node. This ensures that 'this' is first.
*this = *firstnode;
firstnode->next = NULL;
// (Otherwise, deleting firstnode would delete entire list.)
delete firstnode;
}
/**
* Copies all of ent's values here.
*/
EntNode & EntNode::operator= ( EntNode & ent ) {
Name( ent.name );
setmark( ent.mark );
multSuprs( ent.multSupers );
next = ent.next;
return *this;
}
/**
* Marks/unmarks all the nodes in this's list (default is to mark).
*/
void EntNode::markAll( MarkType stamp ) {
EntNode * node = this;
while( node != NULL ) {
node->mark = stamp;
node = node->next;
}
}
/**
* Returns true if this and all nodes following it are marked.
*/
bool EntNode::allMarked() {
EntNode * node = this;
while( node != NULL ) {
if( node->mark == NOMARK ) {
return false;
}
node = node->next;
}
return true;
}
/**
* Returns the number of unmarked nodes in this's list.
*/
int EntNode::unmarkedCount() {
int count = 0;
EntNode * node = this;
while( node != NULL ) {
if( node->mark == NOMARK ) {
count++;
}
node = node->next;
}
return count;
}
/**
* Starting from `this', search for the last node (along our next's) which
* alphabetically precedes ent.
*/
EntNode * EntNode::lastSmaller( EntNode * ent ) {
EntNode * eptr = next, *prev = this;
if( *this > *ent ) {
return NULL;
}
while( eptr && *eptr > *prev && *eptr < *ent ) {
prev = eptr;
eptr = eptr->next;
}
return prev;
}
/**
* Check if our nodes are in order. If not, re-sort. The earlier part of
* the list has been sorted but not necessarily the remainder. This algo-
* rithm sorts our nodes in chunks, and is fairly efficient when we know
* our nodes are basically in order. (sort() is called from STEPcomplex::
* Initialize() when we are creating a complex entity and have renamed a
* few of the nodes. The nodes at first were in order; only the renamed
* ones may be out of place.)
*/
void EntNode::sort( EntNode ** first ) {
EntNode * eptr1, *eptr2, *temp1, *temp2;
while( next && *this > *next ) {
// Find the earliest node greater than next. (I.e., is not only this >
// next but also some of this's preceding nodes. Since the nodes
// earlier in the list are sorted already, we can easily determine the
// ordered chunk of nodes which next should precede.) (eptr1 is
// actually set to the one before, so that we'll know that eptr1->next
// should now be set to next.)
eptr1 = ( *first )->lastSmaller( next );
// Take the latest node eptr1 is greater than. (I.e., beyond next are
// there more nodes which should be immediately after eptr1.) (The
// succeeding nodes are not necessarily in order, so lastSmaller() also
// checks that nodes later than next are also > their prev's.)
if( eptr1 ) {
eptr2 = next->lastSmaller( eptr1->next );
} else {
eptr2 = next->lastSmaller( *first );
}
// Switch the two lists:
if( eptr1 ) {
temp1 = eptr1->next;
eptr1->next = next;
temp2 = eptr2->next;
eptr2->next = temp1;
next = temp2;
} else {
// `this' should be first in the list.
temp2 = eptr2->next;
eptr2->next = *first;
*first = next;
next = temp2;
}
}
if( next ) {
next->sort( first );
}
}