-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathRegistry.cc
More file actions
295 lines (251 loc) · 9.93 KB
/
Registry.cc
File metadata and controls
295 lines (251 loc) · 9.93 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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
* NIST STEP Core Class Library
* clstepcore/Registry.cc
* April 1997
* K. C. Morris
* David Sauder
* Development of this software was funded by the United States Government,
* and is not subject to copyright.
*/
#include "clstepcore/ExpDict.h"
#include "clstepcore/Registry.h"
/* these may be shared between multiple Registry instances, so don't create/destroy in Registry ctor/dtor
* Name, FundamentalType, Originating Schema, Description */
const TypeDescriptor * const t_sdaiINTEGER = new TypeDescriptor( "INTEGER", sdaiINTEGER, 0, "INTEGER" );
const TypeDescriptor * const t_sdaiREAL = new TypeDescriptor( "REAL", sdaiREAL, 0, "Real" );
const TypeDescriptor * const t_sdaiNUMBER = new TypeDescriptor( "NUMBER", sdaiNUMBER, 0, "Number" );
const TypeDescriptor * const t_sdaiSTRING = new TypeDescriptor( "STRING", sdaiSTRING, 0, "String" );
const TypeDescriptor * const t_sdaiBINARY = new TypeDescriptor( "BINARY", sdaiBINARY, 0, "Binary" );
const TypeDescriptor * const t_sdaiBOOLEAN = new TypeDescriptor( "BOOLEAN", sdaiBOOLEAN, 0, "Boolean" );
const TypeDescriptor * const t_sdaiLOGICAL = new TypeDescriptor( "LOGICAL", sdaiLOGICAL, 0, "Logical" );
static int uniqueNames( const char *, const SchRename * );
Registry::Registry( CF_init initFunct )
: col( 0 ), entity_cnt( 0 ), all_ents_cnt( 0 ) {
primordialSwamp = SC_HASHcreate( 1000 );
active_schemas = SC_HASHcreate( 10 );
active_types = SC_HASHcreate( 100 );
initFunct( *this );
SC_HASHlistinit( active_types, &cur_type );
SC_HASHlistinit( primordialSwamp, &cur_entity ); // initialize cur's
SC_HASHlistinit( active_schemas, &cur_schema );
}
Registry::~Registry() {
DeleteContents();
SC_HASHdestroy( primordialSwamp );
SC_HASHdestroy( active_schemas );
SC_HASHdestroy( active_types );
delete col;
}
void Registry::DeleteContents() {
// entities first
SC_HASHlistinit( primordialSwamp, &cur_entity );
while( SC_HASHlist( &cur_entity ) ) {
delete( EntityDescriptor * ) cur_entity.e->data;
}
// schemas
SC_HASHlistinit( active_schemas, &cur_schema );
while( SC_HASHlist( &cur_schema ) ) {
delete( Schema * ) cur_schema.e->data;
}
// types
SC_HASHlistinit( active_types, &cur_type );
while( SC_HASHlist( &cur_type ) ) {
delete( TypeDescriptor * ) cur_type.e->data;
}
}
/**
* schNm refers to the current schema. This will have a value if we are
* reading from a Part 21 file (using a STEPfile object), and the file
* declares a schema name in the File_Schema section of the Header. (If
* >1 schema names are declared, the first is taken.) The schema name is
* significant because of the USE and REFERENCE clause. Say schema X USEs
* entity A from schema Y and renames it to B, X should only refer to A as
* B. Thus, if schNm here = "X", only e="B" would be valid but not e="A".
*/
const EntityDescriptor * Registry::FindEntity( const char * e, const char * schNm, int check_case ) const {
const EntityDescriptor * entd;
const SchRename * altlist;
char schformat[BUFSIZ+1], altName[BUFSIZ+1];
if( check_case ) {
entd = ( EntityDescriptor * )SC_HASHfind( primordialSwamp, ( char * )e );
} else {
entd = ( EntityDescriptor * )SC_HASHfind( primordialSwamp,
( char * )PrettyTmpName( e ) );
}
if( entd && schNm ) {
// We've now found an entity. If schNm has a value, we must ensure we
// have a valid name.
strcpy( schformat, PrettyTmpName( schNm ) );
if( ( ( altlist = entd->AltNameList() ) != 0 )
&& ( altlist->rename( schformat, altName ) ) ) {
// If entd has other name choices, and entd is referred to with a
// new name by schema schNm, then e had better = the new name.
if( !StrCmpIns( e, altName ) ) {
return entd;
}
return NULL;
} else if( FindSchema( schformat, 1 ) ) {
// If schema schNm exists but we had no conditions above to use an
// altName, we must use the original name:
if( !StrCmpIns( e, entd->Name() ) ) {
return entd;
}
return NULL;
} else {
// Last choice: schNm does not exist at all. The user must have
// typed something wrong. Don't penalize him for it (so even if
// we have an altName of entd, accept it):
return entd;
}
}
return entd;
}
const Schema * Registry::FindSchema( const char * n, int check_case ) const {
if( check_case ) {
return ( const Schema * ) SC_HASHfind( active_schemas, ( char * ) n );
}
return ( const Schema * ) SC_HASHfind( active_schemas,
( char * )PrettyTmpName( n ) );
}
const TypeDescriptor * Registry::FindType( const char * n, int check_case ) const {
if( check_case ) {
return ( const TypeDescriptor * ) SC_HASHfind( active_types, ( char * ) n );
}
return ( const TypeDescriptor * ) SC_HASHfind( active_types,
( char * )PrettyTmpName( n ) );
}
void Registry::ResetTypes() {
SC_HASHlistinit( active_types, &cur_type );
}
const TypeDescriptor * Registry::NextType() {
if( 0 == SC_HASHlist( &cur_type ) ) {
return 0;
}
return ( const TypeDescriptor * ) cur_type.e->data;
}
void Registry::AddEntity( const EntityDescriptor & e ) {
SC_HASHinsert( primordialSwamp, ( char * ) e.Name(), ( EntityDescriptor * ) &e );
++entity_cnt;
++all_ents_cnt;
AddClones( e );
}
void Registry::AddSchema( const Schema & d ) {
SC_HASHinsert( active_schemas, ( char * ) d.Name(), ( Schema * ) &d );
}
void Registry::AddType( const TypeDescriptor & d ) {
SC_HASHinsert( active_types, ( char * ) d.Name(), ( TypeDescriptor * ) &d );
}
/**
* Purpose is to insert e into the registry hashed according to all its
* alternate names (the names it was renamed with when other schemas USEd
* or REFERENCEd it). This will make these names available to the Registry
* so that if we comes across one of them in a Part 21 file, we'll recog-
* nize it.
*/
void Registry::AddClones( const EntityDescriptor & e ) {
const SchRename * alts = e.AltNameList();
while( alts ) {
SC_HASHinsert( primordialSwamp, ( char * )alts->objName(),
( EntityDescriptor * )&e );
alts = alts->next;
}
all_ents_cnt += uniqueNames( e.Name(), e.AltNameList() );
}
/**
* Returns the number of unique names in an entity's _altname list. If
* schema B uses ent xx from schema A and renames it to yy, and schema C
* does the same (or if C simply uses yy from B), altlist will contain 2
* entries with the same alt name.
*/
static int uniqueNames( const char * entnm, const SchRename * altlist ) {
int cnt = 0;
const SchRename * alt = altlist;
while( alt ) {
if( !( ( alt->next && alt->next->choice( alt->objName() ) )
|| !StrCmpIns( alt->objName(), entnm ) ) ) {
// alt has a unique alternate name if it's not reused by a later
// alt. alt->next->choice() returns 1 if one of the later alts
// also has alt's name as its value. The final condition checks
// that our alt name is not the same as the original ent's (would
// be the case if the Express file said "USE from A (xx as xx)",
// which may not be legal and certainly isn't meaningful, but we
// check for it just in case. If none of the above conditions are
// true, we have a unique.
cnt++;
}
alt = alt->next;
}
return cnt;
}
void Registry::RemoveEntity( const char * n ) {
const EntityDescriptor * e = FindEntity( n );
struct Element tmp;
if( e ) {
RemoveClones( *e );
}
tmp.key = ( char * ) n;
SC_HASHsearch( primordialSwamp, &tmp, HASH_DELETE ) ? --entity_cnt : 0;
}
void Registry::RemoveSchema( const char * n ) {
struct Element tmp;
tmp.key = ( char * ) n;
SC_HASHsearch( active_schemas, &tmp, HASH_DELETE );
}
void Registry::RemoveType( const char * n ) {
struct Element tmp;
tmp.key = ( char * ) n;
SC_HASHsearch( active_types, &tmp, HASH_DELETE );
}
/**
* Remove all the "clones", or rename values of e.
*/
void Registry::RemoveClones( const EntityDescriptor & e ) {
const SchRename * alts = e.AltNameList();
while( alts ) {
struct Element * tmp = new Element;
tmp->key = ( char * ) alts->objName();
SC_HASHsearch( primordialSwamp, tmp, HASH_DELETE );
alts = alts->next;
delete tmp;
}
}
SDAI_Application_instance * Registry::ObjCreate( const char * nm, const char * schnm, int check_case ) const {
const EntityDescriptor * entd = FindEntity( nm, schnm, check_case );
if( entd ) {
SDAI_Application_instance * se =
( ( EntityDescriptor * )entd ) -> NewSTEPentity();
// See comment in previous function.
if( entd->AbstractEntity().asInt() == 1 ) {
se->Error().severity( SEVERITY_WARNING );
se->Error().UserMsg( "ENTITY is abstract supertype" );
} else if( entd->ExtMapping().asInt() == 1 ) {
se->Error().severity( SEVERITY_WARNING );
se->Error().UserMsg( "ENTITY requires external mapping" );
}
se->eDesc = entd;
return se;
} else {
return ENTITY_NULL;
}
}
int Registry::GetEntityCnt() {
return entity_cnt;
}
void Registry::ResetEntities() {
SC_HASHlistinit( primordialSwamp, &cur_entity );
}
const EntityDescriptor * Registry::NextEntity() {
if( 0 == SC_HASHlist( &cur_entity ) ) {
return 0;
}
return ( const EntityDescriptor * ) cur_entity.e->data;
}
void Registry::ResetSchemas() {
SC_HASHlistinit( active_schemas, &cur_schema );
}
const Schema * Registry::NextSchema() {
if( 0 == SC_HASHlist( &cur_schema ) ) {
return 0;
}
return ( const Schema * ) cur_schema.e->data;
}