Serialization to String
by Xavier "eXoDuS" Amado · 08/30/2005 (1:34 am) · 6 comments
Description
SimObject includes a method that you might have used before, it's the save() method. Save() writes to a FileStream the serialization of an object (and it's subobjects if you serialize a SimSet). I've expanded this functionality with a new ConsoleMethod that writes to a MemStream instead of a FileStream, this means it doesn't write to disk but to memory. The method returns the string of the resulting serialization and takes no arguments (only the optional selectedOnly argument just like the original save() method.
Uses
Uses you ask? Well, there's lots of.. uhm... uses for a rocket launcher (quote from daddy frags best?, anyone seen it? Old machinima) ... err I mean for serializing to string. For example the worldEdtior does this internally (and hackily) to store the object when you copy/cut/paste. You can use it whenever you need to remove an object from the scene, but would like to keep the means to quickly recreate it as it was before.
In my case I needed it to swap a group of objects with another quickly, but without saving to disk.
Expanding
Yes! It can be expanded, and as a matter of fact I already know what I'm going to do next. Right now as you might notice from the code the string buffer is fixed to 4096 bytes. A simple expansion could be to expose the size to the console method itself, although that would make it hard to use for 'scripters'. What I'm going to do next is write a new MemStream class (just deriving a new one from nStream) that can handle dynamic buffers internally, transparently for the programmer. It would re-allocate the memory on each write() call if the buffer is too small. Simple to do, but I'll do that tomorrow, when I get it I'll post it as a resource too.
Hoping that anyone finds this useful, here's the code. Just put this in console/simBase.cc right after the Save() ConsoleMethod.
Regards,
Xavier.
PS. I left the begin write / end write messages so it's as familiar as save() method, but you can remove those easily if you want, read the comments.
SimObject includes a method that you might have used before, it's the save() method. Save() writes to a FileStream the serialization of an object (and it's subobjects if you serialize a SimSet). I've expanded this functionality with a new ConsoleMethod that writes to a MemStream instead of a FileStream, this means it doesn't write to disk but to memory. The method returns the string of the resulting serialization and takes no arguments (only the optional selectedOnly argument just like the original save() method.
Uses
Uses you ask? Well, there's lots of.. uhm... uses for a rocket launcher (quote from daddy frags best?, anyone seen it? Old machinima) ... err I mean for serializing to string. For example the worldEdtior does this internally (and hackily) to store the object when you copy/cut/paste. You can use it whenever you need to remove an object from the scene, but would like to keep the means to quickly recreate it as it was before.
In my case I needed it to swap a group of objects with another quickly, but without saving to disk.
Expanding
Yes! It can be expanded, and as a matter of fact I already know what I'm going to do next. Right now as you might notice from the code the string buffer is fixed to 4096 bytes. A simple expansion could be to expose the size to the console method itself, although that would make it hard to use for 'scripters'. What I'm going to do next is write a new MemStream class (just deriving a new one from nStream) that can handle dynamic buffers internally, transparently for the programmer. It would re-allocate the memory on each write() call if the buffer is too small. Simple to do, but I'll do that tomorrow, when I get it I'll post it as a resource too.
Hoping that anyone finds this useful, here's the code. Just put this in console/simBase.cc right after the Save() ConsoleMethod.
ConsoleMethod(SimObject, saveToString, const char*, 2, 3, "obj.save(<selectedOnly>)")
{
static const char *beginMessage = "//--- OBJECT WRITE BEGIN ---";
static const char *endMessage = "//--- OBJECT WRITE END ---";
char *pSerialized = new char[4096];
MemStream stream(4096, pSerialized, false, true);
// check for flags <selected, ...>
U32 writeFlags = 0;
if(argc > 3)
{
if(dAtob(argv[3]))
writeFlags |= SimObject::SelectedOnly;
}
// Write the begin message
stream.write(dStrlen(beginMessage), beginMessage);
stream.write(2, "\r\n");
// Write the object's serialization into the stream
object->write(stream, 0, writeFlags);
// Write the end message
stream.write(dStrlen(endMessage), endMessage);
stream.write(2, "\r\n");
return pSerialized;
}Regards,
Xavier.
PS. I left the begin write / end write messages so it's as familiar as save() method, but you can remove those easily if you want, read the comments.
About the author
#2
08/30/2005 (2:53 pm)
Sweet resource!
#3
I'll post a resource in a moment.
EDIT: its also included in my "Cryptainer" resource, patched into memStream.cc/memStream.h.
08/31/2005 (10:48 am)
What a coincidence, i already writ a dynamic MemStream ;)I'll post a resource in a moment.
EDIT: its also included in my "Cryptainer" resource, patched into memStream.cc/memStream.h.
#4
09/01/2005 (7:35 pm)
James: Cool, I haven't managed to do it yet, busy with other... um... work.... *cough* gta san andreas *cough*... :)
#5
However, you may occasionally run into a small problem. The array needs to be initialized or it will occasionally contain extra junk.
To fix the problem use insert this code:
char *pSerialized = new char[4096];
for(int count = 0; count < 4096; count++) pSerialized[count] = NULL; // NEW CODE
MemStream stream(4096, pSerialized, false, true);
Hall Of Worlds - For Gamers
EdM|GPGT
PS There is one bug in the code too:
should be
04/03/2006 (11:29 pm)
This is a really excellent resource, especially when paired with this resource.However, you may occasionally run into a small problem. The array needs to be initialized or it will occasionally contain extra junk.
To fix the problem use insert this code:
char *pSerialized = new char[4096];
for(int count = 0; count < 4096; count++) pSerialized[count] = NULL; // NEW CODE
MemStream stream(4096, pSerialized, false, true);
EdM|GPGT
PS There is one bug in the code too:
if(argc > 3)
should be
if(argc == 3)
#6
08/24/2007 (9:23 pm)
When does pSerialized get deleted? 
Torque 3D Owner Xavier "eXoDuS" Amado
Default Studio Name