How do I include two different versions of the same header?
I am writing code to convert files from a proprietary file format to another generic one. My goal is to support multiple versions of the manufacturer file format.
I have several versions of the same proprietary headers. Headers define the various structures that make up the main file header (the file is just a large header followed by the raw data).
I need to read the first 4 bytes of a source file to determine the version of the file. The version of the file, in turn, tells me which version of the C-struct was used to create the file.
Problems:
- I cannot change my own headers
- Headers don't use namespaces or classes
- There is a good portion of macros defined in headers
Possible solutions:
- Create different converter binaries for each type of file version :-(
- Inconvenient for user and developer
- Dynamically loading libraries for each version
- The converter is plugin oriented, so a lot of this is already happening.
I tried to hack namespaces:
namespace version1 {
#include "version1.h"
}
namespace version2 {
#include "version2.h"
}
int main (void) {
version1::header *hdr = new version1::header;
return 0;
}
But it won't work because of the inclusion of guards and because several macros are redefined in each header.
Is there an elegant way to handle this?
source to share
You can use two different source files along with the forward declaration:
// Forward declare in main.cpp:
namespace version1
{
struct header;
}
namespace version2
{
struct header;
}
// version1.cpp:
namespace version1
{
#include <version1.h>
}
version1::header* new_v1_header()
{
return new version1::header;
}
// other functions using `version1::header`
// version2.cpp:
namespace version2
{
#include <version2.h>
}
version2::header* new_v2_header()
{
return new version2::header;
}
// other functions using `version2::header`
Another alternative is to implement a wrapper class that has a base class that is just an empty wrapper:
class header_base
{
virtual int func1(char *stuff) = 0;
... many other virtual functions.
};
// Create implementation of header_v1 or header_v2:
header_base* make_header(unsigned int magic);
header_base.cpp:
#include "header_v1.h"
#include "header_v2.h"
header_base* make_header(unsigned int magic)
{
switch(magic)
{
case Magic_V1:
return new header_v1;
case Magic_V2:
return new header_v2;
default:
assert(0);
return 0;
}
}
and then implement in two separate
in headerv1.h:
class header_v1 : public header_base
{
int func1(char *stuff);
...
};
header_v1.cpp:
#include "header1.h"
int header_v1::func1(char *stuff)
{
...
return 17;
}
And similarly for header_v2.h and header_v2.cpp.
source to share