PageRenderTime 29ms CodeModel.GetById 8ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/io/file.d

http://github.com/wilkie/djehuty
D | 411 lines | 246 code | 114 blank | 51 comment | 33 complexity | 8090ebef17428743b5967b857476b18e MD5 | raw file
  1/*
  2 * file.d
  3 *
  4 * This file contains the magic behind File.
  5 *
  6 * Author: Dave Wilkinson
  7 *
  8 */
  9
 10module io.file;
 11
 12import djehuty;
 13
 14import platform.vars.file;
 15
 16import scaffold.file;
 17
 18import io.directory;
 19
 20// Section: Core/Streams
 21
 22// Description: This class wraps common file operations within the context of a Stream.
 23class File : Stream {
 24	// Description: Will open the file located at the _path at filename.  The internal pointer will point to the beginning of the file.
 25	// filename: The file to open.
 26	this(string filename) {
 27		_name = filename.dup; 
 28
 29		_pos = null;
 30		_curpos = 0;
 31		bool r = FileCreate(_pfvars, _name);
 32
 33		if (!r) {
 34			throw new IOException.CreationFailure(filename);
 35		}
 36
 37		_length = 0;
 38		_inited = true;
 39	}
 40
 41	// Description: Will create a closed File class.  You must open a file to use it as a stream.
 42	this() {
 43	}
 44
 45	~this() {
 46		close();
 47	}
 48
 49	// Description: Will open the file located at the _path at filename.  The internal pointer will point to the beginning of the file.
 50	// filename: The file to open.
 51	// Returns: Will return an instance to the opened file.
 52	static File open(string filename) {
 53		File foo = new File;
 54		foo._name = filename.dup;
 55
 56		foo._pos = null;
 57		foo._curpos = 0;
 58		bool r = FileOpen(foo._pfvars, foo._name);
 59
 60		if (!r) {
 61			return null;
 62		}
 63
 64		FileGetSize(foo._pfvars, foo._length);
 65		foo._inited = true;
 66
 67		return foo;
 68	}
 69
 70	static File create(string filename) {
 71		return new File(filename);
 72	}
 73
 74	// Methods //
 75
 76	// Inherited Functionality
 77
 78	alias Stream.write write;
 79	alias Stream.append append;
 80	alias Stream.read read;
 81
 82	// Core Functionality
 83
 84	// Description: Will close the file.  This is also done upon deconstruction of the class, for instance when it is garbage collected.
 85	void close() {
 86		if (_inited) {
 87			FileClose(_pfvars);
 88			_inited = false;
 89			_name = null;
 90		}
 91	}
 92
 93	// read
 94	override bool read(void* buffer, uint len) {
 95		if (_curpos + len > _length) {
 96			return false;
 97		}
 98
 99		FileRead(_pfvars, cast(ubyte*)buffer, len);
100
101		_curpos += len;
102
103		return true;
104	}
105
106	override bool read(Stream stream, uint len) {
107		if (_curpos + len > _length) {
108			return false;
109		}
110
111		stream.write(this, len);
112
113		return true;
114	}
115
116	override ulong readAny(void* buffer, uint len) {
117		if (_curpos + len > _length) {
118			len = cast(uint)(_length - _curpos);
119		}
120
121		if (len == 0) { return 0; }
122
123		FileRead(_pfvars, cast(ubyte*)buffer, len);
124
125		return len;
126	}
127
128	override ulong readAny(Stream stream, uint len) {
129		if (_curpos + len > _length) {
130			len = cast(uint)(_length - _curpos);
131		}
132
133		if (len == 0) { return 0; }
134
135		stream.write(this, len);
136
137		_curpos += len;
138
139		return len;
140	}
141
142	// Console.put
143
144	override bool write(ubyte* bytes, uint len) {
145		if (len <= 0) { return false;}
146
147		//if (_curpos + len > _length)
148		//{
149		// TODO: throw permission exception
150		//	return false;
151		//}
152
153		FileWrite(_pfvars, bytes, len);
154
155		_curpos += len;
156
157		if (_curpos > _length) { _length = _curpos; }
158		return true;
159	}
160
161	override bool write(Stream stream, uint len) {
162		if (len <= 0) { return false;}
163
164		ubyte buffer[] = new ubyte[len];
165
166		stream.read(&buffer[0], len);
167
168		//if (_curpos + len > _length)
169		//{
170		// TODO: throw permission exception
171		//	return false;
172		//}
173
174		FileWrite(_pfvars, &buffer[0], len);
175
176		_curpos += len;
177
178		if (_curpos > _length) { _length = _curpos; }
179		return true;
180	}
181
182	// append
183
184	override bool append(ubyte* bytes, uint len) {
185		if (len <= 0) { return false;}
186
187		FileAppend(_pfvars, bytes, len);
188
189		_length += len;
190		return true;
191	}
192
193	override bool append(Stream stream, uint len) {
194		if (len <= 0) { return false;}
195
196		ubyte buffer[] = new ubyte[len];
197
198		stream.read(&buffer[0], len);
199		FileAppend(_pfvars, &buffer[0], len);
200
201		_length += len;
202		return true;
203	}
204
205	override ulong remaining() {
206		//Console.put("rem: ", _curpos, " ", _length, " ", _length - _curpos);
207		return _length - _curpos;
208	}
209
210	// rewind
211
212	override void rewind() {
213		// set to start
214		_curpos = 0;
215
216		FileRewindAll(_pfvars);
217	}
218
219	override bool rewind(ulong amount) {
220		if (_curpos - amount < 0) {
221			return false;
222		}
223
224		_curpos -= amount;
225		FileRewind(_pfvars, amount);
226
227		return true;
228	}
229
230	override ulong rewindAny(ulong amount) {
231		if (_curpos - amount < 0) {
232			amount = _curpos;
233		}
234
235		_curpos -= amount;
236		FileRewind(_pfvars, amount);
237
238		return amount;
239	}
240
241	// skip
242
243	override void skip() {
244		_curpos = _length;
245
246		FileSkipAll(_pfvars);
247	}
248
249	override bool skip(ulong amount) {
250		if (_curpos + amount > _length) {
251			return false;
252		}
253
254		_curpos += amount;
255		FileSkip(_pfvars, amount);
256		return true;
257	}
258
259	override ulong skipAny(ulong amount) {
260		if (_curpos + amount > _length) {
261			amount = _length - _curpos;
262		}
263
264		if (amount <= 0) { return 0; }
265
266		_curpos += amount;
267		FileSkip(_pfvars, amount);
268		return amount;
269	}
270
271	// Description: Will return the string representing the filename currently open, or null for when there is no open file.
272	// Returns: The string representing the filename of this class.
273	string name() {
274		if (_inited) {
275			return _name.dup;
276		}
277
278		return null;
279	}
280
281	override bool duplicate(ulong distanceBehind, uint amount) {
282		if (amount <= 0) { return false; }
283
284		if (_curpos - distanceBehind < 0) { return false; }
285
286		// need to store bytes...could be an overlapping array copy!
287		ubyte bytes[] = new ubyte[amount];
288
289		read(bytes.ptr, amount);
290
291		return true;
292	}
293
294	override bool duplicateFromEnd(ulong distanceBehind, uint amount) {
295		if (amount <= 0) { return false; }
296
297		if (_length - distanceBehind < 0) { return false; }
298
299		ubyte bytes[] = new ubyte[amount];
300
301		ulong pos = _curpos;
302
303		skip();
304		rewind(distanceBehind);
305
306		read(bytes.ptr, amount);
307		append(bytes.ptr, amount);
308
309		rewind();
310		skip(pos);
311
312		return true;
313	}
314
315	// File logic
316
317	Directory path() {
318		if (_inited) {
319			return _path;
320		}
321
322		return null;
323	}
324
325	void move(Directory destination) {
326		if (FileMove(_pfvars, _path.path ~ "/" ~ _name, destination.path ~ "/" ~ _name)) {
327			_path = destination;
328		}
329	}
330
331	void move(string destination) {
332		if (FileMove(_pfvars, _path.path ~ "/" ~ _name, destination ~ "/" ~ _name)) {
333			_path = Directory.open(destination);
334		}
335	}
336
337	File copy(Directory destination) {
338		File ret;
339		if (FileCopy(_pfvars, _path.path ~ "/" ~ _name, destination.path ~ "/" ~ _name)) {
340			ret = File.open(destination.path ~ "/" ~ _name);
341		}
342		return ret;
343	}
344
345	File copy(string destination) {
346		File ret;
347		if (FileCopy(_pfvars, _path.path ~ "/" ~ _name, destination ~ "/" ~ _name)) {
348			ret = File.open(destination ~ "/" ~ _name);
349		}
350		return ret;
351	}
352
353	void destroy() {
354	}
355
356	override char[] toString() {
357		return _path.path ~ "/" ~ _name;
358	}
359
360	int opApply(int delegate(ref string) loopFunc) {
361		string nextLine;
362		int ret;
363		while(readLine(nextLine)) {
364			ret = loopFunc(nextLine);
365
366			if (ret) { break; }
367		}
368
369		return ret;
370	}
371
372protected:
373
374	bool _inited = false;
375	FilePlatformVars _pfvars;
376
377	Directory _path;
378	string _name;
379}
380
381// Section: Core/Streams
382
383// Description: This class wraps common file operations within the context of a Stream. The permissions of this object will not allow writes.
384class FileReader : File {
385	// Description: Will open the file located at the _path at filename. The internal pointer will point to the beginning of the file.
386	// filename: The file to open.
387	this(string filename) {
388		super(filename);
389	}
390
391	// Description: Will create a closed File class. You must open a file to use it as a stream.
392	this() {
393		super();
394	}
395}
396
397// Section: Core/Streams
398
399// Description: This class wraps common file operations within the context of a Stream. The permissions of this object will not allow reads.
400class FileWriter : File {
401	// Description: Will open the file located at the _path at filename. The internal pointer will point to the beginning of the file.
402	// filename: The file to open.
403	this(string filename) {
404		super(filename);
405	}
406
407	// Description: Will create a closed File class. You must open a file to use it as a stream.
408	this() {
409		super();
410	}
411}