1 /// Case insensitive path functions
2 module nwnlibd.path;
3 
4 import std.exception;
5 
6 ///
7 string buildPathCI(T...)(in string basePath, T subFiles){
8 	import std.file;
9 	import std.path;
10 	import std.string: toUpper;
11 
12 	enforce(basePath.exists, "basePath '"~basePath~"' does not exist");
13 	string path = basePath;
14 
15 	foreach(subFile ; subFiles){
16 		//Case is correct, cool !
17 		if(buildPath(path, subFile).exists){
18 			path = buildPath(path, subFile);
19 		}
20 		//Most likely only the extension is fucked up
21 		else if(buildPath(path, subFile.stripExtension ~ subFile.extension.toUpper).exists){
22 			path = buildPath(path, subFile.stripExtension ~ subFile.extension.toUpper);
23 		}
24 		//Perform full scan of the directory
25 		else{
26 			bool bFound = false;
27 			foreach(file ; path.dirEntries(SpanMode.shallow)){
28 				if(filenameCmp!(CaseSensitive.no)(file.baseName, subFile) == 0){
29 					bFound = true;
30 					path = file.name;
31 					break;
32 				}
33 			}
34 			if(!bFound)
35 				path = buildPath(path, subFile);
36 		}
37 	}
38 	return path;
39 }
40 
41 ///
42 unittest{
43 	version(Posix){
44 		// First directory must exist and case must be correct
45 		assertThrown(buildPathCI("UNITTEST", "PLC_MC_BALCONY3.MDB"));
46 
47 		// Fix case in file paths
48 		assert(buildPathCI(".", "unittest", "PLC_MC_BALCONY3.MDB") == "./unittest/PLC_MC_BALCONY3.MDB");
49 		assert(buildPathCI(".", "UNITTEST", "PLC_MC_BALCONY3.mdb") == "./unittest/PLC_MC_BALCONY3.MDB");
50 		assert(buildPathCI(".", "unittest", "plc_mc_balcony3.mdb") == "./unittest/PLC_MC_BALCONY3.MDB");
51 		assert(buildPathCI(".", "UNITTEST", "pLc_mc_balConY3.mdB") == "./unittest/PLC_MC_BALCONY3.MDB");
52 
53 		// Non existing files keep the provided case
54 		assert(buildPathCI(".", "Unittest", "YoLo.pNg") == "./unittest/YoLo.pNg");
55 	}
56 }
57