Etterna 0.74.4
Loading...
Searching...
No Matches
RageFileBasic.h
1/* RageFileBasic - simple file interface. */
2
3#ifndef RAGE_FILE_BASIC_H
4#define RAGE_FILE_BASIC_H
5
6/* This is a simple file I/O interface. Although most of these operations
7 * are straightforward, there are several of them; most of the time, you'll
8 * only want to implement RageFileObj. */
10{
11 public:
12 virtual ~RageFileBasic() = default;
13
14 virtual std::string GetError() const = 0;
15 virtual void ClearError() = 0;
16 virtual bool AtEOF() const = 0;
17
18 /* Seek to the given absolute offset. Return to the position actually
19 * seeked to; if the position given was beyond the end of the file, the
20 * return value will be the size of the file. */
21 virtual int Seek(int iOffset) = 0;
22 virtual int Seek(int offset, int whence) = 0;
23 virtual int Tell() const = 0;
24
25 /* Read at most iSize bytes into pBuf. Return the number of bytes read,
26 * 0 on end of stream, or -1 on error. Note that reading less than iSize
27 * does not necessarily mean that the end of the stream has been reached;
28 * keep reading until 0 is returned. */
29 virtual int Read(void* pBuffer, size_t iBytes) = 0;
30 virtual int Read(std::string& buffer, int bytes = -1) = 0;
31 virtual int Read(void* buffer, size_t bytes, int nmemb) = 0;
32
33 /* Write iSize bytes of data from pBuf. Return 0 on success, -1 on error.
34 */
35 virtual int Write(const void* pBuffer, size_t iBytes) = 0;
36 virtual int Write(const std::string& sString) = 0;
37 virtual int Write(const void* buffer, size_t bytes, int nmemb) = 0;
38
39 /* Due to buffering, writing may not happen by the end of a Write() call, so
40 * not all errors may be returned by it. Data will be flushed when the
41 * stream (or its underlying object) is destroyed, but errors can no longer
42 * be returned. Call Flush() to flush pending data, in order to check for
43 * errors. */
44 virtual int Flush() = 0;
45
46 /* This returns a descriptive path for the file, or "". */
47 virtual std::string GetDisplayPath() const { return std::string(); }
48
49 virtual RageFileBasic* Copy() const = 0;
50
51 virtual int GetLine(std::string& out) = 0;
52 virtual int PutLine(const std::string& str) = 0;
53
54 virtual void EnableCRC32(bool on = true) = 0;
55 virtual bool GetCRC32(uint32_t* iRet) = 0;
56
57 virtual int GetFileSize() const = 0;
58
59 /* If this file is backed by a file descriptor, return it. This is valid
60 * even if the file is being filtered or decompressed. If the file has no
61 * associated file descriptor, return -1. */
62 virtual int GetFD() = 0;
63};
64
66{
67 public:
69 RageFileObj(const RageFileObj& cpy);
70 ~RageFileObj() override;
71
72 std::string GetError() const override { return m_sError; }
73 void ClearError() override { SetError(""); }
74
75 bool AtEOF() const override { return m_bEOF; }
76
77 int Seek(int iOffset) override;
78 int Seek(int offset, int whence) override;
79 int Tell() const override { return m_iFilePos; }
80
81 int Read(void* pBuffer, size_t iBytes) override;
82 int Read(std::string& buffer, int bytes = -1) override;
83 int Read(void* buffer, size_t bytes, int nmemb) override;
84
85 int Write(const void* pBuffer, size_t iBytes) override;
86 int Write(const std::string& sString) override
87 {
88 return Write(sString.data(), sString.size());
89 }
90 int Write(const void* buffer, size_t bytes, int nmemb) override;
91
92 int Flush() override;
93
94 int GetLine(std::string& out) override;
95 int PutLine(const std::string& str) override;
96
97 void EnableCRC32(bool on = true) override;
98 bool GetCRC32(uint32_t* iRet) override;
99
100 int GetFileSize() const override = 0;
101 int GetFD() override { return -1; }
102 std::string GetDisplayPath() const override { return std::string(); }
103 RageFileBasic* Copy() const override { return 0; }
104
105 protected:
106 virtual int SeekInternal(int /* iOffset */) { return 0; }
107 virtual int ReadInternal(void* pBuffer, size_t iBytes) = 0;
108 virtual int WriteInternal(const void* pBuffer, size_t iBytes) = 0;
109 virtual int FlushInternal() { return 0; }
110
111 void EnableReadBuffering();
112 void EnableWriteBuffering(int iBytes = 1024 * 64);
113
114 void SetError(const std::string& sError) { m_sError = sError; }
115 std::string m_sError;
116
117 private:
118 int FillReadBuf();
119 void ResetReadBuf();
120 int EmptyWriteBuf();
121
122 bool m_bEOF;
123 int m_iFilePos;
124
125 /*
126 * If read buffering is enabled, m_pReadBuffer is the buffer, m_pReadBuf is
127 * the current read position in the buffer, and m_iReadBufAvail is the
128 * number of bytes at m_pReadBuf. Note that read buffering is only enabled
129 * if:
130 *
131 * - GetLine() is called (which requires buffering to efficiently search
132 * for newlines);
133 * - or EnableReadBuffering() is called
134 *
135 * Once buffering is enabled, it stays enabled for the life of the object.
136 *
137 * If buffering is not enabled, this buffer will not be allocated, keeping
138 * the size overhead of each file down. Layered RageFileBasic
139 * implementations, which read from other RageFileBasics, should generally
140 * not use buffering, in order to avoid reads being passed through several
141 * buffers, which is only a waste of memory.
142 */
143 enum
144 {
145 BSIZE = 1024
146 };
147 char* m_pReadBuffer;
148 char* m_pReadBuf;
149 int m_iReadBufAvail;
150
151 /*
152 * If write buffering is enabled, m_pWriteBuffer will be allocated, and
153 * m_iWriteBufferPos is the file position of the start of the buffer.
154 */
155 char* m_pWriteBuffer;
156 int m_iWriteBufferPos;
157 int m_iWriteBufferSize;
158 int m_iWriteBufferUsed;
159
160 /* If EnableCRC32() is called, a CRC32 will be calculated as the file is
161 * read. This is only meaningful if EnableCRC32() is called at the very
162 * start of the file, and no seeking is performed. */
163 bool m_bCRC32Enabled;
164 uint32_t m_iCRC32;
165
166 // Swallow up warnings. If they must be used, define them.
167 RageFileObj& operator=(const RageFileObj& rhs);
168};
169
170#endif
Definition RageFileBasic.h:10
Definition RageFileBasic.h:66