1 module isodi.internal; 2 3 import std.string; 4 5 6 package @safe: 7 8 9 /// Iterate on file ancestors, starting from and including the requested file and ending on the root. 10 struct DeepAncestors { 11 12 const string path; 13 14 int opApply(int delegate(string) @trusted dg) { 15 16 auto dir = path[]; 17 18 while (dir.length) { 19 20 // Remove trailing slashes 21 dir = dir.stripRight("/"); 22 23 // Yield the content 24 auto result = dg(dir); 25 if (result) return result; 26 27 // Get the position on which the segment ends 28 auto segmentEnd = dir.lastIndexOf("/"); 29 30 // Stop if this is the last segment 31 if (segmentEnd == -1) break; 32 33 // Remove last path segment 34 dir = dir[0 .. segmentEnd]; 35 36 } 37 38 // Push empty path 39 return dg(""); 40 41 } 42 43 } 44 45 /// Iterate on file ancestors starting from root, ending on and including the file itself. 46 struct Ancestors { 47 48 const wstring path; 49 50 int opApply(int delegate(wstring) @trusted dg) { 51 52 wstring current; 53 54 auto result = dg(""w); 55 if (result) return result; 56 57 // Check each value 58 foreach (ch; path) { 59 60 // Encountered a path separator 61 if (ch == '/' || ch == '\\') { 62 63 // Yield the current values 64 result = dg(current); 65 if (result) return result; 66 current ~= "/"; 67 68 } 69 70 // Add the character 71 else current ~= ch; 72 73 } 74 75 // Yield the full path 76 if (current.length && current[$-1] != '/') { 77 78 result = dg(current); 79 return result; 80 81 } 82 83 return 0; 84 85 } 86 87 }