1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6  */
7 
8 #pragma once
9 
10 #include <rtl/ustring.hxx>
11 
12 #include <memory>
13 #include <string_view>
14 #include <vector>
15 
16 #include <config_options_calc.h>
17 
18 class ScFormulaCell;
19 class ScDocument;
20 class ScAddress;
21 struct ScFormulaCellGroup;
22 
23 namespace formula {
24 
25 class FormulaToken;
26 struct VectorRefArray;
27 
28 }
29 
30 namespace osl { class File; }
31 
32 namespace sc {
33 
34 #if ENABLE_FORMULA_LOGGER
35 
36 /**
37  * Outputs formula calculation log outputs to specified file.
38  */
39 class FormulaLogger
40 {
41     std::unique_ptr<osl::File> mpLogFile;
42 
43     sal_Int32 mnNestLevel = 0;
44     const ScFormulaCellGroup* mpLastGroup = nullptr;
45 
46     void writeAscii( const char* s );
47     void writeAscii( const char* s, size_t n );
48     void write( std::u16string_view ou );
49     void write( sal_Int32 n );
50 
51     void sync();
52 
53     void writeNestLevel();
54 
55 public:
56 
57     static FormulaLogger& get();
58 
59     /**
60      * This class is only moveable.
61      */
62     class GroupScope
63     {
64         friend class FormulaLogger;
65 
66         struct Impl;
67         std::unique_ptr<Impl> mpImpl;
68 
69     public:
70         GroupScope() = delete;
71         GroupScope( const GroupScope& ) = delete;
72         GroupScope& operator= ( const GroupScope& ) = delete;
73 
74     private:
75         GroupScope(
76             FormulaLogger& rLogger, const OUString& rPrefix,
77             const ScDocument& rDoc, const ScFormulaCell& rCell,
78             bool bOutputEnabled );
79 
80     public:
81         GroupScope(GroupScope&& r) noexcept;
82         ~GroupScope();
83 
84         /**
85          * Add an arbitrary message to dump to the log.
86          */
87         void addMessage( const OUString& rMsg );
88 
89         /**
90          * Add to the log a vector reference information for a single
91          * reference.
92          */
93         void addRefMessage(
94             const ScAddress& rCellPos, const ScAddress& rRefPos, size_t nLen,
95             const formula::VectorRefArray& rArray );
96 
97         /**
98          * Add to the log a vector reference information for a range
99          * reference.
100          */
101         void addRefMessage(
102             const ScAddress& rCellPos, const ScAddress& rRefPos, size_t nLen,
103             const std::vector<formula::VectorRefArray>& rArrays );
104 
105         /**
106          * Add to the log a single cell reference information.
107          */
108         void addRefMessage(
109             const ScAddress& rCellPos, const ScAddress& rRefPos,
110             const formula::FormulaToken& rToken );
111 
112         void addGroupSizeThresholdMessage( const ScFormulaCell& rCell );
113 
114         /**
115          * Call this when the group calculation has finished successfully.
116          */
117         void setCalcComplete();
118     };
119 
120     FormulaLogger( const FormulaLogger& ) = delete;
121     FormulaLogger& operator= ( const FormulaLogger& ) = delete;
122 
123     FormulaLogger();
124     ~FormulaLogger();
125 
126     GroupScope enterGroup( const ScDocument& rDoc, const ScFormulaCell& rCell );
127 };
128 
129 #else
130 
131 /**
132  * Dummy class with all empty inline methods.
133  */
134 class FormulaLogger
135 {
136 public:
137 
138     static FormulaLogger get()
139     {
140         return FormulaLogger();
141     }
142 
143     class GroupScope
144     {
145     public:
146         void addMessage( [[maybe_unused]] const OUString& /*rMsg*/ ) { (void) this; /* loplugin:staticmethods */ }
147 
148         void addRefMessage(
149             const ScAddress& /*rCellPos*/, const ScAddress& /*rRefPos*/, size_t /*nLen*/,
150             const formula::VectorRefArray& /*rArray*/ )
151         {
152             (void) this; /* loplugin:staticmethods */
153         }
154 
155         void addRefMessage(
156             const ScAddress& /*rCellPos*/, const ScAddress& /*rRefPos*/, size_t /*nLen*/,
157             const std::vector<formula::VectorRefArray>& /*rArrays*/ )
158         {
159             (void) this; /* loplugin:staticmethods */
160         }
161 
162         void addRefMessage(
163             const ScAddress& /*rCellPos*/, const ScAddress& /*rRefPos*/,
164             const formula::FormulaToken& /*rToken*/ )
165         {
166             (void) this; /* loplugin:staticmethods */
167         }
168 
169         void addGroupSizeThresholdMessage( const ScFormulaCell& /*rCell*/ )
170         {
171             (void) this; /* loplugin:staticmethods */
172         }
173 
174         void setCalcComplete() { (void) this; /* loplugin:staticmethods */ }
175     };
176 
177     GroupScope enterGroup( const ScDocument& /*rDoc*/, const ScFormulaCell& /*rCell*/ )
178     {
179         (void) this; /* loplugin:staticmethods */
180         return GroupScope();
181     }
182 };
183 
184 #endif // ENABLE_FORMULA_LOGGER
185 
186 }
187 
188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
189