1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../shared/a_modes.inc}
16 // database of file hashes (md5)
19 interface
21 uses
26 type
28 public
38 private
39 type
46 // used in directory scanner
50 private
57 private
63 public
67 // doesn't clear base path
70 // (re)scans base path and all its subdirs
71 // returns `true` if db was changed
72 // you'd better call it after loading a database
75 // those throws
77 // this clears existing data
80 // returns file name relative to base path or empty string
82 // returns `true` if something was changed
83 // name is relative to base
88 implementation
92 //result := joaatHashPtr(@k, sizeof(TMD5Digest));
93 //k8: use first 4 bytes of k as a hash instead? it should be good enough
96 class function THashKeyMD5.equ (const a, b: TMD5Digest): Boolean; inline; begin result := MD5Match(a, b); end;
100 //==========================================================================
101 //
102 // fixSlashes
103 //
104 // fixes all slashes; adds a final one too
105 //
106 //==========================================================================
108 var
110 begin
113 if (addFinal) and (length(result) > 0) and (result[length(result)] <> '/') then result := result+'/';
117 //==========================================================================
118 //
119 // TFileHashDB.Create
120 //
121 //==========================================================================
123 begin
126 begin
137 //==========================================================================
138 //
139 // TFileHashDB.Destroy
140 //
141 //==========================================================================
143 begin
152 //==========================================================================
153 //
154 // TFileHashDB.clear
155 //
156 // doesn't clear base path
157 //
158 //==========================================================================
160 begin
168 //==========================================================================
169 //
170 // TFileHashDB.saveTo
171 //
172 //==========================================================================
174 var
177 begin
183 begin
193 //==========================================================================
194 //
195 // TFileHashDB.loadFrom
196 //
197 //==========================================================================
199 var
204 begin
206 try
212 if (count < 0) or (count > 1024*1024) then raise Exception.Create('invalid database file count');
214 begin
227 except
228 begin
236 //==========================================================================
237 //
238 // TFileHashDB.removeIndex
239 //
240 //==========================================================================
242 begin
243 if (idx < 0) or (idx > High(mFileList)) or (length(mFileList[idx].name) = 0) then exit; // nothing to do
252 //==========================================================================
253 //
254 // TFileHashDB.allocIndex
255 //
256 //==========================================================================
258 begin
261 begin
263 end
264 else
265 begin
272 //==========================================================================
273 //
274 // TFileHashDB.scanDir
275 //
276 //==========================================================================
278 var
287 begin
289 try
290 repeat
292 begin
293 // directory
295 end
297 begin
298 // file
300 // build internal file name
303 // find file in hash
305 // check if we already have this file
308 begin
309 // do we need to update this file?
311 begin
312 needUpdate :=
315 end
316 else
317 begin
320 // recalc md5 and update file entry, if necessary
322 begin
324 try
327 except
330 begin
332 // remove old hash -> index mapping
334 // update
344 end
345 else
346 begin
347 // update failed, remove this entry
351 end
352 else
353 begin
356 end
357 else
358 begin
359 // remove this file if we don't have it anymore
363 end
364 else
365 begin
367 // build internal file name
370 // find file in hash
372 begin
378 finally
384 //==========================================================================
385 //
386 // TFileHashDB.scanFiles
387 //
388 // scans base path and all its subdirs
389 // returns `true` if db was changed
390 //
391 //==========================================================================
393 var
395 begin
399 // remove all unseen files
402 begin
409 //==========================================================================
410 //
411 // TFileHashDB.findByHash
412 //
413 // returns file name relative to base path or empty string
414 //
415 //==========================================================================
417 var
419 begin
425 //==========================================================================
426 //
427 // TFileHashDB.addWithHash
428 //
429 // returns `true` if something was changed
430 // name is relative to base
431 //
432 //==========================================================================
434 var
440 begin
442 if (length(relname) > length(mBasePath)) and strEquCI1251(mBasePath, Copy(relname, 1, length(mBasePath))) then Delete(relname, 1, Length(mBasePath));
446 // get age
449 // get size
455 // find old file, if any
458 // check for changes
460 begin
461 if (mFileList[idx].size = size) and (mFileList[idx].age = age) and (MD5Match(mFileList[idx].hash, md5)) then exit;