OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 /** | 6 /** |
7 * FileMode describes the modes in which a file can be opened. | 7 * FileMode describes the modes in which a file can be opened. |
8 */ | 8 */ |
9 class FileMode { | 9 class FileMode { |
10 static final READ = const FileMode(0); | 10 static final READ = const FileMode(0); |
(...skipping 11 matching lines...) Expand all Loading... |
22 * streams using [openInputStream] and [openOutputStream] or open the | 22 * streams using [openInputStream] and [openOutputStream] or open the |
23 * file for random access operations using [open]. | 23 * file for random access operations using [open]. |
24 */ | 24 */ |
25 interface File default _File { | 25 interface File default _File { |
26 /** | 26 /** |
27 * Create a File object. | 27 * Create a File object. |
28 */ | 28 */ |
29 File(String name); | 29 File(String name); |
30 | 30 |
31 /** | 31 /** |
32 * Check if the file exists. The callback is called with the result | 32 * Check if the file exists. The [existsHandler] is called with the |
33 * when the operation completes. The [onError] function registered | 33 * result when the operation completes. |
34 * on the file object is called if an error occurs. | |
35 */ | 34 */ |
36 void exists(void callback(bool exists)); | 35 void exists(); |
37 | 36 |
38 /** | 37 /** |
39 * Synchronously check if the file exists. | 38 * Synchronously check if the file exists. |
40 */ | 39 */ |
41 bool existsSync(); | 40 bool existsSync(); |
42 | 41 |
43 /** | 42 /** |
44 * Create the file. The callback is called when the file has been | 43 * Create the file. The [createHandler] is called when the file has |
45 * created. The [onError] function registered on the file object is | 44 * been created. The [errorHandler] is called if the file cannot be |
46 * called if the file cannot be created. Existing files are left | 45 * created. Existing files are left untouched by create. Calling |
47 * untouched by create. Calling create on an existing file might | 46 * create on an existing file might fail if there are restrictive |
48 * fail if there are restrictive permissions on the file. | 47 * permissions on the file. |
49 */ | 48 */ |
50 void create(void callback()); | 49 void create(); |
51 | 50 |
52 /** | 51 /** |
53 * Synchronously create the file. Existing files are left untouched | 52 * Synchronously create the file. Existing files are left untouched |
54 * by create. Calling create on an existing file might fail if there | 53 * by create. Calling create on an existing file might fail if there |
55 * are restrictive permissions on the file. | 54 * are restrictive permissions on the file. |
56 */ | 55 */ |
57 void createSync(); | 56 void createSync(); |
58 | 57 |
59 /** | 58 /** |
60 * Delete the file. The callback is called when the file has been | 59 * Delete the file. The [deleteHandler] is called when the file has |
61 * successfully deleted. The [onError] function registered on the | 60 * been successfully deleted. The [errorHandler] is called if the |
62 * file object is called if the file cannot be deleted. | 61 * file cannot be deleted. |
63 */ | 62 */ |
64 void delete(void callback()); | 63 void delete(); |
65 | 64 |
66 /** | 65 /** |
67 * Synchronously delete the file. | 66 * Synchronously delete the file. |
68 */ | 67 */ |
69 void deleteSync(); | 68 void deleteSync(); |
70 | 69 |
71 /** | 70 /** |
72 * Get a Directory object for the directory containing this | 71 * Get a Directory object for the directory containing this file. If |
73 * file. When the operation completes the callback is called with | 72 * the file does not exist the [errorHandler] is called. When the |
74 * the result. If the file does not exist the [onError] function | 73 * operation completes the [directoryHandler] is called with the |
75 * registered on the file object is called. | 74 * result. |
76 */ | 75 */ |
77 void directory(void callback(Directory dir)); | 76 void directory(); |
78 | 77 |
79 /** | 78 /** |
80 * Synchronously get a Directory object for the directory containing | 79 * Synchronously get a Directory object for the directory containing |
81 * this file. | 80 * this file. |
82 */ | 81 */ |
83 Directory directorySync(); | 82 Directory directorySync(); |
84 | 83 |
85 /** | 84 /** |
86 * Open the file for random access operations. When the file is | 85 * Open the file for random access operations. When the file is |
87 * opened the callback is called with the resulting | 86 * opened the [openHandler] is called with the resulting |
88 * RandomAccessFile. RandomAccessFiles must be closed using the | 87 * RandomAccessFile. RandomAccessFiles must be closed using the |
89 * [close] method. If the file cannot be opened [onError] is called. | 88 * [close] method. If the file cannot be opened the [errorHandler] |
| 89 * is called. |
90 * | 90 * |
91 * Files can be opened in three modes: | 91 * Files can be opened in three modes: |
92 * | 92 * |
93 * FileMode.READ: open the file for reading. If the file does not | 93 * FileMode.READ: open the file for reading. If the file does not |
94 * exist [onError] is called. | 94 * exist the [errorHandler] is called. |
95 * | 95 * |
96 * FileMode.WRITE: open the file for both reading and writing and | 96 * FileMode.WRITE: open the file for both reading and writing and |
97 * truncate the file to length zero. If the file does not exist the | 97 * truncate the file to length zero. If the file does not exist the |
98 * file is created. | 98 * file is created. |
99 * | 99 * |
100 * FileMode.APPEND: same as FileMode.WRITE except that the file is | 100 * FileMode.APPEND: same as FileMode.WRITE except that the file is |
101 * not truncated. | 101 * not truncated. |
| 102 * |
| 103 * By default mode is FileMode.READ. |
102 */ | 104 */ |
103 void open(FileMode mode, void callback(RandomAccessFile opened)); | 105 void open([FileMode mode]); |
104 | 106 |
105 /** | 107 /** |
106 * Synchronously open the file for random access operations. The | 108 * Synchronously open the file for random access operations. The |
107 * result is a RandomAccessFile on which random access operations | 109 * result is a RandomAccessFile on which random access operations |
108 * can be performed. Opened RandomAccessFiles must be closed using | 110 * can be performed. Opened RandomAccessFiles must be closed using |
109 * the [close] method. | 111 * the [close] method. |
110 * | 112 * |
111 * See [open] for information on the [:mode:] argument. | 113 * See [open] for information on the [:mode:] argument. |
112 */ | 114 */ |
113 RandomAccessFile openSync(FileMode mode); | 115 RandomAccessFile openSync([FileMode mode]); |
114 | 116 |
115 /** | 117 /** |
116 * Get the canonical full path corresponding to the file name. The | 118 * Get the canonical full path corresponding to the file name. The |
117 * callback is called with the result when the | 119 * [fullPathHandler] is called with the result when the fullPath |
118 * fullPath operation completes. If the operation fails the | 120 * operation completes. |
119 * [onError] function registered on the file object is called. | |
120 */ | 121 */ |
121 void fullPath(void callback(String path)); | 122 void fullPath(); |
122 | 123 |
123 /** | 124 /** |
124 * Synchronously get the canonical full path corresponding to the file name. | 125 * Synchronously get the canonical full path corresponding to the file name. |
125 */ | 126 */ |
126 String fullPathSync(); | 127 String fullPathSync(); |
127 | 128 |
128 /** | 129 /** |
129 * Create a new independent input stream for the file. The file | 130 * Create a new independent input stream for the file. The file |
130 * input stream must be closed when no longer used to free up system | 131 * input stream must be closed when no longer used to free up system |
131 * resources. | 132 * resources. |
(...skipping 12 matching lines...) Expand all Loading... |
144 * | 145 * |
145 * FileMode.APPEND: create the stream and set the position to the end of | 146 * FileMode.APPEND: create the stream and set the position to the end of |
146 * the underlying file. | 147 * the underlying file. |
147 * | 148 * |
148 * By default the mode is FileMode.WRITE. | 149 * By default the mode is FileMode.WRITE. |
149 */ | 150 */ |
150 OutputStream openOutputStream([FileMode mode]); | 151 OutputStream openOutputStream([FileMode mode]); |
151 | 152 |
152 /** | 153 /** |
153 * Read the entire file contents as a list of bytes. When the | 154 * Read the entire file contents as a list of bytes. When the |
154 * operation completes the callback is called. The [onError] | 155 * operation completes the [readAsBytesHandler] is called. |
155 * function registered on the file object is called if the operation | 156 * The [errorHandler] is called if the operation fails. |
156 * fails. | |
157 */ | 157 */ |
158 void readAsBytes(void callback(List<int> bytes)); | 158 void readAsBytes(); |
159 | 159 |
160 /** | 160 /** |
161 * Synchronously read the entire file contents as a list of bytes. | 161 * Synchronously read the entire file contents as a list of bytes. |
162 */ | 162 */ |
163 List<int> readAsBytesSync(); | 163 List<int> readAsBytesSync(); |
164 | 164 |
165 /** | 165 /** |
166 * Read the entire file contents as text using the given [encoding] | 166 * Read the entire file contents as text using the given [encoding] |
167 * ('UTF-8', 'ISO-8859-1', 'ASCII'). | 167 * ('UTF-8', 'ISO-8859-1', 'ASCII'). By default the encoding is |
| 168 * 'UTF-8'. |
168 * | 169 * |
169 * When the operation completes the callback is called. The | 170 * When the operation completes the [readAsTextHandler] is called |
170 * [onError] function registered on the file object is called if the | 171 * with the resulting string. The [errorHandler] is called if the |
171 * operation fails. | 172 * operation fails. |
172 */ | 173 */ |
173 void readAsText(String encoding, void callback(String text)); | 174 void readAsText([String encoding]); |
174 | 175 |
175 /** | 176 /** |
176 * Synchronously read the entire file contents as text using the | 177 * Synchronously read the entire file contents as text using the |
177 * given [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). By default the | 178 * given [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). By default the |
178 * encoding is 'UTF-8'. | 179 * encoding is 'UTF-8'. |
179 */ | 180 */ |
180 String readAsTextSync([String encoding]); | 181 String readAsTextSync([String encoding]); |
181 | 182 |
182 /** | 183 /** |
183 * Read the entire file contents as lines of text using the give | 184 * Read the entire file contents as lines of text using the give |
184 * [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). | 185 * [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). By default the |
| 186 * encoding is 'UTF-8'. |
185 * | 187 * |
186 * When the operation completes the callback is called. The | 188 * When the operation completes the [readAsLinesHandler] is called |
187 * [onError] function registered on the file object is called if the | 189 * with the resulting string. The [errorHandler] is called if the |
188 * operation fails. | 190 * operation fails. |
189 */ | 191 */ |
190 void readAsLines(String encoding, void callback(List<String> lines)); | 192 void readAsLines(); |
191 | 193 |
192 /** | 194 /** |
193 * Synchronously read the entire file contents as lines of text | 195 * Synchronously read the entire file contents as lines of text |
194 * using the given [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). By | 196 * using the given [encoding] ('UTF-8', 'ISO-8859-1', 'ASCII'). By |
195 * default the encoding is 'UTF-8'. | 197 * default the encoding is 'UTF-8'. |
196 */ | 198 */ |
197 List<String> readAsLinesSync([String encoding]); | 199 List<String> readAsLinesSync([String encoding]); |
198 | 200 |
199 /** | 201 /** |
200 * Get the name of the file. | 202 * Get the name of the file. |
201 */ | 203 */ |
202 String get name(); | 204 String get name(); |
203 | 205 |
204 /** | 206 /** |
| 207 * Sets the handler that gets called when an [exists] operation |
| 208 * completes. |
| 209 */ |
| 210 void set existsHandler(void handler(bool exists)); |
| 211 |
| 212 /** |
| 213 * Sets the handler that gets called when a [create] operation |
| 214 * completes. |
| 215 */ |
| 216 void set createHandler(void handler()); |
| 217 |
| 218 /** |
| 219 * Sets the handler that gets called when a [delete] operation |
| 220 * completes. |
| 221 */ |
| 222 void set deleteHandler(void handler()); |
| 223 |
| 224 /** |
| 225 * Sets the handler that gets called when a [directory] operation |
| 226 * completes. |
| 227 */ |
| 228 void set directoryHandler(void handler(Directory directory)); |
| 229 |
| 230 /** |
| 231 * Sets the handler that gets called when an [open] operation |
| 232 * completes. |
| 233 */ |
| 234 void set openHandler(void handler(RandomAccessFile openedFile)); |
| 235 |
| 236 /** |
| 237 * Set the handler that gets called when a [readAsBytes] operation |
| 238 * completes. |
| 239 */ |
| 240 void set readAsBytesHandler(void handler(List<int> bytes)); |
| 241 |
| 242 /** |
| 243 * Set the handler that gets called when a [readAsText] operation |
| 244 * completes. |
| 245 */ |
| 246 void set readAsTextHandler(void handler(String text)); |
| 247 |
| 248 /** |
| 249 * Set the handler that gets called when a [readAsLines] operation |
| 250 * completes. |
| 251 */ |
| 252 void set readAsLinesHandler(void handler(List<String> lines)); |
| 253 |
| 254 /** |
| 255 * Sets the handler that gets called when a [fullPath] operation |
| 256 * completes. |
| 257 */ |
| 258 void set fullPathHandler(void handler(String path)); |
| 259 |
| 260 /** |
205 * Sets the handler that gets called when errors occur during | 261 * Sets the handler that gets called when errors occur during |
206 * operations on this file. | 262 * operations on this file. |
207 */ | 263 */ |
208 void set onError(void handler(String error)); | 264 void set errorHandler(void handler(String error)); |
209 } | 265 } |
210 | 266 |
211 | 267 |
212 /** | 268 /** |
213 * [RandomAccessFile] provides random access to the data in a | 269 * [RandomAccessFile] provides random access to the data in a |
214 * file. [RandomAccessFile] objects are obtained by calling the | 270 * file. [RandomAccessFile] objects are obtained by calling the |
215 * [:open:] method on a [File] object. | 271 * [:open:] method on a [File] object. |
216 */ | 272 */ |
217 interface RandomAccessFile { | 273 interface RandomAccessFile { |
218 /** | 274 /** |
219 * Close the file. When the file is closed the callback is called. | 275 * Close the file. When the file is closed the [closeHandler] is |
| 276 * called. |
220 */ | 277 */ |
221 void close(void callback()); | 278 void close(); |
222 | 279 |
223 /** | 280 /** |
224 * Synchronously close the file. | 281 * Synchronously close the file. |
225 */ | 282 */ |
226 void closeSync(); | 283 void closeSync(); |
227 | 284 |
228 /** | 285 /** |
229 * Read a byte from the file. When the byte has been read the | 286 * Read a byte from the file. When the byte has been read the |
230 * callback is called with the value. | 287 * [readByteHandler] is called with the value. |
231 */ | 288 */ |
232 void readByte(void callback(int byte)); | 289 void readByte(); |
233 | 290 |
234 /** | 291 /** |
235 * Synchronously read a single byte from the file. | 292 * Synchronously read a single byte from the file. |
236 */ | 293 */ |
237 int readByteSync(); | 294 int readByteSync(); |
238 | 295 |
239 /** | 296 /** |
240 * Read a List<int> from the file. When the list has been read the | 297 * Read a List<int> from the file. When the list has been read the |
241 * callback is called with an integer indicating how much was read. | 298 * [readListHandler] is called with an integer indicating how much |
| 299 * was read. |
242 */ | 300 */ |
243 void readList(List<int> buffer, int offset, int bytes, | 301 void readList(List<int> buffer, int offset, int bytes); |
244 void callback(int read)); | |
245 | 302 |
246 /** | 303 /** |
247 * Synchronously read a List<int> from the file. Returns the number | 304 * Synchronously read a List<int> from the file. Returns the number |
248 * of bytes read. | 305 * of bytes read. |
249 */ | 306 */ |
250 int readListSync(List<int> buffer, int offset, int bytes); | 307 int readListSync(List<int> buffer, int offset, int bytes); |
251 | 308 |
252 /** | 309 /** |
253 * Write a single byte to the file. If the byte cannot be written | 310 * Write a single byte to the file. If the byte cannot be written |
254 * [onError] is called. When all pending write operations have | 311 * the [errorHandler] is called. When all pending write operations |
255 * finished [onNoPendingWrites] is called. | 312 * have finished the [noPendingWriteHandler] is called. |
256 */ | 313 */ |
257 void writeByte(int value); | 314 void writeByte(int value); |
258 | 315 |
259 /** | 316 /** |
260 * Synchronously write a single byte to the file. Returns the | 317 * Synchronously write a single byte to the file. Returns the |
261 * number of bytes successfully written. | 318 * number of bytes successfully written. |
262 */ | 319 */ |
263 int writeByteSync(int value); | 320 int writeByteSync(int value); |
264 | 321 |
265 /** | 322 /** |
266 * Write a List<int> to the file. If the list cannot be written the | 323 * Write a List<int> to the file. If the list cannot be written the |
267 * [onError] is called. When all pending write operations have | 324 * [errorHandler] is called. When all pending write operations have |
268 * finished [onNoPendingWrites] is called. | 325 * finished the [noPendingWriteHandler] is called. |
269 */ | 326 */ |
270 void writeList(List<int> buffer, int offset, int bytes); | 327 void writeList(List<int> buffer, int offset, int bytes); |
271 | 328 |
272 /** | 329 /** |
273 * Synchronously write a List<int> to the file. Returns the number | 330 * Synchronously write a List<int> to the file. Returns the number |
274 * of bytes successfully written. | 331 * of bytes successfully written. |
275 */ | 332 */ |
276 int writeListSync(List<int> buffer, int offset, int bytes); | 333 int writeListSync(List<int> buffer, int offset, int bytes); |
277 | 334 |
278 /** | 335 /** |
279 * Write a string to the file. If the string cannot be written the | 336 * Write a string to the file. If the string cannot be written the |
280 * [onError] is called. When all pending write operations have | 337 * [errorHandler] is called. When all pending write operations have |
281 * finished [onNoPendingWrites] is called. | 338 * finished the [noPendingWriteHandler] is called. |
282 */ | 339 */ |
283 // TODO(ager): writeString should take an encoding. | 340 // TODO(ager): writeString should take an encoding. |
284 void writeString(String string); | 341 void writeString(String string); |
285 | 342 |
286 /** | 343 /** |
287 * Synchronously write a single string to the file. Returns the number | 344 * Synchronously write a single string to the file. Returns the number |
288 * of characters successfully written. | 345 * of characters successfully written. |
289 */ | 346 */ |
290 // TODO(ager): writeStringSync should take an encoding. | 347 // TODO(ager): writeStringSync should take an encoding. |
291 int writeStringSync(String string); | 348 int writeStringSync(String string); |
292 | 349 |
293 /** | 350 /** |
294 * Get the current byte position in the file. When the operation | 351 * Get the current byte position in the file. When the operation |
295 * completes the callback is called with the position. | 352 * completes the [positionHandler] is called with the position. |
296 */ | 353 */ |
297 void position(void callback(int position)); | 354 void position(); |
298 | 355 |
299 /** | 356 /** |
300 * Synchronously get the current byte position in the file. | 357 * Synchronously get the current byte position in the file. |
301 */ | 358 */ |
302 int positionSync(); | 359 int positionSync(); |
303 | 360 |
304 /** | 361 /** |
305 * Set the byte position in the file. When the operation completes | 362 * Set the byte position in the file. When the operation completes |
306 * the callback is called. | 363 * the [setPositionHandler] is called. |
307 */ | 364 */ |
308 void setPosition(int position, void callback()); | 365 void setPosition(int position); |
309 | 366 |
310 /** | 367 /** |
311 * Synchronously set the byte position in the file. | 368 * Synchronously set the byte position in the file. |
312 */ | 369 */ |
313 void setPositionSync(int position); | 370 void setPositionSync(int position); |
314 | 371 |
315 /** | 372 /** |
316 * Truncate (or extend) the file to [length] bytes. When the | 373 * Truncate (or extend) the file to [length] bytes. When the |
317 * operation completes successfully the callback is called. | 374 * operation completes successfully the [truncateHandler] is called. |
318 */ | 375 */ |
319 void truncate(int length, void callback()); | 376 void truncate(int length); |
320 | 377 |
321 /** | 378 /** |
322 * Synchronously truncate (or extend) the file to [length] bytes. | 379 * Synchronously truncate (or extend) the file to [length] bytes. |
323 */ | 380 */ |
324 void truncateSync(int length); | 381 void truncateSync(int length); |
325 | 382 |
326 /** | 383 /** |
327 * Get the length of the file. When the operation completes the | 384 * Get the length of the file. When the operation completes the |
328 * callback is called with the length. | 385 * [lengthHandler] is called with the length. |
329 */ | 386 */ |
330 void length(void callback(int length)); | 387 void length(); |
331 | 388 |
332 /** | 389 /** |
333 * Synchronously get the length of the file. | 390 * Synchronously get the length of the file. |
334 */ | 391 */ |
335 int lengthSync(); | 392 int lengthSync(); |
336 | 393 |
337 /** | 394 /** |
338 * Flush the contents of the file to disk. The callback is | 395 * Flush the contents of the file to disk. The [flushHandler] is |
339 * called when the flush operation completes. | 396 * called when the flush operation completes. |
340 */ | 397 */ |
341 void flush(void callback()); | 398 void flush(); |
342 | 399 |
343 /** | 400 /** |
344 * Synchronously flush the contents of the file to disk. | 401 * Synchronously flush the contents of the file to disk. |
345 */ | 402 */ |
346 void flushSync(); | 403 void flushSync(); |
347 | 404 |
348 /** | 405 /** |
349 * Get the name of the file. | 406 * Get the name of the file. |
350 */ | 407 */ |
351 String get name(); | 408 String get name(); |
352 | 409 |
353 /** | 410 /** |
| 411 * Sets the handler that gets called when a [close] operation |
| 412 * completes. |
| 413 */ |
| 414 void set closeHandler(void handler()); |
| 415 |
| 416 /** |
| 417 * Sets the handler that gets called when a [readByte] operation |
| 418 * completes. |
| 419 */ |
| 420 void set readByteHandler(void handler(int byte)); |
| 421 |
| 422 /** |
| 423 * Sets the handler that gets called when a [readList] operation |
| 424 * completes. |
| 425 */ |
| 426 void set readListHandler(void handler(int read)); |
| 427 |
| 428 /** |
354 * Sets the handler that gets called when there are no more write | 429 * Sets the handler that gets called when there are no more write |
355 * operations pending for this file. | 430 * operations pending for this file. |
356 */ | 431 */ |
357 void set onNoPendingWrites(void handler()); | 432 void set noPendingWriteHandler(void handler()); |
| 433 |
| 434 /** |
| 435 * Sets the handler that gets called when a [position] operation |
| 436 * completes. |
| 437 */ |
| 438 void set positionHandler(void handler(int position)); |
| 439 |
| 440 /** |
| 441 * Sets the handler that gets called when a [setPosition] operation |
| 442 * completes. |
| 443 */ |
| 444 void set setPositionHandler(void handler()); |
| 445 |
| 446 /** |
| 447 * Sets the handler that gets called when a [truncate] operation |
| 448 * completes. |
| 449 */ |
| 450 void set truncateHandler(void handler()); |
| 451 |
| 452 /** |
| 453 * Sets the handler that gets called when a [length] operation |
| 454 * completes. |
| 455 */ |
| 456 void set lengthHandler(void handler(int length)); |
| 457 |
| 458 /** |
| 459 * Sets the handler that gets called when a [flush] operation |
| 460 * completes. |
| 461 */ |
| 462 void set flushHandler(void handler()); |
358 | 463 |
359 /** | 464 /** |
360 * Sets the handler that gets called when errors occur when | 465 * Sets the handler that gets called when errors occur when |
361 * operating on this file. | 466 * operating on this file. |
362 */ | 467 */ |
363 void set onError(void handler(String error)); | 468 void set errorHandler(void handler(String error)); |
364 } | 469 } |
365 | 470 |
366 | 471 |
367 class FileIOException implements Exception { | 472 class FileIOException implements Exception { |
368 const FileIOException([String this.message = ""]); | 473 const FileIOException([String this.message = ""]); |
369 String toString() => "FileIOException: $message"; | 474 String toString() => "FileIOException: $message"; |
370 final String message; | 475 final String message; |
371 } | 476 } |
OLD | NEW |