LibreOffice
LibreOffice 7.1 SDK C/C++ API Reference
log.hxx
Go to the documentation of this file.
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 
28 
29 enum sal_detail_LogAction
30 {
31  SAL_DETAIL_LOG_ACTION_IGNORE,
32  SAL_DETAIL_LOG_ACTION_LOG,
33  SAL_DETAIL_LOG_ACTION_FATAL
34 };
35 
36 extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log(
37  sal_detail_LogLevel level, char const * area, char const * where,
38  char const * message, sal_uInt32 backtraceDepth);
39 
40 // the return value is actually "enum sal_detail_LogAction", but due to ABI
41 // compatibility, it's left as the original "sal_Bool" / "unsigned char".
42 extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report(
43  sal_detail_LogLevel level, char const * area);
44 
45 namespace sal { namespace detail {
46 
47 inline void log(
48  sal_detail_LogLevel level, char const * area, char const * where,
49  std::ostringstream const & stream, sal_uInt32 backtraceDepth)
50 {
51  // An alternative would be to have sal_detail_log take a std::ostringstream
52  // pointer (via a C void pointer); the advantage would be smaller client
53  // code (the ".str().c_str()" part would move into the implementation of
54  // sal_detail_log) and potential for proper support of embedded null
55  // characters within the message, but the disadvantage would be dependence
56  // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
57  // to this inline function so that it is potentially only emitted once per
58  // dynamic library:
59  sal_detail_log(level, area, where, stream.str().c_str(), backtraceDepth);
60 }
61 
62 // Special handling of the common case where the message consists of just a
63 // string literal, to produce smaller call-site code:
64 
65 struct StreamStart {};
66 
67 struct StreamString {
68  StreamString(char const * s): string(s) {}
69 
70  char const * string;
71 
72  typedef char Result;
73 };
74 
75 struct StreamIgnore {
76  typedef struct { char a[2]; } Result;
77 };
78 
79 inline StreamString operator <<(
80  SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
81 {
82  return StreamString(s);
83 }
84 
85 template< typename T > inline StreamIgnore operator <<(
86  SAL_UNUSED_PARAMETER StreamStart const &, SAL_UNUSED_PARAMETER T const &)
87 {
88  std::abort();
89 #if defined _MSC_VER && _MSC_VER < 1700
90  return StreamIgnore();
91 #endif
92 }
93 
94 template< typename T > inline StreamIgnore operator <<(
95  SAL_UNUSED_PARAMETER StreamString const &, SAL_UNUSED_PARAMETER T const &)
96 {
97  std::abort();
98 #if defined _MSC_VER && _MSC_VER < 1700
99  return StreamIgnore();
100 #endif
101 }
102 
103 template< typename T > inline StreamIgnore operator <<(
104  SAL_UNUSED_PARAMETER StreamIgnore const &, SAL_UNUSED_PARAMETER T const &)
105 {
106  std::abort();
107 #if defined _MSC_VER && _MSC_VER < 1700
108  return StreamIgnore();
109 #endif
110 }
111 
112 template< typename T > typename T::Result getResult(T const &);
113 
114 inline char const * unwrapStream(StreamString const & s) { return s.string; }
115 
116 inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
117  std::abort();
118 #if defined _MSC_VER && _MSC_VER < 1700
119  return 0;
120 #endif
121 }
122 
123 } }
124 
125 // to prevent using a local variable, which can eventually shadow,
126 // resulting in compiler warnings (or even errors with -Werror)
127 #define SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream) \
128  if (sizeof ::sal::detail::getResult( \
129  ::sal::detail::StreamStart() << stream) == 1) \
130  { \
131  ::sal_detail_log( \
132  (level), (area), (where), \
133  ::sal::detail::unwrapStream( \
134  ::sal::detail::StreamStart() << stream), \
135  0); \
136  } else { \
137  ::std::ostringstream sal_detail_stream; \
138  sal_detail_stream << stream; \
139  ::sal::detail::log( \
140  (level), (area), (where), sal_detail_stream, 0); \
141  }
142 
143 #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
144  do { \
145  if (condition) \
146  { \
147  switch (sal_detail_log_report(level, area)) \
148  { \
149  case SAL_DETAIL_LOG_ACTION_IGNORE: break; \
150  case SAL_DETAIL_LOG_ACTION_LOG: \
151  SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
152  break; \
153  case SAL_DETAIL_LOG_ACTION_FATAL: \
154  SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
155  std::abort(); \
156  break; \
157  } \
158  } \
159  } while (false)
160 
162 
173 #define SAL_WHERE SAL_DETAIL_WHERE
174 
189 #if defined _LIBCPP_VERSION \
190  || (defined _GLIBCXX_RELEASE \
191  && (_GLIBCXX_RELEASE >= 12 || (_GLIBCXX_RELEASE == 11 && __GLIBCXX__ > 20210428))) \
192  || (defined _MSC_VER && _MSC_VER >= 1915)
193 #define SAL_STREAM(stream) \
194  (::std::ostringstream() << stream).str()
195 #else
196 #define SAL_STREAM(stream) \
197  (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
198 #endif
199 
337 #define SAL_INFO(area, stream) \
338  SAL_DETAIL_LOG_STREAM( \
339  SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
340  SAL_WHERE, stream)
341 
347 #define SAL_INFO_IF(condition, area, stream) \
348  SAL_DETAIL_LOG_STREAM( \
349  SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
350  ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
351 
357 #define SAL_WARN(area, stream) \
358  SAL_DETAIL_LOG_STREAM( \
359  SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
360  SAL_WHERE, stream)
361 
367 #define SAL_WARN_IF(condition, area, stream) \
368  SAL_DETAIL_LOG_STREAM( \
369  SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
370  ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
371 
378 #define SAL_DEBUG(stream) \
379  SAL_DETAIL_LOG_STREAM( \
380  SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
381 
396 #define SAL_DEBUG_BACKTRACE(stream, backtraceDepth) \
397  do { \
398  if (sizeof ::sal::detail::getResult( \
399  ::sal::detail::StreamStart() << stream) == 1) \
400  { \
401  ::sal_detail_log( \
402  ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, \
403  ::sal::detail::unwrapStream( \
404  ::sal::detail::StreamStart() << stream), \
405  backtraceDepth); \
406  } else { \
407  ::std::ostringstream sal_detail_stream; \
408  sal_detail_stream << stream; \
409  ::sal::detail::log( \
410  ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, sal_detail_stream, \
411  backtraceDepth); \
412  } \
413  } while (false)
414 
415 
416 
417 #endif
418 
419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define SAL_DLLPUBLIC
Definition: saldllapi.h:30
#define SAL_UNUSED_PARAMETER
Annotate unused but required C++ function parameters.
Definition: types.h:539
Definition: types.h:394
std::basic_ostream< charT, traits > & operator<<(std::basic_ostream< charT, traits > &stream, OString const &rString)
Support for rtl::OString in std::ostream (and thus in CPPUNIT_ASSERT or SAL_INFO macros,...
Definition: string.hxx:2095