http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/fmt/bundled/ostream.cc ---------------------------------------------------------------------- diff --git a/include/spdlog/fmt/bundled/ostream.cc b/include/spdlog/fmt/bundled/ostream.cc new file mode 100644 index 0000000..2148f3c --- /dev/null +++ b/include/spdlog/fmt/bundled/ostream.cc @@ -0,0 +1,37 @@ +/* +Formatting library for C++ - std::ostream support + +Copyright (c) 2012 - 2016, Victor Zverovich +All rights reserved. + +For the license information refer to format.h. +*/ + +#include "ostream.h" + +namespace fmt { + + namespace internal { + FMT_FUNC void write(std::ostream &os, Writer &w) + { + const char *data = w.data(); + typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize; + UnsignedStreamSize size = w.size(); + UnsignedStreamSize max_size = + internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); + do { + UnsignedStreamSize n = size <= max_size ? size : max_size; + os.write(data, static_cast<std::streamsize>(n)); + data += n; + size -= n; + } while (size != 0); + } + } + + FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) + { + MemoryWriter w; + w.write(format_str, args); + internal::write(os, w); + } +} // namespace fmt
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/fmt/bundled/ostream.h ---------------------------------------------------------------------- diff --git a/include/spdlog/fmt/bundled/ostream.h b/include/spdlog/fmt/bundled/ostream.h new file mode 100644 index 0000000..3bdb375 --- /dev/null +++ b/include/spdlog/fmt/bundled/ostream.h @@ -0,0 +1,118 @@ +/* +Formatting library for C++ - std::ostream support + +Copyright (c) 2012 - 2016, Victor Zverovich +All rights reserved. + +For the license information refer to format.h. +*/ + +#ifndef FMT_OSTREAM_H_ +#define FMT_OSTREAM_H_ + +// commented out by spdlog +// #include "format.h" +#include <ostream> + +namespace fmt +{ + +namespace internal +{ + +template <class Char> +class FormatBuf: public std::basic_streambuf<Char> +{ +private: + typedef typename std::basic_streambuf<Char>::int_type int_type; + typedef typename std::basic_streambuf<Char>::traits_type traits_type; + + Buffer<Char> &buffer_; + Char *start_; + +public: + FormatBuf(Buffer<Char> &buffer): buffer_(buffer), start_(&buffer[0]) + { + this->setp(start_, start_ + buffer_.capacity()); + } + + int_type overflow(int_type ch = traits_type::eof()) + { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + { + size_t buf_size = size(); + buffer_.resize(buf_size); + buffer_.reserve(buf_size * 2); + + start_ = &buffer_[0]; + start_[buf_size] = traits_type::to_char_type(ch); + this->setp(start_ + buf_size + 1, start_ + buf_size * 2); + } + return ch; + } + + size_t size() const + { + return to_unsigned(this->pptr() - start_); + } +}; + +Yes &convert(std::ostream &); + +struct DummyStream: std::ostream +{ + DummyStream(); // Suppress a bogus warning in MSVC. + // Hide all operator<< overloads from std::ostream. + void operator<<(Null<>); +}; + +No &operator<<(std::ostream &, int); + +template<typename T> +struct ConvertToIntImpl<T, true> +{ + // Convert to int only if T doesn't have an overloaded operator<<. + enum + { + value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No) + }; +}; + +// Write the content of w to os. +void write(std::ostream &os, Writer &w); +} // namespace internal + +// Formats a value. +template <typename Char, typename ArgFormatter, typename T> +void format_arg(BasicFormatter<Char, ArgFormatter> &f, + const Char *&format_str, const T &value) +{ + internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer; + + internal::FormatBuf<Char> format_buf(buffer); + std::basic_ostream<Char> output(&format_buf); + output << value; + + BasicStringRef<Char> str(&buffer[0], format_buf.size()); + typedef internal::MakeArg< BasicFormatter<Char> > MakeArg; + format_str = f.format(format_str, MakeArg(str)); +} + +/** +\rst +Prints formatted data to the stream *os*. + +**Example**:: + +print(cerr, "Don't {}!", "panic"); +\endrst +*/ +FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args); +FMT_VARIADIC(void, print, std::ostream &, CStringRef) +} // namespace fmt + +#ifdef FMT_HEADER_ONLY +# include "ostream.cc" +#endif + +#endif // FMT_OSTREAM_H_ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/fmt/bundled/printf.h ---------------------------------------------------------------------- diff --git a/include/spdlog/fmt/bundled/printf.h b/include/spdlog/fmt/bundled/printf.h new file mode 100644 index 0000000..2b9ddfa --- /dev/null +++ b/include/spdlog/fmt/bundled/printf.h @@ -0,0 +1,658 @@ +/* +Formatting library for C++ + +Copyright (c) 2012 - 2016, Victor Zverovich +All rights reserved. + +For the license information refer to format.h. +*/ + +#ifndef FMT_PRINTF_H_ +#define FMT_PRINTF_H_ + +#include <algorithm> // std::fill_n +#include <limits> // std::numeric_limits + +#include "ostream.h" + +namespace fmt +{ +namespace internal +{ + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template <bool IsSigned> +struct IntChecker +{ + template <typename T> + static bool fits_in_int(T value) + { + unsigned max = std::numeric_limits<int>::max(); + return value <= max; + } + static bool fits_in_int(bool) + { + return true; + } +}; + +template <> +struct IntChecker<true> +{ + template <typename T> + static bool fits_in_int(T value) + { + return value >= std::numeric_limits<int>::min() && + value <= std::numeric_limits<int>::max(); + } + static bool fits_in_int(int) + { + return true; + } +}; + +class PrecisionHandler: public ArgVisitor<PrecisionHandler, int> +{ +public: + void report_unhandled_arg() + { + FMT_THROW(FormatError("precision is not integer")); + } + + template <typename T> + int visit_any_int(T value) + { + if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) + FMT_THROW(FormatError("number is too big")); + return static_cast<int>(value); + } +}; + +// IsZeroInt::visit(arg) returns true iff arg is a zero integer. +class IsZeroInt: public ArgVisitor<IsZeroInt, bool> +{ +public: + template <typename T> + bool visit_any_int(T value) + { + return value == 0; + } +}; + +template <typename T, typename U> +struct is_same +{ + enum + { + value = 0 + }; +}; + +template <typename T> +struct is_same<T, T> +{ + enum + { + value = 1 + }; +}; + +// An argument visitor that converts an integer argument to T for printf, +// if T is an integral type. If T is void, the argument is converted to +// corresponding signed or unsigned type depending on the type specifier: +// 'd' and 'i' - signed, other - unsigned) +template <typename T = void> +class ArgConverter: public ArgVisitor<ArgConverter<T>, void> +{ +private: + internal::Arg &arg_; + wchar_t type_; + + FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); + +public: + ArgConverter(internal::Arg &arg, wchar_t type) + : arg_(arg), type_(type) + {} + + void visit_bool(bool value) + { + if (type_ != 's') + visit_any_int(value); + } + + template <typename U> + void visit_any_int(U value) + { + bool is_signed = type_ == 'd' || type_ == 'i'; + using internal::Arg; + typedef typename internal::Conditional< + is_same<T, void>::value, U, T>::type TargetType; + if (sizeof(TargetType) <= sizeof(int)) + { + // Extra casts are used to silence warnings. + if (is_signed) + { + arg_.type = Arg::INT; + arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); + } + else + { + arg_.type = Arg::UINT; + typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; + arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); + } + } + else + { + if (is_signed) + { + arg_.type = Arg::LONG_LONG; + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + arg_.long_long_value = static_cast<LongLong>(value); + } + else + { + arg_.type = Arg::ULONG_LONG; + arg_.ulong_long_value = + static_cast<typename internal::MakeUnsigned<U>::Type>(value); + } + } + } +}; + +// Converts an integer argument to char for printf. +class CharConverter: public ArgVisitor<CharConverter, void> +{ +private: + internal::Arg &arg_; + + FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); + +public: + explicit CharConverter(internal::Arg &arg): arg_(arg) + {} + + template <typename T> + void visit_any_int(T value) + { + arg_.type = internal::Arg::CHAR; + arg_.int_value = static_cast<char>(value); + } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class WidthHandler: public ArgVisitor<WidthHandler, unsigned> +{ +private: + FormatSpec &spec_; + + FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); + +public: + explicit WidthHandler(FormatSpec &spec): spec_(spec) + {} + + void report_unhandled_arg() + { + FMT_THROW(FormatError("width is not integer")); + } + + template <typename T> + unsigned visit_any_int(T value) + { + typedef typename internal::IntTraits<T>::MainType UnsignedType; + UnsignedType width = static_cast<UnsignedType>(value); + if (internal::is_negative(value)) + { + spec_.align_ = ALIGN_LEFT; + width = 0 - width; + } + unsigned int_max = std::numeric_limits<int>::max(); + if (width > int_max) + FMT_THROW(FormatError("number is too big")); + return static_cast<unsigned>(width); + } +}; +} // namespace internal + +/** +\rst +A ``printf`` argument formatter based on the `curiously recurring template +pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_. + +To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some +or all of the visit methods with the same signatures as the methods in +`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`. +Pass the subclass as the *Impl* template parameter. When a formatting +function processes an argument, it will dispatch to a visit method +specific to the argument type. For example, if the argument type is +``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass +will be called. If the subclass doesn't contain a method with this signature, +then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its +superclass will be called. +\endrst +*/ +template <typename Impl, typename Char> +class BasicPrintfArgFormatter: public internal::ArgFormatterBase<Impl, Char> +{ +private: + void write_null_pointer() + { + this->spec().type_ = 0; + this->write("(nil)"); + } + + typedef internal::ArgFormatterBase<Impl, Char> Base; + +public: + /** + \rst + Constructs an argument formatter object. + *writer* is a reference to the output writer and *spec* contains format + specifier information for standard argument types. + \endrst + */ + BasicPrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) + : internal::ArgFormatterBase<Impl, Char>(w, s) + {} + + /** Formats an argument of type ``bool``. */ + void visit_bool(bool value) + { + FormatSpec &fmt_spec = this->spec(); + if (fmt_spec.type_ != 's') + return this->visit_any_int(value); + fmt_spec.type_ = 0; + this->write(value); + } + + /** Formats a character. */ + void visit_char(int value) + { + const FormatSpec &fmt_spec = this->spec(); + BasicWriter<Char> &w = this->writer(); + if (fmt_spec.type_ && fmt_spec.type_ != 'c') + w.write_int(value, fmt_spec); + typedef typename BasicWriter<Char>::CharPtr CharPtr; + CharPtr out = CharPtr(); + if (fmt_spec.width_ > 1) + { + Char fill = ' '; + out = w.grow_buffer(fmt_spec.width_); + if (fmt_spec.align_ != ALIGN_LEFT) + { + std::fill_n(out, fmt_spec.width_ - 1, fill); + out += fmt_spec.width_ - 1; + } + else + { + std::fill_n(out + 1, fmt_spec.width_ - 1, fill); + } + } + else + { + out = w.grow_buffer(1); + } + *out = static_cast<Char>(value); + } + + /** Formats a null-terminated C string. */ + void visit_cstring(const char *value) + { + if (value) + Base::visit_cstring(value); + else if (this->spec().type_ == 'p') + write_null_pointer(); + else + this->write("(null)"); + } + + /** Formats a pointer. */ + void visit_pointer(const void *value) + { + if (value) + return Base::visit_pointer(value); + this->spec().type_ = 0; + write_null_pointer(); + } + + /** Formats an argument of a custom (user-defined) type. */ + void visit_custom(internal::Arg::CustomValue c) + { + BasicFormatter<Char> formatter(ArgList(), this->writer()); + const Char format_str[] = { '}', 0 }; + const Char *format = format_str; + c.format(&formatter, c.value, &format); + } +}; + +/** The default printf argument formatter. */ +template <typename Char> +class PrintfArgFormatter + : public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char> +{ +public: + /** Constructs an argument formatter object. */ + PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) + : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) + {} +}; + +/** This template formats data and writes the output to a writer. */ +template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> > +class PrintfFormatter: private internal::FormatterBase +{ +private: + BasicWriter<Char> &writer_; + + void parse_flags(FormatSpec &spec, const Char *&s); + + // Returns the argument with specified index or, if arg_index is equal + // to the maximum unsigned value, the next argument. + internal::Arg get_arg( + const Char *s, + unsigned arg_index = (std::numeric_limits<unsigned>::max)()); + + // Parses argument index, flags and width and returns the argument index. + unsigned parse_header(const Char *&s, FormatSpec &spec); + +public: + /** + \rst + Constructs a ``PrintfFormatter`` object. References to the arguments and + the writer are stored in the formatter object so make sure they have + appropriate lifetimes. + \endrst + */ + explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w) + : FormatterBase(al), writer_(w) + {} + + /** Formats stored arguments and writes the output to the writer. */ + FMT_API void format(BasicCStringRef<Char> format_str); +}; + +template <typename Char, typename AF> +void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) +{ + for (;;) + { + switch (*s++) + { + case '-': + spec.align_ = ALIGN_LEFT; + break; + case '+': + spec.flags_ |= SIGN_FLAG | PLUS_FLAG; + break; + case '0': + spec.fill_ = '0'; + break; + case ' ': + spec.flags_ |= SIGN_FLAG; + break; + case '#': + spec.flags_ |= HASH_FLAG; + break; + default: + --s; + return; + } + } +} + +template <typename Char, typename AF> +internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s, + unsigned arg_index) +{ + (void)s; + const char *error = FMT_NULL; + internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ? + next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + if (error) + FMT_THROW(FormatError(!*s ? "invalid format string" : error)); + return arg; +} + +template <typename Char, typename AF> +unsigned PrintfFormatter<Char, AF>::parse_header( + const Char *&s, FormatSpec &spec) +{ + unsigned arg_index = std::numeric_limits<unsigned>::max(); + Char c = *s; + if (c >= '0' && c <= '9') + { + // Parse an argument index (if followed by '$') or a width possibly + // preceded with '0' flag(s). + unsigned value = internal::parse_nonnegative_int(s); + if (*s == '$') // value is an argument index + { + ++s; + arg_index = value; + } + else + { + if (c == '0') + spec.fill_ = '0'; + if (value != 0) + { + // Nonzero value means that we parsed width and don't need to + // parse it or flags again, so return now. + spec.width_ = value; + return arg_index; + } + } + } + parse_flags(spec, s); + // Parse width. + if (*s >= '0' && *s <= '9') + { + spec.width_ = internal::parse_nonnegative_int(s); + } + else if (*s == '*') + { + ++s; + spec.width_ = internal::WidthHandler(spec).visit(get_arg(s)); + } + return arg_index; +} + +template <typename Char, typename AF> +void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) +{ + const Char *start = format_str.c_str(); + const Char *s = start; + while (*s) + { + Char c = *s++; + if (c != '%') continue; + if (*s == c) + { + write(writer_, start, s); + start = ++s; + continue; + } + write(writer_, start, s - 1); + + FormatSpec spec; + spec.align_ = ALIGN_RIGHT; + + // Parse argument index, flags and width. + unsigned arg_index = parse_header(s, spec); + + // Parse precision. + if (*s == '.') + { + ++s; + if ('0' <= *s && *s <= '9') + { + spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s)); + } + else if (*s == '*') + { + ++s; + spec.precision_ = internal::PrecisionHandler().visit(get_arg(s)); + } + } + + using internal::Arg; + Arg arg = get_arg(s, arg_index); + if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg)) + spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG); + if (spec.fill_ == '0') + { + if (arg.type <= Arg::LAST_NUMERIC_TYPE) + spec.align_ = ALIGN_NUMERIC; + else + spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. + } + + // Parse length and convert the argument to the required type. + using internal::ArgConverter; + switch (*s++) + { + case 'h': + if (*s == 'h') + ArgConverter<signed char>(arg, *++s).visit(arg); + else + ArgConverter<short>(arg, *s).visit(arg); + break; + case 'l': + if (*s == 'l') + ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); + else + ArgConverter<long>(arg, *s).visit(arg); + break; + case 'j': + ArgConverter<intmax_t>(arg, *s).visit(arg); + break; + case 'z': + ArgConverter<std::size_t>(arg, *s).visit(arg); + break; + case 't': + ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); + break; + case 'L': + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. + break; + default: + --s; + ArgConverter<void>(arg, *s).visit(arg); + } + + // Parse type. + if (!*s) + FMT_THROW(FormatError("invalid format string")); + spec.type_ = static_cast<char>(*s++); + if (arg.type <= Arg::LAST_INTEGER_TYPE) + { + // Normalize type. + switch (spec.type_) + { + case 'i': + case 'u': + spec.type_ = 'd'; + break; + case 'c': + // TODO: handle wchar_t + internal::CharConverter(arg).visit(arg); + break; + } + } + + start = s; + + // Format argument. + AF(writer_, spec).visit(arg); + } + write(writer_, start, s); +} + +template <typename Char> +void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) +{ + PrintfFormatter<Char>(args, w).format(format); +} + +/** +\rst +Formats arguments and returns the result as a string. + +**Example**:: + +std::string message = fmt::sprintf("The answer is %d", 42); +\endrst +*/ +inline std::string sprintf(CStringRef format, ArgList args) +{ + MemoryWriter w; + printf(w, format, args); + return w.str(); +} +FMT_VARIADIC(std::string, sprintf, CStringRef) + +inline std::wstring sprintf(WCStringRef format, ArgList args) +{ + WMemoryWriter w; + printf(w, format, args); + return w.str(); +} +FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef) + +/** +\rst +Prints formatted data to the file *f*. + +**Example**:: + +fmt::fprintf(stderr, "Don't %s!", "panic"); +\endrst +*/ +FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args); +FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) + +/** +\rst +Prints formatted data to ``stdout``. + +**Example**:: + +fmt::printf("Elapsed time: %.2f seconds", 1.23); +\endrst +*/ +inline int printf(CStringRef format, ArgList args) +{ + return fprintf(stdout, format, args); +} +FMT_VARIADIC(int, printf, CStringRef) + +/** +\rst +Prints formatted data to the stream *os*. + +**Example**:: + +fprintf(cerr, "Don't %s!", "panic"); +\endrst +*/ +inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) +{ + MemoryWriter w; + printf(w, format_str, args); + internal::write(os, w); + return static_cast<int>(w.size()); +} +FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef) +} // namespace fmt + +#ifdef FMT_HEADER_ONLY +# include "printf.cc" +#endif + +#endif // FMT_PRINTF_H_ http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/fmt/fmt.h ---------------------------------------------------------------------- diff --git a/include/spdlog/fmt/fmt.h b/include/spdlog/fmt/fmt.h new file mode 100644 index 0000000..dd035fd --- /dev/null +++ b/include/spdlog/fmt/fmt.h @@ -0,0 +1,28 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// +// Include a bundled header-only copy of fmtlib or an external one. +// By default spdlog include its own copy. +// + +#if !defined(SPDLOG_FMT_EXTERNAL) + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#ifndef FMT_USE_WINDOWS_H +#define FMT_USE_WINDOWS_H 0 +#endif +#include <spdlog/fmt/bundled/format.h> + +#else //external fmtlib + +#include <fmt/format.h> + +#endif + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/fmt/ostr.h ---------------------------------------------------------------------- diff --git a/include/spdlog/fmt/ostr.h b/include/spdlog/fmt/ostr.h new file mode 100644 index 0000000..7a65186 --- /dev/null +++ b/include/spdlog/fmt/ostr.h @@ -0,0 +1,17 @@ +// +// Copyright(c) 2016 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// include external or bundled copy of fmtlib's ostream support +// +#if !defined(SPDLOG_FMT_EXTERNAL) +#include <spdlog/fmt/fmt.h> +#include <spdlog/fmt/bundled/ostream.h> +#else +#include <fmt/ostream.h> +#endif + + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/formatter.h ---------------------------------------------------------------------- diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index 35ea041..0ffcec0 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -1,29 +1,16 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + #pragma once -#include "details/log_msg.h" +#include <spdlog/details/log_msg.h> + +#include <vector> +#include <string> +#include <memory> + namespace spdlog { namespace details @@ -54,5 +41,5 @@ private: }; } -#include "details/pattern_formatter_impl.h" +#include <spdlog/details/pattern_formatter_impl.h> http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/logger.h ---------------------------------------------------------------------- diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 7aefcc7..a2deb51 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -1,48 +1,26 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once -// Thread safe logger +// Thread safe logger (except for set_pattern(..), set_formatter(..) and set_error_handler()) // Has name, log level, vector of std::shared sink pointers and formatter // Upon each log write the logger: // 1. Checks if its log level is enough to log the message // 2. Format the message using the formatter function // 3. Pass the formatted message to its sinks to performa the actual logging -#include<vector> -#include<memory> -#include "sinks/base_sink.h" -#include "common.h" +#include <spdlog/sinks/base_sink.h> +#include <spdlog/common.h> -namespace spdlog -{ +#include <vector> +#include <memory> +#include <string> -namespace details +namespace spdlog { -class line_logger; -} class logger { @@ -56,77 +34,61 @@ public: logger(const logger&) = delete; logger& operator=(const logger&) = delete; + + template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args); + template <typename... Args> void log(level::level_enum lvl, const char* msg); + template <typename... Args> void trace(const char* fmt, const Args&... args); + template <typename... Args> void debug(const char* fmt, const Args&... args); + template <typename... Args> void info(const char* fmt, const Args&... args); + template <typename... Args> void warn(const char* fmt, const Args&... args); + template <typename... Args> void error(const char* fmt, const Args&... args); + template <typename... Args> void critical(const char* fmt, const Args&... args); + + template <typename T> void log(level::level_enum lvl, const T&); + template <typename T> void trace(const T&); + template <typename T> void debug(const T&); + template <typename T> void info(const T&); + template <typename T> void warn(const T&); + template <typename T> void error(const T&); + template <typename T> void critical(const T&); + + bool should_log(level::level_enum) const; void set_level(level::level_enum); level::level_enum level() const; - const std::string& name() const; - bool should_log(level::level_enum) const; - - // logger.info(cppformat_string, arg1, arg2, arg3, ...) call style - template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger info(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger notice(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger warn(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger error(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger critical(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger alert(const char* fmt, const Args&... args); - template <typename... Args> details::line_logger emerg(const char* fmt, const Args&... args); - - - // logger.info(msg) << ".." call style - template <typename T> details::line_logger trace(const T&); - template <typename T> details::line_logger debug(const T&); - template <typename T> details::line_logger info(const T&); - template <typename T> details::line_logger notice(const T&); - template <typename T> details::line_logger warn(const T&); - template <typename T> details::line_logger error(const T&); - template <typename T> details::line_logger critical(const T&); - template <typename T> details::line_logger alert(const T&); - template <typename T> details::line_logger emerg(const T&); - - - // logger.info() << ".." call style - details::line_logger trace(); - details::line_logger debug(); - details::line_logger info(); - details::line_logger notice(); - details::line_logger warn(); - details::line_logger error(); - details::line_logger critical(); - details::line_logger alert(); - details::line_logger emerg(); - - - - // Create log message with the given level, no matter what is the actual logger's level - template <typename... Args> - details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args); - - // Set the format of the log messages from this logger void set_pattern(const std::string&); void set_formatter(formatter_ptr); - void flush(); + // error handler + void set_error_handler(log_err_handler); + log_err_handler error_handler(); + + // automatically call flush() if message level >= log_level + void flush_on(level::level_enum log_level); + + virtual void flush(); + + const std::vector<sink_ptr>& sinks() const; protected: - virtual void _log_msg(details::log_msg&); + virtual void _sink_it(details::log_msg&); virtual void _set_pattern(const std::string&); virtual void _set_formatter(formatter_ptr); - details::line_logger _log_if_enabled(level::level_enum lvl); - template <typename... Args> - details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args); - template<typename T> - inline details::line_logger _log_if_enabled(level::level_enum lvl, const T& msg); + // default error handler: print the error to stderr with the max rate of 1 message/minute + virtual void _default_err_handler(const std::string &msg); - friend details::line_logger; - std::string _name; + // return true if the given message level should trigger a flush + bool _should_flush_on(const details::log_msg&); + + const std::string _name; std::vector<sink_ptr> _sinks; formatter_ptr _formatter; - std::atomic_int _level; - + spdlog::level_t _level; + spdlog::level_t _flush_level; + log_err_handler _err_handler; + std::atomic<time_t> _last_err_time; }; } -#include "details/logger_impl.h" +#include <spdlog/details/logger_impl.h> http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/android_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h new file mode 100644 index 0000000..d8c97e0 --- /dev/null +++ b/include/spdlog/sinks/android_sink.h @@ -0,0 +1,75 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#if defined(__ANDROID__) + +#include <spdlog/sinks/sink.h> + +#include <mutex> +#include <string> +#include <android/log.h> + +namespace spdlog +{ +namespace sinks +{ + +/* +* Android sink (logging using __android_log_write) +* __android_log_write is thread-safe. No lock is needed. +*/ +class android_sink : public sink +{ +public: + explicit android_sink(const std::string& tag = "spdlog"): _tag(tag) {} + + void log(const details::log_msg& msg) override + { + const android_LogPriority priority = convert_to_android(msg.level); + // See system/core/liblog/logger_write.c for explanation of return value + const int ret = __android_log_write( + priority, _tag.c_str(), msg.formatted.c_str() + ); + if (ret < 0) + { + throw spdlog_ex("__android_log_write() failed", ret); + } + } + + void flush() override + { + } + +private: + static android_LogPriority convert_to_android(spdlog::level::level_enum level) + { + switch(level) + { + case spdlog::level::trace: + return ANDROID_LOG_VERBOSE; + case spdlog::level::debug: + return ANDROID_LOG_DEBUG; + case spdlog::level::info: + return ANDROID_LOG_INFO; + case spdlog::level::warn: + return ANDROID_LOG_WARN; + case spdlog::level::err: + return ANDROID_LOG_ERROR; + case spdlog::level::critical: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_DEFAULT; + } + } + + std::string _tag; +}; + +} +} + +#endif http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/ansicolor_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/ansicolor_sink.h b/include/spdlog/sinks/ansicolor_sink.h new file mode 100644 index 0000000..96e1014 --- /dev/null +++ b/include/spdlog/sinks/ansicolor_sink.h @@ -0,0 +1,116 @@ +// +// Copyright(c) 2016 Kevin M. Godby (a modified version by spdlog). +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/sinks/base_sink.h> +#include <spdlog/common.h> + +#include <string> +#include <map> + +namespace spdlog +{ +namespace sinks +{ + +/** + * @brief The ansi_color_sink is a decorator around another sink and prefixes + * the output with an ANSI escape sequence color code depending on the severity + * of the message. + */ +class ansicolor_sink : public sink +{ +public: + ansicolor_sink(sink_ptr wrapped_sink); + virtual ~ansicolor_sink(); + + ansicolor_sink(const ansicolor_sink& other) = delete; + ansicolor_sink& operator=(const ansicolor_sink& other) = delete; + + virtual void log(const details::log_msg& msg) override; + virtual void flush() override; + + void set_color(level::level_enum color_level, const std::string& color); + + /// Formatting codes + const std::string reset = "\033[00m"; + const std::string bold = "\033[1m"; + const std::string dark = "\033[2m"; + const std::string underline = "\033[4m"; + const std::string blink = "\033[5m"; + const std::string reverse = "\033[7m"; + const std::string concealed = "\033[8m"; + + // Foreground colors + const std::string grey = "\033[30m"; + const std::string red = "\033[31m"; + const std::string green = "\033[32m"; + const std::string yellow = "\033[33m"; + const std::string blue = "\033[34m"; + const std::string magenta = "\033[35m"; + const std::string cyan = "\033[36m"; + const std::string white = "\033[37m"; + + /// Background colors + const std::string on_grey = "\033[40m"; + const std::string on_red = "\033[41m"; + const std::string on_green = "\033[42m"; + const std::string on_yellow = "\033[43m"; + const std::string on_blue = "\033[44m"; + const std::string on_magenta = "\033[45m"; + const std::string on_cyan = "\033[46m"; + const std::string on_white = "\033[47m"; + + +protected: + sink_ptr sink_; + std::map<level::level_enum, std::string> colors_; +}; + +inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sink) +{ + colors_[level::trace] = cyan; + colors_[level::debug] = cyan; + colors_[level::info] = bold; + colors_[level::warn] = yellow + bold; + colors_[level::err] = red + bold; + colors_[level::critical] = bold + on_red; + colors_[level::off] = reset; +} + +inline void ansicolor_sink::log(const details::log_msg& msg) +{ + // Wrap the originally formatted message in color codes + const std::string& prefix = colors_[msg.level]; + const std::string& s = msg.formatted.str(); + const std::string& suffix = reset; + details::log_msg m; + m.level = msg.level; + m.logger_name = msg.logger_name; + m.time = msg.time; + m.thread_id = msg.thread_id; + m.formatted << prefix << s << suffix; + sink_->log(m); +} + +inline void ansicolor_sink::flush() +{ + sink_->flush(); +} + +inline void ansicolor_sink::set_color(level::level_enum color_level, const std::string& color) +{ + colors_[color_level] = color; +} + +inline ansicolor_sink::~ansicolor_sink() +{ + flush(); +} + +} // namespace sinks +} // namespace spdlog + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/base_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/base_sink.h b/include/spdlog/sinks/base_sink.h index 12d63ea..7f1a31d 100644 --- a/include/spdlog/sinks/base_sink.h +++ b/include/spdlog/sinks/base_sink.h @@ -1,42 +1,21 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once // // base sink templated over a mutex (either dummy or realy) // concrete implementation should only overrid the _sink_it method. -// all locking is taken care of here so no locking needed by the implementors.. +// all locking is taken care of here so no locking needed by the implementers.. // -#include<string> -#include<mutex> -#include<atomic> -#include "./sink.h" -#include "../formatter.h" -#include "../common.h" -#include "../details/log_msg.h" +#include <spdlog/sinks/sink.h> +#include <spdlog/formatter.h> +#include <spdlog/common.h> +#include <spdlog/details/log_msg.h> +#include <mutex> namespace spdlog { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/dist_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/dist_sink.h b/include/spdlog/sinks/dist_sink.h new file mode 100644 index 0000000..cef08bf --- /dev/null +++ b/include/spdlog/sinks/dist_sink.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2015 David Schury, Gabi Melman +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/details/log_msg.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> +#include <spdlog/sinks/sink.h> + +#include <algorithm> +#include <mutex> +#include <memory> +#include <vector> + +// Distribution sink (mux). Stores a vector of sinks which get called when log is called + +namespace spdlog +{ +namespace sinks +{ +template<class Mutex> +class dist_sink: public base_sink<Mutex> +{ +public: + explicit dist_sink() :_sinks() {} + dist_sink(const dist_sink&) = delete; + dist_sink& operator=(const dist_sink&) = delete; + virtual ~dist_sink() = default; + +protected: + std::vector<std::shared_ptr<sink>> _sinks; + + void _sink_it(const details::log_msg& msg) override + { + for (auto &sink : _sinks) + { + if( sink->should_log( msg.level)) + { + sink->log(msg); + } + } + } + +public: + void flush() override + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex); + for (auto &sink : _sinks) + sink->flush(); + } + + void add_sink(std::shared_ptr<sink> sink) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex); + _sinks.push_back(sink); + } + + void remove_sink(std::shared_ptr<sink> sink) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex); + _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end()); + } +}; + +typedef dist_sink<std::mutex> dist_sink_mt; +typedef dist_sink<details::null_mutex> dist_sink_st; +} +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/file_sinks.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/file_sinks.h b/include/spdlog/sinks/file_sinks.h index 79cbb4e..d40499b 100644 --- a/include/spdlog/sinks/file_sinks.h +++ b/include/spdlog/sinks/file_sinks.h @@ -1,64 +1,57 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/details/file_helper.h> +#include <spdlog/fmt/fmt.h> + +#include <algorithm> +#include <chrono> +#include <cstdio> +#include <ctime> #include <mutex> -#include "base_sink.h" -#include "../details/null_mutex.h" -#include "../details/file_helper.h" -#include "../details/format.h" +#include <string> +#include <cerrno> namespace spdlog { namespace sinks { /* -* Trivial file sink with single file as target -*/ + * Trivial file sink with single file as target + */ template<class Mutex> class simple_file_sink : public base_sink < Mutex > { public: - explicit simple_file_sink(const std::string &filename, - bool force_flush = false) : - _file_helper(force_flush) + explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false) { - _file_helper.open(filename); + _file_helper.open(filename, truncate); } void flush() override { _file_helper.flush(); } + void set_force_flush(bool force_flush) + { + _force_flush = force_flush; + } protected: void _sink_it(const details::log_msg& msg) override { _file_helper.write(msg); + if(_force_flush) + _file_helper.flush(); } private: details::file_helper _file_helper; + bool _force_flush; }; typedef simple_file_sink<std::mutex> simple_file_sink_mt; @@ -71,17 +64,17 @@ template<class Mutex> class rotating_file_sink : public base_sink < Mutex > { public: - rotating_file_sink(const std::string &base_filename, const std::string &extension, - std::size_t max_size, std::size_t max_files, - bool force_flush = false) : + rotating_file_sink(const filename_t &base_filename, const filename_t &extension, + std::size_t max_size, std::size_t max_files ) : _base_filename(base_filename), _extension(extension), _max_size(max_size), _max_files(max_files), _current_size(0), - _file_helper(force_flush) + _file_helper() { _file_helper.open(calc_filename(_base_filename, 0, _extension)); + _current_size = _file_helper.size(); //expensive. called only once } void flush() override @@ -102,13 +95,13 @@ protected: } private: - static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension) + static filename_t calc_filename(const filename_t& filename, std::size_t index, const filename_t& extension) { - fmt::MemoryWriter w; + std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; if (index) - w.write("{}.{}.{}", filename, index, extension); + w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension); else - w.write("{}.{}", filename, extension); + w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension); return w.str(); } @@ -120,28 +113,29 @@ private: void _rotate() { + using details::os::filename_to_str; _file_helper.close(); for (auto i = _max_files; i > 0; --i) { - std::string src = calc_filename(_base_filename, i - 1, _extension); - std::string target = calc_filename(_base_filename, i, _extension); + filename_t src = calc_filename(_base_filename, i - 1, _extension); + filename_t target = calc_filename(_base_filename, i, _extension); if (details::file_helper::file_exists(target)) { - if (std::remove(target.c_str()) != 0) + if (details::os::remove(target) != 0) { - throw spdlog_ex("rotating_file_sink: failed removing " + target); + throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno); } } - if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str())) + if (details::file_helper::file_exists(src) && details::os::rename(src, target)) { - throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target); + throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); } } _file_helper.reopen(true); } - std::string _base_filename; - std::string _extension; + filename_t _base_filename; + filename_t _extension; std::size_t _max_size; std::size_t _max_files; std::size_t _current_size; @@ -152,28 +146,56 @@ typedef rotating_file_sink<std::mutex> rotating_file_sink_mt; typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st; /* + * Default generator of daily log file names. + */ +struct default_daily_file_name_calculator +{ + // Create filename for the form basename.YYYY-MM-DD_hh-mm.extension + static filename_t calc_filename(const filename_t& basename, const filename_t& extension) + { + std::tm tm = spdlog::details::os::localtime(); + std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension); + return w.str(); + } +}; + +/* + * Generator of daily log file names in format basename.YYYY-MM-DD.extension + */ +struct dateonly_daily_file_name_calculator +{ + // Create filename for the form basename.YYYY-MM-DD.extension + static filename_t calc_filename(const filename_t& basename, const filename_t& extension) + { + std::tm tm = spdlog::details::os::localtime(); + std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w; + w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension); + return w.str(); + } +}; + +/* * Rotating file sink based on date. rotates at midnight */ -template<class Mutex> +template<class Mutex, class FileNameCalc = default_daily_file_name_calculator> class daily_file_sink :public base_sink < Mutex > { public: //create daily file sink which rotates on given time daily_file_sink( - const std::string& base_filename, - const std::string& extension, + const filename_t& base_filename, + const filename_t& extension, int rotation_hour, - int rotation_minute, - bool force_flush = false) : _base_filename(base_filename), + int rotation_minute) : _base_filename(base_filename), _extension(extension), _rotation_h(rotation_hour), - _rotation_m(rotation_minute), - _file_helper(force_flush) + _rotation_m(rotation_minute) { if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59) throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor"); _rotation_tp = _next_rotation_tp(); - _file_helper.open(calc_filename(_base_filename, _extension)); + _file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension)); } void flush() override @@ -186,7 +208,7 @@ protected: { if (std::chrono::system_clock::now() >= _rotation_tp) { - _file_helper.open(calc_filename(_base_filename, _extension)); + _file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension)); _rotation_tp = _next_rotation_tp(); } _file_helper.write(msg); @@ -195,8 +217,7 @@ protected: private: std::chrono::system_clock::time_point _next_rotation_tp() { - using namespace std::chrono; - auto now = system_clock::now(); + auto now = std::chrono::system_clock::now(); time_t tnow = std::chrono::system_clock::to_time_t(now); tm date = spdlog::details::os::localtime(tnow); date.tm_hour = _rotation_h; @@ -206,20 +227,11 @@ private: if (rotation_time > now) return rotation_time; else - return system_clock::time_point(rotation_time + hours(24)); - } - - //Create filename for the form basename.YYYY-MM-DD.extension - static std::string calc_filename(const std::string& basename, const std::string& extension) - { - std::tm tm = spdlog::details::os::localtime(); - fmt::MemoryWriter w; - w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension); - return w.str(); + return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24)); } - std::string _base_filename; - std::string _extension; + filename_t _base_filename; + filename_t _extension; int _rotation_h; int _rotation_m; std::chrono::system_clock::time_point _rotation_tp; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/msvc_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/msvc_sink.h b/include/spdlog/sinks/msvc_sink.h new file mode 100644 index 0000000..16342ca --- /dev/null +++ b/include/spdlog/sinks/msvc_sink.h @@ -0,0 +1,50 @@ +// +// Copyright(c) 2016 Alexander Dalshov. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#if defined(_MSC_VER) + +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> + +#include <WinBase.h> + +#include <mutex> +#include <string> + +namespace spdlog +{ +namespace sinks +{ +/* +* MSVC sink (logging using OutputDebugStringA) +*/ +template<class Mutex> +class msvc_sink : public base_sink < Mutex > +{ +public: + explicit msvc_sink() + { + } + + void flush() override + { + } + +protected: + void _sink_it(const details::log_msg& msg) override + { + OutputDebugStringA(msg.formatted.c_str()); + } +}; + +typedef msvc_sink<std::mutex> msvc_sink_mt; +typedef msvc_sink<details::null_mutex> msvc_sink_st; + +} +} + +#endif http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/null_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/null_sink.h b/include/spdlog/sinks/null_sink.h index 992b3b7..1d427aa 100644 --- a/include/spdlog/sinks/null_sink.h +++ b/include/spdlog/sinks/null_sink.h @@ -1,32 +1,14 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once -#include <mutex> -#include "./base_sink.h" -#include "../details/null_mutex.h" +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> + +#include <mutex> namespace spdlog { @@ -45,7 +27,7 @@ protected: }; typedef null_sink<details::null_mutex> null_sink_st; -typedef null_sink<std::mutex> null_sink_mt; +typedef null_sink<details::null_mutex> null_sink_mt; } } http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/ostream_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/ostream_sink.h b/include/spdlog/sinks/ostream_sink.h index f2fe3b2..feb5efa 100644 --- a/include/spdlog/sinks/ostream_sink.h +++ b/include/spdlog/sinks/ostream_sink.h @@ -1,35 +1,15 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> + #include <ostream> #include <mutex> -#include <memory> - -#include "../details/null_mutex.h" -#include "./base_sink.h" namespace spdlog { http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 88c423a..b48dd8b 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -1,30 +1,12 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + #pragma once -#include "../details/log_msg.h" +#include <spdlog/details/log_msg.h> namespace spdlog { @@ -33,10 +15,39 @@ namespace sinks class sink { public: + sink() + { + _level = level::trace; + } + virtual ~sink() {} virtual void log(const details::log_msg& msg) = 0; virtual void flush() = 0; + + bool should_log(level::level_enum msg_level) const; + void set_level(level::level_enum log_level); + level::level_enum level() const; + +private: + level_t _level; + }; + +inline bool sink::should_log(level::level_enum msg_level) const +{ + return msg_level >= _level.load(std::memory_order_relaxed); +} + +inline void sink::set_level(level::level_enum log_level) +{ + _level.store(log_level); +} + +inline level::level_enum sink::level() const +{ + return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed)); +} + } } http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/stdout_sinks.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/stdout_sinks.h b/include/spdlog/sinks/stdout_sinks.h index 4ca16ac..c05f80d 100644 --- a/include/spdlog/sinks/stdout_sinks.h +++ b/include/spdlog/sinks/stdout_sinks.h @@ -1,33 +1,16 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once -#include <iostream> +#include <spdlog/details/null_mutex.h> +#include <spdlog/sinks/base_sink.h> + +#include <cstdio> +#include <memory> #include <mutex> -#include "./ostream_sink.h" -#include "spdlog/details/null_mutex.h" namespace spdlog { @@ -35,16 +18,28 @@ namespace sinks { template <class Mutex> -class stdout_sink : public ostream_sink<Mutex> +class stdout_sink: public base_sink<Mutex> { using MyType = stdout_sink<Mutex>; public: - stdout_sink() : ostream_sink<Mutex>(std::cout, true) {} + stdout_sink() + {} static std::shared_ptr<MyType> instance() { static std::shared_ptr<MyType> instance = std::make_shared<MyType>(); return instance; } + + void _sink_it(const details::log_msg& msg) override + { + fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout); + flush(); + } + + void flush() override + { + fflush(stdout); + } }; typedef stdout_sink<details::null_mutex> stdout_sink_st; @@ -52,17 +47,28 @@ typedef stdout_sink<std::mutex> stdout_sink_mt; template <class Mutex> -class stderr_sink : public ostream_sink<Mutex> +class stderr_sink: public base_sink<Mutex> { using MyType = stderr_sink<Mutex>; public: - stderr_sink() : ostream_sink<Mutex>(std::cerr, true) {} + stderr_sink() + {} static std::shared_ptr<MyType> instance() { static std::shared_ptr<MyType> instance = std::make_shared<MyType>(); return instance; } + void _sink_it(const details::log_msg& msg) override + { + fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr); + flush(); + } + + void flush() override + { + fflush(stderr); + } }; typedef stderr_sink<std::mutex> stderr_sink_mt; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/syslog_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index 37b6513..0d8633c 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -1,39 +1,21 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// #pragma once -#ifdef __linux__ +#include <spdlog/common.h> + +#ifdef SPDLOG_ENABLE_SYSLOG + +#include <spdlog/sinks/sink.h> +#include <spdlog/details/log_msg.h> #include <array> #include <string> #include <syslog.h> -#include "./sink.h" -#include "../common.h" -#include "../details/log_msg.h" - namespace spdlog { @@ -54,12 +36,9 @@ public: _priorities[static_cast<int>(level::trace)] = LOG_DEBUG; _priorities[static_cast<int>(level::debug)] = LOG_DEBUG; _priorities[static_cast<int>(level::info)] = LOG_INFO; - _priorities[static_cast<int>(level::notice)] = LOG_NOTICE; _priorities[static_cast<int>(level::warn)] = LOG_WARNING; _priorities[static_cast<int>(level::err)] = LOG_ERR; _priorities[static_cast<int>(level::critical)] = LOG_CRIT; - _priorities[static_cast<int>(level::alert)] = LOG_ALERT; - _priorities[static_cast<int>(level::emerg)] = LOG_EMERG; _priorities[static_cast<int>(level::off)] = LOG_INFO; //set ident to be program name if empty @@ -75,7 +54,7 @@ public: void log(const details::log_msg &msg) override { - ::syslog(syslog_prio_from_level(msg), "%s", msg.formatted.str().c_str()); + ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str()); } void flush() override @@ -84,7 +63,7 @@ public: private: - std::array<int, 10> _priorities; + std::array<int, 7> _priorities; //must store the ident because the man says openlog might use the pointer as is and not a string copy const std::string _ident; http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/sinks/wincolor_sink.h ---------------------------------------------------------------------- diff --git a/include/spdlog/sinks/wincolor_sink.h b/include/spdlog/sinks/wincolor_sink.h new file mode 100644 index 0000000..63ecbe2 --- /dev/null +++ b/include/spdlog/sinks/wincolor_sink.h @@ -0,0 +1,116 @@ +// +// Copyright(c) 2016 spdlog +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/sinks/base_sink.h> +#include <spdlog/details/null_mutex.h> +#include <spdlog/common.h> + +#include <mutex> +#include <string> +#include <map> +#include <wincon.h> + +namespace spdlog +{ +namespace sinks +{ +/* + * Windows color console sink. Uses WriteConsoleA to write to the console with colors + */ +template<class Mutex> +class wincolor_sink: public base_sink<Mutex> +{ +public: + const WORD BOLD = FOREGROUND_INTENSITY; + const WORD RED = FOREGROUND_RED; + const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; + const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; + + wincolor_sink(HANDLE std_handle): out_handle_(std_handle) + { + colors_[level::trace] = CYAN; + colors_[level::debug] = CYAN; + colors_[level::info] = WHITE | BOLD; + colors_[level::warn] = YELLOW | BOLD; + colors_[level::err] = RED | BOLD; // red bold + colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background + colors_[level::off] = 0; + } + + virtual ~wincolor_sink() + { + flush(); + } + + wincolor_sink(const wincolor_sink& other) = delete; + wincolor_sink& operator=(const wincolor_sink& other) = delete; + + virtual void _sink_it(const details::log_msg& msg) override + { + auto color = colors_[msg.level]; + auto orig_attribs = set_console_attribs(color); + WriteConsoleA(out_handle_, msg.formatted.data(), static_cast<DWORD>(msg.formatted.size()), nullptr, nullptr); + SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors + } + + virtual void flush() override + { + // windows console always flushed? + } + + // change the color for the given level + void set_color(level::level_enum level, WORD color) + { + std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex); + colors_[level] = color; + } + +private: + HANDLE out_handle_; + std::map<level::level_enum, WORD> colors_; + + // set color and return the orig console attributes (for resetting later) + WORD set_console_attribs(WORD attribs) + { + CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; + GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); + SetConsoleTextAttribute(out_handle_, attribs); + return orig_buffer_info.wAttributes; //return orig attribs + } +}; + +// +// windows color console to stdout +// +template<class Mutex> +class wincolor_stdout_sink: public wincolor_sink<Mutex> +{ +public: + wincolor_stdout_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_OUTPUT_HANDLE)) + {} +}; + +typedef wincolor_stdout_sink<std::mutex> wincolor_stdout_sink_mt; +typedef wincolor_stdout_sink<details::null_mutex> wincolor_stdout_sink_st; + +// +// windows color console to stderr +// +template<class Mutex> +class wincolor_stderr_sink: public wincolor_sink<Mutex> +{ +public: + wincolor_stderr_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_ERROR_HANDLE)) + {} +}; + +typedef wincolor_stderr_sink<std::mutex> wincolor_stderr_sink_mt; +typedef wincolor_stderr_sink<details::null_mutex> wincolor_stderr_sink_st; + +} +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/939751c1/include/spdlog/spdlog.h ---------------------------------------------------------------------- diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 5cec562..6b93a7a 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -1,48 +1,33 @@ -/*************************************************************************/ -/* spdlog - an extremely fast and easy to use c++11 logging library. */ -/* Copyright (c) 2014 Gabi Melman. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - - +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// // spdlog main header file. -//see example.cpp for usage example +// see example.cpp for usage example #pragma once -#include "tweakme.h" -#include "common.h" -#include "logger.h" +#define SPDLOG_VERSION "0.12.0" + +#include <spdlog/tweakme.h> +#include <spdlog/common.h> +#include <spdlog/logger.h> + +#include <memory> +#include <functional> +#include <chrono> +#include <string> namespace spdlog { + +// // Return an existing logger or nullptr if a logger with such name doesn't exist. -// Examples: +// example: spdlog::get("my_logger")->info("hello {}", "world"); // -// spdlog::get("mylog")->info("Hello"); -// auto logger = spdlog::get("mylog"); -// logger.info("This is another message" , x, y, z); -// logger.info() << "This is another message" << x << y << z; std::shared_ptr<logger> get(const std::string& name); + // // Set global formatting // example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v"); @@ -56,6 +41,11 @@ void set_formatter(formatter_ptr f); void set_level(level::level_enum log_level); // +// Set global error handler +// +void set_error_handler(log_err_handler); + +// // Turn on async mode (off by default) and set the queue size for each async_logger. // effective only for loggers created after this call. // queue_size: size of queue (must be power of 2): @@ -68,23 +58,33 @@ void set_level(level::level_enum log_level); // worker_warmup_cb (optional): // callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity) // -void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero()); +// worker_teardown_cb (optional): +// callback function that will be called in worker thread upon exit +// +void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr); // Turn off async mode void set_sync_mode(); + +// +// Create and register multi/single threaded basic file logger. +// Basic logger simply writes to given file without any limitatons or rotations. +// +std::shared_ptr<logger> basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false); +std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false); + // // Create and register multi/single threaded rotating file logger // -std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false); -std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false); +std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); +std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files); // // Create file logger which creates new file on the given time (default in midnight): // -std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false); -std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false); - +std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); +std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0); // // Create and register stdout/stderr loggers @@ -93,15 +93,28 @@ std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name); std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name); std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name); std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name); +// +// Create and register colored stdout/stderr loggers +// +std::shared_ptr<logger> stdout_color_mt(const std::string& logger_name); +std::shared_ptr<logger> stdout_color_st(const std::string& logger_name); +std::shared_ptr<logger> stderr_color_mt(const std::string& logger_name); +std::shared_ptr<logger> stderr_color_st(const std::string& logger_name); // // Create and register a syslog logger // -#ifdef __linux__ +#ifdef SPDLOG_ENABLE_SYSLOG std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0); #endif +#if defined(__ANDROID__) +std::shared_ptr<logger> android_logger(const std::string& logger_name, const std::string& tag = "spdlog"); +#endif + +// Create and register a logger a single sink +std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink); // Create and register a logger with multiple sinks std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks); @@ -110,40 +123,50 @@ std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_b // Create and register a logger with templated sink type -// Example: spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename", "txt"); +// Example: +// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename", "txt"); template <typename Sink, typename... Args> -std::shared_ptr<spdlog::logger> create(const std::string& logger_name, const Args&...); +std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...); // Register the given logger with the given name void register_logger(std::shared_ptr<logger> logger); +// Apply a user defined function on all registered loggers +// Example: +// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();}); +void apply_all(std::function<void(std::shared_ptr<logger>)> fun); + // Drop the reference to the given logger void drop(const std::string &name); -// Drop all references +// Drop all references from the registry void drop_all(); /////////////////////////////////////////////////////////////////////////////// // -// Macros to be display source file & line // Trace & Debug can be switched on/off at compile time for zero cost debug statements. // Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in teakme.h to enable. +// SPDLOG_TRACE(..) will also print current file and line. // // Example: -// spdlog::set_level(spdlog::level::debug); -// SPDLOG_DEBUG(my_logger, "Some debug message {} {}", 1, 3.2); +// spdlog::set_level(spdlog::level::trace); +// SPDLOG_TRACE(my_logger, "some trace message"); +// SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2); +// SPDLOG_DEBUG(my_logger, "some debug message {} {}", 3, 4); /////////////////////////////////////////////////////////////////////////////// #ifdef SPDLOG_TRACE_ON -#define SPDLOG_TRACE(logger, ...) logger->trace(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")"; +#define SPDLOG_STR_H(x) #x +#define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x) +#define SPDLOG_TRACE(logger, ...) logger->trace("[" __FILE__ " line #" SPDLOG_STR_HELPER(__LINE__) "] " __VA_ARGS__) #else #define SPDLOG_TRACE(logger, ...) #endif #ifdef SPDLOG_DEBUG_ON -#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")"; +#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) #else #define SPDLOG_DEBUG(logger, ...) #endif @@ -152,4 +175,4 @@ void drop_all(); } -#include "details/spdlog_impl.h" +#include <spdlog/details/spdlog_impl.h>
