I am working on an embedded device (microcontroller), and I want to save objects to permanent storage (an EEPROM). Most of the serialization solutions I can find, use the file-system in some way, but my target has no file-system.
Therefore my question is, how can I serialize an object to a byte-array so I can save that byte-array to an EEPROM afterwards?
Here is an example of what i am trying to do:
class Person{
//Constructor, getters and setters are omitted
void save(){
char buffer[sizeof(Person)];
serialize(buffer);
EEPROM::Save(buffer, sizeof(Person));
}
void load(){
char buffer[sizeof(Person)];
EEPROM::Load(buffer, sizeof(Person));
deserialize(buffer);
}
void serialize(char* result){
//?????
}
Person deserialize(char* buffer){
//??????
}
private:
char* name;
int age;
float weight;
};
To save a string to binary, usually we save its length and then its content. To save other primitive data, we can simply store their binary form. So in your case, all you need to store is:
So the code to serial is:
And to read a string from binary buffer, you read its length first, and then copy its data.
It's likely that your code for
save
andload
will be reasonably generic and would work best in a separate 'manager' class, leaving each data class only with the responsibility of rendering itself as re-loadable:Each class you intend to serialize / de-serialize should inherit from an interface which mandates the virtual interface for these functions. Note that you'll need to do your own memory management here. I've given a simple example but you'd probably want something a bit more robust.
Then each function should sequentially serialize all attributes of the class (chaining bases classes and calling
serialize
on aggregate objects if needed.)You'll benefit from generic code to serialize / de-serialize each separate type so you don't keep having code to write the length of strings etc. I.e. a serialize / de-serialize for each POD type:
Incidentally, you might also need to consider what will happen if you change the schema of an object in a software upgrade. Your saved objects would potentially become corrupted on reloading, unless you code round this using - for example - a class version identifier.
Final thought: At a micro level, what you're doing is in many ways similar to the way POD data is serialised for network transmission, so it may be that you can take advantage of libraries to do that - even if you don't have access to an operating system.