Quick.Commons.pas 36 KB

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