Add "file_delete" method in String and NativeString.
[nit.git] / lib / standard / file.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
5 # Copyright 2008 Jean-Sébastien Gélinas <calestar@gmail.com>
6 #
7 # This file is free software, which comes along with NIT. This software is
8 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
11 # is kept unaltered, and a notification of the changes is added.
12 # You are allowed to redistribute it and sell it, alone or is a part of
13 # another product.
14
15 # This module handle file input and output
16 package file
17
18 intrude import stream
19 intrude import string
20 import string_search
21
22 redef class Object
23 # Simple I/O
24
25 # Print `objects' on the standard output (`stdout').
26 protected meth printn(objects: Object...)
27 do
28 stdout.write(objects.to_s)
29 end
30
31 # Print an `object' on the standard output (`stdout') and add a newline.
32 protected meth print(object: Object)
33 do
34 if object != null then
35 stdout.write(object.to_s)
36 end
37 stdout.write("\n")
38 end
39
40 # Read a character from the standard input (`stdin').
41 protected meth getc: Char
42 do
43 return stdin.read_char.ascii
44 end
45
46 # Read a line from the standard input (`stdin').
47 protected meth gets: String
48 do
49 return stdin.read_line
50 end
51 end
52
53 # File Abstract Stream
54 class FStream
55 special IOS
56 special NativeFileCapable
57
58 # The path of the file.
59 readable attr _path: String = null
60
61 # The FILE *.
62 attr _file: NativeFile = null
63
64 meth file_stat: FileStat
65 do return _file.file_stat end
66 end
67
68 # File input stream
69 class IFStream
70 special FStream
71 special BufferedIStream
72 # Misc
73
74 meth reopen
75 do
76 if not eof then close
77 _file = io_open_read(_path.to_cstring)
78 _end_reached = false
79 _buffer_pos = 0
80 _buffer.clear
81 end
82
83 redef meth close
84 do
85 var i = _file.io_close
86 _end_reached = true
87 end
88
89 # Fill the internal read buffer. Needed by read operations.
90 redef meth fill_buffer
91 do
92 var nb = _file.io_read(_buffer._items, _buffer._capacity)
93 if nb <= 0 then
94 _end_reached = true
95 nb = 0
96 end
97 _buffer._length = nb
98 _buffer_pos = 0
99 end
100
101 # End of file?
102 redef readable attr _end_reached: Bool = false
103
104 # Open the file at `path' for reading.
105 init open(path: String)
106 do
107 _path = path
108 prepare_buffer(10)
109 _file = io_open_read(_path.to_cstring)
110 assert cant_open_file: _file != null
111 end
112
113 private init do end
114 private init without_file do end
115 end
116
117 # File output stream
118 class OFStream
119 special FStream
120 special OStream
121
122 # Write a string.
123 redef meth write(s)
124 do
125 assert _writable
126 write_native(s.to_cstring, s.length)
127 end
128
129 redef meth is_writable do return _writable
130
131 redef meth close
132 do
133 var i = _file.io_close
134 _writable = false
135 end
136
137 # Is the file open in write mode
138 attr _writable: Bool
139
140 # Write `len' bytes from `native'.
141 private meth write_native(native: NativeString, len: Int)
142 do
143 assert _writable
144 var err = _file.io_write(native, len)
145 if err != len then
146 # Big problem
147 printn("Problem in writing : ", err, " ", len, "\n")
148 end
149 end
150
151 # Open the file at `path' for writing.
152 init open(path: String)
153 do
154 _file = io_open_write(path.to_cstring)
155 assert cant_open_file: _file != null
156 _path = path
157 _writable = true
158 end
159
160 private init do end
161 private init without_file do end
162 end
163
164 ###############################################################################
165
166 class Stdin
167 special IFStream
168 private init do
169 _file = native_stdin
170 _path = "/dev/stdin"
171 prepare_buffer(1)
172 end
173 end
174
175 class Stdout
176 special OFStream
177 private init do
178 _file = native_stdout
179 _path = "/dev/stdout"
180 _writable = true
181 end
182 end
183
184 class Stderr
185 special OFStream
186 private init do
187 _file = native_stderr
188 _path = "/dev/stderr"
189 _writable = true
190 end
191 end
192
193 ###############################################################################
194
195 redef class String
196 # return true if a file with this names exists
197 meth file_exists: Bool do return to_cstring.file_exists
198
199 meth file_stat: FileStat do return to_cstring.file_stat
200
201 meth file_delete: Bool do return to_cstring.file_delete
202
203 meth strip_extension(ext: String): String
204 do
205 if has_suffix(ext) then
206 return substring(0, length - ext.length)
207 end
208 return self
209 end
210
211 meth basename(ext: String): String
212 do
213 var pos = last_index_of_from('/', _length - 1)
214 var n = self
215 if pos >= 0 then
216 n = substring_from(pos+1)
217 end
218 return n.strip_extension(ext)
219 end
220
221 meth dirname: String
222 do
223 var pos = last_index_of_from('/', _length - 1)
224 if pos >= 0 then
225 return substring(0, pos)
226 else
227 return "."
228 end
229 end
230
231 meth file_path: String
232 do
233 var l = _length
234 var pos = last_index_of_from('/', l - 1)
235 if pos >= 0 then
236 return substring(0, pos)
237 end
238 return "."
239 end
240
241 # Create a directory (and all intermediate directories if needed)
242 meth mkdir
243 do
244 var dirs = self.split_with("/")
245 var path = new String
246 if dirs.is_empty then return
247 if dirs[0].is_empty then
248 # it was a starting /
249 path.add('/')
250 end
251 for d in dirs do
252 if d.is_empty then continue
253 path.append(d)
254 path.add('/')
255 path.to_cstring.file_mkdir
256 end
257 end
258 end
259
260 redef class NativeString
261 private meth file_exists: Bool is extern "string_NativeString_NativeString_file_exists_0"
262 private meth file_stat: FileStat is extern "string_NativeString_NativeString_file_stat_0"
263 private meth file_mkdir: Bool is extern "string_NativeString_NativeString_file_mkdir_0"
264 private meth file_delete: Bool is extern "string_NativeString_NativeString_file_delete_0"
265 end
266
267 universal FileStat
268 special Pointer
269 # This class is system dependent ... must reify the vfs
270 meth mode: Int is extern "file_FileStat_FileStat_mode_0"
271 meth atime: Int is extern "file_FileStat_FileStat_atime_0"
272 meth ctime: Int is extern "file_FileStat_FileStat_ctime_0"
273 meth mtime: Int is extern "file_FileStat_FileStat_mtime_0"
274 meth size: Int is extern "file_FileStat_FileStat_size_0"
275 end
276
277 # Instance of this class are standard FILE * pointers
278 private universal NativeFile
279 special Pointer
280 meth io_read(buf: NativeString, len: Int): Int is extern "file_NativeFile_NativeFile_io_read_2"
281 meth io_write(buf: NativeString, len: Int): Int is extern "file_NativeFile_NativeFile_io_write_2"
282 meth io_close: Int is extern "file_NativeFile_NativeFile_io_close_0"
283 meth file_stat: FileStat is extern "file_NativeFile_NativeFile_file_stat_0"
284 end
285
286 private interface NativeFileCapable
287 meth io_open_read(path: NativeString): NativeFile is extern "file_NativeFileCapable_NativeFileCapable_io_open_read_1"
288 meth io_open_write(path: NativeString): NativeFile is extern "file_NativeFileCapable_NativeFileCapable_io_open_write_1"
289 meth native_stdin: NativeFile is extern "file_NativeFileCapable_NativeFileCapable_native_stdin_0"
290 meth native_stdout: NativeFile is extern "file_NativeFileCapable_NativeFileCapable_native_stdout_0"
291 meth native_stderr: NativeFile is extern "file_NativeFileCapable_NativeFileCapable_native_stderr_0"
292 end
293
294 # Standard input.
295 meth stdin: IFStream do return once new Stdin
296
297 # Standard output.
298 meth stdout: OFStream do return once new Stdout
299
300 # Standard output for error.
301 meth stderr: OFStream do return once new Stderr