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
29enum sal_detail_LogAction
30{
31 SAL_DETAIL_LOG_ACTION_IGNORE,
32 SAL_DETAIL_LOG_ACTION_LOG,
33 SAL_DETAIL_LOG_ACTION_FATAL
34};
35
36extern "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".
42extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report(
43 sal_detail_LogLevel level, char const * area);
44
45namespace sal { namespace detail {
46
47inline 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
65struct StreamStart {};
66
67struct StreamString {
68 StreamString(char const * s): string(s) {}
69
70 char const * string;
71
72 typedef char Result;
73};
74
75struct StreamIgnore {
76 typedef struct { char a[2]; } Result;
77};
78
79inline StreamString operator <<(
80 SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
81{
82 return StreamString(s);
83}
84
85template< 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
94template< 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
103template< 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
112template< typename T > typename T::Result getResult(T const &);
113
114inline char const * unwrapStream(StreamString const & s) { return s.string; }
115
116inline 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_UNUSED_PARAMETER
Annotate unused but required C++ function parameters.
Definition: types.h:539
#define SAL_DLLPUBLIC
Definition: saldllapi.h:30
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
Definition: types.h:394