cmGeneratedFileStream.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #ifndef cmGeneratedFileStream_h
  4. #define cmGeneratedFileStream_h
  5. #include "cmConfigure.h" // IWYU pragma: keep
  6. #include <string>
  7. #include "cmsys/FStream.hxx"
  8. #include "cm_codecvt.hxx"
  9. // This is the first base class of cmGeneratedFileStream. It will be
  10. // created before and destroyed after the ofstream portion and can
  11. // therefore be used to manage the temporary file.
  12. class cmGeneratedFileStreamBase
  13. {
  14. protected:
  15. // This constructor does not prepare the temporary file. The open
  16. // method must be used.
  17. cmGeneratedFileStreamBase();
  18. // This constructor prepares the temporary output file.
  19. cmGeneratedFileStreamBase(std::string const& name);
  20. // The destructor renames the temporary output file to the real name.
  21. ~cmGeneratedFileStreamBase();
  22. // Internal methods to handle the temporary file. Open is always
  23. // called before the real stream is opened. Close is always called
  24. // after the real stream is closed and Okay is set to whether the
  25. // real stream was still valid for writing when it was closed.
  26. void Open(std::string const& name);
  27. bool Close();
  28. // Internal file replacement implementation.
  29. int RenameFile(std::string const& oldname, std::string const& newname);
  30. // Internal file compression implementation.
  31. int CompressFile(std::string const& oldname, std::string const& newname);
  32. // The name of the final destination file for the output.
  33. std::string Name;
  34. // The extension of the temporary file.
  35. std::string TempExt;
  36. // The name of the temporary file.
  37. std::string TempName;
  38. // Whether to do a copy-if-different.
  39. bool CopyIfDifferent = false;
  40. // Whether the real file stream was valid when it was closed.
  41. bool Okay = false;
  42. // Whether the destination file is compressed
  43. bool Compress = false;
  44. // Whether the destination file is compressed
  45. bool CompressExtraExtension = true;
  46. };
  47. /** \class cmGeneratedFileStream
  48. * \brief Output stream for generated files.
  49. *
  50. * File generation should be atomic so that if CMake is killed then a
  51. * generated file is either the original version or the complete new
  52. * version. This stream is used to make sure file generation is
  53. * atomic. Optionally the output file is only replaced if its
  54. * contents have changed to prevent the file modification time from
  55. * being updated.
  56. */
  57. class cmGeneratedFileStream
  58. : private cmGeneratedFileStreamBase
  59. , public cmsys::ofstream
  60. {
  61. public:
  62. using Stream = cmsys::ofstream;
  63. using Encoding = codecvt::Encoding;
  64. /**
  65. * This constructor prepares a default stream. The open method must
  66. * be used before writing to the stream.
  67. */
  68. cmGeneratedFileStream(Encoding encoding = codecvt::None);
  69. /**
  70. * This constructor takes the name of the file to be generated. It
  71. * automatically generates a name for the temporary file. If the
  72. * file cannot be opened an error message is produced unless the
  73. * second argument is set to true.
  74. */
  75. cmGeneratedFileStream(std::string const& name, bool quiet = false,
  76. Encoding encoding = codecvt::None);
  77. /**
  78. * The destructor checks the stream status to be sure the temporary
  79. * file was successfully written before allowing the original to be
  80. * replaced.
  81. */
  82. ~cmGeneratedFileStream() override;
  83. cmGeneratedFileStream(cmGeneratedFileStream const&) = delete;
  84. /**
  85. * Open an output file by name. This should be used only with a
  86. * non-open stream. It automatically generates a name for the
  87. * temporary file. If the file cannot be opened an error message is
  88. * produced unless the second argument is set to true.
  89. */
  90. cmGeneratedFileStream& Open(std::string const& name, bool quiet = false,
  91. bool binaryFlag = false);
  92. /**
  93. * Close the output file. This should be used only with an open
  94. * stream. The temporary file is atomically renamed to the
  95. * destination file if the stream is still valid when this method
  96. * is called.
  97. */
  98. bool Close();
  99. /**
  100. * Set whether copy-if-different is done.
  101. */
  102. void SetCopyIfDifferent(bool copy_if_different);
  103. /**
  104. * Set whether compression is done.
  105. */
  106. void SetCompression(bool compression);
  107. /**
  108. * Set whether compression has extra extension
  109. */
  110. void SetCompressionExtraExtension(bool ext);
  111. /**
  112. * Set name of the file that will hold the actual output. This method allows
  113. * the output file to be changed during the use of cmGeneratedFileStream.
  114. */
  115. void SetName(const std::string& fname);
  116. /**
  117. * Set set a custom temporary file extension used with 'Open'.
  118. * This does not work if the file was opened by the constructor.
  119. */
  120. void SetTempExt(std::string const& ext);
  121. /**
  122. * Writes the given string directly to the file without changing the
  123. * encoding.
  124. */
  125. void WriteRaw(std::string const& data);
  126. private:
  127. // The original locale of the stream (performs no encoding conversion).
  128. std::locale OriginalLocale;
  129. };
  130. #endif