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