1 /*
2 * NIST STEP Core Class Library
3 * clstepcore/STEPattribute.cc
4 * April 1997
5 * K. C. Morris
6 * David Sauder
7
8 * Development of this software was funded by the United States Government,
9 * and is not subject to copyright.
10 */
11
12 #include <iomanip>
13 #include <sstream>
14 #include <string>
15
16 #include <read_func.h>
17 #include <STEPattribute.h>
18 #include <instmgr.h>
19 #include <STEPundefined.h>
20 #include <STEPaggregate.h>
21 #include <ExpDict.h>
22 #include <sdai.h>
23 #include "sc_memmgr.h"
24
25 // REAL_NUM_PRECISION is defined in STEPattribute.h, and is also used
26 // in aggregate real handling (STEPaggregate.cc) -- IMS 6 Jun 95
27 const int Real_Num_Precision = REAL_NUM_PRECISION;
28
29 /**************************************************************//**
30 ** \class STEPattribute
31 ** Functions for manipulating attribute
32 **
33 ** FIXME KNOWN BUGS:
34 ** -- error reporting does not include line number information
35 ** -- null attributes are only handled through the attribute pointer class
36 ** direct access of a null attribute will not indicate whether the
37 ** attribute is null in all cases (although a null value is available
38 ** for entities and enumerations.)
39 **/
40
41
42 ///////////////////////////////////////////////////////////////////////////////
43 ///////////////////////////////////////////////////////////////////////////////
44 // STEPattribute Functions
45 ///////////////////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////////////////
47
48 /// the value of the attribute is assigned from the supplied string
StrToVal(const char * s,InstMgrBase * instances,int addFileId)49 Severity STEPattribute::StrToVal( const char * s, InstMgrBase * instances, int addFileId ) {
50 if( _redefAttr ) {
51 return _redefAttr->StrToVal( s, instances, addFileId );
52 }
53
54 _error.ClearErrorMsg(); // also sets Severity to SEVERITY_NULL
55
56 // set the value to be null (reinitialize the attribute value)
57 set_null();
58
59 int nullable = ( aDesc->Optional().asInt() == BTrue );
60
61 // an empty str gets assigned NULL
62 if( !s ) {
63 if( nullable || IsDerived() ) { // if it is derived it doesn't
64 return SEVERITY_NULL; // matter if it is null DAS
65 } else {
66 _error.severity( SEVERITY_INCOMPLETE );
67 return SEVERITY_INCOMPLETE;
68 }
69 }
70 if( s[0] == '\0' ) {
71 if( NonRefType() == STRING_TYPE ) {
72 // this is interpreted as a string with no value i.e. "".
73 *( ptr.S ) = s; // using string class - don't need to declare space
74 return SEVERITY_NULL;
75 }
76 if( nullable || IsDerived() ) { // if it is derived it doesn't
77 return SEVERITY_NULL; // matter if it is null DAS
78 } else {
79 _error.severity( SEVERITY_INCOMPLETE );
80 return SEVERITY_INCOMPLETE;
81 }
82 }
83
84 // an overridden attribute always has a \'*\' value
85 if( IsDerived() ) { // check to see if value contains: optional space,
86 // followed by *, followed by optional space
87 const char * tmpSptr = s;
88 while( isspace( *tmpSptr ) ) {
89 tmpSptr++;
90 }
91 if( *tmpSptr == '*' ) {
92 tmpSptr++;
93 char tmpC;
94 int charsFound = sscanf( tmpSptr, "%c", &tmpC );
95 if( charsFound == EOF ) { // no non-white chars followed the *
96 return SEVERITY_NULL;
97 }
98 }
99 _error.AppendToDetailMsg(
100 "Derived attribute must have \'*\' for its value.\n" );
101 return _error.severity( SEVERITY_INPUT_ERROR );
102 }
103
104 istringstream in( ( char * )s ); // sz defaults to length of s
105
106 // read in value for attribute
107 switch( NonRefType() ) {
108 case INTEGER_TYPE: {
109 ReadInteger( *( ptr.i ), s, &_error, 0 );
110 break;
111 }
112 case REAL_TYPE: {
113 ReadReal( *( ptr.r ), s, &_error, 0 );
114 break;
115 }
116 case NUMBER_TYPE: {
117 ReadNumber( *( ptr.r ), s, &_error, 0 );
118 break;
119 }
120
121 case ENTITY_TYPE: {
122 STEPentity * se = ReadEntityRef( s, &_error, 0, instances, addFileId );
123 if( se != S_ENTITY_NULL ) {
124 if( EntityValidLevel( se, aDesc->NonRefTypeDescriptor(),
125 &_error )
126 == SEVERITY_NULL ) {
127 *( ptr.c ) = se;
128 } else {
129 *( ptr.c ) = S_ENTITY_NULL;
130 }
131 } else {
132 *( ptr.c ) = S_ENTITY_NULL;
133 }
134 break;
135 }
136
137 case BINARY_TYPE: {
138 ptr.b->StrToVal( s, &_error ); // call class SDAI_Binary::StrToVal()
139 break;
140 }
141 case STRING_TYPE: {
142 *( ptr.S ) = s; // using string class - don't need to declare space
143 break;
144 }
145
146 case BOOLEAN_TYPE:
147 case LOGICAL_TYPE:
148 case ENUM_TYPE: {
149 ptr.e->StrToVal( s, &_error, nullable );
150 break;
151 }
152
153 case AGGREGATE_TYPE:
154 case ARRAY_TYPE: // DAS
155 case BAG_TYPE: // DAS
156 case SET_TYPE: // DAS
157 case LIST_TYPE: // DAS
158 ptr.a -> StrToVal( s, &_error,
159 aDesc -> AggrElemTypeDescriptor(),
160 instances, addFileId );
161 break;
162
163 case SELECT_TYPE:
164 if( _error.severity( ptr.sh->STEPread( in, &_error, instances, 0 ) )
165 != SEVERITY_NULL ) {
166 _error.AppendToDetailMsg( ptr.sh ->Error() );
167 }
168 break;
169
170 // case UNKNOWN_TYPE: // should never have this case
171 case GENERIC_TYPE:
172 default:
173 // other cases are the same for StrToVal and file
174 return STEPread( in, instances, addFileId );
175 }
176 return _error.severity();
177 }
178
179
180 /**************************************************************//**
181 ** \fn STEPread
182 ** \brief Reads attribute value from in, formatted as P21 file.
183 ** The value of the attribute is read from istream. The format
184 ** expected is STEP exchange file.
185 **
186 ** Accepts '$' or nothing as value for OPTIONAL ATTRIBUTE, since
187 ** this function is used for reading files in both old an new
188 ** formats.
189 **
190 ** Does not read the delimiter separating individual attributes (i.e. ',') or
191 ** the delim separating the last attribute from the end of the entity (')').
192 **
193 ** \returns Severity, which indicates success or failure
194 ** value >= SEVERITY_WARNING means program can continue parsing input,
195 ** value <= SEVERITY_INPUT_ERROR is fatal read error
196 ******************************************************************/
STEPread(istream & in,InstMgrBase * instances,int addFileId,const char * currSch,bool strict)197 Severity STEPattribute::STEPread( istream & in, InstMgrBase * instances, int addFileId,
198 const char * currSch, bool strict ) {
199
200 // The attribute has been redefined by the attribute pointed
201 // to by _redefAttr so write the redefined value.
202 if( _redefAttr ) {
203 return _redefAttr->STEPread( in, instances, addFileId, currSch );
204 }
205
206 _error.ClearErrorMsg(); // also sets Severity to SEVERITY_NULL
207
208 // set the value to be null (reinitialize the attribute value)
209 set_null();
210
211 in >> ws; // skip whitespace
212 char c = in.peek();
213
214 if( IsDerived() ) {
215 if( c == '*' ) {
216 in.get( c ); // take * off the istream
217 _error.severity( SEVERITY_NULL );
218 } else {
219 _error.severity( SEVERITY_WARNING );
220 _error.AppendToDetailMsg( " WARNING: attribute '" );
221 _error.AppendToDetailMsg( aDesc->Name() );
222 _error.AppendToDetailMsg( "' of type '" );
223 _error.AppendToDetailMsg( aDesc->TypeName() );
224 _error.AppendToDetailMsg( "' - missing asterisk for derived attribute.\n" );
225 }
226 CheckRemainingInput( in, &_error, aDesc->TypeName(), ",)" );
227 return _error.severity();
228 }
229 PrimitiveType attrBaseType = NonRefType();
230
231 // check for NULL or derived attribute value, return if either
232 switch( c ) {
233 case '$':
234 case ',':
235 case ')':
236 if( c == '$' ) {
237 in.ignore();
238 CheckRemainingInput( in, &_error, aDesc->TypeName(), ",)" );
239 }
240 if( Nullable() ) {
241 _error.severity( SEVERITY_NULL );
242 } else if( !strict ) {
243 std::string fillerValue;
244 // we aren't in strict mode, so find out the type of the missing attribute and insert a suitable value.
245 ErrorDescriptor err; //this will be discarded
246 switch( attrBaseType ) {
247 case INTEGER_TYPE: {
248 fillerValue = "'0',";
249 ReadInteger( *( ptr.i ), fillerValue.c_str(), &err, ",)" );
250 break;
251 }
252 case REAL_TYPE: {
253 fillerValue = "'0.0',";
254 ReadReal( *( ptr.r ), fillerValue.c_str(), &err, ",)" );
255 break;
256 }
257 case NUMBER_TYPE: {
258 fillerValue = "'0',";
259 ReadNumber( *( ptr.r ), fillerValue.c_str(), &err, ",)" );
260 break;
261 }
262 case STRING_TYPE: {
263 fillerValue = "'',";
264 *( ptr.S ) = "''";
265 break;
266 }
267 default: { //do not know what a good value would be for other types
268 _error.severity( SEVERITY_INCOMPLETE );
269 _error.AppendToDetailMsg( " missing and required\n" );
270 return _error.severity();
271 }
272 }
273 if( err.severity() <= SEVERITY_INCOMPLETE ) {
274 _error.severity( SEVERITY_BUG );
275 _error.AppendToDetailMsg( " Error in STEPattribute::STEPread()\n" );
276 return _error.severity();
277 }
278 //create a warning. SEVERITY_WARNING makes more sense to me, but is considered more severe than SEVERITY_INCOMPLETE
279 _error.severity( SEVERITY_USERMSG );
280 _error.AppendToDetailMsg( " missing and required. For compatibility, replacing with " );
281 _error.AppendToDetailMsg( fillerValue.substr( 0, fillerValue.length() - 1 ) );
282 _error.AppendToDetailMsg( ".\n" );
283 } else {
284 _error.severity( SEVERITY_INCOMPLETE );
285 _error.AppendToDetailMsg( " missing and required\n" );
286 }
287 return _error.severity();
288 }
289
290 switch( attrBaseType ) {
291 case INTEGER_TYPE: {
292 ReadInteger( *( ptr.i ), in, &_error, ",)" );
293 return _error.severity();
294 }
295 case REAL_TYPE: {
296 ReadReal( *( ptr.r ), in, &_error, ",)" );
297 return _error.severity();
298 }
299 case NUMBER_TYPE: {
300 ReadNumber( *( ptr.r ), in, &_error, ",)" );
301 return _error.severity();
302 }
303 case STRING_TYPE: {
304 ptr.S->STEPread( in, &_error );
305 CheckRemainingInput( in, &_error, "string", ",)" );
306 return _error.severity();
307 }
308 case BINARY_TYPE: {
309 // call class SDAI_Binary::STEPread()
310 ptr.b->STEPread( in, &_error );
311 CheckRemainingInput( in, &_error, "binary", ",)" );
312 return _error.severity();
313 }
314 case BOOLEAN_TYPE: {
315 ptr.e->STEPread( in, &_error, Nullable() );
316 CheckRemainingInput( in, &_error, "boolean", ",)" );
317 return _error.severity();
318 }
319 case LOGICAL_TYPE: {
320 ptr.e->STEPread( in, &_error, Nullable() );
321 CheckRemainingInput( in, &_error, "logical", ",)" );
322 return _error.severity();
323 }
324 case ENUM_TYPE: {
325 ptr.e->STEPread( in, &_error, Nullable() );
326 CheckRemainingInput( in, &_error, "enumeration", ",)" );
327 return _error.severity();
328 }
329 case AGGREGATE_TYPE:
330 case ARRAY_TYPE: // DAS
331 case BAG_TYPE: // DAS
332 case SET_TYPE: // DAS
333 case LIST_TYPE: { // DAS
334 ptr.a->STEPread( in, &_error,
335 aDesc->AggrElemTypeDescriptor(),
336 instances, addFileId, currSch );
337
338 // cannot recover so give up and let STEPentity recover
339 if( _error.severity() < SEVERITY_WARNING ) {
340 return _error.severity();
341 }
342
343 // check for garbage following the aggregate
344 CheckRemainingInput( in, &_error, "aggregate", ",)" );
345 return _error.severity();
346 }
347 case ENTITY_TYPE: {
348 STEPentity * se = ReadEntityRef( in, &_error, ",)", instances,
349 addFileId );
350 if( se != S_ENTITY_NULL ) {
351 if( EntityValidLevel( se,
352 aDesc->NonRefTypeDescriptor(),
353 &_error ) == SEVERITY_NULL ) {
354 *( ptr.c ) = se;
355 } else {
356 *( ptr.c ) = S_ENTITY_NULL;
357 }
358 } else {
359 *( ptr.c ) = S_ENTITY_NULL;
360 }
361 return _error.severity();
362
363 }
364 case SELECT_TYPE:
365 if( _error.severity( ptr.sh->STEPread( in, &_error, instances, 0,
366 addFileId, currSch ) )
367 != SEVERITY_NULL ) {
368 _error.AppendToDetailMsg( ptr.sh ->Error() );
369 }
370 CheckRemainingInput( in, &_error, "select", ",)" );
371 return _error.severity();
372
373 case GENERIC_TYPE: {
374 cerr << "Internal error: " << __FILE__ << __LINE__
375 << "\n" << _POC_ "\n";
376 _error.GreaterSeverity( SEVERITY_BUG );
377 return _error.severity();
378 }
379
380 case UNKNOWN_TYPE:
381 case REFERENCE_TYPE:
382 default: {
383 // bug
384 cerr << "Internal error: " << __FILE__ << __LINE__
385 << "\n" << _POC_ "\n";
386 _error.GreaterSeverity( SEVERITY_BUG );
387 return _error.severity();
388 }
389 }
390 }
391
392 /*****************************************************************//**
393 ** \fn asStr
394 ** \param currSch - used for select type writes. See commenting in SDAI_Select::STEPwrite().
395 ** \returns the value of the attribute
396 ** Status: complete 3/91
397 *********************************************************************/
asStr(const char * currSch) const398 std::string STEPattribute::asStr( const char * currSch ) const {
399 ostringstream ss;
400 std::string str;
401
402 // The attribute has been derived by a subtype's attribute
403 if( IsDerived() ) {
404 str = "*";
405 return str;
406 }
407
408 // The attribute has been redefined by the attribute pointed
409 // to by _redefAttr so write the redefined value.
410 if( _redefAttr ) {
411 return _redefAttr->asStr( currSch );
412 }
413
414 if( is_null() ) {
415 return str;
416 }
417
418 switch( NonRefType() ) {
419 case INTEGER_TYPE:
420 ss << *( ptr.i );
421 str += ss.str();
422 break;
423
424 case NUMBER_TYPE:
425 case REAL_TYPE:
426
427 ss.precision( ( int ) Real_Num_Precision );
428 ss << *( ptr.r );
429 str += ss.str();
430 break;
431
432 case ENTITY_TYPE:
433 // print instance id only if not empty pointer
434 // and has value assigned
435 if( ( *( ptr.c ) == S_ENTITY_NULL ) || ( *( ptr.c ) == 0 ) ) {
436 break;
437 } else {
438 ( *( ptr.c ) )->STEPwrite_reference( str );
439 }
440 break;
441
442 case BINARY_TYPE:
443 if( !( ptr.b->empty() ) ) {
444 ptr.b->STEPwrite( str );
445 }
446 break;
447
448 case STRING_TYPE:
449 if( !( ( ptr.S )->empty() ) ) {
450 ptr.S->asStr( str );
451 }
452 break;
453
454 case AGGREGATE_TYPE:
455 case ARRAY_TYPE: // DAS
456 case BAG_TYPE: // DAS
457 case SET_TYPE: // DAS
458 case LIST_TYPE: // DAS
459 ptr.a->asStr( str );
460 break;
461
462 case ENUM_TYPE:
463 case BOOLEAN_TYPE:
464 case LOGICAL_TYPE:
465 ptr.e->asStr( str );
466 break;
467
468 case SELECT_TYPE:
469 ptr.sh->STEPwrite( str, currSch );
470 break;
471
472 case REFERENCE_TYPE:
473 case GENERIC_TYPE:
474 cerr << "Internal error: " << __FILE__ << __LINE__
475 << "\n" << _POC_ "\n";
476 str.clear();
477 break;
478
479 case UNKNOWN_TYPE:
480 default:
481 ptr.u->asStr( str );
482 }
483 return str;
484 }
485
486 /// write '$' to out, put message in error, write brief error to stderr
STEPwriteError(ostream & out,unsigned int line,const char * desc)487 void STEPattribute::STEPwriteError( ostream & out, unsigned int line, const char* desc ) {
488 out << "$";
489 cerr << "Internal error: " << __FILE__ << ":" << line << "\n" << _POC_ "\n";
490
491 _error.GreaterSeverity( SEVERITY_BUG );
492 std::stringstream ss;
493 ss << " Warning: attribute '" << Name() << " : " << TypeName() << "' " << desc << std::endl;
494 _error.AppendToUserMsg( ss.str() );
495 _error.AppendToDetailMsg( ss.str() );
496 }
497
498 /**
499 * The value of the attribute is printed to the output stream specified by out.
500 * The output is in physical file format.
501 *
502 */
STEPwrite(ostream & out,const char * currSch)503 void STEPattribute::STEPwrite( ostream & out, const char * currSch ) {
504 // The attribute has been derived by a subtype's attribute
505 if( IsDerived() ) {
506 out << "*";
507 return;
508 }
509 // The attribute has been redefined by the attribute pointed
510 // to by _redefAttr so write the redefined value.
511 if( _redefAttr ) {
512 _redefAttr->STEPwrite( out );
513 return;
514 }
515
516 if( is_null() ) {
517 out << "$";
518 return;
519 }
520
521 switch( NonRefType() ) {
522 case INTEGER_TYPE:
523 out << *( ptr.i );
524 break;
525
526 case NUMBER_TYPE:
527 case REAL_TYPE: {
528 WriteReal( *( ptr.r ), out );
529 break;
530 }
531
532 case ENTITY_TYPE:
533 // print instance id only if not empty pointer
534 if( ( ptr.c == 0 ) || ( *( ptr.c ) == 0 ) ||
535 // no value was assigned <-- this would be a BUG
536 ( *( ptr.c ) == S_ENTITY_NULL ) ) {
537 STEPwriteError( out, __LINE__, "is null and shouldn't be." );
538 } else {
539 ( *( ptr.c ) ) -> STEPwrite_reference( out );
540 }
541 break;
542
543 case STRING_TYPE:
544 // if null pointer or pointer to a string of length zero
545 if( ptr.S ) {
546 ( ptr.S ) -> STEPwrite( out );
547 } else {
548 STEPwriteError( out, __LINE__, "should be pointing at an SDAI_String." );
549 }
550 break;
551
552 case BINARY_TYPE:
553 // if null pointer or pointer to a string of length zero
554 if( ptr.b ) {
555 ( ptr.b ) -> STEPwrite( out );
556 } else {
557 STEPwriteError( out, __LINE__, "should be pointing at an SDAI_Binary." );
558 }
559 break;
560
561 case AGGREGATE_TYPE:
562 case ARRAY_TYPE: // DAS
563 case BAG_TYPE: // DAS
564 case SET_TYPE: // DAS
565 case LIST_TYPE: // DAS
566 ptr.a -> STEPwrite( out, currSch );
567 break;
568
569 case ENUM_TYPE:
570 case BOOLEAN_TYPE:
571 case LOGICAL_TYPE:
572 if( ptr.e ) {
573 ptr.e -> STEPwrite( out );
574 } else {
575 STEPwriteError( out, __LINE__, "should be pointing at a SDAI_Enum class." );
576 }
577 break;
578
579 case SELECT_TYPE:
580 if( ptr.sh ) {
581 ptr.sh -> STEPwrite( out, currSch );
582 } else {
583 STEPwriteError( out, __LINE__, "should be pointing at a SDAI_Select class." );
584 }
585 break;
586
587 case REFERENCE_TYPE:
588 case GENERIC_TYPE:
589 cerr << "Internal error: " << __FILE__ << ":" << __LINE__ << "\n" << _POC_ "\n";
590 _error.GreaterSeverity( SEVERITY_BUG );
591 return;
592
593 case UNKNOWN_TYPE:
594 default:
595 ptr.u -> STEPwrite( out );
596 break;
597
598 }
599 }
600
601
ShallowCopy(const STEPattribute * sa)602 void STEPattribute::ShallowCopy( const STEPattribute * sa ) {
603 _mustDeletePtr = false;
604 aDesc = sa->aDesc;
605 refCount = 0;
606 _derive = sa->_derive;
607 _redefAttr = sa->_redefAttr;
608 if( _redefAttr ) {
609 _redefAttr->ShallowCopy( sa );
610 }
611 //Should we just use memcpy()? That would be a true shallowCopy
612 switch( sa->NonRefType() ) {
613 case INTEGER_TYPE:
614 ptr.i = sa->ptr.i;
615 break;
616 case BINARY_TYPE:
617 ptr.b = sa->ptr.b;
618 break;
619 case STRING_TYPE:
620 ptr.S = sa->ptr.S;
621 break;
622 case REAL_TYPE:
623 case NUMBER_TYPE:
624 ptr.r = sa->ptr.r;
625 break;
626 case ENTITY_TYPE:
627 ptr.c = sa->ptr.c;
628 break;
629 case ARRAY_TYPE: // DAS
630 case BAG_TYPE: // DAS
631 case SET_TYPE: // DAS
632 case LIST_TYPE: // DAS
633 switch( sa->BaseType() ) {
634 case sdaiAGGR:
635 ptr.a = new GenericAggregate;
636 break;
637 case sdaiINSTANCE:
638 ptr.a = new EntityAggregate;
639 break;
640 case sdaiSELECT:
641 ptr.a = new SelectAggregate;
642 break;
643 case sdaiSTRING:
644 ptr.a = new StringAggregate;
645 break;
646 case sdaiBINARY:
647 ptr.a = new BinaryAggregate;
648 break;
649 case sdaiENUMERATION:
650 ptr.a = new EnumAggregate;
651 break;
652 case sdaiBOOLEAN:
653 ptr.a = new BOOLEANS;
654 break;
655 case sdaiLOGICAL:
656 ptr.a = new LOGICALS;
657 break;
658 case sdaiREAL:
659 case sdaiNUMBER:
660 ptr.a = new RealAggregate;
661 break;
662 case sdaiINTEGER:
663 ptr.a = new IntAggregate;
664 break;
665 default:
666 std::cerr << "WARNING: Reached default case for BaseType() in STEPattribute::"
667 << "ShallowCopy(). New attribute may be invalid." << std::endl;
668 ptr.a = new STEPaggregate;
669 break;
670 }
671 ptr.a->ShallowCopy( *( sa->ptr.a ) );
672 _mustDeletePtr = true;
673 break;
674 case SELECT_TYPE:
675 ptr.sh = sa->ptr.sh;
676 break;
677 case BOOLEAN_TYPE:
678 ptr.e = new SDAI_BOOLEAN;
679 ptr.e->put( sa->ptr.e->asInt() );
680 _mustDeletePtr = true;
681 break;
682 case LOGICAL_TYPE:
683 ptr.e = new SDAI_LOGICAL;
684 ptr.e->put( sa->ptr.e->asInt() );
685 _mustDeletePtr = true;
686 break;
687
688 case AGGREGATE_TYPE:
689 case ENUM_TYPE:
690 default:
691 std::cerr << "WARNING: Reached default case for NonRefType() in STEPattribute::"
692 << "ShallowCopy(). New attribute may be invalid." << std::endl;
693 memcpy( & ptr, & ( sa->ptr ), sizeof( sa->ptr ) );
694 break;
695 }
696 }
697
698 /**
699 * for a string attribute this means, make it not exist i.e. SDAI_String
700 * will exist in member variable ptr but SDAI_string will be told to report
701 * as not containing a value (even a value of no chars).
702 */
set_null()703 Severity STEPattribute::set_null() {
704 if( _redefAttr ) {
705 return _redefAttr->set_null();
706 }
707 switch( NonRefType() ) {
708 case INTEGER_TYPE:
709 *( ptr.i ) = S_INT_NULL;
710 break;
711
712 case NUMBER_TYPE:
713 *( ptr.r ) = S_NUMBER_NULL;
714 break;
715
716 case REAL_TYPE:
717 *( ptr.r ) = S_REAL_NULL;
718 break;
719
720 case ENTITY_TYPE:
721 *( ptr.c ) = S_ENTITY_NULL;
722 break;
723
724 case STRING_TYPE:
725 ptr.S->clear();
726 break;
727
728 case BINARY_TYPE:
729 ptr.b ->clear();
730 break;
731
732 case AGGREGATE_TYPE:
733 case ARRAY_TYPE: // DAS
734 case BAG_TYPE: // DAS
735 case SET_TYPE: // DAS
736 case LIST_TYPE: { // DAS
737 ptr.a -> Empty();
738 break;
739 }
740
741 case ENUM_TYPE:
742 case BOOLEAN_TYPE:
743 case LOGICAL_TYPE:
744 ptr.e -> set_null();
745 break;
746
747 case SELECT_TYPE:
748 ptr.sh -> set_null();
749 break;
750
751 case REFERENCE_TYPE:
752 case GENERIC_TYPE:
753 cerr << "Internal error: " << __FILE__ << ":" << __LINE__ << "\n" << _POC_ "\n";
754 return SEVERITY_BUG;
755
756 case UNKNOWN_TYPE:
757 default:
758 ptr.u -> set_null();
759 std::stringstream err;
760 err << " Warning: attribute '" << Name() << " : " << TypeName() << " : ";
761 err << Type() << "' - " << "Don't know how to make attribute NULL" << std::endl;
762 _error.AppendToDetailMsg( err.str() );
763 _error.GreaterSeverity( SEVERITY_WARNING );
764 return SEVERITY_WARNING;
765 }
766 if( Nullable() ) {
767 return SEVERITY_NULL;
768 } else {
769 return SEVERITY_INCOMPLETE;
770 }
771 }
772
773 /**
774 * For a string value this reports whether the string exists (as reported by
775 * SDAI_String ) not whether SDAI_String contains a null string.
776 */
is_null() const777 bool STEPattribute::is_null() const {
778 if( _redefAttr ) {
779 return _redefAttr->is_null();
780 }
781 switch( NonRefType() ) {
782 case INTEGER_TYPE:
783 return ( *( ptr.i ) == S_INT_NULL );
784
785 case NUMBER_TYPE:
786 return ( *( ptr.r ) == S_NUMBER_NULL );
787
788 case REAL_TYPE:
789 return ( *( ptr.r ) == S_REAL_NULL );
790
791 case ENTITY_TYPE:
792 return ( *( ptr.c ) == S_ENTITY_NULL );
793
794 case STRING_TYPE:
795 return ( *( ptr.S ) == S_STRING_NULL );
796
797 case BINARY_TYPE:
798 return ptr.b->empty();
799
800 case AGGREGATE_TYPE:
801 case ARRAY_TYPE: // DAS
802 case BAG_TYPE: // DAS
803 case SET_TYPE: // DAS
804 case LIST_TYPE: { // DAS
805 return ( ptr.a -> is_null() );
806 }
807
808 case ENUM_TYPE:
809 case BOOLEAN_TYPE:
810 case LOGICAL_TYPE:
811 return ( ptr.e -> is_null() );
812
813 case SELECT_TYPE:
814 return( ptr.sh->is_null() );
815
816 case REFERENCE_TYPE:
817 case GENERIC_TYPE:
818 cerr << "Internal error: " << __FILE__ << ": " << __LINE__
819 << "\n" << _POC_ "\n";
820 return SEVERITY_BUG;
821
822 case UNKNOWN_TYPE:
823 default:
824 return ( ptr.u -> is_null() );
825 }
826 }
827
828 // these get the attr value
829
Integer()830 SDAI_Integer * STEPattribute::Integer(){
831 if( NonRefType() == INTEGER_TYPE ) {
832 return ptr.i;
833 }
834 return 0;
835 }
836
Number()837 SDAI_Real * STEPattribute::Number() {
838 if( NonRefType() == NUMBER_TYPE ) {
839 return ptr.r;
840 }
841 return 0;
842 }
843
Real()844 SDAI_Real * STEPattribute::Real() {
845 if( NonRefType() == REAL_TYPE ) {
846 return ptr.r;
847 }
848 return 0;
849 }
850
Entity()851 SDAI_Application_instance * STEPattribute::Entity() {
852 if( NonRefType() == ENTITY_TYPE ) {
853 return *( ptr.c );
854 }
855 return 0;
856 }
857
String()858 SDAI_String * STEPattribute::String() {
859 if( NonRefType() == STRING_TYPE ) {
860 return ptr.S;
861 }
862 return 0;
863 }
864
Binary()865 SDAI_Binary * STEPattribute::Binary() {
866 if( NonRefType() == BINARY_TYPE ) {
867 return ptr.b;
868 }
869 return 0;
870 }
871
Aggregate()872 STEPaggregate * STEPattribute::Aggregate() {
873 if( ( NonRefType() == AGGREGATE_TYPE ) || ( NonRefType() == ARRAY_TYPE ) || ( NonRefType() == BAG_TYPE )
874 || ( NonRefType() == SET_TYPE ) || ( NonRefType() == LIST_TYPE ) ) {
875 return ptr.a;
876 }
877 return 0;
878 }
879
Boolean()880 SDAI_BOOLEAN * STEPattribute::Boolean() {
881 if( NonRefType() == BOOLEAN_TYPE ) {
882 return ( SDAI_BOOLEAN * ) ptr.e;
883 }
884 return 0;
885 }
886
Logical()887 SDAI_LOGICAL * STEPattribute::Logical() {
888 if( NonRefType() == LOGICAL_TYPE ) {
889 return ( SDAI_LOGICAL * ) ptr.e;
890 }
891 return 0;
892 }
893
Enum()894 SDAI_Enum * STEPattribute::Enum() {
895 if( NonRefType() == ENUM_TYPE ) {
896 return ptr.e;
897 }
898 return 0;
899 }
900
Select()901 SDAI_Select * STEPattribute::Select() {
902 if( NonRefType() == SELECT_TYPE ) {
903 return ptr.sh;
904 }
905 return 0;
906 }
907
Undefined()908 SCLundefined * STEPattribute::Undefined() {
909 if( ( NonRefType() != REFERENCE_TYPE ) && ( NonRefType() != GENERIC_TYPE ) ) {
910 return ptr.u;
911 }
912 return 0;
913 }
914
915 // these set the attr value
916
Integer(SDAI_Integer * n)917 void STEPattribute::Integer( SDAI_Integer * n ) {
918 assert( NonRefType() == INTEGER_TYPE );
919 if( ptr.i ) {
920 *( ptr.i ) = * n;
921 } else {
922 ptr.i = n;
923 }
924 }
925
Real(SDAI_Real * n)926 void STEPattribute::Real( SDAI_Real * n ) {
927 assert( NonRefType() == REAL_TYPE );
928 if( ptr.r ) {
929 *( ptr.r ) = * n;
930 } else {
931 ptr.r = n;
932 }
933 }
934
Number(SDAI_Real * n)935 void STEPattribute::Number( SDAI_Real * n ) {
936 assert( NonRefType() == NUMBER_TYPE );
937 if( ptr.r ) {
938 *( ptr.r ) = * n;
939 } else {
940 ptr.r = n;
941 }
942 }
943
String(SDAI_String * str)944 void STEPattribute::String( SDAI_String * str ) {
945 assert( NonRefType() == STRING_TYPE );
946 if( ptr.S ) {
947 *( ptr.S ) = * str;
948 } else {
949 ptr.S = str;
950 }
951 }
952
Binary(SDAI_Binary * bin)953 void STEPattribute::Binary( SDAI_Binary * bin ) {
954 assert( NonRefType() == BINARY_TYPE );
955 if( ptr.b ) {
956 *( ptr.b ) = * bin;
957 } else {
958 ptr.b = bin;
959 }
960 }
961
Entity(SDAI_Application_instance * ent)962 void STEPattribute::Entity( SDAI_Application_instance * ent ) {
963 assert( NonRefType() == ENTITY_TYPE );
964 if( ptr.c ) {
965 delete ptr.c;
966 }
967 ptr.c = new (SDAI_Application_instance * );
968 *( ptr.c ) = ent;
969 }
970
Aggregate(STEPaggregate * aggr)971 void STEPattribute::Aggregate( STEPaggregate * aggr ) {
972 assert( ( NonRefType() == AGGREGATE_TYPE ) || ( NonRefType() == ARRAY_TYPE ) || ( NonRefType() == BAG_TYPE )
973 || ( NonRefType() == SET_TYPE ) || ( NonRefType() == LIST_TYPE ) );
974 if( ptr.a ) {
975 *( ptr.a ) = * aggr;
976 } else {
977 ptr.a = aggr;
978 }
979 }
980
Enum(SDAI_Enum * enu)981 void STEPattribute::Enum( SDAI_Enum * enu ) {
982 assert( NonRefType() == ENUM_TYPE );
983 if( ptr.e ) {
984 ptr.e->set_null();
985 *( ptr.e ) = * enu;
986 } else {
987 ptr.e = enu;
988 }
989 }
990
Logical(SDAI_LOGICAL * log)991 void STEPattribute::Logical( SDAI_LOGICAL * log ) {
992 assert( NonRefType() == LOGICAL_TYPE );
993 if( ptr.e ) {
994 ptr.e->set_null();
995 *( ptr.e ) = * log;
996 } else {
997 ptr.e = log;
998 }
999 }
1000
Boolean(SDAI_BOOLEAN * boo)1001 void STEPattribute::Boolean( SDAI_BOOLEAN * boo ) {
1002 assert( NonRefType() == BOOLEAN_TYPE );
1003 if( ptr.e ) {
1004 ptr.e->set_null();
1005 *( ptr.e ) = *boo;
1006 } else {
1007 ptr.e = boo;
1008 }
1009 }
1010
Select(SDAI_Select * sel)1011 void STEPattribute::Select( SDAI_Select * sel ) {
1012 assert( NonRefType() == SELECT_TYPE );
1013 if( ptr.sh ) {
1014 ptr.sh->set_null();
1015 *( ptr.sh ) = * sel;
1016 } else {
1017 ptr.sh = sel;
1018 }
1019 }
1020
Undefined(SCLundefined * undef)1021 void STEPattribute::Undefined( SCLundefined * undef ) {
1022 //FIXME is this right, or is the Undefined() above right?
1023 assert( NonRefType() == REFERENCE_TYPE || NonRefType() == UNKNOWN_TYPE );
1024 if( ptr.u ) {
1025 *( ptr.u ) = * undef;
1026 } else {
1027 ptr.u = undef;
1028 }
1029 }
1030
1031
1032 /** evaluate the equality of two attributes
1033 * ignores _error and refCount, since those are ancillary
1034 * \return true if equal
1035 */
operator ==(const STEPattribute & a1,const STEPattribute & a2)1036 bool operator == ( const STEPattribute & a1, const STEPattribute & a2 ) {
1037 if( & a1 == & a2 ) {
1038 return true;
1039 }
1040 if( a1._derive == a2._derive && a1.aDesc == a2.aDesc && a1._redefAttr == a2._redefAttr ){
1041 if( 0 == memcmp( & a1.ptr, & a2.ptr, sizeof( a1.ptr ) ) ) {
1042 return true;
1043 } else {
1044 //ptr differs between a1 and a2, but contents aren't necessarily different
1045 return a1.asStr() == a2.asStr();
1046 }
1047 }
1048 return false;
1049 }
1050
1051 /** evaluate the equality of two attributes
1052 * ignores _error and refCount, since those are ancillary
1053 * \return true if not equal
1054 */
operator !=(const STEPattribute & a1,const STEPattribute & a2)1055 bool operator != ( const STEPattribute & a1, const STEPattribute & a2 ) {
1056 return !( a1 == a2 );
1057 }
1058
1059 /// return true if the attr descriptor is identical
sameADesc(const STEPattribute & a1,const STEPattribute & a2)1060 bool sameADesc( const STEPattribute & a1, const STEPattribute & a2 ) {
1061 return a1.aDesc == a2.aDesc;
1062 }
1063
1064
1065
1066 /**************************************************************//**
1067 * \returns the severity level that the parameter attrValue would pass if it
1068 * was the value for this attribute.
1069 * *note* for string values - (attrValue = 0) => string value does not exist,
1070 * attrValue exists it is valid.
1071 ******************************************************************/
ValidLevel(const char * attrValue,ErrorDescriptor * error,InstMgrBase * im,bool clearError)1072 Severity STEPattribute::ValidLevel( const char * attrValue, ErrorDescriptor * error, InstMgrBase * im, bool clearError ) {
1073 if( clearError ) {
1074 ClearErrorMsg();
1075 }
1076
1077 if( _redefAttr ) {
1078 return _redefAttr->ValidLevel( attrValue, error, im, clearError );
1079 }
1080 bool optional = Nullable();
1081
1082 if( !attrValue ) {
1083 if( optional ) {
1084 return error->severity();
1085 } else {
1086 error->GreaterSeverity( SEVERITY_INCOMPLETE );
1087 return SEVERITY_INCOMPLETE;
1088 }
1089 }
1090 if( attrValue[0] == '\0' ) {
1091 if( NonRefType() == STRING_TYPE ) {
1092 // this is interpreted as a string with no value i.e. "".
1093 // Thus if it exists it has to be valid.
1094 return SEVERITY_NULL;
1095 }
1096 if( optional ) {
1097 return error->severity();
1098 } else {
1099 error->GreaterSeverity( SEVERITY_INCOMPLETE );
1100 return SEVERITY_INCOMPLETE;
1101 }
1102 }
1103
1104 // an overridden attribute always has a \'*\' value
1105 if( IsDerived() ) {
1106 if( !strcmp( attrValue, "*" ) ) {
1107 return SEVERITY_NULL;
1108 } else {
1109 _error.AppendToDetailMsg( "attr is derived - value not permitted\n" );
1110 return _error.severity( SEVERITY_INPUT_ERROR );
1111 }
1112 }
1113
1114 switch( NonRefType() ) {
1115 case INTEGER_TYPE:
1116 return IntValidLevel( attrValue, error, clearError, optional, 0 );
1117
1118 case STRING_TYPE:
1119 // if a value exists (checked above) then that is the string value
1120 return SEVERITY_NULL;
1121
1122 case REAL_TYPE:
1123 return RealValidLevel( attrValue, error, clearError, optional, 0 );
1124
1125 case NUMBER_TYPE:
1126 return NumberValidLevel( attrValue, error, clearError, optional, 0 );
1127
1128 case ENTITY_TYPE:
1129 return EntityValidLevel( attrValue,
1130 aDesc->NonRefTypeDescriptor(),
1131 error, im, 0 );
1132 case BINARY_TYPE:
1133 return ptr.b->BinaryValidLevel( attrValue, &_error, optional, 0 );
1134
1135 case AGGREGATE_TYPE:
1136 case ARRAY_TYPE: // DAS
1137 case BAG_TYPE: // DAS
1138 case SET_TYPE: // DAS
1139 case LIST_TYPE: { // DAS
1140 return ptr.a->AggrValidLevel( attrValue, error,
1141 aDesc->AggrElemTypeDescriptor(), im,
1142 optional, 0, 0, 0 );
1143 }
1144 case ENUM_TYPE:
1145 case BOOLEAN_TYPE:
1146 case LOGICAL_TYPE:
1147 return ptr.e->EnumValidLevel( attrValue, error, optional, 0, 0, 1 );
1148 case SELECT_TYPE:
1149 return ptr.sh->SelectValidLevel( attrValue, error, im );
1150
1151 default:
1152 cerr << "Internal error: " << __FILE__ << __LINE__
1153 << "\n" << _POC_ "\n";
1154 return error->severity();
1155 }
1156 }
1157
1158 /**************************************************************//**
1159 ** \param out -- output stream
1160 ** \param a -- attribute to output
1161 ** Description: overloads the output operator to print an attribute
1162 ******************************************************************/
operator <<(ostream & out,STEPattribute & a)1163 ostream & operator<< ( ostream & out, STEPattribute & a ) {
1164 a.STEPwrite( out );
1165 return out;
1166 }
1167
1168 /**************************************************************//**
1169 * This prepends attribute information to the detailed error msg. This
1170 * is intended to add information to the error msgs written by Enumerations,
1171 * Aggregates, and SDAI_Strings which don't know they are a STEPattribute
1172 * value.
1173 ******************************************************************/
AddErrorInfo()1174 void STEPattribute::AddErrorInfo() {
1175 char errStr[BUFSIZ];
1176 errStr[0] = '\0';
1177 if( SEVERITY_INPUT_ERROR < _error.severity() &&
1178 _error.severity() < SEVERITY_NULL ) {
1179 sprintf( errStr, " Warning: ATTRIBUTE '%s : %s : %d' - ",
1180 Name(), TypeName(), Type() );
1181 _error.PrependToDetailMsg( errStr );
1182 } else if( _error.severity() == SEVERITY_INPUT_ERROR ) {
1183 sprintf( errStr, " Error: ATTRIBUTE '%s : %s : %d' - ",
1184 Name(), TypeName(), Type() );
1185 _error.PrependToDetailMsg( errStr );
1186 } else if( _error.severity() <= SEVERITY_BUG ) {
1187 sprintf( errStr, " BUG: ATTRIBUTE '%s : %s : %d' - ",
1188 Name(), TypeName(), Type() );
1189 _error.PrependToDetailMsg( errStr );
1190 }
1191 }
1192
1193 /**************************************************************//**
1194 * this function reads until it hits eof or one of the StopChars.
1195 * if it hits one of StopChars it puts it back.
1196 * RETURNS: the last char it read.
1197 ******************************************************************/
SkipBadAttr(istream & in,char * StopChars)1198 char STEPattribute::SkipBadAttr( istream & in, char * StopChars ) {
1199 ios_base::fmtflags flbuf = in.flags();
1200 in.unsetf( ios::skipws ); // turn skipping whitespace off
1201
1202 // read bad data until end of this attribute or entity.
1203 char * foundCh = 0;
1204 char c = '\0';
1205 char errStr[BUFSIZ];
1206 errStr[0] = '\0';
1207
1208 _error.GreaterSeverity( SEVERITY_WARNING );
1209 in >> c;
1210 while( !in.eof() && !( foundCh = strchr( StopChars, c ) ) ) {
1211 in >> c;
1212 }
1213 if( in.eof() ) {
1214 _error.GreaterSeverity( SEVERITY_INPUT_ERROR );
1215 sprintf( errStr, " Error: attribute '%s : %s : %d' - %s.\n",
1216 Name(), TypeName(), Type(),
1217 "Unexpected EOF when skipping bad attr value" );
1218 _error.AppendToDetailMsg( errStr );
1219 } else {
1220 sprintf( errStr, " Error: attribute '%s : %s : %d' - %s.\n",
1221 Name(), TypeName(), Type(), "Invalid value" );
1222 _error.AppendToDetailMsg( errStr );
1223 }
1224 in.putback( c );
1225 in.flags( flbuf ); // set skip whitespace to its original state
1226 return c;
1227 }
1228