blocxx
FileBuf.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Quest Software, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Quest Software, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38#include "blocxx/BLOCXX_config.h"
39#include "blocxx/FileBuf.hpp"
41
42#ifdef BLOCXX_HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
46#include <fcntl.h>
47#include <ios>
48
49#ifdef BLOCXX_WIN32
50#include <io.h>
51#endif
52
53namespace BLOCXX_NAMESPACE
54{
55
57: BaseStreamBuffer(E_IN_OUT)
58, m_file(0)
59{
60}
61
63{
64 close();
65}
66
67bool
69{
70 return m_file != 0;
71}
72
75{
76 if (isOpen())
77 {
78 return 0;
79 }
80
81 m_file = fp;
82 return this;
83}
84
87{
88 if (isOpen())
89 {
90 return 0;
91 }
92
93int d = -1;
94
95#ifdef BLOCXX_WIN32
96#pragma message(Reminder "TODO: implement it for Win!")
97 //maybe it's enough just to set flags = O_RDWR
98 //but it's unclear what to do with O_APPEND
99 int flags = O_RDWR;
100
101 d = _open_osfhandle(reinterpret_cast<long>(fd.get()), flags);
102#else
103 d = fd.get();
104 int flags = ::fcntl(d, F_GETFL);
105 if (flags == -1)
106 {
107 return 0;
108 }
109#endif
110
111 m_file = ::fdopen(d, cppModeToCMode(posixModeToCppMode(flags)));
112 if (m_file == 0)
113 {
114 return 0;
115 }
116 ::setbuf(m_file, 0);
117 fd.release();
118 return this;
119}
120
121#if 0
122FileBuf*
123FileBuf::open(const File& f)
124{
125 if (isOpen())
126 {
127 return 0;
128 }
129 int flags = ::fcntl(f.???, F_GETFL);
130 if (flags == -1)
131 {
132 return 0;
133 }
134
135 m_file = ::fdopen(???, cppModeToCMode(posixModeToCppMode(flags)));
136 if (m_file == 0)
137 {
138 return 0;
139 }
140 ::setbuf(m_file, 0);
141 return this;
142}
143#endif
144
145FileBuf*
146FileBuf::open(const char* path, std::ios_base::openmode mode, mode_t permissions)
147{
148 if (isOpen())
149 {
150 return 0;
151 }
152
153 int d = ::open(path, cppModeToPOSIXMode(mode), permissions);
154
155#ifdef BLOCXX_WIN32
156 Descriptor h = reinterpret_cast<Descriptor>(_get_osfhandle(d));
157 AutoDescriptor fd(h);
158#else
159 AutoDescriptor fd(d);
160#endif
161
162 if (fd.get() == BLOCXX_INVALID_HANDLE)
163 {
164 return 0;
165 }
166
167 m_file = ::fdopen(d, cppModeToCMode(mode));
168
169 if (m_file == 0)
170 {
171 return 0;
172 }
173
174 ::setbuf(m_file, 0);
175 fd.release();
176
177 return this;
178}
179
180FileBuf*
182{
183 if (isOpen())
184 {
185 ::fclose(m_file);
186 }
187 m_file = 0;
188 return this;
189}
190
191int
192FileBuf::buffer_to_device(const char* c, int n)
193{
194 size_t written = ::fwrite(c, 1, n, m_file);
195 if (written == static_cast<size_t>(n))
196 {
197 return 0;
198 }
199 else
200 {
201 return -1;
202 }
203}
204
205int
207{
208 if (!isOpen())
209 {
210 return -1;
211 }
212 size_t numRead = ::fread(c, 1, n, m_file);
213 if (numRead != static_cast<size_t>(n))
214 {
215 if (ferror(m_file))
216 {
217 BLOCXX_THROW_ERRNO_MSG(IOException, "FileBuf::buffer_from_device: ::fread()");
218 }
219 else if (feof(m_file) && numRead == 0)
220 {
221 return -1;
222 }
223 else
224 {
225 return numRead;
226 }
227 }
228 else
229 {
230 return n;
231 }
232}
233
234std::ios_base::openmode
236{
237 std::ios_base::openmode mode = posixMode & O_APPEND ? std::ios::app : std::ios_base::openmode(0);
238
239#ifdef BLOCXX_WIN32
240 #define O_ACCMODE 3
241#endif
242 switch (posixMode & O_ACCMODE)
243 {
244 case O_RDONLY: mode |= (std::ios::in | std::ios::binary); break;
245 case O_WRONLY: mode |= (std::ios::out | std::ios::binary); break;
246 case O_RDWR: mode |= (std::ios::in | std::ios::out | std::ios::binary); break;
247 }
248 return mode;
249}
250
251int
252FileBuf::cppModeToPOSIXMode(std::ios_base::openmode cppMode)
253{
254 int mode = 0;
255 if (cppMode & std::ios::app)
256 {
257 mode |= O_APPEND;
258 }
259
260 if (cppMode & std::ios::trunc)
261 {
262 mode |= O_TRUNC;
263 }
264
265 if (cppMode & (std::ios::in | std::ios::out))
266 {
267 mode |= O_RDWR;
268 }
269 else if (cppMode & std::ios::in)
270 {
271 mode |= O_RDONLY;
272 }
273 else if (cppMode & std::ios::out)
274 {
275 mode |= O_WRONLY;
276 }
277 return mode;
278}
279
280const char* FileBuf::cppModeToCMode(std::ios_base::openmode cppMode)
281{
282 // mask out irrelevant bits
283 cppMode = cppMode & ~std::ios::ate;
284
285 using std::ios;
286 // can't use a switch here because the ios flags aren't native types.
287 if( cppMode == ios::app ||
288 cppMode == (ios::in|ios::app) ||
289 cppMode == (ios::out|ios::app) )
290 {
291 return "a";
292 }
293
294 else if( cppMode == (ios::binary|ios::app) ||
295 cppMode == (ios::in|ios::binary|ios::app) ||
296 cppMode == (ios::out|ios::binary|ios::app) )
297 {
298 return "ab";
299 }
300
301 else if (cppMode == ios::in)
302 {
303 return "r";
304 }
305
306 else if (cppMode == (ios::in|ios::binary))
307 {
308 return "rb";
309 }
310
311 else if (cppMode == (ios::out|ios::in))
312 {
313 return "r+";
314 }
315
316 else if (cppMode == (ios::out|ios::in|ios::app))
317 {
318 return "a+";
319 }
320
321 else if (cppMode == (ios::out|ios::in|ios::binary))
322 {
323 return "r+b";
324 }
325
326 else if (cppMode == (ios::out|ios::in|ios::binary|ios::app))
327 {
328 return "a+b";
329 }
330
331 else if( (cppMode == ios::out) ||
332 cppMode == (ios::trunc) ||
333 cppMode == (ios::trunc|ios::app) ||
334 cppMode == (ios::trunc|ios::out) ||
335 cppMode == (ios::trunc|ios::out|ios::app) )
336 {
337 return "w";
338 }
339
340 else if( (cppMode == (ios::trunc|ios::binary)) ||
341 (cppMode == (ios::trunc|ios::binary|ios::app)) ||
342 (cppMode == (ios::out|ios::binary)) ||
343 (cppMode == (ios::trunc|ios::out|ios::binary)) ||
344 (cppMode == (ios::trunc|ios::out|ios::binary|ios::app) ))
345 {
346 return "wb";
347 }
348
349 else if( (cppMode == (ios::trunc|ios::out|ios::in)) ||
350 (cppMode == (ios::trunc|ios::out|ios::in|ios::app)) )
351 {
352 return "w+";
353 }
354
355 else if( (cppMode == (ios::trunc|ios::out|ios::in|ios::binary)) ||
356 (cppMode == (ios::trunc|ios::out|ios::in|ios::binary|ios::app)) )
357 {
358 return "w+b";
359 }
360 else
361 {
362 return ""; // bad mode
363 }
364
365}
366
367
368} // end namespace BLOCXX_NAMESPACE
369
370
#define BLOCXX_THROW_ERRNO_MSG(exType, msg)
Throw an exception using FILE, LINE, errno and strerror(errno)
#define BLOCXX_INVALID_HANDLE
Definition Types.hpp:136
PURPOSE: The AutoResource class template is an analog of std::auto_ptr for managing arbitrary resourc...
handle_type get() const
Return handle of resource, retaining ownership.
handle_type release()
Relinquish ownership of resource and return its handle.
The purpose of this class is to provide an alternative implementation of std::filebuf that is based o...
Definition FileBuf.hpp:59
const char * cppModeToCMode(std::ios_base::openmode cppMode)
Converts C++ iostream open mode to C stdio file open mode or the empty string on error (never returns...
Definition FileBuf.cpp:280
std::ios_base::openmode posixModeToCppMode(int posixMode)
Converts POSIX io open mode flags to C++ iostream open mode.
Definition FileBuf.cpp:235
int cppModeToPOSIXMode(std::ios_base::openmode cppMode)
Converts C++ iostream open mode to POSIX io open mode.
Definition FileBuf.cpp:252
virtual int buffer_from_device(char *c, int n)
Fill the buffer from the "device".
Definition FileBuf.cpp:206
virtual int buffer_to_device(const char *c, int n)
Writes the buffer to the "device".
Definition FileBuf.cpp:192
~FileBuf()
Calls close().
Definition FileBuf.cpp:62
FileBuf()
Constructor.
Definition FileBuf.cpp:56
FileBuf * close()
If isOpen() == false, returns a null pointer.
Definition FileBuf.cpp:181
FileBuf * open(FILE *fp)
If isOpen() == true, returns 0, otherwise initializes the FileBuf to use fp.
Definition FileBuf.cpp:74
The purpose of the File class is to provide an abstraction layer over the platform dependant function...
Definition File.hpp:55
Taken from RFC 1321.