Blog

02 Aug 2012 . .
Boost Serialization fast and easy Serialization of objects for C++ to XML,Text or Binary Comments

While coding I always try to learn new ways of writing old things. There are many many libraries out there for C++ all work in different ways, but the library I fell in love with is Boost. Ignoring the massive extension to the STL basic classes it bundles up matrix, graph, system functionality. But what beats all of that mainly because I write it to often is the ever allusive save and load functionality you have to write for all classes. Serialization is one of the things I really miss from my old C# writing days. So here goes a few examples of how to make serialization work!

In C++ there is no reflector so sadly we have to tell the compiler what to save. So an example class

 

1 class NodeDescriptor{ 2 public: 3 NodeDescriptor() {} ; 4 NodeDescriptor(int offset): 5 Offset(offset){} ; 6 ~NodeDescriptor() {} ; 7 int Offset; 8 private: 9 };

Very very basic, one public variable this is an internal of another object so is reasonable to allow a public property style access. So what we want to do is to do is allow Boost access to save out the variables.

 

1 class NodeDescriptor{ 2 public: 3 NodeDescriptor() {} ; 4 NodeDescriptor(int offset): 5 Offset(offset){} ; 6 ~NodeDescriptor() {} ; 7 int Offset; 8 private: 9 // Serialization Settings 10 friend class boost::serialization::access; 11 friend std::ostream & operator<<(std::ostream &os, const MotionGraphDesc &mgd); 12 template<class Archive> 13 void serialize(Archive & ar, const unsigned int /* file_version */) 14 { 15 ar & BOOST_SERIALIZATION_NVP(Offset); 16 } 17 };

So what we have added is allowing boost access via a friend operator. Then adding a class for serialize the data, unfortunately you have to define the data of which there is many ways todo, above is an example of the xml way, what this does is create a xml tag called Offset where it stores the value of Offset. Alternatively say we had a private member _offset, it wouldn’t be visually nice to read the xml so we can customise the name of the tag.

1 void serialize(Archive & ar, const unsigned int /* file_version */) 2 { 3 ar & boost::serialization::make_nvp("Offset",_offset); 4 }

This is actually what the BOOST_SERIALIZATION_NVP macro roles out into but BOOST_SERIALIZATION_NVP is slightly more convenient in a large amount of cases. So now the question is how do we save? Well if you add in a couple of methods to your class description for Load, Save you get something like this, to note I have defined an enum that will come in to play with the read write functions.

1 bool NodeDescriptor::Load(const char* path,SerializeAsType t){ 2 std::ifstream f(path); 3 if (f.is_open()){ 4 Read(f,t); 5 }else 6 return false; 7 } 8 9 bool NodeDescriptor::Save(const char* path,SerializeAsType t){ 10 std::ofstream f(path); 11 if (f.is_open()){ 12 Write(f,t); 13 }else 14 return false; 15 }

Now we define the read write:

1 bool NodeDescriptor::Read(std::istream& str,SerializeAsType t){ 2 switch(t){ 3 case XmlArc: 4 { 5 boost::archive::xml_iarchive ia(str); 6 ia >> boost::serialization::make_nvp("NodeDescriptor",(*this)); 7 } 8 break; 9 case TextArc: 10 { 11 boost::archive::text_iarchive ia(str); 12 ia >> *this; 13 } 14 break; 15 case BinaryArc: 16 { 17 boost::archive::binary_iarchive ia(str); 18 ia >> *this; 19 } 20 break; 21 } 22 return true; 23 } 24 25 bool NodeDescriptor::Write(std::ostream& str,SerializeAsType t){ 26 switch(t){ 27 case XmlArc: 28 { 29 boost::archive::xml_oarchive oa(str); 30 oa << boost::serialization::make_nvp("NodeDescriptor",(*this)); 31 } 32 break; 33 case TextArc: 34 { 35 boost::archive::text_oarchive oa(str); 36 oa << (*this); 37 } 38 break; 39 case BinaryArc: 40 { 41 boost::archive::binary_oarchive oa(str); 42 oa << (*this); 43 } 44 break; 45 } 46 return true; 47 }

How easy is that? Most of the space is taken up by making it more compatible allowing the save and load of XML, Text and Binary archives. One thing to note thought is that this is for the purpose of serialization not really a property config file. The other thing to consider is this is a lazy coder solution, it isn’t fast so don't create massive xml files or they will take a long time to read in and out!


Stuart James  


23 Jun 2012 . .
Visual Studio 12 Performance Analysis Comments

Since the Visual Studio 2012 RTM came out I have been experimenting with the different features. Now this may of existed in previous versions(although not as pretty), but this is quite a nice little tool for understanding where your code is being locked up. Sadly though in this case I wasn’t actually able to get any advantage without a big re-write.

image

So what do you get, some charts some nice percentage bars, and also the ability to dig down into your function and find where it really is going slow.

image

This is an example of a tree being searched through so there is little to be gained (or at least on first glance) to improve the performance. But is nice to know that abusing vectors is killing my code… maybe a note for next time I write something like this.


Stuart James  


19 Jun 2012 . .
Google user interface consistency error Comments

 

google-listen-ui-fail <p> </p> <p>Every so often you will hit a user interface that will break your user model. It isn’t often that mainstream publishers will do this so I was quite shocked on the Google Listen App for Android (2.3) in the add podcast option the add and cancel buttons are around the wrong way. Making me accidently click add instead of cancel. The worse part when these events occur you have to think, is that actually the wrong way? but after opening a few more apps I felt happy to say Google FAIL!</p>
Stuart James