cmGeneratedFileStream.h 4.9 KB

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