|
From: Marc D. <bdu...@gm...> - 2004-12-24 09:28:16
|
Excellent!
Prefs is an API for loading saving/loading application preferences as well as
for all sorts of config files. The important thing is that it doesnt build on
simple string maps but on concrete Entry and Section types. So when you
change someting in the Prefs and forget to change it in your program you are
more likely to realise it at compile time.
Preference data is organised in sections. Each section has a list of
subsections and a list of entries yielding a tree like structure.
class Section {
/* ... */
private:
std::list<Entriy*> _entries;
std::list<Section*> _sections
};
Entries and Sections have a name and a parent. The both derive from Node:
class Node {
/* ... */
private:
Node* _parentNode;
std::string _name;
};
Entry and Section are base classes and you CAN add derived ones or use one of
the simple predefined Entry types (String, int, float etc...) made available
by the ValueEntry template class for all streamables.
class Entry : public Node {
public:
Entry(const std::string& name);
virtual std::string str() const = 0;
};
template <class ValueT>
class ValueEntry : public Entry {
public:
ValueEntry(const std::string& name, const ValueT& value);
virtual std::string str() const; // stream conversion of _value;
const ValueT& value() const;
void setValue(const ValueT& value);
private:
ValueT _value;
};
// examples
typedef ValueEntry<std::string> StringEntry;
typedef ValueEntry<int> IntEntry;
The Prefs class holds the root section and a PrefsStore class which knows how
to load and save the data. This would be where I have to look at s11n.
class PrefsStore {
public:
PrefsStore() {}
virtual ~PrefsStore() {}
virtual void load(Prefs::Section& root) throw(P::IOError) = 0;
virtual void update(Prefs::Section& root) throw(P::IOError) = 0;
};
class Prefs {
/* ... */
private:
Section _root;
PrefsStore* _store;
};
We want to be able to use Prefs with predefined strores like INI, xml or even
some network location.
@Stephan what would you suggest? wrapping up s11n in IniStore, XmlStore etc?
Or kick out PrefsStore and use s11n? It would also be interesting to have the
parsers as seperate classes in P2.
One other idea I had was to have Iterators that stride (hope that is the
correct term) over one type of entry. So if you want to have only the
nameserver entries from a resolv.conf file you would do something like this:
- Impelment ResolvConf derived from Prefs with its store class for the
resolv.conf config file format with a NameserverEntry class derived from i.e.
StringEntry
- Use "stride" iterator for NameserverEntries to print all nameserver entries.
Now for a simple file like resolv.conf it doesnt look like much, but imagine
to simply iterate through all InputDevice sections in a XF86Config.
The "stride" or "select" iterator was rather easy to implement as a template
class encapsulating a normal "linear" iterator. operator++ has to do some
type checking though. But maybe that should not be part of Prefs but part of
the the containers, with SelectTraits or something.
happy cristmas,
Marc
On Friday 24 Dec 2004 00:43, stephan beal wrote:
> On Thursday 23 December 2004 22:52, Marc Duerner wrote:
> > Hello,
> > I still want to look at P::Prefs and some containers. Specially the
> > first one may benefit from s11n.
>
> Any std container is usably out of the box by s11n:
>
> #include <s11n.net/s11n/s11nlite.hpp>
> #include <s11n.net/s11n/list.hpp>
> #include <s11n.net/s11n/map.hpp>
> #include <s11n.net/s11n/pods_streamable.hpp>
>
> ...
>
> typedef map<string,list<map<int,string> > > Geez;
>
> Geez g;
> ... populate it ...
> bool worked = s11nlite::save( g, stream|file );
>
> Loading has 2 options:
>
> #1:
> Geez * g = s11nlite::load_serializable<Geez>( stream|file );
>
> #2:
> s11nlite::node_type * n = s11nlite::load_node( stream|file );
> if( ! n ) { ... error ... }
> Geez g;
> bool worked= = s11nlite::deserialize( *n, g );
>
>
> P::s11n works identically, but also supports URLs (whatever is supported
> by IOManager).
|