HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
safeOutputFile.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_SAFE_OUTPUT_FILE_H
8 #define PXR_BASE_TF_SAFE_OUTPUT_FILE_H
9 
10 /// \file tf/safeOutputFile.h
11 /// Safe file writer with FILE * interface.
12 
13 #include "pxr/pxr.h"
14 #include "pxr/base/tf/api.h"
15 
16 #include <cstdio>
17 #include <memory>
18 #include <string>
19 
21 
22 /// \class TfSafeOutputFile
23 ///
24 /// Opens a file for output, either for update "r+" or to completely replace
25 /// "w+". In the case of complete replacement, create a sibling temporary file
26 /// to write to instead. When writing is complete, rename the temporary file
27 /// over the target file. This provides some safety to other processes reading
28 /// the existing file (at least on unix-like OSs). They will continue to see
29 /// the existing contents of the old file. If we overwrote the file itself,
30 /// then those other processes would see undefined, possibly partially updated
31 /// content.
33 {
34  TfSafeOutputFile(TfSafeOutputFile const &) = delete;
35  TfSafeOutputFile &operator=(TfSafeOutputFile const &) = delete;
36 public:
37  TfSafeOutputFile() = default;
38 
40  : _file(other._file)
41  , _targetFileName(std::move(other._targetFileName))
42  , _tempFileName(std::move(other._tempFileName))
43  { other._file = nullptr; }
44 
46  _file = other._file;
47  _targetFileName = std::move(other._targetFileName);
48  _tempFileName = std::move(other._tempFileName);
49  other._file = nullptr;
50  return *this;
51  }
52 
53  /// Destructor invokes Close().
55 
56  /// Open \p fileName for update ("r+").
57  TF_API static TfSafeOutputFile Update(std::string const &fileName);
58 
59  /// Arrange for \p fileName to be replaced. Create a sibling temporary file
60  /// and open that for writing. When Close() is called (or the destructor is
61  /// run) close the temporary file and rename it over \p fileName.
62  TF_API static TfSafeOutputFile Replace(std::string const &fileName);
63 
64  /// Close the file. If the file was opened with Replace(), rename the
65  /// temporary file over the target file to replace it.
66  TF_API void Close();
67 
68  /// Close the file. If the file was opened with Replace(), the temporary
69  /// file is removed and not renamed over the target file. It is an error
70  /// to call this for files opened for Update.
71  TF_API void Discard();
72 
73  /// Return the opened FILE *.
74  FILE *Get() const { return _file; }
75 
76  /// If the underlying file was opened by Update(), return it. The caller
77  /// takes responsibility for closing the file later. It is an error to call
78  /// this for files opened for Replace.
79  TF_API FILE *ReleaseUpdatedFile();
80 
81  /// Return true if this TfSafeOutputFile was created by a call to Update(),
82  /// false otherwise.
83  TF_API bool IsOpenForUpdate() const;
84 
85 private:
86  FILE *_file = nullptr;
87  std::string _targetFileName;
88  std::string _tempFileName;
89 };
90 
92 
93 #endif // PXR_BASE_TF_SAFE_OUTPUT_FILE_H
static TF_API TfSafeOutputFile Replace(std::string const &fileName)
#define TF_API
Definition: api.h:23
TF_API bool IsOpenForUpdate() const
FILE * Get() const
Return the opened FILE *.
TF_API FILE * ReleaseUpdatedFile()
TfSafeOutputFile & operator=(TfSafeOutputFile &&other)
static TF_API TfSafeOutputFile Update(std::string const &fileName)
Open fileName for update ("r+").
TF_API ~TfSafeOutputFile()
Destructor invokes Close().
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
TF_API void Close()
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
TF_API void Discard()
TfSafeOutputFile()=default
TfSafeOutputFile(TfSafeOutputFile &&other)