source: tags/1.3.1/Packages/Common/UCommon.pas

Last change on this file was 424, checked in by chronos, 2 years ago
  • Modified: Update Common package to version 0.10.
  • Modified: fgl unit replaced by Generics.Collections.
File size: 18.9 KB
Line 
1unit UCommon;
2
3interface
4
5uses
6 {$IFDEF WINDOWS}Windows,{$ENDIF}
7 {$IFDEF UNIX}baseunix,{$ENDIF}
8 Classes, SysUtils, StrUtils, Dialogs, Process, LCLIntf, Graphics,
9 FileUtil; //, ShFolder, ShellAPI;
10
11type
12 TArrayOfByte = array of Byte;
13 TExceptionEvent = procedure(Sender: TObject; E: Exception) of object;
14
15 TUserNameFormat = (
16 unfNameUnknown = 0, // Unknown name type.
17 unfNameFullyQualifiedDN = 1, // Fully qualified distinguished name
18 unfNameSamCompatible = 2, // Windows NT® 4.0 account name
19 unfNameDisplay = 3, // A "friendly" display name
20 unfNameUniqueId = 6, // GUID string that the IIDFromString function returns
21 unfNameCanonical = 7, // Complete canonical name
22 unfNameUserPrincipal = 8, // User principal name
23 unfNameCanonicalEx = 9,
24 unfNameServicePrincipal = 10, // Generalized service principal name
25 unfDNSDomainName = 11);
26
27 TFilterMethod = function (FileName: string): Boolean of object;
28 TFileNameMethod = procedure (FileName: string) of object;
29
30var
31 ExceptionHandler: TExceptionEvent;
32 DLLHandle1: HModule;
33
34 {$IFDEF WINDOWS}
35 GetUserNameEx: procedure (NameFormat: DWORD;
36 lpNameBuffer: LPSTR; nSize: PULONG); stdcall;
37 {$ENDIF}
38
39const
40 clLightBlue = TColor($FF8080);
41 clLightGreen = TColor($80FF80);
42 clLightRed = TColor($8080FF);
43
44function AddLeadingZeroes(const aNumber, Length : integer) : string;
45function BinToInt(BinStr: string): Int64;
46function BinToHexString(Source: AnsiString): string;
47//function DelTree(DirName : string): Boolean;
48//function GetSpecialFolderPath(Folder: Integer): string;
49function BCDToInt(Value: Byte): Byte;
50function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
51procedure CopyStringArray(Dest: TStringArray; Source: array of string);
52function CombinePaths(Path1, Path2: string): string;
53function ComputerName: string;
54procedure DeleteFiles(APath, AFileSpec: string);
55function Explode(Separator: Char; Data: string): TStringArray;
56procedure ExecuteProgram(Executable: string; Parameters: array of string);
57procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
58procedure FreeThenNil(var Obj);
59function GetDirCount(Dir: string): Integer;
60function GetUserName: string;
61function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
62function GetBit(Variable: QWord; Index: Byte): Boolean;
63function GetStringPart(var Text: string; Separator: string): string;
64function GenerateNewName(OldName: string): string;
65function GetFileFilterItemExt(Filter: string; Index: Integer): string;
66function IntToBin(Data: Int64; Count: Byte): string;
67function LastPos(const SubStr: String; const S: String): Integer;
68function LoadFileToStr(const FileName: TFileName): AnsiString;
69function LoggedOnUserNameEx(Format: TUserNameFormat): string;
70function MergeArray(A, B: array of string): TStringArray;
71function OccurenceOfChar(What: Char; Where: string): Integer;
72procedure OpenWebPage(URL: string);
73procedure OpenEmail(Email: string);
74procedure OpenFileInShell(FileName: string);
75function PosFromIndex(SubStr: string; Text: string;
76 StartIndex: Integer): Integer;
77function PosFromIndexReverse(SubStr: string; Text: string;
78 StartIndex: Integer): Integer;
79function RemoveQuotes(Text: string): string;
80procedure SaveStringToFile(S, FileName: string);
81procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean); overload;
82procedure SetBit(var Variable: QWord; Index: Byte; State: Boolean); overload;
83procedure SetBit(var Variable: Cardinal; Index: Byte; State: Boolean); overload;
84procedure SetBit(var Variable: Word; Index: Byte; State: Boolean); overload;
85procedure SearchFiles(AList: TStrings; Dir: string;
86 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
87function SplitString(var Text: string; Count: Word): string;
88function StripTags(const S: string): string;
89function TryHexToInt(Data: string; out Value: Integer): Boolean;
90function TryBinToInt(Data: string; out Value: Integer): Boolean;
91procedure SortStrings(Strings: TStrings);
92
93
94implementation
95
96function BinToInt(BinStr : string) : Int64;
97var
98 i : byte;
99 RetVar : Int64;
100begin
101 BinStr := UpperCase(BinStr);
102 if BinStr[length(BinStr)] = 'B' then Delete(BinStr,length(BinStr),1);
103 RetVar := 0;
104 for i := 1 to length(BinStr) do begin
105 if not (BinStr[i] in ['0','1']) then begin
106 RetVar := 0;
107 Break;
108 end;
109 RetVar := (RetVar shl 1) + (byte(BinStr[i]) and 1) ;
110 end;
111
112 Result := RetVar;
113end;
114
115function BinToHexString(Source: AnsiString): string;
116var
117 I: Integer;
118begin
119 Result := '';
120 for I := 1 to Length(Source) do begin
121 Result := Result + LowerCase(IntToHex(Ord(Source[I]), 2));
122 end;
123end;
124
125
126procedure DeleteFiles(APath, AFileSpec: string);
127var
128 SearchRec: TSearchRec;
129 Find: Integer;
130 Path: string;
131begin
132 Path := IncludeTrailingPathDelimiter(APath);
133
134 Find := FindFirst(Path + AFileSpec, faAnyFile xor faDirectory, SearchRec);
135 while Find = 0 do begin
136 DeleteFile(Path + SearchRec.Name);
137
138 Find := SysUtils.FindNext(SearchRec);
139 end;
140 FindClose(SearchRec);
141end;
142
143
144function GetFileFilterItemExt(Filter: string; Index: Integer): string;
145var
146 List: TStringList;
147begin
148 try
149 List := TStringList.Create;
150 List.Text := StringReplace(Filter, '|', #10, [rfReplaceAll]);
151 Result := List[Index * 2 + 1];
152 finally
153 List.Free;
154 end;
155end;
156
157procedure FileDialogUpdateFilterFileType(FileDialog: TOpenDialog);
158var
159 FileExt: string;
160begin
161 FileExt := GetFileFilterItemExt(FileDialog.Filter, FileDialog.FilterIndex - 1);
162 Delete(FileExt, 1, 1); // Remove symbol '*'
163 if FileExt <> '.*' then
164 FileDialog.FileName := ChangeFileExt(FileDialog.FileName, FileExt)
165end;
166
167function GenerateNewName(OldName: string): string;
168var
169 I: Integer;
170 Number: Integer;
171begin
172 Number := 1;
173 // Find number on end
174 if Length(OldName) > 0 then begin
175 I := Length(OldName);
176 while (I > 1) and ((OldName[I] >= '0') and (OldName[I] <= '9')) do Dec(I);
177 TryStrToInt(Copy(OldName, I + 1, Length(OldName) - I), Number);
178 Inc(Number)
179 end;
180 Result := Copy(OldName, 1, I) + IntToStr(Number);
181end;
182
183(*function DelTree(DirName : string): Boolean;
184var
185 SHFileOpStruct : TSHFileOpStruct;
186 DirBuf : array [0..255] of char;
187begin
188 DirName := UTF8Decode(DirName);
189 try
190 Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0) ;
191 FillChar(DirBuf, Sizeof(DirBuf), 0 ) ;
192 StrPCopy(DirBuf, DirName) ;
193 with SHFileOpStruct do begin
194 Wnd := 0;
195 pFrom := @DirBuf;
196 wFunc := FO_DELETE;
197 fFlags := FOF_ALLOWUNDO;
198 fFlags := fFlags or FOF_NOCONFIRMATION;
199 fFlags := fFlags or FOF_SILENT;
200 end;
201 Result := (SHFileOperation(SHFileOpStruct) = 0) ;
202 except
203 Result := False;
204 end;
205end;*)
206
207function LastPos(const SubStr: String; const S: String): Integer;
208begin
209 Result := Pos(ReverseString(SubStr), ReverseString(S));
210 if (Result <> 0) then
211 Result := ((Length(S) - Length(SubStr)) + 1) - Result + 1;
212end;
213
214function BCDToInt(Value: Byte): Byte;
215begin
216 Result := (Value shr 4) * 10 + (Value and 15);
217end;
218
219(*function GetSpecialFolderPath(Folder: Integer): string;
220const
221 SHGFP_TYPE_CURRENT = 0;
222var
223 Path: array[0..MAX_PATH] of Char;
224begin
225 Result := 'C:\Test';
226 if SUCCEEDED(SHGetFolderPath(0, Folder, 0, SHGFP_TYPE_CURRENT, @path[0])) then
227 Result := path
228 else
229 Result := '';
230end;*)
231
232function IntToBin(Data: Int64; Count: Byte): string;
233var
234 I: Integer;
235begin
236 Result := '';
237 for I := 0 to Count - 1 do
238 Result := IntToStr((Data shr I) and 1) + Result;
239end;
240
241function IntToHex(Data: Cardinal; Count: Byte): string;
242const
243 Chars: array[0..15] of Char = '0123456789ABCDEF';
244var
245 I: Integer;
246begin
247 Result := '';
248 for I := 0 to Count - 1 do
249 Result := Result + Chars[(Data shr (I * 4)) and 15];
250end;
251
252function TryHexToInt(Data: string; out Value: Integer): Boolean;
253var
254 I: Integer;
255begin
256 Data := UpperCase(Data);
257 Result := True;
258 Value := 0;
259 for I := 0 to Length(Data) - 1 do begin
260 if (Data[I + 1] >= '0') and (Data[I + 1] <= '9') then
261 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1) * 4)
262 else if (Data[I + 1] >= 'A') and (Data[I + 1] <= 'F') then
263 Value := Value or (Ord(Data[I + 1]) - Ord('A') + 10) shl ((Length(Data) - I - 1) * 4)
264 else Result := False;
265 end;
266end;
267
268function TryBinToInt(Data: string; out Value: Integer): Boolean;
269var
270 I: Integer;
271begin
272 Result := True;
273 Value := 0;
274 for I := 0 to Length(Data) - 1 do begin
275 if (Data[I + 1] >= '0') and (Data[I + 1] <= '1') then
276 Value := Value or (Ord(Data[I + 1]) - Ord('0')) shl ((Length(Data) - I - 1))
277 else Result := False;
278 end;
279end;
280
281function CompareByteArray(Data1, Data2: TArrayOfByte): Boolean;
282var
283 I: Integer;
284begin
285 if Length(Data1) = Length(Data2) then begin
286 Result := True;
287 for I := 0 to Length(Data1) - 1 do begin
288 if Data1[I] <> Data2[I] then begin
289 Result := False;
290 Break;
291 end
292 end;
293 end else Result := False;
294end;
295
296function Explode(Separator: Char; Data: string): TStringArray;
297var
298 Index: Integer;
299begin
300 Result := Default(TStringArray);
301 repeat
302 Index := Pos(Separator, Data);
303 if Index > 0 then begin
304 SetLength(Result, Length(Result) + 1);
305 Result[High(Result)] := Copy(Data, 1, Index - 1);
306 Delete(Data, 1, Index);
307 end else Break;
308 until False;
309 if Data <> '' then begin
310 SetLength(Result, Length(Result) + 1);
311 Result[High(Result)] := Data;
312 end;
313end;
314
315{$IFDEF WINDOWS}
316function GetUserName: string;
317const
318 MAX_USERNAME_LENGTH = 256;
319var
320 L: LongWord;
321begin
322 L := MAX_USERNAME_LENGTH + 2;
323 Result := Default(string);
324 SetLength(Result, L);
325 if Windows.GetUserName(PChar(Result), L) and (L > 0) then begin
326 SetLength(Result, StrLen(PChar(Result)));
327 Result := UTF8Encode(Result);
328 end else Result := '';
329end;
330
331function GetVersionInfo: TOSVersionInfo;
332begin
333 Result.dwOSVersionInfoSize := SizeOf(Result);
334 if GetVersionEx(Result) then begin
335 end;
336end;
337{$ENDIF}
338
339function ComputerName: string;
340{$IFDEF WINDOWS}
341const
342 INFO_BUFFER_SIZE = 32767;
343var
344 Buffer : array[0..INFO_BUFFER_SIZE] of WideChar;
345 Ret : DWORD;
346begin
347 Ret := INFO_BUFFER_SIZE;
348 If (GetComputerNameW(@Buffer[0],Ret)) then begin
349 Result := UTF8Encode(WideString(Buffer));
350 end
351 else begin
352 Result := 'ERROR_NO_COMPUTERNAME_RETURNED';
353 end;
354end;
355{$ENDIF}
356{$IFDEF UNIX}
357var
358 Name: UtsName;
359begin
360 Name := Default(UtsName);
361 fpuname(Name);
362 Result := Name.Nodename;
363end;
364{$ENDIF}
365
366{$IFDEF WINDOWS}
367function LoggedOnUserNameEx(Format: TUserNameFormat): string;
368const
369 MaxLength = 1000;
370var
371 UserName: array[0..MaxLength] of Char;
372 VersionInfo: TOSVersionInfo;
373 Size: DWORD;
374begin
375 VersionInfo := GetVersionInfo;
376 if VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT then begin
377 Size := MaxLength;
378 GetUserNameEx(Integer(Format), @UserName, @Size);
379 //ShowMessage(SysErrorMessage(GetLastError));
380 if GetLastError = 0 then Result := UTF8Encode(UserName)
381 else Result := GetUserName;
382 end else Result := GetUserName;
383end;
384{$ELSE}
385function GetUserName: string;
386begin
387 Result := '';
388end;
389
390function LoggedOnUserNameEx(Format: TUserNameFormat): string;
391begin
392 Result := '';
393end;
394
395{$ENDIF}
396
397function SplitString(var Text: string; Count: Word): string;
398begin
399 Result := Copy(Text, 1, Count);
400 Delete(Text, 1, Count);
401end;
402
403function GetBitCount(Variable: QWord; MaxIndex: Integer): Integer;
404var
405 I: Integer;
406begin
407 Result := 0;
408 for I := 0 to MaxIndex - 1 do
409 if ((Variable shr I) and 1) = 1 then Inc(Result);
410end;
411
412function GetBit(Variable:QWord;Index:Byte):Boolean;
413begin
414 Result := ((Variable shr Index) and 1) = 1;
415end;
416
417procedure SetBit(var Variable: Int64; Index: Byte; State: Boolean);
418begin
419 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (Int64(State) shl Index);
420end;
421
422procedure SetBit(var Variable:QWord;Index:Byte;State:Boolean); overload;
423begin
424 Variable := (Variable and ((1 shl Index) xor High(QWord))) or (QWord(State) shl Index);
425end;
426
427procedure SetBit(var Variable:Cardinal;Index:Byte;State:Boolean); overload;
428begin
429 Variable := (Variable and ((1 shl Index) xor High(Cardinal))) or (Cardinal(State) shl Index);
430end;
431
432procedure SetBit(var Variable:Word;Index:Byte;State:Boolean); overload;
433begin
434 Variable := (Variable and ((1 shl Index) xor High(Word))) or (Word(State) shl Index);
435end;
436
437function AddLeadingZeroes(const aNumber, Length : integer) : string;
438begin
439 Result := SysUtils.Format('%.*d', [Length, aNumber]) ;
440end;
441
442procedure LoadLibraries;
443begin
444 {$IFDEF WINDOWS}
445 DLLHandle1 := LoadLibrary('secur32.dll');
446 if DLLHandle1 <> 0 then
447 begin
448 @GetUserNameEx := GetProcAddress(DLLHandle1, 'GetUserNameExA');
449 end;
450 {$ENDIF}
451end;
452
453procedure FreeLibraries;
454begin
455 {$IFDEF WINDOWS}
456 if DLLHandle1 <> 0 then FreeLibrary(DLLHandle1);
457 {$ENDIF}
458end;
459
460procedure ExecuteProgram(Executable: string; Parameters: array of string);
461var
462 Process: TProcess;
463 I: Integer;
464begin
465 try
466 Process := TProcess.Create(nil);
467 Process.Executable := Executable;
468 for I := 0 to Length(Parameters) - 1 do
469 Process.Parameters.Add(Parameters[I]);
470 Process.Options := [poNoConsole];
471 Process.Execute;
472 finally
473 Process.Free;
474 end;
475end;
476
477procedure FreeThenNil(var Obj);
478begin
479 TObject(Obj).Free;
480 TObject(Obj) := nil;
481end;
482
483procedure OpenWebPage(URL: string);
484begin
485 OpenURL(URL);
486end;
487
488procedure OpenEmail(Email: string);
489begin
490 OpenURL('mailto:' + Email);
491end;
492
493procedure OpenFileInShell(FileName: string);
494begin
495 ExecuteProgram('cmd.exe', ['/c', 'start', FileName]);
496end;
497
498function RemoveQuotes(Text: string): string;
499begin
500 Result := Text;
501 if (Pos('"', Text) = 1) and (Text[Length(Text)] = '"') then
502 Result := Copy(Text, 2, Length(Text) - 2);
503end;
504
505function OccurenceOfChar(What: Char; Where: string): Integer;
506var
507 I: Integer;
508begin
509 Result := 0;
510 for I := 1 to Length(Where) do
511 if Where[I] = What then Inc(Result);
512end;
513
514function GetDirCount(Dir: string): Integer;
515begin
516 Result := OccurenceOfChar(DirectorySeparator, Dir);
517 if Copy(Dir, Length(Dir), 1) = DirectorySeparator then
518 Dec(Result);
519end;
520
521function MergeArray(A, B: array of string): TStringArray;
522var
523 I: Integer;
524begin
525 Result := Default(TStringArray);
526 SetLength(Result, Length(A) + Length(B));
527 for I := 0 to Length(A) - 1 do
528 Result[I] := A[I];
529 for I := 0 to Length(B) - 1 do
530 Result[Length(A) + I] := B[I];
531end;
532
533function LoadFileToStr(const FileName: TFileName): AnsiString;
534var
535 FileStream: TFileStream;
536 Read: Integer;
537begin
538 Result := '';
539 FileStream := TFileStream.Create(FileName, fmOpenRead);
540 try
541 if FileStream.Size > 0 then begin
542 SetLength(Result, FileStream.Size);
543 Read := FileStream.Read(Pointer(Result)^, FileStream.Size);
544 SetLength(Result, Read);
545 end;
546 finally
547 FileStream.Free;
548 end;
549end;
550
551function DefaultSearchFilter(const FileName: string): Boolean;
552begin
553 Result := True;
554end;
555
556procedure SaveStringToFile(S, FileName: string);
557var
558 F: TextFile;
559begin
560 AssignFile(F, FileName);
561 try
562 ReWrite(F);
563 Write(F, S);
564 finally
565 CloseFile(F);
566 end;
567end;
568
569procedure SearchFiles(AList: TStrings; Dir: string;
570 FilterMethod: TFilterMethod = nil; FileNameMethod: TFileNameMethod = nil);
571var
572 SR: TSearchRec;
573begin
574 Dir := IncludeTrailingPathDelimiter(Dir);
575 if FindFirst(Dir + '*', faAnyFile, SR) = 0 then
576 try
577 repeat
578 if (SR.Name = '.') or (SR.Name = '..') or (Assigned(FilterMethod) and (not FilterMethod(SR.Name) or
579 not FilterMethod(Copy(Dir, 3, Length(Dir)) + SR.Name))) then Continue;
580 if Assigned(FileNameMethod) then
581 FileNameMethod(Dir + SR.Name);
582 AList.Add(Dir + SR.Name);
583 if (SR.Attr and faDirectory) <> 0 then
584 SearchFiles(AList, Dir + SR.Name, FilterMethod);
585 until FindNext(SR) <> 0;
586 finally
587 FindClose(SR);
588 end;
589end;
590
591function GetStringPart(var Text: string; Separator: string): string;
592var
593 P: Integer;
594begin
595 P := Pos(Separator, Text);
596 if P > 0 then begin
597 Result := Copy(Text, 1, P - 1);
598 Delete(Text, 1, P - 1 + Length(Separator));
599 end else begin
600 Result := Text;
601 Text := '';
602 end;
603 Result := Trim(Result);
604 Text := Trim(Text);
605end;
606
607function StripTags(const S: string): string;
608var
609 Len: Integer;
610
611 function ReadUntil(const ReadFrom: Integer; const C: Char): Integer;
612 var
613 J: Integer;
614 begin
615 for J := ReadFrom to Len do
616 if (S[j] = C) then
617 begin
618 Result := J;
619 Exit;
620 end;
621 Result := Len + 1;
622 end;
623
624var
625 I, APos: Integer;
626begin
627 Len := Length(S);
628 I := 0;
629 Result := '';
630 while (I <= Len) do begin
631 Inc(I);
632 APos := ReadUntil(I, '<');
633 Result := Result + Copy(S, I, APos - i);
634 I := ReadUntil(APos + 1, '>');
635 end;
636end;
637
638function PosFromIndex(SubStr: string; Text: string;
639 StartIndex: Integer): Integer;
640var
641 I, MaxLen: SizeInt;
642 Ptr: PAnsiChar;
643begin
644 Result := 0;
645 if (StartIndex < 1) or (StartIndex > Length(Text) - Length(SubStr)) then Exit;
646 if Length(SubStr) > 0 then begin
647 MaxLen := Length(Text) - Length(SubStr) + 1;
648 I := StartIndex;
649 Ptr := @Text[StartIndex];
650 while (I <= MaxLen) do begin
651 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
652 Result := I;
653 Exit;
654 end;
655 Inc(I);
656 Inc(Ptr);
657 end;
658 end;
659end;
660
661function PosFromIndexReverse(SubStr: string; Text: string;
662 StartIndex: Integer): Integer;
663var
664 I: SizeInt;
665 Ptr: PAnsiChar;
666begin
667 Result := 0;
668 if (StartIndex < 1) or (StartIndex > Length(Text)) then Exit;
669 if Length(SubStr) > 0 then begin
670 I := StartIndex;
671 Ptr := @Text[StartIndex];
672 while (I > 0) do begin
673 if (SubStr[1] = Ptr^) and (CompareByte(Substr[1], Ptr^, Length(SubStr)) = 0) then begin
674 Result := I;
675 Exit;
676 end;
677 Dec(I);
678 Dec(Ptr);
679 end;
680 end;
681end;
682
683procedure CopyStringArray(Dest: TStringArray; Source: array of string);
684var
685 I: Integer;
686begin
687 SetLength(Dest, Length(Source));
688 for I := 0 to Length(Dest) - 1 do
689 Dest[I] := Source[I];
690end;
691
692function CombinePaths(Path1, Path2: string): string;
693begin
694 Result := Path1;
695 if Result <> '' then Result := Result + DirectorySeparator + Path2
696 else Result := Path2;
697end;
698
699procedure SortStrings(Strings: TStrings);
700var
701 Tmp: TStringList;
702begin
703 Strings.BeginUpdate;
704 try
705 if Strings is TStringList then begin
706 TStringList(Strings).Sort;
707 end else begin
708 Tmp := TStringList.Create;
709 try
710 Tmp.Assign(Strings);
711 Tmp.Sort;
712 Strings.Assign(Tmp);
713 finally
714 Tmp.Free;
715 end;
716 end;
717 finally
718 Strings.EndUpdate;
719 end;
720end;
721
722
723initialization
724
725LoadLibraries;
726
727
728finalization
729
730FreeLibraries;
731
732end.
Note: See TracBrowser for help on using the repository browser.