Quick.Commons.pas 60 KB

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