@StefanS Well I meant something completely different. My point was that most of your member variables are more or less directly convertible to var so you should create an Array<var> to store them all as vars in an ordner known to you and then restore them back again from such an array. This should be a lot safer. Example class layout:
class TestClass
{
public:
int iVar;
std::string strVar;
AudioChannelSet cs;
bool boolVar;
float floatVar;
TestClass (int i, const std::string& s, AudioChannelSet a, bool b, float f)
: iVar (i),
strVar (s),
cs (a),
boolVar (b),
floatVar (f)
{}
/** Serializes this class into a var */
var toVar()
{
// To be able to safely serialize/deserialize our content, each element needs to
// be stored to a separate var. Therefore, we create an array of vars with one array
// field for each value
Array<var> valuesArray;
valuesArray.resize (numElements);
// var has a constructor allowing implicit int to var conversion
valuesArray.set (iVarIdx, iVar);
// var has a constructor that takes a JUCE string. We can convert a std::string to a
// JUCE string. Other, probaly better option: Use a JUCE string directly
valuesArray.set (strVarIdx, String (strVar));
// The AudioChannelSet needs some custom serialization/deserialization logic. How
// straightforward/complicated this logic is will depend on what kind of sets you expect
valuesArray.set (csIdx, channelSetToVar (cs));
// var has a constructor allowing implicit bool to var conversion
valuesArray.set (boolVarIdx, boolVar);
// var has a constructor allowing implicit double to var conversion
valuesArray.set (floatVarIdx, double (floatVar));
// After all the nested values have been set, we wrap the array in a single var
var valuesWrapper (valuesArray);
return valuesWrapper;
}
/** This constructor lets us (re) construct a TestClass instance previously serialized by toVar */
TestClass (const var& source)
{
// We stored an array in our outer wrapper var below – so let's ensure if it is an array
// in the first place and if the size matches
jassert (source.isArray());
auto& valuesArray = *source.getArray();
jassert (valuesArray.size() == numElements);
// No we do the whole stuff from above backwards.
iVar = valuesArray[iVarIdx];
strVar = valuesArray[iVarIdx].toString().toStdString();
cs = varToChannelSet (valuesArray[csIdx]);
boolVar = valuesArray[boolVarIdx];
floatVar = float (double (valuesArray[floatVarIdx]));
}
private:
// Each element should correspond to a certain element in the inner var array, this enum holds the indices
enum ValueIdx
{
iVarIdx = 0,
strVarIdx = 1,
csIdx = 2,
boolVarIdx = 3,
floatVarIdx = 4,
numElements
};
static var channelSetToVar (const AudioChannelSet& setToConvert)
{
// A suitable way to do the conversion implemented here!
return var();
}
static AudioChannelSet varToChannelSet (const var& varToConvert)
{
// A suitable backwards conversion implemented here
return AudioChannelSet();
}
};
Then writing would look like
TestClass tc (42, "Some Text", AudioChannelSet::stereo(), true, 0.154);
MemoryBlock memBlock;
MemoryOutputStream mos (memBlock, false);
auto tcVar = tc.toVar();
tcVar.writeToStream (mos);
Reading:
void messageReceived (const MemoryBlock& message)
{
MemoryInputStream mis (message, false);
var v = var::readFromStream (mis);
TestClass tc (v);
}
Note, that in your version you are still stupidly copying a non trivial copyable object (because of the nested std::string and audio channel set) there in a trivial way, which will lead to crashes.