Console: Documentation of the configuration support
[senf.git] / Console / Config.hh
index 898a02a..f5804b7 100644 (file)
 #include "Executor.hh"
 
 //#include "Config.mpp"
+#include "Config.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
 namespace console {
 
-    /** \brief Console node tree based config file parser
+    /** \brief Combine multiple configuration sources
 
-        A ConfigFile instance allows flexible parsing of a config file against the console node
-        tree. If you just want to parse a file completely, the senf::console::readConfig() function
-        will do that. ConfigFile however allows to incrementally parse only a subdirectory of the
-        complete configuration file.
+        A ConfigBundle combines several sources and parses them together, in the order they were
+        added. Parse restrictions are applied uniformly to all sources.
         \code
-        senf::console::ConfigFile cf ("/my/config/file")
+        // Add three configuration sources: A system configuration file, a user configuration file
+        // and command line options
+        senf::console::ConfigBundle conf;
+        conf.add( senf::console::FileConfig("/etc/some.conf") );
+        conf.add( senf::console::FileConfig("local.conf") );
+        conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(),
+                                               senf::Daemon::instance().argv()) );
+
+        conf.parse();
+        \endcode
 
-        // Parse only statements under the directory of some object. The object 'ob'
-        // must have been registered somewhere in the node tree
-        cf.parse(ob.dir);
+        This bundle may also be passed to other code which may use restricted parsing to parse
+        partial information from all configuration sources.
         
-        // Parse rest of the config file
-        cf.parse();
-        \endcode
+        \ingroup console_access
       */
-    class ConfigFile
-        : boost::noncopyable
+    class ConfigBundle
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
 
-        explicit ConfigFile(std::string const & filename, DirectoryNode & root = root());
-                                        ///< Create ConfigFile object for \a filename
-                                        /**< The \a filename configuration file will be parsed using
-                                             parse() calls. All configuration statements will be
-                                             interpreted relative to \a root as root node. */
+        ConfigBundle();
+        ConfigBundle(DirectoryNode & root); ///< Set custom root node
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
+        template <class Source>
+        Source & add(boost::intrusive_ptr<Source> source);
+                                        ///< Add configuration source
+       
         void parse();                   ///< Parse config file
                                         /**< All nodes already parsed are skipped */
         void parse(DirectoryNode & restrict); ///< Parse config file under \a restrict
@@ -79,7 +84,6 @@ namespace console {
 
         bool complete() const;          ///< \c true, if all nodes have been parsed
         bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed
-
         void reset();                   ///< Reset node parse info state
                                         /**< After a call to reset(), all information about already
                                              parsed nodes is cleared. Calling parse() will parse the
@@ -88,37 +92,56 @@ namespace console {
     protected:
 
     private:
-        void policyCallback(DirectoryNode::ptr restrict, DirectoryNode & dir, 
-                            std::string const & item);
+        void parseInternal();
 
-        void insertParsedNode(DirectoryNode::ptr node);
+        typedef std::vector<detail::ConfigSource::ptr> Sources;
 
-        typedef std::vector<DirectoryNode::weak_ptr> ParsedNodes;
+        Sources sources_;
+        detail::RestrictedExecutor executor_;
+    };
 
-        std::string filename_;
-        CommandParser parser_;
-        Executor executor_;
+namespace detail {
+    // hrmpf ... Can't place this into Config.ih ...
 
-        ParsedNodes parsedNodes_;
-    };
+    /** \brief Internal: Provide ConfigBundle facade for a single-source config.
 
-    /** \brief Read configuration file
+        The BundleMixin is used to define supplementary configuration objects for one specific
+        configuration source. A BundleMixin is \e not a ConfigBundle since it has no public \c add()
+        member.
+     */
+    class BundleMixin
+    {
+    public:
+        BundleMixin();
+        BundleMixin(DirectoryNode & root);
 
-        The configuration file \a filename will be loaded, interpreting all node's relative to \a
-        root as root node.
+        void parse();                   ///< Parse config file
+                                        /**< All nodes already parsed are skipped */
+        void parse(DirectoryNode & restrict); ///< Parse config file under \a restrict
+                                        /**< Only nodes which are children of \a restrict are
+                                             parsed.  */
 
-        This function uses a local ConfigFile object to perform the parsing.
+        bool complete() const;          ///< \c true, if all nodes have been parsed
+        bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed
+        void reset();                   ///< Reset node parse info state
+                                        /**< After a call to reset(), all information about already
+                                             parsed nodes is cleared. Calling parse() will parse the
+                                             complete config file again. */
 
-        \related ConfigFile
-     */
-    void readConfig(std::string const & filename, DirectoryNode & root = root());
+    protected:
+        template <class Source>
+        Source & add(boost::intrusive_ptr<Source> source);
+        
+    private:
+        ConfigBundle bundle_;
+    };
 
-}}
+}}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "Config.cci"
 //#include "Config.ct"
-//#include "Config.cti"
+#include "Config.cti"
 #endif
 
 \f