Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2007-10-19 08:12:16


Author: jtorjo
Date: 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
New Revision: 40182
URL: http://svn.boost.org/trac/boost/changeset/40182

Log:
[logging]
v0.7.3, 19 oct 2007
- added the manipulator::class_ concept
- added some documentation

Added:
   sandbox/logging/boost/logging/detail/raw_doc/common_usage.hpp (contents, props changed)
   sandbox/logging/boost/logging/detail/raw_doc/customize_manipulator.hpp (contents, props changed)
Removed:
   sandbox/logging/lib/logging/doc/html/
Text files modified:
   sandbox/logging/boost/logging/detail/manipulator.hpp | 301 ++++++++++++++++++++++++---------------
   sandbox/logging/boost/logging/detail/raw_doc/main.hpp | 2
   sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp | 9
   sandbox/logging/boost/logging/format.hpp | 2
   sandbox/logging/boost/logging/format/destination/defaults.hpp | 2
   sandbox/logging/boost/logging/format/formatter/defaults.hpp | 4
   sandbox/logging/boost/logging/format/formatter/time.hpp | 12
   sandbox/logging/lib/logging/samples/vc8/loggingvc8/loggingvc8.vcproj | 15 +
   sandbox/logging/lib/logging/src/changelog.txt | 12 +
   sandbox/logging/lib/logging/tests/format/test_manip_w_msgroute.cpp | 14 -
   sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp | 16 +-
   11 files changed, 245 insertions(+), 144 deletions(-)

Modified: sandbox/logging/boost/logging/detail/manipulator.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/manipulator.hpp (original)
+++ sandbox/logging/boost/logging/detail/manipulator.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -26,193 +26,235 @@
 namespace boost { namespace logging {
 
 
+typedef enum implement_op_equal {
+ op_equal_no_context,
+ op_equal_has_context
+};
+
+
 /**
 @brief Manipulators = Formatters and/or destinations.
 
+
+- @ref manipulator_common
+- @ref manipulator_base_class
+- @ref manipulator_generic
+- @ref manipulator_create
+- @ref manipulator_share_data
+
+
+
+\n\n\n
+@section manipulator_common Common base class
+
 All formatters need to derive from a <b>common %base class</b>. Same goes for destinations.
 
 Remember:
 - formatter - allows formatting the message before writing it (like, prepending extra information - an index, the time, thread id, etc)
 - destination - is a place where the message is to be written to (like, the console, a file, a socket, etc)
 
-In your @ref boost::logging::writer::format_write "format_write" object, you can have several formatters and destinations. Note that each formatter class and each destination class is a @c %manipulator.
+In your @ref boost::logging::writer::format_write "format_write" object, you can have several formatters and destinations.
+Note that each formatter class and each destination class is a @c %manipulator.
 
+Each formatter and destination classes implement <tt>operator()(arg_type msg);</tt>, which
+processes the message:
+- for a formatter, this formats the msg (like, prepends time to it, appends an enter, etc)
+- for a destination, this writes the message to a destination (like, to console, a file, etc)
 
 
-When dealing with formatters, the first thing you must do is to specify that common %base class.
-All formatter classes will derive from it, directly or indirectly. Again, same goes for destinations.
 
+\n\n\n
+@section manipulator_base_class Specifying the base class
 
-Note that the %formatter %base class and the %destination %base class don't need to be the same. Example:
+As said @ref manipulator_common "above", formatters and destinations need a %base class.
+You do this through a typedef - one for the formatters, and one for the destinations:
 
 @code
-typedef optimize::cache_string_one_str<> cache_string;
-typedef formatter::base<cache_string&, op_equal::same_type > format_base;
-
+// ptr_type - optional ; usualy you don't need to worry about this
+typedef formatter::base<arg_type [,ptr_type]> formatter_base;
+typedef destination::base<arg_type [,ptr_type]> destination_base;
+@endcode
 
-struct write_time : format_base {
- void operator()(cache_string & str) const {
- char t[10];
- time_t now = time(0);
- tm details = *localtime(&now);
- strftime(t, 10, "%M:%S ", &details);
- str.prepend_string(t);
- }
-};
-//...
+The @c arg_type is the argument you receive in your <tt>operator()</tt>, to process the message. It can be as simple as this:
 
-typedef destination::base<const std::string &, op_equal::same_type> destination_base;
-struct write_to_cout : destination_base {
- void operator()(param msg) const {
- std::cout << msg ;
- }
-};
+@code
+// formatter - needs to modify the message
+typedef formatter::base< std::string&> formatter_base;
 
+// destination - needs to write the message - usually, it doesn't need to modify the message
+typedef destination::base<const std::string &> destination_base;
 @endcode
 
-This namespace contains the classes formatter or destination classes need to use as %base class.
+Or, you can use a @ref customize_manipulator "custom string class", or, even an @ref customize_optimize "optimization string class".
+So, it's not uncommon to do something like this:
 
+@code
+typedef optimize::cache_string_one_str<> cache_string;
 
+// formatter - needs to modify the message - use an optimizer while formatting
+typedef formatter::base< cache_string&> formatter_base;
 
-_at_section manipulator_base Manipulator base classes
+// destination - needs to write the message - which has been converted to string
+typedef destination::base<const std::string &> destination_base;
+@endcode
 
-Your formatter or destination class should derive from either of the following:
-- base - recommented %base class
-- base_no_operator_call - %base class , not implementing the operator() call
 
 
+\n\n\n
+@section manipulator_generic Using manipulators that come with the library
 
+Now, you will define your @ref logger "logger(s)", to use the @ref boost::logging::writer::format_write "format_write" class:
 
-_at_section share_data Sharing data for manipulator classes
+@code
+logger< ... format_write<formatter_base,destination_base> > g_l;
+@endcode
 
-The manipulator classes need to contain data as constant:
+After this, you'll add formatter and/or destination classes to your logger(s):
 
 @code
-struct my_formatter : format_base {
- ...
-private:
- const int m_idx;
-};
+// add formatters : [idx] [time] message [enter]
+g_l->writer().add_formatter( formatter::idx() );
+g_l->writer().add_formatter( formatter::time() );
+g_l->writer().add_formatter( formatter::append_enter() );
+
+// write to cout and file
+g_l->writer().add_destination( destination::cout() );
+g_l->writer().add_destination( destination::file("out.txt") );
 @endcode
 
-As long as data is constant, it's all ok - that is, no matter what functions get called, all the data in the formatter/destination
-must remain constant. We need constant functors - just like in STL - because internally, we copy formatters/destinations: that is, we keep
-several copies of a certain object - they all need to be syncronized. In case the objects' data is constant, that's no problem.
-
-In case the data needs to be changed - it needs to be shared. Several copies of the same instance must point to the same data. In other words,
-use shared pointers:
+In the above case, if you were to write:
 
 @code
-struct write_to_file {
- typedef boost::shared_ptr<std::ofstream> ptr;
- write_to_file(const std::string & filename) : m_out(new std::ofstream(filename.c_str())) {}
- void operator()(const std::string & msg) const {
- (*m_out) << msg << std::endl ;
- }
- mutable ptr m_out;
-};
+int i = 1;
+L_ << "this is so cool" << i++;
 @endcode
 
-Since quite a few of the manipulator objects will need this, it's quite acceptable to have a class that deals with this:
-the non_const_context class.
+a message similar to this would appear on both the console, and the file:
 
+@code
+[1] 12:57 this is so cool 1 <enter>
+@endcode
 
-*/
-namespace manipulator {
 
- namespace detail {
- struct default_type {};
- template<class type_> struct ptr_finder {
- template<class other_type> struct find { typedef other_type type ; };
- };
- template<> struct ptr_finder<default_type> {
- template<class other_type> struct find { typedef other_type* type ; };
- };
- }
+You can use the formatter and/or destination classes that come with the library:
+- formatters: in the formatter namespace. Here are a few examples:
+ - formatter::idx - prepends an index
+ - formatter::append_enter - appends an enter after the message
+ - formatter::time - prepends the time
+ - formatter::thread_id - prepends the current thread id
+- destinations: in the destination namespace
+ - destination::cout - writes to console
+ - destination::file - writes to file
+ - destination::rolling_file - writes to a rolling file
+ - destination::shared_memory - writes into shared memory (using @c boost::shmem::named_shared_object)
+
+Or, you can create your own formatter and/or destination class. See below:
 
-/**
-Formatters and/or destinations are Manipulators.
-
-All formatter or destination class need to directly or indirectly derive from this.
 
-_at_section manipulator_base_class Manipulator base classes
 
-<b>All formatters need to derive from a common %base class.
-When dealing with formatters, the first thing you must do is to specify that common base class.
-All formatter classes will derive from it, directly or indirectly.
+\n\n\n
+@section manipulator_create Creating your own formatter and/or destination class(es)
 
-Same goes for destinations.</b>
+To create your formatter class, you need to derive from @ref class_ "formatter::class_". You will need to implement
+<tt>operator()(arg_type)</tt> <br> (@c arg_type is the argument you passed in your @ref manipulator_base_class "formatter_base" typedef)
 
-Note that the formatter base class and the destination base class don't need to be the same.
+@code
+typedef formatter::base< std::string&> formatter_base;
+...
+
+// milliseconds since start of the program
+struct ms_since_start : formatter::class_<ms_since_start, formatter_base, op_equal_no_context> {
+ time_t m_start;
+ ms_since_start : m_start( time(0) ) {}
 
-You should derive your formatter or destination class from this, ONLY if you want to provide
-your own operator() which could take more than one argument. Otherwise, derive from base.
+ // param = std::string&
+ // (in other words, it's the parameter you used when you defined formatter_base)
+ void operator()(param msg) const {
+ std::ostringstream out;
+ time_t now = time(0);
+ out << "[" << (now-start) << "] ";
+ msg = out.str() + msg;
+ }
+};
+@endcode
 
+To create your destination class, you need to derive from @ref class_ "destination::class_". You will need to implement
+<tt>operator()(arg_type)</tt> <br> (@c arg_type is the argument you passed in your @ref manipulator_base_class "destination_base" typedef)
 
-_at_section implementing_op_equal_ Implementing operator==
+@code
+typedef destination::base< const std::string&> destination_base;
+...
 
-Formatter objects must be able to be compared. Same goes for destination objects. This is especially
-needed when a formatter or destination is to be erased - from a @ref boost::logging::writer::format_write "format_write" object.
+struct to_hwnd : destination::class_<to_hwnd, destination_base, op_equal_has_context> {
+ HWND h;
+ to_hwnd(HWND h) : h(h) {}
 
-There are multiple ways to be able to compare formatter/destination objects - see op_equal namespace.
+ bool operator==(const to_hwnd& other) { return h == other.h; }
 
-By default, @ref boost::logging::op_equal::same_type_op_equal_base is used.
+ // param = const std::string&
+ // (in other words, it's the parameter you used when you defined destination_base)
+ void operator()(param msg) const {
+ ::SetWindowText(h, msg.c_str());
+ }
+};
+@endcode
 
 
 
+\n\n\n
+@section manipulator_share_data Sharing data for manipulator classes
 
-_at_param implement_op_equal see @ref implementing_op_equal_
+When you implement your own %manipulator (%formatter or %destination) class, you must make sure that
+it behaves like an STL function: <b>it needs to contain data as constant.</b>
 
-_at_param ptr_type_ the type used to hold a pointer to the type. By defaut, it's the type itself.
+As long as data is constant, it's all ok - that is, no matter what functions get called, all the data in the formatter/destination
+must remain constant. We need constant functors - just like in STL - because internally, we copy formatters/destinations: that is, we keep
+several copies of a certain object - they all need to be syncronized. In case the objects' data is constant, that's no problem.
 
-*/
-template<
- class implement_op_equal = op_equal::same_type_op_equal_base,
- class ptr_type_ = detail::default_type >
- struct base_no_operator_call : implement_op_equal {
+In case the data needs to be changed - it needs to be shared. Several copies of the same instance must point to the same data.
+I've already provided a class you can derive from , when this is the case: the non_const_context class.
 
- typedef base_no_operator_call<implement_op_equal, ptr_type_> self_type;
- typedef typename detail::ptr_finder<ptr_type_> type_finder;
- typedef typename type_finder::template find<self_type>::type ptr_type;
+@code
+struct my_file : destination::class_<my_file,destination_base,op_equal_has_context>, non_const_context<std::ofstream> {
+ std::string m_filename;
+ bool operator==(const my_file & other) { return m_filename == other.m_filename; }
 
- virtual ~base_no_operator_call() {}
+ write_to_file(const std::string & filename) : m_filename(filename), non_const_context_base(filename.c_str()) {}
+ void operator()(param msg) const {
+ context() << msg << std::endl ;
+ }
 };
+@endcode
 
 
-/**
- Helper - in case your formatter or destination, in its operator(), it has only one argument
- (which is most of the time, unless you're doing something extreme ;)), you should derive from this.
 
+*/
+namespace manipulator {
 
- Examples:
- @code
- // takes a "string&" as argument:
- struct append_enter : single_param_base<std::string&> {
- // param - typedef defined in base class; param = std::string&
- void operator()(param a) {
- a += "\n";
- }
+ namespace detail {
+ struct default_type {};
+ template<class type_> struct ptr_finder {
+ template<class other_type> struct find { typedef other_type type ; };
+ };
+ template<> struct ptr_finder<default_type> {
+ template<class other_type> struct find { typedef other_type* type ; };
+ };
     }
 
- // takes a "const std::string&" as argument
- struct write_to_cout : single_param_base<const std::string&> {
- void operator()(param msg) const {
- std::cout << msg << std::endl ;
- }
- };
- @endcode
 
 
-_at_param implement_op_equal see @ref implementing_op_equal_
+/**
+ @brief What to use as base class, for your formatter and destination classes
 
+ When using formatters and destinations, formatters must share a %base class,
+ and destinations must share a %base class - see manipulator namespace.
 */
 template<
         class arg_type,
- class implement_op_equal = op_equal::same_type_op_equal_base,
         class ptr_type_ = detail::default_type >
- struct base : base_no_operator_call<implement_op_equal, ptr_type_> {
+ struct base : boost::logging::op_equal::same_type_op_equal_base {
 
- typedef base<arg_type, implement_op_equal, ptr_type_> self_type;
+ typedef base<arg_type, ptr_type_> self_type;
     typedef typename detail::ptr_finder<ptr_type_> type_finder;
     typedef typename type_finder::template find<self_type>::type ptr_type;
 
@@ -226,6 +268,28 @@
     virtual void operator()(param val) const = 0;
 };
 
+
+namespace detail {
+ template<implement_op_equal> struct op_equal_base {
+ bool operator==(const op_equal_base& ) const { return true; }
+ };
+
+ template<> struct op_equal_base<op_equal_has_context> {};
+}
+
+/**
+ @brief Use this when implementing your own formatter or destination class
+
+ x
+*/
+template<class type, class base_type, implement_op_equal op_e> struct class_
+ : base_type,
+ detail::op_equal_base<op_e>,
+ boost::logging::op_equal::same_type_op_equal<type> {
+};
+
+
+
 /**
     In case your manipulator (formatter or destination) needs to hold non-const context information, it can to derive from this.
     This automatically creates a shared pointer to the context information.
@@ -352,13 +416,18 @@
 */
 namespace formatter {
     using boost::logging::manipulator::base;
- using boost::logging::manipulator::base_no_operator_call;
     using boost::logging::manipulator::non_const_context;
 
     /**
+ @sa boost::logging::manipulator::class_
+ */
+ using boost::logging::manipulator::class_;
+
+ /**
         @sa boost::logging::manipulator::is_generic
     */
     typedef boost::logging::manipulator::is_generic is_generic;
+
 }
 
 /**
@@ -374,10 +443,14 @@
 */
 namespace destination {
     using boost::logging::manipulator::base;
- using boost::logging::manipulator::base_no_operator_call;
     using boost::logging::manipulator::non_const_context;
 
     /**
+ @sa boost::logging::manipulator::class_
+ */
+ using boost::logging::manipulator::class_;
+
+ /**
         @sa boost::logging::manipulator::is_generic
     */
     typedef boost::logging::manipulator::is_generic is_generic;

Added: sandbox/logging/boost/logging/detail/raw_doc/common_usage.hpp
==============================================================================
--- (empty file)
+++ sandbox/logging/boost/logging/detail/raw_doc/common_usage.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -0,0 +1,30 @@
+namespace boost { namespace logging {
+
+/**
+@page common_usage Scenario 1: Common Usage
+
+define the class_ - with @param
+
+- with levels
+- write to different thingies
+- etc
+
+Explain about samples!
+
+
+
+have 3 scenarios
+- several levels, same log
+- several levels, different logs
+- with custom router FIXME (that is, use cache_string_several_str())
+- one logger; several levels - use a sink (that is, see how we find "is_enabled")
+ - we can simply use the level.is_enabled(xxx) question, and then write to the log
+- no levels
+- etc
+- fastest , no <<
+- fastest , using <<
+- using your own formatters and destinations integrated
+
+*/
+
+}}

Added: sandbox/logging/boost/logging/detail/raw_doc/customize_manipulator.hpp
==============================================================================
--- (empty file)
+++ sandbox/logging/boost/logging/detail/raw_doc/customize_manipulator.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -0,0 +1,18 @@
+namespace boost { namespace logging {
+
+/**
+@page customize_manipulator Customizing manipulator arguments
+
+FIXME
+
+optimize::cache_string_on_str
+optimize::cache_string_several_str
+
+
+@section customize_optimize Optimizing manipulator arguments
+
+FIXME
+
+*/
+
+}}

Modified: sandbox/logging/boost/logging/detail/raw_doc/main.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/main.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/main.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -30,7 +30,7 @@
 - Efficient filtering of log messages - that is, if a log is turned off, the message is not processed at all
 - Thread-safe - the library allows you several degrees of thread-safety, as you'll see
 - Allows for formatters and destinations
- - formatters format the message (like, prepending extra information - an index, the time, thread is, etc)
+ - formatters format the message (like, prepending extra information - an index, the time, thread id, etc)
     - destinations specify where the message is to be written
     - Formatters and Destinations are orthogonal to the rest of the library - if you want you can use them, otherwise
       you can define your own writing mechanism

Modified: sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -23,8 +23,13 @@
     - @ref gather "The gather namespace"
     - @ref writer "The writer namespace"
 - @ref manipulator "Formatters and/or destinations (manipulators namespace)"
- - @ref manipulator_base
- - @ref share_data
+ - @ref manipulator_common
+ - @ref manipulator_base_class
+ - @ref manipulator_generic
+ - @ref manipulator_create
+ - @ref manipulator_share_data
+ - @ref formatter "Formatters"
+ - @ref destination "Destinations"
 
 - @ref thread_safety
 

Modified: sandbox/logging/boost/logging/format.hpp
==============================================================================
--- sandbox/logging/boost/logging/format.hpp (original)
+++ sandbox/logging/boost/logging/format.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -369,7 +369,7 @@
                 is_fmt, is_dest, is_clear
             };
             struct item {
- item() : m_type(is_clear) {}
+ item() : m_type(is_clear), m_fmt(0), m_dest(0) {}
                 item& fmt(formatter_ptr f) { m_fmt = f; m_type = is_fmt; return *this; }
                 item &dest(destination_ptr d) { m_dest = d; m_type = is_dest; return *this; }
                 formatter_ptr m_fmt;

Modified: sandbox/logging/boost/logging/format/destination/defaults.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/destination/defaults.hpp (original)
+++ sandbox/logging/boost/logging/format/destination/defaults.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -33,7 +33,7 @@
 /**
     @brief Writes the string to console
 */
-template<class convert_dest = do_convert_destination > struct cout {
+template<class convert_dest = do_convert_destination > struct cout : is_generic, same_type {
     template<class msg_type> void operator()(const msg_type & msg) const {
 #ifndef UNICODE
         convert_dest::write(msg, std::cout);

Modified: sandbox/logging/boost/logging/format/formatter/defaults.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/formatter/defaults.hpp (original)
+++ sandbox/logging/boost/logging/format/formatter/defaults.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -50,8 +50,8 @@
 @param convert [optional] In case there needs to be a conversion between std::(w)string and the string that holds your logged message. See convert_format.
 For instance, you might use @ref boost::logging::optimize::cache_string_one_str "a cached_string class" (see @ref boost::logging::optimize "optimize namespace").
 */
-template<class convert = do_convert_format::prepend> struct write_idx : formatter::non_const_context<int> {
- write_idx() : non_const_context_base((int)0) {}
+template<class convert = do_convert_format::prepend> struct idx : formatter::non_const_context<int> {
+ idx() : non_const_context_base((int)0) {}
     template<class msg_type> void operator()(msg_type & str) const {
         std::basic_ostringstream<char_type> idx;
         idx << _T("[") << ++context() << _T("] ");

Modified: sandbox/logging/boost/logging/format/formatter/time.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/formatter/time.hpp (original)
+++ sandbox/logging/boost/logging/format/formatter/time.hpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -42,12 +42,12 @@
 $mm - minute, 2 digits
 $ss - second, 2 digits
 
-Example: write_time("Today is $dd/$MM/$yyyy");
+Example: time("Today is $dd/$MM/$yyyy");
 
 @param convert [optional] In case there needs to be a conversion between std::(w)string and the string that holds your logged message. See convert_format.
 For instance, you might use @ref boost::logging::optimize::cache_string_one_str "a cached_string class" (see @ref boost::logging::optimize "optimize namespace").
 */
-template<class convert = do_convert_format::prepend> struct write_time {
+template<class convert = do_convert_format::prepend> struct time {
 private:
     typedef std::basic_string<c_type> string_type;
 
@@ -67,9 +67,9 @@
 public:
 
     /**
- constructs a write_time object
+ constructs a time object
     */
- write_time(const string_type & format) : m_day(-1), m_month(-1), m_yy(-1), m_yyyy(-1), m_hour(-1), m_min(-1), m_sec(-1) {
+ time(const string_type & format) : m_day(-1), m_month(-1), m_yy(-1), m_yyyy(-1), m_hour(-1), m_min(-1), m_sec(-1) {
         // format too big
         assert( format.size() < 64);
 
@@ -123,7 +123,7 @@
     template<class msg_type> void operator()(msg_type & msg) {
         char_type buffer[64];
 
- time_t t = time(0);
+ time_t t = ::time(0);
         tm details = *localtime( &t);
 
         int vals[8];
@@ -175,7 +175,7 @@
 
     template<class msg_type> void operator()(msg_type & msg) {
         char_type buffer[64];
- time_t t = time (0);
+ time_t t = ::time (0);
         tm t_details = m_localtime ? *localtime( &m_t) : *gmtime( &m_t);
     #ifdef UNICODE
         if (0 != wcsftime (buffer, sizeof (buffer), m_format.c_str (), &t_details))

Modified: sandbox/logging/lib/logging/samples/vc8/loggingvc8/loggingvc8.vcproj
==============================================================================
--- sandbox/logging/lib/logging/samples/vc8/loggingvc8/loggingvc8.vcproj (original)
+++ sandbox/logging/lib/logging/samples/vc8/loggingvc8/loggingvc8.vcproj 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -423,6 +423,13 @@
                         <File
                                 RelativePath="..\..\..\tests\format\test_simple_formatter.cpp"
>
+ <FileConfiguration
+ Name="Test|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
                         </File>
                 </Filter>
                 <Filter
@@ -713,6 +720,14 @@
>
                         </File>
                         <File
+ RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\common_usage.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\customize_manipulator.hpp"
+ >
+ </File>
+ <File
                                 RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\fixme.hpp"
>
                         </File>

Modified: sandbox/logging/lib/logging/src/changelog.txt
==============================================================================
--- sandbox/logging/lib/logging/src/changelog.txt (original)
+++ sandbox/logging/lib/logging/src/changelog.txt 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -1,3 +1,14 @@
+
+
+v0.7.3, 19 oct 2007
+- added the manipulator::class_ concept
+- added some documentation
+
+
+v0.7.2, 18 oct 2007
+- format_write cares if formatter/destination is generic or not
+- solved bug when deleting manipulators (same_type needed to have a virtual destructor)
+
 v0.4, 9 oct 2007
 - ts_write and on_dedicated_thread work
 
@@ -15,4 +26,3 @@
 
 v0.7, 15 oct 2007
 - compiles with gcc 3.4.2
-

Modified: sandbox/logging/lib/logging/tests/format/test_manip_w_msgroute.cpp
==============================================================================
--- sandbox/logging/lib/logging/tests/format/test_manip_w_msgroute.cpp (original)
+++ sandbox/logging/lib/logging/tests/format/test_manip_w_msgroute.cpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -42,7 +42,7 @@
 
     to cout: [idx] [time] message [enter]
     to dbg_window: [time] message [enter]
- to file: [idx] message [enter]
+ to file: message [enter]
 
     So our route is:
 
@@ -52,7 +52,6 @@
     prepend [idx]
     to cout
     clear format
- prepend [idx]
     append [enter]
     to file
 */
@@ -62,7 +61,7 @@
 //////////////////////////////////////////////////////////////////////
 // Formatters
 
-typedef formatter::base<cache_string&, op_equal::same_type > format_base;
+typedef formatter::base<cache_string&> format_base;
 
 // formatter: prepend the message's index
 struct write_idx : format_base, formatter::non_const_context<int> {
@@ -93,7 +92,7 @@
 //////////////////////////////////////////////////////////////////////
 // Destinations
 
-typedef destination::base<const std::string &, op_equal::same_type> destination_base;
+typedef destination::base<const std::string &> destination_base;
 
 struct write_to_cout : destination_base {
     void operator()(param msg) const {
@@ -158,14 +157,13 @@
         .fmt( write_idx() )
         .dest( write_to_cout() )
         .clear()
- .fmt( write_idx() )
         .fmt( append_enter() )
- .fmt( write_to_file())
+ .dest( write_to_file())
         ;
-// DOES NOT work
 
     int i = 1;
- L_ << "must be prefixed by index and time , enter is appended as well " << i++;
+ L_ << "good to use " << i++ << " version";
+ L_ << "Boost Logging lib v" << i++;
 }
 
 #ifdef SINGLE_TEST

Modified: sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp
==============================================================================
--- sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp (original)
+++ sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp 2007-10-19 08:12:15 EDT (Fri, 19 Oct 2007)
@@ -51,10 +51,10 @@
 //////////////////////////////////////////////////////////////////////
 // Formatters
 
-typedef formatter::base<cache_string&, op_equal::same_type > format_base;
+typedef formatter::base<cache_string&> format_base;
 
 // formatter: prepend the message's index
-struct write_idx : format_base, formatter::non_const_context<int> {
+struct write_idx : formatter::class_<write_idx, format_base, op_equal_no_context>, formatter::non_const_context<int> {
     write_idx() : non_const_context_base((int)0) {}
     void operator()(param str) const {
         std::stringstream idx;
@@ -63,7 +63,7 @@
     }
 };
 
-struct write_time : format_base {
+struct write_time : formatter::class_<write_time, format_base, op_equal_no_context> {
     void operator()(cache_string & str) const {
         char t[10];
         time_t now = time(0);
@@ -73,7 +73,7 @@
     }
 };
 
-struct append_enter : format_base {
+struct append_enter : formatter::class_<append_enter, format_base, op_equal_no_context> {
     void operator()(cache_string & str) const {
         str.append_string("\n");
     }
@@ -82,15 +82,15 @@
 //////////////////////////////////////////////////////////////////////
 // Destinations
 
-typedef destination::base<const std::string &, op_equal::same_type> destination_base;
+typedef destination::base<const std::string &> destination_base;
 
-struct write_to_cout : destination_base {
+struct write_to_cout : destination::class_<write_to_cout, destination_base, op_equal_no_context> {
     void operator()(param msg) const {
         std::cout << msg ;
     }
 };
 
-struct write_to_file : destination_base, destination::non_const_context<std::ofstream> {
+struct write_to_file : destination::class_<write_to_file, destination_base, op_equal_no_context>, destination::non_const_context<std::ofstream> {
     write_to_file(const char* filename) : non_const_context_base(filename) {}
     void operator()(param msg) const {
         context() << msg ;
@@ -118,7 +118,7 @@
     g_l->writer().add_destination( write_to_file("out.txt") );
 
     int i = 1;
- L_ << "must be prefixed by index and time , enter is appended as well " << i++;
+ L_ << "this is so cool" << i++;
     L_ << "must be prefixed by index and time , enter is appended as well " << i++;
     L_ << "must be prefixed by index and time , enter is appended as well " << i++;
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk