1 /* 2 Copyright (c) 2016-2021 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module dlib.filesystem.stdwindowsdir; 30 31 import std..string; 32 import std.conv; 33 import std.range; 34 import core.stdc..string; 35 import core.stdc.wchar_; 36 37 version(Windows) 38 { 39 import core.sys.windows.windows; 40 } 41 42 import dlib.core.memory; 43 import dlib.filesystem.filesystem; 44 import dlib.text.utf16; 45 46 version(Windows): 47 48 string unmanagedStrFromCStrW(wchar* cstr) 49 { 50 return cast(string)convertUTF16ztoUTF8(cstr); 51 } 52 53 class StdWindowsDirEntryRange: InputRange!(DirEntry) 54 { 55 HANDLE hFind = INVALID_HANDLE_VALUE; 56 WIN32_FIND_DATAW findData; 57 DirEntry frontEntry; 58 bool _empty = false; 59 wchar* path; 60 bool initialized = false; 61 62 this(wchar* cwstr) 63 { 64 this.path = cwstr; 65 } 66 67 ~this() 68 { 69 if (frontEntry.name.length) 70 Delete(frontEntry.name); 71 72 close(); 73 } 74 75 import std.stdio; 76 77 bool advance() 78 { 79 bool success = false; 80 81 if (frontEntry.name.length) 82 Delete(frontEntry.name); 83 84 if (!initialized) 85 { 86 hFind = FindFirstFileW(path, &findData); 87 initialized = true; 88 if (hFind != INVALID_HANDLE_VALUE) 89 success = true; 90 91 string name = unmanagedStrFromCStrW(findData.cFileName.ptr); 92 if (name == "." || name == "..") 93 { 94 success = false; 95 Delete(name); 96 } 97 else 98 { 99 bool isDir = cast(bool)(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 100 bool isFile = !isDir; 101 frontEntry = DirEntry(name, isFile, isDir); 102 } 103 } 104 105 if (!success && hFind != INVALID_HANDLE_VALUE) 106 { 107 string name; 108 while(!success) 109 { 110 auto r = FindNextFileW(hFind, &findData); 111 if (!r) 112 break; 113 114 name = unmanagedStrFromCStrW(findData.cFileName.ptr); 115 if (name != "." && name != "..") 116 success = true; 117 else 118 Delete(name); 119 } 120 121 if (success) 122 { 123 bool isDir = cast(bool)(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 124 bool isFile = !isDir; 125 frontEntry = DirEntry(name, isFile, isDir); 126 } 127 } 128 129 if (!success) 130 { 131 FindClose(hFind); 132 hFind = INVALID_HANDLE_VALUE; 133 } 134 135 return success; 136 } 137 138 override DirEntry front() 139 { 140 return frontEntry; 141 } 142 143 override void popFront() 144 { 145 _empty = !advance(); 146 } 147 148 override DirEntry moveFront() 149 { 150 _empty = !advance(); 151 return frontEntry; 152 } 153 154 override bool empty() 155 { 156 return _empty; 157 } 158 159 int opApply(scope int delegate(DirEntry) dg) 160 { 161 int result = 0; 162 163 for (size_t i = 0; !empty; i++) 164 { 165 popFront(); 166 if (!empty()) 167 result = dg(frontEntry); 168 169 if (result != 0) 170 break; 171 } 172 173 return result; 174 } 175 176 int opApply(scope int delegate(size_t, DirEntry) dg) 177 { 178 int result = 0; 179 180 for (size_t i = 0; !empty; i++) 181 { 182 popFront(); 183 if (!empty()) 184 result = dg(i, frontEntry); 185 186 if (result != 0) 187 break; 188 } 189 190 return result; 191 } 192 193 void reset() 194 { 195 close(); 196 } 197 198 void close() 199 { 200 if (hFind != INVALID_HANDLE_VALUE) 201 { 202 FindClose(hFind); 203 hFind = INVALID_HANDLE_VALUE; 204 } 205 initialized = false; 206 _empty = false; 207 } 208 } 209 210 class StdWindowsDirectory: Directory 211 { 212 StdWindowsDirEntryRange drange; 213 wchar* path; 214 215 this(wchar* cwstr) 216 { 217 path = cwstr; 218 drange = New!StdWindowsDirEntryRange(path); 219 } 220 221 void close() 222 { 223 drange.close(); 224 } 225 226 StdWindowsDirEntryRange contents() 227 { 228 if (drange) 229 drange.reset(); 230 return drange; 231 } 232 233 ~this() 234 { 235 Delete(drange); 236 drange = null; 237 Delete(path); 238 } 239 }