This is an automated email from the git hooks/post-receive script. tille pushed a commit to branch master in repository r-cran-plogr.
commit 79f48a442cae924fed33e63432944eafc7c892c9 Author: Andreas Tille <[email protected]> Date: Fri Sep 29 09:37:42 2017 +0200 New upstream version 0.1-1 --- DESCRIPTION | 24 +++++ LICENSE | 2 + MD5 | 18 ++++ NAMESPACE | 2 + NEWS.md | 12 +++ R/plogr-package.R | 21 ++++ README.md | 68 ++++++++++++ debian/changelog | 5 - debian/compat | 1 - debian/control | 24 ----- debian/copyright | 33 ------ debian/rules | 5 - debian/source/format | 1 - debian/watch | 2 - inst/include/plog/Appenders/ColorConsoleAppender.h | 101 +++++++++++++++++ inst/include/plog/Appenders/ConsoleAppender.h | 26 +++++ inst/include/plog/Appenders/IAppender.h | 14 +++ .../include/plog/Formatters/FuncMessageFormatter.h | 23 ++++ inst/include/plog/Init.h | 23 ++++ inst/include/plog/Log.h | 98 +++++++++++++++++ inst/include/plog/Logger.h | 69 ++++++++++++ inst/include/plog/Record.h | 82 ++++++++++++++ inst/include/plog/Severity.h | 54 ++++++++++ inst/include/plog/Util.h | 120 +++++++++++++++++++++ inst/include/plogr.h | 39 +++++++ man/plogr-package.Rd | 33 ++++++ 26 files changed, 829 insertions(+), 71 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..952aca0 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,24 @@ +Package: plogr +Title: The 'plog' C++ Logging Library +Version: 0.1-1 +Date: 2016-09-24 +Authors@R: c( + person("Kirill", "Müller", role = c("aut", "cre"), email = "[email protected]"), + person("Sergey", "Podobry", role = "cph", comment = "Author of the bundled plog library")) +Description: + A simple header-only logging library for C++. + Add 'LinkingTo: plogr' to 'DESCRIPTION', and '#include <plogr.h>' in your C++ modules to use it. +Suggests: Rcpp +License: MIT + file LICENSE +Encoding: UTF-8 +LazyData: true +URL: https://github.com/krlmlr/plogr#readme +BugReports: https://github.com/krlmlr/plogr/issues +RoxygenNote: 5.0.1.9000 +NeedsCompilation: no +Packaged: 2016-09-24 12:08:49 UTC; muelleki +Author: Kirill Müller [aut, cre], + Sergey Podobry [cph] (Author of the bundled plog library) +Maintainer: Kirill Müller <[email protected]> +Repository: CRAN +Date/Publication: 2016-09-24 18:23:26 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..03c9403 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2016 +COPYRIGHT HOLDER: Kirill Müller, Sergey Podobry diff --git a/MD5 b/MD5 new file mode 100644 index 0000000..b332dd4 --- /dev/null +++ b/MD5 @@ -0,0 +1,18 @@ +a3025b78a00a0ad0435a99ed24068ac8 *DESCRIPTION +79a530ad02c67c61317228e9b1ffadfc *LICENSE +dc21c19f0d6968ee25d441b2cf46017d *NAMESPACE +2c7edb9a1a0e2dfb68e01a041f4731c5 *NEWS.md +cbd1a36ca99d14682d9240d6c0f7cf2e *R/plogr-package.R +318bfd2a6d61c8549dcbb86379c3a5b0 *README.md +93068ec6c9320f5672c2a7dd0944830f *inst/include/plog/Appenders/ColorConsoleAppender.h +212f37e372f00972a3c4b16f295789c0 *inst/include/plog/Appenders/ConsoleAppender.h +ffc24c1e15a5bd226534ebf74f8e6445 *inst/include/plog/Appenders/IAppender.h +bb505ee61650e93389cecf4508fb0b7d *inst/include/plog/Formatters/FuncMessageFormatter.h +7e5c2d6e546594d0b03bc5e2cb45da0e *inst/include/plog/Init.h +e0d71adacd017bb8cf4bc2d58f163e37 *inst/include/plog/Log.h +85ffbe6c9063ccdd24b540230e36ec24 *inst/include/plog/Logger.h +119bb25733f63c1da2b26933ea8032d4 *inst/include/plog/Record.h +aa8f12ddb28fe989c9310cef9c73fb03 *inst/include/plog/Severity.h +27eb1a6142b2fffd4d894e72ff98632c *inst/include/plog/Util.h +e2a198d4ef360342d027202193176552 *inst/include/plogr.h +ae4e871bc4cd45b2342d51cd09476def *man/plogr-package.Rd diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..6ae9268 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,2 @@ +# Generated by roxygen2: do not edit by hand + diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..925a907 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,12 @@ +## plogr 0.1-1 (2016-09-24) + +- Remove useless operator overloads. +- Reword description. + + +# plogr 0.1 (2016-09-24) + +- Using a stripped version of plog 1.0-1. +- Works on Linux, OS X, and Windows. +- Log items are printed using. +- New `plog::init_r()` to initialize logging via `REprintf()`, allows changing the log level and passing the log level as string. diff --git a/R/plogr-package.R b/R/plogr-package.R new file mode 100644 index 0000000..15427f1 --- /dev/null +++ b/R/plogr-package.R @@ -0,0 +1,21 @@ +#' @examples +#' plogr_demo <- Rcpp::cppFunction(depends = "plogr", ' +#' // C++ code begin +#' #include <plogr.h> +#' +#' RObject plogr_demo() { +#' plog::init_r(plog::info); +#' LOG_INFO << "shown"; +#' LOG_DEBUG << "not shown"; +#' plog::init_r("DEBUG"); +#' LOG_DEBUG << "shown now"; +#' return R_NilValue; +#' } +#' +#' #include <Rcpp.h> // not necessary to use plogr +#' // C++ code end +#' ' +#' ) +#' +#' plogr_demo() +"_PACKAGE" diff --git a/README.md b/README.md new file mode 100644 index 0000000..1ed902f --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ + +<!-- README.md is generated from README.Rmd. Please edit that file --> +plogr [](https://travis-ci.org/krlmlr/plogr) [](https://ci.appveyor.com/project/krlmlr/plogr) +============================================================================================================================================================================================================================================================================================ + +Provides the header files for a stripped-down version of the [plog](https://github.com/SergiusTheBest/plog) header-only C++ logging library, and a method to log to R's standard error stream. + +Installation +------------ + +You can install `plogr` from GitHub with: + +``` r +# install.packages("devtools") +devtools::install_github("krlmlr/plogr") +``` + +Usage +----- + +Add `LinkingTo: plogr` to your `DESCRIPTION`, and add `#include <plogr.h>` to all modules where you want to access the logging. If your package has an univeral header file which you include from all modules, it's probably a good idea to insert the `#include` directive there, so that all of your code has access to logging. The following system header files will be included: + +- `sstream` +- `iostream` +- `vector` +- `cassert` +- `cstring` +- `time.h` (on Linux/OS X) +- `sys/time.h` (on Windows) +- `R.h` + +Example +------- + +The code shows a small usage example and a demo which we'll call from R below. (`Rcpp` is *not* necessary to use `plogr`, it is only needed to run the C++ code chunk.) The `init_r()` function is the only new function added by the R package, and initializes a logger that logs to R's standard error stream. For further details consult the [plog documentation](https://github.com/SergiusTheBest/plog#readme); for compatibility reasons you won't find the file appenders in this package. + +``` cpp +// [[Rcpp::depends(plogr)]] +#include <plogr.h> + +// [[Rcpp::export]] +void plogr_demo() { + LOG_INFO << "test 1"; + plog::init_r(plog::info); + LOG_INFO << "test 2"; + LOG_DEBUG << "test 3"; + plog::init_r("DEBUG"); // You can also pass a string + LOG_INFO << "test 4"; + LOG_DEBUG << "test 5"; +} + +#include <Rcpp.h> // not necessary to use plogr +``` + +The R code below calls the `plogr_demo()` C++ function defined above. Currently, the messages are printed straight to the standard error stream, so the message capturing mechanisms employed by `knitr` don't work. We use a sink with a text connection to capture the messages, and print the contents of the variable to which the text connection assigns. + +``` r +output <- character() +con <- textConnection("output", "a") +withr::with_message_sink(con, plogr_demo()) +close(con) +cat(output, sep = "\n") +#> plogr_demo@8: test 2 +#> plogr_demo@11: test 4 +#> plogr_demo@12: test 5 +``` + +Nothing is printed before we actually initialize the logger. Because it is initialized to the `info` level, the debug log message is not shown, and only "test 2" comes through. After changing the log level, the debug message is also shown. diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 85c2ba1..0000000 --- a/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -r-cran-plogr (0.1-1-1) unstable; urgency=medium - - * Initial release (closes: #846349) - - -- Andreas Tille <[email protected]> Wed, 30 Nov 2016 15:59:05 +0100 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index f599e28..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/debian/control b/debian/control deleted file mode 100644 index edf7714..0000000 --- a/debian/control +++ /dev/null @@ -1,24 +0,0 @@ -Source: r-cran-plogr -Maintainer: Debian Med Packaging Team <[email protected]> -Uploaders: Andreas Tille <[email protected]> -Section: gnu-r -Priority: optional -Build-Depends: debhelper (>= 10), - dh-r, - r-base-dev -Standards-Version: 3.9.8 -Vcs-Browser: https://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-plogr/trunk/ -Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-plogr/trunk/ -Homepage: https://cran.r-project.org/package=plogr - -Package: r-cran-plogr -Architecture: all -Depends: ${R:Depends}, - ${shlibs:Depends}, - ${misc:Depends} -Recommends: ${R:Recommends} -Suggests: ${R:Suggests} -Description: GNU R C++ Logging Library - Plogr is a simple header-only logging library for C++ to be used with - GNU R. Add 'LinkingTo: plogr' to 'DESCRIPTION', and '#include <plogr.h>' - in your C++ modules to use it. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 10b6825..0000000 --- a/debian/copyright +++ /dev/null @@ -1,33 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: plogr -Upstream-Contact: Kirill Müller <[email protected]> -Source: https://cran.r-project.org/package=plogr - -Files: * -Copyright: 2015-2016 Kirill Müller - Sergey Podobry(Author of the bundled plog library) -License: MIT - -Files: debian/* -Copyright: 2016 Andreas Tille <[email protected]> -License: MIT - -License: MIT - 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. diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 529c38a..0000000 --- a/debian/rules +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/make -f - -%: - dh $@ --buildsystem R - diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8..0000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debian/watch b/debian/watch deleted file mode 100644 index c3f4210..0000000 --- a/debian/watch +++ /dev/null @@ -1,2 +0,0 @@ -version=4 -https://cran.r-project.org/src/contrib/plogr_([-\d.]*)\.tar\.gz diff --git a/inst/include/plog/Appenders/ColorConsoleAppender.h b/inst/include/plog/Appenders/ColorConsoleAppender.h new file mode 100644 index 0000000..10a00f1 --- /dev/null +++ b/inst/include/plog/Appenders/ColorConsoleAppender.h @@ -0,0 +1,101 @@ +#pragma once +#include "ConsoleAppender.h" + +namespace plog +{ + template<class Formatter> + class ColorConsoleAppender : public ConsoleAppender<Formatter> + { + public: +#ifdef _WIN32 + ColorConsoleAppender() : m_isatty(!!::_isatty(::_fileno(stdout))), m_stdoutHandle(), m_originalAttr() + { + if (m_isatty) + { + m_stdoutHandle = ::GetStdHandle(STD_OUTPUT_HANDLE); + + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + ::GetConsoleScreenBufferInfo(m_stdoutHandle, &csbiInfo); + + m_originalAttr = csbiInfo.wAttributes; + } + } +#else + ColorConsoleAppender() : m_isatty(!!::isatty(::fileno(stdout))) {} +#endif + + virtual void write(const Record& record) + { + setColor(record.getSeverity()); + ConsoleAppender<Formatter>::write(record); + resetColor(); + } + + private: + void setColor(Severity severity) + { + if (m_isatty) + { + switch (severity) + { +#ifdef _WIN32 + case fatal: + ::SetConsoleTextAttribute(m_stdoutHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED); // white on red background + break; + + case error: + ::SetConsoleTextAttribute(m_stdoutHandle, FOREGROUND_RED | FOREGROUND_INTENSITY | (m_originalAttr & 0xf0)); // red + break; + + case warning: + ::SetConsoleTextAttribute(m_stdoutHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | (m_originalAttr & 0xf0)); // yellow + break; + + case debug: + case verbose: + ::SetConsoleTextAttribute(m_stdoutHandle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | (m_originalAttr & 0xf0)); // cyan + break; +#else + case fatal: + std::cout << "\x1B[97m\x1B[41m"; // white on red background + break; + + case error: + std::cout << "\x1B[91m"; // red + break; + + case warning: + std::cout << "\x1B[93m"; // yellow + break; + + case debug: + case verbose: + std::cout << "\x1B[96m"; // cyan + break; +#endif + default: + break; + } + } + } + + void resetColor() + { + if (m_isatty) + { +#ifdef _WIN32 + ::SetConsoleTextAttribute(m_stdoutHandle, m_originalAttr); +#else + std::cout << "\x1B[0m\x1B[0K"; +#endif + } + } + + private: + bool m_isatty; +#ifdef _WIN32 + HANDLE m_stdoutHandle; + WORD m_originalAttr; +#endif + }; +} diff --git a/inst/include/plog/Appenders/ConsoleAppender.h b/inst/include/plog/Appenders/ConsoleAppender.h new file mode 100644 index 0000000..51067f9 --- /dev/null +++ b/inst/include/plog/Appenders/ConsoleAppender.h @@ -0,0 +1,26 @@ +#pragma once +#include <iostream> + +namespace plog +{ + template<class Formatter> + class ConsoleAppender : public IAppender + { + public: + ConsoleAppender() + { +#ifdef _WIN32 + ::setlocale(LC_ALL, ""); +#endif + } + + virtual void write(const Record& record) + { +#ifdef _WIN32 + std::wcout << Formatter::format(record) << std::flush; +#else + std::cout << Formatter::format(record) << std::flush; +#endif + } + }; +} diff --git a/inst/include/plog/Appenders/IAppender.h b/inst/include/plog/Appenders/IAppender.h new file mode 100644 index 0000000..a0c4920 --- /dev/null +++ b/inst/include/plog/Appenders/IAppender.h @@ -0,0 +1,14 @@ +#pragma once + +namespace plog +{ + class IAppender + { + public: + virtual ~IAppender() + { + } + + virtual void write(const Record& record) = 0; + }; +} diff --git a/inst/include/plog/Formatters/FuncMessageFormatter.h b/inst/include/plog/Formatters/FuncMessageFormatter.h new file mode 100644 index 0000000..88d65f0 --- /dev/null +++ b/inst/include/plog/Formatters/FuncMessageFormatter.h @@ -0,0 +1,23 @@ +#pragma once +#include <plog/Util.h> + +namespace plog +{ + class FuncMessageFormatter + { + public: + static util::nstring header() + { + return util::nstring(); + } + + static util::nstring format(const Record& record) + { + util::nstringstream ss; + ss << record.getFunc().c_str() << "@" << record.getLine() << ": "; + ss << record.getMessage().c_str() << "\n"; + + return ss.str(); + } + }; +} diff --git a/inst/include/plog/Init.h b/inst/include/plog/Init.h new file mode 100644 index 0000000..6927ec9 --- /dev/null +++ b/inst/include/plog/Init.h @@ -0,0 +1,23 @@ +#pragma once +#include <plog/Logger.h> +#include <plog/Severity.h> +#include <plog/Appenders/IAppender.h> + +namespace plog +{ + ////////////////////////////////////////////////////////////////////////// + // Empty initializer / one appender + + template<int instance> + inline Logger<instance>& init(Severity maxSeverity = none, IAppender* appender = NULL) + { + static Logger<instance> logger; + logger.setMaxSeverity(maxSeverity); + return appender ? logger.addAppender(appender) : logger; + } + + inline Logger<0>& init(Severity maxSeverity = none, IAppender* appender = NULL) + { + return init<0>(maxSeverity, appender); + } +} diff --git a/inst/include/plog/Log.h b/inst/include/plog/Log.h new file mode 100644 index 0000000..a17e3ab --- /dev/null +++ b/inst/include/plog/Log.h @@ -0,0 +1,98 @@ +////////////////////////////////////////////////////////////////////////// +// Plog - portable and simple log for C++ +// Documentation and sources: https://github.com/SergiusTheBest/plog +// License: MPL 2.0, http://mozilla.org/MPL/2.0/ + +#pragma once +#include <plog/Record.h> +#include <plog/Logger.h> +#include <plog/Init.h> + +////////////////////////////////////////////////////////////////////////// +// Helper macros that get context info + +#ifdef _MSC_BUILD +# if _MSC_VER >= 1600 && !defined(__INTELLISENSE__) // >= Visual Studio 2010 and skip IntelliSense +# define PLOG_GET_THIS() __if_exists(this) { this } __if_not_exists(this) { 0 } +# else +# define PLOG_GET_THIS() 0 +# endif +# define PLOG_GET_FUNC() __FUNCTION__ +#else +# define PLOG_GET_THIS() 0 +# define PLOG_GET_FUNC() __PRETTY_FUNCTION__ +#endif + +////////////////////////////////////////////////////////////////////////// +// Log severity level checker + +#define IF_LOG_(instance, severity) if (plog::get<instance>() && plog::get<instance>()->checkSeverity(severity)) +#define IF_LOG(severity) IF_LOG_(0, severity) + +////////////////////////////////////////////////////////////////////////// +// Main logging macros + +#define LOG_(instance, severity) IF_LOG_(instance, severity) (*plog::get<instance>()) += plog::Record(severity, PLOG_GET_FUNC(), __LINE__, PLOG_GET_THIS()) +#define LOG(severity) LOG_(0, severity) + +#define LOG_VERBOSE LOG(plog::verbose) +#define LOG_DEBUG LOG(plog::debug) +#define LOG_INFO LOG(plog::info) +#define LOG_WARNING LOG(plog::warning) +#define LOG_ERROR LOG(plog::error) +#define LOG_FATAL LOG(plog::fatal) + +#define LOG_VERBOSE_(instance) LOG_(instance, plog::verbose) +#define LOG_DEBUG_(instance) LOG_(instance, plog::debug) +#define LOG_INFO_(instance) LOG_(instance, plog::info) +#define LOG_WARNING_(instance) LOG_(instance, plog::warning) +#define LOG_ERROR_(instance) LOG_(instance, plog::error) +#define LOG_FATAL_(instance) LOG_(instance, plog::fatal) + +#define LOGV LOG_VERBOSE +#define LOGD LOG_DEBUG +#define LOGI LOG_INFO +#define LOGW LOG_WARNING +#define LOGE LOG_ERROR +#define LOGF LOG_FATAL + +#define LOGV_(instance) LOG_VERBOSE_(instance) +#define LOGD_(instance) LOG_DEBUG_(instance) +#define LOGI_(instance) LOG_INFO_(instance) +#define LOGW_(instance) LOG_WARNING_(instance) +#define LOGE_(instance) LOG_ERROR_(instance) +#define LOGF_(instance) LOG_FATAL_(instance) + +////////////////////////////////////////////////////////////////////////// +// Conditional logging macros + +#define LOG_IF_(instance, severity, condition) if (condition) LOG_(instance, severity) +#define LOG_IF(severity, condition) LOG_IF_(0, severity, condition) + +#define LOG_VERBOSE_IF(condition) LOG_IF(plog::verbose, condition) +#define LOG_DEBUG_IF(condition) LOG_IF(plog::debug, condition) +#define LOG_INFO_IF(condition) LOG_IF(plog::info, condition) +#define LOG_WARNING_IF(condition) LOG_IF(plog::warning, condition) +#define LOG_ERROR_IF(condition) LOG_IF(plog::error, condition) +#define LOG_FATAL_IF(condition) LOG_IF(plog::fatal, condition) + +#define LOG_VERBOSE_IF_(instance, condition) LOG_IF_(instance, plog::verbose, condition) +#define LOG_DEBUG_IF_(instance, condition) LOG_IF_(instance, plog::debug, condition) +#define LOG_INFO_IF_(instance, condition) LOG_IF_(instance, plog::info, condition) +#define LOG_WARNING_IF_(instance, condition) LOG_IF_(instance, plog::warning, condition) +#define LOG_ERROR_IF_(instance, condition) LOG_IF_(instance, plog::error, condition) +#define LOG_FATAL_IF_(instance, condition) LOG_IF_(instance, plog::fatal, condition) + +#define LOGV_IF(condition) LOG_VERBOSE_IF(condition) +#define LOGD_IF(condition) LOG_DEBUG_IF(condition) +#define LOGI_IF(condition) LOG_INFO_IF(condition) +#define LOGW_IF(condition) LOG_WARNING_IF(condition) +#define LOGE_IF(condition) LOG_ERROR_IF(condition) +#define LOGF_IF(condition) LOG_FATAL_IF(condition) + +#define LOGV_IF_(instance, condition) LOG_VERBOSE_IF_(instance, condition) +#define LOGD_IF_(instance, condition) LOG_DEBUG_IF_(instance, condition) +#define LOGI_IF_(instance, condition) LOG_INFO_IF_(instance, condition) +#define LOGW_IF_(instance, condition) LOG_WARNING_IF_(instance, condition) +#define LOGE_IF_(instance, condition) LOG_ERROR_IF_(instance, condition) +#define LOGF_IF_(instance, condition) LOG_FATAL_IF_(instance, condition) diff --git a/inst/include/plog/Logger.h b/inst/include/plog/Logger.h new file mode 100644 index 0000000..f80dac5 --- /dev/null +++ b/inst/include/plog/Logger.h @@ -0,0 +1,69 @@ +#pragma once +#include <vector> +#include <plog/Appenders/IAppender.h> +#include <plog/Util.h> + +namespace plog +{ + template<int instance> + class Logger : public util::Singleton<Logger<instance> >, public IAppender + { + public: + Logger() : m_maxSeverity(none) + { + } + + Logger& addAppender(IAppender* appender) + { + assert(appender != this); + m_appenders.push_back(appender); + return *this; + } + + Severity getMaxSeverity() const + { + return m_maxSeverity; + } + + void setMaxSeverity(Severity severity) + { + m_maxSeverity = severity; + } + + bool checkSeverity(Severity severity) const + { + return severity <= m_maxSeverity; + } + + virtual void write(const Record& record) + { + if (checkSeverity(record.getSeverity())) + { + *this += record; + } + } + + void operator+=(const Record& record) + { + for (std::vector<IAppender*>::iterator it = m_appenders.begin(); it != m_appenders.end(); ++it) + { + (*it)->write(record); + } + } + + private: + Severity m_maxSeverity; + std::vector<IAppender*> m_appenders; + }; + + template<int instance> + inline Logger<instance>* get() + { + return Logger<instance>::getInstance(); + } + + inline Logger<0>* get() + { + return Logger<0>::getInstance(); + } +} diff --git a/inst/include/plog/Record.h b/inst/include/plog/Record.h new file mode 100644 index 0000000..41e5d95 --- /dev/null +++ b/inst/include/plog/Record.h @@ -0,0 +1,82 @@ +#pragma once +#include <sstream> +#include <plog/Util.h> +#include <plog/Severity.h> + +namespace plog +{ + class Record + { + public: + Record(Severity severity, const char* func, size_t line, const void* object) + : m_severity(severity), m_object(object), m_line(line), m_func(func) + { + util::ftime(&m_time); + } + + ////////////////////////////////////////////////////////////////////////// + // Stream output operators + + Record& operator<<(char data) + { + char str[] = { data, 0 }; + *this << str; + return *this; + } + + Record& operator<<(wchar_t data) + { + wchar_t str[] = { data, 0 }; + *this << str; + return *this; + } + + template<typename T> + Record& operator<<(const T& data) + { + m_message << data; + return *this; + } + + ////////////////////////////////////////////////////////////////////////// + // Getters + + const util::Time& getTime() const + { + return m_time; + } + + Severity getSeverity() const + { + return m_severity; + } + + const void* getObject() const + { + return m_object; + } + + size_t getLine() const + { + return m_line; + } + + const util::nstring getMessage() const + { + return m_message.str(); + } + + std::string getFunc() const + { + return util::processFuncName(m_func); + } + + private: + util::Time m_time; + const Severity m_severity; + const void* const m_object; + const size_t m_line; + util::nstringstream m_message; + const char* const m_func; + }; +} diff --git a/inst/include/plog/Severity.h b/inst/include/plog/Severity.h new file mode 100644 index 0000000..2e67ea2 --- /dev/null +++ b/inst/include/plog/Severity.h @@ -0,0 +1,54 @@ +#pragma once + +namespace plog +{ + enum Severity + { + none = 0, + fatal = 1, + error = 2, + warning = 3, + info = 4, + debug = 5, + verbose = 6 + }; + + inline const char* getSeverityName(Severity severity) + { + switch (severity) + { + case fatal: + return "FATAL"; + case error: + return "ERROR"; + case warning: + return "WARN"; + case info: + return "INFO"; + case debug: + return "DEBUG"; + case verbose: + return "VERB"; + default: + return "NONE"; + } + } + + inline Severity getSeverityCode(const std::string& name) + { + if (name == "FATAL") + return fatal; + if (name == "ERROR") + return error; + if (name == "WARN") + return warning; + if (name == "INFO") + return info; + if (name == "DEBUG") + return debug; + if (name == "VERB") + return verbose; + + return none; + } +} diff --git a/inst/include/plog/Util.h b/inst/include/plog/Util.h new file mode 100644 index 0000000..bef4a02 --- /dev/null +++ b/inst/include/plog/Util.h @@ -0,0 +1,120 @@ +#pragma once +#include <cassert> +#include <cstring> + +#ifdef _WIN32 +# include <time.h> +#else +# include <sys/time.h> +#endif + +#ifdef _WIN32 +# define _PLOG_NSTR(x) L##x +# define PLOG_NSTR(x) _PLOG_NSTR(x) +#else +# define PLOG_NSTR(x) x +#endif + +namespace plog +{ + namespace util + { + typedef std::string nstring; + typedef std::stringstream nstringstream; + typedef char nchar; + + inline void localtime_s(struct tm* t, const time_t* time) + { +#ifdef _WIN32 + ::localtime_s(t, time); +#else + ::localtime_r(time, t); +#endif + } + +#ifdef _WIN32 + typedef timeb Time; + + inline void ftime(Time* t) + { + ::ftime(t); + } +#else + struct Time + { + time_t time; + unsigned short millitm; + }; + + inline void ftime(Time* t) + { + timeval tv; + ::gettimeofday(&tv, NULL); + + t->time = tv.tv_sec; + t->millitm = static_cast<unsigned short>(tv.tv_usec / 1000); + } +#endif + + inline std::string processFuncName(const char* func) + { +#if (defined(_WIN32) && !defined(__MINGW32__)) || defined(__OBJC__) + return std::string(func); +#else + const char* funcBegin = func; + const char* funcEnd = ::strchr(funcBegin, '('); + + for (const char* i = funcEnd - 1; i >= funcBegin; --i) + { + if (*i == ' ') + { + funcBegin = i + 1; + break; + } + } + + return std::string(funcBegin, funcEnd); +#endif + } + + class NonCopyable + { + protected: + NonCopyable() + { + } + + private: + NonCopyable(const NonCopyable&); + NonCopyable& operator=(const NonCopyable&); + }; + + template<class T> + class Singleton : NonCopyable + { + public: + Singleton() + { + assert(!m_instance); + m_instance = static_cast<T*>(this); + } + + ~Singleton() + { + assert(m_instance); + m_instance = 0; + } + + static T* getInstance() + { + return m_instance; + } + + private: + static T* m_instance; + }; + + template<class T> + T* Singleton<T>::m_instance = NULL; + } +} diff --git a/inst/include/plogr.h b/inst/include/plogr.h new file mode 100644 index 0000000..a4f5489 --- /dev/null +++ b/inst/include/plogr.h @@ -0,0 +1,39 @@ +#ifndef plogr_plogr_H +#define plogr_plogr_H + +#include "plog/Log.h" +#include "plog/Formatters/FuncMessageFormatter.h" + +#include <R.h> + +namespace plog { + +template<class Formatter> +class RAppender : public IAppender +{ +public: + virtual void write(const Record& record) + { + util::nstring str = Formatter::format(record); // Use the formatter to get a string from a record. + REprintf("%s", str.c_str()); + } +}; + +inline void init_r(Severity maxSeverity = none) { + static bool initialized = false; + static RAppender<FuncMessageFormatter> appender; + if (!initialized) { + init(maxSeverity, &appender); + initialized = true; + } else { + init(maxSeverity); + } +} + +inline void init_r(const std::string& maxSeverity = "NONE") { + init_r(getSeverityCode(maxSeverity)); +} + +} + +#endif // #ifndef plogr_plogr_H diff --git a/man/plogr-package.Rd b/man/plogr-package.Rd new file mode 100644 index 0000000..dcb6b06 --- /dev/null +++ b/man/plogr-package.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plogr-package.R +\docType{package} +\name{plogr-package} +\alias{plogr} +\alias{plogr-package} +\title{The 'plog' C++ Logging Library} +\description{ +A simple header-only logging library for C++. +Add 'LinkingTo: plogr' to 'DESCRIPTION', and '#include <plogr.h>' in your C++ modules to use it. +} +\examples{ +plogr_demo <- Rcpp::cppFunction(depends = "plogr", ' +// C++ code begin +#include <plogr.h> + +RObject plogr_demo() { + plog::init_r(plog::info); + LOG_INFO << "shown"; + LOG_DEBUG << "not shown"; + plog::init_r("DEBUG"); + LOG_DEBUG << "shown now"; + return R_NilValue; +} + +#include <Rcpp.h> // not necessary to use plogr +// C++ code end +' +) + +plogr_demo() +} + -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-plogr.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
