diff options
author | David Tardon <dtardon@redhat.com> | 2013-04-19 18:54:16 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2013-04-24 05:17:10 +0000 |
commit | 6c7659b584ea7ed3652ca4eb9a2297f36310c365 (patch) | |
tree | adf631e2d3db309b0696babd9d026bce0996c215 /include/sal/log.hxx | |
parent | Rename image files to match with command name (diff) | |
download | core-6c7659b584ea7ed3652ca4eb9a2297f36310c365.tar.gz core-6c7659b584ea7ed3652ca4eb9a2297f36310c365.zip |
move URE headers to include/
Change-Id: Ib48a12e902f2311c295b2007f08f44dee28f431d
Reviewed-on: https://gerrit.libreoffice.org/3499
Reviewed-by: David Tardon <dtardon@redhat.com>
Tested-by: David Tardon <dtardon@redhat.com>
Diffstat (limited to 'include/sal/log.hxx')
-rw-r--r-- | include/sal/log.hxx | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/include/sal/log.hxx b/include/sal/log.hxx new file mode 100644 index 000000000000..6eae1b59d43c --- /dev/null +++ b/include/sal/log.hxx @@ -0,0 +1,317 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_SAL_LOG_HXX +#define INCLUDED_SAL_LOG_HXX + +#include "sal/config.h" + +#include <cstdlib> +#include <sstream> +#include <string> + +#include "sal/detail/log.h" +#include "sal/saldllapi.h" +#include "sal/types.h" + +// Avoid the use of other sal code in this header as much as possible, so that +// this code can be called from other sal code without causing endless +// recursion. + +/// @cond INTERNAL + +extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log( + enum sal_detail_LogLevel level, char const * area, char const * where, + char const * message); + +namespace sal { namespace detail { + +inline void SAL_CALL log( + sal_detail_LogLevel level, char const * area, char const * where, + std::ostringstream const & stream) +{ + // An alternative would be to have sal_detail_log take a std::ostringstream + // pointer (via a C void pointer); the advantage would be smaller client + // code (the ".str().c_str()" part would move into the implementation of + // sal_detail_log) and potential for proper support of embedded null + // characters within the message, but the disadvantage would be dependence + // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved + // to this inline function so that it is potentially only emitted once per + // dynamic library: + sal_detail_log(level, area, where, stream.str().c_str()); +} + +// Special handling of the common case where the message consists of just a +// string literal, to produce smaller call-site code: + +struct StreamStart {}; + +struct StreamString { + StreamString(char const * s): string(s) {} + + char const * string; + + typedef char Result; +}; + +struct StreamIgnore { + typedef struct { char a[2]; } Result; +}; + +inline StreamString operator <<( + SAL_UNUSED_PARAMETER StreamStart const &, char const * s) +{ + return StreamString(s); +} + +template< typename T > inline StreamIgnore operator <<( + SAL_UNUSED_PARAMETER StreamStart const &, SAL_UNUSED_PARAMETER T const &) +{ + std::abort(); +#if defined _MSC_VER && _MSC_VER < 1700 + return StreamIgnore(); +#endif +} + +template< typename T > inline StreamIgnore operator <<( + SAL_UNUSED_PARAMETER StreamString const &, SAL_UNUSED_PARAMETER T const &) +{ + std::abort(); +#if defined _MSC_VER && _MSC_VER < 1700 + return StreamIgnore(); +#endif +} + +template< typename T > inline StreamIgnore operator <<( + SAL_UNUSED_PARAMETER StreamIgnore const &, SAL_UNUSED_PARAMETER T const &) +{ + std::abort(); +#if defined _MSC_VER && _MSC_VER < 1700 + return StreamIgnore(); +#endif +} + +template< typename T > typename T::Result getResult(T const &); + +inline char const * unwrapStream(StreamString const & s) { return s.string; } + +inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { + std::abort(); +#if defined _MSC_VER && _MSC_VER < 1700 + return 0; +#endif +} + +} } + +#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \ + do { \ + if (condition) { \ + if (sizeof ::sal::detail::getResult( \ + ::sal::detail::StreamStart() << stream) == 1) \ + { \ + ::sal_detail_log( \ + (level), (area), (where), \ + ::sal::detail::unwrapStream( \ + ::sal::detail::StreamStart() << stream)); \ + } else { \ + ::std::ostringstream sal_detail_stream; \ + sal_detail_stream << stream; \ + ::sal::detail::log( \ + (level), (area), (where), sal_detail_stream); \ + } \ + } \ + } while (false) + +/// @endcond + +/** A simple macro to create a "file and line number" string. + + Potentially not only useful within the log framework (where it is used + automatically), but also when creating exception messages. + + @attention For now, this functionality should only be used internally within + LibreOffice. It may change again in a future version. + + @since LibreOffice 3.5 +*/ +#define SAL_WHERE SAL_DETAIL_WHERE + +/** A facility for generating temporary string messages by piping items into a + C++ std::ostringstream. + + This can be useful for example in a call to SAL_INFO when depending on some + boolean condition data of incompatible types shall be streamed into the + message, as in: + + SAL_INFO("foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj))); + + @attention For now, this functionality should only be used internally within + LibreOffice. It may change again in a future version. + + @since LibreOffice 3.5 +*/ +#define SAL_STREAM(stream) \ + (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream). \ + str()) + +/** + @page sal_log Basic logging functionality. + + @short Macros for logging. + + SAL_INFO(char const * area, expr), + SAL_INFO_IF(bool condition, char const * area, expr), + SAL_WARN(char const * area, expr), + SAL_WARN_IF(bool condition, char const * area, expr), and SAL_DEBUG(expr) + produce an info, warning, or debug log entry with a message produced by + piping items into a C++ std::ostringstream. The given expr must be so that + the full expression "stream << expr" is valid, where stream is a variable of + type std::ostringstream. + + SAL_INFO("foo", "string " << s << " of length " << n) + + would be an example of such a call. + + The composed message should be in UTF-8 and it should contain no vertical + formatting characters and no null characters + + For the _IF variants, log output is only generated if the given condition is + true (in addition to the other conditions that have to be met). + + The SAL_DEBUG macro is for temporary debug statements that are used while + working on code. It is never meant to remain in the code. It will always + simply output the given expression in debug builds. + + For all the other macros, the given area argument must be non-null and must + match the regular expression + + @verbatim + <area> ::= <segment>("."<segment>)* + @endverbatim + + with + + @verbatim + <segment> ::= [0-9a-z]+ + @endverbatim + + For a list of areas used see @ref sal_log_areas "SAL debug areas". Whenever + you use a new log area, add it to the file sal/inc/sal/log-areas.dox . + + Whether these macros generate any log output is controlled in a two-stage + process. + + First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN, + respectively, control whether the INFO and WARN macros, respectively, + expand to actual code (in case the macro is defined, to any value) or to + no-ops (in case the macro is not defined). + + Second, at runtime the environment variable SAL_LOG further limits which + macro calls actually generate log output. The environment variable SAL_LOG + must either be unset or must match the regular expression + + @verbatim + <env> ::= <switch>* + @endverbatim + + with + + @verbatim + <switch> ::= <sense><level>("."<area>)? + <sense> ::= "+"|"-" + <level> ::= "INFO"|"WARN" + @endverbatim + + If the environment variable is unset, "+WARN" is used instead (which results + in all warnings being output but no infos). If the given value does not + match the regular expression, "+INFO+WARN" is used instead (which in turn + results in everything being output). + + A given macro call's level (INFO or WARN) and area is matched against the + given switches as follows: Only those switches for which the level matches + the given level and for which the area is a prefix (including both empty and + full prefixes) of the given area are considered. Log output is generated if + and only if among the longest such switches (if any), there is at least one + that has a sense of "+". (That is, if both +INFO.foo and -INFO.foo are + present, +INFO.foo wins.) + + For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like + SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or + SAL_INFO("other", ...) generate output, while calls like + SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not. + + The generated log output consists of the given level ("info" or "warn"), the + given area, the process ID, the thread ID, the source file, and the source + line number, each followed by a colon, followed by a space, the given + message, and a newline. The precise format of the log output is subject to + change. The log output is printed to stderr without further text encoding + conversion. + + @see @ref sal_log_areas + + @attention For now, this functionality should only be used internally within + LibreOffice. It may change again in a future version. + + @since LibreOffice 3.5 +*/ + +/** + Produce log entry from stream in the given log area. + + See @ref sal_log "basic logging functionality" for details. +*/ +#define SAL_INFO(area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \ + SAL_WHERE, stream) + +/** + Produce log entry from stream in the given log area if condition is true. + + See @ref sal_log "basic logging functionality" for details. +*/ +#define SAL_INFO_IF(condition, area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + SAL_DETAIL_ENABLE_LOG_INFO && (condition), \ + ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream) + +/** + Produce warning entry from stream in the given log area. + + See @ref sal_log "basic logging functionality" for details. +*/ +#define SAL_WARN(area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \ + SAL_WHERE, stream) + +/** + Produce warning entry from stream in the given log area if condition is true. + + See @ref sal_log "basic logging functionality" for details. +*/ +#define SAL_WARN_IF(condition, area, stream) \ + SAL_DETAIL_LOG_STREAM( \ + SAL_DETAIL_ENABLE_LOG_WARN && (condition), \ + ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream) + +/** + Produce temporary debugging output from stream. This macro is meant to be + used only while working on code and should never exist in production code. + + See @ref sal_log "basic logging functionality" for details. +*/ +#define SAL_DEBUG(stream) \ + SAL_DETAIL_LOG_STREAM( \ + SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, 0, 0, stream) + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |