1 /** 2 * Defines the FilePath class, which stores default resource paths, and handles path manipulation. 3 */ 4 module utility.filepath; 5 import utility.output; 6 7 static import std.file, std.path; 8 import std.stdio; 9 10 /** 11 * A class which stores default resource paths, and handles path manipulation. 12 */ 13 final class FilePath 14 { 15 public: 16 /** 17 * The path to the resources home folder. 18 */ 19 enum ResourceHome = ".."; 20 21 /** 22 * Paths to the different resource files. 23 */ 24 enum Resources : string 25 { 26 Materials = ResourceHome ~ "/Materials", 27 Meshes = ResourceHome ~ "/Meshes", 28 Textures = ResourceHome ~ "/Textures", 29 Scripts = ResourceHome ~ "/Scripts", 30 Prefabs = ResourceHome ~ "/Prefabs", 31 Objects = ResourceHome ~ "/Objects", 32 Shaders = ResourceHome ~ "/Shaders", 33 UI = ResourceHome ~ "/UI", 34 ConfigDir = ResourceHome ~ "/Config", 35 ConfigFile = ConfigDir ~ "/Config.yml", 36 InputBindings = ConfigDir ~ "/Input.yml", 37 } 38 39 /** 40 * Get all files in a given directory. 41 */ 42 final static FilePath[] scanDirectory( string path, string pattern = "" ) 43 { 44 // Get absolute path to folder 45 string safePath = std.path.buildNormalizedPath( std.path.absolutePath( path ) ); 46 47 if( !std.file.exists( safePath ) ) 48 { 49 log( OutputType.Info, path, " does not exist." ); 50 return []; 51 } 52 53 // Start array 54 auto files = new FilePath[ 1 ]; 55 uint filesFound = 0; 56 57 // Add file to array 58 void handleFile( string name ) 59 { 60 if( filesFound == files.length ) 61 files.length *= 2; 62 63 files[ filesFound++ ] = new FilePath( name ); 64 } 65 66 // Find files 67 if( pattern.length ) 68 foreach( name; std.file.dirEntries( safePath, pattern, std.file.SpanMode.breadth ) ) 69 handleFile( name ); 70 else 71 foreach( name; std.file.dirEntries( safePath, std.file.SpanMode.breadth ) ) 72 handleFile( name ); 73 74 files.length = filesFound; 75 76 return files; 77 } 78 79 /// The full path to the file. 80 final @property string fullPath() { return _fullPath; } 81 /// The relative path from the executable to the file. 82 final @property string relativePath() 83 { 84 if( !_relativePath ) 85 _relativePath = std.path.relativePath( _fullPath ); 86 87 return _relativePath; 88 } 89 /// The name of the file with its extension. 90 final @property string fileName() 91 { 92 if( !_fileName ) 93 _fileName = std.path.baseName( _fullPath ); 94 95 return _fileName; 96 } 97 /// The name of the file without its extension. 98 final @property string baseFileName() 99 { 100 if( !_baseFileName ) 101 _baseFileName = std.path.stripExtension( fileName ); 102 103 return _baseFileName; 104 } 105 /// The path to the directory containing the file. 106 final @property string directory() 107 { 108 if( !_directory ) 109 _directory = std.path.dirName( _fullPath ); 110 111 return _directory; 112 } 113 /// The extensino of the file. 114 final @property ref string extension() 115 { 116 if( !_extension ) 117 _extension = std.path.extension( _fullPath ); 118 119 return _extension; 120 } 121 /// Converts to a std.stdio.File 122 final File* toFile( string mode = "r" ) 123 { 124 if( !file ) 125 file = new File( _fullPath, mode ); 126 127 return file; 128 } 129 130 final string getContents() 131 { 132 return cast(string)std.file.read(_fullPath); 133 } 134 135 /** 136 * Create an instance based on a given file path. 137 */ 138 this( string path ) 139 { 140 if( std.file.isFile( path ) ) 141 _fullPath = std.path.buildNormalizedPath( std.path.absolutePath( path ) ); 142 else 143 throw new Exception( "Invalid file name." ); 144 } 145 146 /** 147 * Shuts down the File if it was instantiated. 148 */ 149 ~this() 150 { 151 if( file && file.isOpen ) 152 file.close(); 153 } 154 155 private: 156 string _fullPath; 157 string _relativePath; 158 string _fileName; 159 string _baseFileName; 160 string _directory; 161 string _extension; 162 File* file; 163 } 164 165 unittest 166 { 167 import std.stdio; 168 writeln( "Dash FilePath properties unittest" ); 169 170 auto fp = new FilePath( FilePath.Resources.ConfigFile ); 171 172 assert( fp.fileName == "Config.yml", "FilePath.fileName error." ); 173 assert( fp.baseFileName == "Config", "FilePath.baseFileName error." ); 174 assert( fp.extension == ".yml", "FilePath.extension error." ); 175 }