resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmListFileCache.h
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #pragma once
4
5 #include "cmConfigure.h" // IWYU pragma: keep
6
7 #include <iosfwd>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include <cm/optional>
14
15 #include "cmConstStack.h"
16 #include "cmSystemTools.h"
17
18 /** \class cmListFileCache
19  * \brief A class to cache list file contents.
20  *
21  * cmListFileCache is a class used to cache the contents of parsed
22  * cmake list files.
23  */
24
25 class cmMessenger;
26
27 struct cmListFileArgument
28 {
29   enum Delimiter
30   {
31     Unquoted,
32     Quoted,
33     Bracket
34   };
35   cmListFileArgument() = default;
36   cmListFileArgument(std::string v, Delimiter d, long line)
37     : Value(std::move(v))
38     , Delim(d)
39     , Line(line)
40   {
41   }
42   bool operator==(const cmListFileArgument& r) const
43   {
44     return (this->Value == r.Value) && (this->Delim == r.Delim);
45   }
46   bool operator!=(const cmListFileArgument& r) const { return !(*this == r); }
47   std::string Value;
48   Delimiter Delim = Unquoted;
49   long Line = 0;
50 };
51
52 class cmListFileFunction
53 {
54 public:
55   cmListFileFunction(std::string name, long line, long lineEnd,
56                      std::vector<cmListFileArgument> args)
57     : Impl{ std::make_shared<Implementation>(std::move(name), line, lineEnd,
58                                              std::move(args)) }
59   {
60   }
61
62   std::string const& OriginalName() const noexcept
63   {
64     return this->Impl->OriginalName;
65   }
66
67   std::string const& LowerCaseName() const noexcept
68   {
69     return this->Impl->LowerCaseName;
70   }
71
72   long Line() const noexcept { return this->Impl->Line; }
73   long LineEnd() const noexcept { return this->Impl->LineEnd; }
74
75   std::vector<cmListFileArgument> const& Arguments() const noexcept
76   {
77     return this->Impl->Arguments;
78   }
79
80 private:
81   struct Implementation
82   {
83     Implementation(std::string name, long line, long lineEnd,
84                    std::vector<cmListFileArgument> args)
85       : OriginalName{ std::move(name) }
86       , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) }
87       , Line{ line }
88       , LineEnd{ lineEnd }
89       , Arguments{ std::move(args) }
90     {
91     }
92
93     std::string OriginalName;
94     std::string LowerCaseName;
95     long Line = 0;
96     long LineEnd = 0;
97     std::vector<cmListFileArgument> Arguments;
98   };
99
100   std::shared_ptr<Implementation const> Impl;
101 };
102
103 class cmListFileContext
104 {
105 public:
106   std::string Name;
107   std::string FilePath;
108   long Line = 0;
109   static long const DeferPlaceholderLine = -1;
110   cm::optional<std::string> DeferId;
111
112   cmListFileContext() = default;
113   // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it
114   // as being able to throw an exception. Suppress the warning as there doesn't
115   // seem to be any way for this to happen given the member types.
116   // NOLINTNEXTLINE(bugprone-exception-escape)
117   cmListFileContext(cmListFileContext&& /*other*/) noexcept = default;
118   cmListFileContext(const cmListFileContext& /*other*/) = default;
119   cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
120 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
121   cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
122     default;
123 #else
124   // The move assignment operators for several STL classes did not become
125   // noexcept until C++17, which causes some tools to warn about this move
126   // assignment operator throwing an exception when it shouldn't.
127   cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
128     delete;
129 #endif
130
131   cmListFileContext(std::string name, std::string filePath, long line)
132     : Name(std::move(name))
133     , FilePath(std::move(filePath))
134     , Line(line)
135   {
136   }
137
138   static cmListFileContext FromListFilePath(std::string const& filePath)
139   {
140     // We are entering a file-level scope but have not yet reached
141     // any specific line or command invocation within it.  This context
142     // is useful to print when it is at the top but otherwise can be
143     // skipped during call stack printing.
144     cmListFileContext lfc;
145     lfc.FilePath = filePath;
146     return lfc;
147   }
148
149   static cmListFileContext FromListFileFunction(
150     cmListFileFunction const& lff, std::string const& fileName,
151     cm::optional<std::string> deferId = {})
152   {
153     cmListFileContext lfc;
154     lfc.FilePath = fileName;
155     lfc.Line = lff.Line();
156     lfc.Name = lff.OriginalName();
157     lfc.DeferId = std::move(deferId);
158     return lfc;
159   }
160 };
161
162 std::ostream& operator<<(std::ostream&, cmListFileContext const&);
163 bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
164 bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
165 bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
166
167 // Represent a backtrace (call stack) with efficient value semantics.
168 class cmListFileBacktrace
169   : public cmConstStack<cmListFileContext, cmListFileBacktrace>
170 {
171   using cmConstStack::cmConstStack;
172   friend class cmConstStack<cmListFileContext, cmListFileBacktrace>;
173 };
174 #ifndef cmListFileCache_cxx
175 extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>;
176 #endif
177
178 // Wrap type T as a value with a backtrace.  For purposes of
179 // ordering and equality comparison, only the original value is
180 // used.  The backtrace is considered incidental.
181 template <typename T>
182 class BT
183 {
184 public:
185   BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
186     : Value(std::move(v))
187     , Backtrace(std::move(bt))
188   {
189   }
190   T Value;
191   cmListFileBacktrace Backtrace;
192   friend bool operator==(BT<T> const& l, BT<T> const& r)
193   {
194     return l.Value == r.Value;
195   }
196   friend bool operator<(BT<T> const& l, BT<T> const& r)
197   {
198     return l.Value < r.Value;
199   }
200   friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; }
201   friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; }
202 };
203
204 std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
205
206 // Wrap type T as a value with potentially multiple backtraces.  For purposes
207 // of ordering and equality comparison, only the original value is used.  The
208 // backtrace is considered incidental.
209 template <typename T>
210 class BTs
211 {
212 public:
213   BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
214     : Value(std::move(v))
215   {
216     this->Backtraces.emplace_back(std::move(bt));
217   }
218   T Value;
219   std::vector<cmListFileBacktrace> Backtraces;
220   friend bool operator==(BTs<T> const& l, BTs<T> const& r)
221   {
222     return l.Value == r.Value;
223   }
224   friend bool operator<(BTs<T> const& l, BTs<T> const& r)
225   {
226     return l.Value < r.Value;
227   }
228   friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; }
229   friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; }
230 };
231
232 std::vector<BT<std::string>> cmExpandListWithBacktrace(
233   std::string const& list,
234   cmListFileBacktrace const& bt = cmListFileBacktrace(),
235   bool emptyArgs = false);
236
237 struct cmListFile
238 {
239   bool ParseFile(const char* path, cmMessenger* messenger,
240                  cmListFileBacktrace const& lfbt);
241
242   bool ParseString(const char* str, const char* virtual_filename,
243                    cmMessenger* messenger, cmListFileBacktrace const& lfbt);
244
245   std::vector<cmListFileFunction> Functions;
246 };