1 /******************************************************************************* 2 3 copyright: Copyright (c) 2007 Tango. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Jul 2007: Initial version 8 9 author: Lars Ivar, Kris 10 11 *******************************************************************************/ 12 13 module tango.io.vfs.model.Vfs; 14 15 16 17 private import tango.time.Time : Time; 18 19 private import tango.io.model.IConduit; 20 21 private import tango.io.model.IFile : FileInfo; 22 23 /******************************************************************************* 24 25 alias FileInfo for filtering 26 27 *******************************************************************************/ 28 29 alias FileInfo VfsFilterInfo; 30 alias VfsFilterInfo* VfsInfo; 31 32 // return false to exclude something 33 alias bool delegate(VfsInfo) VfsFilter; 34 35 36 /******************************************************************************* 37 38 *******************************************************************************/ 39 40 struct VfsStats 41 { 42 ulong bytes; // byte count of files 43 size_t files, // number of files 44 folders; // number of folders 45 } 46 47 /******************************************************************************* 48 49 ******************************************************************************/ 50 51 interface VfsHost : VfsFolder 52 { 53 /********************************************************************** 54 55 Add a child folder. The child cannot 'overlap' with others 56 in the tree of the same type. Circular references across a 57 tree of virtual folders are detected and trapped. 58 59 The second argument represents an optional name that the 60 mount should be known as, instead of the name exposed by 61 the provided folder (it is not an alias). 62 63 **********************************************************************/ 64 65 VfsHost mount (VfsFolder folder, const(char)[] name=null); 66 67 /*********************************************************************** 68 69 Add a set of child folders. The children cannot 'overlap' 70 with others in the tree of the same type. Circular references 71 are detected and trapped. 72 73 ***********************************************************************/ 74 75 VfsHost mount (VfsFolders group); 76 77 /********************************************************************** 78 79 Unhook a child folder 80 81 **********************************************************************/ 82 83 VfsHost dismount (VfsFolder folder); 84 85 /********************************************************************** 86 87 Add a symbolic link to another file. These are referenced 88 by file() alone, and do not show up in tree traversals 89 90 **********************************************************************/ 91 92 VfsHost map (VfsFile target, const(char)[] name); 93 94 /*********************************************************************** 95 96 Add a symbolic link to another folder. These are referenced 97 by folder() alone, and do not show up in tree traversals 98 99 ***********************************************************************/ 100 101 VfsHost map (VfsFolderEntry target, const(char)[] name); 102 } 103 104 105 /******************************************************************************* 106 107 Supports a model a bit like CSS selectors, where a selection 108 of operands is made before applying some operation. For example: 109 --- 110 // count of files in this folder 111 auto count = folder.self.files; 112 113 // accumulated file byte-count 114 auto bytes = folder.self.bytes; 115 116 // a group of one folder (itself) 117 auto folders = folder.self; 118 --- 119 120 The same approach is used to select the subtree descending from 121 a folder: 122 --- 123 // count of files in this tree 124 auto count = folder.tree.files; 125 126 // accumulated file byte-count 127 auto bytes = folder.tree.bytes; 128 129 // the group of child folders 130 auto folders = folder.tree; 131 --- 132 133 Filtering can be applied to the tree resulting in a sub-group. 134 Group operations remain applicable. Note that various wildcard 135 characters may be used in the filtering: 136 --- 137 // select a subset of the resultant tree 138 auto folders = folder.tree.subset("install"); 139 140 // get total file bytes for a tree subset, using wildcards 141 auto bytes = folder.tree.subset("foo*").bytes; 142 --- 143 144 Files are selected from a set of folders in a similar manner: 145 --- 146 // files called "readme.txt" in this folder 147 auto count = folder.self.catalog("readme.txt").files; 148 149 // files called "read*.*" in this tree 150 auto count = folder.tree.catalog("read*.*").files; 151 152 // all txt files belonging to folders starting with "ins" 153 auto count = folder.tree.subset("ins*").catalog("*.txt").files; 154 155 // custom-filtered files within a subtree 156 auto count = folder.tree.catalog(&filter).files; 157 --- 158 159 Sets of folders and files support iteration via foreach: 160 --- 161 foreach (folder; root.tree) 162 Stdout.formatln ("folder name:{}", folder.name); 163 164 foreach (folder; root.tree.subset("ins*")) 165 Stdout.formatln ("folder name:{}", folder.name); 166 167 foreach (file; root.tree.catalog("*.d")) 168 Stdout.formatln ("file name:{}", file.name); 169 --- 170 171 Creating and opening a sub-folder is supported in a similar 172 manner, where the single instance is 'selected' before the 173 operation is applied. Open differs from create in that the 174 folder must exist for the former: 175 --- 176 root.folder("myNewFolder").create; 177 178 root.folder("myExistingFolder").open; 179 --- 180 181 File manipulation is handled in much the same way: 182 --- 183 root.file("myNewFile").create; 184 185 auto source = root.file("myExistingFile"); 186 root.file("myCopiedFile").copy(source); 187 --- 188 189 The principal benefits of these approaches are twofold: 1) it 190 turns out to be notably more efficient in terms of traversal, and 191 2) there's no casting required, since there is a clean separation 192 between files and folders. 193 194 See VfsFile for more information on file handling 195 196 *******************************************************************************/ 197 198 interface VfsFolder 199 { 200 /*********************************************************************** 201 202 Return a short name 203 204 ***********************************************************************/ 205 206 @property const(char)[] name (); 207 208 /*********************************************************************** 209 210 Return a long name 211 212 ***********************************************************************/ 213 214 string toString (); 215 216 /*********************************************************************** 217 218 Return a contained file representation 219 220 ***********************************************************************/ 221 222 @property VfsFile file (const(char)[] path); 223 224 /*********************************************************************** 225 226 Return a contained folder representation 227 228 ***********************************************************************/ 229 230 @property VfsFolderEntry folder (const(char)[] path); 231 232 /*********************************************************************** 233 234 Returns a folder set containing only this one. Statistics 235 are inclusive of entries within this folder only 236 237 ***********************************************************************/ 238 239 @property VfsFolders self (); 240 241 /*********************************************************************** 242 243 Returns a subtree of folders. Statistics are inclusive of 244 files within this folder and all others within the tree 245 246 ***********************************************************************/ 247 248 @property VfsFolders tree (); 249 250 /*********************************************************************** 251 252 Iterate over the set of immediate child folders. This is 253 useful for reflecting the hierarchy 254 255 ***********************************************************************/ 256 257 int opApply (scope int delegate(ref VfsFolder) dg); 258 259 /*********************************************************************** 260 261 Clear all content from this folder and subordinates 262 263 ***********************************************************************/ 264 265 VfsFolder clear (); 266 267 /*********************************************************************** 268 269 Is folder writable? 270 271 ***********************************************************************/ 272 273 @property bool writable (); 274 275 /*********************************************************************** 276 277 Close and/or synchronize changes made to this folder. Each 278 driver should take advantage of this as appropriate, perhaps 279 combining multiple files together, or possibly copying to a 280 remote location 281 282 ***********************************************************************/ 283 284 VfsFolder close (bool commit = true); 285 286 /*********************************************************************** 287 288 A folder is being added or removed from the hierarchy. Use 289 this to test for validity (or whatever) and throw exceptions 290 as necessary 291 292 ***********************************************************************/ 293 294 void verify (VfsFolder folder, bool mounting); 295 296 //VfsFolder copy(VfsFolder from, const(char)[] to); 297 //VfsFolder move(Entry from, VfsFolder toFolder, const(char)[] toName); 298 //const(char)[] absolutePath(const(char)[] path); 299 } 300 301 302 /******************************************************************************* 303 304 Operations upon a set of folders 305 306 *******************************************************************************/ 307 308 interface VfsFolders 309 { 310 /*********************************************************************** 311 312 Iterate over the set of contained VfsFolder instances 313 314 ***********************************************************************/ 315 316 int opApply (scope int delegate(ref VfsFolder) dg); 317 318 /*********************************************************************** 319 320 Return the number of files 321 322 ***********************************************************************/ 323 324 @property size_t files (); 325 326 /*********************************************************************** 327 328 Return the number of folders 329 330 ***********************************************************************/ 331 332 @property size_t folders (); 333 334 /*********************************************************************** 335 336 Return the total number of entries (files + folders) 337 338 ***********************************************************************/ 339 340 @property size_t entries (); 341 342 /*********************************************************************** 343 344 Return the total size of contained files 345 346 ***********************************************************************/ 347 348 @property ulong bytes (); 349 350 /*********************************************************************** 351 352 Return a subset of folders matching the given pattern 353 354 ***********************************************************************/ 355 356 VfsFolders subset (const(char)[] pattern); 357 358 /*********************************************************************** 359 360 Return a set of files matching the given pattern 361 362 ***********************************************************************/ 363 364 @property VfsFiles catalog (const(char)[] pattern); 365 366 /*********************************************************************** 367 368 Return a set of files matching the given filter 369 370 ***********************************************************************/ 371 372 @property VfsFiles catalog (VfsFilter filter = null); 373 } 374 375 376 /******************************************************************************* 377 378 Operations upon a set of files 379 380 *******************************************************************************/ 381 382 interface VfsFiles 383 { 384 /*********************************************************************** 385 386 Iterate over the set of contained VfsFile instances 387 388 ***********************************************************************/ 389 390 int opApply (scope int delegate(ref VfsFile) dg); 391 392 /*********************************************************************** 393 394 Return the total number of entries 395 396 ***********************************************************************/ 397 398 @property size_t files (); 399 400 /*********************************************************************** 401 402 Return the total size of all files 403 404 ***********************************************************************/ 405 406 @property ulong bytes (); 407 } 408 409 410 /******************************************************************************* 411 412 A specific file representation 413 414 *******************************************************************************/ 415 416 interface VfsFile 417 { 418 /*********************************************************************** 419 420 Return a short name 421 422 ***********************************************************************/ 423 424 @property const(char)[] name (); 425 426 /********************************************************************** 427 428 Return a long name 429 430 ***********************************************************************/ 431 432 immutable(char)[] toString (); 433 434 /*********************************************************************** 435 436 Does this file exist? 437 438 ***********************************************************************/ 439 440 @property bool exists (); 441 442 /*********************************************************************** 443 444 Return the file size 445 446 ***********************************************************************/ 447 448 @property ulong size (); 449 450 /*********************************************************************** 451 452 Create and copy the given source 453 454 ***********************************************************************/ 455 456 VfsFile copy (VfsFile source); 457 458 /*********************************************************************** 459 460 Create and copy the given source, and remove the source 461 462 ***********************************************************************/ 463 464 VfsFile move (VfsFile source); 465 466 /*********************************************************************** 467 468 Create a new file instance 469 470 ***********************************************************************/ 471 472 VfsFile create (); 473 474 /*********************************************************************** 475 476 Create a new file instance and populate with stream 477 478 ***********************************************************************/ 479 480 VfsFile create (InputStream stream); 481 482 /*********************************************************************** 483 484 Remove this file 485 486 ***********************************************************************/ 487 488 VfsFile remove (); 489 490 /*********************************************************************** 491 492 Return the input stream. Don't forget to close it 493 494 ***********************************************************************/ 495 496 @property InputStream input (); 497 498 /*********************************************************************** 499 500 Return the output stream. Don't forget to close it 501 502 ***********************************************************************/ 503 504 @property OutputStream output (); 505 506 /*********************************************************************** 507 508 Duplicate this entry 509 510 ***********************************************************************/ 511 512 @property VfsFile dup (); 513 514 /*********************************************************************** 515 516 The modified time of the folder 517 518 ***********************************************************************/ 519 520 @property Time modified (); 521 } 522 523 524 /******************************************************************************* 525 526 Handler for folder operations. Needs some work ... 527 528 *******************************************************************************/ 529 530 interface VfsFolderEntry 531 { 532 /*********************************************************************** 533 534 Open a folder 535 536 ***********************************************************************/ 537 538 VfsFolder open (); 539 540 /*********************************************************************** 541 542 Create a new folder 543 544 ***********************************************************************/ 545 546 VfsFolder create (); 547 548 /*********************************************************************** 549 550 Test to see if a folder exists 551 552 ***********************************************************************/ 553 554 @property bool exists (); 555 } 556 557 558 /******************************************************************************* 559 560 Would be used for things like zip files, where the 561 implementation mantains the contents in memory or on disk, and where 562 the actual zip file isn't/shouldn't be written until one is finished 563 filling it up (for zip due to inefficient file format). 564 565 *******************************************************************************/ 566 567 interface VfsSync 568 { 569 /*********************************************************************** 570 571 ***********************************************************************/ 572 573 VfsFolder sync (); 574 } 575