I'm currently working on a project that encrypts files and adds them to the application's library. I need to version the file format so that I'm planning to prepend a file header to the encrypted file. The project is in Qt and currently for Windows. Later will make app for android and mac as well.
FOr this I made these structures, the version 1 file.
struct Header_Meta
{
char signature [4];
char version [4];
};
struct Header_v1
{
char id [12];
char flag [8];
char name [128];
long size;
};
union File_v1
{
Header_Meta meta;
Header_v1 header;
byte null [512 - sizeof (Header_Meta) - sizeof (Header_v1)];
byte data [MAX_HEADERv1];
};
The file is binary file. Now in the getDetails() function, I'll read the MAX_HEADERv1 bytes to file_v1.data and will get the details in the member variables.
My questions are
There is a slight possibility that you will end up having a lot of #ifdef BIG/LITTLE_ENDIAN's in the code depending on the platform you are trying to deploy your product. I would use for the long size to be like: unsigned char size[8] (this would yield a 64 (=8*8) bit value) and then you could use a formula in your code, like:
uint64_t real_size = size[0] + size[1] << 8 + size[2] << 16 + ....
and when calculating individual size bytes you could do it like:
size[0] = real_size && 0xFF;
size[1] = (real_size && 0xFF00) >> 8;
size[2] = (real_size && 0xFF0000) >> 16;
and so on...
and from this point on you just need to worry about correctly writing out the bytes of size to their corresponding position.
Regarding the version string you want to add to the header (char version[4]) it all depends on what do you want to store there. If you want to put textual information (such as: "v1.0") you will limit the possible version you can have, so I would recommend again putting in a binary version, such as:
version[0] = VERSION // customers usually pay for an increase in this
version[1] = RELEASE // new functionality, it's up to you if customer pays or not :)
version[2] = MAINTENANCE // planned maintenance, usually customers don't pay for this
version[3] = PATCH // emergency patch, hopefully you never have to use this
This will allow for version numbers in the form of VERSION.RELEASE.MAINTENACE.PATCH and you can go up to 255.255.255.255
Also, please pay attention to @Ben's comment, the union just feels wrong. Usually these fields should come one after the other, but with the union they all will overlap each other, starting at the same location.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With