Quick.Commons.pas 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 Kike Pérez
  3. Unit : Quick.Commons
  4. Description : Common functions
  5. Author : Kike Pérez
  6. Version : 2.0
  7. Created : 14/07/2017
  8. Modified : 01/01/2021
  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, etDone, etTrace, etCritical, etException);
  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, etDebug, etDone, etTrace, etCritical, etException];
  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. TEnvironmentPath = record
  81. EXEPATH : string;
  82. {$IFDEF MSWINDOWS}
  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. {$ENDIF MSWINDOWS}
  100. end;
  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. {$IFNDEF FPC}
  150. {$IFNDEF DELPHIXE7_UP}
  151. TArrayUtil<T> = class
  152. class procedure Delete(var aArray : TArray<T>; aIndex : Integer);
  153. end;
  154. {$ENDIF}
  155. TArrayOfStringHelper = record helper for TArray<string>
  156. public
  157. function Any : Boolean; overload;
  158. function Any(const aValue : string) : Boolean; overload;
  159. function Add(const aValue : string) : Integer;
  160. function AddIfNotExists(const aValue : string; aCaseSense : Boolean = False) : Integer;
  161. function Remove(const aValue : string) : Boolean;
  162. function Exists(const aValue : string) : Boolean;
  163. function Count : Integer;
  164. end;
  165. TDelegate<T> = reference to procedure(Value : T);
  166. {$ENDIF}
  167. TPairItem = record
  168. Name : string;
  169. Value : string;
  170. constructor Create(const aName, aValue : string);
  171. end;
  172. TPairList = class
  173. type
  174. TPairEnumerator = class
  175. private
  176. fArray : ^TArray<TPairItem>;
  177. fIndex : Integer;
  178. function GetCurrent: TPairItem;
  179. public
  180. constructor Create(var aArray: TArray<TPairItem>);
  181. property Current : TPairItem read GetCurrent;
  182. function MoveNext: Boolean;
  183. end;
  184. private
  185. fItems : TArray<TPairItem>;
  186. public
  187. function GetEnumerator : TPairEnumerator;
  188. function GetValue(const aName : string) : string;
  189. function GetPair(const aName : string) : TPairItem;
  190. function Add(aPair : TPairItem) : Integer; overload;
  191. function Add(const aName, aValue : string) : Integer; overload;
  192. procedure AddOrUpdate(const aName, aValue : string);
  193. function Exists(const aName : string) : Boolean;
  194. function Remove(const aName : string) : Boolean;
  195. function Count : Integer;
  196. property Items[const aName : string] : string read GetValue write AddOrUpdate;
  197. function ToArray : TArray<TPairItem>;
  198. procedure FromArray(aValue : TArray<TPairItem>);
  199. procedure Clear;
  200. end;
  201. EEnvironmentPath = class(Exception);
  202. EShellError = class(Exception);
  203. //generates a random password with complexity options
  204. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  205. //generates a random string
  206. function RandomString(const aLength: Integer) : string;
  207. //extracts file extension from a filename
  208. function ExtractFileNameWithoutExt(const FileName: string): string;
  209. //converts a Unix path to Windows path
  210. function UnixToWindowsPath(const UnixPath: string): string;
  211. //converts a Windows path to Unix path
  212. function WindowsToUnixPath(const WindowsPath: string): string;
  213. //corrects malformed urls
  214. function CorrectURLPath(cUrl : string) : string;
  215. //get typical environment paths as temp, desktop, etc
  216. procedure GetEnvironmentPaths;
  217. {$IFDEF MSWINDOWS}
  218. function GetSpecialFolderPath(folderID : Integer) : string;
  219. //checks if running on a 64bit OS
  220. function Is64bitOS : Boolean;
  221. //checks if is a console app
  222. function IsConsole : Boolean;
  223. function HasConsoleOutput : Boolean;
  224. //checks if compiled in debug mode
  225. {$ENDIF}
  226. function IsDebug : Boolean;
  227. {$IFDEF MSWINDOWS}
  228. //checks if running as a service
  229. function IsService : Boolean;
  230. //gets number of seconds without user interaction (mouse, keyboard)
  231. function SecondsIdle: DWord;
  232. //frees process memory not needed
  233. procedure FreeUnusedMem;
  234. //changes screen resolution
  235. function SetScreenResolution(Width, Height: integer): Longint;
  236. {$ENDIF MSWINDOWS}
  237. //returns last day of current month
  238. function LastDayCurrentMonth: TDateTime;
  239. {$IFDEF FPC}
  240. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  241. {$ENDIF}
  242. //checks if two datetimes are in same day
  243. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  244. //change Time of a DateTime
  245. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  246. //change Date of a DateTime
  247. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  248. //returns n times a char
  249. function FillStr(const C : Char; const Count : Integer) : string;
  250. //checks if string exists in array of string
  251. function StrInArray(const aValue : string; const aInArray : array of string; aCaseSensitive : Boolean = True) : Boolean;
  252. //checks if integer exists in array of integer
  253. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  254. //check if array is empty
  255. function IsEmptyArray(aArray : TArray<string>) : Boolean; overload;
  256. function IsEmptyArray(aArray : TArray<Integer>) : Boolean; overload;
  257. //returns a number leading zero
  258. function Zeroes(const Number, Len : Int64) : string;
  259. //converts a number to thousand delimeter string
  260. function NumberToStr(const Number : Int64) : string;
  261. //returns n spaces
  262. function Spaces(const Count : Integer) : string;
  263. //returns current date as a string
  264. function NowStr : string;
  265. //returns a new GUID as string
  266. function NewGuidStr : string;
  267. //compare a string with a wildcard pattern (? or *)
  268. function IsLike(cText, Pattern: string) : Boolean;
  269. //Upper case for first letter
  270. function Capitalize(s: string): string;
  271. function CapitalizeWords(s: string): string;
  272. //returns current logged user
  273. function GetLoggedUserName : string;
  274. //returns computer name
  275. function GetComputerName : string;
  276. //extract domain and user name from user login
  277. function ExtractDomainAndUser(const aUser : string; out oDomain, oUser : string) : Boolean;
  278. //Changes incorrect delims in path
  279. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  280. //combine paths normalized with delim
  281. function CombinePaths(const aFirstPath, aSecondPath: string; aDelim : Char): string;
  282. //Removes firs segment of a path
  283. function RemoveFirstPathSegment(const cdir : string) : string;
  284. //Removes last segment of a path
  285. function RemoveLastPathSegment(const cDir : string) : string;
  286. //returns path delimiter if found
  287. function GetPathDelimiter(const aPath : string) : string;
  288. //returns first segment of a path
  289. function GetFirstPathSegment(const aPath : string) : string;
  290. //returns last segment of a path
  291. function GetLastPathSegment(const aPath : string) : string;
  292. //finds swith in commandline params
  293. function ParamFindSwitch(const Switch : string) : Boolean;
  294. //gets value for a switch if exists
  295. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  296. //returns app name (filename based)
  297. function GetAppName : string;
  298. //returns app version (major & minor)
  299. function GetAppVersionStr: string;
  300. //returns app version full (major, minor, release & compiled)
  301. function GetAppVersionFullStr: string;
  302. //convert UTC DateTime to Local DateTime
  303. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  304. //convert Local DateTime to UTC DateTime
  305. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  306. //convert DateTime to GTM Time string
  307. function DateTimeToGMT(aDate : TDateTime) : string;
  308. //convert GMT Time string to DateTime
  309. function GMTToDateTime(aDate : string) : TDateTime;
  310. //convert DateTime to Json Date format
  311. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  312. //convert Json Date format to DateTime
  313. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  314. //count number of digits of a Integer
  315. function CountDigits(anInt: Cardinal): Cardinal; inline;
  316. //count times a string is present in other string
  317. function CountStr(const aFindStr, aSourceStr : string) : Integer;
  318. //save stream to file
  319. procedure SaveStreamToFile(aStream : TStream; const aFilename : string);
  320. //save stream to string
  321. function StreamToString(aStream : TStream) : string;
  322. function StreamToString2(const aStream: TStream; const aEncoding: TEncoding): string;
  323. //save string to stream
  324. procedure StringToStream(const aStr : string; aStream : TStream);
  325. procedure StringToStream2(const aStr : string; aStream : TStream);
  326. //returns a real comma separated text from stringlist
  327. function CommaText(aList : TStringList) : string; overload;
  328. //returns a real comma separated text from array of string
  329. function CommaText(aArray : TArray<string>) : string; overload;
  330. //returns a string CRLF from array of string
  331. function ArrayToString(aArray : TArray<string>) : string;
  332. //converts TStrings to array
  333. function StringsToArray(aStrings : TStrings) : TArray<string>;
  334. {$IFDEF MSWINDOWS}
  335. //process messages on console applications
  336. procedure ProcessMessages;
  337. //get last error message
  338. function GetLastOSError : String;
  339. {$ENDIF}
  340. {$IF DEFINED(FPC) AND DEFINED(MSWINDOWS)}
  341. function GetLastInputInfo(var plii: TLastInputInfo): BOOL;stdcall; external 'user32' name 'GetLastInputInfo';
  342. {$ENDIF}
  343. function RemoveLastChar(const aText : string) : string;
  344. function DateTimeToSQL(aDateTime : TDateTime) : string;
  345. function IsInteger(const aValue : string) : Boolean;
  346. function IsFloat(const aValue : string) : Boolean;
  347. function IsBoolean(const aValue : string) : Boolean;
  348. //extract a substring and deletes from source string
  349. function ExtractStr(var vSource : string; aIndex : Integer; aCount : Integer) : string;
  350. //get first string between string delimiters
  351. function GetSubString(const aSource, aFirstDelimiter, aLastDelimiter : string) : string;
  352. //get double quoted or dequoted string
  353. function DbQuotedStr(const str : string): string;
  354. function UnDbQuotedStr(const str: string) : string;
  355. //get simple quoted or dequoted string
  356. function SpQuotedStr(const str : string): string;
  357. function UnSpQuotedStr(const str : string): string;
  358. //ternary operator
  359. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : string) : string; overload;
  360. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Integer) : Integer; overload;
  361. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Extended) : Extended; overload;
  362. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : TObject) : TObject; overload;
  363. var
  364. path : TEnvironmentPath;
  365. //Enabled if QuickService is defined
  366. IsQuickServiceApp : Boolean;
  367. implementation
  368. {TFileHelper}
  369. {$IFNDEF FPC}
  370. {$IFDEF MSWINDOWS}
  371. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  372. var
  373. HFileRes: HFILE;
  374. begin
  375. Result := False;
  376. if not FileExists(FileName) then Exit;
  377. try
  378. HFileRes := CreateFile(PChar(FileName)
  379. ,GENERIC_READ or GENERIC_WRITE
  380. ,0
  381. ,nil
  382. ,OPEN_EXISTING
  383. ,FILE_ATTRIBUTE_NORMAL
  384. ,0);
  385. Result := (HFileRes = INVALID_HANDLE_VALUE);
  386. if not(Result) then begin
  387. CloseHandle(HFileRes);
  388. end;
  389. except
  390. Result := True;
  391. end;
  392. end;
  393. {$ENDIF}
  394. {$IFDEF DELPHILINUX}
  395. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  396. var
  397. fs : TFileStream;
  398. begin
  399. try
  400. fs := TFileStream.Create(FileName, fmOpenReadWrite, fmShareExclusive);
  401. Result := True;
  402. fs.Free;
  403. except
  404. Result := False;
  405. end;
  406. end;
  407. {$ENDIF}
  408. {$IFDEF MSWINDOWS}
  409. class function TFileHelper.GetSize(const FileName: String): Int64;
  410. var
  411. info: TWin32FileAttributeData;
  412. begin
  413. Result := -1;
  414. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  415. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  416. end;
  417. {$ELSE}
  418. class function TFileHelper.GetSize(const FileName: String): Int64;
  419. var
  420. sr : TSearchRec;
  421. begin
  422. if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
  423. else Result := -1;
  424. end;
  425. {$ENDIF}
  426. {TDirectoryHelper}
  427. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  428. var
  429. filename : string;
  430. begin
  431. Result := -1;
  432. for filename in TDirectory.GetFiles(Path) do
  433. begin
  434. Result := Result + TFile.GetSize(filename);
  435. end;
  436. end;
  437. {$ENDIF}
  438. {other functions}
  439. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  440. const
  441. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  442. PassSigns = '@!&$';
  443. PassNumbers = '1234567890';
  444. var
  445. MinNumbers,
  446. MinSigns : Integer;
  447. NumNumbers,
  448. NumSigns : Integer;
  449. begin
  450. Result := '';
  451. Randomize;
  452. //fill all alfa
  453. repeat
  454. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  455. until (Length(Result) = PasswordLength);
  456. //checks if need include numbers
  457. if pfIncludeNumbers in Complexity then
  458. begin
  459. MinNumbers := Round(PasswordLength / 10 * 2);
  460. NumNumbers := 0;
  461. if MinNumbers = 0 then MinNumbers := 1;
  462. repeat
  463. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  464. Inc(NumNumbers);
  465. until NumNumbers = MinNumbers;
  466. end;
  467. //checks if need include signs
  468. if pfIncludeSigns in Complexity then
  469. begin
  470. MinSigns := Round(PasswordLength / 10 * 1);
  471. NumSigns := 0;
  472. if MinSigns = 0 then MinSigns := 1;
  473. repeat
  474. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  475. Inc(NumSigns);
  476. until NumSigns = MinSigns;
  477. end;
  478. end;
  479. function RandomString(const aLength: Integer) : string;
  480. const
  481. chars : string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
  482. var
  483. i : Integer;
  484. clong : Integer;
  485. begin
  486. clong := High(chars);
  487. SetLength(Result, aLength);
  488. for i := 1 to aLength do
  489. begin
  490. Result[i] := chars[Random(clong) + 1];
  491. end;
  492. end;
  493. function ExtractFileNameWithoutExt(const FileName: string): string;
  494. begin
  495. Result := TPath.GetFileNameWithoutExtension(FileName);
  496. end;
  497. function UnixToWindowsPath(const UnixPath: string): string;
  498. begin
  499. Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  500. end;
  501. function WindowsToUnixPath(const WindowsPath: string): string;
  502. begin
  503. Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  504. end;
  505. function CorrectURLPath(cUrl : string) : string;
  506. var
  507. nurl : string;
  508. begin
  509. nurl := WindowsToUnixPath(cUrl);
  510. nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
  511. Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
  512. //TNetEncoding.Url.Encode()
  513. end;
  514. procedure GetEnvironmentPaths;
  515. begin
  516. //gets path
  517. path.EXEPATH := TPath.GetDirectoryName(ParamStr(0));
  518. {$IFDEF MSWINDOWS}
  519. path.WINDOWS := SysUtils.GetEnvironmentVariable('windir');
  520. path.PROGRAMFILES := SysUtils.GetEnvironmentVariable('ProgramFiles');
  521. path.COMMONFILES := SysUtils.GetEnvironmentVariable('CommonProgramFiles(x86)');
  522. path.HOMEDRIVE := SysUtils.GetEnvironmentVariable('SystemDrive');
  523. path.USERPROFILE := SysUtils.GetEnvironmentVariable('USERPROFILE');
  524. path.PROGRAMDATA := SysUtils.GetEnvironmentVariable('ProgramData');
  525. path.ALLUSERSPROFILE := SysUtils.GetEnvironmentVariable('AllUsersProfile');
  526. path.INSTDRIVE := path.HOMEDRIVE;
  527. path.TEMP := SysUtils.GetEnvironmentVariable('TEMP');
  528. //these paths fail if user is SYSTEM
  529. try
  530. path.SYSTEM := GetSpecialFolderPath(CSIDL_SYSTEM);
  531. path.APPDATA := GetSpecialFolderPath(CSIDL_APPDATA);
  532. path.DESKTOP := GetSpecialFolderPath(CSIDL_DESKTOP);
  533. path.DESKTOP_ALLUSERS := GetSpecialFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY);
  534. path.STARTMENU:=GetSpecialFolderPath(CSIDL_PROGRAMS);
  535. path.STARTMENU_ALLUSERS:=GetSpecialFolderPath(CSIDL_COMMON_PROGRAMS);
  536. path.STARTMENU_ALLUSERS := path.STARTMENU;
  537. path.STARTUP:=GetSpecialFolderPath(CSIDL_STARTUP);
  538. except
  539. //
  540. end;
  541. {$ENDIF}
  542. end;
  543. {$IFDEF MSWINDOWS}
  544. function GetSpecialFolderPath(folderID : Integer) : string;
  545. var
  546. ppidl: PItemIdList;
  547. begin
  548. SHGetSpecialFolderLocation(0, folderID, ppidl);
  549. SetLength(Result, MAX_PATH);
  550. if not SHGetPathFromIDList(ppidl,{$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}) then
  551. begin
  552. raise EShellError.create(Format('GetSpecialFolderPath: Invalid PIPL (%d)',[folderID]));
  553. end;
  554. SetLength(Result, lStrLen({$IFDEF FPC}PAnsiChar(Result){$ELSE}PChar(Result){$ENDIF}));
  555. end;
  556. function Is64bitOS : Boolean;
  557. begin
  558. {$IFDEF WIN64}
  559. Result := True;
  560. {$ELSE}
  561. Result := False;
  562. {$ENDIF WIN64}
  563. end;
  564. function IsConsole: Boolean;
  565. begin
  566. {$IFDEF CONSOLE}
  567. Result := True;
  568. {$ELSE}
  569. Result := False;
  570. {$ENDIF CONSOLE}
  571. end;
  572. {$ENDIF}
  573. function HasConsoleOutput : Boolean;
  574. {$IFDEF MSWINDOWS}
  575. var
  576. stout : THandle;
  577. begin
  578. try
  579. stout := GetStdHandle(Std_Output_Handle);
  580. Win32Check(stout <> Invalid_Handle_Value);
  581. Result := stout <> 0;
  582. except
  583. Result := False;
  584. end;
  585. end;
  586. {$ELSE}
  587. begin
  588. Result := IsConsole;
  589. end;
  590. {$ENDIF}
  591. function IsDebug: Boolean;
  592. begin
  593. {$IFDEF DEBUG}
  594. Result := True;
  595. {$ELSE}
  596. Result := False;
  597. {$ENDIF DEBUG}
  598. end;
  599. {$IFDEF MSWINDOWS}
  600. function IsService : Boolean;
  601. begin
  602. //only working with my Quick.AppService unit
  603. try
  604. Result := (IsConsole) and (not HasConsoleOutput);
  605. except
  606. Result := False;
  607. end;
  608. end;
  609. function SecondsIdle: DWord;
  610. var
  611. liInfo: TLastInputInfo;
  612. begin
  613. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  614. GetLastInputInfo(liInfo) ;
  615. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  616. end;
  617. procedure FreeUnusedMem;
  618. begin
  619. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  620. end;
  621. function SetScreenResolution(Width, Height: integer): Longint;
  622. var
  623. DeviceMode: TDeviceMode;
  624. begin
  625. with DeviceMode do
  626. begin
  627. dmSize := SizeOf(TDeviceMode);
  628. dmPelsWidth := Width;
  629. dmPelsHeight := Height;
  630. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  631. end;
  632. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  633. end;
  634. {$ENDIF MSWINDOWS}
  635. function LastDayCurrentMonth: TDateTime;
  636. begin
  637. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  638. end;
  639. {$IFDEF FPC}
  640. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  641. begin
  642. if aInclusive then
  643. Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
  644. else
  645. Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
  646. end;
  647. {$ENDIF}
  648. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  649. begin
  650. //Test: Result := MinutesBetween(cBefore,cNow) < 1;
  651. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
  652. end;
  653. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  654. var
  655. y, m, d : Word;
  656. begin
  657. DecodeDate(aDate,y,m,d);
  658. Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
  659. end;
  660. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  661. var
  662. h, m, s, ms : Word;
  663. begin
  664. DecodeTime(aDate,h,m,s,ms);
  665. Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
  666. end;
  667. function FillStr(const C : Char; const Count : Integer) : string;
  668. var
  669. i : Integer;
  670. begin
  671. Result := '';
  672. for i := 1 to Count do Result := Result + C;
  673. end;
  674. function StrInArray(const aValue : string; const aInArray : array of string; aCaseSensitive : Boolean = True) : Boolean;
  675. var
  676. s : string;
  677. begin
  678. for s in aInArray do
  679. begin
  680. if aCaseSensitive then
  681. begin
  682. if s = aValue then Exit(True);
  683. end
  684. else
  685. begin
  686. if CompareText(aValue,s) = 0 then Exit(True);
  687. end;
  688. end;
  689. Result := False;
  690. end;
  691. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  692. var
  693. i : Integer;
  694. begin
  695. for i in aInArray do
  696. begin
  697. if i = aValue then Exit(True);
  698. end;
  699. Result := False;
  700. end;
  701. function IsEmptyArray(aArray : TArray<string>) : Boolean;
  702. begin
  703. Result := Length(aArray) = 0;
  704. end;
  705. function IsEmptyArray(aArray : TArray<Integer>) : Boolean;
  706. begin
  707. Result := Length(aArray) = 0;
  708. end;
  709. function Zeroes(const Number, Len : Int64) : string;
  710. begin
  711. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  712. else Result := IntToStr(Number);
  713. end;
  714. function NumberToStr(const Number : Int64) : string;
  715. begin
  716. try
  717. Result := FormatFloat('0,',Number);
  718. except
  719. Result := '#Error';
  720. end;
  721. end;
  722. function Spaces(const Count : Integer) : string;
  723. begin
  724. Result := FillStr(' ',Count);
  725. end;
  726. function NowStr : string;
  727. begin
  728. Result := DateTimeToStr(Now());
  729. end;
  730. function NewGuidStr : string;
  731. {$IFNDEF DELPHIRX10_UP}
  732. var
  733. guid : TGUID;
  734. {$ENDIF}
  735. begin
  736. {$IFDEF DELPHIRX10_UP}
  737. Result := TGUID.NewGuid.ToString;
  738. {$ELSE}
  739. guid.NewGuid;
  740. Result := guid.ToString
  741. {$ENDIF}
  742. end;
  743. function IsLike(cText, Pattern: string) : Boolean;
  744. var
  745. i, n : Integer;
  746. match : Boolean;
  747. wildcard : Boolean;
  748. CurrentPattern : Char;
  749. begin
  750. Result := False;
  751. wildcard := False;
  752. cText := LowerCase(cText);
  753. Pattern := LowerCase(Pattern);
  754. match := False;
  755. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  756. if Pattern = '*' then
  757. begin
  758. Result := True;
  759. Exit;
  760. end;
  761. for i := 1 to cText.Length do
  762. begin
  763. CurrentPattern := Pattern[i];
  764. if CurrentPattern = '*' then wildcard := True;
  765. if wildcard then
  766. begin
  767. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  768. if (n > i) or (Pattern.Length = i) then
  769. begin
  770. Result := True;
  771. Exit;
  772. end;
  773. end
  774. else
  775. begin
  776. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  777. else match := False;
  778. end;
  779. end;
  780. Result := match;
  781. end;
  782. function Capitalize(s: string): string;
  783. begin
  784. Result := '';
  785. if s.Length = 0 then Exit;
  786. s := LowerCase(s,loUserLocale);
  787. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  788. end;
  789. function CapitalizeWords(s: string): string;
  790. var
  791. cword : string;
  792. begin
  793. Result := '';
  794. if s.Length = 0 then Exit;
  795. s := LowerCase(s,loUserLocale);
  796. for cword in s.Split([' ']) do
  797. begin
  798. if Result = '' then Result := Capitalize(cword)
  799. else Result := Result + ' ' + Capitalize(cword);
  800. end;
  801. end;
  802. function GetLoggedUserName : string;
  803. {$IFDEF MSWINDOWS}
  804. const
  805. cnMaxUserNameLen = 254;
  806. var
  807. sUserName : string;
  808. dwUserNameLen : DWord;
  809. begin
  810. dwUserNameLen := cnMaxUserNameLen-1;
  811. SetLength( sUserName, cnMaxUserNameLen );
  812. GetUserName(PChar( sUserName ),dwUserNameLen );
  813. SetLength( sUserName, dwUserNameLen );
  814. Result := sUserName;
  815. end;
  816. {$ELSE}
  817. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  818. begin
  819. Result := GetEnvironmentVariable('USERNAME');
  820. end;
  821. {$ELSE}
  822. var
  823. {$IFNDEF NEXTGEN}
  824. plogin : PAnsiChar;
  825. {$ELSE}
  826. plogin : MarshaledAString;
  827. {$ENDIF}
  828. begin
  829. {$IFDEF POSIX}
  830. try
  831. plogin := getlogin;
  832. Result := Copy(plogin,1,Length(Trim(plogin)));
  833. except
  834. Result := 'N/A';
  835. end;
  836. {$ELSE}
  837. Result := 'N/A';
  838. {$ENDIF}
  839. //raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
  840. end;
  841. {$ENDIF}
  842. {$ENDIF}
  843. {$IFDEF IOS}
  844. function GetDeviceModel : String;
  845. var
  846. size : size_t;
  847. buffer : array of Byte;
  848. begin
  849. sysctlbyname('hw.machine',nil,@size,nil,0);
  850. if size > 0 then
  851. begin
  852. SetLength(buffer, size);
  853. sysctlbyname('hw.machine',@buffer[0],@size,nil,0);
  854. Result := UTF8ToString(MarshaledAString(buffer));
  855. end
  856. else Result := EmptyStr;
  857. end;
  858. {$ENDIF}
  859. function GetComputerName : string;
  860. {$IFDEF MSWINDOWS}
  861. var
  862. dwLength: dword;
  863. begin
  864. dwLength := 253;
  865. SetLength(Result, dwLength+1);
  866. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  867. Result := pchar(result);
  868. end;
  869. {$ELSE}
  870. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  871. begin
  872. Result := GetEnvironmentVariable('COMPUTERNAME');
  873. end;
  874. {$ELSE} //Android gets model name
  875. {$IFDEF NEXTGEN}
  876. begin
  877. {$IFDEF ANDROID}
  878. Result := JStringToString(TJBuild.JavaClass.MODEL);
  879. {$ELSE} //IOS
  880. Result := GetDeviceModel;
  881. {$ENDIF}
  882. end;
  883. {$ELSE}
  884. {$IFDEF DELPHILINUX}
  885. var
  886. phost : PAnsiChar;
  887. begin
  888. try
  889. phost := AllocMem(256);
  890. try
  891. if gethostname(phost,_SC_HOST_NAME_MAX) = 0 then
  892. begin
  893. {$IFDEF DEBUG}
  894. Result := Copy(Trim(phost),1,Length(Trim(phost)));
  895. {$ELSE}
  896. Result := Copy(phost,1,Length(phost));
  897. {$ENDIF}
  898. end
  899. else Result := 'N/A.';
  900. finally
  901. FreeMem(phost);
  902. end;
  903. except
  904. Result := 'N/A';
  905. end;
  906. end;
  907. {$ELSE} //OSX
  908. begin
  909. Result := NSStrToStr(TNSHost.Wrap(TNSHost.OCClass.currentHost).localizedName);
  910. end;
  911. {$ENDIF}
  912. {$ENDIF}
  913. {$ENDIF}
  914. {$ENDIF}
  915. function ExtractDomainAndUser(const aUser : string; out oDomain, oUser : string) : Boolean;
  916. begin
  917. //check if domain specified into username
  918. if aUser.Contains('\') then
  919. begin
  920. oDomain := Copy(aUser,Low(aUser),Pos('\',aUser)-1);
  921. oUser := Copy(aUser,Pos('\',aUser)+1,aUser.Length);
  922. Exit(True);
  923. end
  924. else if aUser.Contains('@') then
  925. begin
  926. oDomain := Copy(aUser,Pos('@',aUser)+1,aUser.Length);
  927. oUser := Copy(aUser,Low(aUser),Pos('@',aUser)-1);
  928. Exit(True);
  929. end;
  930. oDomain := '';
  931. oUser := aUser;
  932. Result := False;
  933. end;
  934. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  935. begin
  936. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  937. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  938. end;
  939. function CombinePaths(const aFirstPath, aSecondPath: string; aDelim : Char): string;
  940. begin
  941. var path1 := NormalizePathDelim(aFirstPath,aDelim);
  942. var path2 := NormalizePathDelim(aSecondPath,aDelim);
  943. if path1.EndsWith(aDelim) then
  944. begin
  945. if path2.StartsWith(aDelim) then Result := path1 + path2.Substring(1)
  946. else Result := path1 + path2;
  947. end
  948. else
  949. begin
  950. if path2.StartsWith(aDelim) then Result := path1 + path2
  951. else result := path1 + aDelim + path2;
  952. end;
  953. end;
  954. function RemoveFirstPathSegment(const cdir : string) : string;
  955. var
  956. posi : Integer;
  957. delim : Char;
  958. dir : string;
  959. StartsWithDelim : Boolean;
  960. begin
  961. if cDir.Contains('\') then delim := '\'
  962. else if cDir.Contains('/') then delim := '/'
  963. else
  964. begin
  965. Exit('');
  966. end;
  967. dir := NormalizePathDelim(cDir,delim);
  968. if dir.StartsWith(delim) then
  969. begin
  970. dir := Copy(dir,2,dir.Length);
  971. StartsWithDelim := True;
  972. end
  973. else StartsWithDelim := False;
  974. if dir.CountChar(delim) = 0 then Exit('')
  975. else posi := Pos(delim,dir)+1;
  976. Result := Copy(dir,posi,dir.Length);
  977. if (not Result.IsEmpty) and (StartsWithDelim) then Result := delim + Result;
  978. end;
  979. function RemoveLastPathSegment(const cDir : string) : string;
  980. var
  981. posi : Integer;
  982. delim : Char;
  983. dir : string;
  984. EndsWithDelim : Boolean;
  985. begin
  986. if cDir.Contains('\') then delim := '\'
  987. else if cDir.Contains('/') then delim := '/'
  988. else
  989. begin
  990. Exit('');
  991. end;
  992. dir := NormalizePathDelim(cDir,delim);
  993. if dir.EndsWith(delim) then
  994. begin
  995. dir := Copy(dir,1,dir.Length-1);
  996. EndsWithDelim := True;
  997. end
  998. else EndsWithDelim := False;
  999. if dir.CountChar(delim) > 1 then posi := dir.LastDelimiter(delim)
  1000. else posi := Pos(delim,dir)-1;
  1001. if posi = dir.Length then posi := 0;
  1002. Result := Copy(dir,1,posi);
  1003. if (not Result.IsEmpty) and (EndsWithDelim) then Result := Result + delim;
  1004. end;
  1005. function GetPathDelimiter(const aPath : string) : string;
  1006. begin
  1007. if aPath.Contains('/') then Result := '/'
  1008. else if aPath.Contains('\') then Result := '\'
  1009. else Result := '';
  1010. end;
  1011. function GetFirstPathSegment(const aPath : string) : string;
  1012. var
  1013. delimiter : string;
  1014. spath : string;
  1015. begin
  1016. delimiter := GetPathDelimiter(aPath);
  1017. if delimiter.IsEmpty then Exit(aPath);
  1018. if aPath.StartsWith(delimiter) then spath := Copy(aPath,2,aPath.Length)
  1019. else spath := aPath;
  1020. if spath.Contains(delimiter) then Result := Copy(spath,0,spath.IndexOf(delimiter))
  1021. else Result := spath;
  1022. end;
  1023. function GetLastPathSegment(const aPath : string) : string;
  1024. var
  1025. delimiter : string;
  1026. spath : string;
  1027. begin
  1028. delimiter := GetPathDelimiter(aPath);
  1029. if delimiter.IsEmpty then Exit(aPath);
  1030. if aPath.EndsWith(delimiter) then spath := Copy(aPath,0,aPath.Length - 1)
  1031. else spath := aPath;
  1032. Result := spath.Substring(spath.LastDelimiter(delimiter)+1);
  1033. end;
  1034. function ParamFindSwitch(const Switch : string) : Boolean;
  1035. begin
  1036. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  1037. end;
  1038. {$IFDEF FPC}
  1039. function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
  1040. const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
  1041. type
  1042. TCompareProc = function(const S1, S2: string): Boolean;
  1043. var
  1044. Param: string;
  1045. I, ValueOfs,
  1046. SwitchLen, ParamLen: Integer;
  1047. SameSwitch: TCompareProc;
  1048. begin
  1049. Result := False;
  1050. Value := '';
  1051. if IgnoreCase then
  1052. SameSwitch := SameText else
  1053. SameSwitch := SameStr;
  1054. SwitchLen := Switch.Length;
  1055. for I := 1 to ParamCount do
  1056. begin
  1057. Param := ParamStr(I);
  1058. if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
  1059. begin
  1060. ParamLen := Param.Length;
  1061. // Look for an appended value if the param is longer than the switch
  1062. if (ParamLen > SwitchLen + 1) then
  1063. begin
  1064. // If not looking for appended value switches then this is not a matching switch
  1065. if not (clstValueAppended in SwitchTypes) then
  1066. Continue;
  1067. ValueOfs := SwitchLen + 1;
  1068. if Param.Chars[ValueOfs] = ':' then
  1069. Inc(ValueOfs);
  1070. Value := Param.SubString(ValueOfs, MaxInt);
  1071. end
  1072. // If the next param is not a switch, then treat it as the value
  1073. else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
  1074. not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
  1075. Value := ParamStr(I+1);
  1076. Result := True;
  1077. Break;
  1078. end;
  1079. end;
  1080. end;
  1081. {$ENDIF}
  1082. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  1083. begin
  1084. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  1085. end;
  1086. function GetAppName : string;
  1087. begin
  1088. Result := ExtractFilenameWithoutExt(ParamStr(0));
  1089. end;
  1090. function GetAppVersionStr: string;
  1091. {$IFDEF MSWINDOWS}
  1092. var
  1093. Rec: LongRec;
  1094. ver : Cardinal;
  1095. begin
  1096. ver := GetFileVersion(ParamStr(0));
  1097. if ver <> Cardinal(-1) then
  1098. begin
  1099. Rec := LongRec(ver);
  1100. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  1101. end
  1102. else Result := '';
  1103. end;
  1104. {$ELSE}
  1105. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  1106. var
  1107. version : TProgramVersion;
  1108. begin
  1109. if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
  1110. else Result := '';
  1111. end;
  1112. {$ELSE}
  1113. {$IFDEF NEXTGEN}
  1114. {$IFDEF ANDROID}
  1115. var
  1116. PkgInfo : JPackageInfo;
  1117. begin
  1118. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  1119. Result := IntToStr(PkgInfo.VersionCode);
  1120. end;
  1121. {$ELSE} //IOS
  1122. var
  1123. AppKey: Pointer;
  1124. AppBundle: NSBundle;
  1125. BuildStr : NSString;
  1126. begin
  1127. try
  1128. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1129. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1130. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1131. Result := UTF8ToString(BuildStr.UTF8String);
  1132. except
  1133. Result := '';
  1134. end;
  1135. end;
  1136. {$ENDIF}
  1137. {$ELSE} //OSX
  1138. {$IFDEF OSX}
  1139. var
  1140. AppKey: Pointer;
  1141. AppBundle: NSBundle;
  1142. BuildStr : NSString;
  1143. begin
  1144. try
  1145. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1146. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1147. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1148. Result := UTF8ToString(BuildStr.UTF8String);
  1149. except
  1150. Result := '';
  1151. end;
  1152. end;
  1153. {$ELSE}
  1154. begin
  1155. Result := '';
  1156. end;
  1157. {$ENDIF}
  1158. {$ENDIF}
  1159. {$ENDIF}
  1160. {$ENDIF}
  1161. function GetAppVersionFullStr: string;
  1162. {$IFDEF MSWINDOWS}
  1163. var
  1164. Exe: string;
  1165. Size, Handle: DWORD;
  1166. Buffer: TBytes;
  1167. FixedPtr: PVSFixedFileInfo;
  1168. begin
  1169. Result := '';
  1170. Exe := ParamStr(0);
  1171. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  1172. if Size = 0 then
  1173. begin
  1174. //RaiseLastOSError;
  1175. //no version info in file
  1176. Exit;
  1177. end;
  1178. SetLength(Buffer, Size);
  1179. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  1180. RaiseLastOSError;
  1181. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  1182. RaiseLastOSError;
  1183. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  1184. begin
  1185. Result := Format('%d.%d',
  1186. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1187. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  1188. end
  1189. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  1190. begin
  1191. Result := Format('%d.%d.%d',
  1192. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1193. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  1194. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  1195. end
  1196. else
  1197. begin
  1198. Result := Format('%d.%d.%d.%d',
  1199. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1200. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  1201. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  1202. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  1203. end;
  1204. end;
  1205. {$ELSE}
  1206. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  1207. var
  1208. version : TProgramVersion;
  1209. begin
  1210. if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
  1211. else Result := '';
  1212. end;
  1213. {$ELSE}
  1214. {$IFDEF NEXTGEN}
  1215. {$IFDEF ANDROID}
  1216. var
  1217. PkgInfo : JPackageInfo;
  1218. begin
  1219. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  1220. Result := JStringToString(PkgInfo.versionName);
  1221. end;
  1222. {$ELSE} //IOS
  1223. var
  1224. AppKey: Pointer;
  1225. AppBundle: NSBundle;
  1226. BuildStr : NSString;
  1227. begin
  1228. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1229. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1230. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1231. Result := UTF8ToString(BuildStr.UTF8String);
  1232. end;
  1233. {$ENDIF}
  1234. {$ELSE}
  1235. {$IFDEF OSX}
  1236. var
  1237. AppKey: Pointer;
  1238. AppBundle: NSBundle;
  1239. BuildStr : NSString;
  1240. begin
  1241. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1242. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1243. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1244. Result := UTF8ToString(BuildStr.UTF8String);
  1245. end;
  1246. {$ELSE}
  1247. begin
  1248. Result := '';
  1249. end;
  1250. {$ENDIF}
  1251. {$ENDIF}
  1252. {$ENDIF}
  1253. {$ENDIF}
  1254. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  1255. begin
  1256. {$IFDEF FPC}
  1257. Result := LocalTimeToUniversal(GMTTime);
  1258. {$ELSE}
  1259. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  1260. {$ENDIF}
  1261. end;
  1262. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  1263. begin
  1264. {$IFDEF FPC}
  1265. Result := UniversalTimeToLocal(Localtime);
  1266. {$ELSE}
  1267. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  1268. {$ENDIF}
  1269. end;
  1270. function DateTimeToGMT(aDate : TDateTime) : string;
  1271. var
  1272. FmtSettings : TFormatSettings;
  1273. begin
  1274. FmtSettings.DateSeparator := '-';
  1275. FmtSettings.TimeSeparator := ':';
  1276. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1277. Result := DateTimeToStr(aDate,FmtSettings).Trim;
  1278. end;
  1279. function GMTToDateTime(aDate : string) : TDateTime;
  1280. var
  1281. FmtSettings : TFormatSettings;
  1282. begin
  1283. FmtSettings.DateSeparator := '-';
  1284. FmtSettings.TimeSeparator := ':';
  1285. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1286. Result := StrToDateTime(aDate,FmtSettings);
  1287. end;
  1288. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  1289. {$IFNDEF DELPHIXE7_UP}
  1290. var
  1291. FmtSettings : TFormatSettings;
  1292. {$ENDIF}
  1293. begin
  1294. {$IFDEF DELPHIXE7_UP}
  1295. Result := DateToISO8601(aDateTime);
  1296. {$ELSE}
  1297. FmtSettings.DateSeparator := '-';
  1298. FmtSettings.TimeSeparator := ':';
  1299. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1300. Result := DateTimeToStr(aDateTime,FmtSettings).Trim;
  1301. {$ENDIF}
  1302. end;
  1303. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  1304. {$IFNDEF DELPHIXE7_UP}
  1305. var
  1306. FmtSettings : TFormatSettings;
  1307. {$ENDIF}
  1308. {$IFDEF FPC}
  1309. var
  1310. jdate : string;
  1311. {$ENDIF}
  1312. begin
  1313. {$IFDEF DELPHIXE7_UP}
  1314. Result := ISO8601ToDate(aJsonDate);
  1315. {$ELSE}
  1316. FmtSettings.DateSeparator := '-';
  1317. FmtSettings.TimeSeparator := ':';
  1318. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1319. {$IFDEF FPC}
  1320. jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
  1321. jdate := Copy(jdate,1,Pos('.',jdate)-1);
  1322. Result := StrToDateTime(jdate,FmtSettings);
  1323. {$ELSE}
  1324. Result := StrToDateTime(aJsonDate,FmtSettings);
  1325. {$ENDIF}
  1326. {$ENDIF}
  1327. end;
  1328. function CountDigits(anInt: Cardinal): Cardinal; inline;
  1329. var
  1330. cmp: Cardinal;
  1331. begin
  1332. cmp := 10;
  1333. Result := 1;
  1334. while (Result < 10) and (cmp <= anInt) do
  1335. begin
  1336. cmp := cmp*10;
  1337. Inc(Result);
  1338. end;
  1339. end;
  1340. function CountStr(const aFindStr, aSourceStr : string) : Integer;
  1341. var
  1342. i : Integer;
  1343. found : Integer;
  1344. findstr : string;
  1345. mainstr : string;
  1346. begin
  1347. findstr := aFindStr.ToLower;
  1348. mainstr := aSourceStr.ToLower;
  1349. Result := 0;
  1350. i := 0;
  1351. while i < mainstr.Length do
  1352. begin
  1353. found := Pos(findstr,mainstr,i);
  1354. if found > 0 then
  1355. begin
  1356. i := found;
  1357. Inc(Result);
  1358. end
  1359. else Break;
  1360. end;
  1361. end;
  1362. procedure SaveStreamToFile(aStream : TStream; const aFileName : string);
  1363. var
  1364. fs : TFileStream;
  1365. begin
  1366. fs := TFileStream.Create(aFileName,fmCreate);
  1367. try
  1368. aStream.Seek(0,soBeginning);
  1369. fs.CopyFrom(aStream,aStream.Size);
  1370. finally
  1371. fs.Free;
  1372. end;
  1373. end;
  1374. function StreamToString(aStream : TStream) : string;
  1375. var
  1376. ss : TStringStream;
  1377. begin
  1378. aStream.Position := 0;
  1379. if aStream = nil then Exit;
  1380. if aStream is TMemoryStream then
  1381. begin
  1382. SetString(Result, PChar(TMemoryStream(aStream).Memory), TMemoryStream(aStream).Size div SizeOf(Char));
  1383. end
  1384. else if aStream is TStringStream then
  1385. begin
  1386. Result := TStringStream(aStream).DataString;
  1387. end
  1388. else
  1389. begin
  1390. ss := TStringStream.Create;
  1391. try
  1392. aStream.Seek(0,soBeginning);
  1393. ss.CopyFrom(aStream,aStream.Size);
  1394. Result := ss.DataString;
  1395. finally
  1396. ss.Free;
  1397. end;
  1398. end;
  1399. end;
  1400. function StreamToString2(const aStream: TStream; const aEncoding: TEncoding): string;
  1401. var
  1402. sbytes: TBytes;
  1403. begin
  1404. aStream.Position := 0;
  1405. SetLength(sbytes, aStream.Size);
  1406. aStream.ReadBuffer(sbytes,aStream.Size);
  1407. Result := aEncoding.GetString(sbytes);
  1408. end;
  1409. procedure StringToStream(const aStr : string; aStream : TStream);
  1410. begin
  1411. aStream.Seek(0,soBeginning);
  1412. aStream.WriteBuffer(Pointer(aStr)^,aStr.Length * SizeOf(Char));
  1413. end;
  1414. procedure StringToStream2(const aStr : string; aStream : TStream);
  1415. var
  1416. stream : TStringStream;
  1417. begin
  1418. stream := TStringStream.Create(aStr,TEncoding.UTF8);
  1419. try
  1420. aStream.CopyFrom(stream,stream.Size);
  1421. finally
  1422. stream.Free;
  1423. end;
  1424. end;
  1425. function CommaText(aList : TStringList) : string;
  1426. var
  1427. value : string;
  1428. sb : TStringBuilder;
  1429. begin
  1430. if aList.Text = '' then Exit;
  1431. sb := TStringBuilder.Create;
  1432. try
  1433. for value in aList do
  1434. begin
  1435. sb.Append(value);
  1436. sb.Append(',');
  1437. end;
  1438. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1439. finally
  1440. sb.Free;
  1441. end;
  1442. end;
  1443. function CommaText(aArray : TArray<string>) : string;
  1444. var
  1445. value : string;
  1446. sb : TStringBuilder;
  1447. begin
  1448. if High(aArray) < 0 then Exit;
  1449. sb := TStringBuilder.Create;
  1450. try
  1451. for value in aArray do
  1452. begin
  1453. sb.Append(value);
  1454. sb.Append(',');
  1455. end;
  1456. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1457. finally
  1458. sb.Free;
  1459. end;
  1460. end;
  1461. function ArrayToString(aArray : TArray<string>) : string;
  1462. var
  1463. value : string;
  1464. sb : TStringBuilder;
  1465. begin
  1466. if High(aArray) < 0 then Exit;
  1467. sb := TStringBuilder.Create;
  1468. try
  1469. for value in aArray do
  1470. begin
  1471. sb.Append(value);
  1472. sb.Append(#10#13);
  1473. end;
  1474. finally
  1475. sb.Free;
  1476. end;
  1477. end;
  1478. function StringsToArray(aStrings : TStrings) : TArray<string>;
  1479. var
  1480. i : Integer;
  1481. begin
  1482. if aStrings.Count = 0 then Exit;
  1483. SetLength(Result,aStrings.Count);
  1484. for i := 0 to aStrings.Count - 1 do
  1485. begin
  1486. Result[i] := aStrings[i];
  1487. end;
  1488. end;
  1489. { TCounter }
  1490. procedure TCounter.Init(aMaxValue : Integer);
  1491. begin
  1492. fMaxValue := aMaxValue;
  1493. fCurrentValue := 0;
  1494. end;
  1495. function TCounter.Count : Integer;
  1496. begin
  1497. Result := fCurrentValue;
  1498. end;
  1499. function TCounter.CountIs(aValue : Integer) : Boolean;
  1500. begin
  1501. Result := fCurrentValue = aValue;
  1502. end;
  1503. function TCounter.Check : Boolean;
  1504. begin
  1505. if fCurrentValue = fMaxValue then
  1506. begin
  1507. Result := True;
  1508. Reset;
  1509. end
  1510. else
  1511. begin
  1512. Result := False;
  1513. Inc(fCurrentValue);
  1514. end;
  1515. end;
  1516. procedure TCounter.Reset;
  1517. begin
  1518. fCurrentValue := fMaxValue;
  1519. end;
  1520. { TimeCounter }
  1521. procedure TTimeCounter.Init(MillisecondsToReach : Integer);
  1522. begin
  1523. fDoneEvery := MillisecondsToReach;
  1524. end;
  1525. function TTimeCounter.Check : Boolean;
  1526. begin
  1527. if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
  1528. begin
  1529. fCurrentTime := Now();
  1530. Result := True;
  1531. end
  1532. else Result := False;
  1533. end;
  1534. procedure TTimeCounter.Reset;
  1535. begin
  1536. fCurrentTime := Now();
  1537. end;
  1538. { TArrayOfStringHelper}
  1539. {$IFNDEF FPC}
  1540. function TArrayOfStringHelper.Any : Boolean;
  1541. begin
  1542. Result := High(Self) >= 0;
  1543. end;
  1544. function TArrayOfStringHelper.Any(const aValue : string) : Boolean;
  1545. begin
  1546. Result := Exists(aValue);
  1547. end;
  1548. function TArrayOfStringHelper.Add(const aValue : string) : Integer;
  1549. begin
  1550. SetLength(Self,Length(Self)+1);
  1551. Self[High(Self)] := aValue;
  1552. Result := High(Self);
  1553. end;
  1554. function TArrayOfStringHelper.AddIfNotExists(const aValue : string; aCaseSense : Boolean = False) : Integer;
  1555. var
  1556. i : Integer;
  1557. begin
  1558. for i := Low(Self) to High(Self) do
  1559. begin
  1560. if aCaseSense then
  1561. begin
  1562. if Self[i] = aValue then Exit(i);
  1563. end
  1564. else
  1565. begin
  1566. if CompareText(Self[i],aValue) = 0 then Exit(i)
  1567. end;
  1568. end;
  1569. //if not exists add it
  1570. Result := Self.Add(aValue);
  1571. end;
  1572. function TArrayOfStringHelper.Remove(const aValue : string) : Boolean;
  1573. var
  1574. i : Integer;
  1575. begin
  1576. for i := Low(Self) to High(Self) do
  1577. begin
  1578. if CompareText(Self[i],aValue) = 0 then
  1579. begin
  1580. {$IFDEF DELPHIXE7_UP}
  1581. System.Delete(Self,i,1);
  1582. {$ELSE}
  1583. TArrayUtil<string>.Delete(Self,i);
  1584. {$ENDIF}
  1585. Exit(True);
  1586. end;
  1587. end;
  1588. Result := False;
  1589. end;
  1590. function TArrayOfStringHelper.Exists(const aValue : string) : Boolean;
  1591. var
  1592. value : string;
  1593. begin
  1594. Result := False;
  1595. for value in Self do
  1596. begin
  1597. if CompareText(value,aValue) = 0 then Exit(True)
  1598. end;
  1599. end;
  1600. function TArrayOfStringHelper.Count : Integer;
  1601. begin
  1602. Result := High(Self) + 1;
  1603. end;
  1604. {$ENDIF}
  1605. { TPairItem }
  1606. constructor TPairItem.Create(const aName, aValue: string);
  1607. begin
  1608. Name := aName;
  1609. Value := aValue;
  1610. end;
  1611. { TPairList }
  1612. function TPairList.GetEnumerator : TPairEnumerator;
  1613. begin
  1614. Result := TPairEnumerator.Create(fItems);
  1615. end;
  1616. function TPairList.Add(aPair: TPairItem): Integer;
  1617. begin
  1618. SetLength(fItems,Length(fItems)+1);
  1619. fItems[High(fItems)] := aPair;
  1620. Result := High(fItems);
  1621. end;
  1622. function TPairList.Add(const aName, aValue: string): Integer;
  1623. begin
  1624. SetLength(fItems,Length(fItems)+1);
  1625. fItems[High(fItems)].Name := aName;
  1626. fItems[High(fItems)].Value := aValue;
  1627. Result := High(fItems);
  1628. end;
  1629. procedure TPairList.AddOrUpdate(const aName, aValue: string);
  1630. var
  1631. i : Integer;
  1632. begin
  1633. for i := Low(fItems) to High(fItems) do
  1634. begin
  1635. if CompareText(fItems[i].Name,aName) = 0 then
  1636. begin
  1637. fItems[i].Value := aValue;
  1638. Exit;
  1639. end;
  1640. end;
  1641. //if not exists add it
  1642. Self.Add(aName,aValue);
  1643. end;
  1644. function TPairList.Count: Integer;
  1645. begin
  1646. Result := High(fItems) + 1;
  1647. end;
  1648. function TPairList.Exists(const aName: string): Boolean;
  1649. var
  1650. i : Integer;
  1651. begin
  1652. Result := False;
  1653. for i := Low(fItems) to High(fItems) do
  1654. begin
  1655. if CompareText(fItems[i].Name,aName) = 0 then Exit(True)
  1656. end;
  1657. end;
  1658. function TPairList.GetPair(const aName: string): TPairItem;
  1659. var
  1660. i : Integer;
  1661. begin
  1662. for i := Low(fItems) to High(fItems) do
  1663. begin
  1664. if CompareText(fItems[i].Name,aName) = 0 then Exit(fItems[i]);
  1665. end;
  1666. end;
  1667. function TPairList.GetValue(const aName: string): string;
  1668. var
  1669. i : Integer;
  1670. begin
  1671. Result := '';
  1672. for i := Low(fItems) to High(fItems) do
  1673. begin
  1674. if CompareText(fItems[i].Name,aName) = 0 then Exit(fItems[i].Value);
  1675. end;
  1676. end;
  1677. function TPairList.Remove(const aName: string): Boolean;
  1678. var
  1679. i : Integer;
  1680. begin
  1681. for i := Low(fItems) to High(fItems) do
  1682. begin
  1683. if CompareText(fItems[i].Name,aName) = 0 then
  1684. begin
  1685. {$IF Defined(DELPHIXE7_UP) OR Defined(FPC)}
  1686. System.Delete(fItems,i,1);
  1687. {$ELSE}
  1688. TArrayUtil<TPairItem>.Delete(fItems,i);
  1689. {$ENDIF}
  1690. Exit(True);
  1691. end;
  1692. end;
  1693. Result := False;
  1694. end;
  1695. function TPairList.ToArray : TArray<TPairItem>;
  1696. begin
  1697. Result := fItems;
  1698. end;
  1699. procedure TPairList.FromArray(aValue : TArray<TPairItem>);
  1700. begin
  1701. fItems := aValue;
  1702. end;
  1703. procedure TPairList.Clear;
  1704. begin
  1705. SetLength(fItems,0);
  1706. end;
  1707. { TPairList.TPairEnumerator}
  1708. constructor TPairList.TPairEnumerator.Create(var aArray: TArray<TPairItem>);
  1709. begin
  1710. fIndex := -1;
  1711. fArray := @aArray;
  1712. end;
  1713. function TPairList.TPairEnumerator.GetCurrent : TPairItem;
  1714. begin
  1715. Result := TArray<TPairItem>(fArray^)[fIndex];
  1716. end;
  1717. function TPairList.TPairEnumerator.MoveNext: Boolean;
  1718. begin
  1719. Inc(fIndex);
  1720. Result := fIndex < High(TArray<TPairItem>(fArray^))+1;
  1721. end;
  1722. {$IFDEF MSWINDOWS}
  1723. procedure ProcessMessages;
  1724. var
  1725. Msg: TMsg;
  1726. begin
  1727. while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
  1728. begin
  1729. TranslateMessage(Msg);
  1730. DispatchMessage(Msg);
  1731. end;
  1732. end;
  1733. function GetLastOSError: String;
  1734. begin
  1735. Result := SysErrorMessage(Windows.GetLastError);
  1736. end;
  1737. {$ENDIF}
  1738. function RemoveLastChar(const aText : string) : string;
  1739. begin
  1740. Result := aText.Remove(aText.Length - 1);
  1741. end;
  1742. function DateTimeToSQL(aDateTime : TDateTime) : string;
  1743. begin
  1744. Result := FormatDateTime('YYYYMMDD hh:mm:ss',aDateTime);
  1745. end;
  1746. function IsInteger(const aValue : string) : Boolean;
  1747. var
  1748. i : Integer;
  1749. begin
  1750. Result := TryStrToInt(aValue,i);
  1751. end;
  1752. function IsFloat(const aValue : string) : Boolean;
  1753. var
  1754. e : Extended;
  1755. begin
  1756. Result := TryStrToFloat(aValue,e);
  1757. end;
  1758. function IsBoolean(const aValue : string) : Boolean;
  1759. var
  1760. b : Boolean;
  1761. begin
  1762. Result := TryStrToBool(aValue,b);
  1763. end;
  1764. function ExtractStr(var vSource : string; aIndex : Integer; aCount : Integer) : string;
  1765. begin
  1766. if aIndex > vSource.Length then Exit('');
  1767. Result := Copy(vSource,aIndex,aCount);
  1768. Delete(vSource,aIndex,aCount);
  1769. end;
  1770. function GetSubString(const aSource, aFirstDelimiter, aLastDelimiter : string) : string;
  1771. var
  1772. i : Integer;
  1773. begin
  1774. i := Pos(aFirstDelimiter,aSource);
  1775. if i > -1 then Result := Copy(aSource, i + aFirstDelimiter.Length, Pos(aLastDelimiter, aSource, i + aFirstDelimiter.Length) - i - aFirstDelimiter.Length)
  1776. else Result := '';
  1777. end;
  1778. function DbQuotedStr(const str : string): string;
  1779. var
  1780. i : Integer;
  1781. begin
  1782. Result := str;
  1783. for i := Result.Length - 1 downto 0 do
  1784. begin
  1785. if Result.Chars[i] = '"' then Result := Result.Insert(i, '"');
  1786. end;
  1787. Result := '"' + Result + '"';
  1788. end;
  1789. function UnDbQuotedStr(const str: string) : string;
  1790. begin
  1791. Result := Trim(str);
  1792. if not Result.IsEmpty then
  1793. begin
  1794. if Result.StartsWith('"') then Result := Copy(Result, 2, Result.Length - 2);
  1795. end;
  1796. end;
  1797. function SpQuotedStr(const str : string): string;
  1798. begin
  1799. Result := '''' + str + '''';
  1800. end;
  1801. function UnSpQuotedStr(const str: string) : string;
  1802. begin
  1803. Result := Trim(str);
  1804. if not Result.IsEmpty then
  1805. begin
  1806. if Result.StartsWith('''') then Result := Copy(Result, 2, Result.Length - 2);
  1807. end;
  1808. end;
  1809. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : string) : string;
  1810. begin
  1811. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1812. end;
  1813. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Integer) : Integer;
  1814. begin
  1815. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1816. end;
  1817. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Extended) : Extended;
  1818. begin
  1819. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1820. end;
  1821. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : TObject) : TObject;
  1822. begin
  1823. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1824. end;
  1825. {$IFNDEF FPC}
  1826. {$IFNDEF DELPHIXE7_UP}
  1827. class procedure TArrayUtil<T>.Delete(var aArray : TArray<T>; aIndex : Integer);
  1828. var
  1829. n : Integer;
  1830. len : Integer;
  1831. begin
  1832. len := Length(aArray);
  1833. if (len > 0) and (aIndex < len) then
  1834. begin
  1835. for n := aIndex + 1 to len - 1 do aArray[n - 1] := aArray[n];
  1836. SetLength(aArray, len - 1);
  1837. end;
  1838. end;
  1839. {$ENDIF}
  1840. {$ENDIF}
  1841. {$IFNDEF NEXTGEN}
  1842. initialization
  1843. try
  1844. GetEnvironmentPaths;
  1845. except
  1846. {$IFDEF SHOW_ENVIRONMENTPATH_ERRORS}
  1847. on E : Exception do
  1848. begin
  1849. if not IsService then
  1850. begin
  1851. if HasConsoleOutput then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
  1852. else MessageBox(0,PWideChar(Format('Get environment path error: %s',[E.Message])),'GetEnvironmentPaths',MB_ICONEXCLAMATION);
  1853. end;
  1854. end;
  1855. {$ENDIF}
  1856. end;
  1857. {$ENDIF}
  1858. end.