Part: refactor PropertyPartShape::SaveDocFile and PropertyPartShape::RestoreDocFile

Set exception mask of std::istream::failbit | std::istream::badbit to istream to make sure it raises an exception for corrupted input files.
See: https://forum.freecadweb.org/viewtopic.php?p=536747
This commit is contained in:
wmayer
2022-03-11 22:06:38 +01:00
parent cb5334a98c
commit ec8353ba99
3 changed files with 115 additions and 86 deletions

View File

@@ -276,6 +276,102 @@ static Standard_Boolean BRepTools_Write(const TopoDS_Shape& Sh, const Standard_
return isGood;
}
void PropertyPartShape::saveToFile(Base::Writer &writer) const
{
// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(App::Application::getTempFileName());
TopoDS_Shape myShape = _Shape.getShape();
if (!BRepTools_Write(myShape,(Standard_CString)fi.filePath().c_str())) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
}
std::stringstream ss;
ss << "Cannot save BRep file '" << fi.filePath() << "'";
writer.addError(ss.str());
}
Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file) {
std::streambuf* buf = file.rdbuf();
writer.Stream() << buf;
}
file.close();
// remove temp file
fi.deleteFile();
}
void PropertyPartShape::loadFromFile(Base::Reader &reader)
{
BRep_Builder builder;
// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(App::Application::getTempFileName());
// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();
// Read the shape from the temp file, if the file is empty the stored shape was already empty.
// If it's still empty after reading the (non-empty) file there must occurred an error.
TopoDS_Shape shape;
if (ulSize > 0) {
if (!BRepTools::Read(shape, (Standard_CString)fi.filePath().c_str(), builder)) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
}
}
}
// delete the temp file
fi.deleteFile();
setValue(shape);
}
void PropertyPartShape::loadFromStream(Base::Reader &reader)
{
try {
reader.exceptions(std::istream::failbit | std::istream::badbit);
BRep_Builder builder;
TopoDS_Shape shape;
BRepTools::Read(shape, reader, builder);
setValue(shape);
}
catch (const std::exception& e) {
Base::Console().Warning("Failed to load BRep file %s\n", reader.getFileName().c_str());
}
}
void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
{
// If the shape is empty we simply store nothing. The file size will be 0 which
@@ -292,40 +388,7 @@ void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
bool direct = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Mod/Part/General")->GetBool("DirectAccess", true);
if (!direct) {
// create a temporary file and copy the content to the zip stream
// once the tmp. filename is known use always the same because otherwise
// we may run into some problems on the Linux platform
static Base::FileInfo fi(App::Application::getTempFileName());
if (!BRepTools_Write(myShape,(Standard_CString)fi.filePath().c_str())) {
// Note: Do NOT throw an exception here because if the tmp. file could
// not be created we should not abort.
// We only print an error message but continue writing the next files to the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n",
obj->Label.getValue(),fi.filePath().c_str());
}
else {
Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
}
std::stringstream ss;
ss << "Cannot save BRep file '" << fi.filePath() << "'";
writer.addError(ss.str());
}
Base::ifstream file(fi, std::ios::in | std::ios::binary);
if (file) {
std::streambuf* buf = file.rdbuf();
writer.Stream() << buf;
}
file.close();
// remove temp file
fi.deleteFile();
saveToFile(writer);
}
else {
TopoShape shape;
@@ -347,51 +410,12 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader)
bool direct = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Mod/Part/General")->GetBool("DirectAccess", true);
if (!direct) {
BRep_Builder builder;
// create a temporary file and copy the content from the zip stream
Base::FileInfo fi(App::Application::getTempFileName());
// read in the ASCII file and write back to the file stream
Base::ofstream file(fi, std::ios::out | std::ios::binary);
unsigned long ulSize = 0;
if (reader) {
std::streambuf* buf = file.rdbuf();
reader >> buf;
file.flush();
ulSize = buf->pubseekoff(0, std::ios::cur, std::ios::in);
}
file.close();
// Read the shape from the temp file, if the file is empty the stored shape was already empty.
// If it's still empty after reading the (non-empty) file there must occurred an error.
TopoDS_Shape shape;
if (ulSize > 0) {
if (!BRepTools::Read(shape, (Standard_CString)fi.filePath().c_str(), builder)) {
// Note: Do NOT throw an exception here because if the tmp. created file could
// not be read it's NOT an indication for an invalid input stream 'reader'.
// We only print an error message but continue reading the next files from the
// stream...
App::PropertyContainer* father = this->getContainer();
if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
Base::Console().Error("BRep file '%s' with shape of '%s' seems to be empty\n",
fi.filePath().c_str(),obj->Label.getValue());
}
else {
Base::Console().Warning("Loaded BRep file '%s' seems to be empty\n", fi.filePath().c_str());
}
}
}
// delete the temp file
fi.deleteFile();
setValue(shape);
loadFromFile(reader);
}
else {
BRep_Builder builder;
TopoDS_Shape shape;
BRepTools::Read(shape, reader, builder);
setValue(shape);
auto iostate = reader.exceptions();
loadFromStream(reader);
reader.exceptions(iostate);
}
}
}

View File

@@ -91,6 +91,11 @@ public:
/// Get valid paths for this property; used by auto completer
virtual void getPaths(std::vector<App::ObjectIdentifier> & paths) const;
private:
void saveToFile(Base::Writer &writer) const;
void loadFromFile(Base::Reader &reader);
void loadFromStream(Base::Reader &reader);
private:
TopoShape _Shape;
};

View File

@@ -637,9 +637,9 @@ void PlyReader::read(const std::string& filename)
if (alpha != max_size)
a = data(i, alpha);
colors.emplace_back(static_cast<float>(r)/255.0f,
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
}
}
else if (types[red] == "float") {
@@ -1085,9 +1085,9 @@ void PcdReader::read(const std::string& filename)
uint32_t g = (packed >> 8) & 0xff;
uint32_t b = packed & 0xff;
colors.emplace_back(static_cast<float>(r)/255.0f,
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
}
}
else if (types[rgba] == "F") {
@@ -1105,9 +1105,9 @@ void PcdReader::read(const std::string& filename)
uint32_t g = (packed >> 8) & 0xff;
uint32_t b = packed & 0xff;
colors.emplace_back(static_cast<float>(r)/255.0f,
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
static_cast<float>(g)/255.0f,
static_cast<float>(b)/255.0f,
static_cast<float>(a)/255.0f);
}
}
}