Skip to content

Commit b61a5e5

Browse files
committed
BUG: Remove m_InputFile from OFFMeshIO, use RAII for input file
Fixed exception safety problems by using local `inputFile` variables, instead of a `m_InputFile` member variable. Initialized these variables by `MeshIOBase::OpenInputFile()`. Removed the old OpenFile() and CloseFile() member functions. Added `m_CellsStartPosition` for `OFFMeshIO::ReadCells` to start reading from the right position, after reopening the input file. Follow-up to pull request InsightSoftwareConsortium#5964 commit f9a6f13 "BUG: Remove m_InputFile and CloseFile from OBJMeshIO, use RAII for file"
1 parent ab54e82 commit b61a5e5

2 files changed

Lines changed: 37 additions & 65 deletions

File tree

Modules/IO/MeshOFF/include/itkOFFMeshIO.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,9 @@ class ITKIOMeshOFF_EXPORT OFFMeshIO : public MeshIOBase
196196
void
197197
PrintSelf(std::ostream & os, Indent indent) const override;
198198

199-
void
200-
OpenFile();
201-
202-
void
203-
CloseFile();
204-
205199
private:
206-
std::ifstream m_InputFile{};
207200
StreamOffsetType m_PointsStartPosition{}; // file position for points relative to std::ios::beg
201+
StreamOffsetType m_CellsStartPosition{}; // file position for cells relative to std::ios::beg
208202
bool m_TriangleCellType{}; // if all cells are triangle it is true. otherwise, it is false.
209203
};
210204
} // end namespace itk

Modules/IO/MeshOFF/src/itkOFFMeshIO.cxx

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -60,51 +60,17 @@ OFFMeshIO::CanWriteFile(const char * fileName)
6060
return true;
6161
}
6262

63-
void
64-
OFFMeshIO::OpenFile()
65-
{
66-
if (this->m_FileName.empty())
67-
{
68-
itkExceptionStringMacro("No input FileName");
69-
}
70-
71-
if (!itksys::SystemTools::FileExists(m_FileName.c_str()))
72-
{
73-
itkExceptionMacro("File " << this->m_FileName << " does not exist");
74-
}
75-
76-
// Read file as ascii
77-
// Due to the windows doesn't work well for tellg() and seekg() for ASCII mode, hence we
78-
// open the file with std::ios::binary
79-
m_InputFile.open(this->m_FileName.c_str(), std::ios_base::in | std::ios::binary);
80-
81-
// Test whether the file was opened
82-
if (!m_InputFile.is_open())
83-
{
84-
itkExceptionMacro("Unable to open file " << this->m_FileName);
85-
}
86-
}
87-
88-
void
89-
OFFMeshIO::CloseFile()
90-
{
91-
if (m_InputFile.is_open())
92-
{
93-
m_InputFile.close();
94-
}
95-
}
96-
9763
void
9864
OFFMeshIO::ReadMeshInformation()
9965
{
10066
// Define input file stream and attach it to input file
101-
OpenFile();
67+
std::ifstream inputFile = MeshIOBase::OpenInputFile();
10268

10369
// Read and analyze the first line in the file
10470
std::string line;
10571

10672
// The OFF file must contain "OFF"
107-
std::getline(m_InputFile, line, '\n'); // delimiter is '\n'
73+
std::getline(inputFile, line, '\n'); // delimiter is '\n'
10874
if (line.find("OFF") == std::string::npos)
10975
{
11076
itkExceptionStringMacro("Error, the file doesn't begin with keyword \"OFF\" ");
@@ -123,7 +89,7 @@ OFFMeshIO::ReadMeshInformation()
12389
// Read and Set point dimension
12490
if (line.find("nOFF") != std::string::npos)
12591
{
126-
m_InputFile >> this->m_PointDimension;
92+
inputFile >> this->m_PointDimension;
12793
++m_PointDimension;
12894
}
12995
else if (line.find("4OFF") != std::string::npos)
@@ -136,10 +102,10 @@ OFFMeshIO::ReadMeshInformation()
136102
}
137103

138104
// Ignore comment lines
139-
std::getline(m_InputFile, line, '\n');
105+
std::getline(inputFile, line, '\n');
140106
while (line.find('#') != std::string::npos)
141107
{
142-
std::getline(m_InputFile, line, '\n');
108+
std::getline(inputFile, line, '\n');
143109
}
144110

145111
// Read points and cells information
@@ -160,13 +126,16 @@ OFFMeshIO::ReadMeshInformation()
160126
ss >> numberOfEdges;
161127

162128
// Read points start position in the file
163-
m_PointsStartPosition = m_InputFile.tellg();
129+
m_PointsStartPosition = inputFile.tellg();
164130

165131
for (SizeValueType id = 0; id < this->m_NumberOfPoints; ++id)
166132
{
167-
std::getline(m_InputFile, line, '\n');
133+
std::getline(inputFile, line, '\n');
168134
}
169135

136+
// Read cells start position in the file
137+
m_CellsStartPosition = inputFile.tellg();
138+
170139
// Set default cell component type
171140
this->m_CellBufferSize = this->m_NumberOfCells * 2;
172141

@@ -176,9 +145,9 @@ OFFMeshIO::ReadMeshInformation()
176145
unsigned int numberOfCellPoints = 0;
177146
for (SizeValueType id = 0; id < this->m_NumberOfCells; ++id)
178147
{
179-
m_InputFile >> numberOfCellPoints;
148+
inputFile >> numberOfCellPoints;
180149
this->m_CellBufferSize += numberOfCellPoints;
181-
std::getline(m_InputFile, line, '\n');
150+
std::getline(inputFile, line, '\n');
182151

183152
if (numberOfCellPoints != 3)
184153
{
@@ -191,27 +160,30 @@ OFFMeshIO::ReadMeshInformation()
191160
{
192161
// Read the number of points
193162
itk::uint32_t numberOfPoints = 0;
194-
this->ReadBufferAsBinary(&numberOfPoints, m_InputFile, 1);
163+
this->ReadBufferAsBinary(&numberOfPoints, inputFile, 1);
195164
this->m_NumberOfPoints = numberOfPoints;
196165

197166
// Read the number of cells
198167
itk::uint32_t numberOfCells = 0;
199-
this->ReadBufferAsBinary(&numberOfCells, m_InputFile, 1);
168+
this->ReadBufferAsBinary(&numberOfCells, inputFile, 1);
200169
this->m_NumberOfCells = numberOfCells;
201170

202171
// Read number of edges
203172
itk::uint32_t numberOfEdges = 0;
204-
this->ReadBufferAsBinary(&numberOfEdges, m_InputFile, 1);
173+
this->ReadBufferAsBinary(&numberOfEdges, inputFile, 1);
205174

206175
// Get points start position
207-
m_PointsStartPosition = m_InputFile.tellg();
176+
m_PointsStartPosition = inputFile.tellg();
208177

209178
// Read points
210179
const auto numberOfCoordinates = this->m_NumberOfPoints * this->m_PointDimension;
211180
this->ReadBufferAsBinary(make_unique_for_overwrite<float[]>(numberOfCoordinates).get(),
212-
m_InputFile,
181+
inputFile,
213182
this->m_NumberOfPoints * this->m_PointDimension);
214183

184+
// Read cells start position in the file
185+
m_CellsStartPosition = inputFile.tellg();
186+
215187
// Set default cell component type
216188
this->m_CellBufferSize = this->m_NumberOfCells * 2;
217189

@@ -220,9 +192,9 @@ OFFMeshIO::ReadMeshInformation()
220192
const auto cellsBuffer = make_unique_for_overwrite<itk::uint32_t[]>(this->m_NumberOfCells);
221193
for (unsigned long id = 0; id < this->m_NumberOfCells; ++id)
222194
{
223-
this->ReadBufferAsBinary(&numberOfCellPoints, m_InputFile, 1);
195+
this->ReadBufferAsBinary(&numberOfCellPoints, inputFile, 1);
224196
this->m_CellBufferSize += numberOfCellPoints;
225-
this->ReadBufferAsBinary(cellsBuffer.get(), m_InputFile, numberOfCellPoints);
197+
this->ReadBufferAsBinary(cellsBuffer.get(), inputFile, numberOfCellPoints);
226198
if (numberOfCellPoints != 3)
227199
{
228200
m_TriangleCellType = false;
@@ -264,18 +236,20 @@ OFFMeshIO::ReadMeshInformation()
264236
void
265237
OFFMeshIO::ReadPoints(void * buffer)
266238
{
239+
// Define input file stream and attach it to input file
240+
std::ifstream inputFile = MeshIOBase::OpenInputFile();
241+
267242
// Set file position to points start position
268-
m_InputFile.seekg(m_PointsStartPosition, std::ios::beg);
243+
inputFile.seekg(m_PointsStartPosition, std::ios::beg);
269244

270245
// Read file according to ASCII or BINARY
271246
if (this->m_FileType == IOFileEnum::ASCII)
272247
{
273-
this->ReadBufferAsAscii(static_cast<float *>(buffer), m_InputFile, this->m_NumberOfPoints * this->m_PointDimension);
248+
this->ReadBufferAsAscii(static_cast<float *>(buffer), inputFile, this->m_NumberOfPoints * this->m_PointDimension);
274249
}
275250
else if (this->m_FileType == IOFileEnum::BINARY)
276251
{
277-
this->ReadBufferAsBinary(
278-
static_cast<float *>(buffer), m_InputFile, this->m_NumberOfPoints * this->m_PointDimension);
252+
this->ReadBufferAsBinary(static_cast<float *>(buffer), inputFile, this->m_NumberOfPoints * this->m_PointDimension);
279253
}
280254
else
281255
{
@@ -286,23 +260,27 @@ OFFMeshIO::ReadPoints(void * buffer)
286260
void
287261
OFFMeshIO::ReadCells(void * buffer)
288262
{
263+
// Define input file stream and attach it to input file
264+
std::ifstream inputFile = MeshIOBase::OpenInputFile();
265+
266+
// Set file position to cells start position
267+
inputFile.seekg(m_CellsStartPosition, std::ios::beg);
268+
289269
const auto data = make_unique_for_overwrite<itk::uint32_t[]>(this->m_CellBufferSize - this->m_NumberOfCells);
290270

291271
if (this->m_FileType == IOFileEnum::ASCII)
292272
{
293-
this->ReadCellsBufferAsAscii(data.get(), m_InputFile);
273+
this->ReadCellsBufferAsAscii(data.get(), inputFile);
294274
}
295275
else if (this->m_FileType == IOFileEnum::BINARY)
296276
{
297-
this->ReadBufferAsBinary(data.get(), m_InputFile, this->m_CellBufferSize - this->m_NumberOfCells);
277+
this->ReadBufferAsBinary(data.get(), inputFile, this->m_CellBufferSize - this->m_NumberOfCells);
298278
}
299279
else
300280
{
301281
itkExceptionStringMacro("Invalid file type (not ASCII or BINARY)");
302282
}
303283

304-
CloseFile();
305-
306284
if (m_TriangleCellType)
307285
{
308286
this->WriteCellsBuffer(

0 commit comments

Comments
 (0)