00001 #ifndef toast_log_output_policies_hpp_INCLUDED
00002 #define toast_log_output_policies_hpp_INCLUDED
00003
00004 #include <iostream>
00005 #include <fstream>
00006 #include <toast/concept_check.hpp>
00007
00008 #include <cstdio>
00009
00010 #include <toast/log/header_policies.hpp>
00011 #include <toast/log/footer_policies.hpp>
00012 #include <toast/log/stream_policies.hpp>
00013 #include <toast/log/rotation_policies.hpp>
00014
00026 namespace toast {
00027 namespace log {
00028
00038 class ConsumingOutputPolicy {};
00039
00052 template <typename Policy>
00053 struct OutputPolicyConcept
00054 {
00059 void constraints() {
00060 p.message(c, ERROR);
00061 }
00062 private:
00063 typename Policy::char_type c[10];
00064 Policy p;
00065 };
00066
00067 typedef header_policy_aggregator<microseconds, severity_header> default_header_policy;
00068 typedef rotation_policy<max_file_size, roll_rotation> default_rotation_policy;
00069
00074 template <typename HeaderPolicy = default_header_policy,
00075 typename FooterPolicy = newline,
00076 typename StreamPolicy = any_stream>
00077 struct to_stream
00078 : public HeaderPolicy,
00079 public FooterPolicy,
00080 public StreamPolicy
00081 {
00082 TOAST_CLASS_REQUIRE(HeaderPolicy, toast::log, HeaderPolicyConcept);
00083 TOAST_CLASS_REQUIRE(FooterPolicy, toast::log, FooterPolicyConcept);
00084 TOAST_CLASS_REQUIRE(StreamPolicy, toast::log, StreamPolicyConcept);
00085
00086 typedef typename StreamPolicy::char_type char_type;
00087
00088 void message(char_type const *message, log::severity severity)
00089 {
00090 StreamPolicy::stream() << HeaderPolicy::header(severity) << message
00091 << FooterPolicy::footer(severity);
00092 StreamPolicy::stream().flush();
00093 }
00094 protected:
00095 ~to_stream() {}
00096 };
00097
00098 template <typename HeaderPolicy, typename StreamPolicy>
00099 struct to_stream<HeaderPolicy, no_footer, StreamPolicy>
00100 : public HeaderPolicy,
00101 public no_footer,
00102 public StreamPolicy
00103 {
00104 TOAST_CLASS_REQUIRE(HeaderPolicy, toast::log, HeaderPolicyConcept);
00105 TOAST_CLASS_REQUIRE(StreamPolicy, toast::log, StreamPolicyConcept);
00106
00107 typedef typename StreamPolicy::char_type char_type;
00108
00109 void message(char_type const *message, log::severity severity)
00110 {
00111 StreamPolicy::stream() << HeaderPolicy::header(severity) << message;
00112 StreamPolicy::stream().flush();
00113 }
00114 protected:
00115 ~to_stream() {}
00116 };
00117
00118 template <typename FooterPolicy, typename StreamPolicy>
00119 struct to_stream<no_header, FooterPolicy, StreamPolicy>
00120 : public no_header,
00121 public FooterPolicy,
00122 public StreamPolicy
00123 {
00124 TOAST_CLASS_REQUIRE(FooterPolicy, toast::log, FooterPolicyConcept);
00125 TOAST_CLASS_REQUIRE(StreamPolicy, toast::log, StreamPolicyConcept);
00126
00127 typedef typename StreamPolicy::char_type char_type;
00128
00129 void message(char_type const *message, log::severity severity)
00130 {
00131 StreamPolicy::stream() << message << FooterPolicy::footer(severity);
00132 StreamPolicy::stream().flush();
00133 }
00134 protected:
00135 ~to_stream() {}
00136 };
00137
00138 template <typename StreamPolicy>
00139 struct to_stream<no_header, no_footer, StreamPolicy>
00140 : public no_header,
00141 public no_footer,
00142 public StreamPolicy
00143 {
00144 TOAST_CLASS_REQUIRE(StreamPolicy, toast::log, StreamPolicyConcept);
00145
00146 typedef typename StreamPolicy::char_type char_type;
00147
00148 void message(char_type const *message, log::severity severity)
00149 {
00150 StreamPolicy::stream() << message;
00151 StreamPolicy::stream().flush();
00152 }
00153 protected:
00154 ~to_stream() {}
00155 };
00156
00157
00158
00159
00160
00165 template <typename HeaderPolicy = default_header_policy,
00166 typename FooterPolicy = newline>
00167 struct to_stderr_buffered
00168 : public to_stream<HeaderPolicy, FooterPolicy, clog_stream>
00169 {
00170 typedef typename
00171 to_stream<HeaderPolicy, FooterPolicy, clog_stream>::char_type char_type;
00172 protected:
00173 ~to_stderr_buffered() {}
00174 };
00175
00180 template <typename HeaderPolicy = default_header_policy,
00181 typename FooterPolicy = newline,
00182 typename RotationPolicy = default_rotation_policy>
00183 struct to_file :
00184 public HeaderPolicy,
00185 public FooterPolicy,
00186 public RotationPolicy
00187 {
00188 TOAST_CLASS_REQUIRE(RotationPolicy, toast::log, RotationPolicyConcept);
00189 typedef char char_type;
00190
00191 void message(char_type const *message, log::severity severity)
00192 {
00193 int written = 0;
00194 std::string header_normalized(HeaderPolicy::header(severity));
00195 std::string footer_normalized(FooterPolicy::footer(severity));
00196 written += std::fprintf(f_, header_normalized.c_str());
00197 written += std::fprintf(f_, message);
00198 written += std::fprintf(f_, footer_normalized.c_str());
00199
00200 std::fflush(f_);
00201 if (RotationPolicy::test(written)) rotate();
00202 }
00203
00204 void open(std::string const& file)
00205 {
00206 open(file.c_str());
00207 }
00208 void open(char const* file)
00209 {
00210 RotationPolicy::set_file(file);
00211 f_ = std::fopen(file, "a");
00212
00213 if(!f_)
00214 throw std::ios_base::failure("Unable to open log file. Check file permissions.");
00215 }
00216 void close()
00217 {
00218 if(f_) std::fclose(f_);
00219 }
00220 void rotate()
00221 {
00222 close();
00223 f_ = std::fopen(RotationPolicy::rotate(), "a");
00224 }
00225
00226 protected:
00227 ~to_file() { close(); }
00228 private:
00229 FILE* f_;
00230 };
00231
00235 template <typename HeaderPolicy = default_header_policy,
00236 typename FooterPolicy = newline>
00237 struct to_stdout
00238 : public to_stream<HeaderPolicy, FooterPolicy, cout_stream>
00239 {
00240 typedef typename
00241 to_stream<HeaderPolicy, FooterPolicy, cout_stream>::char_type char_type;
00242 protected:
00243 ~to_stdout() {}
00244 };
00245
00249 template <typename HeaderPolicy = default_header_policy,
00250 typename FooterPolicy = newline>
00251 struct to_stderr
00252 : public to_stream<HeaderPolicy, FooterPolicy, cerr_stream>
00253 {
00254 typedef typename
00255 to_stream<HeaderPolicy, FooterPolicy, cerr_stream>::char_type char_type;
00256 protected:
00257 ~to_stderr() {}
00258 };
00259
00260 template <typename FirstOutputPolicy, typename SecondOutputPolicy>
00261 struct output_policy_aggregator
00262 : public FirstOutputPolicy, public SecondOutputPolicy
00263 {
00264 TOAST_CLASS_REQUIRE(FirstOutputPolicy, toast::log, OutputPolicyConcept);
00265 TOAST_CLASS_REQUIRE(SecondOutputPolicy, toast::log, OutputPolicyConcept);
00266
00267 typedef typename FirstOutputPolicy::char_type char_type;
00268
00269 void message(char_type const *message, log::severity severity)
00270 {
00271 FirstOutputPolicy::message(message, severity);
00272 SecondOutputPolicy::message(message, severity);
00273 }
00274 protected:
00275 ~output_policy_aggregator() {}
00276 };
00277
00278
00279
00280
00281
00282
00283
00284
00285
00288 }
00289 }
00290
00291 #endif // toast_log_output_policies_hpp_INCLUDED