6 #include <msp/strings/formatter.h>
16 Creates a new file object and opens it. If the
17 create flag is true and write access is requested and the file does exist, it
18 is created. Otherwise a missing file is an error.
20 @param fn Name of the file to open
22 @param cm Flags controlling creation of a new file
24 File::File(const string &fn, Mode m, CreateMode cm)
27 throw InvalidParameterValue("Invalid read/write mode");
28 if(cm&~(C_CREATE|C_TRUNCATE))
29 throw InvalidParameterValue("Invalid create mode");
35 int create_flags = OPEN_EXISTING;
38 flags |= GENERIC_READ;
41 flags |= GENERIC_WRITE;
43 switch(static_cast<int>(cm))
45 case C_NONE: create_flags = OPEN_EXISTING; break;
46 case C_CREATE: create_flags = OPEN_ALWAYS; break;
47 case C_TRUNCATE: create_flags = TRUNCATE_EXISTING; break;
48 case C_CREATE+C_TRUNCATE: create_flags = CREATE_ALWAYS; break;
52 handle = CreateFile(fn.c_str(), flags, 0, 0, create_flags, FILE_ATTRIBUTE_NORMAL, 0);
53 if(handle==INVALID_HANDLE_VALUE)
55 int err = GetLastError();
56 if(err==ERROR_FILE_NOT_FOUND)
57 throw FileNotFound("Can't find file "+fn, fn);
59 throw SystemError(format("Can't open file '%s'", fn), GetLastError());
65 case M_READ: flags |= O_RDONLY; break;
66 case M_WRITE: flags |= O_WRONLY; break;
67 case M_RDWR: flags |= O_RDWR; break;
83 handle = ::open(fn.c_str(), flags, 0666);
88 throw FileNotFound("Can't find file "+fn, fn);
90 throw SystemError(format("Can't open file '%s'", fn), err);
98 Closes the file. Any attempt to access the file after this will cause an
99 exception to be thrown.
103 if(handle==MSP_IO_INVALID_HANDLE)
108 signal_flush_required.emit();
116 handle = MSP_IO_INVALID_HANDLE;
117 signal_closed.emit();
121 Sets the blocking state of the file. If blocking is disabled, all operations
122 will return immediately, even if they can't be fully completed.
124 void File::set_block(bool b)
126 check_access(M_NONE);
128 mode = (mode&~M_NONBLOCK);
130 mode = (mode|M_NONBLOCK);
132 int flags = fcntl(handle, F_GETFD);
133 fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
140 signal_flush_required.emit();
147 Seeks the file to the given byte offset.
149 @param off Offset in bytes
152 @return The resulting offset
154 int File::seek(int off, SeekType st)
156 check_access(M_NONE);
158 signal_flush_required.emit();
160 int type = sys_seek_type(st);
162 DWORD ret = SetFilePointer(handle, off, 0, type);
163 if(ret==INVALID_SET_FILE_POINTER)
164 throw SystemError("Seek failed", GetLastError());
166 int ret = lseek(handle, off, type);
168 throw SystemError("Seek failed", errno);
177 Returns the current read/write offset of the file.
179 int File::tell() const
181 check_access(M_NONE);
184 DWORD ret = SetFilePointer(handle, 0, 0, FILE_CURRENT);
185 if(ret==INVALID_SET_FILE_POINTER)
186 throw SystemError("Tell failed", GetLastError());
188 int ret = lseek(handle, 0, SEEK_CUR);
190 throw SystemError("Tell failed", errno);
201 void File::check_access(Mode m) const
203 if(handle==MSP_IO_INVALID_HANDLE)
204 throw InvalidState("File is not open");
205 if(m==M_READ && !(mode&M_READ))
206 throw InvalidState("File is not readable");
207 if(m==M_WRITE && !(mode&M_WRITE))
208 throw InvalidState("File is not writable");
212 Writes data from a buffer to the file.
214 @param buf Buffer to write from.
215 @param size Length of data to write.
217 @return The number of bytes written
219 unsigned File::do_write(const char *buf, unsigned size)
221 check_access(M_WRITE);
230 if(WriteFile(handle, buf, size, &ret, 0)==0)
231 throw SystemError("Writing to file failed", GetLastError());
233 int ret = ::write(handle, buf, size);
239 throw SystemError("Writing to file failed", errno);
247 Reads data from the file.
249 @param buf Buffer to read data into.
250 @param size Maximum size of data to read.
252 @return The number of bytes read, possibly zero
254 unsigned File::do_read(char *buf, unsigned size)
256 check_access(M_READ);
263 if(ReadFile(handle, buf, size, &ret, 0)==0)
264 throw SystemError("Reading from file failed", GetLastError());
266 int ret = ::read(handle, buf, size);
272 throw SystemError("Reading from file failed", errno);
279 signal_end_of_file.emit();