Preferred way to serialize an object with C++ - c++

Java has a very simple way to serialize objects. couldn't find something similar in C++.
I found Boost Serialization, and a basic approach using ifstream and ofstream.
I have a Task class wich has a title, id, status and date/time. I want to implement a serialize function within the class to save that object in binary mode.
But I want to save multiple instances of the class on a single binary file. Let's say, a Task array.
Would it be a good approach to implement a serialize method on the class? It will only serialize one at a time and It doesn't looks well-done if I use ifstream/ofstream, as I'll be opening and closing files a lot. Also every task will be saved on different files.
Boost's serialization looked fine, but is best for me to avoid 3rd party dependencies if possible.
What would be the best way of accomplish this?
My class header:
#ifndef TASK_H
#define TASK_H
class Task {
public:
enum Status { COMPLETED, PENDIENT };
Task(std::string text);
~Task();
// SETTERS
void setText(std::string text);
void setStatus(Status status);
// GETTERS
const std::string getText() const;
const bool getStatus() const;
const int getID() const;
const int getCount() const;
const std::string getDate() const;
const std::string getTime() const;
// DATE
const int getDay() const;
const int getMonth() const;
const int getYear() const;
// TIME
const int getSecond() const;
const int getMinute() const;
const int getHour() const;
// UTILS
//serialize
const void printFormatted() const;
// OVERLOAD
bool operator==( const Task &text2 ) const;
private:
void setID();
static int sCount;
int id;
std::string text;
Status status;
tm *timestamp;
};
#endif

If you only have a single, very simple class to serialise out, it's not that hard to implement a serialisation function that writes out the handful of members that you need to save. You don't give a code example that shows your class, but with a handful of members it should be comparatively easy as long as there are no pointers involved. If you write out the number of objects serialised followed by the data contained therein, that would probably be good enough for your purposes.
If you want to implement the serialisation yourself, I would have an external function (possibly a friend of your class) handle the serialisation of the Task array rather than trying to put the array serialisation into your class. What you can do is add a serialiseObject() function to your class that serialises a single object, then call it repeatedly from the array serialisation function. That's a much cleaner design than having the array serialisation also bolted onto the class itself.
Once you get into serialising C++ object that are a little more complex, especially ones containing references and pointers, serialisation very quickly becomes a hard problem and you really, really want to use an existing, third-party mechanism that has been well tested.
That said, as someone who does C++ development for a living, I consider a dependency on boost as normal, not a third party library I would want to avoid. Boost gives you so much additional functionality that I consider it part of "my standard library".

Since there is no standard for serializing data in C++, the "preferred" way is what you prefer. Boost is entirely acceptable, unless your project explicitly prohibits the use of third-party libraries, in which case you can certainly roll your own.
If you choose to roll your own, make sure that your serializers and deserializers do not open and close the streams on their own. Instead, the callers need to pass the stream to them. See this link for more information.

I have also used Google protobuf for serialization. While not strictly serialization, Google protobuf can be nicely efficient and cross platform for containers of data.

Related

Efficient way of storing a large amount of character data between transactions in C++

For our application we have the following scenario:
Firstly, we get a large amount of data (on cases, this can be more than 100MB) through a 3rd party API into our class via a constructor, like:
class DataInputer
{
public:
DataInputer(int id, const std::string& data) : m_id(id), m_data(data) {}
int handle() { /* Do some stuff */ }
private:
std::string m_id;
std::string m_data;
};
The chain of invocation going into our class DataInputer looks like:
int dataInputHandler()
{
std::string inputStringFromThirdParty = GiveMeStringFrom3rdPartyMagic(); // <- 1.
int inputIntFromThirdParty = GiveMeIntFrom3rdPartyMagic();
return DataInputer(inputIntFromThirdParty, inputDataFromThirdParty).handle();
}
We have some control over how the dataInputHandler handles its string (Line marked with 1. is the place where the string is created as an actual object), but no control for what GiveMeStringFrom3rdPartyMagic actually uses to provide it (if it's important for anyone, this data is coming from somewhere via a network connection) so we need. As a consolation we have full control over the DataInputer class.
Now, what the application is supposedly doing is to hold on to the string and the associated integer ID till a later point when it can send to another component (via a different network connection) provided the component provides a valid ID (this is the short description). The problem is that we can't (don't want to) do it in the handle method of the DataInputer class, it would block it for an unknown amount of time.
As a rudimentary solution, we were thinking on creating an "in-memory" string store for all the various strings that will come in from all the various network clients, where the bottom line consists of a:
std::map<int, std::string> idStringStore;
where the int identifies the id of the string, the string is actually the data and DataInputer::handle does something like idStringStore.emplace(m_id, m_data);:
The problem is that unnecessarily copying a string which is on the size of 100s of megabytes can be a very time consuming process, so I would like to ask the community if they have any recommendations or best practices for scenarios like this.
An important mention: we are bound to C++11 for now :(
Use move-semantics to pass the 3rd-party data into your DataInputer constructor. The std::move here is redundant but makes the intention clear to the reader:
class DataInputer
{
public:
DataInputer(int id, std::string&& data) : m_id(id), m_data(std::move(data)) {}
int handle() { /* Do some stuff */ }
private:
std::string m_id;
std::string m_data;
};
And pass GiveMeStringFrom3rdPartyMagic() directly as an argument to the constructor without first copying into inputStringFromThirdParty.
int dataInputHandler()
{
int inputIntFromThirdParty = GiveMeIntFrom3rdPartyMagic();
return DataInputer(inputIntFromThirdParty, GiveMeStringFrom3rdPartyMagic()).handle();
}
Of course, you can use a std::map or any other STL container that supports move-semantics. The point is that move-semantics, generally, is what you're looking to use to avoid needless copies.

Wrapper class design and dependency injection

I have a simple FTP class that take care of downloading and uploading through cURL libraries:
class FTPClient
{
public:
explicit FTPClient(const std::string& strIPAddress);
virtual ~FTPClient();
bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile);
bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile);
private:
static size_t WriteToFileCallBack(void *ptr, size_t size, size_t nmemb, FILE *stream);
static size_t ReadFromFileCallback(void* ptr, size_t size, size_t nmemb, FILE *stream);
std::string m_strUser;
std::string m_strPass;
std::string m_strIPAddress;
std::string m_strPort;
mutable CURL* m_objCurlSession;
};
I've asked some advices on how it could be implemented and structured better since it's the base and core for a project and it's going to be used in many parts.
I've been told to use a cURLWrapper class to wrap all of the cURL calls (curl_easy_setopt(..)), but then I've been told to create an Interface for the FTP class, a cURLWrapper that just calls the FTP methods and then a concrete class.. but still it's too abstract for me and don't understand the best way to implement it and which path to follow..
How would you approach this small structure?
Define a simple interface for your FTP class:
class IFTPClient
{
public:
virtual ~IFTPClient();
virtual bool DownloadFile(const std::string& strRemoteFile, const std::string& strLocalFile) = 0;
virtual bool UploadFile(const std::string& strLocalFile, const std::string& strRemoteFile) = 0;
};
I assume your static callback methods are calling back into some class instance rather than into a singleton? That's fine then. Derive your class from the interface:
class FTPClient:IFTPClient
{
...
I notice that you have the IP address passed into the constructor and have other parameters (user name, password, port, etc.) defined elsewhere. That does not appear to be quite consistent yet. You would need to refactor that so that these parameters can be set through interface methods or add those to the upload/download methods.
Construct your FTPClient object(s) before you need it elsewhere and then only pass ("inject") the interface into objects that want to use the FTPClient. For unit testing without the use of the actual FTPClient, construct a mock object derived from the same interface and inject that into other objects instead.
Other objects simply make use of the functionality exposed in the interface and don't need to know or worry about its internal implementation; if you decide to use curl or something else is then entirely up to FTPClient.
That's in in a nutshell; you may want to search for dependency injection and frameworks on the Internet but you don't need a framework to follow dependency injection principles and, in my opinion, they can be overkill for simple projects.

const correctness for configuration structures

I have a configuration file which gets read in, parsed and put into structures at the beginning of my programs run time.
The problem I am having is that I want these structures to be constant since the values in them should not change during the programs lifespan.
Currently I am doing the following:
config.h
#pragma warning(push)
#pragma warning(disable: 4510) /*-- we don't want a default constructor --*/
#pragma warning(disable: 4610) /*-- we don't want this to ever be user instantiated --*/
typedef struct SerialNode {
private:
void operator=(SerialNode&);
public:
const char* const port;
const char* const format;
} SerialNode;
#pragma warning(pop)
typedef std::map<const char*, const SerialNode*, MapStrComp> SerialMap;
SerialMap SerialConfig;
config.cpp
/*-- so we don't fall out of scope --*/
SerialNode* global_sn;
SerialNode local_sn = {port, format};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
This works fine. However my problem is that now I am dealing with more complicated configuration data which requires me to pull a structure back out of the list, modify it and then put it back.
Obviously I can't modify it, so the solution would be something like:
SerialNode* global_sn;
SerialNode* old_sn = SerialConfig[key_store];
SerialNode local_sn = {port, format, old_sn->old_data, old_sn->more_old_data};
global_sn = new SerialNode(local_sn);
SerialConfig[key_store] = global_sn;
delete old_sn;
But this strikes me as bad programming practice. Is there is a better way to achieve what I'm going for which doesn't require such a hacked looking solution?
For reference, I'm using Visual Studio 2010
As always, the best thing you can do is not re-implement something that has already been written. There are a large number of libraries and frameworks that will help with serialization for c++:
Boost Serialization
Qt
Protocol Buffers
msgpack
Capn' Proto
Ideally the serialization framework you choose will exactly recreate the data graph that you are trying to store. Regardless of whether you have done any fixup, your goal will likely be to only provide const access to the global configuration data. Just make sure that mutators (including non const pointers) are not exposed via a header file.
The simple answer is what Thomas suggest, but correctly done (that is, not causing undefined behavior):
Create a mutable configuration object but pass it to the rest of the components by constant reference. When you create (and where you maintain) the real object you can change it, but the rest of the application won't be able to modify the config. A common pattern I have used in the past was:
class SomeObject {
Configuration const & config;
public:
SomeObject(Configuration const & config) : config(config) {}
void f() {
if (config.someParam()) { ...
// ...
void loadConfiguration(Config & config) { ... }
int main() {
Configuration config;
loadConfiguration(config); // config is a non-const &, can modify
SomeObject object(config); // object holds a const&, can only read
object.f();
// ...
This is not an answer to your question, just some observations to your code.
You don't need the typedef struct SerialNode { ... } SerialNode;, this is a c idiom. In c++, you just write struct SerialNode { ... }; and use SerialNode as a type name.
If you want to prevent a default constructor, make it private as you already do with the assignment operator
class SerialNode {
private:
SerialNode();
SerialNode &operator=(SerialNode&);
...
};
Don't use char* members, use std::string instead. C++ strings are much easier and safer to use than plain char pointers and the associated heap allocation.
Same goes for the map key; if you use std::string as a key, you don't need MapStrComp anymore, because std::string already provides an appropriate comparison.
Probably nicer is to wrap the whole thing in a singleton class:
class Config {
public:
static Config const& get() { return *config; }
static void load();
SerialNode const* operator[](const char*);
private:
static Config* config;
SerialMap map;
};
void Config::load() {
config = new Config();
// put things into it
}
Disclaimer: not tested, and haven't used C++ in a while, so there might be some syntax errors :)

Best way to expose API from a library

I am designing a Win32 library to parse the contents of the file (Columns and Values) and store it internally in a datastructure (Map). Now i need to expose API's so that the consumer can call those API's to get the results.
The file may have different formats eg FM1, FM2 etc. The consumer may query like
FM1Provider.GetRecords("XYZ");
FM2Provider.GetRecords("XYZ");
What i am planning to do is to have a CParser class that does all the parsing and expose the class.
CParser
{
bool LoadFile(string strFile);
Map<string,string> GetFM1Records(string key);
Map<string,string> GetFM1Records(string key);
};
or
class CResultProvider
{
virtual Map<string,string> GetRecords(string key)=0;
}
class CFM1ResultProvider : public CResultProvider
{
Map<string,string> GetRecords(string key);
}
class CFM2ResultProvider : public CResultProvider
{
Map<string,string> GetRecords(string key);
}
CParser
{
bool LoadFile(string strFile);
CResultProvider GetFM1ResultProvider();
CResultProvider GetFM1ResultProvider();
};
Please suggest me which one of these approaches are correct and scalable considering i am developing a library.
Your component seems to be dealing with two problems: parsing and storing. It is a good design practise to separate these into different components so that they can be used independently.
I would suggest you provide the parser only with callbacks for parsed data. This way the user of it can choose the most suitable container for her application, or may choose to apply and discard read data without storing.
E.g.:
namespace my_lib {
struct ParserCb {
virtual void on_column(std::string const& column) = 0;
virtual void on_value(std::string const& value) = 0;
protected:
~ParserCb() {} // no ownership through this interface
};
void parse(char const* filename, ParserCb& cb);
} // my_lib
BTW, prefer using namespaces instead of prefixing your classes with C.
Assuming the client would only have to call GetRecords once, and then work with the map, the first approach I prefer the first approach because it is simpler.
If the client has to reload the map in different places in his code, the second approach is preferable, because it enables the client to write his code against one interface (CResultProvider). Thus, he can easily switch the file format simply by selecting a different implementation (there should be exactly one place in his code where the implementation is chosen).

easing c++ to objective-c/cocoa bridging via metaprogramming?

In a pure C++ world we can generate interfacing or glue code between different components or interfaces at compile time, using a combination of template-based compile-time and runtime-techniques (to e.g. mostly automatically marshall to/from calls using legacy types).
When having to interface C++ applications with Objective-C/Cocoa for GUI, system integration or IPC though, things become harder due to the less strict typing - yet often not more then a flat repitive interface layer is needed: thin bridging delegates have to be defined or conversion code to language bridging calls has to be written.
If you have to deal with interfaces of non-trivial size and want to avoid script-based code generation this quickly becomes cumbersome and is just a pain every time refactorings have to take place. Using a combination of (template) metaprogramming and the Objective-C runtime library, it should be possible to reduce the amount of code considerably...
Before i go to reinvent the wheel (and possibly waste time), does anyone know about techniques, best-practices or examples in that direction?
As for an example, lets say we need a delegate that supports this informal protocol:
- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
- (NSNumber*) indexOf:(CustomClass*)obj;
Instead of implementing an Obj-C class now that explicitly bridges to a C++-instance, i'd like to do something like this instead:
class CppObj {
ObjcDelegate m_del;
public:
CppObj() : m_del(this)
{
m_del.addHandler
<NSString* (NSString*, NSString*)>
("concatString", &CppObj::concat);
m_del.addHandler
<NSNumber* (CustomClass*)>
("indexOf", &CppObj::indexOf);
}
std::string concat(const std::string& s1, const std::string& s2) {
return s1.append(s2);
}
size_t indexOf(const ConvertedCustomClass& obj) {
return 42;
}
};
All that should be needed from the user to support additional types would be to specialize a conversion template function:
template<class To, class From> To convert(const From&);
template<>
NSString* convert<NSString*, std::string>(const std::string& s) {
// ...
}
// ...
The example above of course does ignore support for formal protocols etc. but should get the point across. Also, due to the type-information for Objc-runtime-types being mostly decayed into some-native-types or class-type i don't think the explicit specification of parameter and return types for the delegate-methods can be avoided.
I didn't find anything satisfactory and came up with a prototype that, given the following informal protocol:
- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
and this C++ code:
struct CppClass {
std::string concatStrings(const std::string& s1, const std::string& s2) const {
return s1+s2;
}
};
std::string concatStrings(const std::string& s1, const std::string& s2) {
return s1+s2;
}
allows creating and passing a delegate:
CppClass cpp;
og::ObjcClass objc("MyGlueClass");
objc.add_handler<NSString* (NSString*, NSString*)>
("concatString:withString:", &cpp, &CppClass::concatStrings);
// or using a free function:
objc.add_handler<NSString* (NSString*, NSString*)>
("concatString:withString:", &concatStrings);
[someInstance setDelegate:objc.get_instance()];
which can then be used:
NSString* result = [delegate concatString:#"abc" withString:#"def"];
assert([result compare:#"abcdef"] == NSOrderedSame);
Boost.Function objects can also be passed, which means Boost.Bind can easily be used as well.
While the basic idea works, this is still a prototype. I did a short blog post on the subject and the prototype source is available via bitbucket. Constructive input and ideas welcome.
Did you look at the wxWidgets library? I don't code in Objective-C, but at least the developers claim decent support for Cocoa/Objective-C. Which means, they have some mapping from C++ implemented somehow. The library's website is http://www.wxwidgets.org.