// abv 09.04.99 S4136: eliminate parameter step.readaccept.void // sln 04,10.2001. BUC61003. Prevent exception which may occur during reading of complex entity (if entity's items are not in alphabetical order) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Le Header est constitue d entites analogues dans leur principe a celles // du Data, a ceci pres qu elles sont sans identifieur, et ne peuvent ni // referencer, ni etre referencees (que ce soit avec Header ou avec Data) // Ainsi, dans StepReaderData, le Header est constitue des "thenbhead" 1res Entites // ######################################################################### // .... Creation et Acces de base aux donnees atomiques du fichier .... typedef TCollection_HAsciiString String; typedef Handle(TCollection_HAsciiString) Handle(String); static char txtmes[200]; // plus commode que redeclarer partout static Standard_Boolean initstr = Standard_False; #define Maxlst 64 //static TCollection_AsciiString subl[Maxlst]; // Maxlst : minimum 10 static Standard_Integer acceptvoid = 0; // ---------- Fonctions Utilitaires ---------- //======================================================================= //function : CleanText //purpose : //======================================================================= static void CleanText (const Handle(TCollection_HAsciiString)& val) { Standard_Integer n = val->Length(); // avant reduction val->Remove(n); val->Remove(1); // Ne pas oublier de traiter les caracteres speciaux for (Standard_Integer i = n-2; i > 0; i --) { char uncar = val->Value(i); if (uncar == '\n') { val->Remove(i); if (i < n-2) uncar = val->Value(i); } if (uncar == '\'' && i < n-2) { if (val->Value(i+1) == '\'') { val->Remove(i+1); continue; } } if (uncar == '\\' && i < n-2) { if (val->Value(i+1) == '\\') { val->Remove(i+1); continue; } } else if (uncar == '\\' && i < n-3) { if (val->Value(i+2) == '\\') { if (val->Value(i+1) == 'N') { val->SetValue(i,'\n'); val->Remove(i+1,2); continue; } if (val->Value(i+1) == 'T') { val->SetValue(i,'\t'); val->Remove(i+1,2); continue; } } } } } // ------------- METHODES ------------- //======================================================================= //function : StepData_StepReaderData //purpose : //======================================================================= StepData_StepReaderData::StepData_StepReaderData (const Standard_Integer nbheader, const Standard_Integer nbtotal, const Standard_Integer nbpar) : Interface_FileReaderData (nbtotal,nbpar), theidents (1,nbtotal), thetypes (1,nbtotal) //, themults (1,nbtotal) { // char textnum[10]; thenbscop = 0; thenbents = 0; thelastn = 0; thenbhead = nbheader; //themults.Init(0); thecheck = new Interface_Check; //:S4136 acceptvoid = Interface_Static::IVal("step.readaccept.void"); if (initstr) return; //for (Standard_Integer i = 0; i < Maxlst; i ++) { // sprintf(textnum,"$%d",i+1); // subl[i].AssignCat(textnum); //} initstr = Standard_True; } //======================================================================= //function : SetRecord //purpose : //======================================================================= void StepData_StepReaderData::SetRecord (const Standard_Integer num, const Standard_CString ident, const Standard_CString type, const Standard_Integer /* nbpar */) { Standard_Integer numlst; /* if (strcmp(type,"/ * (SUB) * /") == 0) { // defini dans recfile.pc thetypes.SetValue (num,sublist); } else { thenbents ++; // total de termes propres du fichier thetypes.SetValue(num,TCollection_AsciiString(type)); // if (strcmp(ident,"SCOPE") != 0) thenbscop ++; // ?? a verifier } */ if (type[0] != '(') thenbents ++; // total de termes propres du fichier //thetypes.ChangeValue(num).SetValue(1,type); gka memory //============================================ Standard_Integer index = 0; TCollection_AsciiString strtype(type); if(thenametypes.Contains(type)) index = thenametypes.FindIndex(strtype); else index = thenametypes.Add(strtype); thetypes.ChangeValue(num) = index; //=========================================== if (ident[0] == '$') { if (strlen(ident) > 2) numlst = atoi(&ident[1]); else numlst = ident[1] - 48; if (thelastn < numlst) thelastn = numlst; // plus fort n0 de sous-liste theidents.SetValue(num,-2-numlst); } else if (ident[0] == '#') { numlst = atoi(&ident[1]); theidents.SetValue(num,numlst); if (numlst == 0 && num > thenbhead) { // Header, ou bien Type Complexe ... // Si Type Complexe, retrouver Type Precedent (on considere que c est rare) // On chaine le type precedent sur le suivant // VERIFICATION que les types sont en ordre alphabetique for (Standard_Integer prev = num-1; prev > thenbhead; prev --) { if (theidents(prev) >= 0) { //themults.SetValue(prev,num); themults.Bind(prev,num); if(thenametypes.FindKey(thetypes.Value(num)).IsLess(thenametypes.FindKey(thetypes.Value(prev)))) { //if (thetypes.Value(num).IsLess(thetypes.Value(prev))) // ERREUR : Type complexe pas en ordre alphabetique. On enregistre. TCollection_AsciiString errm("Complex Type incorrect : "); errm.AssignCat(thenametypes.FindKey(thetypes.Value(prev))); errm.AssignCat(" / "); errm.AssignCat(thenametypes.FindKey(thetypes.Value(num))); errm.AssignCat(" ... "); thecheck->AddFail(errm.ToCString(),"Complex Type incorrect : "); // On Affiche a l ecran, le plus de donnees possibles while (theidents(prev) <= 0) { prev --; if (prev <= 0) break; } Handle(Message_Messenger) sout = Message::DefaultMessenger(); sout << " *** Error on Record " << num << " (on " << NbRecords() << " -> " << num*100/NbRecords() << " % in File) ***"; if (prev > 0) sout << " Ident #" << theidents(prev); sout << "\n" << errm << endl; } break; } } } } else if (!strcmp(ident,"SCOPE")) { theidents.SetValue(num,-1); // SCOPE thenbscop ++; } else if (!strcmp(ident,"ENDSCOPE")) theidents.SetValue(num,-2); // ENDSCOPE // Reste 0 // InitParams(num); } //======================================================================= //function : AddStepParam //purpose : //======================================================================= void StepData_StepReaderData::AddStepParam (const Standard_Integer num, const Standard_CString aval, const Interface_ParamType atype, const Standard_Integer nument) { if (atype == Interface_ParamSub) { Standard_Integer numid = 0; if (aval[2] != '\0') { numid = atoi(&aval[1]); // if (numid <= Maxlst) Interface_FileReaderData::AddParam // (num,subl[numid-1].ToCString(),atype,numid); Interface_FileReaderData::AddParam (num,aval,atype,numid); } else { char *numlstchar = (char *)(aval+1); numid = (*numlstchar) - 48; // -48 ('0') -1 (adresse [] depuis 0) // Interface_FileReaderData::AddParam (num,subl[numid].ToCString(),atype,numid); Interface_FileReaderData::AddParam (num,aval,atype,numid); } } else if (atype == Interface_ParamIdent) { Standard_Integer numid = atoi(&aval[1]); Interface_FileReaderData::AddParam (num,aval,atype,numid); } else { Interface_FileReaderData::AddParam (num,aval,atype,nument); } // Interface_FileReaderData::AddParam (num,parval,atype,numid); } //======================================================================= //function : RecordType //purpose : //======================================================================= const TCollection_AsciiString& StepData_StepReaderData::RecordType (const Standard_Integer num) const { return thenametypes.FindKey(thetypes.Value(num)); } //======================================================================= //function : CType //purpose : //======================================================================= Standard_CString StepData_StepReaderData::CType(const Standard_Integer num) const { return thenametypes.FindKey(thetypes.Value(num)).ToCString(); } //======================================================================= //function : RecordIdent //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::RecordIdent (const Standard_Integer num) const { return theidents(num); } // ######################################################################## // .... Aides a la lecture des parametres, adaptees a STEP .... //======================================================================= //function : SubListNumber //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::SubListNumber (const Standard_Integer num, const Standard_Integer nump, const Standard_Boolean aslast) const { if (nump == 0 || nump > NbParams(num)) return 0; const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() != Interface_ParamSub) return 0; if (aslast) { if(nump != NbParams(num)) return 0; } return FP.EntityNumber(); } //======================================================================= //function : IsComplex //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::IsComplex(const Standard_Integer num) const { //return (themults(num) != 0); return themults.IsBound(num); } //======================================================================= //function : ComplexType //purpose : //======================================================================= void StepData_StepReaderData::ComplexType(const Standard_Integer num, TColStd_SequenceOfAsciiString& types) const { if (theidents(num) < 0) return; for (Standard_Integer i = num; i > 0; i = NextForComplex(i)) { types.Append(RecordType(i)); } } //======================================================================= //function : NextForComplex //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::NextForComplex (const Standard_Integer num) const { Standard_Integer next =0; if(themults.IsBound(num)) next = themults.Find(num); return next; } //======================================================================= //function : stepstrcmp //purpose : //======================================================================= static Standard_Boolean stepstrcmp(const Standard_CString type, const Standard_CString name) { // name peut etre d un tenant ou de deux : auquel cas il a une partie LONGUE // et une partie COURTE separees par un blanc // Attention : False pour dire OK, True sinon (car remplace strcmp) Standard_Integer i,j = 0; Standard_Boolean res = Standard_False; for (i = 0; name[i] != '\0' && type[i] != '\0' && !res ; i ++) { if (name[i] == ' ') { j = i; break; } if (type[i] != name[i]) res = Standard_True; } if (!res || (j == 0)) return res; // Pas trouve et un blanc suit : on continue for (i = j+1; name[i] != '\0'; i ++) { if (type[i-j-1] != name[i]) return Standard_True; } return Standard_False; } //======================================================================= //function : NamedForComplex //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::NamedForComplex (const Standard_CString name, const Standard_Integer num0, Standard_Integer& num, Handle(Interface_Check)& ach) const { //Standard_Boolean stat = Standard_True; Standard_Integer n = (num <= 0 ? num0 : NextForComplex(num)); // sln 04,10.2001. BUC61003. if(n==0) the next function is not called in order to avoid exception if ((n!=0) && (!stepstrcmp (RecordType(n).ToCString(),name))) { num = n; return Standard_True; } if (n == 0) /*stat =*/ NamedForComplex (name,num0,n,ach); // on a rembobine // Pas dans l ordre alphabetique : boucler Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST"); sprintf (txtmes,errmess->ToCString(),num0,name); for (n = num0; n > 0; n = NextForComplex(n)) { if (!stepstrcmp (RecordType(n).ToCString(),name)) { num = n; errmess = new String("Complex Record n0.%d, member type %s not in alphabetic order"); sprintf (txtmes,errmess->ToCString(),num0,name); ach->AddWarning(txtmes,errmess->ToCString()); return Standard_False; } } num = 0; errmess = new String("Complex Record n0.%d, member type %s not found"); sprintf (txtmes,errmess->ToCString(),num0,name); ach->AddFail (txtmes,errmess->ToCString()); return Standard_False; } // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## //======================================================================= //function : CheckNbParams //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::CheckNbParams(const Standard_Integer num, const Standard_Integer nbreq, Handle(Interface_Check)& ach, const Standard_CString mess) const { if (NbParams(num) == nbreq) return Standard_True; Handle(String) errmess; if (mess[0] == '\0') errmess = new String("Count of Parameters is not %d"); else errmess = new String("Count of Parameters is not %d for %s"); sprintf (txtmes,errmess->ToCString(),nbreq,mess); ach->AddFail (txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadSubList //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadSubList(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Integer& numsub, const Standard_Boolean optional, const Standard_Integer /* lenmin */, const Standard_Integer /* lenmax */) const { numsub = SubListNumber (num,nump,Standard_False); if (numsub > 0) return Standard_True; // Si optionel indefini, on passe l eponge numsub = 0; Standard_Boolean isvoid = (Param(num,nump).ParamType() == Interface_ParamVoid); if (isvoid && optional) return Standard_False; Handle(String) errmess = new String("Parameter n0.%d (%s) not a LIST"); sprintf (txtmes,errmess->ToCString(),nump,mess); if (acceptvoid && isvoid) ach->AddWarning(txtmes,errmess->ToCString()); else { ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } return Standard_True; } // ... Facilites pour LateBinding //======================================================================= //function : ReadSub //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::ReadSub(const Standard_Integer numsub, const Standard_CString mess, Handle(Interface_Check)& ach, const Handle(StepData_PDescr)& descr, Handle(Standard_Transient)& val) const { Standard_Integer nbp = NbParams(numsub); if (nbp == 0) return 0; // liste vide = Handle Null const TCollection_AsciiString& rectyp = RecordType (numsub); if (nbp == 1 && rectyp.ToCString()[0] != '(') { // c est un type avec un parametre -> SelectNamed // cf ReadSelect mais ici, on est deja sur le contenu du parametre Handle(StepData_SelectNamed) sn = new StepData_SelectNamed; val = sn; sn->SetName (rectyp.ToCString()); if (ReadAny (numsub,1,mess,ach,descr,sn)) return sn->Kind(); else return 0; } // cas courant : faire un HArray1 de ... de ... de quoi au fait const Interface_FileParameter& FP0 = Param(numsub,1); Interface_ParamType FT, FT0 = FP0.ParamType(); Standard_CString str = FP0.CValue(); Handle(TColStd_HArray1OfTransient) htr; Handle(TColStd_HArray1OfInteger) hin; Handle(TColStd_HArray1OfReal) hre; Handle(Interface_HArray1OfHAsciiString) hst; Standard_Integer kod = 0; switch (FT0) { case Interface_ParamMisc : return -1; case Interface_ParamInteger : kod = 1; break; case Interface_ParamReal : kod = 5; break; case Interface_ParamIdent : kod = 7; break; case Interface_ParamVoid : kod = 0; break; case Interface_ParamText : kod = 6; break; case Interface_ParamEnum : kod = 4; break; // a confirmer(logical) /* kod = 4; if ( str[0] == '.' && str[2] == '.' && str[3] == '\0' && (str[1] == 'T' || str[1] == 'F' || str[1] == 'U') ) kod = 3; break; */ // svv #2 case Interface_ParamLogical : return -1; case Interface_ParamSub : kod = 0; break; case Interface_ParamHexa : return -1; case Interface_ParamBinary : return -1; default : return -1; } if (kod == 1 || kod == 3) { hin = new TColStd_HArray1OfInteger (1,nbp); val = hin; } else if (kod == 5) { hre = new TColStd_HArray1OfReal (1,nbp); val = hre; } else if (kod == 6) { hst = new Interface_HArray1OfHAsciiString (1,nbp); val = hst; } else { htr = new TColStd_HArray1OfTransient (1,nbp); val = htr; } // Attention : si type variable, faudra changer son fusil d epaule -> htr for (Standard_Integer ip = 1; ip <= nbp; ip ++) { const Interface_FileParameter& FP = Param(numsub,ip); str = FP.CValue(); FT = FP.ParamType(); switch (kod) { case 1 : { if (FT != Interface_ParamInteger) { kod = 0; break; } hin->SetValue (ip,atoi(str)); break; } case 2 : case 3 : { if (FT != Interface_ParamEnum) { kod = 0; break; } if (!strcmp(str,".F.")) hin->SetValue (ip,0); else if (!strcmp(str,".T.")) hin->SetValue (ip,1); else if (!strcmp(str,".U.")) hin->SetValue (ip,2); else kod = 0; break; } case 4 : { if (FT != Interface_ParamEnum) { kod = 0; break; } Handle(StepData_SelectNamed) sn = new StepData_SelectNamed; sn->SetEnum (-1,str); htr->SetValue (ip,sn); break; } case 5 : { if (FT != Interface_ParamReal) { kod = 0; break; } hre->SetValue (ip,Interface_FileReaderData::Fastof(str)); break; } case 6 : { if (FT != Interface_ParamText) { kod = 0; break; } Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str); CleanText (txt); hst->SetValue (ip,txt); break; } case 7 : { Handle(Standard_Transient) ent = BoundEntity (FP.EntityNumber()); htr->SetValue (ip,ent); break; } default : break; } // Restent les autres cas ... tout est possible. cf le type du Param if (kod > 0) continue; // Il faut passer au transient ... if (htr.IsNull()) { htr = new TColStd_HArray1OfTransient (1,nbp); val = htr; Standard_Integer jp; if (!hin.IsNull()) { for (jp = 1; jp < ip; jp ++) { Handle(StepData_SelectInt) sin = new StepData_SelectInt; sin->SetInt (hin->Value(jp)); htr->SetValue (jp,sin); } } if (!hre.IsNull()) { for (jp = 1; jp < ip; jp ++) { Handle(StepData_SelectReal) sre = new StepData_SelectReal; sre->SetReal (hre->Value(jp)); htr->SetValue (jp,sre); } } if (!hst.IsNull()) { for (jp = 1; jp < ip; jp ++) { htr->SetValue (jp,hst->Value(jp)); } } } // A present, faut y aller : lire le champ et le mettre en place // Ce qui suit ressemble fortement a ReadAny ... switch (FT) { case Interface_ParamMisc : break; case Interface_ParamInteger : { Handle(StepData_SelectInt) sin = new StepData_SelectInt; sin->SetInteger (atoi(str)); htr->SetValue (ip,sin); break; } case Interface_ParamReal : { Handle(StepData_SelectReal) sre = new StepData_SelectReal; sre->SetReal (Interface_FileReaderData::Fastof(str)); break; //htr->SetValue (ip,sre); break; svv #2: unreachable } case Interface_ParamIdent : htr->SetValue (ip,BoundEntity (FP.EntityNumber())); break; case Interface_ParamVoid : break; case Interface_ParamEnum : { Handle(StepData_SelectInt) sin; Handle(StepData_SelectNamed) sna; Standard_Integer logic = -1; // PTV 16.09.2000 // set the default value of StepData_Logical StepData_Logical slog = StepData_LUnknown; if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') { if (str[1] == 'F') { slog = StepData_LFalse; logic = 0; } else if (str[1] == 'T') { slog = StepData_LTrue; logic = 1; } else if (str[1] == 'U') { slog = StepData_LUnknown; logic = 2; } } if (logic >= 0) { sin = new StepData_SelectInt; sin->SetLogical(slog); htr->SetValue(ip,sin); } else { sna = new StepData_SelectNamed; sna->SetEnum (logic,str); htr->SetValue (ip,sna); } break; } case Interface_ParamLogical : break; case Interface_ParamText : { Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str); CleanText (txt); htr->SetValue (ip,txt); break; } case Interface_ParamSub : { Handle(Standard_Transient) sub; Standard_Integer nent = FP.EntityNumber(); Standard_Integer kind = ReadSub (nent,mess,ach,descr,sub); if (kind < 0) break; htr->SetValue(ip,sub); break; } case Interface_ParamHexa : break; case Interface_ParamBinary : break; default : break; } return -1; } return 8; // pour Any } //======================================================================= //function : ReadMember //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadMember(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Handle(StepData_SelectMember)& val) const { Handle(Standard_Transient) v = val; Handle(StepData_PDescr) nuldescr; if (v.IsNull()) return ReadAny (num,nump,mess,ach,nuldescr,val); Standard_Boolean res = ReadAny (num,nump,mess,ach,nuldescr,v); if (v == val) return res; // changement -> refus Handle(String) errmess = new String("Parameter n0.%d (%s) : does not match SELECT clause"); sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadField //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadField(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, const Handle(StepData_PDescr)& descr, StepData_Field& fild) const { const Interface_FileParameter& FP = Param(num,nump); Standard_CString str = FP.CValue(); Standard_Boolean OK = Standard_True; Standard_Integer nent, kind; Handle(TCollection_HAsciiString) txt; Handle(Standard_Transient) sub; Interface_ParamType FT = FP.ParamType(); switch (FT) { case Interface_ParamMisc : OK = Standard_False; break; case Interface_ParamInteger : fild.SetInteger (atoi(str)); break; case Interface_ParamReal : fild.SetReal (Interface_FileReaderData::Fastof(str)); break; case Interface_ParamIdent : nent = FP.EntityNumber(); if (nent > 0) fild.SetEntity (BoundEntity(nent)); break; case Interface_ParamVoid : break; case Interface_ParamText : txt = new TCollection_HAsciiString(str); CleanText (txt); fild.Set (txt); break; case Interface_ParamEnum : if (!strcmp(str,".T.")) fild.SetLogical (StepData_LTrue); else if (!strcmp(str,".F.")) fild.SetLogical (StepData_LFalse); else if (!strcmp(str,".U.")) fild.SetLogical (StepData_LUnknown); else fild.SetEnum (-1,str); break; case Interface_ParamLogical : OK = Standard_False; break; case Interface_ParamSub : nent = FP.EntityNumber(); kind = ReadSub (nent,mess,ach,descr,sub); if (kind < 0) break; fild.Clear(kind); fild.Set (sub); break; case Interface_ParamHexa : OK = Standard_False; break; case Interface_ParamBinary : OK = Standard_False; break; default : OK = Standard_False; break; } if (!OK) { if (!strcmp(str,"*")) fild.SetDerived(); } return Standard_True; } //======================================================================= //function : ReadList //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadList(const Standard_Integer num, Handle(Interface_Check)& ach, const Handle(StepData_ESDescr)& descr, StepData_FieldList& list) const { // controler nbs egaux Standard_Integer i,nb = list.NbFields(); if (!CheckNbParams (num,nb,ach,descr->TypeName())) return Standard_False; for (i = 1; i <= nb; i ++) { Handle(StepData_PDescr) pde = descr->Field(i); StepData_Field& fild = list.CField(i); ReadField (num,i,pde->Name(),ach,pde,fild); } return Standard_True; } //======================================================================= //function : ReadAny //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadAny(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, const Handle(StepData_PDescr)& descr, Handle(Standard_Transient)& val) const { const Interface_FileParameter& FP = Param(num,nump); Standard_CString str = FP.CValue(); Interface_ParamType FT = FP.ParamType(); // A present, faut y aller : lire le champ et le mettre en place switch (FT) { case Interface_ParamMisc : break; case Interface_ParamInteger : { if (!val.IsNull()) { DeclareAndCast(StepData_SelectMember,sm,val); sm->SetInteger(atoi(str)); return Standard_True; } Handle(StepData_SelectInt) sin = new StepData_SelectInt; sin->SetInteger (atoi(str)); val = sin; return Standard_True; } case Interface_ParamReal : { if (!val.IsNull()) { DeclareAndCast(StepData_SelectMember,sm,val); sm->SetReal (Interface_FileReaderData::Fastof(str)); return Standard_True; } Handle(StepData_SelectReal) sre = new StepData_SelectReal; sre->SetReal (Interface_FileReaderData::Fastof(str)); val = sre; return Standard_True; } case Interface_ParamIdent : { Standard_Integer nent = FP.EntityNumber(); if (nent > 0) val = BoundEntity(nent); return (!val.IsNull()); } case Interface_ParamVoid : break; case Interface_ParamEnum : { Handle(StepData_SelectMember) sm; if (!val.IsNull()) sm = GetCasted(StepData_SelectMember,val); Handle(StepData_SelectInt) sin; Handle(StepData_SelectNamed) sna; Standard_Integer logic = -1; // PTV 16.09.2000 // set the default value of StepData_Logical StepData_Logical slog = StepData_LUnknown; if ( str[0] == '.' && str[2] == '.' && str[3] == '\0') { if (str[1] == 'F') { slog = StepData_LFalse; logic = 0; } else if (str[1] == 'T') { slog = StepData_LTrue; logic = 1; } else if (str[1] == 'U') { slog = StepData_LUnknown; logic = 2; } } if (logic >= 0) { if (!sm.IsNull()) sm->SetLogical(slog); else { sin = new StepData_SelectInt; val = sin; sin->SetLogical(slog); } } else { if (!sm.IsNull()) sm->SetEnum (logic,str); else { sna = new StepData_SelectNamed; val = sna; // Named sans nom... sna->SetEnum (logic,str); } } // -> Select general return Standard_True; } case Interface_ParamLogical : break; case Interface_ParamText : { Handle(TCollection_HAsciiString) txt = new TCollection_HAsciiString(str); CleanText (txt); // PDN May 2000: for reading SOURCE_ITEM (external references) if (!val.IsNull()) { DeclareAndCast(StepData_SelectMember,sm,val); sm->SetString (txt->ToCString()); return Standard_True; } val = txt; return Standard_True; } case Interface_ParamSub : { Standard_Integer numsub = SubListNumber (num,nump,Standard_False); Standard_Integer nbp = NbParams(numsub); if (nbp == 0) return Standard_False; // liste vide = Handle Null const TCollection_AsciiString& rectyp = RecordType (numsub); if (nbp == 1 && rectyp.ToCString()[0] != '(') { // SelectNamed because Field !!! // skl 15.01.2003 (for members with array of real) DeclareAndCast(StepData_SelectArrReal,sma,val); if(!sma.IsNull()) { Standard_Integer numsub2 = SubListNumber (numsub,1,Standard_False); Standard_Integer nbp2 = NbParams(numsub2); if(nbp2>1) { if( Param(numsub2,1).ParamType() == Interface_ParamReal ) { if (!sma->SetName (rectyp.ToCString())) return Standard_False; Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal; for(Standard_Integer i=1; i<=nbp2; i++) { if( Param(numsub2,i).ParamType() != Interface_ParamReal ) continue; Handle(StepData_SelectReal) sm1 = new StepData_SelectReal; if( !ReadAny(numsub2,i,mess,ach,descr,sm1) ) continue; aSeq->Append(sm1->Real()); } Handle(TColStd_HArray1OfReal) anArr = new TColStd_HArray1OfReal(1,aSeq->Length()); for(Standard_Integer nr=1; nr<=aSeq->Length(); nr++) { anArr->SetValue(nr,aSeq->Value(nr)); } sma->SetArrReal(anArr); return Standard_True; } } } DeclareAndCast(StepData_SelectMember,sm,val); if (sm.IsNull()) { sm = new StepData_SelectNamed; val = sm; } if (!sm->SetName (rectyp.ToCString())) return Standard_False; // loupe return ReadAny (numsub,1,mess,ach,descr,val); } } default : break; } return Standard_False; } // .... //======================================================================= //function : ReadXY //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadXY(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Real& X, Standard_Real& Y) const { Handle(String) errmess; // Null si pas d erreur Standard_Integer numsub = SubListNumber(num,nump,Standard_False); if (numsub != 0) { if (NbParams(numsub) == 2) { const Interface_FileParameter& FPX = Param(numsub,1); if (FPX.ParamType() == Interface_ParamReal) X = Interface_FileReaderData::Fastof(FPX.CValue()); else errmess = new String("Parameter n0.%d (%s) : (X,Y) X not a Real"); const Interface_FileParameter& FPY = Param(numsub,2); if (FPY.ParamType() == Interface_ParamReal) Y = Interface_FileReaderData::Fastof( FPY.CValue()); else errmess = new String("Parameter n0.%d (%s) : (X,Y) Y not a Real"); } else errmess = new String("Parameter n0.%d (%s) : (X,Y) has not 2 params"); } else errmess = new String("Parameter n0.%d (%s) : (X,Y) not a SubList"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadXYZ //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadXYZ(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Real& X, Standard_Real& Y, Standard_Real& Z) const { Handle(String) errmess; // Null si pas d erreur Standard_Integer numsub = SubListNumber(num,nump,Standard_False); if (numsub != 0) { if (NbParams(numsub) == 3) { const Interface_FileParameter& FPX = Param(numsub,1); if (FPX.ParamType() == Interface_ParamReal) X = Interface_FileReaderData::Fastof(FPX.CValue()); else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) X not a Real"); const Interface_FileParameter& FPY = Param(numsub,2); if (FPY.ParamType() == Interface_ParamReal) Y = Interface_FileReaderData::Fastof(FPY.CValue()); else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Y not a Real"); const Interface_FileParameter& FPZ = Param(numsub,3); if (FPZ.ParamType() == Interface_ParamReal) Z = Interface_FileReaderData::Fastof(FPZ.CValue()); else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) Z not a Real"); } else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) has not 3 params"); } else errmess = new String("Parameter n0.%d (%s) : (X,Y,Z) not a SubList"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadReal //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadReal(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Real& val) const { Handle(String) errmess; // Null si pas d erreur if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamReal) val = Interface_FileReaderData::Fastof(FP.CValue()); else errmess = new String("Parameter n0.%d (%s) not a Real"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## //======================================================================= //function : ReadEntity //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, const Handle(Standard_Type)& atype, Handle(Standard_Transient)& ent) const { Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = Standard_False; if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); Standard_Integer nent = FP.EntityNumber(); if (FP.ParamType() == Interface_ParamIdent) { warn = (acceptvoid > 0); if (nent > 0) { Handle(Standard_Transient) entent = BoundEntity(nent); if (entent.IsNull() || !entent->IsKind(atype)) errmess = new String("Parameter n0.%d (%s) : Entity has illegal type"); else ent = entent; } else errmess = new String("Parameter n0.%d (%s) : Unresolved reference"); } else { if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True; errmess = new String("Parameter n0.%d (%s) not an Entity"); } } else { warn = (acceptvoid > 0); errmess = new String("Parameter n0.%d (%s) absent"); } if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning(txtmes,errmess->ToCString()); else ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadEntity //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadEntity(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, StepData_SelectType& sel) const { Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = Standard_False; if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); Standard_Integer nent = FP.EntityNumber(); if (FP.ParamType() == Interface_ParamIdent) { warn = (acceptvoid > 0); if (nent > 0) { Handle(Standard_Transient) entent = BoundEntity(nent); if (!sel.Matches(entent)) errmess = new String("Parameter n0.%d (%s) : Entity has illegal type"); else sel.SetValue(entent); } else errmess = new String("Parameter n0.%d (%s) : Unresolved reference"); } else if (FP.ParamType() == Interface_ParamVoid) { if (acceptvoid) warn = Standard_True; errmess = new String("Parameter n0.%d (%s) not an Entity"); } else { // Cas restant : on s interesse en fait au SelectMember ... Handle(Standard_Transient) sm = sel.NewMember(); // SelectMember qui assure ce role. Peut etre specialise if (!ReadAny (num,nump,mess,ach,sel.Description(),sm)) errmess = new String("Parameter n0.%d (%s) : could not be read"); if (!sel.Matches(sm)) errmess = new String("Parameter n0.%d (%s) : illegal parameter type"); else sel.SetValue(sm); } } else { warn = (acceptvoid > 0); errmess = new String("Parameter n0.%d (%s) absent"); } if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning(txtmes,errmess->ToCString()); else ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## //======================================================================= //function : ReadInteger //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadInteger(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Integer& val) const { Handle(String) errmess; // Null si pas d erreur if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamInteger) val = atoi(FP.CValue()); else errmess = new String("Parameter n0.%d (%s) not an Integer"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadBoolean //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadBoolean(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Boolean& flag) const { Handle(String) errmess; // Null si pas d erreur if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamEnum) { Standard_CString txt = FP.CValue(); if (!strcmp(txt,".T.")) flag = Standard_True; else if (!strcmp(txt,".F.")) flag = Standard_False; else errmess = new String("Parameter n0.%d (%s) : Incorrect Boolean Value"); } else errmess = new String("Parameter n0.%d (%s) not a Boolean"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadLogical //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadLogical(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, StepData_Logical& flag) const { Handle(String) errmess; // Null si pas d erreur if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamEnum) { Standard_CString txt = FP.CValue(); if (!strcmp(txt,".T.")) flag = StepData_LTrue; else if (!strcmp(txt,".F.")) flag = StepData_LFalse; else if (!strcmp(txt,".U.")) flag = StepData_LUnknown; else errmess = new String("Parameter n0.%d (%s) : Incorrect Logical Value"); } else errmess = new String("Parameter n0.%d (%s) not a Logical"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadString //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadString(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Handle(TCollection_HAsciiString)& val) const { Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = Standard_False; if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamText) { /*Standard_CString anStr = FP.CValue(); if(strlen(anStr) < 3) val = new TCollection_HAsciiString(""); else { val = new TCollection_HAsciiString(FP.CValue()); CleanText (val); }*/ val = new TCollection_HAsciiString(FP.CValue()); CleanText (val); } else { if (acceptvoid && FP.ParamType() == Interface_ParamVoid) warn = Standard_True; errmess = new String("Parameter n0.%d (%s) not a quoted String"); } } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning(txtmes,errmess->ToCString()); else ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadEnumParam //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadEnumParam(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_CString& text) const { Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = Standard_False; if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamEnum) { text = FP.CValue(); warn = (acceptvoid > 0); } else if (FP.ParamType() == Interface_ParamVoid) { errmess = new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed"); warn = (acceptvoid > 0); } else errmess = new String("Parameter n0.%d (%s) not an Enumeration"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning(txtmes,errmess->ToCString()); else ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : FailEnumValue //purpose : //======================================================================= void StepData_StepReaderData::FailEnumValue(const Standard_Integer /* num */, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach) const { Handle(String) errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value"); sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); } //======================================================================= //function : ReadEnum //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadEnum(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, const StepData_EnumTool& enumtool, Standard_Integer& val) const { // reprendre avec ReadEnumParam ? Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = Standard_False; if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() == Interface_ParamEnum) { val = enumtool.Value (FP.CValue()); if (val >= 0) return Standard_True; else errmess = new String("Parameter n0.%d (%s) : Incorrect Enumeration Value"); warn = (acceptvoid > 0); } else if (FP.ParamType() == Interface_ParamVoid) { val = enumtool.NullValue(); if (val < 0) errmess = new String("Parameter n0.%d (%s) : Undefined Enumeration not allowed"); warn = (acceptvoid > 0); } else errmess = new String("Parameter n0.%d (%s) not an Enumeration"); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning(txtmes,errmess->ToCString()); else ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : ReadTypedParam //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::ReadTypedParam(const Standard_Integer num, const Standard_Integer nump, const Standard_Boolean mustbetyped, const Standard_CString mess, Handle(Interface_Check)& ach, Standard_Integer& numr, Standard_Integer& numrp, TCollection_AsciiString& typ) const { Handle(String) errmess; // Null si pas d erreur if (nump > 0 && nump <= NbParams(num)) { const Interface_FileParameter& FP = Param(num,nump); if (FP.ParamType() != Interface_ParamSub) { // Pas une sous-liste : OK si admis numr = num; numrp = nump; typ.Clear(); if (mustbetyped) { errmess = new String("Parameter n0.%d (%s) : single, not typed"); sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } return Standard_True; } numr = FP.EntityNumber(); numrp = 1; if (NbParams(numr) != 1) errmess = new String("Parameter n0.%d (%s) : SubList, not typed"); typ = RecordType(numr); } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); ach->AddFail(txtmes,errmess->ToCString()); return Standard_False; } //======================================================================= //function : CheckDerived //purpose : //======================================================================= Standard_Boolean StepData_StepReaderData::CheckDerived(const Standard_Integer num, const Standard_Integer nump, const Standard_CString mess, Handle(Interface_Check)& ach, const Standard_Boolean errstat) const { Handle(String) errmess; // Null si pas d erreur Standard_Boolean warn = !errstat; if (nump > 0 && nump <= NbParams(num)) { if (!strcmp(Param(num,nump).CValue(),"*")) return Standard_True; else errmess = new String("Parameter n0.%d (%s) not Derived"); if (acceptvoid) warn = Standard_True; } else errmess = new String("Parameter n0.%d (%s) absent"); if (errmess.IsNull()) return Standard_True; sprintf (txtmes,errmess->ToCString(),nump,mess); if (warn) ach->AddWarning (txtmes,errmess->ToCString()); else ach->AddFail (txtmes,errmess->ToCString()); return Standard_False; } // ######################################################################### // .... Methodes specifiques (demandees par FileReaderData) .... // //======================================================================= //function : NbEntities //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::NbEntities () const // redefined { return thenbents; } //======================================================================= //function : FindNextRecord //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::FindNextRecord (const Standard_Integer num) const { // retourne, sur un numero d enregistrement donne (par num), le suivant qui // definit une entite, ou 0 si c est fini : // passe le Header (nbhend premiers records) et // saute les enregistrements SCOPE et ENDSCOPE et les SOUS-LISTES if (num < 0) return 0 ; Standard_Integer num1 = num + 1 ; if (num == 0) num1 = thenbhead + 1; Standard_Integer max = NbRecords() ; while (num1 <= max ) { if (theidents(num1) > 0) return num1; // SCOPE,ENDSCOPE et Sous-Liste ont un identifieur fictif: -1,-2 respectivement // et SUBLIST ont un negatif. Seule une vraie entite a un Ident positif num1 ++ ; } return 0; } //======================================================================= //function : FindEntityNumber //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::FindEntityNumber(const Standard_Integer num, const Standard_Integer id) const { // Soit un "Id" : recherche dans les Parametres de type Ident de , // si un d eux designe #Id justement. Si oui, retourne son EntityNumber if (num == 0) return 0; Standard_Integer nb = NbParams(num); for (Standard_Integer i = 1; i <= nb; i ++) { const Interface_FileParameter& FP = Param(num,i); if (FP.ParamType() != Interface_ParamIdent) continue; Standard_Integer ixp = atoi( &FP.CValue()[1] ); if (ixp == id) return FP.EntityNumber(); } return 0; // ici, pas trouve } // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // .... La fonction qui suit merite une attention speciale .... // Cette methode precharge les EntityNumbers dans les Params : ils designent // les Entites proprement dites dans la liste lue par BoundEntity // Interet : adresse de meme les sous-listes (Num->no record dans le Direc) // resultat exploite par ParamEntity et ParamNumber // En l absence de SCOPE, ou si les "ident" sont strictement ordonnes, a coup // sur ils ne sont pas dupliques, on peut utiliser une IndexedMap en toute // confiance. Sinon, il faut balayer dans le fichier, mais avec les SCOPES // cela va beaucoup plus vite (s ils sont assez gros) : on s y retrouve. // Pour la recherche par balayage, On opere en plusieurs etapes // Avant toute chose, le chargement a deja fait une preparation : les idents // (Entity, SubList) sont deja en entiers (rapidite de lecture), en particulier // dans les EntityNumber : ainsi, on lit cet ident, on le traite, et on remet // a la place un vrai numero de Record // // D abord, on passe le directory en table d entiers, sous-listes expurgees // en // , table inverse vers cette table, car les sous-listes peuvent par // contre designer des objets ... // Pour les sous-listes, on exploite leur mode de construction : elles sont // enregistrees AVANT d etre referencees. Un tableau "subn" note donc pour // chaque numero de sous-liste (relatif a une entite qui suit, et reference // par elle ou une autre sous-liste qui suit egalement), son n0 de record // REMARQUE : ceci marche aussi pour le Header, traite par l occasion //======================================================================= //function : SetEntityNumbers //purpose : //======================================================================= void StepData_StepReaderData::SetEntityNumbers(const Standard_Boolean withmap) { Handle(Message_Messenger) sout = Message::DefaultMessenger(); // Passe initiale : Resolution directe par Map // si tout passe (pas de collision), OK. Sinon, autres passes a prevoir // On resoud du meme coup les sous-listes Standard_Integer nbdirec = NbRecords() ; Standard_Integer *subn = new Standard_Integer[thelastn+1]; Standard_Boolean pbmap = Standard_False; // au moins un conflit Standard_Integer nbmap = 0; TColStd_IndexedMapOfInteger imap(thenbents); Standard_Integer *indm; // Index Map -> Record Number (seulement si map) indm = new Standard_Integer[nbdirec+1]; Standard_Integer num; // svv Jan11 2000 : porting on DEC for (num = 1 ; num <= nbdirec ; num ++) { Standard_Integer ident = theidents(num); if (ident > 0) { // Ident normal -> Map ? // Map : si Recouvrement, l inhiber. Sinon, noter index Standard_Integer indmap = imap.Add(ident); if (indmap <= nbmap) { indmap = imap.FindIndex(ident); // plus sur indm[indmap] = -1; // Map -> pb pbmap = Standard_True; // pbmap signifie qu une autre passe sera necessaire ... } else { nbmap = indmap; indm[indmap] = num; // Map ->ident } } } for (num = 1 ; num <= nbdirec ; num ++) { Standard_Integer ident = theidents(num); if (ident < -2) subn[-(ident+2)] = num; // toujours a jour ... Standard_Integer nba = NbParams(num) ; Standard_Integer nda = (num == 1 ? 0 : ParamFirstRank(num-1)); for (Standard_Integer na = nba ; na > 0 ; na --) { // On traite : les sous-listes (sf subn), les idents (si Map dit OK ...) Interface_FileParameter& FP = ChangeParameter (nda+na); // Interface_FileParameter& FP = ChangeParam (num,na); Interface_ParamType letype = FP.ParamType(); if (letype == Interface_ParamSub) { Standard_Integer numsub = FP.EntityNumber(); if (numsub > thelastn) { sout<<"Bad Sub.N0, Record "< 0) { // la map a trouve Standard_Integer num0 = indm[indmap]; if (num0 > 0) FP.SetEntityNumber(num0); // ET VOILA, on a resolu else FP.SetEntityNumber(-id); // CONFLIT -> faudra resoudre ... } else { // NON RESOLU, si pas pbmap, le dire FP.SetEntityNumber(-id); if (pbmap) continue; // pbmap : on se retrouvera char failmess[100]; // ... Construire le Check ... sprintf(failmess, "Unresolved Reference, Ent.Id.#%d Param.n0 %d (Id.#%d)", ident,na,id); thecheck->AddFail(failmess,"Unresolved Reference"); // ... Et sortir message un peu plus complet sout << "*** ERR StepReaderData *** Pour Entite #"<< ident << "\n Type:" << RecordType(num) << " Param.n0 " << na << ": #" << id << " Non trouve" << endl ; } // FIN Mapping } // FIN Traitement Reference } // FIN Boucle Parametres } // FIN Boucle Repertoires delete [] subn; if (!pbmap) { delete [] indm; return; } sout << " -- 2nd pass required --"; Standard_Integer nbseq = thenbents+2*thenbscop; Standard_Integer *inds = new Standard_Integer[nbseq+1]; // n0 Record/Entite Standard_Integer *indi = new Standard_Integer[nbseq+1]; // Idents/scopes Standard_Integer *indr = new Standard_Integer[nbdirec+1]; // inverse de nds Standard_Integer *indx = NULL; // pour EXPORT (silya) imap.Clear(); Standard_Boolean iamap = withmap; // (par defaut True) nbmap = 0; TColStd_SequenceOfInteger scopile; // chainage des scopes note par pile Standard_Integer nr = 0 ; for (num = 1 ; num <= nbdirec ; num ++) { Standard_Integer ident = theidents(num); if (ident < -2) { // SOUS-LISTE (cas le plus courant) indr[num] = nr + 1; // recherche basee sur nr (objet qui suit) } else if (ident >= 0) { // Ident normal nr ++; inds[nr] = num; indi[nr] = ident; indr[num] = nr; if (ident > 0) { // et non (iamap && ident > 0) // Map : si Recouvrement, l inhiber. Sinon, noter index Standard_Integer indmap = imap.Add(ident); if (indmap <= nbmap) { Standard_Boolean errorscope = Standard_False; indmap = imap.FindIndex(ident); // plus sur pbmap = Standard_True; if (thenbscop == 0) errorscope = Standard_True; // Numeros identiques alors quilnya pas de SCOPE ? ERREUR ! // (Bien sur, silya des SCOPES, on passe au travers, mais bon...) else { // Silya des SCOPES, tachons d y voir de plus pres pour signaler un probleme // Erreur si MEME groupe SCOPE // ATTENTION, on recherche, non dans tous les records, mais dans les records // CHAINES, cf nr et non num (pas de sous-liste, chainage scope-endscope) Standard_Integer fromscope = nr; Standard_Integer toscope = indm[indmap]; if (toscope < 0) toscope = -toscope; while (1) { fromscope --; // iteration de base if (fromscope <= toscope) { errorscope = Standard_True; // BANG, on est dessus break; } Standard_Integer idtest = indi[fromscope]; if (idtest >= 0) continue; // le suivant (enfin, le precedent) if (idtest == -1) break; // pas meme niveau, donc c est OK if (idtest == -3) { fromscope = inds[fromscope]; if (fromscope < toscope) break; // on sort, pas en meme niveau } } } if (errorscope) { // On est dedans : le signaler char ligne[80]; sprintf(ligne,"Ident defined SEVERAL TIMES : #%d",ident); thecheck->AddFail(ligne,"Ident defined SEVERAL TIMES : #%d"); sout << "StepReaderData:SetEntityNumbers, " << ligne << endl; } if (indm[indmap] > 0) indm[indmap] = -indm[indmap]; // Pas pour Map // Cas Normal pour la Map } else { nbmap = indmap; indm[indmap] = nr; // Map ->(indm)->inds } } } else if (ident == -1) { // SCOPE nr ++; inds[nr] = num; indi[nr] = -1; indr[num] = 0; scopile.Append(nr) ; } else if (ident == -2) { // ENDSCOPE Standard_Integer nscop = scopile.Last() ; // chainage SCOPE-ENDSCOPE scopile.Remove(scopile.Length()) ; nr ++; inds[nr] = nscop; indi[nr] = -3; indr[num] = 0; inds[nscop] = nr; if (NbParams(num) > 0) { // EXPORT : traitement special greffe sur celui de SCOPE (sans le perturber) if (!indx) { indx = new Standard_Integer[nbseq+1]; for (Standard_Integer ixp = 0; ixp <= nbseq; ixp ++) indx[ixp] = 0; } indx[nr] = num; indx[nscop] = num; } } else if (ident == 0) { // HEADER indr[num] = 0; } } // .. Resolution des EXPORT, silyena et silya besoin .. // Pour chaque valeur de EXPORT qui n a pas ete resolue par la MAP, // determiner sa position locale par recherche en arriere depuis ENDSCOPE if ((!iamap || pbmap) && indx) { for (nr = 0; nr <= nbseq; nr ++) { if (indx[nr] == 0 && indi[nr] != -3) continue; // ENDSCOPE + EXPORT num = indx[nr]; Standard_Integer nba = NbParams(num); for (Standard_Integer na = 1; na <= nba; na ++) { Interface_FileParameter& FP = ChangeParam (num,na); if (FP.ParamType() != Interface_ParamIdent) continue; Standard_Integer id = - FP.EntityNumber(); if (id < 0) continue; // deja resolu en tete /* if (imap.Contains(id)) { et voila FP.SetEntityNumber(indm[imap.FindIndex(id)]); continue; } */ // Recherche du Id demande : si EXPORT imbrique, deja resolu mais il faut // regarder ! (inutile par contre d aller y voir : c est deja fait, car // un EXPORT imbrique a ete traite AVANT celui qui imbrique) Standard_Integer n0 = nr-1 ; if (indi[n0] == -3) n0 --; // si on suit juste un ENDSCOPE while (n0 > 0) { Standard_Integer irec = indi[n0]; if (irec == id) { // trouve FP.SetEntityNumber(inds[n0]); break ; } if (irec == -1) break; // SCOPE : fin de ce SCOPE/ENDSCOPE if (irec == -3) { // gare a EXPORT : si un EXPORT detient Id, noter son Numero deja calcule // Attention : Id a lire depuis CValue car EntityNumber deja resolu Standard_Integer nok = FindEntityNumber (indx[n0],id); if (nok > 0) { FP.SetEntityNumber(nok); break; } n0 = inds[n0]; // ENDSCOPE ou EXPORT infructueux : le sauter } // fin traitement sur un ENDSCOPE ou EXPORT n0 -- ; } // fin resolution d un Parametre EXPORT } // fin resolution de la liste d un EXPORT } // fin bouclage sur les EXPORT } // Exploitation de la table : bouclage porte sur la table // Traitement des sous-listes : se fait dans la foulee, par gestion d une pile // basee sur la constitution des sous-listes Standard_Integer maxsubpil = 30; // pile simulee avec un Array : tres fort Handle(TColStd_HArray1OfInteger) subpile = // ... gagne de la memoire ... new TColStd_HArray1OfInteger (1,maxsubpil); Standard_Integer nbsubpil = 0; // ... et tellement plus rapide ! for (num = 1 ; num <= nbdirec ; num ++) { nr = indr[num]; if (nr == 0) continue; // pas un objet ou une sous-liste Standard_Integer nba = NbParams(num) ; for (Standard_Integer na = nba ; na > 0 ; na --) { // On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee // Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite Interface_FileParameter& FP = ChangeParam (num,na); Interface_ParamType letype = FP.ParamType(); if (letype == Interface_ParamSub) { // parametre type sous-liste : numero de la sous-liste lu par depilement FP.SetEntityNumber(subpile->Value(nbsubpil)); nbsubpil --; // subpile->Remove(nbsubpil); } else if (letype == Interface_ParamIdent) { // parametre type ident (reference une entite) : chercher ident demande Standard_Integer id = - FP.EntityNumber(); if (id < 0) continue; // deja resolu en tete // Voila : on va chercher id dans ndi; algorithme de balayage Standard_Integer pass, sens, nok, n0,irec; pass = sens = nok = 0; if (!iamap) pass = 1; // si map non disponible while (pass < 3) { pass ++ ; // MAP disponible if (pass == 1) { // MAP DISPONIBLE Standard_Integer indmap = imap.FindIndex(id); if (indmap > 0) { // la map a trouve nok = indm[indmap]; if (nok < 0) continue; // CONFLIT -> faut resoudre ... break; } else continue; } // 1re Passe : REMONTEE -> Debut fichier if (sens == 0 && nr > 1) { n0 = nr-1 ; if (indi[n0] == -3) n0 --; // si on suit juste un ENDSCOPE while (n0 > 0) { irec = indi[n0]; if (irec == id) { // trouve nok = n0 ; break ; } // ENDSCOPE : Attention a EXPORT sinon sauter if (irec == -3) { if (!indx) n0 = inds[n0]; else { // EXPORT, il faut regarder nok = FindEntityNumber (indx[n0],id); if (nok > 0) break; n0 = inds[n0]; // ENDSCOPE : le sauter } } n0 -- ; } // 2me Passe : DESCENTE -> Fin fichier } else if (nr < nbseq) { // descente -> fin fichier n0 = nr+1 ; while (n0 <= nbseq) { irec = indi[n0]; if (irec == id) { // trouve nok = n0 ; break ; } // SCOPE : Attention a EXPORT sinon sauter if (irec == -1) { if (!indx) n0 = inds[n0]; else { // EXPORT, il faut regarder nok = FindEntityNumber (indx[n0],id); if (nok > 0) break; n0 = inds[n0]; // SCOPE : le sauter } } n0 ++ ; } } if (nok > 0) break ; sens = 1 - sens ; // passe suivante } // ici on a nok, numero trouve if (nok > 0) { Standard_Integer num0 = inds[nok]; FP.SetEntityNumber(num0); // ET VOILA, on a resolu // pas trouve : le signaler } else { // Alimenter le Check ... Pour cela, determiner n0 Entite et Ident char failmess[100]; Standard_Integer nument = 0; Standard_Integer n0ent; // svv Jan11 2000 : porting on DEC for (n0ent = 1; n0ent <= nr; n0ent ++) { if (indi[n0ent] > 0) nument ++; } Standard_Integer ident = RecordIdent(num); if (ident < 0) { for (n0ent = num + 1; n0ent <= nbdirec; n0ent ++) { ident = RecordIdent(n0ent); if (ident > 0) break; } } // ... Construire le Check ... sprintf(failmess, "Unresolved Reference, Ent.n0 %d (Id.#%d) Param.n0 %d (Id.#%d)", nument,ident,na,id); thecheck->AddFail(failmess,"Unresolved Reference"); // ... Et sortir message un peu plus complet sout << "*** ERR StepReaderData *** Pour Entite "< Reference non resolue } } } // Si ce record est lui-meme une sous-liste, empiler ! if (inds[nr] != num) { if (nbsubpil >= maxsubpil) { maxsubpil = maxsubpil+30; Handle(TColStd_HArray1OfInteger) newsubpil = new TColStd_HArray1OfInteger (1,maxsubpil); for (Standard_Integer bidpil = 1; bidpil <= maxsubpil - 30; bidpil ++) newsubpil->SetValue(bidpil,subpile->Value(bidpil)); subpile = newsubpil; } nbsubpil ++; subpile->SetValue(nbsubpil,num); // Append(num); } } delete [] inds; delete [] indi; delete [] indr; delete [] indm; // subpile->Detroy(); if (indx) delete [] indx; } // ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## // .... Gestion du Header : Preparation, lecture .... //======================================================================= //function : FindNextHeaderRecord //purpose : //======================================================================= Standard_Integer StepData_StepReaderData::FindNextHeaderRecord (const Standard_Integer num) const { // retourne, sur un numero d enregistrement donne (par num), le suivant qui // definit une entite, ou 0 si c est fini : // Opere comme FindNextRecord mais ne balaie que le Header if (num < 0) return 0 ; Standard_Integer num1 = num + 1 ; Standard_Integer max = thenbhead; while (num1 <= max ) { // SCOPE,ENDSCOPE et Sous-Liste ont un identifieur negatif // Ne retenir que les Idents positifs ou nuls (nul : pas d Ident dans Header) if ( RecordIdent(num1) >= 0) return num1 ; num1 ++ ; } return 0; } //======================================================================= //function : PrepareHeader //purpose : //======================================================================= void StepData_StepReaderData::PrepareHeader () { // Resolution des references : ne concerne que les sous-listes // deja faite par SetEntityNumbers donc pas de souci a se faire /* // Algorithme repris et adapte de SetEntityNumbers // Traitement des sous-listes : se fait dans la foulee, par gestion d une pile // basee sur la constitution des sous-listes TColStd_SequenceOfInteger subpile; Standard_Integer nbsubpil = 0; // profondeur de pile mais plus rapide ... for (Standard_Integer num = 1 ; num <= thenbhead ; num ++) { Standard_Integer nba = NbParams(num) ; for (Standard_Integer na = nba ; na > 0 ; na --) { .. On lit depuis la fin : cela permet de traiter les sous-listes dans la foulee .. Sinon, on devrait noter qu il y a eu des sous-listes et reprendre ensuite Interface_FileParameter& FP = ChangeParam(num,na); Interface_ParamType letype = FP.ParamType(); if (letype == Interface_ParamSub) { .. parametre type sous-liste : numero de la sous-liste lu par depilement FP.SetEntityNumber(subpile.Last()); .. .. SetParam(num,na,FP); subpile.Remove(nbsubpil); nbsubpil --; } } .. Si c est une sous-liste, empiler if (RecordIdent(num) < -2) { subpile.Append(num); nbsubpil ++; } } */ } //======================================================================= //function : GlobalCheck //purpose : //======================================================================= const Handle(Interface_Check) StepData_StepReaderData::GlobalCheck () const { return thecheck; }