Quick.Commons.pas 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. { ***************************************************************************
  2. Copyright (c) 2016-2019 Kike Pérez
  3. Unit : Quick.Commons
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 1.7
  7. Created : 14/07/2017
  8. Modified : 27/02/2019
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.Commons;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. Types,
  28. {$IFDEF MSWINDOWS}
  29. Windows,
  30. ShlObj,
  31. Registry,
  32. {$ENDIF MSWINDOWS}
  33. {$IFDEF FPC}
  34. Quick.Files,
  35. {$IFDEF LINUX}
  36. FileInfo,
  37. {$ENDIF}
  38. {$ELSE}
  39. IOUtils,
  40. {$ENDIF}
  41. {$IFDEF ANDROID}
  42. Androidapi.JNI.Os,
  43. Androidapi.Helpers,
  44. Androidapi.JNI.JavaTypes,
  45. Androidapi.JNI.GraphicsContentViewText,
  46. {$ENDIF}
  47. {$IFDEF IOS}
  48. iOSapi.UIKit,
  49. Posix.SysSysctl,
  50. Posix.StdDef,
  51. iOSapi.Foundation,
  52. Macapi.ObjectiveC,
  53. Macapi.Helpers,
  54. {$ENDIF}
  55. {$IFDEF OSX}
  56. Macapi.Foundation,
  57. Macapi.Helpers,
  58. FMX.Helpers.Mac,
  59. Macapi.ObjectiveC,
  60. {$ENDIF}
  61. {$IFDEF POSIX}
  62. Posix.Unistd,
  63. {$ENDIF}
  64. DateUtils;
  65. type
  66. TLogEventType = (etInfo, etSuccess, etWarning, etError, etDebug, etTrace);
  67. TLogVerbose = set of TLogEventType;
  68. const
  69. LOG_ONLYERRORS = [etInfo,etError];
  70. LOG_ERRORSANDWARNINGS = [etInfo,etWarning,etError];
  71. LOG_TRACE = [etInfo,etError,etWarning,etTrace];
  72. LOG_ALL = [etInfo,etSuccess,etWarning,etError,etTrace];
  73. LOG_DEBUG = [etInfo,etSuccess,etWarning,etError,etDebug];
  74. {$IFDEF DELPHIXE7_UP}
  75. EventStr : array of string = ['INFO','SUCC','WARN','ERROR','DEBUG','TRACE'];
  76. {$ELSE}
  77. EventStr : array[0..5] of string = ('INFO','SUCC','WARN','ERROR','DEBUG','TRACE');
  78. {$ENDIF}
  79. type
  80. TPasswordComplexity = set of (pfIncludeNumbers,pfIncludeSigns);
  81. {$IFDEF MSWINDOWS}
  82. TEnvironmentPath = record
  83. EXEPATH : string;
  84. WINDOWS : string;
  85. SYSTEM : string;
  86. PROGRAMFILES : string;
  87. COMMONFILES : string;
  88. HOMEDRIVE : string;
  89. TEMP : string;
  90. USERPROFILE : string;
  91. INSTDRIVE : string;
  92. DESKTOP : string;
  93. STARTMENU : string;
  94. DESKTOP_ALLUSERS : string;
  95. STARTMENU_ALLUSERS : string;
  96. STARTUP : string;
  97. APPDATA : String;
  98. PROGRAMDATA : string;
  99. ALLUSERSPROFILE : string;
  100. end;
  101. {$ENDIF MSWINDOWS}
  102. {$IFNDEF FPC}
  103. TFileHelper = record helper for TFile
  104. {$IF DEFINED(MSWINDOWS) OR DEFINED(DELPHILINUX)}
  105. class function IsInUse(const FileName : string) : Boolean; static;
  106. {$ENDIF}
  107. class function GetSize(const FileName: String): Int64; static;
  108. end;
  109. TDirectoryHelper = record helper for TDirectory
  110. class function GetSize(const Path: String): Int64; static;
  111. end;
  112. {$ENDIF}
  113. {$IFDEF FPC}
  114. {$IFDEF LINUX}
  115. UINT = cardinal;
  116. {$ENDIF}
  117. PLASTINPUTINFO = ^LASTINPUTINFO;
  118. tagLASTINPUTINFO = record
  119. cbSize: UINT;
  120. dwTime: DWORD;
  121. end;
  122. LASTINPUTINFO = tagLASTINPUTINFO;
  123. TLastInputInfo = LASTINPUTINFO;
  124. type
  125. TCmdLineSwitchType = (clstValueNextParam, clstValueAppended);
  126. TCmdLineSwitchTypes = set of TCmdLineSwitchType;
  127. {$ENDIF}
  128. TCounter = record
  129. private
  130. fMaxValue : Integer;
  131. fCurrentValue : Integer;
  132. public
  133. property MaxValue : Integer read fMaxValue;
  134. procedure Init(aMaxValue : Integer);
  135. function Count : Integer;
  136. function CountIs(aValue : Integer) : Boolean;
  137. function Check : Boolean;
  138. procedure Reset;
  139. end;
  140. TTimeCounter = record
  141. private
  142. fCurrentTime : TDateTime;
  143. fDoneEvery : Integer;
  144. public
  145. property DoneEvery : Integer read fDoneEvery;
  146. procedure Init(MillisecondsToReach : Integer);
  147. function Check : Boolean;
  148. procedure Reset;
  149. end;
  150. EEnvironmentPath = class(Exception);
  151. EShellError = class(Exception);
  152. //generates a random password with complexity options
  153. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  154. //extracts file extension from a filename
  155. function ExtractFileNameWithoutExt(const FileName: string): string;
  156. //converts a Unix path to Windows path
  157. function UnixToWindowsPath(const UnixPath: string): string;
  158. //converts a Windows path to Unix path
  159. function WindowsToUnixPath(const WindowsPath: string): string;
  160. //corrects malformed urls
  161. function CorrectURLPath(cUrl : string) : string;
  162. {$IFDEF MSWINDOWS}
  163. //get typical environment paths as temp, desktop, etc
  164. procedure GetEnvironmentPaths;
  165. function GetSpecialFolderPath(folderID : Integer) : string;
  166. //checks if running on a 64bit OS
  167. function Is64bitOS : Boolean;
  168. //checks if is a console app
  169. function IsConsole : Boolean;
  170. //checks if compiled in debug mode
  171. {$ENDIF}
  172. function IsDebug : Boolean;
  173. {$IFDEF MSWINDOWS}
  174. //checks if running as a service
  175. function IsService : Boolean;
  176. //gets number of seconds without user interaction (mouse, keyboard)
  177. function SecondsIdle: DWord;
  178. //frees process memory not needed
  179. procedure FreeUnusedMem;
  180. //changes screen resolution
  181. function SetScreenResolution(Width, Height: integer): Longint;
  182. {$ENDIF MSWINDOWS}
  183. //returns last day of current month
  184. function LastDayCurrentMonth: TDateTime;
  185. {$IFDEF FPC}
  186. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  187. {$ENDIF}
  188. //checks if two datetimes are in same day
  189. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  190. //change Time of a DateTime
  191. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  192. //change Date of a DateTime
  193. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  194. //returns n times a char
  195. function FillStr(const C : Char; const Count : Byte) : string;
  196. //checks if string exists in array of string
  197. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  198. //checks if integer exists in array of integer
  199. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  200. //returns a number leading zero
  201. function Zeroes(const Number, Len : Int64) : string;
  202. //converts a number to thousand delimeter string
  203. function NumberToStr(const Number : Int64) : string;
  204. //returns n spaces
  205. function Spaces(const Count : Integer) : string;
  206. //returns current date as a string
  207. function NowStr : string;
  208. //returns a new GUID as string
  209. function NewGuidStr : string;
  210. //compare a string with a wildcard pattern (? or *)
  211. function IsLike(cText, Pattern: string) : Boolean;
  212. //Upper case for first letter
  213. function Capitalize(s: string): string;
  214. function CapitalizeWords(s: string): string;
  215. //returns current logged user
  216. function GetLoggedUserName : string;
  217. //returns computer name
  218. function GetComputerName : string;
  219. //Changes incorrect delims in path
  220. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  221. //Removes last segment of a path
  222. function RemoveLastPathSegment(cDir : string) : string;
  223. //finds swith in commandline params
  224. function ParamFindSwitch(const Switch : string) : Boolean;
  225. //gets value for a switch if exists
  226. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  227. //returns app name (filename based)
  228. function GetAppName : string;
  229. //returns app version (major & minor)
  230. function GetAppVersionStr: string;
  231. //returns app version full (major, minor, release & compiled)
  232. function GetAppVersionFullStr: string;
  233. //convert UTC DateTime to Local DateTime
  234. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  235. //convert Local DateTime to UTC DateTime
  236. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  237. //convert DateTime to GTM Time string
  238. function DateTimeToGMT(aDate : TDateTime) : string;
  239. //convert GMT Time string to DateTime
  240. function GMTToDateTime(aDate : string) : TDateTime;
  241. //convert DateTime to Json Date format
  242. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  243. //convert Json Date format to DateTime
  244. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  245. //count number of digits of a Integer
  246. function CountDigits(anInt: Cardinal): Cardinal; inline;
  247. //save stream to file
  248. procedure SaveStreamToFile(stream : TStream; const filename : string);
  249. //save stream to string
  250. function StreamToString(stream : TStream) : string;
  251. //returns a real comma separated text from stringlist
  252. function CommaText(aList : TStringList) : string;
  253. {$IFDEF MSWINDOWS}
  254. //process messages on console applications
  255. procedure ProcessMessages;
  256. //get last error message
  257. function GetLastOSError : String;
  258. {$ENDIF}
  259. {$IF DEFINED(FPC) AND DEFINED(MSWINDOWS)}
  260. function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
  261. {$ENDIF}
  262. function RemoveLastChar(const aText : string) : string;
  263. function DateTimeToSQL(aDateTime : TDateTime) : string;
  264. function IsInteger(const aValue : string) : Boolean;
  265. {$IFDEF MSWINDOWS}
  266. var
  267. path : TEnvironmentPath;
  268. {$ENDIF}
  269. implementation
  270. {TFileHelper}
  271. {$IFNDEF FPC}
  272. {$IFDEF MSWINDOWS}
  273. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  274. var
  275. HFileRes: HFILE;
  276. begin
  277. Result := False;
  278. if not FileExists(FileName) then Exit;
  279. try
  280. HFileRes := CreateFile(PChar(FileName)
  281. ,GENERIC_READ or GENERIC_WRITE
  282. ,0
  283. ,nil
  284. ,OPEN_EXISTING
  285. ,FILE_ATTRIBUTE_NORMAL
  286. ,0);
  287. Result := (HFileRes = INVALID_HANDLE_VALUE);
  288. if not(Result) then begin
  289. CloseHandle(HFileRes);
  290. end;
  291. except
  292. Result := True;
  293. end;
  294. end;
  295. {$ENDIF}
  296. {$IFDEF DELPHILINUX}
  297. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  298. var
  299. fs : TFileStream;
  300. begin
  301. try
  302. fs := TFileStream.Create(FileName, fmOpenReadWrite, fmShareExclusive);
  303. Result := True;
  304. fs.Free;
  305. except
  306. Result := False;
  307. end;
  308. end;
  309. {$ENDIF}
  310. {$IFDEF MSWINDOWS}
  311. class function TFileHelper.GetSize(const FileName: String): Int64;
  312. var
  313. info: TWin32FileAttributeData;
  314. begin
  315. Result := -1;
  316. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  317. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  318. end;
  319. {$ELSE}
  320. class function TFileHelper.GetSize(const FileName: String): Int64;
  321. var
  322. sr : TSearchRec;
  323. begin
  324. if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
  325. else Result := -1;
  326. end;
  327. {$ENDIF}
  328. {TDirectoryHelper}
  329. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  330. var
  331. filename : string;
  332. begin
  333. Result := -1;
  334. for filename in TDirectory.GetFiles(Path) do
  335. begin
  336. Result := Result + TFile.GetSize(filename);
  337. end;
  338. end;
  339. {$ENDIF}
  340. {other functions}
  341. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  342. const
  343. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  344. PassSigns = '@!&$';
  345. PassNumbers = '1234567890';
  346. var
  347. MinNumbers,
  348. MinSigns : Integer;
  349. NumNumbers,
  350. NumSigns : Integer;
  351. begin
  352. Result := '';
  353. Randomize;
  354. //fill all alfa
  355. repeat
  356. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  357. until (Length(Result) = PasswordLength);
  358. //checks if need include numbers
  359. if pfIncludeNumbers in Complexity then
  360. begin
  361. MinNumbers := Round(PasswordLength / 10 * 2);
  362. NumNumbers := 0;
  363. if MinNumbers = 0 then MinNumbers := 1;
  364. repeat
  365. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  366. Inc(NumNumbers);
  367. until NumNumbers = MinNumbers;
  368. end;
  369. //checks if need include signs
  370. if pfIncludeNumbers in Complexity then
  371. begin
  372. MinSigns := Round(PasswordLength / 10 * 1);
  373. NumSigns := 0;
  374. if MinSigns = 0 then MinSigns := 1;
  375. repeat
  376. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  377. Inc(NumSigns);
  378. until NumSigns = MinSigns;
  379. end;
  380. end;
  381. function ExtractFileNameWithoutExt(const FileName: string): string;
  382. begin
  383. Result := TPath.GetFileNameWithoutExtension(FileName);
  384. end;
  385. function UnixToWindowsPath(const UnixPath: string): string;
  386. begin
  387. Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  388. end;
  389. function WindowsToUnixPath(const WindowsPath: string): string;
  390. begin
  391. Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  392. end;
  393. function CorrectURLPath(cUrl : string) : string;
  394. var
  395. nurl : string;
  396. begin
  397. nurl := WindowsToUnixPath(cUrl);
  398. nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
  399. Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
  400. //TNetEncoding.Url.Encode()
  401. end;
  402. {$IFDEF MSWINDOWS}
  403. procedure GetEnvironmentPaths;
  404. begin
  405. //gets path
  406. path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
  407. path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
  408. path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
  409. path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
  410. path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
  411. path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
  412. path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
  413. path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
  414. path.INSTDRIVE := path.HOMEDRIVE;
  415. path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
  416. path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
  417. path.APPDATA:=GetSpecialFolderPath(CSIDL_APPDATA);
  418. //these paths fail if user is SYSTEM
  419. try
  420. path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
  421. path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
  422. path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
  423. path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
  424. path.STARTMENU_ALLUSERS := path.STARTMENU;
  425. path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
  426. except
  427. //
  428. end;
  429. end;
  430. function GetSpecialFolderPath(folderID : Integer) : string;
  431. var
  432. ppidl: PItemIdList;
  433. begin
  434. SHGetSpecialFolderLocation(0, folderID, ppidl);
  435. SetLength(Result, MAX_PATH);
  436. if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
  437. begin
  438. raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
  439. end;
  440. SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
  441. end;
  442. function Is64bitOS : Boolean;
  443. begin
  444. {$IFDEF WIN64}
  445. Result := True;
  446. {$ELSE}
  447. Result := False;
  448. {$ENDIF WIN64}
  449. end;
  450. function IsConsole: Boolean;
  451. begin
  452. {$IFDEF CONSOLE}
  453. Result := True;
  454. {$ELSE}
  455. Result := False;
  456. {$ENDIF CONSOLE}
  457. end;
  458. {$ENDIF}
  459. function IsDebug: Boolean;
  460. begin
  461. {$IFDEF DEBUG}
  462. Result := True;
  463. {$ELSE}
  464. Result := False;
  465. {$ENDIF DEBUG}
  466. end;
  467. {$IFDEF MSWINDOWS}
  468. function IsService : Boolean;
  469. begin
  470. //only working with my Quick.AppService unit
  471. try
  472. Result := (IsConsole) and (GetStdHandle(STD_OUTPUT_HANDLE) = 0);
  473. except
  474. Result := False;
  475. end;
  476. end;
  477. function SecondsIdle: DWord;
  478. var
  479. liInfo: TLastInputInfo;
  480. begin
  481. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  482. GetLastInputInfo(liInfo) ;
  483. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  484. end;
  485. procedure FreeUnusedMem;
  486. begin
  487. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  488. end;
  489. function SetScreenResolution(Width, Height: integer): Longint;
  490. var
  491. DeviceMode: TDeviceMode;
  492. begin
  493. with DeviceMode do
  494. begin
  495. dmSize := SizeOf(TDeviceMode);
  496. dmPelsWidth := Width;
  497. dmPelsHeight := Height;
  498. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  499. end;
  500. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  501. end;
  502. {$ENDIF MSWINDOWS}
  503. function LastDayCurrentMonth: TDateTime;
  504. begin
  505. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  506. end;
  507. {$IFDEF FPC}
  508. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  509. begin
  510. if aInclusive then
  511. Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
  512. else
  513. Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
  514. end;
  515. {$ENDIF}
  516. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  517. begin
  518. //Test: Result := MinutesBetween(cBefore,cNow) < 1;
  519. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
  520. end;
  521. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  522. var
  523. y, m, d : Word;
  524. begin
  525. DecodeDate(aDate,y,m,d);
  526. Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
  527. end;
  528. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  529. var
  530. h, m, s, ms : Word;
  531. begin
  532. DecodeTime(aDate,h,m,s,ms);
  533. Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
  534. end;
  535. function FillStr(const C : Char; const Count : Byte) : string;
  536. var
  537. i : Byte;
  538. begin
  539. Result := '';
  540. for i := 1 to Count do Result := Result + C;
  541. end;
  542. function StrInArray(const aValue : string; const aInArray : array of string) : Boolean;
  543. var
  544. s : string;
  545. begin
  546. for s in aInArray do
  547. begin
  548. if s = aValue then Exit(True);
  549. end;
  550. Result := False;
  551. end;
  552. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  553. var
  554. i : Integer;
  555. begin
  556. for i in aInArray do
  557. begin
  558. if i = aValue then Exit(True);
  559. end;
  560. Result := False;
  561. end;
  562. function Zeroes(const Number, Len : Int64) : string;
  563. begin
  564. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  565. else Result := IntToStr(Number);
  566. end;
  567. function NumberToStr(const Number : Int64) : string;
  568. begin
  569. try
  570. Result := FormatFloat('0,',Number);
  571. except
  572. Result := '#Error';
  573. end;
  574. end;
  575. function Spaces(const Count : Integer) : string;
  576. begin
  577. Result := FillStr(' ',Count);
  578. end;
  579. function NowStr : string;
  580. begin
  581. Result := DateTimeToStr(Now());
  582. end;
  583. function NewGuidStr : string;
  584. var
  585. guid : TGUID;
  586. begin
  587. guid.NewGuid;
  588. Result := guid.ToString
  589. //GUIDToString(guid);
  590. end;
  591. function IsLike(cText, Pattern: string) : Boolean;
  592. var
  593. i, n : Integer;
  594. match : Boolean;
  595. wildcard : Boolean;
  596. CurrentPattern : Char;
  597. begin
  598. Result := False;
  599. wildcard := False;
  600. cText := LowerCase(cText);
  601. Pattern := LowerCase(Pattern);
  602. match := False;
  603. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  604. if Pattern = '*' then
  605. begin
  606. Result := True;
  607. Exit;
  608. end;
  609. for i := 1 to cText.Length do
  610. begin
  611. CurrentPattern := Pattern[i];
  612. if CurrentPattern = '*' then wildcard := True;
  613. if wildcard then
  614. begin
  615. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  616. if (n > i) or (Pattern.Length = i) then
  617. begin
  618. Result := True;
  619. Exit;
  620. end;
  621. end
  622. else
  623. begin
  624. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  625. else match := False;
  626. end;
  627. end;
  628. Result := match;
  629. end;
  630. function Capitalize(s: string): string;
  631. begin
  632. Result := '';
  633. if s.Length = 0 then Exit;
  634. s := LowerCase(s,loUserLocale);
  635. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  636. end;
  637. function CapitalizeWords(s: string): string;
  638. var
  639. cword : string;
  640. begin
  641. Result := '';
  642. if s.Length = 0 then Exit;
  643. s := LowerCase(s,loUserLocale);
  644. for cword in s.Split([' ']) do
  645. begin
  646. if Result = '' then Result := Capitalize(cword)
  647. else Result := Result + ' ' + Capitalize(cword);
  648. end;
  649. end;
  650. function GetLoggedUserName : string;
  651. {$IFDEF MSWINDOWS}
  652. const
  653. cnMaxUserNameLen = 254;
  654. var
  655. sUserName : string;
  656. dwUserNameLen : DWord;
  657. begin
  658. dwUserNameLen := cnMaxUserNameLen-1;
  659. SetLength( sUserName, cnMaxUserNameLen );
  660. GetUserName(PChar( sUserName ),dwUserNameLen );
  661. SetLength( sUserName, dwUserNameLen );
  662. Result := sUserName;
  663. end;
  664. {$ELSE}
  665. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  666. begin
  667. Result := GetEnvironmentVariable('USERNAME');
  668. end;
  669. {$ELSE}
  670. begin
  671. {$IFDEF POSIX}
  672. Result := string(getlogin);
  673. {$ELSE}
  674. Result := 'N/A';
  675. {$ENDIF}
  676. //raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
  677. end;
  678. {$ENDIF}
  679. {$ENDIF}
  680. {$IFDEF IOS}
  681. function GetDeviceModel : String;
  682. var
  683. size : size_t;
  684. buffer : array of Byte;
  685. begin
  686. sysctlbyname('hw.machine',nil,@size,nil,0);
  687. if size > 0 then
  688. begin
  689. SetLength(buffer, size);
  690. sysctlbyname('hw.machine',@buffer[0],@size,nil,0);
  691. Result := UTF8ToString(MarshaledAString(buffer));
  692. end
  693. else Result := EmptyStr;
  694. end;
  695. {$ENDIF}
  696. function GetComputerName : string;
  697. {$IFDEF MSWINDOWS}
  698. var
  699. dwLength: dword;
  700. begin
  701. dwLength := 253;
  702. SetLength(Result, dwLength+1);
  703. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  704. Result := pchar(result);
  705. end;
  706. {$ELSE}
  707. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  708. begin
  709. Result := GetEnvironmentVariable('COMPUTERNAME');
  710. end;
  711. {$ELSE} //Android gets model name
  712. {$IFDEF NEXTGEN}
  713. begin
  714. {$IFDEF ANDROID}
  715. Result := JStringToString(TJBuild.JavaClass.MODEL);
  716. {$ELSE} //IOS
  717. Result := GetDeviceModel;
  718. {$ENDIF}
  719. end;
  720. {$ELSE}
  721. {$IFDEF DELPHILINUX}
  722. var
  723. puser : PAnsiChar;
  724. begin
  725. //puser := '';
  726. try
  727. if gethostname(puser,_SC_HOST_NAME_MAX) = 0 then Result := string(puser)
  728. else Result := 'N/A';
  729. except
  730. Result := 'N/A';
  731. end;
  732. end;
  733. {$ELSE} //OSX
  734. begin
  735. Result := NSStrToStr(TNSHost.Wrap(TNSHost.OCClass.currentHost).localizedName);
  736. end;
  737. {$ENDIF}
  738. {$ENDIF}
  739. {$ENDIF}
  740. {$ENDIF}
  741. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  742. begin
  743. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  744. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  745. end;
  746. function RemoveLastPathSegment(cDir : string) : string;
  747. var
  748. posi : Integer;
  749. delim : Char;
  750. EndsWithDelim : Boolean;
  751. begin
  752. if cDir.Contains('\') then delim := '\'
  753. else if cDir.Contains('/') then delim := '/'
  754. else
  755. begin
  756. Result := '';
  757. Exit;
  758. end;
  759. NormalizePathDelim(cDir,delim);
  760. if cDir.EndsWith(delim) then
  761. begin
  762. cDir := Copy(cDir,1,cDir.Length-1);
  763. EndsWithDelim := True;
  764. end
  765. else EndsWithDelim := False;
  766. if cDir.CountChar(delim) > 1 then posi := cDir.LastDelimiter(delim)
  767. else posi := Pos(delim,cDir)-1;
  768. if posi = cDir.Length then posi := 0;
  769. Result := Copy(cDir,1,posi);
  770. if (Result <> '') and (EndsWithDelim) then Result := Result + delim;
  771. end;
  772. function ParamFindSwitch(const Switch : string) : Boolean;
  773. begin
  774. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  775. end;
  776. {$IFDEF FPC}
  777. function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
  778. const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
  779. type
  780. TCompareProc = function(const S1, S2: string): Boolean;
  781. var
  782. Param: string;
  783. I, ValueOfs,
  784. SwitchLen, ParamLen: Integer;
  785. SameSwitch: TCompareProc;
  786. begin
  787. Result := False;
  788. Value := '';
  789. if IgnoreCase then
  790. SameSwitch := SameText else
  791. SameSwitch := SameStr;
  792. SwitchLen := Switch.Length;
  793. for I := 1 to ParamCount do
  794. begin
  795. Param := ParamStr(I);
  796. if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
  797. begin
  798. ParamLen := Param.Length;
  799. // Look for an appended value if the param is longer than the switch
  800. if (ParamLen > SwitchLen + 1) then
  801. begin
  802. // If not looking for appended value switches then this is not a matching switch
  803. if not (clstValueAppended in SwitchTypes) then
  804. Continue;
  805. ValueOfs := SwitchLen + 1;
  806. if Param.Chars[ValueOfs] = ':' then
  807. Inc(ValueOfs);
  808. Value := Param.SubString(ValueOfs, MaxInt);
  809. end
  810. // If the next param is not a switch, then treat it as the value
  811. else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
  812. not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
  813. Value := ParamStr(I+1);
  814. Result := True;
  815. Break;
  816. end;
  817. end;
  818. end;
  819. {$ENDIF}
  820. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  821. begin
  822. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  823. end;
  824. function GetAppName : string;
  825. begin
  826. Result := ExtractFilenameWithoutExt(ParamStr(0));
  827. end;
  828. function GetAppVersionStr: string;
  829. {$IFDEF MSWINDOWS}
  830. var
  831. Rec: LongRec;
  832. ver : Cardinal;
  833. begin
  834. ver := GetFileVersion(ParamStr(0));
  835. if ver <> Cardinal(-1) then
  836. begin
  837. Rec := LongRec(ver);
  838. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  839. end
  840. else Result := '';
  841. end;
  842. {$ELSE}
  843. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  844. var
  845. version : TProgramVersion;
  846. begin
  847. if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
  848. else Result := '';
  849. end;
  850. {$ELSE}
  851. {$IFDEF NEXTGEN}
  852. {$IFDEF ANDROID}
  853. var
  854. PkgInfo : JPackageInfo;
  855. begin
  856. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  857. Result := IntToStr(PkgInfo.VersionCode);
  858. end;
  859. {$ELSE} //IOS
  860. var
  861. AppKey: Pointer;
  862. AppBundle: NSBundle;
  863. BuildStr : NSString;
  864. begin
  865. try
  866. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  867. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  868. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  869. Result := UTF8ToString(BuildStr.UTF8String);
  870. except
  871. Result := '';
  872. end;
  873. end;
  874. {$ENDIF}
  875. {$ELSE} //OSX
  876. {$IFDEF OSX}
  877. var
  878. AppKey: Pointer;
  879. AppBundle: NSBundle;
  880. BuildStr : NSString;
  881. begin
  882. try
  883. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  884. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  885. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  886. Result := UTF8ToString(BuildStr.UTF8String);
  887. except
  888. Result := '';
  889. end;
  890. end;
  891. {$ELSE}
  892. begin
  893. Result := '';
  894. end;
  895. {$ENDIF}
  896. {$ENDIF}
  897. {$ENDIF}
  898. {$ENDIF}
  899. function GetAppVersionFullStr: string;
  900. {$IFDEF MSWINDOWS}
  901. var
  902. Exe: string;
  903. Size, Handle: DWORD;
  904. Buffer: TBytes;
  905. FixedPtr: PVSFixedFileInfo;
  906. begin
  907. Result := '';
  908. Exe := ParamStr(0);
  909. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  910. if Size = 0 then
  911. begin
  912. //RaiseLastOSError;
  913. //no version info in file
  914. Exit;
  915. end;
  916. SetLength(Buffer, Size);
  917. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  918. RaiseLastOSError;
  919. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  920. RaiseLastOSError;
  921. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  922. begin
  923. Result := Format('%d.%d',
  924. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  925. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  926. end
  927. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  928. begin
  929. Result := Format('%d.%d.%d',
  930. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  931. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  932. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  933. end
  934. else
  935. begin
  936. Result := Format('%d.%d.%d.%d',
  937. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  938. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  939. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  940. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  941. end;
  942. end;
  943. {$ELSE}
  944. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  945. var
  946. version : TProgramVersion;
  947. begin
  948. if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
  949. else Result := '';
  950. end;
  951. {$ELSE}
  952. {$IFDEF NEXTGEN}
  953. {$IFDEF ANDROID}
  954. var
  955. PkgInfo : JPackageInfo;
  956. begin
  957. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  958. Result := JStringToString(PkgInfo.versionName);
  959. end;
  960. {$ELSE} //IOS
  961. var
  962. AppKey: Pointer;
  963. AppBundle: NSBundle;
  964. BuildStr : NSString;
  965. begin
  966. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  967. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  968. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  969. Result := UTF8ToString(BuildStr.UTF8String);
  970. end;
  971. {$ENDIF}
  972. {$ELSE}
  973. {$IFDEF OSX}
  974. var
  975. AppKey: Pointer;
  976. AppBundle: NSBundle;
  977. BuildStr : NSString;
  978. begin
  979. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  980. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  981. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  982. Result := UTF8ToString(BuildStr.UTF8String);
  983. end;
  984. {$ELSE}
  985. begin
  986. Result := '';
  987. end;
  988. {$ENDIF}
  989. {$ENDIF}
  990. {$ENDIF}
  991. {$ENDIF}
  992. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  993. begin
  994. {$IFDEF FPC}
  995. Result := LocalTimeToUniversal(GMTTime);
  996. {$ELSE}
  997. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  998. {$ENDIF}
  999. end;
  1000. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  1001. begin
  1002. {$IFDEF FPC}
  1003. Result := UniversalTimeToLocal(Localtime);
  1004. {$ELSE}
  1005. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  1006. {$ENDIF}
  1007. end;
  1008. function DateTimeToGMT(aDate : TDateTime) : string;
  1009. var
  1010. FmtSettings : TFormatSettings;
  1011. begin
  1012. FmtSettings.DateSeparator := '-';
  1013. FmtSettings.TimeSeparator := ':';
  1014. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1015. Result := DateTimeToStr(aDate,FmtSettings).Trim;
  1016. end;
  1017. function GMTToDateTime(aDate : string) : TDateTime;
  1018. var
  1019. FmtSettings : TFormatSettings;
  1020. begin
  1021. FmtSettings.DateSeparator := '-';
  1022. FmtSettings.TimeSeparator := ':';
  1023. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1024. Result := StrToDateTime(aDate,FmtSettings);
  1025. end;
  1026. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  1027. {$IFNDEF DELPHIXE7_UP}
  1028. var
  1029. FmtSettings : TFormatSettings;
  1030. {$ENDIF}
  1031. begin
  1032. {$IFDEF DELPHIXE7_UP}
  1033. Result := DateToISO8601(aDateTime);
  1034. {$ELSE}
  1035. FmtSettings.DateSeparator := '-';
  1036. FmtSettings.TimeSeparator := ':';
  1037. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1038. Result := DateTimeToStr(aDateTime,FmtSettings).Trim;
  1039. {$ENDIF}
  1040. end;
  1041. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  1042. {$IFNDEF DELPHIXE7_UP}
  1043. var
  1044. FmtSettings : TFormatSettings;
  1045. {$ENDIF}
  1046. {$IFDEF FPC}
  1047. var
  1048. jdate : string;
  1049. {$ENDIF}
  1050. begin
  1051. {$IFDEF DELPHIXE7_UP}
  1052. Result := ISO8601ToDate(aJsonDate);
  1053. {$ELSE}
  1054. FmtSettings.DateSeparator := '-';
  1055. FmtSettings.TimeSeparator := ':';
  1056. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1057. {$IFDEF FPC}
  1058. jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
  1059. jdate := Copy(jdate,1,Pos('.',jdate)-1);
  1060. Result := StrToDateTime(jdate,FmtSettings);
  1061. {$ELSE}
  1062. Result := StrToDateTime(aJsonDate,FmtSettings);
  1063. {$ENDIF}
  1064. {$ENDIF}
  1065. end;
  1066. function CountDigits(anInt: Cardinal): Cardinal; inline;
  1067. var
  1068. cmp: Cardinal;
  1069. begin
  1070. cmp := 10;
  1071. Result := 1;
  1072. while (Result < 10) and (cmp <= anInt) do
  1073. begin
  1074. cmp := cmp*10;
  1075. Inc(Result);
  1076. end;
  1077. end;
  1078. procedure SaveStreamToFile(stream : TStream; const filename : string);
  1079. var
  1080. fs : TFileStream;
  1081. begin
  1082. fs := TFileStream.Create(filename,fmCreate);
  1083. try
  1084. stream.Seek(0,soBeginning);
  1085. fs.CopyFrom(stream,stream.Size);
  1086. finally
  1087. fs.Free;
  1088. end;
  1089. end;
  1090. function StreamToString(stream : TStream) : string;
  1091. var
  1092. ss : TStringStream;
  1093. begin
  1094. if stream = nil then Exit;
  1095. ss := TStringStream.Create;
  1096. try
  1097. stream.Seek(0,soBeginning);
  1098. ss.CopyFrom(stream,stream.Size);
  1099. Result := ss.DataString;
  1100. finally
  1101. ss.Free;
  1102. end;
  1103. end;
  1104. function CommaText(aList : TStringList) : string;
  1105. var
  1106. value : string;
  1107. sb : TStringBuilder;
  1108. begin
  1109. if aList.Text = '' then Exit;
  1110. sb := TStringBuilder.Create;
  1111. try
  1112. for value in aList do
  1113. begin
  1114. sb.Append(value);
  1115. sb.Append(',');
  1116. end;
  1117. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1118. finally
  1119. sb.Free;
  1120. end;
  1121. end;
  1122. { TCounter }
  1123. procedure TCounter.Init(aMaxValue : Integer);
  1124. begin
  1125. fMaxValue := aMaxValue;
  1126. fCurrentValue := 0;
  1127. end;
  1128. function TCounter.Count : Integer;
  1129. begin
  1130. Result := fCurrentValue;
  1131. end;
  1132. function TCounter.CountIs(aValue : Integer) : Boolean;
  1133. begin
  1134. Result := fCurrentValue = aValue;
  1135. end;
  1136. function TCounter.Check : Boolean;
  1137. begin
  1138. if fCurrentValue = fMaxValue then
  1139. begin
  1140. Result := True;
  1141. Reset;
  1142. end
  1143. else
  1144. begin
  1145. Result := False;
  1146. Inc(fCurrentValue);
  1147. end;
  1148. end;
  1149. procedure TCounter.Reset;
  1150. begin
  1151. fCurrentValue := fMaxValue;
  1152. end;
  1153. { TimeCounter }
  1154. procedure TTimeCounter.Init(MillisecondsToReach : Integer);
  1155. begin
  1156. fDoneEvery := MillisecondsToReach;
  1157. end;
  1158. function TTimeCounter.Check : Boolean;
  1159. begin
  1160. if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
  1161. begin
  1162. fCurrentTime := Now();
  1163. Result := True;
  1164. end
  1165. else Result := False;
  1166. end;
  1167. procedure TTimeCounter.Reset;
  1168. begin
  1169. fCurrentTime := Now();
  1170. end;
  1171. {$IFDEF MSWINDOWS}
  1172. procedure ProcessMessages;
  1173. var
  1174. Msg: TMsg;
  1175. begin
  1176. while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
  1177. begin
  1178. TranslateMessage(Msg);
  1179. DispatchMessage(Msg);
  1180. end;
  1181. end;
  1182. function GetLastOSError: String;
  1183. begin
  1184. Result := SysErrorMessage(Windows.GetLastError);
  1185. end;
  1186. {$ENDIF}
  1187. function RemoveLastChar(const aText : string) : string;
  1188. begin
  1189. Result := aText.Remove(aText.Length - 1);
  1190. end;
  1191. function DateTimeToSQL(aDateTime : TDateTime) : string;
  1192. begin
  1193. Result := FormatDateTime('YYYYMMDD hh:mm:ss',aDateTime);
  1194. end;
  1195. function IsInteger(const aValue : string) : Boolean;
  1196. var
  1197. i : Integer;
  1198. begin
  1199. Result := TryStrToInt(aValue,i);
  1200. end;
  1201. {$IFDEF MSWINDOWS}
  1202. initialization
  1203. try
  1204. GetEnvironmentPaths;
  1205. except
  1206. on E : Exception do
  1207. begin
  1208. if not IsService then
  1209. begin
  1210. if IsConsole then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
  1211. else raise EEnvironmentPath.Create(Format('Get environment path error: %s',[E.Message]));
  1212. end;
  1213. end;
  1214. end;
  1215. {$ENDIF}
  1216. end.