1
2 #include <sdai.h>
3 #include "sc_memmgr.h"
4
5 /*
6 * NIST STEP Core Class Library
7 * cldai/sdaiEnum.cc
8 * April 1997
9 * K. C. Morris
10 * David Sauder
11
12 * Development of this software was funded by the United States Government,
13 * and is not subject to copyright.
14 */
15
16 #include <sstream>
17
18 ///////////////////////////////////////////////////////////////////////////////
19 // class Logical
20 ///////////////////////////////////////////////////////////////////////////////
21
SDAI_LOGICAL(const char * val)22 SDAI_LOGICAL::SDAI_LOGICAL( const char * val ) {
23 set_value( val );
24 }
25
SDAI_LOGICAL(Logical state)26 SDAI_LOGICAL::SDAI_LOGICAL( Logical state ) {
27 set_value( state );
28 }
29
SDAI_LOGICAL(const SDAI_LOGICAL & source)30 SDAI_LOGICAL::SDAI_LOGICAL( const SDAI_LOGICAL & source ) {
31 set_value( source.asInt() );
32 }
33
SDAI_LOGICAL(int i)34 SDAI_LOGICAL::SDAI_LOGICAL( int i ) {
35 if( i == 0 ) {
36 v = LFalse ;
37 } else {
38 v = LTrue ;
39 }
40 }
41
~SDAI_LOGICAL()42 SDAI_LOGICAL::~SDAI_LOGICAL() {
43 }
44
Name() const45 const char * SDAI_LOGICAL::Name() const {
46 return "Logical";
47 }
48
no_elements() const49 int SDAI_LOGICAL::no_elements() const {
50 return 3;
51 }
52
element_at(int n) const53 const char * SDAI_LOGICAL::element_at( int n ) const {
54 switch( n ) {
55 case LUnknown :
56 return "U";
57 case LFalse :
58 return "F";
59 case LTrue :
60 return "T";
61 default:
62 return "UNSET";
63 }
64 }
65
exists() const66 int SDAI_LOGICAL::exists() const { // return 0 if unset otherwise return 1
67 return !( v == 2 );
68 }
69
nullify()70 void SDAI_LOGICAL::nullify() { // change the receiver to an unset status
71 v = 2;
72 }
73
operator Logical() const74 SDAI_LOGICAL::operator Logical() const {
75 switch( v ) {
76 case LFalse :
77 return LFalse ;
78 case LTrue :
79 return LTrue ;
80 case LUnknown :
81 return LUnknown ;
82 case LUnset :
83 default:
84 return LUnset ;
85 }
86 }
87
operator =(const SDAI_LOGICAL & t)88 SDAI_LOGICAL & SDAI_LOGICAL::operator= ( const SDAI_LOGICAL & t ) {
89 set_value( t.asInt() );
90 return *this;
91 }
92
operator ==(const SDAI_LOGICAL & t) const93 SDAI_LOGICAL SDAI_LOGICAL::operator ==( const SDAI_LOGICAL & t ) const {
94 if( v == t.asInt() ) {
95 return LTrue ;
96 }
97 return LFalse ;
98 }
99
set_value(const int i)100 int SDAI_LOGICAL::set_value( const int i ) {
101 if( i > no_elements() + 1 ) {
102 v = 2;
103 return v;
104 }
105 const char * tmp = element_at( i );
106 if( tmp[0] != '\0' ) {
107 return ( v = i );
108 }
109 // otherwise
110 cerr << "(OLD Warning:) invalid enumeration value " << i
111 << " for " << Name() << "\n";
112 DebugDisplay();
113 return no_elements() + 1 ;
114 }
115
set_value(const char * n)116 int SDAI_LOGICAL::set_value( const char * n ) {
117 // assigns the appropriate value based on n
118 if( !n || ( !strcmp( n, "" ) ) ) {
119 nullify();
120 return asInt();
121 }
122
123 int i = 0;
124 std::string tmp;
125 while( ( i < ( no_elements() + 1 ) ) &&
126 ( strcmp( ( char * )StrToUpper( n, tmp ), element_at( i ) ) != 0 ) ) {
127 ++i;
128 }
129 if( ( no_elements() + 1 ) == i ) { // exhausted all the possible values
130 nullify();
131 return v;
132 }
133 v = i;
134 return v;
135 }
136
ReadEnum(istream & in,ErrorDescriptor * err,int AssignVal,int needDelims)137 Severity SDAI_LOGICAL::ReadEnum( istream & in, ErrorDescriptor * err, int AssignVal,
138 int needDelims ) {
139 if( AssignVal ) {
140 set_null();
141 }
142
143 std::string str;
144 char messageBuf[512];
145 messageBuf[0] = '\0';
146
147 in >> ws; // skip white space
148
149 if( in.good() ) {
150 char c;
151 in.get( c );
152 if( c == '.' || isalpha( c ) ) {
153 int validDelimiters = 1;
154 if( c == '.' ) {
155 in.get( c ); // push past the delimiter
156 // since found a valid delimiter it is now invalid until the
157 // matching ending delim is found
158 validDelimiters = 0;
159 }
160
161 // look for UPPER
162 if( in.good() && ( isalpha( c ) || c == '_' ) ) {
163 str += c;
164 in.get( c );
165 }
166
167 // look for UPPER or DIGIT
168 while( in.good() && ( isalnum( c ) || c == '_' ) ) {
169 str += c;
170 in.get( c );
171 }
172 // if character is not the delimiter unread it
173 if( in.good() && ( c != '.' ) ) {
174 in.putback( c );
175 }
176
177 // a value was read
178 if( str.length() > 0 ) {
179 int i = 0;
180 const char * strval = str.c_str();
181 std::string tmp;
182 while( ( i < ( no_elements() + 1 ) ) &&
183 ( strcmp( ( char * )StrToUpper( strval, tmp ),
184 element_at( i ) ) != 0 ) ) {
185 ++i;
186 }
187 if( ( no_elements() + 1 ) == i ) {
188 // exhausted all the possible values
189 err->GreaterSeverity( SEVERITY_WARNING );
190 err->AppendToDetailMsg( "Invalid Enumeration value.\n" );
191 err->AppendToUserMsg( "Invalid Enumeration value.\n" );
192 } else {
193 if( AssignVal ) {
194 v = i;
195 }
196 }
197
198 // now also check the delimiter situation
199 if( c == '.' ) { // if found ending delimiter
200 // if expecting delim (i.e. validDelimiter == 0)
201 if( !validDelimiters ) {
202 validDelimiters = 1; // everything is fine
203 } else { // found ending delimiter but no initial delimiter
204 validDelimiters = 0;
205 }
206 }
207 // didn't find any delimiters at all and need them.
208 else if( needDelims ) {
209 validDelimiters = 0;
210 }
211
212 if( !validDelimiters ) {
213 err->GreaterSeverity( SEVERITY_WARNING );
214 if( needDelims )
215 sprintf( messageBuf,
216 "Enumerated value has invalid period delimiters.\n" );
217 else
218 sprintf( messageBuf,
219 "Mismatched period delimiters for enumeration.\n" );
220 err->AppendToDetailMsg( messageBuf );
221 err->AppendToUserMsg( messageBuf );
222 }
223 return err->severity();
224 }
225 // found valid or invalid delimiters with no associated value
226 else if( ( c == '.' ) || !validDelimiters ) {
227 err->GreaterSeverity( SEVERITY_WARNING );
228 err->AppendToDetailMsg(
229 "Enumerated has valid or invalid period delimiters with no value.\n"
230 );
231 err->AppendToUserMsg(
232 "Enumerated has valid or invalid period delimiters with no value.\n"
233 );
234 return err->severity();
235 } else { // no delims and no value
236 err->GreaterSeverity( SEVERITY_INCOMPLETE );
237 }
238
239 } else if( ( c == ',' ) || ( c == ')' ) ) {
240 in.putback( c );
241 err->GreaterSeverity( SEVERITY_INCOMPLETE );
242 } else {
243 in.putback( c );
244 err->GreaterSeverity( SEVERITY_WARNING );
245 sprintf( messageBuf, "Invalid enumeration value.\n" );
246 err->AppendToDetailMsg( messageBuf );
247 err->AppendToUserMsg( messageBuf );
248 }
249 } else { // hit eof (assuming there was no error state for istream passed in)
250 err->GreaterSeverity( SEVERITY_INCOMPLETE );
251 }
252 return err->severity();
253 }
254
255 ///////////////////////////////////////////////////////////////////////////////
256 // class BOOLEAN Jan 97
257 ///////////////////////////////////////////////////////////////////////////////
258
Name() const259 const char * SDAI_BOOLEAN::Name() const {
260 return "Bool";
261 }
262
SDAI_BOOLEAN(char * val)263 SDAI_BOOLEAN::SDAI_BOOLEAN( char * val ) {
264 set_value( val );
265 }
266
SDAI_BOOLEAN(Boolean state)267 SDAI_BOOLEAN::SDAI_BOOLEAN( Boolean state ) {
268 set_value( state );
269 }
270
SDAI_BOOLEAN(const SDAI_BOOLEAN & source)271 SDAI_BOOLEAN::SDAI_BOOLEAN( const SDAI_BOOLEAN & source ) {
272 set_value( source.asInt() );
273 }
274
~SDAI_BOOLEAN()275 SDAI_BOOLEAN::~SDAI_BOOLEAN() {
276 }
277
no_elements() const278 int SDAI_BOOLEAN::no_elements() const {
279 return 2;
280 }
281
SDAI_BOOLEAN(int i)282 SDAI_BOOLEAN::SDAI_BOOLEAN( int i ) {
283 if( i == 0 ) {
284 v = BFalse ;
285 } else {
286 v = BTrue ;
287 }
288 }
289
SDAI_BOOLEAN(const SDAI_LOGICAL & val)290 SDAI_BOOLEAN::SDAI_BOOLEAN( const SDAI_LOGICAL & val ) {
291 if( val.asInt() == LUnknown ) {
292 // this should set error code sdaiVT_NVLD i.e. Invalid value type.
293 v = BUnset;
294 return;
295 }
296 set_value( val );
297 }
298
operator Boolean() const299 SDAI_BOOLEAN::operator Boolean() const {
300 switch( v ) {
301 case BFalse :
302 return BFalse ;
303 case BTrue :
304 return BTrue ;
305 case BUnset :
306 default:
307 return BUnset ;
308 }
309 }
310
operator =(const SDAI_LOGICAL & t)311 SDAI_BOOLEAN & SDAI_BOOLEAN::operator= ( const SDAI_LOGICAL & t ) {
312 set_value( t.asInt() );
313 return *this;
314 }
315
operator =(const Boolean t)316 SDAI_BOOLEAN & SDAI_BOOLEAN::operator= ( const Boolean t ) {
317 v = t;
318 return *this;
319 }
320
element_at(int n) const321 const char * SDAI_BOOLEAN::element_at( int n ) const {
322 switch( n ) {
323 case BFalse :
324 return "F";
325 case BTrue :
326 return "T";
327 default:
328 return "UNSET";
329 }
330 }
331
operator ==(const SDAI_LOGICAL & t) const332 SDAI_LOGICAL SDAI_BOOLEAN::operator ==( const SDAI_LOGICAL & t ) const {
333 if( v == t.asInt() ) {
334 return LTrue ;
335 }
336 return LFalse ;
337 }
338
339 ///////////////////////////////////////////////////////////////////////////////
340
SDAI_Enum()341 SDAI_Enum::SDAI_Enum() {
342 v = 0;
343 }
344
345 /**
346 * \copydoc set_value( const char * n )
347 */
put(int val)348 int SDAI_Enum::put( int val ) {
349 return set_value( val );
350 }
351
352 /**
353 * \copydoc set_value( const char * n )
354 */
put(const char * n)355 int SDAI_Enum::put( const char * n ) {
356 return set_value( n );
357 }
358
359 /// return 0 if unset otherwise return 1
exists() const360 int SDAI_Enum::exists() const {
361 return !( v > no_elements() );
362 }
363 /**
364 * change the receiver to an unset status
365 * unset is generated to be 1 greater than last element
366 */
nullify()367 void SDAI_Enum::nullify() {
368 set_value( no_elements() + 1 );
369 }
370
371 /**************************************************************//**
372 ** prints out some information on the enumerated item for
373 ** debugging purposes
374 ** Status: ok 2/1/91
375 ******************************************************************/
DebugDisplay(ostream & out) const376 void SDAI_Enum::DebugDisplay( ostream & out ) const {
377 std::string tmp;
378 out << "Current " << Name() << " value: " << endl
379 << " cardinal: " << v << endl
380 << " string: " << asStr( tmp ) << endl
381 << " Part 21 file format: ";
382 STEPwrite( out );
383 out << endl;
384
385 out << "Valid values are: " << endl;
386 int i = 0;
387 while( i < ( no_elements() + 1 ) ) {
388 out << i << " " << element_at( i ) << endl;
389 i++;
390 }
391 out << "\n";
392 }
393
394 /**
395 ** Read an Enumeration value
396 ** ENUMERATION = "." UPPER { UPPER | DIGIT } "."
397 ** *note* UPPER is defined as alpha or underscore.
398 **
399 ** \returns Severity of the error.
400 ** \param err error message and error Severity is written to ErrorDescriptor *err.
401 ** \param AssignVal is:
402 ** true => value is assigned to the SDAI_Enum;
403 ** true or false => value is read and appropriate error info is set and returned.
404 ** \param int needDelims is:
405 ** false => absence of the period delimiters is not an error;
406 ** true => delimiters must be valid;
407 ** true or false => non-matching delimiters are flagged as an error
408 */
ReadEnum(istream & in,ErrorDescriptor * err,int AssignVal,int needDelims)409 Severity SDAI_Enum::ReadEnum( istream & in, ErrorDescriptor * err, int AssignVal,
410 int needDelims ) {
411 if( AssignVal ) {
412 set_null();
413 }
414
415 std::string str;
416 char messageBuf[512];
417 messageBuf[0] = '\0';
418
419 in >> ws; // skip white space
420
421 if( in.good() ) {
422 char c;
423 in.get( c );
424 if( c == '.' || isalpha( c ) ) {
425 int validDelimiters = 1;
426 if( c == '.' ) {
427 in.get( c ); // push past the delimiter
428 // since found a valid delimiter it is now invalid until the
429 // matching ending delim is found
430 validDelimiters = 0;
431 }
432
433 // look for UPPER
434 if( in.good() && ( isalpha( c ) || c == '_' ) ) {
435 str += c;
436 in.get( c );
437 }
438
439 // look for UPPER or DIGIT
440 while( in.good() && ( isalnum( c ) || c == '_' ) ) {
441 str += c;
442 in.get( c );
443 }
444 // if character is not the delimiter unread it
445 if( in.good() && ( c != '.' ) ) {
446 in.putback( c );
447 }
448
449 // a value was read
450 if( str.length() > 0 ) {
451 int i = 0;
452 const char * strval = str.c_str();
453 std::string tmp;
454 while( ( i < no_elements() ) &&
455 ( strcmp( ( char * )StrToUpper( strval, tmp ),
456 element_at( i ) ) != 0 ) ) {
457 ++i;
458 }
459 if( no_elements() == i ) {
460 // exhausted all the possible values
461 err->GreaterSeverity( SEVERITY_WARNING );
462 err->AppendToDetailMsg( "Invalid Enumeration value.\n" );
463 err->AppendToUserMsg( "Invalid Enumeration value.\n" );
464 } else {
465 if( AssignVal ) {
466 v = i;
467 }
468 }
469
470 // now also check the delimiter situation
471 if( c == '.' ) { // if found ending delimiter
472 // if expecting delim (i.e. validDelimiter == 0)
473 if( !validDelimiters ) {
474 validDelimiters = 1; // everything is fine
475 } else { // found ending delimiter but no initial delimiter
476 validDelimiters = 0;
477 }
478 }
479 // didn't find any delimiters at all and need them.
480 else if( needDelims ) {
481 validDelimiters = 0;
482 }
483
484 if( !validDelimiters ) {
485 err->GreaterSeverity( SEVERITY_WARNING );
486 if( needDelims )
487 sprintf( messageBuf,
488 "Enumerated value has invalid period delimiters.\n" );
489 else
490 sprintf( messageBuf,
491 "Mismatched period delimiters for enumeration.\n" );
492 err->AppendToDetailMsg( messageBuf );
493 err->AppendToUserMsg( messageBuf );
494 }
495 return err->severity();
496 }
497 // found valid or invalid delimiters with no associated value
498 else if( ( c == '.' ) || !validDelimiters ) {
499 err->GreaterSeverity( SEVERITY_WARNING );
500 err->AppendToDetailMsg(
501 "Enumerated has valid or invalid period delimiters with no value.\n"
502 );
503 err->AppendToUserMsg(
504 "Enumerated has valid or invalid period delimiters with no value.\n"
505 );
506 return err->severity();
507 } else { // no delims and no value
508 err->GreaterSeverity( SEVERITY_INCOMPLETE );
509 }
510
511 } else if( ( c == ',' ) || ( c == ')' ) ) {
512 in.putback( c );
513 err->GreaterSeverity( SEVERITY_INCOMPLETE );
514 } else {
515 in.putback( c );
516 err->GreaterSeverity( SEVERITY_WARNING );
517 sprintf( messageBuf, "Invalid enumeration value.\n" );
518 err->AppendToDetailMsg( messageBuf );
519 err->AppendToUserMsg( messageBuf );
520 }
521 } else { // hit eof (assuming there was no error state for istream passed in)
522 err->GreaterSeverity( SEVERITY_INCOMPLETE );
523 }
524 return err->severity();
525 }
526
StrToVal(const char * s,ErrorDescriptor * err,int optional)527 Severity SDAI_Enum::StrToVal( const char * s, ErrorDescriptor * err, int optional ) {
528 istringstream in( ( char * )s ); // sz defaults to length of s
529
530 ReadEnum( in, err, 1, 0 );
531 if( ( err->severity() == SEVERITY_INCOMPLETE ) && optional ) {
532 err->severity( SEVERITY_NULL );
533 }
534
535 return err->severity();
536 }
537
538 /// reads an enumerated value in STEP file format
STEPread(const char * s,ErrorDescriptor * err,int optional)539 Severity SDAI_Enum::STEPread( const char * s, ErrorDescriptor * err, int optional ) {
540 istringstream in( ( char * )s );
541 return STEPread( in, err, optional );
542 }
543
544 /// reads an enumerated value in STEP file format
STEPread(istream & in,ErrorDescriptor * err,int optional)545 Severity SDAI_Enum::STEPread( istream & in, ErrorDescriptor * err, int optional ) {
546 ReadEnum( in, err, 1, 1 );
547 if( ( err->severity() == SEVERITY_INCOMPLETE ) && optional ) {
548 err->severity( SEVERITY_NULL );
549 }
550
551 return err->severity();
552 }
553
asStr(std::string & s) const554 const char * SDAI_Enum::asStr( std::string & s ) const {
555 if( exists() ) {
556 s = element_at( v );
557 return s.c_str();
558 } else {
559 s.clear();
560 return "";
561 }
562 }
563
STEPwrite(ostream & out) const564 void SDAI_Enum::STEPwrite( ostream & out ) const {
565 if( is_null() ) {
566 out << '$';
567 } else {
568 std::string tmp;
569 out << "." << asStr( tmp ) << ".";
570 }
571 }
572
STEPwrite(std::string & s) const573 const char * SDAI_Enum::STEPwrite( std::string & s ) const {
574 if( is_null() ) {
575 s.clear();
576 } else {
577 std::string tmp;
578 s = ".";
579 s.append( asStr( tmp ) );
580 s.append( "." );
581 }
582 return const_cast<char *>( s.c_str() );
583 }
584
EnumValidLevel(istream & in,ErrorDescriptor * err,int optional,char * tokenList,int needDelims,int clearError)585 Severity SDAI_Enum::EnumValidLevel( istream & in, ErrorDescriptor * err,
586 int optional, char * tokenList,
587 int needDelims, int clearError ) {
588 if( clearError ) {
589 err->ClearErrorMsg();
590 }
591
592 in >> ws; // skip white space
593 char c = ' ';
594 c = in.peek();
595 if( c == '$' || in.eof() ) {
596 if( !optional ) {
597 err->GreaterSeverity( SEVERITY_INCOMPLETE );
598 }
599 if( in ) {
600 in >> c;
601 }
602 CheckRemainingInput( in, err, "enumeration", tokenList );
603 return err->severity();
604 } else {
605 ErrorDescriptor error;
606
607 ReadEnum( in, &error, 0, needDelims );
608 CheckRemainingInput( in, &error, "enumeration", tokenList );
609
610 Severity sev = error.severity();
611 if( sev < SEVERITY_INCOMPLETE ) {
612 err->AppendToDetailMsg( error.DetailMsg() );
613 err->AppendToUserMsg( error.UserMsg() );
614 err->GreaterSeverity( error.severity() );
615 } else if( sev == SEVERITY_INCOMPLETE && !optional ) {
616 err->GreaterSeverity( SEVERITY_INCOMPLETE );
617 }
618 }
619 return err->severity();
620 }
621
EnumValidLevel(const char * value,ErrorDescriptor * err,int optional,char * tokenList,int needDelims,int clearError)622 Severity SDAI_Enum::EnumValidLevel( const char * value, ErrorDescriptor * err,
623 int optional, char * tokenList,
624 int needDelims, int clearError ) {
625 istringstream in( ( char * )value );
626 return EnumValidLevel( in, err, optional, tokenList, needDelims,
627 clearError );
628 }
629
630 /**************************************************************//**
631 ** sets the value of an enumerated attribute case is not important
632 ** in the character based version if value is not acceptable, a
633 ** warning is printed and processing continues
634 **
635 ** set_value is the same function as put
636 **
637 ** Parameter: value to be set
638 ** Status: ok 2.91
639 ** \returns: value set
640 ******************************************************************/
set_value(const char * n)641 int SDAI_Enum::set_value( const char * n ) {
642 if( !n || ( !strcmp( n, "" ) ) ) {
643 nullify();
644 return asInt();
645 }
646
647 int i = 0;
648 std::string tmp;
649 while( ( i < no_elements() ) &&
650 ( strcmp( ( char * )StrToUpper( n, tmp ), element_at( i ) ) != 0 ) ) {
651 ++i;
652 }
653 if( no_elements() == i ) { // exhausted all the possible values
654 return v = no_elements() + 1; // defined as UNSET
655 }
656 v = i;
657 return v;
658
659 }
660
661 /**
662 * \copydoc set_value( const char * n )
663 */
set_value(const int i)664 int SDAI_Enum::set_value( const int i ) {
665 if( i > no_elements() ) {
666 v = no_elements() + 1;
667 return v;
668 }
669 const char * tmp = element_at( i );
670 if( tmp[0] != '\0' ) {
671 return ( v = i );
672 }
673 // otherwise
674 cerr << "(OLD Warning:) invalid enumeration value " << i
675 << " for " << Name() << "\n";
676 DebugDisplay();
677 return no_elements() + 1 ;
678 }
679
operator =(const int i)680 SDAI_Enum & SDAI_Enum::operator= ( const int i ) {
681 put( i );
682 return *this;
683 }
684
operator =(const SDAI_Enum & Senum)685 SDAI_Enum & SDAI_Enum::operator= ( const SDAI_Enum & Senum ) {
686 put( Senum.asInt() );
687 return *this;
688 }
689
operator <<(ostream & out,const SDAI_Enum & a)690 ostream & operator<< ( ostream & out, const SDAI_Enum & a ) {
691 std::string tmp;
692 out << a.asStr( tmp );
693 return out;
694
695 }
696