cmGeneratedFileStream.h 4.47 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3 4 5
#ifndef cmGeneratedFileStream_h
#define cmGeneratedFileStream_h

6
#include "cmConfigure.h" // IWYU pragma: keep
7

8 9
#include "cm_codecvt.hxx"
#include "cmsys/FStream.hxx"
10
#include <string>
11 12 13 14 15 16 17

// This is the first base class of cmGeneratedFileStream.  It will be
// created before and destroyed after the ofstream portion and can
// therefore be used to manage the temporary file.
class cmGeneratedFileStreamBase
{
protected:
18 19 20 21 22
  // This constructor does not prepare the temporary file.  The open
  // method must be used.
  cmGeneratedFileStreamBase();

  // This constructor prepares the temporary output file.
23
  cmGeneratedFileStreamBase(std::string const& name);
24 25 26 27

  // The destructor renames the temporary output file to the real name.
  ~cmGeneratedFileStreamBase();

28 29
  // Internal methods to handle the temporary file.  Open is always
  // called before the real stream is opened.  Close is always called
30
  // after the real stream is closed and Okay is set to whether the
31
  // real stream was still valid for writing when it was closed.
32
  void Open(std::string const& name);
33
  bool Close();
34

35
  // Internal file replacement implementation.
36
  int RenameFile(std::string const& oldname, std::string const& newname);
37

38
  // Internal file compression implementation.
39
  int CompressFile(std::string const& oldname, std::string const& newname);
40

41
  // The name of the final destination file for the output.
42
  std::string Name;
43 44

  // The name of the temporary file.
45
  std::string TempName;
46 47

  // Whether to do a copy-if-different.
48
  bool CopyIfDifferent = false;
49

50
  // Whether the real file stream was valid when it was closed.
51
  bool Okay = false;
52

53
  // Whether the destination file is compressed
54
  bool Compress = false;
55

56
  // Whether the destination file is compressed
57
  bool CompressExtraExtension = true;
58
};
59 60

/** \class cmGeneratedFileStream
61
 * \brief Output stream for generated files.
62
 *
63 64 65 66 67 68
 * File generation should be atomic so that if CMake is killed then a
 * generated file is either the original version or the complete new
 * version.  This stream is used to make sure file generation is
 * atomic.  Optionally the output file is only replaced if its
 * contents have changed to prevent the file modification time from
 * being updated.
69
 */
70 71 72
class cmGeneratedFileStream
  : private cmGeneratedFileStreamBase
  , public cmsys::ofstream
73 74
{
public:
75
  typedef cmsys::ofstream Stream;
76
  typedef codecvt::Encoding Encoding;
77

78
  /**
79 80 81
   * This constructor prepares a default stream.  The open method must
   * be used before writing to the stream.
   */
82
  cmGeneratedFileStream(Encoding encoding = codecvt::None);
83 84 85

  /**
   * This constructor takes the name of the file to be generated.  It
86 87 88
   * automatically generates a name for the temporary file.  If the
   * file cannot be opened an error message is produced unless the
   * second argument is set to true.
89
   */
90
  cmGeneratedFileStream(std::string const& name, bool quiet = false,
91
                        Encoding encoding = codecvt::None);
92 93

  /**
94 95 96
   * The destructor checks the stream status to be sure the temporary
   * file was successfully written before allowing the original to be
   * replaced.
97
   */
98
  ~cmGeneratedFileStream() override;
99

wahikihiki's avatar
wahikihiki committed
100 101
  cmGeneratedFileStream(cmGeneratedFileStream const&) = delete;

102 103
  /**
   * Open an output file by name.  This should be used only with a
104 105 106
   * non-open stream.  It automatically generates a name for the
   * temporary file.  If the file cannot be opened an error message is
   * produced unless the second argument is set to true.
107
   */
108
  cmGeneratedFileStream& Open(std::string const& name, bool quiet = false,
109
                              bool binaryFlag = false);
110

111 112 113
  /**
   * Close the output file.  This should be used only with an open
   * stream.  The temporary file is atomically renamed to the
luz.paz's avatar
luz.paz committed
114
   * destination file if the stream is still valid when this method
115 116
   * is called.
   */
117
  bool Close();
118

119 120 121 122
  /**
   * Set whether copy-if-different is done.
   */
  void SetCopyIfDifferent(bool copy_if_different);
123 124 125 126 127

  /**
   * Set whether compression is done.
   */
  void SetCompression(bool compression);
128

129 130 131 132 133
  /**
   * Set whether compression has extra extension
   */
  void SetCompressionExtraExtension(bool ext);

134 135 136 137
  /**
   * Set name of the file that will hold the actual output. This method allows
   * the output file to be changed during the use of cmGeneratedFileStream.
   */
138
  void SetName(const std::string& fname);
139 140 141
};

#endif