Skip to content

Commit 736b1ba

Browse files
committed
some simplification and better handling of an edge case in writeFile
1 parent 1c7ed5a commit 736b1ba

File tree

2 files changed

+30
-33
lines changed

2 files changed

+30
-33
lines changed

Cifti/CiftiFile.cxx

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,27 @@ void CiftiFile::writeFile(const QString& fileName, const CiftiVersion& writingVe
107107
if (m_readingImpl == NULL || m_dims.empty()) throw CiftiException("writeFile called on uninitialized CiftiFile");
108108
QFileInfo myInfo(fileName);
109109
QString canonicalFilename = myInfo.canonicalFilePath();//NOTE: returns EMPTY STRING for nonexistant file
110+
shared_ptr<ReadImplInterface> tempRead = m_readingImpl;
110111
const CiftiOnDiskImpl* testImpl = dynamic_cast<CiftiOnDiskImpl*>(m_readingImpl.get());
111112
bool collision = false;
112113
if (testImpl != NULL && canonicalFilename != "" && QFileInfo(testImpl->getFilename()).canonicalFilePath() == canonicalFilename)
113-
{
114-
collision = true;//empty string test is so that we don't say collision if both are nonexistant - could happen if file is removed/unlinked while reading on some filesystems
115-
}
116-
if (collision)
117-
{
114+
{//empty string test is so that we don't say collision if both are nonexistant - could happen if file is removed/unlinked while reading on some filesystems
118115
if (m_writingVersion == writingVersion) return;//don't need to copy to itself
119-
convertToInMemory();//otherwise, we need to preserve the contents first - if writing fails, we will end up with it converted to in-memory, but oh well
120-
}
121-
shared_ptr<WriteImplInterface> tempWrite(new CiftiOnDiskImpl(myInfo.absoluteFilePath(), m_xml, writingVersion));
122-
vector<int64_t> iterateDims(m_dims.begin() + 1, m_dims.end());//above constructor creates new file in read/write mode
123-
vector<float> scratchRow(m_dims[0]);
124-
for (MultiDimIterator<int64_t> iter(iterateDims); !iter.atEnd(); ++iter)
125-
{
126-
m_readingImpl->getRow(scratchRow.data(), *iter, false);
127-
tempWrite->setRow(scratchRow.data(), *iter);
116+
collision = true;//we need to copy to memory temporarily
117+
shared_ptr<WriteImplInterface> tempMemory(new CiftiMemoryImpl(m_xml));//because tempRead is a ReadImpl, can't be used to copy to
118+
copyImplData(m_readingImpl.get(), tempMemory.get(), m_dims);
119+
tempRead = tempMemory;//set it to read from the memory rather than m_readingImpl
128120
}
129-
if (collision)//drop the in-memory representation afterwards
121+
shared_ptr<WriteImplInterface> tempWrite(new CiftiOnDiskImpl(myInfo.absoluteFilePath(), m_xml, writingVersion));//NOTE: this makes m_readingImpl/m_writingImpl unusable if collision is true!
122+
copyImplData(tempRead.get(), tempWrite.get(), m_dims);
123+
if (collision)//if we rewrote the file, we need the handle to the new file, the old one has the wrong version and vox_offset in it
130124
{
131125
m_writingVersion = writingVersion;//also record the current version number
132-
m_writingImpl = tempWrite;
133-
m_readingImpl = tempWrite;
126+
if (m_writingImpl != NULL)//NULL can happen if setWritingFile is called with a name other than the current file, then writeFile is called with the same name as current file but different version
127+
{
128+
m_writingImpl = tempWrite;//replace the now-unusable old file implementation
129+
}
130+
m_readingImpl = tempWrite;//replace the now-unusable old file implementation
134131
}
135132
}
136133

@@ -142,19 +139,13 @@ void CiftiFile::writeFile(const QString& fileName)
142139
void CiftiFile::convertToInMemory()
143140
{
144141
if (isInMemory()) return;
145-
if (m_readingImpl == NULL || m_dims.empty())//not set up yet
142+
if (m_readingImpl == NULL || m_dims.empty())//not set up yet
146143
{
147144
m_writingFile = "";//make sure it doesn't do on-disk when set...() is called
148145
return;
149146
}
150-
shared_ptr<WriteImplInterface> tempWrite(new CiftiMemoryImpl(m_xml));//if we get an error while reading, free the memory immediately
151-
vector<int64_t> iterateDims(m_dims.begin() + 1, m_dims.end());
152-
vector<float> scratchRow(m_dims[0]);
153-
for (MultiDimIterator<int64_t> iter(iterateDims); !iter.atEnd(); ++iter)
154-
{
155-
m_readingImpl->getRow(scratchRow.data(), *iter, false);
156-
tempWrite->setRow(scratchRow.data(), *iter);
157-
}
147+
shared_ptr<WriteImplInterface> tempWrite(new CiftiMemoryImpl(m_xml));//if we get an error while reading, free the memory immediately, and don't leave m_readingImpl and m_writingImpl pointing to different things
148+
copyImplData(m_readingImpl.get(), tempWrite.get(), m_dims);
158149
m_writingImpl = tempWrite;
159150
m_readingImpl = tempWrite;
160151
}
@@ -267,18 +258,23 @@ void CiftiFile::verifyWriteImpl()
267258
m_writingImpl = shared_ptr<CiftiOnDiskImpl>(new CiftiOnDiskImpl(m_writingFile, m_xml, m_writingVersion));//this constructor makes new file for writing
268259
if (m_readingImpl != NULL)
269260
{
270-
vector<int64_t> iterateDims(m_dims.begin() + 1, m_dims.end());
271-
vector<float> scratchRow(m_dims[0]);
272-
for (MultiDimIterator<int64_t> iter(iterateDims); !iter.atEnd(); ++iter)
273-
{
274-
m_readingImpl->getRow(scratchRow.data(), *iter, false);
275-
m_writingImpl->setRow(scratchRow.data(), *iter);
276-
}
261+
copyImplData(m_readingImpl.get(), m_writingImpl.get(), m_dims);
277262
}
278263
}
279264
m_readingImpl = m_writingImpl;//read-only implementations are set up in specialized functions
280265
}
281266

267+
void CiftiFile::copyImplData(const ReadImplInterface* from, WriteImplInterface* to, const vector<int64_t>& dims)
268+
{
269+
vector<int64_t> iterateDims(dims.begin() + 1, dims.end());
270+
vector<float> scratchRow(dims[0]);
271+
for (MultiDimIterator<int64_t> iter(iterateDims); !iter.atEnd(); ++iter)
272+
{
273+
from->getRow(scratchRow.data(), *iter, false);
274+
to->setRow(scratchRow.data(), *iter);
275+
}
276+
}
277+
282278
CiftiMemoryImpl::CiftiMemoryImpl(const CiftiXML& xml)
283279
{
284280
CaretAssert(xml.getNumberOfDimensions() != 0);

Cifti/CiftiFile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ namespace cifti
8787
CiftiXML m_xml;
8888
CiftiVersion m_writingVersion;
8989
void verifyWriteImpl();
90+
static void copyImplData(const ReadImplInterface* from, WriteImplInterface* to, const std::vector<int64_t>& dims);
9091
};
9192

9293
}

0 commit comments

Comments
 (0)