In VTK, they are a few reader/writers that internally supports multiple file formats.
eg:
- vtkGLTFReader supports .gltf and .glb
- vtkOCCTReader supports .stp and .igs
However, the actual reading of these files is usually different depending of the format, so the reader must use the right method to read. There are different approaches to that. I see the following:
- Parse the filename extension to automatically choose the right behavior (vtkGLTFReader does that)
- Let the user specify which code path to take using a setter/getter (vtkOCCTReader does that)
- Let the user specify wich code path to take but add a “Automatic” mode that behave like one and make this the default
- Use mime types
I think 1. is working until it doesn’t for reasons, as file extensions are bad to detect the actual format of a file. The simple case were it breaks is a format using multiple file extensions were one if forgotten or more confidential. Also some file format just do not have extensions so 1. would not be usable in that case.
-
is fine too but makes the reader hard to integrate in applicative layer, eg, to integrate the OCCT reader in ParaView we need to create two different “reader proxy”, one for each format, so not very nice.
-
would work but requires a bit more code, see below.
-
is not realistic, also mime types are not a thing in Windows world (I think)
So here is a proposed standard API trying to implement 3.
enum Format : unsigned int
{
FOO,
BAR
};
vtkGetMacro(ManualFileFormat, unsigned int)
vtkSetClampMacro(ManualFileFormat, unsigned int, Format::FOO, Format::BAR);
vtkSetMacro(AutomaticFileFormat, bool)
vtkGetMacro(AutomaticFileFormat, bool)
vtkBooleanMacro(AutomaticFileFormat)
unsigned int ManualFileFormat;
bool AutomaticFileFormat;
// Should be in the internal pimpl
unsigned int FileFormat;
if (this->AutomaticFileFormat)
{
std::string extension = vtksys::SystemTools::GetFilenameLastExtension(this->FileName);
if (extension == ".foo")
{
this->FileFormat = FOO;
}
else // "bar"
{
this->FileFormat = FOO;
}
}
else
{
this->FileFormat = this->ManualFileFormat;
}
With such an implementation, user have full control when needed but also simplify the developpement of the applicative layer.
I know. nothing special in that code but since it may applies on multiple reader, just trying to make sure I’m not missing anything.