123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984 |
- { ***************************************************************************
- Copyright (c) 2016-2018 Kike Pérez
- Unit : Quick.Commons
- Description : Common functions
- Author : Kike Pérez
- Version : 1.4
- Created : 14/07/2017
- Modified : 16/05/2018
- This file is part of QuickLib: https://github.com/exilon/QuickLib
- ***************************************************************************
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- *************************************************************************** }
- unit Quick.Commons;
- {$i QuickLib.inc}
- interface
- uses
- Classes,
- SysUtils,
- Types,
- {$IFDEF MSWINDOWS}
- Windows,
- ShlObj,
- Registry,
- {$ENDIF MSWINDOWS}
- {$IFDEF FPC}
- Quick.Files,
- {$IFDEF LINUX}
- FileInfo,
- {$ENDIF}
- {$ELSE}
- IOUtils,
- {$ENDIF}
- DateUtils;
- type
- TLogEventType = (etInfo, etSuccess, etWarning, etError, etDebug, etTrace);
- TLogVerbose = set of TLogEventType;
- const
- LOG_ONLYERRORS = [etInfo,etError];
- LOG_ERRORSANDWARNINGS = [etInfo,etWarning,etError];
- LOG_TRACE = [etInfo,etError,etWarning,etTrace];
- LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
- LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
- {$IFDEF DELPHIXE7_UP}
- EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
- {$ELSE}
- EventStr : array[0..5] of string = ('INFO','SUCC','WARN','ERROR','DEBUG','TRACE');
- {$ENDIF}
- type
- TPasswordComplexity = set of (pfIncludeNumbers,pfIncludeSigns);
- {$IFDEF MSWINDOWS}
- TEnvironmentPath = record
- EXEPATH : string;
- WINDOWS : string;
- SYSTEM : string;
- PROGRAMFILES : string;
- COMMONFILES : string;
- HOMEDRIVE : string;
- TEMP : string;
- USERPROFILE : string;
- INSTDRIVE : string;
- DESKTOP : string;
- STARTMENU : string;
- DESKTOP_ALLUSERS : string;
- STARTMENU_ALLUSERS : string;
- STARTUP : string;
- APPDATA : String;
- PROGRAMDATA : string;
- ALLUSERSPROFILE : string;
- end;
- {$ENDIF MSWINDOWS}
- {$IFNDEF FPC}
- TFileHelper = record helper for TFile
- {$IFDEF MSWINDOWS}
- class function IsInUse(const FileName : string) : Boolean; static;
- {$ENDIF}
- class function GetSize(const FileName: String): Int64; static;
- end;
- TDirectoryHelper = record helper for TDirectory
- class function GetSize(const Path: String): Int64; static;
- end;
- {$ENDIF}
- {$IFDEF FPC}
- {$IFDEF LINUX}
- UINT = cardinal;
- {$ENDIF}
- PLASTINPUTINFO = ^LASTINPUTINFO;
- tagLASTINPUTINFO = record
- cbSize: UINT;
- dwTime: DWORD;
- end;
- LASTINPUTINFO = tagLASTINPUTINFO;
- TLastInputInfo = LASTINPUTINFO;
- type
- TCmdLineSwitchType = (clstValueNextParam, clstValueAppended);
- TCmdLineSwitchTypes = set of TCmdLineSwitchType;
- {$ENDIF}
- TCounter = record
- private
- fMaxValue : Integer;
- fCurrentValue : Integer;
- public
- property MaxValue : Integer read fMaxValue;
- procedure Init(aMaxValue : Integer);
- function Count : Integer;
- function CountIs(aValue : Integer) : Boolean;
- function Check : Boolean;
- procedure Reset;
- end;
- TTimeCounter = record
- private
- fCurrentTime : TDateTime;
- fDoneEvery : Integer;
- public
- property DoneEvery : Integer read fDoneEvery;
- procedure Init(MillisecondsToReach : Integer);
- function Check : Boolean;
- procedure Reset;
- end;
- EEnvironmentPath = class(Exception);
- EShellError = class(Exception);
- //generates a random password with complexity options
- function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
- //extracts file extension from a filename
- function ExtractFileNameWithoutExt(const FileName: string): string;
- //converts a Unix path to Windows path
- function UnixToWindowsPath(const UnixPath: string): string;
- //converts a Windows path to Unix path
- function WindowsToUnixPath(const WindowsPath: string): string;
- //corrects malformed urls
- function CorrectURLPath(cUrl : string) : string;
- {$IFDEF MSWINDOWS}
- //get typical environment paths as temp, desktop, etc
- procedure GetEnvironmentPaths;
- function GetSpecialFolderPath(folderID : Integer) : string;
- //checks if running on a 64bit OS
- function Is64bitOS : Boolean;
- //checks if is a console app
- function IsConsole : Boolean;
- //checks if compiled in debug mode
- {$ENDIF}
- function IsDebug : Boolean;
- {$IFDEF MSWINDOWS}
- //checks if running as a service
- function IsService : Boolean;
- //gets number of seconds without user interaction (mouse, keyboard)
- function SecondsIdle: DWord;
- //frees process memory not needed
- procedure FreeUnusedMem;
- //changes screen resolution
- function SetScreenResolution(Width, Height: integer): Longint;
- {$ENDIF MSWINDOWS}
- //returns last day of current month
- function LastDayCurrentMonth: TDateTime;
- {$IFDEF FPC}
- function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
- {$ENDIF}
- //checks if two datetimes are in same day
- function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
- //returns n times a char
- function FillStr(const C : Char; const Count : Byte) : string;
- //returns a number leading zero
- function Zeroes(const Number, Len : Int64) : string;
- //converts a number to thousand delimeter string
- function NumberToStr(const Number : Int64) : string;
- //returns n spaces
- function Spaces(const Count : Integer) : string;
- //returns current date as a string
- function NowStr : string;
- //returns a new GUID as string
- function NewGuidStr : string;
- //compare a string with a wildcard pattern (? or *)
- function IsLike(cText, Pattern: string) : Boolean;
- //Upper case for first letter
- function Capitalize(s: string): string;
- function CapitalizeWords(s: string): string;
- //returns current logged user
- function GetLoggedUserName : string;
- //returns computer name
- function GetComputerName : string;
- //Changes incorrect delims in path
- function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
- //Removes last segment of a path
- function RemoveLastPathSegment(cDir : string) : string;
- //finds swith in commandline params
- function ParamFindSwitch(const Switch : string) : Boolean;
- //gets value for a switch if exists
- function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
- //returns app name (filename based)
- function GetAppName : string;
- //returns app version (major & minor)
- function GetAppVersionStr: string;
- //returns app version full (major, minor, release & compiled)
- function GetAppVersionFullStr: string;
- //UTC DateTime to Local DateTime
- function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
- //Local DateTime to UTC DateTime
- function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
- //return GTM time string
- function DateTimeToGMT(aDate : TDateTime) : string;
- //count number of digits of a Integer
- function CountDigits(anInt: Cardinal): Cardinal; inline;
- //save stream to file
- procedure SaveStreamToFile(stream : TStream; const filename : string);
- {$IFDEF MSWINDOWS}
- //process messages on console applications
- procedure ProcessMessages;
- //get last error message
- function GetLastOSError : String;
- {$ENDIF}
- {$IF DEFINED(FPC) AND DEFINED(MSWINDOWS)}
- function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
- {$ENDIF}
- {$IFDEF MSWINDOWS}
- var
- path : TEnvironmentPath;
- {$ENDIF}
- implementation
- {TFileHelper}
- {$IFNDEF FPC}
- {$IFDEF MSWINDOWS}
- class function TFileHelper.IsInUse(const FileName : string) : Boolean;
- var
- HFileRes: HFILE;
- begin
- Result := False;
- if not FileExists(FileName) then Exit;
- try
- HFileRes := CreateFile(PChar(FileName)
- ,GENERIC_READ or GENERIC_WRITE
- ,0
- ,nil
- ,OPEN_EXISTING
- ,FILE_ATTRIBUTE_NORMAL
- ,0);
- Result := (HFileRes = INVALID_HANDLE_VALUE);
- if not(Result) then begin
- CloseHandle(HFileRes);
- end;
- except
- Result := True;
- end;
- end;
- {$ENDIF}
- {$IFDEF MSWINDOWS}
- class function TFileHelper.GetSize(const FileName: String): Int64;
- var
- info: TWin32FileAttributeData;
- begin
- Result := -1;
- if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
- Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
- end;
- {$ELSE}
- class function TFileHelper.GetSize(const FileName: String): Int64;
- var
- sr : TSearchRec;
- begin
- if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
- else Result := -1;
- end;
- {$ENDIF}
- {TDirectoryHelper}
- class function TDirectoryHelper.GetSize(const Path: String): Int64;
- var
- filename : string;
- begin
- Result := -1;
- for filename in TDirectory.GetFiles(Path) do
- begin
- Result := Result + TFile.GetSize(filename);
- end;
- end;
- {$ENDIF}
- {other functions}
- function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
- const
- PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- PassSigns = '@!&$';
- PassNumbers = '1234567890';
- var
- MinNumbers,
- MinSigns : Integer;
- NumNumbers,
- NumSigns : Integer;
- begin
- Result := '';
- Randomize;
- //fill all alfa
- repeat
- Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
- until (Length(Result) = PasswordLength);
- //checks if need include numbers
- if pfIncludeNumbers in Complexity then
- begin
- MinNumbers := Round(PasswordLength / 10 * 2);
- NumNumbers := 0;
- if MinNumbers = 0 then MinNumbers := 1;
- repeat
- Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
- Inc(NumNumbers);
- until NumNumbers = MinNumbers;
- end;
- //checks if need include signs
- if pfIncludeNumbers in Complexity then
- begin
- MinSigns := Round(PasswordLength / 10 * 1);
- NumSigns := 0;
- if MinSigns = 0 then MinSigns := 1;
- repeat
- Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
- Inc(NumSigns);
- until NumSigns = MinSigns;
- end;
- end;
- function ExtractFileNameWithoutExt(const FileName: string): string;
- begin
- Result := TPath.GetFileNameWithoutExtension(FileName);
- end;
- function UnixToWindowsPath(const UnixPath: string): string;
- begin
- Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
- end;
- function WindowsToUnixPath(const WindowsPath: string): string;
- begin
- Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
- end;
- function CorrectURLPath(cUrl : string) : string;
- var
- nurl : string;
- begin
- nurl := WindowsToUnixPath(cUrl);
- nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
- Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
- //TNetEncoding.Url.Encode()
- end;
- {$IFDEF MSWINDOWS}
- procedure GetEnvironmentPaths;
- begin
- //gets path
- path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
- path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
- path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
- path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
- path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
- path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
- path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
- path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
- path.INSTDRIVE := path.HOMEDRIVE;
- path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
- path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
- path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
- //these paths fail if user is SYSTEM
- try
- path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
- path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
- path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
- path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
- path.STARTMENU_ALLUSERS := path.STARTMENU;
- path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
- except
- //
- end;
- end;
- function GetSpecialFolderPath(folderID : Integer) : string;
- var
- ppidl: PItemIdList;
- begin
- SHGetSpecialFolderLocation(0, folderID, ppidl);
- SetLength(Result, MAX_PATH);
- if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
- begin
- raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
- end;
- SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
- end;
- function Is64bitOS : Boolean;
- begin
- {$IFDEF WIN64}
- Result := True;
- {$ELSE}
- Result := False;
- {$ENDIF WIN64}
- end;
- function IsConsole: Boolean;
- begin
- {$IFDEF CONSOLE}
- Result := True;
- {$ELSE}
- Result := False;
- {$ENDIF CONSOLE}
- end;
- {$ENDIF}
- function IsDebug: Boolean;
- begin
- {$IFDEF DEBUG}
- Result := True;
- {$ELSE}
- Result := False;
- {$ENDIF DEBUG}
- end;
- {$IFDEF MSWINDOWS}
- function IsService : Boolean;
- begin
- //only working with my Quick.AppService unit
- try
- Result := (IsConsole) and (GetStdHandle(STD_OUTPUT_HANDLE) = 0);
- except
- Result := False;
- end;
- end;
- function SecondsIdle: DWord;
- var
- liInfo: TLastInputInfo;
- begin
- liInfo.cbSize := SizeOf(TLastInputInfo) ;
- GetLastInputInfo(liInfo) ;
- Result := (GetTickCount - liInfo.dwTime) DIV 1000;
- end;
- procedure FreeUnusedMem;
- begin
- if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
- end;
- function SetScreenResolution(Width, Height: integer): Longint;
- var
- DeviceMode: TDeviceMode;
- begin
- with DeviceMode do
- begin
- dmSize := SizeOf(TDeviceMode);
- dmPelsWidth := Width;
- dmPelsHeight := Height;
- dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
- end;
- Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
- end;
- {$ENDIF MSWINDOWS}
- function LastDayCurrentMonth: TDateTime;
- begin
- Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
- end;
- {$IFDEF FPC}
- function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
- begin
- if aInclusive then
- Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
- else
- Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
- end;
- {$ENDIF}
- function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
- begin
- //Test: Result := MinutesBetween(cBefore,cNow) < 1;
- Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
- end;
- function FillStr(const C : Char; const Count : Byte) : string;
- var
- i : Byte;
- begin
- Result := '';
- for i := 1 to Count do Result := Result + C;
- end;
- function Zeroes(const Number, Len : Int64) : string;
- begin
- if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
- else Result := IntToStr(Number);
- end;
- function NumberToStr(const Number : Int64) : string;
- begin
- try
- Result := FormatFloat('0,',Number);
- except
- Result := '#Error';
- end;
- end;
- function Spaces(const Count : Integer) : string;
- begin
- Result := FillStr(' ',Count);
- end;
- function NowStr : string;
- begin
- Result := DateTimeToStr(Now());
- end;
- function NewGuidStr : string;
- var
- guid : TGUID;
- begin
- guid.NewGuid;
- Result := guid.ToString
- //GUIDToString(guid);
- end;
- function IsLike(cText, Pattern: string) : Boolean;
- var
- i, n : Integer;
- match : Boolean;
- wildcard : Boolean;
- CurrentPattern : Char;
- begin
- Result := False;
- wildcard := False;
- cText := LowerCase(cText);
- Pattern := LowerCase(Pattern);
- match := False;
- if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
- if Pattern = '*' then
- begin
- Result := True;
- Exit;
- end;
- for i := 1 to cText.Length do
- begin
- CurrentPattern := Pattern[i];
- if CurrentPattern = '*' then wildcard := True;
- if wildcard then
- begin
- n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
- if (n > i) or (Pattern.Length = i) then
- begin
- Result := True;
- Exit;
- end;
- end
- else
- begin
- if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
- else match := False;
- end;
- end;
- Result := match;
- end;
- function Capitalize(s: string): string;
- begin
- Result := '';
- if s.Length = 0 then Exit;
- s := LowerCase(s,loUserLocale);
- Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
- end;
- function CapitalizeWords(s: string): string;
- var
- cword : string;
- begin
- Result := '';
- if s.Length = 0 then Exit;
- s := LowerCase(s,loUserLocale);
- for cword in s.Split([' ']) do
- begin
- if Result = '' then Result := Capitalize(cword)
- else Result := Result + ' ' + Capitalize(cword);
- end;
- end;
- function GetLoggedUserName : string;
- {$IFDEF MSWINDOWS}
- const
- cnMaxUserNameLen = 254;
- var
- sUserName : string;
- dwUserNameLen : DWord;
- begin
- dwUserNameLen := cnMaxUserNameLen-1;
- SetLength( sUserName, cnMaxUserNameLen );
- GetUserName(PChar( sUserName ),dwUserNameLen );
- SetLength( sUserName, dwUserNameLen );
- Result := sUserName;
- end;
- {$ENDIF}
- {$IF DEFINED(FPC) AND DEFINED(LINUX)}
- begin
- Result := GetEnvironmentVariable('USERNAME');
- end;
- {$ENDIF}
- function GetComputerName : string;
- {$IFDEF MSWINDOWS}
- var
- dwLength: dword;
- begin
- dwLength := 253;
- SetLength(Result, dwLength+1);
- if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
- Result := pchar(result);
- end;
- {$ENDIF}
- {$IF DEFINED(FPC) AND DEFINED(LINUX)}
- begin
- Result := GetEnvironmentVariable('COMPUTERNAME');
- end;
- {$ENDIF}
- function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
- begin
- if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
- else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
- end;
- function RemoveLastPathSegment(cDir : string) : string;
- var
- posi : Integer;
- delim : Char;
- EndsWithDelim : Boolean;
- begin
- if cDir.Contains('\') then delim := '\'
- else if cDir.Contains('/') then delim := '/'
- else
- begin
- Result := '';
- Exit;
- end;
- NormalizePathDelim(cDir,delim);
- if cDir.EndsWith(delim) then
- begin
- cDir := Copy(cDir,1,cDir.Length-1);
- EndsWithDelim := True;
- end
- else EndsWithDelim := False;
- if cDir.CountChar(delim) > 1 then posi := cDir.LastDelimiter(delim)
- else posi := Pos(delim,cDir)-1;
- if posi = cDir.Length then posi := 0;
- Result := Copy(cDir,1,posi);
- if (Result <> '') and (EndsWithDelim) then Result := Result + delim;
- end;
- function ParamFindSwitch(const Switch : string) : Boolean;
- begin
- Result := FindCmdLineSwitch(Switch,['-', '/'],True);
- end;
- {$IFDEF FPC}
- function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
- const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
- type
- TCompareProc = function(const S1, S2: string): Boolean;
- var
- Param: string;
- I, ValueOfs,
- SwitchLen, ParamLen: Integer;
- SameSwitch: TCompareProc;
- begin
- Result := False;
- Value := '';
- if IgnoreCase then
- SameSwitch := SameText else
- SameSwitch := SameStr;
- SwitchLen := Switch.Length;
- for I := 1 to ParamCount do
- begin
- Param := ParamStr(I);
- if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
- begin
- ParamLen := Param.Length;
- // Look for an appended value if the param is longer than the switch
- if (ParamLen > SwitchLen + 1) then
- begin
- // If not looking for appended value switches then this is not a matching switch
- if not (clstValueAppended in SwitchTypes) then
- Continue;
- ValueOfs := SwitchLen + 1;
- if Param.Chars[ValueOfs] = ':' then
- Inc(ValueOfs);
- Value := Param.SubString(ValueOfs, MaxInt);
- end
- // If the next param is not a switch, then treat it as the value
- else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
- not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
- Value := ParamStr(I+1);
- Result := True;
- Break;
- end;
- end;
- end;
- {$ENDIF}
- function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
- begin
- Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
- end;
- function GetAppName : string;
- begin
- Result := ExtractFilenameWithoutExt(ParamStr(0));
- end;
- function GetAppVersionStr: string;
- {$IFDEF MSWINDOWS}
- var
- Rec: LongRec;
- ver : Cardinal;
- begin
- ver := GetFileVersion(ParamStr(0));
- if ver <> Cardinal(-1) then
- begin
- Rec := LongRec(ver);
- Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
- end
- else Result := '';
- end;
- {$ENDIF}
- {$IF DEFINED(FPC) AND DEFINED(LINUX)}
- var
- version : TProgramVersion;
- begin
- if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
- else Result := '';
- end;
- {$ENDIF}
- function GetAppVersionFullStr: string;
- {$IFDEF MSWINDOWS}
- var
- Exe: string;
- Size, Handle: DWORD;
- Buffer: TBytes;
- FixedPtr: PVSFixedFileInfo;
- begin
- Result := '';
- Exe := ParamStr(0);
- Size := GetFileVersionInfoSize(PChar(Exe), Handle);
- if Size = 0 then
- begin
- //RaiseLastOSError;
- //no version info in file
- Exit;
- end;
- SetLength(Buffer, Size);
- if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
- RaiseLastOSError;
- if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
- RaiseLastOSError;
- if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
- begin
- Result := Format('%d.%d',
- [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
- LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
- end
- else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
- begin
- Result := Format('%d.%d.%d',
- [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
- LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
- LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
- end
- else
- begin
- Result := Format('%d.%d.%d.%d',
- [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
- LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
- LongRec(FixedPtr.dwFileVersionLS).Hi, //release
- LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
- end;
- end;
- {$ENDIF}
- {$IF DEFINED(FPC) AND DEFINED(LINUX)}
- var
- version : TProgramVersion;
- begin
- if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
- else Result := '';
- end;
- {$ENDIF}
- function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
- begin
- {$IFDEF FPC}
- Result := LocalTimeToUniversal(GMTTime);
- {$ELSE}
- Result := TTimeZone.Local.ToLocalTime(GMTTime);
- {$ENDIF}
- end;
- function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
- begin
- {$IFDEF FPC}
- Result := UniversalTimeToLocal(Localtime);
- {$ELSE}
- Result := TTimeZone.Local.ToUniversalTime(LocalTime);
- {$ENDIF}
- end;
- function DateTimeToGMT(aDate : TDateTime) : string;
- var
- FmtSettings : TFormatSettings;
- begin
- FmtSettings.DateSeparator := '-';
- FmtSettings.TimeSeparator := ':';
- FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
- Result := DateTimeToStr(aDate,FmtSettings);
- end;
- function CountDigits(anInt: Cardinal): Cardinal; inline;
- var
- cmp: Cardinal;
- begin
- cmp := 10;
- Result := 1;
- while (Result < 10) and (cmp <= anInt) do
- begin
- cmp := cmp*10;
- Inc(Result);
- end;
- end;
- procedure SaveStreamToFile(stream : TStream; const filename : string);
- var
- fs : TFileStream;
- begin
- fs := TFileStream.Create(filename,fmCreate);
- try
- stream.Seek(0,soBeginning);
- fs.CopyFrom(stream,stream.Size);
- finally
- fs.Free;
- end;
- end;
- { TCounter }
- procedure TCounter.Init(aMaxValue : Integer);
- begin
- fMaxValue := aMaxValue;
- fCurrentValue := 0;
- end;
- function TCounter.Count : Integer;
- begin
- Result := fCurrentValue;
- end;
- function TCounter.CountIs(aValue : Integer) : Boolean;
- begin
- Result := fCurrentValue = aValue;
- end;
- function TCounter.Check : Boolean;
- begin
- if fCurrentValue = fMaxValue then
- begin
- Result := True;
- Reset;
- end
- else
- begin
- Result := False;
- Inc(fCurrentValue);
- end;
- end;
- procedure TCounter.Reset;
- begin
- fCurrentValue := fMaxValue;
- end;
- { TimeCounter }
- procedure TTimeCounter.Init(MillisecondsToReach : Integer);
- begin
- fDoneEvery := MillisecondsToReach;
- end;
- function TTimeCounter.Check : Boolean;
- begin
- if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
- begin
- fCurrentTime := Now();
- Result := True;
- end
- else Result := False;
- end;
- procedure TTimeCounter.Reset;
- begin
- fCurrentTime := Now();
- end;
- {$IFDEF MSWINDOWS}
- procedure ProcessMessages;
- var
- Msg: TMsg;
- begin
- while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
- begin
- TranslateMessage(Msg);
- DispatchMessage(Msg);
- end;
- end;
- function GetLastOSError: String;
- begin
- Result := SysErrorMessage(Windows.GetLastError);
- end;
- {$ENDIF}
- initialization
- {$IFDEF MSWINDOWS}
- try
- GetEnvironmentPaths;
- except
- on E : Exception do
- begin
- if not IsService then
- begin
- if IsConsole then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
- else raise EEnvironmentPath.Create(Format('Get environment path error: %s',[E.Message]));
- end;
- end;
- end;
- {$ENDIF}
- end.
|