LibreOffice
LibreOffice 24.2 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 /*
11  * This file is part of LibreOffice published API.
12  */
13 
14 #ifndef INCLUDED_SAL_LOG_HXX
15 #define INCLUDED_SAL_LOG_HXX
16 
17 #include "sal/config.h"
18 
19 #include <cstdlib>
20 #include <sstream>
21 #include <string>
22 
23 #include "sal/detail/log.h"
24 #include "sal/saldllapi.h"
25 #include "sal/types.h"
26 
27 // Avoid the use of other sal code in this header as much as possible, so that
28 // this code can be called from other sal code without causing endless
29 // recursion.
30 
32 
33 enum sal_detail_LogAction
34 {
35  SAL_DETAIL_LOG_ACTION_IGNORE,
36  SAL_DETAIL_LOG_ACTION_LOG,
37  SAL_DETAIL_LOG_ACTION_FATAL
38 };
39 
40 extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log(
41  sal_detail_LogLevel level, char const * area, char const * where,
42  char const * message, sal_uInt32 backtraceDepth);
43 
44 extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_set_log_selector(char const *logSelector);
45 
46 // the return value is actually "enum sal_detail_LogAction", but due to ABI
47 // compatibility, it's left as the original "sal_Bool" / "unsigned char".
48 extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report(
49  sal_detail_LogLevel level, char const * area);
50 
51 namespace sal { namespace detail {
52 
53 inline void log(
54  sal_detail_LogLevel level, char const * area, char const * where,
55  std::ostringstream const & stream, sal_uInt32 backtraceDepth)
56 {
57  // An alternative would be to have sal_detail_log take a std::ostringstream
58  // pointer (via a C void pointer); the advantage would be smaller client
59  // code (the ".str().c_str()" part would move into the implementation of
60  // sal_detail_log) and potential for proper support of embedded null
61  // characters within the message, but the disadvantage would be dependence
62  // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
63  // to this inline function so that it is potentially only emitted once per
64  // dynamic library:
65  sal_detail_log(level, area, where, stream.str().c_str(), backtraceDepth);
66 }
67 
68 // Special handling of the common case where the message consists of just a
69 // string literal, to produce smaller call-site code:
70 
71 struct StreamStart {};
72 
73 struct StreamString {
74  StreamString(char const * s): string(s) {}
75 
76  char const * string;
77 
78  typedef char Result;
79 };
80 
81 struct StreamIgnore {
82  typedef struct { char a[2]; } Result;
83 };
84 
85 inline StreamString operator <<(
86  SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
87 {
88  return StreamString(s);
89 }
90 
91 template< typename T > inline StreamIgnore operator <<(
92  SAL_UNUSED_PARAMETER StreamStart 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 > inline StreamIgnore operator <<(
101  SAL_UNUSED_PARAMETER StreamString const &, SAL_UNUSED_PARAMETER T const &)
102 {
103  std::abort();
104 #if defined _MSC_VER && _MSC_VER < 1700
105  return StreamIgnore();
106 #endif
107 }
108 
109 template< typename T > inline StreamIgnore operator <<(
110  SAL_UNUSED_PARAMETER StreamIgnore const &, SAL_UNUSED_PARAMETER T const &)
111 {
112  std::abort();
113 #if defined _MSC_VER && _MSC_VER < 1700
114  return StreamIgnore();
115 #endif
116 }
117 
118 template< typename T > typename T::Result getResult(T const &);
119 
120 inline char const * unwrapStream(StreamString const & s) { return s.string; }
121 
122 inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
123  std::abort();
124 #if defined _MSC_VER && _MSC_VER < 1700
125  return 0;
126 #endif
127 }
128 
129 } }
130 
131 // to prevent using a local variable, which can eventually shadow,
132 // resulting in compiler warnings (or even errors with -Werror)
133 #define SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream) \
134  if (sizeof ::sal::detail::getResult( \
135  ::sal::detail::StreamStart() << stream) == 1) \
136  { \
137  ::sal_detail_log( \
138  (level), (area), (where), \
139  ::sal::detail::unwrapStream( \
140  ::sal::detail::StreamStart() << stream), \
141  0); \
142  } else { \
143  ::std::ostringstream sal_detail_stream; \
144  sal_detail_stream << stream; \
145  ::sal::detail::log( \
146  (level), (area), (where), sal_detail_stream, 0); \
147  }
148 
149 #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
150  do { \
151  if (SAL_UNLIKELY(condition)) \
152  { \
153  switch (sal_detail_log_report(level, area)) \
154  { \
155  case SAL_DETAIL_LOG_ACTION_IGNORE: break; \
156  case SAL_DETAIL_LOG_ACTION_LOG: \
157  SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
158  break; \
159  case SAL_DETAIL_LOG_ACTION_FATAL: \
160  SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
161  std::abort(); \
162  break; \
163  } \
164  } \
165  } while (false)
166 
168 
179 #define SAL_WHERE SAL_DETAIL_WHERE
180 
195 #if defined _LIBCPP_VERSION \
196  || (defined _GLIBCXX_RELEASE \
197  && (_GLIBCXX_RELEASE >= 12 || (_GLIBCXX_RELEASE == 11 && __GLIBCXX__ > 20210428))) \
198  || (defined _MSC_VER && _MSC_VER >= 1915)
199 #define SAL_STREAM(stream) \
200  (::std::ostringstream() << stream).str()
201 #else
202 #define SAL_STREAM(stream) \
203  (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
204 #endif
205 
343 #define SAL_INFO(area, stream) \
344  SAL_DETAIL_LOG_STREAM( \
345  SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
346  SAL_WHERE, stream)
347 
353 #define SAL_INFO_IF(condition, area, stream) \
354  SAL_DETAIL_LOG_STREAM( \
355  SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
356  ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
357 
363 #define SAL_WARN(area, stream) \
364  SAL_DETAIL_LOG_STREAM( \
365  SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
366  SAL_WHERE, stream)
367 
373 #define SAL_WARN_IF(condition, area, stream) \
374  SAL_DETAIL_LOG_STREAM( \
375  SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
376  ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
377 
384 #define SAL_DEBUG(stream) \
385  SAL_DETAIL_LOG_STREAM( \
386  SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
387 
395 #define SAL_DEBUG_IF(condition, stream) \
396  SAL_DETAIL_LOG_STREAM( \
397  (condition), ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
398 
413 #define SAL_DEBUG_BACKTRACE(stream, backtraceDepth) \
414  do { \
415  if (sizeof ::sal::detail::getResult( \
416  ::sal::detail::StreamStart() << stream) == 1) \
417  { \
418  ::sal_detail_log( \
419  ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, \
420  ::sal::detail::unwrapStream( \
421  ::sal::detail::StreamStart() << stream), \
422  backtraceDepth); \
423  } else { \
424  ::std::ostringstream sal_detail_stream; \
425  sal_detail_stream << stream; \
426  ::sal::detail::log( \
427  ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, sal_detail_stream, \
428  backtraceDepth); \
429  } \
430  } while (false)
431 
432 
433 
434 #endif
435 
436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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, for example).
Definition: string.hxx:2355
#define SAL_DLLPUBLIC
Definition: saldllapi.h:34
#define SAL_UNUSED_PARAMETER
Annotate unused but required C++ function parameters.
Definition: types.h:568
Definition: types.h:423