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