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