Utils/Logger: Implement more flexible routing parameter parsing in console commands
[senf.git] / Utils / Logger / Target.ih
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Target internal header */
25
26 #ifndef IH_SENF_Utils_Logger_Target_
27 #define IH_SENF_Utils_Logger_Target_ 1
28
29 // Custom includes
30 #include <memory>
31 #include <boost/type_traits/is_same.hpp>
32 #include <boost/static_assert.hpp>
33 #include "../Console/LazyDirectory.hh"
34 #include "../Console/Parse.hh"
35
36 ///////////////////////////////ih.p////////////////////////////////////////
37
38 namespace senf {
39 namespace log {
40 namespace detail {
41
42     struct LogParameters {
43         StreamBase const * stream;
44         AreaBase const * area;
45         unsigned level;
46         void clear();
47         void setDefaults();
48         static LogParameters defaultParameters();
49     };
50
51     std::ostream & operator<<(std::ostream & os, LogParameters const & pm);
52
53     void senf_console_parse_argument(console::ParseCommandInfo::TokensRange const & tokens, 
54                                      LogParameters & out);
55
56     /** \brief Internal: Target registry */
57     class TargetRegistry
58         : public senf::singleton<TargetRegistry>
59     {
60     public:
61         enum Level { 
62             VERBOSE = senf::log::VERBOSE::value, 
63             NOTICE = senf::log::NOTICE::value, 
64             MESSAGE = senf::log::MESSAGE::value, 
65             IMPORTANT = senf::log::IMPORTANT::value, 
66             CRITICAL = senf::log::CRITICAL::value, 
67             FATAL = senf::log::FATAL::value
68         };
69
70         using senf::singleton<TargetRegistry>::instance;
71
72         void write(StreamBase const & stream, AreaBase const & area, unsigned level, 
73                    std::string const & msg);
74
75         void routed();
76         bool fallbackRouting();
77
78         senf::console::ScopedDirectory<> & consoleDir();
79
80         void dynamicTarget(std::auto_ptr<Target> target);
81
82     private:
83         TargetRegistry();
84         ~TargetRegistry();
85         
86         void registerTarget(Target * target, std::string const & name);
87         void unregisterTarget(Target * target);
88
89         void consoleAreas(std::ostream & os);
90         void consoleStreams(std::ostream & os);
91         void consoleWrite(LogParameters parameters, std::string const & msg);
92         void consoleRemoveTarget(Target * target);
93
94         typedef std::set<Target *> Targets;
95         Targets targets_;
96
97         bool fallbackRouting_;
98
99         console::LazyDirectory consoleDir_;
100
101         Targets dynamicTargets_;
102         
103         friend class senf::log::Target;
104         friend class senf::singleton<TargetRegistry>;
105     };
106
107     /** \brief Internal: Write log message */
108     template <class Stream, class Area, class Level>
109     void write(std::string const & msg);
110
111 #ifndef DOXYGEN
112
113     // This code takes the routing target template arguments in any order and sorts them 
114     // by type (Stream, Area and Level).
115
116     senf::mpl::rv<0u> RouteParameterCheck_(...);
117     senf::mpl::rv<1u> RouteParameterCheck_(StreamBase *);
118     senf::mpl::rv<2u> RouteParameterCheck_(AreaBase *);
119     template <class T> senf::mpl::rv<3u> RouteParameterCheck_(T*, typename T::SENFLogArea * = 0);
120     senf::mpl::rv<4u> RouteParameterCheck_(LevelBase *);
121
122     // For g++ 4.0 (at least) we need to provide the fully scoped name for this default value.
123     // no idea why. It works without the scope in 4.1
124     template < class T, class A2, class A1,
125                unsigned type = SENF_MPL_RV( senf::log::detail::RouteParameterCheck_(static_cast<T*>(0)) ) >
126     struct RouteParameters
127     {};
128
129     template <class A2, class A1>
130     struct RouteParameters<mpl::nil,A2,A1,0u>
131         : public RouteParameters<A2,A1,mpl::nil>
132     {};
133
134     struct NilLevel {
135         static unsigned const value = NONE::value;
136     };
137
138     template <>
139     struct RouteParameters<mpl::nil,mpl::nil,mpl::nil,0u>
140     {
141         typedef mpl::nil Stream;
142         typedef mpl::nil Area;
143         typedef NilLevel Level;
144     };
145
146     template <class T, class A2, class A1>
147     struct RouteParameters<T,A2,A1,1u>
148         : public RouteParameters<A2,A1,mpl::nil>
149     {
150         typedef RouteParameters<A2,A1,mpl::nil> base;
151         BOOST_STATIC_ASSERT(( boost::is_same<typename base::Stream, mpl::nil>::value ));
152         typedef T Stream;
153     };
154
155     template <class T, class A2, class A1>
156     struct RouteParameters<T,A2,A1,2u>
157         : public RouteParameters<A2,A1,mpl::nil>
158     {
159         typedef RouteParameters<A2,A1,mpl::nil> base;
160         BOOST_STATIC_ASSERT(( boost::is_same<typename base::Area, mpl::nil>::value ));
161         typedef T Area;
162     };
163
164     template <class T, class A2, class A1>
165     struct RouteParameters<T,A2,A1,3u>
166         : public RouteParameters<A2,A1,mpl::nil>
167     {
168         typedef RouteParameters<A2,A1,mpl::nil> base;
169         BOOST_STATIC_ASSERT(( boost::is_same<typename base::Area, mpl::nil>::value ));
170         typedef typename T::SENFLogArea Area;
171     };
172
173     template <class T, class A2, class A1>
174     struct RouteParameters<T,A2,A1,4u>
175         : public RouteParameters<A2,A1,mpl::nil>
176     {
177         typedef RouteParameters<A2,A1,mpl::nil> base;
178         BOOST_STATIC_ASSERT(( boost::is_same<typename base::Level, NilLevel>::value ));
179         typedef T Level;
180     };
181
182     template <class T, class RV>
183     struct InstanceP
184     {
185         static RV * value() { return & T::instance(); }
186     };
187
188     template <class RV>
189     struct InstanceP<mpl::nil, RV>
190     {
191         static RV * value() { return 0; }
192     };
193
194 #endif
195
196 }}}
197
198 ///////////////////////////////ih.e////////////////////////////////////////
199 #endif
200
201 \f
202 // Local Variables:
203 // mode: c++
204 // fill-column: 100
205 // comment-column: 40
206 // c-file-style: "senf"
207 // indent-tabs-mode: nil
208 // ispell-local-dictionary: "american"
209 // compile-command: "scons -u test"
210 // End: