Utils/Logger: Implement Area and Stream registry
g0dil [Thu, 11 Oct 2007 08:07:14 +0000 (08:07 +0000)]
Utils/Logger: New SENF_LOG_CONF syntax supporting not-yet-declared areas and streams
Utils/Logger: Target baseclass

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@461 270642c3-0616-0410-b53a-bc976706d245

17 files changed:
Utils/Logger/Area.cci [new file with mode: 0644]
Utils/Logger/Area.hh
Utils/Logger/Area.ih
Utils/Logger/Config.ih
Utils/Logger/Defaults.hh
Utils/Logger/Log.test.cc
Utils/Logger/Parameters.hh
Utils/Logger/SConscript
Utils/Logger/Stream.cc [new file with mode: 0644]
Utils/Logger/Stream.cci [new file with mode: 0644]
Utils/Logger/Stream.hh
Utils/Logger/Stream.ih
Utils/Logger/Target.cc [new file with mode: 0644]
Utils/Logger/Target.cci [new file with mode: 0644]
Utils/Logger/Target.hh [new file with mode: 0644]
Utils/SConscript
Utils/preprocessor.hh [new file with mode: 0644]

diff --git a/Utils/Logger/Area.cci b/Utils/Logger/Area.cci
new file mode 100644 (file)
index 0000000..58a59cb
--- /dev/null
@@ -0,0 +1,110 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Area inline non-template implementation */
+
+#include "Area.ih"
+
+// Custom includes
+#include "../TypeInfo.hh"
+#include "Levels.hh"
+#include "Stream.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::AreaRegistry
+
+prefix_ std::string const &
+senf::log::AreaRegistry::SelectName::operator()(Registry::value_type const & v)
+    const
+{
+    return v.first;
+}
+
+prefix_ senf::log::AreaRegistry::AreaRegistry()
+{}
+
+prefix_ senf::log::AreaRegistry::iterator senf::log::AreaRegistry::begin()
+{
+    return boost::make_transform_iterator(registry_.begin(), SelectName());
+}
+
+prefix_ senf::log::AreaRegistry::iterator senf::log::AreaRegistry::end()
+{
+    return boost::make_transform_iterator(registry_.end(), SelectName());
+}
+
+prefix_ void senf::log::AreaRegistry::registerArea(detail::AreaBase const & area)
+{
+    registry_.insert( std::make_pair(area.v_name(), &area) );
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::detail::AreaBase
+
+prefix_ std::string senf::log::detail::AreaBase::fullName()
+    const
+{
+    return prettyName(typeid(*this));
+}
+
+prefix_ std::string senf::log::detail::AreaBase::v_name()
+    const
+{
+    return fullName();
+}
+
+prefix_ void senf::log::detail::AreaBase::init()
+{
+    senf::log::AreaRegistry::instance().registerArea(*this);
+}
+
+prefix_ unsigned senf::log::detail::AreaBase::streamLimit(StreamBase const & stream)
+    const
+{
+    return stream.index >= streamLimits_.size() ? DISABLED::value : streamLimits_[stream.index];
+}
+
+prefix_ void senf::log::detail::AreaBase::setStreamLimit(StreamBase const & stream, unsigned value)
+    const
+{
+    if (stream.index >= streamLimits_.size())
+        streamLimits_.resize(stream.index+1,0u);
+    streamLimits_[stream.index] = value;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 20ff5db..648bd8c 100644 (file)
 #define HH_Area_ 1
 
 // Custom includes
+#include <map>
+#include <functional>
+#include <boost/iterator/transform_iterator.hpp>
+#include "../singleton.hh"
 
 //#include "Area.mpp"
-#include "Area.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 /** \brief Define log area
 
     \hideinitializer
  */
-#define SENF_LOG_DEF_AREA(area)                                                                   \
-    struct area                                                                                   \
-        : public senf::log::detail::AreaBase                                                      \
-    {}
+#define SENF_LOG_DEF_AREA(area) SENF_LOG_DEF_AREA_I(area, ; )
+
+namespace senf {
+namespace log { 
+
+    namespace detail { struct AreaBase; }
+    
+    class AreaRegistry
+        : public senf::singleton<AreaRegistry>
+    {
+        typedef std::map<std::string, detail::AreaBase const *> Registry;
+
+        struct SelectName 
+        {
+            typedef std::string result_type;
+            std::string const & operator()(Registry::value_type const & v) const;
+        };
+
+    public:
+        typedef boost::transform_iterator<SelectName, Registry::const_iterator> iterator;
+
+        using senf::singleton<AreaRegistry>::instance;
+
+        iterator begin();
+        iterator end();
+
+    private:
+        AreaRegistry();
+
+        void registerArea(detail::AreaBase const & area);
+
+        Registry registry_;
+
+        friend class senf::singleton<AreaRegistry>;
+        friend class detail::AreaBase;
+        friend class Target;
+    };        
+    
+}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "Area.cci"
+#include "Area.cci"
 //#include "Area.ct"
 //#include "Area.cti"
 #endif
index d5ddbf3..168ecb0 100644 (file)
@@ -27,6 +27,8 @@
 #define IH_Area_ 1
 
 // Custom includes
+#include <string>
+#include <vector>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -34,11 +36,39 @@ namespace senf {
 namespace log {
 namespace detail {
 
+    class StreamBase;
+
     struct AreaBase
-    {};
+    {
+        virtual ~AreaBase() {};
+        
+        std::string fullName() const;
+        virtual std::string v_name() const;
+
+        void init();
+
+        unsigned streamLimit(StreamBase const & stream) const;
+        void setStreamLimit(StreamBase const & stream, unsigned value) const;
+
+    private:
+        typedef std::vector<unsigned> StreamLimits;
+        // mutable since this is a cache and may therefore change at unexpected places ...
+        mutable StreamLimits streamLimits_;
+    };
 
 }}}
 
+#define SENF_LOG_DEF_AREA_I(area, decls)                                                          \
+    struct area                                                                                   \
+        : public senf::log::detail::AreaBase, public senf::singleton<area>                        \
+    {                                                                                             \
+        static std::string name() { return instance().v_name(); }                                 \
+        decls                                                                                     \
+    private:                                                                                      \
+        area() { init(); }                                                                        \
+        friend class senf::singleton<area>;                                                       \
+    }
+
 ///////////////////////////////ih.e////////////////////////////////////////
 #endif
 
index dae740d..10b9e4a 100644 (file)
 #include <boost/preprocessor/expand.hpp>
 #include <boost/preprocessor/seq/for_each.hpp>
 #include <boost/preprocessor/seq/to_tuple.hpp>
-#include "Defaults.hh"
+#include <boost/preprocessor/seq/fold_right.hpp>
+#include <boost/preprocessor/seq/pop_back.hpp>
+#include <boost/preprocessor/if.hpp>
+#include "../preprocessor.hh"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -50,25 +53,49 @@ namespace detail {
         typedef typename Stream::compileLimit compileLimit;
     };
 
-#   define SENF_LOG_CONF_DEFINE(stream, area, level)                                              \
-           template <>                                                                            \
-           struct Config<stream, area>                                                            \
-           { typedef senf::log::level compileLimit; };
+}}}
 
-#   ifdef SENF_LOG_CONF
+#define SENF_LOG_SEQ_TO_NAME_(s,data,elem) ::elem
 
-#       define _ void
-#       define SLC_elt(r, data, elt) \
-            BOOST_PP_EXPAND(SENF_LOG_CONF_DEFINE BOOST_PP_SEQ_TO_TUPLE(elt))
+#define SENF_LOG_SEQ_TO_NAME(seq)                                                                 \
+    BOOST_PP_SEQ_FOR_EACH(SENF_LOG_SEQ_TO_NAME_, none, seq)
 
-        BOOST_PP_SEQ_FOR_EACH(SLC_elt, x, SENF_LOG_CONF)
+#define SENF_LOG_PREDECL_(s, state, elem)                                                         \
+    namespace elem { state }
 
-#       undef SLC_elt
-#       undef _
+#define SENF_LOG_PREDECL(seq)                                                                     \
+    BOOST_PP_SEQ_FOLD_RIGHT( SENF_LOG_PREDECL_,                                                   \
+                             class SENF_PP_SEQ_BACK(seq);,                                        \
+                             BOOST_PP_SEQ_POP_BACK(seq) )
 
-#   endif
+#define SENF_LOG_NIL(x)
+
+#define SENF_LOG_CONF_DEFINE(stream, area, level)                                                 \
+    SENF_LOG_PREDECL(stream)                                                                      \
+    BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(area)),                                            \
+                SENF_LOG_PREDECL,                                                                 \
+                SENF_LOG_NIL)(area)                                                               \
+    namespace senf { namespace log { namespace detail {                                           \
+        template <>                                                                               \
+        struct Config< SENF_LOG_SEQ_TO_NAME(stream),                                              \
+                       BOOST_PP_IF(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(area)),                         \
+                                   SENF_LOG_SEQ_TO_NAME(area),                                    \
+                                   void) >                                                        \
+        { typedef senf::log::level compileLimit; };                                               \
+    }}}
+
+#ifdef SENF_LOG_CONF
+
+#   define SLC_elt(s, state, elt)                                                                  \
+        SENF_LOG_CONF_DEFINE elt
+
+    // Need to use fold here to not exhaust the maximum FOR nesting depth ...
+    BOOST_PP_SEQ_FOLD_LEFT(SLC_elt, none, SENF_LOG_CONF)
+
+#   undef SLC_elt
+
+#endif
 
-}}}
 
 
 
index 833f8f0..a6d6340 100644 (file)
@@ -37,7 +37,9 @@ namespace senf {
 namespace log {
 
     SENF_LOG_DEF_STREAM(Debug, MESSAGE, DISABLED, DISABLED);
-    SENF_LOG_DEF_AREA(DefaultArea);
+
+    SENF_LOG_DEF_AREA_I(DefaultArea,
+                        std::string v_name() const { return ""; });
 
 }}
 
index d57d625..cc31c61 100644 (file)
 // Custom includes
 #include <sstream>
 
+// We need to put all tests into this single file to not violate the ODR
+
 #define _senf_LOG_STREAM logstream
 namespace {
     std::stringstream logstream;
 }
 
-#define SENF_LOG_CONF ((senf::log::Debug)(_)(VERBOSE))
+#define SENF_LOG_CONF (( (senf)(log)(Debug), (_), NOTICE ))
 
 #include "Log.hh"
 #include "Defaults.hh"
@@ -55,7 +57,7 @@ namespace {
         typedef int value;
     };
 
-    SENF_LOG_DEF_ALIAS( LogFoo, (senf::log::Debug) (senf::log::CRITICAL) );
+    SENF_LOG_DEF_ALIAS( LogCritical, (senf::log::Debug) (senf::log::CRITICAL) );
     SENF_LOG_DEF_STREAM( myStream, senf::log::MESSAGE, senf::log::MESSAGE, senf::log::MESSAGE );
     SENF_LOG_DEF_AREA( myArea );
 
@@ -65,11 +67,14 @@ BOOST_AUTO_UNIT_TEST(logger)
 {
     SENF_LOG_DEFAULT_STREAM(senf::log::Debug);
     SENF_LOG_DEFAULT_AREA(senf::log::DefaultArea);
-    SENF_LOG_DEFAULT_LEVEL(senf::log::NOTICE);
+    SENF_LOG_DEFAULT_LEVEL(senf::log::VERBOSE);
 
+    // should be disabled
     SENF_LOG(("Log message"));
-
-    SENF_LOG((LogFoo) ("Another log message: " << 10));
+    SENF_LOG((senf::log::VERBOSE)("Log message 2"));
+    // should be enabled
+    SENF_LOG((senf::log::IMPORTANT)("Important message"));
+    SENF_LOG((LogCritical) ("Another log message: " << 10));
 
     SENF_LOG_BLOCK((senf::log::Debug) (senf::log::IMPORTANT) ({
         log << "Last message";
@@ -77,7 +82,29 @@ BOOST_AUTO_UNIT_TEST(logger)
     }));
 
     BOOST_CHECK_EQUAL( logstream.str(), 
-                       "Log message\nAnother log message: 10\nLast message continued here\n" );
+                       "Important message\n"
+                       "Another log message: 10\n"
+                       "Last message continued here\n" );
+}
+
+BOOST_AUTO_UNIT_TEST(streamRegistry)
+{
+    char const * streams[] = { "(anonymous namespace)::myStream", "senf::log::Debug" };
+
+    BOOST_CHECK_EQUAL_COLLECTIONS( senf::log::StreamRegistry::instance().begin(),
+                                   senf::log::StreamRegistry::instance().end(),
+                                   streams, streams+sizeof(streams)/sizeof(streams[0]) );
+    BOOST_CHECK_EQUAL( senf::log::detail::StreamBase::nStreams, 2u );
+}
+
+BOOST_AUTO_UNIT_TEST(areaRegistry)
+{
+    char const * areas[] = { "", "(anonymous namespace)::myArea" };
+
+    BOOST_CHECK_EQUAL_COLLECTIONS( senf::log::AreaRegistry::instance().begin(),
+                                   senf::log::AreaRegistry::instance().end(),
+                                   areas, areas+sizeof(areas)/sizeof(areas[0]) );
+
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index c34d308..e811cb1 100644 (file)
@@ -27,6 +27,7 @@
 #define HH_Parameters_ 1
 
 // Custom includes
+#include "Area.hh"
 
 //#include "Parameters.mpp"
 #include "Parameters.ih"
         };                                                                                        \
     }
 
+#define SENF_LOG_CLASS_AREA()                                                                     \
+    SENF_LOG_DEF_AREA_I(SenfLogArea,                                                              \
+                        std::string v_name() const                                                \
+                            { std::string s (fullName()); return std::string(s,s.size()-13); });  \
+    SENF_LOG_DEFAULT_AREA(SenfLogArea)
+
+
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "Parameters.cci"
 //#include "Parameters.ct"
index bd53fae..138b282 100644 (file)
@@ -10,7 +10,7 @@ SENFSCons.StandardTargets(env)
 SENFSCons.AllIncludesHH(env, [ f for f in glob.glob("*.hh")
                                if f not in ('all_includes.hh','INet.hh') and not f.endswith('.test.hh') ])
 sources = SENFSCons.GlobSources()
-objects = SENFSCons.Objects( env, sources = sources )
+objects = SENFSCons.Objects( env, sources = sources, LIBS = [ 'Utils' ] )
 
 SENFSCons.Doxygen(env)
 
diff --git a/Utils/Logger/Stream.cc b/Utils/Logger/Stream.cc
new file mode 100644 (file)
index 0000000..e3c37e0
--- /dev/null
@@ -0,0 +1,50 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Stream non-inline non-template implementation */
+
+#include "Stream.hh"
+#include "Stream.ih"
+
+// Custom includes
+
+//#include "Stream.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+unsigned senf::log::detail::StreamBase::nStreams = 0;
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Stream.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/Logger/Stream.cci b/Utils/Logger/Stream.cci
new file mode 100644 (file)
index 0000000..f106291
--- /dev/null
@@ -0,0 +1,98 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Stream inline non-template implementation */
+
+#include "Stream.ih"
+
+// Custom includes
+#include "../TypeInfo.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::StreamRegistry
+
+prefix_ std::string const &
+senf::log::StreamRegistry::SelectName::operator()(Registry::value_type const & v)
+    const
+{
+    return v.first;
+}
+
+prefix_ senf::log::StreamRegistry::StreamRegistry()
+{}
+
+prefix_ senf::log::StreamRegistry::iterator senf::log::StreamRegistry::begin()
+{
+    return boost::make_transform_iterator(registry_.begin(), SelectName());
+}
+
+prefix_ senf::log::StreamRegistry::iterator senf::log::StreamRegistry::end()
+{
+    return boost::make_transform_iterator(registry_.end(), SelectName());
+}
+
+prefix_ void senf::log::StreamRegistry::registerStream(detail::StreamBase const & stream)
+{
+    registry_.insert( std::make_pair(stream.v_name(), &stream) );
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::detail::StreamBase
+
+prefix_ senf::log::detail::StreamBase::StreamBase()
+    : index( nStreams++ )
+{}
+
+prefix_ std::string senf::log::detail::StreamBase::fullName()
+    const
+{
+    return prettyName(typeid(*this));
+}
+
+prefix_ std::string senf::log::detail::StreamBase::v_name()
+    const
+{
+    return fullName();
+}
+
+prefix_ void senf::log::detail::StreamBase::init()
+{
+    senf::log::StreamRegistry::instance().registerStream(*this);
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index b4bab97..d30d2ca 100644 (file)
 #define HH_Stream_ 1
 
 // Custom includes
+#include <map>
+#include <functional>
+#include <boost/iterator/transform_iterator.hpp>
 #include "Levels.hh"
+#include "../singleton.hh"
 
 //#include "Stream.mpp"
-#include "Stream.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 /** \brief Define log stream
  */
 #define SENF_LOG_DEF_STREAM(stream, defaultLevel_, runtimeLimit_, compileLimit_)                  \
     struct stream                                                                                 \
-        : public senf::log::detail::StreamBase                                                    \
+        : public senf::log::detail::StreamBase, public senf::singleton<stream>                    \
     {                                                                                             \
         typedef defaultLevel_ defaultLevel;                                                       \
         typedef runtimeLimit_ runtimeLimit;                                                       \
         typedef compileLimit_ compileLimit;                                                       \
-                                                                                                  \
-        static char const * name() { return #stream ; }                                           \
-        virtual char const * v_name() { return name(); }                                          \
+        static std::string name() { return instance().v_name(); }                                 \
+    private:                                                                                      \
+        stream() { init(); }                                                                      \
+        friend class senf::singleton<stream>;                                                     \
     }
 
-///////////////////////////////hh.e////////////////////////////////////////
-//#include "Stream.cci"
+namespace senf {
+namespace log {
+
+    namespace detail { struct StreamBase; }
+
+    class StreamRegistry 
+        : public senf::singleton<StreamRegistry>
+    {
+        typedef std::map<std::string, detail::StreamBase const *> Registry;
+
+        struct SelectName 
+        {
+            typedef std::string result_type;
+            std::string const & operator()(Registry::value_type const & v) const;
+        };
+
+    public:
+        typedef boost::transform_iterator<SelectName, Registry::const_iterator> iterator;
+
+        using senf::singleton<StreamRegistry>::instance;
+
+        iterator begin();
+        iterator end();
+
+    private:
+        StreamRegistry();
+
+        void registerStream(detail::StreamBase const & stream);
+
+        Registry registry_;
+
+        friend class senf::singleton<StreamRegistry>;
+        friend class detail::StreamBase;
+        friend class Target;
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////#
+#include "Stream.cci"
 //#include "Stream.ct"
 //#include "Stream.cti"
 #endif
index 55b2dd2..a2db435 100644 (file)
@@ -27,6 +27,7 @@
 #define IH_Stream_ 1
 
 // Custom includes
+#include <string>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -36,8 +37,16 @@ namespace detail {
 
     struct StreamBase 
     {
+        StreamBase();
         virtual ~StreamBase() {};
-        virtual char const * v_name() = 0;
+        
+        std::string fullName() const;
+        virtual std::string v_name() const;
+
+        void init();
+
+        unsigned index;
+        static unsigned nStreams;
     };
 
 }}}
diff --git a/Utils/Logger/Target.cc b/Utils/Logger/Target.cc
new file mode 100644 (file)
index 0000000..651671e
--- /dev/null
@@ -0,0 +1,69 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Target non-inline non-template implementation */
+
+#include "Target.hh"
+//#include "Target.ih"
+
+// Custom includes
+
+//#include "Target.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::Target
+
+prefix_ senf::log::Target::~Target()
+{}
+
+prefix_ void senf::log::Target::write(detail::StreamBase const & stream, 
+                                      detail::AreaBase const & area,
+                                      unsigned level, std::string const & message)
+{
+    RIB::iterator i (rib_.begin());
+    RIB::iterator const i_end (rib_.end());
+    for (; i != i_end; ++i)
+        if ( ( ! i->stream || i->stream == &stream ) &&
+             ( ! i->area || i->area == &area ) &&
+             i->level <= level ) {
+            v_write(stream.v_name(), area.v_name(), level, message);
+            return;
+        }
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Target.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/Logger/Target.cci b/Utils/Logger/Target.cci
new file mode 100644 (file)
index 0000000..07db6d6
--- /dev/null
@@ -0,0 +1,93 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Target inline non-template implementation */
+
+//#include "Target.ih"
+
+// Custom includes
+#include <algorithm>
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::Target
+
+prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
+                                      detail::AreaBase const * area, unsigned level)
+{
+    rib_.push_back(RoutingEntry(stream, area, level));
+
+    // Update the area/stream routing cache
+    if (area)
+        updateAreaCache(*area, stream, level);
+    else {
+        AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin());
+        AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end());
+        for (; i != i_end; ++i)
+            updateAreaCache(*(i->second), stream, level);
+    }
+        
+}
+
+prefix_ void
+senf::log::Target::updateAreaCache(detail::AreaBase const & area,
+                                   detail::StreamBase const * stream, unsigned level)
+{
+    if (stream) {
+        if (level < area.streamLimit(*stream))
+            area.setStreamLimit(*stream, level);
+    } else {
+        StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin());
+        StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end());
+        for(; i != i_end; ++i)
+            if (level < area.streamLimit(*(i->second)))
+                area.setStreamLimit(*(i->second),level);
+    }
+}
+
+prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
+                                        detail::AreaBase const * area, unsigned level)
+{
+    rib_.erase(std::remove(rib_.begin(), rib_.end(), RoutingEntry(stream, area, level)),
+               rib_.end());
+
+    ///\fixme Update area/stream routing cache
+    // Not doing anything here does not produce incorrect behavior, since removing a route
+    // can never lower the logging limit. Not updating the cache just reduces the performance.
+}
+
+/////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/Logger/Target.hh b/Utils/Logger/Target.hh
new file mode 100644 (file)
index 0000000..43ae954
--- /dev/null
@@ -0,0 +1,120 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief Target public header */
+
+#ifndef HH_Target_
+#define HH_Target_ 1
+
+// Custom includes
+#include "../singleton.hh"
+#include "Stream.hh"
+#include "Area.hh"
+
+//#include "Target.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+
+    /** \brief
+      */
+    class Target
+        : public senf::singleton<Target>
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        virtual ~Target();
+
+        // default default constructor
+        // default copy constructor
+        // default copy assignment
+        // default destructor
+
+        // no conversion constructors
+
+        ///@}
+
+    protected:
+
+    private:
+
+        void route(detail::StreamBase const * stream, detail::AreaBase const * area, 
+                   unsigned level);
+        void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, 
+                     unsigned level);
+
+        void updateAreaCache(detail::AreaBase const & area, detail::StreamBase const * stream,
+                             unsigned level);
+
+        void write(detail::StreamBase const & stream, detail::AreaBase const & area, 
+                   unsigned level, std::string const & message);
+        
+        virtual void v_write(std::string const & stream, std::string const & area, unsigned level,
+                             std::string const & message) = 0;
+
+        struct RoutingEntry 
+        {
+            RoutingEntry(detail::StreamBase const * stream_, detail::AreaBase const * area_, 
+                         unsigned level_)
+                : stream(stream_), area(area_), level(level_) {}
+            RoutingEntry() 
+                : stream(0), area(0), level(0) {}
+
+            bool operator==(RoutingEntry const & other) 
+                { return stream == other.stream && area == other.area && level == other.level; }
+
+            detail::StreamBase const * stream;
+            detail::AreaBase const * area;
+            unsigned level;
+        };
+
+        typedef std::vector<RoutingEntry> RIB;
+
+        RIB rib_;
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Target.cci"
+//#include "Target.ct"
+//#include "Target.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 8d67e70..561137b 100644 (file)
@@ -8,7 +8,7 @@ import SENFSCons, glob
 SENFSCons.StandardTargets(env)
 
 sources, testSources = SENFSCons.GlobSources()
-objects = SENFSCons.Objects( env, sources = sources )
+objects = SENFSCons.Objects( env, sources = sources, testSources=testSources )
 
 for sc in glob.glob("*/SConscript"):
     ob = SConscript(sc)
diff --git a/Utils/preprocessor.hh b/Utils/preprocessor.hh
new file mode 100644 (file)
index 0000000..c51605a
--- /dev/null
@@ -0,0 +1,54 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief preprocessor public header */
+
+#ifndef HH_preprocessor_
+#define HH_preprocessor_ 1
+
+// Custom includes
+#include <boost/preprocessor/seq/size.hpp>
+#include <boost/preprocessor/seq/elem.hpp>
+#include <boost/preprocessor/dec.hpp>
+
+//#include "preprocessor.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+#define SENF_PP_SEQ_BACK(seq) BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)),seq)
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "preprocessor.cci"
+//#include "preprocessor.ct"
+//#include "preprocessor.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End: