Menu

[r2337]: / trunk / Src / UUtils.pas  Maximize  Restore  History

Download this file

338 lines (291 with data), 10.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
{
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/
*
* Copyright (C) 2005-2012, Peter Johnson (www.delphidabbler.com).
*
* $Rev$
* $Date$
*
* General utility routines.
}
unit UUtils;
interface
uses
// Delphi
SysUtils, Classes;
/// <summary>Gets the OS time stamp for a file.</summary>
/// <param name="FileName">string [in] Name of file.</param>
/// <returns>Integer. Required OS time stamp or -1 if file does not exist.
/// </returns>
function FileAge(const FileName: string): Integer;
/// <summary>Deletes all files in a directory that match a wildcard.</summary>
/// <param name="Dir">string [in] Directory containing files to be deleted.
/// </param>
/// <param name="Wildcard">string [in] Wildcard specifying files to be deleted.
/// *.* assumed if WildCard=''.</param>
/// <returns>Integer. Number of files deleted.</returns>
/// <remarks>Sub-directories and their files are ignored.</remarks>
function DeleteFiles(const Dir, Wildcard: string): Integer;
/// <summary>Ensures that a folder and all its subfolder exist.</summary>
/// <param name="Folder">string [in] Fully specified name of folder.</param>
/// <remarks>Any folder that does not exist is created.</remarks>
procedure EnsureFolders(const Folder: string);
/// <summary>Gets a list of the files and sub-directories of a directory that
/// match a wild card.</summary>
/// <param name="Dir">string [in] Directory to be listed.</param>
/// <param name="Wildcard">string [in] Wildcard of files to be listed.</param>
/// <param name="List">TStrings [in] Receives directory listing.</param>
/// <param name="IncludeDirs">Boolean [in] Flag true if sub-directory names are
/// to be included in List, False if only files are required.</param>
/// <returns>Boolean. True if Dir is a valid directory, False otherwise.
/// </returns>
/// <remarks>
/// <para>Sub-directories are not recursed.</para>
/// <para>File names include the full file path.</para>
/// </remarks>
function ListFiles(const Dir, Wildcard: string; const List: TStrings;
IncludeDirs: Boolean = True): Boolean;
/// <summary>Converts a long file name to the equivalent shortened DOS style
/// 8.3 path.</summary>
/// <param name="LongName">string [in] Long file name to be converted.</param>
/// <returns>string. Short file name.</returns>
function LongToShortFilePath(const LongName: string): string;
/// <summary>Checks if a directory exists.</summary>
/// <param name="DirName">string [in] Name of directory to check.</param>
/// <returns>Boolean. True if DirName is valid directory, False otherwise.
/// </returns>
function IsDirectory(const DirName: string): Boolean;
/// <summary>Converts a floating point number to an integer, rounding to
/// nearest integer.</summary>
/// <param name="F">Double [in] Floating point number to be rounded off.
/// </param>
/// <returns>Integer. Rounded value.</returns>
function FloatToInt(const F: Double): Int64;
/// <summary>Creates a date stamp for current date in RFC1123 format.</summary>
/// <returns>string. Required date and time as date stamp in UTC/GMT.</returns>
function DateStamp: string;
/// <summary>Get a desired interface pointer to an object instance.</summary>
/// <param name="Instance">IInterface [in] Instance for which an interface is
/// requested. May be nil.</param>
/// <param name="IID">TGUID [in] Identifier of required interface.</param>
/// <param name="Intf">Untyped [out] Set to required interface pointer if
/// Instance supports interface, or nil if interface not supported or Instance
/// is nil.</param>
procedure GetIntf(const Instance: IInterface; const IID: TGUID; out Intf);
/// <summary>Checks if a file name is a base file name (i.e. contains no path
/// information).</summary>
/// <param name="FileName">string [in] File name to be tested.</param>
/// <returns>Boolean. True if file is a base file name, False otherwise.
/// </returns>
function IsBaseFileName(const FileName: string): Boolean;
/// <summary>Pauses for a specified number of milliseconds before returning.
/// </summary>
/// <param name="ADelay">Cardinal [in] Number of milliseconds to pause.</param>
/// <remarks>Performs a busy wait.</remarks>
procedure Pause(const ADelay: Cardinal);
/// <summary>Checks if a character is a valid Windows drive letter.</summary>
/// <param name="C">Char [in] Character to be tested.</param>
/// <returns>Boolean. True if C is a valid drive letter, False otherwise.
/// </returns>
function IsValidDriveLetter(const C: Char): Boolean;
/// <summary>Emits a sound indicating a keypress error.</summary>
procedure KeyErrorBeep;
/// <summary>Checks whether a character is a valid hex digit.</summary>
/// <param name="C">Char [in] Character to be tested.</param>
/// <returns>Boolean. True if character is a hex digit, False if not.</returns>
function IsHexDigit(C: Char): Boolean;
/// <summary>Gets the base resource name from a forward slash delimited URI.
/// </summary>
/// <param name="URI">string [in] Full URI.</param>
/// <returns>string. Name following last slash in URI.</returns>
function URIBaseName(const URI: string): string;
implementation
uses
// Delphi
Windows, ShlObj, ActiveX, Messages, Character, Math,
// Project
UConsts, UStrUtils;
function FileAge(const FileName: string): Integer;
var
FH: Integer; // file handle
begin
// This function is provided to avoid using FileAge unit in SysUtils since
// the routine is deprecated in Delphi 2006
Result := -1;
if IsDirectory(FileName) then
Exit;
FH := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
if FH <> -1 then
begin
Result := FileGetDate(FH);
FileClose(FH);
end;
end;
function DeleteFiles(const Dir, Wildcard: string): Integer;
var
Files: TStringList; // stores files to be deleted
I: Integer; // loops thru files in folder
AFile: string; // a file to be deleted
Attr: Integer; // attributes of a file
begin
Result := 0;
Files := TStringList.Create;
try
// Get matching list of files / folders in directory
if not ListFiles(Dir, Wildcard, Files) then
Exit;
for I := 0 to Pred(Files.Count) do
begin
AFile := Files[I];
Attr := FileGetAttr(AFile);
// Delete file if it is not a directory
if (Attr and faDirectory = 0) then
begin
if SysUtils.DeleteFile(AFile) then
// File deleted: count it
Inc(Result);
end;
end;
finally
FreeAndNil(Files);
end;
end;
procedure EnsureFolders(const Folder: string);
begin
// Check there's a folder to create: ForceDirectories raises exception if
// passed empty string as parameter
if Length(Folder) = 0 then
Exit;
// Create the folders
ForceDirectories(Folder);
end;
function IsDirectory(const DirName: string): Boolean;
begin
Result := DirectoryExists(DirName);
end;
function ListFiles(const Dir, Wildcard: string; const List: TStrings;
IncludeDirs: Boolean = True): Boolean;
var
FileSpec: string; // full file spec of a wildcard
Path: string; // full path of directory, including training backslash
SR: TSearchRec; // file search result
Success: Integer; // success code for FindXXX routines
const
faVolumeId = $00000008; // redefined from SysUtils to avoid deprecated warning
begin
Assert(Assigned(List), 'ListFiles: List is nil');
// Check if true directory and exit if not
Result := IsDirectory(Dir);
if not Result then
Exit;
// Build FileSpec from directory and wildcard
FileSpec := IncludeTrailingPathDelimiter(Dir);
if Wildcard = '' then
FileSpec := FileSpec + '*.*'
else
FileSpec := FileSpec + Wildcard;
Path := IncludeTrailingPathDelimiter(Dir);
// Do search
Success := FindFirst(FileSpec, faAnyFile, SR);
try
while Success = 0 do
begin
// only add true files or directories to list
if (SR.Name <> '.') and (SR.Name <> '..')
and (SR.Attr and faVolumeId = 0)
and (IncludeDirs or not IsDirectory(Path + SR.Name)) then
List.Add(Path + SR.Name);
Success := FindNext(SR);
end;
finally
SysUtils.FindClose(SR);
end;
end;
function LongToShortFilePath(const LongName: string): string;
begin
SetLength(Result, MAX_PATH);
SetLength(Result, GetShortPathName(PChar(LongName), PChar(Result), MAX_PATH));
end;
function FloatToInt(const F: Double): Int64;
begin
// We don't just use Round() on its own because don't want bankers rounding.
Result := Round(SimpleRoundTo(F, 0));
end;
function DateStamp: string;
const
// Pattern to create RFC1123 date formats
cRFC1123Pattern = 'ddd, dd mmm yyyy HH'':''nn'':''ss ''GMT''';
var
ST: TSystemTime; // system time
begin
// This Windows API function gets system time in UTC/GMT
// see http://msdn.microsoft.com/en-us/library/ms724390
GetSystemTime(ST);
// Format system time in RFC1123 format
Result := FormatDateTime(cRFC1123Pattern, SystemTimeToDateTime(ST));
end;
procedure GetIntf(const Instance: IInterface; const IID: TGUID; out Intf);
begin
if not Supports(Instance, IID, Intf) then
Pointer(Intf) := nil;
end;
function IsBaseFileName(const FileName: string): Boolean;
begin
Result := (FileName <> '') and (ExtractFileName(FileName) = FileName);
end;
procedure Pause(const ADelay: LongWord);
// ---------------------------------------------------------------------------
/// Processes all the messages in program's message queue.
procedure ProcessMessages;
var
Msg: TMsg; // stores message peeked from message loop
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if Msg.Message <> WM_QUIT then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end
else
Exit;
end;
end;
// ---------------------------------------------------------------------------
var
StartTC: DWORD; // tick count when routine called
CurrentTC: Int64; // tick count at each loop iteration
begin
StartTC := GetTickCount;
repeat
ProcessMessages;
CurrentTC := GetTickCount;
if CurrentTC < StartTC then
// tick count has wrapped around: adjust it
CurrentTC := CurrentTC + High(DWORD);
until CurrentTC - StartTC >= ADelay;
end;
function IsValidDriveLetter(const C: Char): Boolean;
begin
Result := CharInSet(C, ['A'..'Z', 'a'..'z']);
end;
procedure KeyErrorBeep;
begin
MessageBeep(UINT(-1));
end;
function IsHexDigit(C: Char): Boolean;
begin
Result := CharInSet(C, ['A'..'F', 'a'..'f', '0'..'9']);
end;
function URIBaseName(const URI: string): string;
var
LastSlashPos: Integer; // position of last '/' in URI
begin
LastSlashPos := StrLastPos('/', URI);
if LastSlashPos = 0 then
Exit(URI);
Result := StrSliceRight(URI, Length(URI) - LastSlashPos);
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.