s11nlite::save(Anything, Anywhere);
Project powered by:

Why use libs11n?

Almost every application needs some way to read data, and most also need a way to write data. For many applications, the only reading of data they need to be able to do is the simple parsing of a typical configuration file of key/value pairs. For example:
# configuration file for MyApplication
setting_1 = 45
plugins_path = /home/me/lib/MyApplication:/usr/local/lib/MyApplication
Most programmers have written code to read in such a file. If indeed that is all the support you need, then libs11n is overkill for your purposes and you are probably better off using your own ConfigFile class. If, however, you want to load and save more complex data, such as multiple instances of a particular class, then libs11n is probably a good choice. Let's take a brief look at why...

First off, implementing i/o support is not trivial. Even the ConfigFile example can take an hour or two of work to get right when one considers problems like handling of multi-line values. And such a ConfigFile handles only basic data with no hierarchical structure. It does not scale well to handle hierarchical data without a lot more work (even then, there are limits, and it does not scale well to support multiple instances of any given object). As soon as we want to save, e.g., a std::vector or std::map, we have to write completely new code to handle them. Since std::map<int,string> and std::map<string,int> are different types, we also have to handle those different cases unless we want to lock ourselves in to a very limited set of map types. And what about std::map<int,vector<string>>? libs11n handles all supported types to arbitrarily deep nesting levels, so as our data complexity grows libs11n is still suitable, whereas our ConfigFile type has long since been obsoleted by new data requirements.

Many programmers will of course say, "we can use XML." That's all fine and good - XML is a wonderful technology. My first argument against that would then be, "then you have to embed XML support into your application." My second argument would be, "and you still need to design an i/o interface suitable for XML." That is, your objects have to know that they are working with XML. That requires, amongst other things, adding a dependency to a particular XML implementation. Even if you have a generic, factory-based XML interface with hot-swappable implementations behind it, you're still limited to using XML. In my opinion, application objects should not know what data store they are using (except, of course, in the case of the objects which do the data marshaling). libs11n is, AFAIK, the only C++ serialization library which hides the detail of format from clients. Even in C# clients must specify whether they want to use XML or Binary serialization and they are then stuck with that format - they cannot change it without changing their objects' code. This is not the case in s11n - the format can be changed independently of the de/serialized objects.

While there are many examples of use cases for which libs11n is not suitable, there are many, many more for which libs11n is an ideal solution. Not only is it ideal for many problems, but it has the following additional properties:
  • Here today. You don't need to design and implement an i/o mechanism for your types. libs11n provides the mechanism and you just have to fill in a few blanks so that it knows how to work with your types.
  • Well supported. libs11n is my favourite "pet project", and therefore gets a lot of attention. When something doesn't work, fixing it becomes my first priority. (Just don't tell my girlfriend that. ;)
  • It's damned easy to use. Out of the box, libs11n supports a huge range of types which coders commonly want to serialize. If you're not serializing custom types, adding s11n support to an application takes only a few minutes of work. Adding support for custom types typically takes between 3 and 5 minutes of work per custom type (and much less if a type is s11n-compatible with an existing supported type).
For completeness, here are some cases for which s11n is not particularly well suited:
  • Projects with huge data amounts which need to be stored/loaded as a single blob. s11n can handle as much data as you can throw at it, but huge object trees (e.g. hundreds of megs) will consume huge amounts of memory. That said, since s11n allows one to selectively serialize any given branch of an object tree, branches of huge data sets can be selectively serialized to help alleviate memory consumption problems.
  • When individual objects in a container need to be saved or loaded often and independently of one anotherindividually. For example, if you have a hashtable or list of objects which need to be saved/loaded very often independently of each other, s11n is not a good choice. Also, if the saving or loading of an object needs to be able to update only individual properties of an object, s11n is not suitable. Use a database for those cases. If you do not need a full-fledged database, sqlite is an excellent (and flexible) solution for serialization. LiteSQL might also be a good choice for you.
  • When you need to customize the data format, e.g. to provide rich XML descriptions of data relationships. s11n's data format is very simplistic, and essentially acts only as a dumb container with no structural definition other than plain hierarchies and key/value pairs. If you want to handle complex object relationships via XML, LiteSQL may provide a good solution for you.
  • When a project is primarily serializing graphs (that is, object trees which may have circular references/cycles). s11n can serialize graphs, but has no built-in support for them. s11n's internal policies and philosophies about how to follow an object tree make it much more difficult to serialize graphs than it is to serialize acyclic data structures.