1 /*
2  *          Copyright Andrey Semashev 2007 - 2015.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   text_multifile_backend.cpp
9  * \author Andrey Semashev
10  * \date   09.06.2009
11  *
12  * \brief  This header is the Boost.Log library implementation, see the library documentation
13  *         at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
14  */
15 
16 #include <boost/log/detail/config.hpp>
17 #include <ios>
18 #include <boost/filesystem/path.hpp>
19 #include <boost/filesystem/fstream.hpp>
20 #include <boost/filesystem/operations.hpp>
21 #include <boost/log/detail/parameter_tools.hpp>
22 #include <boost/log/sinks/auto_newline_mode.hpp>
23 #include <boost/log/sinks/text_multifile_backend.hpp>
24 #include <boost/log/detail/header.hpp>
25 
26 namespace boost {
27 
28 BOOST_LOG_OPEN_NAMESPACE
29 
30 namespace sinks {
31 
32 //! Sink implementation data
33 struct text_multifile_backend::implementation
34 {
35     //! File name composer
36     file_name_composer_type m_FileNameComposer;
37     //! Base path for absolute path composition
38     const filesystem::path m_BasePath;
39     //! File stream
40     filesystem::ofstream m_File;
41     //! Indicates whether to append a trailing newline after every log record
42     auto_newline_mode m_AutoNewlineMode;
43 
implementationboost::sinks::text_multifile_backend::implementation44     explicit implementation(auto_newline_mode auto_newline) :
45         m_BasePath(filesystem::current_path()),
46         m_AutoNewlineMode(auto_newline)
47     {
48     }
49 
50     //! Makes relative path absolute with respect to the base path
make_absoluteboost::sinks::text_multifile_backend::implementation51     filesystem::path make_absolute(filesystem::path const& p)
52     {
53         return filesystem::absolute(p, m_BasePath);
54     }
55 };
56 
57 //! Default constructor
text_multifile_backend()58 BOOST_LOG_API text_multifile_backend::text_multifile_backend()
59 {
60     construct(log::aux::empty_arg_list());
61 }
62 
63 //! Constructor implementation
construct(auto_newline_mode auto_newline)64 BOOST_LOG_API void text_multifile_backend::construct(auto_newline_mode auto_newline)
65 {
66     m_pImpl = new implementation(auto_newline);
67 }
68 
69 //! Destructor
~text_multifile_backend()70 BOOST_LOG_API text_multifile_backend::~text_multifile_backend()
71 {
72     delete m_pImpl;
73 }
74 
75 //! The method sets the file name composer
set_file_name_composer_internal(file_name_composer_type const & composer)76 BOOST_LOG_API void text_multifile_backend::set_file_name_composer_internal(file_name_composer_type const& composer)
77 {
78     m_pImpl->m_FileNameComposer = composer;
79 }
80 
81 //! Selects whether a trailing newline should be automatically inserted after every log record.
set_auto_newline_mode(auto_newline_mode mode)82 BOOST_LOG_API void text_multifile_backend::set_auto_newline_mode(auto_newline_mode mode)
83 {
84     m_pImpl->m_AutoNewlineMode = mode;
85 }
86 
87 //! The method writes the message to the sink
consume(record_view const & rec,string_type const & formatted_message)88 BOOST_LOG_API void text_multifile_backend::consume(record_view const& rec, string_type const& formatted_message)
89 {
90     if (BOOST_LIKELY(!m_pImpl->m_FileNameComposer.empty()))
91     {
92         filesystem::path file_name = m_pImpl->make_absolute(m_pImpl->m_FileNameComposer(rec));
93         filesystem::create_directories(file_name.parent_path());
94         m_pImpl->m_File.open(file_name, std::ios_base::out | std::ios_base::app);
95         if (BOOST_LIKELY(m_pImpl->m_File.is_open()))
96         {
97             m_pImpl->m_File.write(formatted_message.data(), static_cast< std::streamsize >(formatted_message.size()));
98             if (m_pImpl->m_AutoNewlineMode != disabled_auto_newline)
99             {
100                 if (m_pImpl->m_AutoNewlineMode == always_insert || formatted_message.empty() || *formatted_message.rbegin() != static_cast< string_type::value_type >('\n'))
101                     m_pImpl->m_File.put(static_cast< string_type::value_type >('\n'));
102             }
103             m_pImpl->m_File.close();
104         }
105     }
106 }
107 
108 } // namespace sinks
109 
110 BOOST_LOG_CLOSE_NAMESPACE // namespace log
111 
112 } // namespace boost
113 
114 #include <boost/log/detail/footer.hpp>
115