LibreOffice
LibreOffice 26.2 SDK C/C++ API Reference
Loading...
Searching...
No Matches
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
33enum sal_detail_LogAction
34{
35 SAL_DETAIL_LOG_ACTION_IGNORE,
36 SAL_DETAIL_LOG_ACTION_LOG,
37 SAL_DETAIL_LOG_ACTION_FATAL
38};
39
40extern "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
44extern "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".
48extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report(
49 sal_detail_LogLevel level, char const * area);
50
51namespace sal { namespace detail {
52
53inline 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
71struct StreamStart {};
72
73struct StreamString {
74 StreamString(char const * s): string(s) {}
75
76 char const * string;
77
78 typedef char Result;
79};
80
81struct StreamIgnore {
82 typedef struct { char a[2]; } Result;
83};
84
85inline StreamString operator <<(
86 SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
87{
88 return StreamString(s);
89}
90
91template< 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
100template< 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
109template< 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
118template< typename T > typename T::Result getResult(T const &);
119
120inline char const * unwrapStream(StreamString const & s) { return s.string; }
121
122inline 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#if defined LIBO_INTERNAL_ONLY && defined __GNUC__ && !defined __clang__
150// move cold/seldom-used code out of line, and into a separate linker section
151#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
152 do { \
153 if (SAL_UNLIKELY(condition)) \
154 { \
155 [&]() __attribute__((noinline,cold)) \
156 { \
157 switch (sal_detail_log_report(level, area)) \
158 { \
159 case SAL_DETAIL_LOG_ACTION_IGNORE: break; \
160 case SAL_DETAIL_LOG_ACTION_LOG: \
161 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
162 break; \
163 case SAL_DETAIL_LOG_ACTION_FATAL: \
164 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
165 std::abort(); \
166 break; \
167 } \
168 }(); \
169 } \
170 } while (false)
171#else
172#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
173 do { \
174 if (SAL_UNLIKELY(condition)) \
175 { \
176 switch (sal_detail_log_report(level, area)) \
177 { \
178 case SAL_DETAIL_LOG_ACTION_IGNORE: break; \
179 case SAL_DETAIL_LOG_ACTION_LOG: \
180 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
181 break; \
182 case SAL_DETAIL_LOG_ACTION_FATAL: \
183 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
184 std::abort(); \
185 break; \
186 } \
187 } \
188 } while (false)
189#endif
190
192
203#define SAL_WHERE SAL_DETAIL_WHERE
204
219#if defined _LIBCPP_VERSION \
220 || (defined _GLIBCXX_RELEASE \
221 && (_GLIBCXX_RELEASE >= 12 || (_GLIBCXX_RELEASE == 11 && __GLIBCXX__ > 20210428))) \
222 || (defined _MSC_VER && _MSC_VER >= 1915)
223#define SAL_STREAM(stream) \
224 (::std::ostringstream() << stream).str()
225#else
226#define SAL_STREAM(stream) \
227 (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
228#endif
229
362
368#define SAL_INFO(area, stream) \
369 SAL_DETAIL_LOG_STREAM( \
370 SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
371 SAL_WHERE, stream)
372
378#define SAL_INFO_IF(condition, area, stream) \
379 SAL_DETAIL_LOG_STREAM( \
380 SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
381 ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
382
388#define SAL_WARN(area, stream) \
389 SAL_DETAIL_LOG_STREAM( \
390 SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
391 SAL_WHERE, stream)
392
398#define SAL_WARN_IF(condition, area, stream) \
399 SAL_DETAIL_LOG_STREAM( \
400 SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
401 ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
402
409#define SAL_DEBUG(stream) \
410 SAL_DETAIL_LOG_STREAM( \
411 SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
412
420#define SAL_DEBUG_IF(condition, stream) \
421 SAL_DETAIL_LOG_STREAM( \
422 (condition), ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
423
438#define SAL_DEBUG_BACKTRACE(stream, backtraceDepth) \
439 do { \
440 if (sizeof ::sal::detail::getResult( \
441 ::sal::detail::StreamStart() << stream) == 1) \
442 { \
443 ::sal_detail_log( \
444 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, \
445 ::sal::detail::unwrapStream( \
446 ::sal::detail::StreamStart() << stream), \
447 backtraceDepth); \
448 } else { \
449 ::std::ostringstream sal_detail_stream; \
450 sal_detail_stream << stream; \
451 ::sal::detail::log( \
452 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, sal_detail_stream, \
453 backtraceDepth); \
454 } \
455 } while (false)
456
457
458
459#endif
460
461/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define SAL_UNUSED_PARAMETER
Annotate unused but required C++ function parameters.
Definition types.h:592
#define SAL_DLLPUBLIC
Definition saldllapi.h:34
Definition types.h:441