3 This file is part of libmspio
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
12 #include <msp/strings/formatter.h>
22 Creates a new file object and opens it. If the
23 create flag is true and write access is requested and the file does exist, it
24 is created. Otherwise a missing file is an error.
26 @param fn Name of the file to open
28 @param cm Flags controlling creation of a new file
30 File::File(const string &fn, Mode m, CreateMode cm)
33 throw InvalidParameterValue("Invalid read/write mode");
34 if(cm&~(C_CREATE|C_TRUNCATE))
35 throw InvalidParameterValue("Invalid create mode");
41 int create_flags=OPEN_EXISTING;
49 switch(static_cast<int>(cm))
51 case C_NONE: create_flags=OPEN_EXISTING; break;
52 case C_CREATE: create_flags=OPEN_ALWAYS; break;
53 case C_TRUNCATE: create_flags=TRUNCATE_EXISTING; break;
54 case C_CREATE+C_TRUNCATE: create_flags=CREATE_ALWAYS; break;
58 handle=CreateFile(fn.c_str(), flags, 0, 0, create_flags, FILE_ATTRIBUTE_NORMAL, 0);
59 if(handle==INVALID_HANDLE_VALUE)
61 int err=GetLastError();
62 if(err==ERROR_FILE_NOT_FOUND)
63 throw FileNotFound("Can't find file "+fn, fn);
65 throw SystemError(format("Can't open file '%s'", fn), GetLastError());
71 case M_READ: flags|=O_RDONLY; break;
72 case M_WRITE: flags|=O_WRONLY; break;
73 case M_RDWR: flags|=O_RDWR; break;
89 handle=::open(fn.c_str(), flags, 0666);
94 throw FileNotFound("Can't find file "+fn, fn);
96 throw SystemError(format("Can't open file '%s'", fn), err);
104 Closes the file. Any attempt to access the file after this will cause an
105 exception to be thrown.
109 if(handle==MSP_IO_INVALID_HANDLE)
114 signal_flush_required.emit();
122 handle=MSP_IO_INVALID_HANDLE;
123 signal_closed.emit();
127 Sets the blocking state of the file. If blocking is disabled, all operations
128 will return immediately, even if they can't be fully completed.
130 void File::set_block(bool b)
132 check_access(M_NONE);
134 mode=(mode&~M_NONBLOCK);
136 mode=(mode|M_NONBLOCK);
138 int flags=fcntl(handle, F_GETFD);
139 fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
146 signal_flush_required.emit();
153 Seeks the file to the given byte offset.
155 @param off Offset in bytes
158 @return The resulting offset
160 int File::seek(int off, SeekType st)
162 check_access(M_NONE);
164 signal_flush_required.emit();
166 int type=sys_seek_type(st);
168 DWORD ret=SetFilePointer(handle, off, 0, type);
169 if(ret==INVALID_SET_FILE_POINTER)
170 throw SystemError("Seek failed", GetLastError());
172 int ret=lseek(handle, off, type);
174 throw SystemError("Seek failed", errno);
183 Returns the current read/write offset of the file.
185 int File::tell() const
187 check_access(M_NONE);
190 DWORD ret=SetFilePointer(handle, 0, 0, FILE_CURRENT);
191 if(ret==INVALID_SET_FILE_POINTER)
192 throw SystemError("Tell failed", GetLastError());
194 int ret=lseek(handle, 0, SEEK_CUR);
196 throw SystemError("Tell failed", errno);
207 void File::check_access(Mode m) const
209 if(handle==MSP_IO_INVALID_HANDLE)
210 throw InvalidState("File is not open");
211 if(m==M_READ && !(mode&M_READ))
212 throw InvalidState("File is not readable");
213 if(m==M_WRITE && !(mode&M_WRITE))
214 throw InvalidState("File is not writable");
218 Writes data from a buffer to the file.
220 @param buf Buffer to write from.
221 @param size Length of data to write.
223 @return The number of bytes written
225 unsigned File::do_write(const char *buf, unsigned size)
227 check_access(M_WRITE);
236 if(WriteFile(handle, buf, size, &ret, 0)==0)
237 throw SystemError("Writing to file failed", GetLastError());
239 int ret=::write(handle, buf, size);
245 throw SystemError("Writing to file failed", errno);
253 Reads data from the file.
255 @param buf Buffer to read data into.
256 @param size Maximum size of data to read.
258 @return The number of bytes read, possibly zero
260 unsigned File::do_read(char *buf, unsigned size)
262 check_access(M_READ);
269 if(ReadFile(handle, buf, size, &ret, 0)==0)
270 throw SystemError("Reading from file failed", GetLastError());
272 int ret=::read(handle, buf, size);
278 throw SystemError("Reading from file failed", errno);
285 signal_end_of_file.emit();