0027772: Foundation Classes - define Standard_Boolean using C++ type "bool" instead...
[occt.git] / src / RWStl / RWStl.cxx
index 4346f27..d574f34 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <RWStl.ixx>
-#include <OSD_Protection.hxx>
-#include <OSD_File.hxx>
+
+#include <BRepBuilderAPI_CellFilter.hxx>
+#include <BRepBuilderAPI_VertexInspector.hxx>
+#include <gp.hxx>
+#include <gp_Vec.hxx>
+#include <gp_XYZ.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <Message_ProgressIndicator.hxx>
 #include <Message_ProgressSentry.hxx>
-#include <TCollection_AsciiString.hxx>
+#include <OSD.hxx>
+#include <OSD_File.hxx>
+#include <OSD_Host.hxx>
+#include <OSD_OpenFile.hxx>
+#include <OSD_Path.hxx>
+#include <OSD_Protection.hxx>
+#include <Precision.hxx>
+#include <RWStl.hxx>
 #include <Standard_NoMoreObject.hxx>
 #include <Standard_TypeMismatch.hxx>
-#include <Precision.hxx>
+#include <StlMesh_Mesh.hxx>
 #include <StlMesh_MeshExplorer.hxx>
-#include <OSD.hxx>
-#include <OSD_Host.hxx>
-#include <gp_XYZ.hxx>
-#include <gp.hxx>
-#include <stdio.h>
-#include <gp_Vec.hxx>
-
-#include <BRepBuilderAPI_CellFilter.hxx>
-#include <BRepBuilderAPI_VertexInspector.hxx>
+#include <TCollection_AsciiString.hxx>
 
+#include <stdio.h>
 // A static method adding nodes to a mesh and keeping coincident (sharing) nodes.
 static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
                                   BRepBuilderAPI_CellFilter& filter, 
@@ -62,7 +68,6 @@ static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
 // constants
 static const size_t HEADER_SIZE           =  84;
 static const size_t SIZEOF_STL_FACET      =  50;
-static const size_t STL_MIN_FILE_SIZE     = 284;
 static const size_t ASCII_LINES_PER_FACET =   7;
 
 static const int IND_THRESHOLD = 1000; // increment the indicator every 1k triangles
@@ -124,8 +129,8 @@ inline static void WriteDouble2Float(OSD_File& ofile,Standard_Real value)
 inline static Standard_Real ReadFloat2Double(OSD_File &aFile)
 {
   union {
-    Standard_Boolean i; // don't be afraid, this is just an unsigned int
-    Standard_ShortReal f;
+    uint32_t i;
+    float    f;
   }bidargum;
 
   char c[4];
@@ -334,7 +339,7 @@ Handle(StlMesh_Mesh) RWStl::ReadFile (const OSD_Path& thePath,
       IsAscii = Standard_False;
     }
   }
-#ifdef RWSTL_DEB
+#ifdef OCCT_DEBUG
   cout << (IsAscii ? "ascii\n" : "binary\n");
 #endif
   file.Close();
@@ -352,7 +357,6 @@ Handle(StlMesh_Mesh) RWStl::ReadFile (const OSD_Path& thePath,
 Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
                                        const Handle(Message_ProgressIndicator)& /*theProgInd*/)
 {
-  Standard_Integer NBFACET;
   Standard_Integer ifacet;
   Standard_Real fx,fy,fz,fx1,fy1,fz1,fx2,fy2,fz2,fx3,fy3,fz3;
   Standard_Integer i1,i2,i3,lread;
@@ -370,14 +374,34 @@ Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
   // compute file size
   Standard_Size filesize = theFile.Size();
 
-  if ( (filesize - HEADER_SIZE) % SIZEOF_STL_FACET !=0
-       || (filesize < STL_MIN_FILE_SIZE)) {
+  // don't trust the number of triangles which is coded in the file sometimes it is wrong
+  Standard_Integer NBFACET = (Standard_Integer)((filesize - HEADER_SIZE) / SIZEOF_STL_FACET);
+  if (NBFACET < 1)
+  {
     Standard_NoMoreObject::Raise("RWStl::ReadBinary (wrong file size)");
   }
 
-  // don't trust the number of triangles which is coded in the file
-  // sometimes it is wrong, and with this technique we don't need to swap endians for integer
-  NBFACET = (Standard_Integer)((filesize - HEADER_SIZE) / SIZEOF_STL_FACET);
+  theFile.Seek (80, OSD_FromBeginning);
+  theFile.Read (adr, 4, lread);
+  Standard_Integer aNbTrisInHeader = (((char*           )buftest)[3] << 24) | (((Standard_Byte* )buftest)[2] << 16)
+                                    | (((Standard_Byte* )buftest)[1] << 8 ) | (((Standard_Byte* )buftest)[0] << 0 );
+  if (NBFACET < aNbTrisInHeader)
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines more triangles (") + aNbTrisInHeader
+                                     + ") that can be read (" + NBFACET + ") - probably corrupted file",
+                                       Message_Warning);
+  }
+  else if (NBFACET > aNbTrisInHeader)
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file defines less triangles (") + aNbTrisInHeader
+                                     + ") that can be read (" + NBFACET + ") - probably corrupted file",
+                                       Message_Warning);
+  }
+  else if ((filesize - HEADER_SIZE) % SIZEOF_STL_FACET != 0)
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString ("RWStl - Binary STL file has unidentified tail"),
+                                       Message_Warning);
+  }
 
   // skip the header
   theFile.Seek(HEADER_SIZE,OSD_FromBeginning);
@@ -447,14 +471,13 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
   thePath.SystemName (filename);
 
   // Open the file
-  FILE* file = fopen(filename.ToCString(),"r");
+  FILE* file = OSD_OpenFile(filename.ToCString(),"r");
 
   fseek(file,0L,SEEK_END);
 
   long filesize = ftell(file);
 
-  fclose(file);
-  file = fopen(filename.ToCString(),"r");
+  rewind(file);
 
   // count the number of lines
   for (ipos = 0; ipos < filesize; ++ipos) {
@@ -466,13 +489,11 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
   nbTris = (nbLines / ASCII_LINES_PER_FACET);
 
   // go back to the beginning of the file
-//  fclose(file);
-//  file = fopen(filename.ToCString(),"r");
   rewind(file);
 
   // skip header
   while (getc(file) != '\n');
-#ifdef RWSTL_DEB
+#ifdef OCCT_DEBUG
   cout << "start mesh\n";
 #endif
   ReadMesh = new StlMesh_Mesh();
@@ -494,7 +515,8 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
     gp_XYZ aN (Atof(x), Atof(y), Atof(z));
 
     // skip the keywords "outer loop"
-    fscanf(file,"%*s %*s");
+    if (fscanf(file,"%*s %*s") < 0)
+      break;
 
     // reading vertex
     if (3 != fscanf(file,"%*s %80s %80s %80s\n", x, y, z))
@@ -515,16 +537,18 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
     ReadMesh->AddTriangle (i1, i2, i3, aN.X(), aN.Y(), aN.Z());
 
     // skip the keywords "endloop"
-    fscanf(file,"%*s");
+    if (fscanf(file,"%*s") < 0)
+      break;
 
     // skip the keywords "endfacet"
-    fscanf(file,"%*s");
+    if (fscanf(file,"%*s") < 0)
+      break;
 
     // update progress only per 1k triangles
     if (++iTri % IND_THRESHOLD == 0)
       aPS.Next();
   }
-#ifdef RWSTL_DEB
+#ifdef OCCT_DEBUG
   cout << "end mesh\n";
 #endif
   fclose(file);