LCOV - code coverage report
Current view: top level - include/sal - log.hxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 4 0.0 %
Date: 2014-04-14 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #ifndef INCLUDED_SAL_LOG_HXX
      11             : #define INCLUDED_SAL_LOG_HXX
      12             : 
      13             : #include <sal/config.h>
      14             : 
      15             : #include <cstdlib>
      16             : #include <sstream>
      17             : #include <string>
      18             : 
      19             : #include <sal/detail/log.h>
      20             : #include <sal/saldllapi.h>
      21             : #include <sal/types.h>
      22             : 
      23             : // Avoid the use of other sal code in this header as much as possible, so that
      24             : // this code can be called from other sal code without causing endless
      25             : // recursion.
      26             : 
      27             : /// @cond INTERNAL
      28             : 
      29             : extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log(
      30             :     enum sal_detail_LogLevel level, char const * area, char const * where,
      31             :     char const * message);
      32             : 
      33             : namespace sal { namespace detail {
      34             : 
      35             : inline void SAL_CALL log(
      36             :     sal_detail_LogLevel level, char const * area, char const * where,
      37             :     std::ostringstream const & stream)
      38             : {
      39             :     // An alternative would be to have sal_detail_log take a std::ostringstream
      40             :     // pointer (via a C void pointer); the advantage would be smaller client
      41             :     // code (the ".str().c_str()" part would move into the implementation of
      42             :     // sal_detail_log) and potential for proper support of embedded null
      43             :     // characters within the message, but the disadvantage would be dependence
      44             :     // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
      45             :     // to this inline function so that it is potentially only emitted once per
      46             :     // dynamic library:
      47             :     sal_detail_log(level, area, where, stream.str().c_str());
      48             : }
      49             : 
      50             : // Special handling of the common case where the message consists of just a
      51             : // string literal, to produce smaller call-site code:
      52             : 
      53             : struct StreamStart {};
      54             : 
      55             : struct StreamString {
      56           0 :     StreamString(char const * s): string(s) {}
      57             : 
      58             :     char const * string;
      59             : 
      60             :     typedef char Result;
      61             : };
      62             : 
      63             : struct StreamIgnore {
      64             :     typedef struct { char a[2]; } Result;
      65             : };
      66             : 
      67           0 : inline StreamString operator <<(
      68             :     SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
      69             : {
      70           0 :     return StreamString(s);
      71             : }
      72             : 
      73             : template< typename T > inline StreamIgnore operator <<(
      74             :     SAL_UNUSED_PARAMETER StreamStart const &, SAL_UNUSED_PARAMETER T const &)
      75             : {
      76             :     std::abort();
      77             : #if defined _MSC_VER && _MSC_VER < 1700
      78             :     return StreamIgnore();
      79             : #endif
      80             : }
      81             : 
      82             : template< typename T > inline StreamIgnore operator <<(
      83             :     SAL_UNUSED_PARAMETER StreamString const &, SAL_UNUSED_PARAMETER T const &)
      84             : {
      85             :     std::abort();
      86             : #if defined _MSC_VER && _MSC_VER < 1700
      87             :     return StreamIgnore();
      88             : #endif
      89             : }
      90             : 
      91             : template< typename T > inline StreamIgnore operator <<(
      92             :     SAL_UNUSED_PARAMETER StreamIgnore const &, SAL_UNUSED_PARAMETER T const &)
      93             : {
      94             :     std::abort();
      95             : #if defined _MSC_VER && _MSC_VER < 1700
      96             :     return StreamIgnore();
      97             : #endif
      98             : }
      99             : 
     100             : template< typename T > typename T::Result getResult(T const &);
     101             : 
     102           0 : inline char const * unwrapStream(StreamString const & s) { return s.string; }
     103             : 
     104             : inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
     105             :     std::abort();
     106             : #if defined _MSC_VER && _MSC_VER < 1700
     107             :     return 0;
     108             : #endif
     109             : }
     110             : 
     111             : } }
     112             : 
     113             : #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
     114             :     do { \
     115             :         if (condition) { \
     116             :             if (sizeof ::sal::detail::getResult( \
     117             :                     ::sal::detail::StreamStart() << stream) == 1) \
     118             :             { \
     119             :                 ::sal_detail_log( \
     120             :                     (level), (area), (where), \
     121             :                     ::sal::detail::unwrapStream( \
     122             :                         ::sal::detail::StreamStart() << stream)); \
     123             :             } else { \
     124             :                 ::std::ostringstream sal_detail_stream; \
     125             :                 sal_detail_stream << stream; \
     126             :                 ::sal::detail::log( \
     127             :                     (level), (area), (where), sal_detail_stream); \
     128             :             } \
     129             :         } \
     130             :     } while (false)
     131             : 
     132             : /// @endcond
     133             : 
     134             : /** A simple macro to create a "file and line number" string.
     135             : 
     136             :     Potentially not only useful within the log framework (where it is used
     137             :     automatically), but also when creating exception messages.
     138             : 
     139             :     @attention For now, this functionality should only be used internally within
     140             :     LibreOffice. It may change again in a future version.
     141             : 
     142             :     @since LibreOffice 3.5
     143             : */
     144             : #define SAL_WHERE SAL_DETAIL_WHERE
     145             : 
     146             : /** A facility for generating temporary string messages by piping items into a
     147             :     C++ std::ostringstream.
     148             : 
     149             :     This can be useful for example in a call to SAL_INFO when depending on some
     150             :     boolean condition data of incompatible types shall be streamed into the
     151             :     message, as in:
     152             : 
     153             :       SAL_INFO("foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj)));
     154             : 
     155             :     @attention For now, this functionality should only be used internally within
     156             :     LibreOffice. It may change again in a future version.
     157             : 
     158             :     @since LibreOffice 3.5
     159             : */
     160             : #ifdef _LIBCPP_VERSION
     161             : #define SAL_STREAM(stream) \
     162             :     (::std::ostringstream() << stream).str()
     163             : #else
     164             : #define SAL_STREAM(stream) \
     165             :     (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
     166             : #endif
     167             : 
     168             : /**
     169             :     @page sal_log Basic logging functionality.
     170             : 
     171             :     @short Macros for logging.
     172             : 
     173             :     SAL_INFO(char const * area, expr),
     174             :     SAL_INFO_IF(bool condition, char const * area, expr),
     175             :     SAL_WARN(char const * area, expr),
     176             :     SAL_WARN_IF(bool condition, char const * area, expr), and SAL_DEBUG(expr)
     177             :     produce an info, warning, or debug log entry with a message produced by
     178             :     piping items into a C++ std::ostringstream.  The given expr must be so that
     179             :     the full expression "stream << expr" is valid, where stream is a variable of
     180             :     type std::ostringstream.
     181             : 
     182             :       SAL_INFO("foo", "string " << s << " of length " << n)
     183             : 
     184             :     would be an example of such a call.
     185             : 
     186             :     The composed message should be in UTF-8 and it should contain no vertical
     187             :     formatting characters and no null characters
     188             : 
     189             :     For the _IF variants, log output is only generated if the given condition is
     190             :     true (in addition to the other conditions that have to be met).
     191             : 
     192             :     The SAL_DEBUG macro is for temporary debug statements that are used while
     193             :     working on code.  It is never meant to remain in the code.  It will always
     194             :     simply output the given expression in debug builds.
     195             : 
     196             :     For all the other macros, the given area argument must be non-null and must
     197             :     match the regular expression
     198             : 
     199             :     @verbatim
     200             :       <area> ::= <segment>("."<segment>)*
     201             :     @endverbatim
     202             : 
     203             :     with
     204             : 
     205             :     @verbatim
     206             :       <segment> ::= [0-9a-z]+
     207             :     @endverbatim
     208             : 
     209             :     For a list of areas used see @ref sal_log_areas "SAL debug areas". Whenever
     210             :     you use a new log area, add it to the file include/sal/log-areas.dox .
     211             : 
     212             :     Whether these macros generate any log output is controlled in a two-stage
     213             :     process.
     214             : 
     215             :     First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN,
     216             :     respectively, control whether the INFO and WARN macros, respectively,
     217             :     expand to actual code (in case the macro is defined, to any value) or to
     218             :     no-ops (in case the macro is not defined).
     219             : 
     220             :     Second, at runtime the environment variable SAL_LOG further limits which
     221             :     macro calls actually generate log output.  The environment variable SAL_LOG
     222             :     must either be unset or must match the regular expression
     223             : 
     224             :     @verbatim
     225             :       <env> ::= <switch>*
     226             :     @endverbatim
     227             : 
     228             :     with
     229             : 
     230             :     @verbatim
     231             :       <switch> ::= <sense><level>("."<area>)?
     232             :       <sense> ::= "+"|"-"
     233             :       <level> ::= "INFO"|"WARN"
     234             :     @endverbatim
     235             : 
     236             :     If the environment variable is unset, "+WARN" is used instead (which results
     237             :     in all warnings being output but no infos).  If the given value does not
     238             :     match the regular expression, "+INFO+WARN" is used instead (which in turn
     239             :     results in everything being output).
     240             : 
     241             :     A given macro call's level (INFO or WARN) and area is matched against the
     242             :     given switches as follows:  Only those switches for which the level matches
     243             :     the given level and for which the area is a prefix (including both empty and
     244             :     full prefixes) of the given area are considered.  Log output is generated if
     245             :     and only if among the longest such switches (if any), there is at least one
     246             :     that has a sense of "+".  (That is, if both +INFO.foo and -INFO.foo are
     247             :     present, +INFO.foo wins.)
     248             : 
     249             :     For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like
     250             :     SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or
     251             :     SAL_INFO("other", ...) generate output, while calls like
     252             :     SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
     253             : 
     254             :     The generated log output consists of the given level ("info" or "warn"), the
     255             :     given area, the process ID, the thread ID, the source file, and the source
     256             :     line number, each followed by a colon, followed by a space, the given
     257             :     message, and a newline.  The precise format of the log output is subject to
     258             :     change.  The log output is printed to stderr without further text encoding
     259             :     conversion.
     260             : 
     261             :     @see @ref sal_log_areas
     262             : 
     263             :     @attention For now, this functionality should only be used internally within
     264             :     LibreOffice. It may change again in a future version.
     265             : 
     266             :     @since LibreOffice 3.5
     267             : */
     268             : 
     269             : /**
     270             :   Produce log entry from stream in the given log area.
     271             : 
     272             :   See @ref sal_log "basic logging functionality" for details.
     273             : */
     274             : #define SAL_INFO(area, stream) \
     275             :     SAL_DETAIL_LOG_STREAM( \
     276             :         SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
     277             :         SAL_WHERE, stream)
     278             : 
     279             : /**
     280             :   Produce log entry from stream in the given log area if condition is true.
     281             : 
     282             :   See @ref sal_log "basic logging functionality" for details.
     283             : */
     284             : #define SAL_INFO_IF(condition, area, stream)  \
     285             :     SAL_DETAIL_LOG_STREAM( \
     286             :         SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
     287             :         ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
     288             : 
     289             : /**
     290             :   Produce warning entry from stream in the given log area.
     291             : 
     292             :   See @ref sal_log "basic logging functionality" for details.
     293             : */
     294             : #define SAL_WARN(area, stream) \
     295             :     SAL_DETAIL_LOG_STREAM( \
     296             :         SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
     297             :         SAL_WHERE, stream)
     298             : 
     299             : /**
     300             :   Produce warning entry from stream in the given log area if condition is true.
     301             : 
     302             :   See @ref sal_log "basic logging functionality" for details.
     303             : */
     304             : #define SAL_WARN_IF(condition, area, stream)   \
     305             :     SAL_DETAIL_LOG_STREAM( \
     306             :         SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
     307             :         ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
     308             : 
     309             : /**
     310             :   Produce temporary debugging output from stream.  This macro is meant to be
     311             :   used only while working on code and should never exist in production code.
     312             : 
     313             :   See @ref sal_log "basic logging functionality" for details.
     314             : */
     315             : #define SAL_DEBUG(stream) \
     316             :     SAL_DETAIL_LOG_STREAM( \
     317             :         SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, 0, 0, stream)
     318             : 
     319             : #endif
     320             : 
     321             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10