source: trunk/Packages/Common/UCommon.pas

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