From: g0dil Date: Mon, 19 May 2008 14:37:08 +0000 (+0000) Subject: Add 'rt' library to build (needed at least by gentoo) X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=7a1093db9def94e1cc1aac873f98e28b92fde889;p=senf.git Add 'rt' library to build (needed at least by gentoo) Console: Restructure ConfigFile::parse and add chroot support Console: Some ConfigFile documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@847 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Config.cc b/Console/Config.cc index 15d3cc5..afb365f 100644 --- a/Console/Config.cc +++ b/Console/Config.cc @@ -35,27 +35,90 @@ /////////////////////////////////////////////////////////////////////////// // senf::console::ConfigFile -prefix_ void senf::console::ConfigFile::parse() +#ifndef DOXYGEN + +namespace { + struct BindPolicy + { + BindPolicy(senf::console::Executor & e, senf::console::Executor::SecurityPolicy p) + : e_ (e) + { e_.policy(p); } + + ~BindPolicy() + { e_.policy(senf::console::Executor::SecurityPolicy()); } + + senf::console::Executor & e_; + }; +} + +#endif + +prefix_ void senf::console::ConfigFile::parse(DirectoryNode & restrict) { + DirectoryNode::ptr r (restrict.thisptr()); + BindPolicy bp ( executor_, + boost::bind(&ConfigFile::policyCallback, this, r, _1, _2) ); if (! parser_.parseFile(filename_, boost::bind( boost::ref(executor_), boost::ref(std::cerr), _1 )) ) throw SyntaxErrorException(); + insertParsedNode(r); } -prefix_ void senf::console::ConfigFile::parse(DirectoryNode & restrict) +prefix_ bool senf::console::ConfigFile::parsed(GenericNode & node) + const +{ + ParsedNodes::const_iterator i (parsedNodes_.begin()); + ParsedNodes::const_iterator const i_end (parsedNodes_.end()); + for (; i != i_end; ++i) + if ( ! i->expired() && node.isChildOf(*(i->lock())) ) + return true; + return false; +} + +prefix_ void senf::console::ConfigFile::policyCallback(DirectoryNode::ptr restrict, + DirectoryNode & dir, + std::string const & name) +{ + if (dir.hasChild(name)) { + GenericNode & item (dir.get(name)); + if (restrict && ! item.isChildOf(*restrict)) { + DirectoryNode * itemdir (dynamic_cast(&item)); + if (! itemdir || ! restrict->isChildOf(*itemdir)) + throw Executor::IgnoreCommandException(); + } + if (parsed(item)) + throw Executor::IgnoreCommandException(); + } + else if (restrict && ! dir.isChildOf(*restrict)) + throw Executor::IgnoreCommandException(); +} + +namespace { + struct RemoveNodesFn + { + RemoveNodesFn(senf::console::DirectoryNode::ptr newNode) : newNode_ (newNode) {} + + bool operator()(senf::console::DirectoryNode::weak_ptr node) const + { return node.expired() || node.lock()->isChildOf(*newNode_); } + + senf::console::DirectoryNode::ptr newNode_; + }; +} + +prefix_ void senf::console::ConfigFile::insertParsedNode(DirectoryNode::ptr node) { - restrict_ = restrict.thisptr(); - parse(); - parsedNodes_.push_back(restrict_); - restrict_.reset(); + parsedNodes_.erase( + std::remove_if(parsedNodes_.begin(), parsedNodes_.end(), RemoveNodesFn(node)), + parsedNodes_.end()); + parsedNodes_.push_back(node); } /////////////////////////////////////////////////////////////////////////// -prefix_ void senf::console::readConfig(std::string const & filename) +prefix_ void senf::console::readConfig(std::string const & filename, DirectoryNode & root) { - ConfigFile cfg (filename); + ConfigFile cfg (filename, root); cfg.parse(); } diff --git a/Console/Config.cci b/Console/Config.cci index f4e42bc..3c96a59 100644 --- a/Console/Config.cci +++ b/Console/Config.cci @@ -34,33 +34,29 @@ /////////////////////////////////////////////////////////////////////////// // senf::console::ConfigFile -prefix_ senf::console::ConfigFile::ConfigFile(std::string const & filename) +prefix_ senf::console::ConfigFile::ConfigFile(std::string const & filename, + DirectoryNode & root) : filename_ (filename) { - executor_.policy(senf::membind(&ConfigFile::policyCallback, this)); + executor_.chroot(root); } -prefix_ void senf::console::ConfigFile::policyCallback(DirectoryNode & dir, - std::string const & name) +prefix_ void senf::console::ConfigFile::parse() { - if (dir.hasChild(name)) { - GenericNode & item (dir.get(name)); - if (restrict_ && ! item.isChildOf(*restrict_)) { - DirectoryNode * itemdir (dynamic_cast(&item)); - if (! itemdir || ! restrict_->isChildOf(*itemdir)) - throw Executor::IgnoreCommandException(); - } - ParsedNodes::const_iterator i (parsedNodes_.begin()); - ParsedNodes::const_iterator const i_end (parsedNodes_.end()); - for (; i != i_end; ++i) { - if ( ! i->expired() && item.isChildOf(*(i->lock())) ) - throw Executor::IgnoreCommandException(); - } - } - else { - if (restrict_ && ! dir.isChildOf(*restrict_)) - throw Executor::IgnoreCommandException(); - } + parse(executor_.chroot()); +} + +prefix_ bool senf::console::ConfigFile::complete() + const +{ + return parsedNodes_.size() == 1 + && ! parsedNodes_[0].expired() + && *parsedNodes_[0].lock() == executor_.chroot(); +} + +prefix_ void senf::console::ConfigFile::reset() +{ + parsedNodes_.clear(); } ///////////////////////////////cci.e/////////////////////////////////////// diff --git a/Console/Config.hh b/Console/Config.hh index ce74973..898a02a 100644 --- a/Console/Config.hh +++ b/Console/Config.hh @@ -37,7 +37,22 @@ namespace senf { namespace console { - /** \brief + /** \brief Console node tree based config file parser + + 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. + \code + senf::console::ConfigFile cf ("/my/config/file") + + // 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); + + // Parse rest of the config file + cf.parse(); + \endcode */ class ConfigFile : boost::noncopyable @@ -47,18 +62,36 @@ namespace console { ///\name Structors and default members ///@{ - explicit ConfigFile(std::string const & filename); + 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. */ ///@} /////////////////////////////////////////////////////////////////////////// - void parse(); - void parse(DirectoryNode & restrict); + 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. */ + + 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. */ protected: private: - void policyCallback(DirectoryNode & dir, std::string const & item); + void policyCallback(DirectoryNode::ptr restrict, DirectoryNode & dir, + std::string const & item); + + void insertParsedNode(DirectoryNode::ptr node); typedef std::vector ParsedNodes; @@ -66,11 +99,19 @@ namespace console { CommandParser parser_; Executor executor_; - DirectoryNode::ptr restrict_; ParsedNodes parsedNodes_; }; - void readConfig(std::string const & filename); + /** \brief Read configuration file + + The configuration file \a filename will be loaded, interpreting all node's relative to \a + root as root node. + + This function uses a local ConfigFile object to perform the parsing. + + \related ConfigFile + */ + void readConfig(std::string const & filename, DirectoryNode & root = root()); }} diff --git a/Console/Config.test.cc b/Console/Config.test.cc index df5c070..2215cce 100644 --- a/Console/Config.test.cc +++ b/Console/Config.test.cc @@ -76,8 +76,18 @@ BOOST_AUTO_UNIT_TEST(configFile) dir1.add("fun1",&fun1); { - var1 = 0; senf::console::ConfigFile cfg (cfgf.name()); + + var1 = 0; + SENF_CHECK_NO_THROW( cfg.parse() ) + BOOST_CHECK_EQUAL( var1, 10 ); + + var1 = 0; + SENF_CHECK_NO_THROW( cfg.parse() ) + BOOST_CHECK_EQUAL( var1, 0 ); + + var1 = 0; + cfg.reset(); SENF_CHECK_NO_THROW( cfg.parse() ) BOOST_CHECK_EQUAL( var1, 10 ); } @@ -98,9 +108,11 @@ BOOST_AUTO_UNIT_TEST(configFileRestrict) var1 = 0; var2 = false; senf::console::ConfigFile cfg (cfgf.name()); - SENF_CHECK_NO_THROW( cfg.parse(dir1.node()) ); + SENF_CHECK_NO_THROW( cfg.parse(dir1) ); BOOST_CHECK_EQUAL( var1, 10 ); BOOST_CHECK_EQUAL( var2, false ); + BOOST_CHECK( cfg.parsed(dir1) ); + BOOST_CHECK( ! cfg.complete() ); senf::console::ScopedDirectory<> dir2; senf::console::root().add("dir2", dir2); @@ -111,6 +123,7 @@ BOOST_AUTO_UNIT_TEST(configFileRestrict) SENF_CHECK_NO_THROW( cfg.parse() ); BOOST_CHECK_EQUAL( var1, 0 ); BOOST_CHECK_EQUAL( var2, true ); + BOOST_CHECK( cfg.complete() ); } } @@ -135,15 +148,17 @@ BOOST_AUTO_UNIT_TEST(configFileSkipGroup) var1 = 0; var2 = false; senf::console::ConfigFile cfg (cfgf.name()); - SENF_CHECK_NO_THROW( cfg.parse(dir1.node()) ); + SENF_CHECK_NO_THROW( cfg.parse(dir1) ); BOOST_CHECK_EQUAL( var1, 10 ); BOOST_CHECK_EQUAL( var2, false ); + BOOST_CHECK( cfg.parsed(dir1) ); var1 = 0; var2 = false; SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) ); BOOST_CHECK_EQUAL( var1, 0 ); BOOST_CHECK_EQUAL( var2, true ); + BOOST_CHECK( ! cfg.parsed(dir2) ); var1 = 0; var2 = false; diff --git a/Console/Executor.hh b/Console/Executor.hh index 5cdd1f7..2c21ee1 100644 --- a/Console/Executor.hh +++ b/Console/Executor.hh @@ -120,7 +120,7 @@ namespace console { are accessible via the executor. This value defaults to senf::console::root(). */ - Executor & policy(SecurityPolicy policy); ///< Set security policy + Executor & policy(SecurityPolicy policy = SecurityPolicy()); ///< Set security policy /**< The security policy is called before traversing a node to validate that access. */ diff --git a/Console/ScopedDirectory.cci b/Console/ScopedDirectory.cci index 6f19b12..c94e1c0 100644 --- a/Console/ScopedDirectory.cci +++ b/Console/ScopedDirectory.cci @@ -39,6 +39,12 @@ prefix_ senf::console::DirectoryNode & senf::console::ScopedDirectoryBase::node( return *node_; } +prefix_ senf::console::ScopedDirectoryBase::operator DirectoryNode &() + const +{ + return node(); +} + prefix_ senf::console::GenericNode::ptr senf::console::ScopedDirectoryBase::remove(std::string const & name) { diff --git a/Console/ScopedDirectory.hh b/Console/ScopedDirectory.hh index cd5b9b4..89da74b 100644 --- a/Console/ScopedDirectory.hh +++ b/Console/ScopedDirectory.hh @@ -69,6 +69,7 @@ namespace console { { public: DirectoryNode & node() const; ///< Access the proxied DirectoryNode + operator DirectoryNode & () const; ///< Access the proxied DirectoryNode /////////////////////////////////////////////////////////////////////////// ///\name Proxied members (see DirectoryNode) diff --git a/SConstruct b/SConstruct index fce3c2d..19eadb3 100644 --- a/SConstruct +++ b/SConstruct @@ -142,7 +142,7 @@ def configFilesOpts(target, source, env, for_signature): env.Append( CPPPATH = [ '#/include' ], - LIBS = [ 'readline', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB' ], + LIBS = [ 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB' ], TEST_EXTRA_LIBS = [ '$BOOSTFSLIB' ], DOXY_XREF_TYPES = [ 'bug', 'fixme', 'todo', 'idea' ], DOXY_HTML_XSL = '#/doclib/html-munge.xsl', diff --git a/senfscons/senfutil.py b/senfscons/senfutil.py index c3ef1b2..249a78d 100644 --- a/senfscons/senfutil.py +++ b/senfscons/senfutil.py @@ -8,7 +8,7 @@ from SCons.Script import * # c) check for a local SENF, set options accordingly and update that SENF if needed def SetupForSENF(env): - env.Append( LIBS = [ 'senf', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB' ], + env.Append( LIBS = [ 'senf', 'readline', 'rt', '$BOOSTREGEXLIB', '$BOOSTIOSTREAMSLIB' ], BOOSTREGEXLIB = 'boost_regex', BOOSTIOSTREAMSLIB = 'boost_iostreams', CXXFLAGS = [ '-Wno-long-long',