]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_cfile_stream.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_cfile_stream.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_cfile_stream.h
28 #pragma once
29
30 #include "vogl_core.h"
31 #include "vogl_data_stream.h"
32
33 namespace vogl
34 {
35     class cfile_stream : public data_stream
36     {
37     public:
38         cfile_stream()
39             : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false)
40         {
41         }
42
43         cfile_stream(FILE *pFile, const char *pFilename, uint attribs, bool has_ownership)
44             : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false)
45         {
46             open(pFile, pFilename, attribs, has_ownership);
47         }
48
49         cfile_stream(const char *pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false)
50             : data_stream(), m_pFile(NULL), m_size(0), m_ofs(0), m_has_ownership(false)
51         {
52             open(pFilename, attribs, open_existing);
53         }
54
55         virtual ~cfile_stream()
56         {
57             close();
58         }
59
60         virtual bool close()
61         {
62             clear_error();
63
64             if (m_opened)
65             {
66                 bool status = true;
67                 if (m_has_ownership)
68                 {
69                     if (EOF == vogl_fclose(m_pFile))
70                         status = false;
71                 }
72
73                 m_pFile = NULL;
74                 m_opened = false;
75                 m_size = 0;
76                 m_ofs = 0;
77                 m_has_ownership = false;
78
79                 return status;
80             }
81
82             return false;
83         }
84
85         bool open(FILE *pFile, const char *pFilename, uint attribs, bool has_ownership)
86         {
87             VOGL_ASSERT(pFile);
88             VOGL_ASSERT(pFilename);
89
90             close();
91
92             set_name(pFilename);
93             m_pFile = pFile;
94             m_has_ownership = has_ownership;
95             m_attribs = static_cast<uint16>(attribs);
96
97             m_ofs = vogl_ftell(m_pFile);
98             vogl_fseek(m_pFile, 0, SEEK_END);
99             m_size = vogl_ftell(m_pFile);
100             vogl_fseek(m_pFile, m_ofs, SEEK_SET);
101
102             m_opened = true;
103
104             return true;
105         }
106
107         bool open(const char *pFilename, uint attribs = cDataStreamReadable | cDataStreamSeekable, bool open_existing = false)
108         {
109             VOGL_ASSERT(pFilename);
110
111             close();
112
113             m_attribs = static_cast<uint16>(attribs);
114
115             const char *pMode;
116             if ((is_readable()) && (is_writable()))
117                 pMode = open_existing ? "r+b" : "w+b";
118             else if (is_writable())
119                 pMode = open_existing ? "ab" : "wb";
120             else if (is_readable())
121                 pMode = "rb";
122             else
123             {
124                 set_error();
125                 return false;
126             }
127
128             FILE *pFile = vogl_fopen(pFilename, pMode);
129             m_has_ownership = true;
130
131             if (!pFile)
132             {
133                 set_error();
134                 return false;
135             }
136
137             // TODO: Change stream class to support UCS2 filenames.
138
139             return open(pFile, pFilename, attribs, true);
140         }
141
142         FILE *get_file() const
143         {
144             return m_pFile;
145         }
146
147         virtual uint read(void *pBuf, uint len)
148         {
149             VOGL_ASSERT(len <= 0x7FFFFFFF);
150
151             if (!m_opened || (!is_readable()) || (!len))
152                 return 0;
153
154             len = static_cast<uint>(math::minimum<uint64_t>(len, get_remaining()));
155
156             if (vogl_fread(pBuf, 1, len, m_pFile) != len)
157             {
158                 set_error();
159                 return 0;
160             }
161
162             m_ofs += len;
163             return len;
164         }
165
166         virtual uint write(const void *pBuf, uint len)
167         {
168             VOGL_ASSERT(len <= 0x7FFFFFFF);
169
170             if (!m_opened || (!is_writable()) || (!len))
171                 return 0;
172
173             if (vogl_fwrite(pBuf, 1, len, m_pFile) != len)
174             {
175                 set_error();
176                 return 0;
177             }
178
179             m_ofs += len;
180             m_size = math::maximum(m_size, m_ofs);
181
182             return len;
183         }
184
185         virtual bool flush()
186         {
187             if ((!m_opened) || (!is_writable()))
188                 return false;
189
190             if (EOF == vogl_fflush(m_pFile))
191             {
192                 set_error();
193                 return false;
194             }
195
196             return true;
197         }
198
199         virtual uint64_t get_size() const
200         {
201             if (!m_opened)
202                 return 0;
203
204             return m_size;
205         }
206
207         virtual uint64_t get_remaining() const
208         {
209             if (!m_opened)
210                 return 0;
211
212             VOGL_ASSERT(m_ofs <= m_size);
213             return m_size - m_ofs;
214         }
215
216         virtual uint64_t get_ofs() const
217         {
218             if (!m_opened)
219                 return 0;
220
221             return m_ofs;
222         }
223
224         virtual bool seek(int64_t ofs, bool relative)
225         {
226             if ((!m_opened) || (!is_seekable()))
227                 return false;
228
229             int64_t new_ofs = relative ? (m_ofs + ofs) : ofs;
230             if (new_ofs < 0)
231                 return false;
232             else if (static_cast<uint64_t>(new_ofs) > m_size)
233                 return false;
234
235             if (static_cast<uint64_t>(new_ofs) != m_ofs)
236             {
237                 if (vogl_fseek(m_pFile, new_ofs, SEEK_SET) != 0)
238                 {
239                     set_error();
240                     return false;
241                 }
242
243                 m_ofs = new_ofs;
244             }
245
246             return true;
247         }
248
249         static bool read_file_into_array(const char *pFilename, vector<uint8> &buf)
250         {
251             cfile_stream in_stream(pFilename);
252             if (!in_stream.is_opened())
253                 return false;
254             return in_stream.read_array(buf);
255         }
256
257         static bool write_array_to_file(const char *pFilename, const vector<uint8> &buf)
258         {
259             cfile_stream out_stream(pFilename, cDataStreamWritable | cDataStreamSeekable);
260             if (!out_stream.is_opened())
261                 return false;
262             return out_stream.write_array(buf);
263         }
264
265     private:
266         FILE *m_pFile;
267         uint64_t m_size, m_ofs;
268         bool m_has_ownership;
269     };
270
271 } // namespace vogl