Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Source / cmGeneratedFileStream.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 <string>
8
9 #include "cmsys/FStream.hxx"
10
11 #include "cm_codecvt.hxx"
12
13 // This is the first base class of cmGeneratedFileStream.  It will be
14 // created before and destroyed after the ofstream portion and can
15 // therefore be used to manage the temporary file.
16 class cmGeneratedFileStreamBase
17 {
18 protected:
19   // This constructor does not prepare the temporary file.  The open
20   // method must be used.
21   cmGeneratedFileStreamBase();
22
23   // This constructor prepares the temporary output file.
24   cmGeneratedFileStreamBase(std::string const& name);
25
26   // The destructor renames the temporary output file to the real name.
27   ~cmGeneratedFileStreamBase();
28
29   // Internal methods to handle the temporary file.  Open is always
30   // called before the real stream is opened.  Close is always called
31   // after the real stream is closed and Okay is set to whether the
32   // real stream was still valid for writing when it was closed.
33   void Open(std::string const& name);
34   bool Close();
35
36   // Internal file replacement implementation.
37   int RenameFile(std::string const& oldname, std::string const& newname);
38
39   // Internal file compression implementation.
40   int CompressFile(std::string const& oldname, std::string const& newname);
41
42   // The name of the final destination file for the output.
43   std::string Name;
44
45   // The extension of the temporary file.
46   std::string TempExt;
47
48   // The name of the temporary file.
49   std::string TempName;
50
51   // Whether to do a copy-if-different.
52   bool CopyIfDifferent = false;
53
54   // Whether the real file stream was valid when it was closed.
55   bool Okay = false;
56
57   // Whether the destination file is compressed
58   bool Compress = false;
59
60   // Whether the destination file is compressed
61   bool CompressExtraExtension = true;
62 };
63
64 /** \class cmGeneratedFileStream
65  * \brief Output stream for generated files.
66  *
67  * File generation should be atomic so that if CMake is killed then a
68  * generated file is either the original version or the complete new
69  * version.  This stream is used to make sure file generation is
70  * atomic.  Optionally the output file is only replaced if its
71  * contents have changed to prevent the file modification time from
72  * being updated.
73  */
74 class cmGeneratedFileStream
75   : private cmGeneratedFileStreamBase
76   , public cmsys::ofstream
77 {
78 public:
79   using Stream = cmsys::ofstream;
80   using Encoding = codecvt::Encoding;
81
82   /**
83    * This constructor prepares a default stream.  The open method must
84    * be used before writing to the stream.
85    */
86   cmGeneratedFileStream(Encoding encoding = codecvt::None);
87
88   /**
89    * This constructor takes the name of the file to be generated.  It
90    * automatically generates a name for the temporary file.  If the
91    * file cannot be opened an error message is produced unless the
92    * second argument is set to true.
93    */
94   cmGeneratedFileStream(std::string const& name, bool quiet = false,
95                         Encoding encoding = codecvt::None);
96
97   /**
98    * The destructor checks the stream status to be sure the temporary
99    * file was successfully written before allowing the original to be
100    * replaced.
101    */
102   ~cmGeneratedFileStream() override;
103
104   cmGeneratedFileStream(cmGeneratedFileStream const&) = delete;
105
106   /**
107    * Open an output file by name.  This should be used only with a
108    * non-open stream.  It automatically generates a name for the
109    * temporary file.  If the file cannot be opened an error message is
110    * produced unless the second argument is set to true.
111    */
112   cmGeneratedFileStream& Open(std::string const& name, bool quiet = false,
113                               bool binaryFlag = false);
114
115   /**
116    * Close the output file.  This should be used only with an open
117    * stream.  The temporary file is atomically renamed to the
118    * destination file if the stream is still valid when this method
119    * is called.
120    */
121   bool Close();
122
123   /**
124    * Set whether copy-if-different is done.
125    */
126   void SetCopyIfDifferent(bool copy_if_different);
127
128   /**
129    * Set whether compression is done.
130    */
131   void SetCompression(bool compression);
132
133   /**
134    * Set whether compression has extra extension
135    */
136   void SetCompressionExtraExtension(bool ext);
137
138   /**
139    * Set name of the file that will hold the actual output. This method allows
140    * the output file to be changed during the use of cmGeneratedFileStream.
141    */
142   void SetName(const std::string& fname);
143
144   /**
145    * Set set a custom temporary file extension used with 'Open'.
146    * This does not work if the file was opened by the constructor.
147    */
148   void SetTempExt(std::string const& ext);
149
150   /**
151    * Write a specific string using an alternate encoding.
152    * Afterward, the original encoding is restored.
153    */
154   void WriteAltEncoding(std::string const& data, Encoding encoding);
155 };