Quick.Commons.pas 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331
  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 : 29/08/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. //ternary operator
  406. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : string) : string; overload;
  407. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Integer) : Integer; overload;
  408. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Extended) : Extended; overload;
  409. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : TObject) : TObject; overload;
  410. var
  411. path : TEnvironmentPath;
  412. //Enabled if QuickService is defined
  413. IsQuickServiceApp : Boolean;
  414. implementation
  415. {TFileHelper}
  416. {$IFNDEF FPC}
  417. {$IFDEF MSWINDOWS}
  418. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  419. var
  420. HFileRes: HFILE;
  421. begin
  422. Result := False;
  423. if not FileExists(FileName) then Exit;
  424. try
  425. HFileRes := CreateFile(PChar(FileName)
  426. ,GENERIC_READ or GENERIC_WRITE
  427. ,0
  428. ,nil
  429. ,OPEN_EXISTING
  430. ,FILE_ATTRIBUTE_NORMAL
  431. ,0);
  432. Result := (HFileRes = INVALID_HANDLE_VALUE);
  433. if not(Result) then begin
  434. CloseHandle(HFileRes);
  435. end;
  436. except
  437. Result := True;
  438. end;
  439. end;
  440. {$ENDIF}
  441. {$IFDEF DELPHILINUX}
  442. class function TFileHelper.IsInUse(const FileName : string) : Boolean;
  443. var
  444. fs : TFileStream;
  445. begin
  446. try
  447. fs := TFileStream.Create(FileName, fmOpenReadWrite, fmShareExclusive);
  448. Result := True;
  449. fs.Free;
  450. except
  451. Result := False;
  452. end;
  453. end;
  454. {$ENDIF}
  455. {$IFDEF MSWINDOWS}
  456. class function TFileHelper.GetSize(const FileName: String): Int64;
  457. var
  458. info: TWin32FileAttributeData;
  459. begin
  460. Result := -1;
  461. if not GetFileAttributesEx(PWideChar(FileName), GetFileExInfoStandard, @info) then Exit;
  462. Result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
  463. end;
  464. {$ELSE}
  465. class function TFileHelper.GetSize(const FileName: String): Int64;
  466. var
  467. sr : TSearchRec;
  468. begin
  469. if FindFirst(fileName, faAnyFile, sr ) = 0 then Result := sr.Size
  470. else Result := -1;
  471. end;
  472. {$ENDIF}
  473. {TDirectoryHelper}
  474. class function TDirectoryHelper.GetSize(const Path: String): Int64;
  475. var
  476. filename : string;
  477. begin
  478. Result := -1;
  479. for filename in TDirectory.GetFiles(Path) do
  480. begin
  481. Result := Result + TFile.GetSize(filename);
  482. end;
  483. end;
  484. {$ENDIF}
  485. {other functions}
  486. function RandomPassword(const PasswordLength : Integer; Complexity : TPasswordComplexity = [pfIncludeNumbers,pfIncludeSigns]) : string;
  487. const
  488. PassAlpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  489. PassSigns = '@!&$';
  490. PassNumbers = '1234567890';
  491. var
  492. MinNumbers,
  493. MinSigns : Integer;
  494. NumNumbers,
  495. NumSigns : Integer;
  496. begin
  497. Result := '';
  498. Randomize;
  499. //fill all alfa
  500. repeat
  501. Result := Result + PassAlpha[Random(Length(PassAlpha))+1];
  502. until (Length(Result) = PasswordLength);
  503. //checks if need include numbers
  504. if pfIncludeNumbers in Complexity then
  505. begin
  506. MinNumbers := Round(PasswordLength / 10 * 2);
  507. NumNumbers := 0;
  508. if MinNumbers = 0 then MinNumbers := 1;
  509. repeat
  510. Result[Random(PasswordLength)+1] := PassNumbers[Random(Length(PassNumbers))+1];
  511. Inc(NumNumbers);
  512. until NumNumbers = MinNumbers;
  513. end;
  514. //checks if need include signs
  515. if pfIncludeSigns in Complexity then
  516. begin
  517. MinSigns := Round(PasswordLength / 10 * 1);
  518. NumSigns := 0;
  519. if MinSigns = 0 then MinSigns := 1;
  520. repeat
  521. Result[Random(PasswordLength)+1] := PassSigns[Random(Length(PassSigns))+1];
  522. Inc(NumSigns);
  523. until NumSigns = MinSigns;
  524. end;
  525. end;
  526. function RandomString(const aLength: Integer) : string;
  527. const
  528. chars : string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
  529. var
  530. i : Integer;
  531. clong : Integer;
  532. begin
  533. clong := High(chars);
  534. SetLength(Result, aLength);
  535. for i := 1 to aLength do
  536. begin
  537. Result[i] := chars[Random(clong) + 1];
  538. end;
  539. end;
  540. function ExtractFileNameWithoutExt(const FileName: string): string;
  541. begin
  542. Result := TPath.GetFileNameWithoutExtension(FileName);
  543. end;
  544. function UnixToWindowsPath(const UnixPath: string): string;
  545. begin
  546. Result := StringReplace(UnixPath, '/', '\',[rfReplaceAll, rfIgnoreCase]);
  547. end;
  548. function WindowsToUnixPath(const WindowsPath: string): string;
  549. begin
  550. Result := StringReplace(WindowsPath, '\', '/',[rfReplaceAll, rfIgnoreCase]);
  551. end;
  552. function CorrectURLPath(const cUrl : string) : string;
  553. var
  554. nurl : string;
  555. begin
  556. nurl := WindowsToUnixPath(cUrl);
  557. nurl := StringReplace(nurl,'//','/',[rfReplaceAll]);
  558. Result := StringReplace(nurl,' ','%20',[rfReplaceAll]);
  559. //TNetEncoding.Url.Encode()
  560. end;
  561. function UrlGetProtocol(const aUrl : string) : string;
  562. begin
  563. Result := aUrl.SubString(0,aUrl.IndexOf('://'));
  564. end;
  565. function UrlGetHost(const aUrl : string) : string;
  566. var
  567. url : string;
  568. len : Integer;
  569. begin
  570. url := UrlRemoveProtocol(aUrl);
  571. if url.Contains('/') then len := url.IndexOf('/')
  572. else len := url.Length;
  573. Result := url.SubString(0,len);
  574. end;
  575. function UrlGetPath(const aUrl : string) : string;
  576. var
  577. url : string;
  578. len : Integer;
  579. query : 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. Win32Check(stout <> Invalid_Handle_Value);
  688. Result := stout <> 0;
  689. except
  690. Result := False;
  691. end;
  692. end;
  693. {$ELSE}
  694. begin
  695. Result := IsConsole;
  696. end;
  697. {$ENDIF}
  698. function IsDebug: Boolean;
  699. begin
  700. {$IFDEF DEBUG}
  701. Result := True;
  702. {$ELSE}
  703. Result := False;
  704. {$ENDIF DEBUG}
  705. end;
  706. {$IFDEF MSWINDOWS}
  707. function IsService : Boolean;
  708. begin
  709. //only working with my Quick.AppService unit
  710. try
  711. Result := (IsConsole) and (not HasConsoleOutput);
  712. except
  713. Result := False;
  714. end;
  715. end;
  716. function SecondsIdle: DWord;
  717. var
  718. liInfo: TLastInputInfo;
  719. begin
  720. liInfo.cbSize := SizeOf(TLastInputInfo) ;
  721. GetLastInputInfo(liInfo) ;
  722. Result := (GetTickCount - liInfo.dwTime) DIV 1000;
  723. end;
  724. procedure FreeUnusedMem;
  725. begin
  726. if Win32Platform = VER_PLATFORM_WIN32_NT then SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
  727. end;
  728. function SetScreenResolution(Width, Height: integer): Longint;
  729. var
  730. DeviceMode: TDeviceMode;
  731. begin
  732. with DeviceMode do
  733. begin
  734. dmSize := SizeOf(TDeviceMode);
  735. dmPelsWidth := Width;
  736. dmPelsHeight := Height;
  737. dmFields := DM_PELSWIDTH or DM_PELSHEIGHT;
  738. end;
  739. Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);
  740. end;
  741. {$ENDIF MSWINDOWS}
  742. function LastDayCurrentMonth: TDateTime;
  743. begin
  744. Result := EncodeDate(YearOf(Now),MonthOf(Now), DaysInMonth(Now));
  745. end;
  746. {$IFDEF FPC}
  747. function DateTimeInRange(ADateTime: TDateTime; AStartDateTime, AEndDateTime: TDateTime; aInclusive: Boolean = True): Boolean;
  748. begin
  749. if aInclusive then
  750. Result := (AStartDateTime <= ADateTime) and (ADateTime <= AEndDateTime)
  751. else
  752. Result := (AStartDateTime < ADateTime) and (ADateTime < AEndDateTime);
  753. end;
  754. {$ENDIF}
  755. function IsSameDay(cBefore, cNow : TDateTime) : Boolean;
  756. begin
  757. //Test: Result := MinutesBetween(cBefore,cNow) < 1;
  758. Result := DateTimeInRange(cNow,StartOfTheDay(cBefore),EndOfTheDay(cBefore),True);
  759. end;
  760. function ChangeTimeOfADay(aDate : TDateTime; aHour, aMinute, aSecond : Word; aMilliSecond : Word = 0) : TDateTime;
  761. var
  762. y, m, d : Word;
  763. begin
  764. DecodeDate(aDate,y,m,d);
  765. Result := EncodeDateTime(y,m,d,aHour,aMinute,aSecond,aMilliSecond);
  766. end;
  767. function ChangeDateOfADay(aDate : TDateTime; aYear, aMonth, aDay : Word) : TDateTime;
  768. var
  769. h, m, s, ms : Word;
  770. begin
  771. DecodeTime(aDate,h,m,s,ms);
  772. Result := EncodeDateTime(aYear,aMonth,aDay,h,m,s,0);
  773. end;
  774. function FillStr(const C : Char; const Count : Integer) : string;
  775. var
  776. i : Integer;
  777. begin
  778. Result := '';
  779. for i := 1 to Count do Result := Result + C;
  780. end;
  781. function StrInArray(const aValue : string; const aInArray : array of string; aCaseSensitive : Boolean = True) : Boolean;
  782. var
  783. s : string;
  784. begin
  785. for s in aInArray do
  786. begin
  787. if aCaseSensitive then
  788. begin
  789. if s = aValue then Exit(True);
  790. end
  791. else
  792. begin
  793. if CompareText(aValue,s) = 0 then Exit(True);
  794. end;
  795. end;
  796. Result := False;
  797. end;
  798. function IntInArray(const aValue : Integer; const aInArray : array of Integer) : Boolean;
  799. var
  800. i : Integer;
  801. begin
  802. for i in aInArray do
  803. begin
  804. if i = aValue then Exit(True);
  805. end;
  806. Result := False;
  807. end;
  808. function IsEmptyArray(aArray : TArray<string>) : Boolean;
  809. begin
  810. Result := Length(aArray) = 0;
  811. end;
  812. function IsEmptyArray(aArray : TArray<Integer>) : Boolean;
  813. begin
  814. Result := Length(aArray) = 0;
  815. end;
  816. function Zeroes(const Number, Len : Int64) : string;
  817. begin
  818. if Len > Length(IntToStr(Number)) then Result := FillStr('0',Len - Length(IntToStr(Number))) + IntToStr(Number)
  819. else Result := IntToStr(Number);
  820. end;
  821. function NumberToStr(const Number : Int64) : string;
  822. begin
  823. try
  824. Result := FormatFloat('0,',Number);
  825. except
  826. Result := '#Error';
  827. end;
  828. end;
  829. function Spaces(const Count : Integer) : string;
  830. begin
  831. Result := FillStr(' ',Count);
  832. end;
  833. function NowStr : string;
  834. begin
  835. Result := DateTimeToStr(Now());
  836. end;
  837. function NewGuidStr : string;
  838. {$IFNDEF DELPHIRX10_UP}
  839. var
  840. guid : TGUID;
  841. {$ENDIF}
  842. begin
  843. {$IFDEF DELPHIRX10_UP}
  844. Result := TGUID.NewGuid.ToString;
  845. {$ELSE}
  846. guid.NewGuid;
  847. Result := guid.ToString
  848. {$ENDIF}
  849. end;
  850. function IsLike(cText, Pattern: string) : Boolean;
  851. var
  852. i, n : Integer;
  853. match : Boolean;
  854. wildcard : Boolean;
  855. CurrentPattern : Char;
  856. begin
  857. Result := False;
  858. wildcard := False;
  859. cText := LowerCase(cText);
  860. Pattern := LowerCase(Pattern);
  861. match := False;
  862. if (Pattern.Length > cText.Length) or (Pattern = '') then Exit;
  863. if Pattern = '*' then
  864. begin
  865. Result := True;
  866. Exit;
  867. end;
  868. for i := 1 to cText.Length do
  869. begin
  870. CurrentPattern := Pattern[i];
  871. if CurrentPattern = '*' then wildcard := True;
  872. if wildcard then
  873. begin
  874. n := Pos(Copy(Pattern,i+1,Pattern.Length),cText);
  875. if (n > i) or (Pattern.Length = i) then
  876. begin
  877. Result := True;
  878. Exit;
  879. end;
  880. end
  881. else
  882. begin
  883. if (cText[i] = CurrentPattern) or (CurrentPattern = '?') then match := True
  884. else match := False;
  885. end;
  886. end;
  887. Result := match;
  888. end;
  889. function Capitalize(s: string): string;
  890. begin
  891. Result := '';
  892. if s.Length = 0 then Exit;
  893. s := LowerCase(s,loUserLocale);
  894. Result := UpperCase(s[1],loUserLocale) + Trim(Copy(s, 2, s.Length));
  895. end;
  896. function CapitalizeWords(s: string): string;
  897. var
  898. cword : string;
  899. begin
  900. Result := '';
  901. if s.Length = 0 then Exit;
  902. s := LowerCase(s,loUserLocale);
  903. for cword in s.Split([' ']) do
  904. begin
  905. if Result = '' then Result := Capitalize(cword)
  906. else Result := Result + ' ' + Capitalize(cword);
  907. end;
  908. end;
  909. function GetLoggedUserName : string;
  910. {$IFDEF MSWINDOWS}
  911. const
  912. cnMaxUserNameLen = 254;
  913. var
  914. sUserName : string;
  915. dwUserNameLen : DWord;
  916. begin
  917. dwUserNameLen := cnMaxUserNameLen-1;
  918. SetLength( sUserName, cnMaxUserNameLen );
  919. GetUserName(PChar( sUserName ),dwUserNameLen );
  920. SetLength( sUserName, dwUserNameLen );
  921. Result := sUserName;
  922. end;
  923. {$ELSE}
  924. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  925. begin
  926. Result := GetEnvironmentVariable('USERNAME');
  927. end;
  928. {$ELSE}
  929. var
  930. {$IFNDEF NEXTGEN}
  931. plogin : PAnsiChar;
  932. {$ELSE}
  933. plogin : MarshaledAString;
  934. {$ENDIF}
  935. begin
  936. {$IFDEF POSIX}
  937. try
  938. plogin := getlogin;
  939. Result := Copy(plogin,1,Length(Trim(plogin)));
  940. except
  941. Result := 'N/A';
  942. end;
  943. {$ELSE}
  944. Result := 'N/A';
  945. {$ENDIF}
  946. //raise ENotImplemented.Create('Not Android GetLoggedUserName implemented!');
  947. end;
  948. {$ENDIF}
  949. {$ENDIF}
  950. {$IFDEF IOS}
  951. function GetDeviceModel : String;
  952. var
  953. size : size_t;
  954. buffer : array of Byte;
  955. begin
  956. sysctlbyname('hw.machine',nil,@size,nil,0);
  957. if size > 0 then
  958. begin
  959. SetLength(buffer, size);
  960. sysctlbyname('hw.machine',@buffer[0],@size,nil,0);
  961. Result := UTF8ToString(MarshaledAString(buffer));
  962. end
  963. else Result := EmptyStr;
  964. end;
  965. {$ENDIF}
  966. function GetComputerName : string;
  967. {$IFDEF MSWINDOWS}
  968. var
  969. dwLength: dword;
  970. begin
  971. dwLength := 253;
  972. SetLength(Result, dwLength+1);
  973. if not Windows.GetComputerName(pchar(result), dwLength) then Result := 'Not detected!';
  974. Result := pchar(result);
  975. end;
  976. {$ELSE}
  977. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  978. begin
  979. Result := GetEnvironmentVariable('COMPUTERNAME');
  980. end;
  981. {$ELSE} //Android gets model name
  982. {$IFDEF NEXTGEN}
  983. begin
  984. {$IFDEF ANDROID}
  985. Result := JStringToString(TJBuild.JavaClass.MODEL);
  986. {$ELSE} //IOS
  987. Result := GetDeviceModel;
  988. {$ENDIF}
  989. end;
  990. {$ELSE}
  991. {$IFDEF DELPHILINUX}
  992. var
  993. phost : PAnsiChar;
  994. begin
  995. try
  996. phost := AllocMem(256);
  997. try
  998. if gethostname(phost,_SC_HOST_NAME_MAX) = 0 then
  999. begin
  1000. {$IFDEF DEBUG}
  1001. Result := Copy(Trim(phost),1,Length(Trim(phost)));
  1002. {$ELSE}
  1003. Result := Copy(phost,1,Length(phost));
  1004. {$ENDIF}
  1005. end
  1006. else Result := 'N/A.';
  1007. finally
  1008. FreeMem(phost);
  1009. end;
  1010. except
  1011. Result := 'N/A';
  1012. end;
  1013. end;
  1014. {$ELSE} //OSX
  1015. begin
  1016. Result := NSStrToStr(TNSHost.Wrap(TNSHost.OCClass.currentHost).localizedName);
  1017. end;
  1018. {$ENDIF}
  1019. {$ENDIF}
  1020. {$ENDIF}
  1021. {$ENDIF}
  1022. {$IFDEF MSWINDOWS}
  1023. function IsRemoteSession : Boolean;
  1024. const
  1025. SM_REMOTECONTROL = $2001;
  1026. SM_REMOTESESSION = $1000;
  1027. begin
  1028. Result := (GetSystemMetrics(SM_REMOTESESSION) <> 0) or (GetSystemMetrics(SM_REMOTECONTROL) <> 0);
  1029. end;
  1030. {$ENDIF}
  1031. function ExtractDomainAndUser(const aUser : string; out oDomain, oUser : string) : Boolean;
  1032. begin
  1033. //check if domain specified into username
  1034. if aUser.Contains('\') then
  1035. begin
  1036. oDomain := Copy(aUser,Low(aUser),Pos('\',aUser)-1);
  1037. oUser := Copy(aUser,Pos('\',aUser)+1,aUser.Length);
  1038. Exit(True);
  1039. end
  1040. else if aUser.Contains('@') then
  1041. begin
  1042. oDomain := Copy(aUser,Pos('@',aUser)+1,aUser.Length);
  1043. oUser := Copy(aUser,Low(aUser),Pos('@',aUser)-1);
  1044. Exit(True);
  1045. end;
  1046. oDomain := '';
  1047. oUser := aUser;
  1048. Result := False;
  1049. end;
  1050. function NormalizePathDelim(const cPath : string; const Delim : Char) : string;
  1051. begin
  1052. if Delim = '\' then Result := StringReplace(cPath,'/',Delim,[rfReplaceAll])
  1053. else Result := StringReplace(cPath,'\',Delim,[rfReplaceAll]);
  1054. end;
  1055. function CombinePaths(const aFirstPath, aSecondPath: string; aDelim : Char): string;
  1056. var
  1057. path1 : string;
  1058. path2 : string;
  1059. begin
  1060. path1 := NormalizePathDelim(aFirstPath,aDelim);
  1061. path2 := NormalizePathDelim(aSecondPath,aDelim);
  1062. if path1.EndsWith(aDelim) then
  1063. begin
  1064. if path2.StartsWith(aDelim) then Result := path1 + path2.Substring(1)
  1065. else Result := path1 + path2;
  1066. end
  1067. else
  1068. begin
  1069. if path2.StartsWith(aDelim) then Result := path1 + path2
  1070. else result := path1 + aDelim + path2;
  1071. end;
  1072. end;
  1073. function RemoveFirstPathSegment(const cdir : string) : string;
  1074. var
  1075. posi : Integer;
  1076. delim : Char;
  1077. dir : string;
  1078. StartsWithDelim : Boolean;
  1079. begin
  1080. if cDir.Contains('\') then delim := '\'
  1081. else if cDir.Contains('/') then delim := '/'
  1082. else
  1083. begin
  1084. Exit('');
  1085. end;
  1086. dir := NormalizePathDelim(cDir,delim);
  1087. if dir.StartsWith(delim) then
  1088. begin
  1089. dir := Copy(dir,2,dir.Length);
  1090. StartsWithDelim := True;
  1091. end
  1092. else StartsWithDelim := False;
  1093. if dir.CountChar(delim) = 0 then Exit('')
  1094. else posi := Pos(delim,dir)+1;
  1095. Result := Copy(dir,posi,dir.Length);
  1096. if (not Result.IsEmpty) and (StartsWithDelim) then Result := delim + Result;
  1097. end;
  1098. function RemoveLastPathSegment(const cDir : string) : string;
  1099. var
  1100. posi : Integer;
  1101. delim : Char;
  1102. dir : string;
  1103. EndsWithDelim : Boolean;
  1104. begin
  1105. if cDir.Contains('\') then delim := '\'
  1106. else if cDir.Contains('/') then delim := '/'
  1107. else
  1108. begin
  1109. Exit('');
  1110. end;
  1111. dir := NormalizePathDelim(cDir,delim);
  1112. if dir.EndsWith(delim) then
  1113. begin
  1114. dir := Copy(dir,1,dir.Length-1);
  1115. EndsWithDelim := True;
  1116. end
  1117. else EndsWithDelim := False;
  1118. if dir.CountChar(delim) > 1 then posi := dir.LastDelimiter(delim)
  1119. else posi := Pos(delim,dir)-1;
  1120. if posi = dir.Length then posi := 0;
  1121. Result := Copy(dir,1,posi);
  1122. if (not Result.IsEmpty) and (EndsWithDelim) then Result := Result + delim;
  1123. end;
  1124. function GetPathDelimiter(const aPath : string) : string;
  1125. begin
  1126. if aPath.Contains('/') then Result := '/'
  1127. else if aPath.Contains('\') then Result := '\'
  1128. else Result := '';
  1129. end;
  1130. function GetFirstPathSegment(const aPath : string) : string;
  1131. var
  1132. delimiter : string;
  1133. spath : string;
  1134. begin
  1135. delimiter := GetPathDelimiter(aPath);
  1136. if delimiter.IsEmpty then Exit(aPath);
  1137. if aPath.StartsWith(delimiter) then spath := Copy(aPath,2,aPath.Length)
  1138. else spath := aPath;
  1139. if spath.Contains(delimiter) then Result := Copy(spath,0,spath.IndexOf(delimiter))
  1140. else Result := spath;
  1141. end;
  1142. function GetLastPathSegment(const aPath : string) : string;
  1143. var
  1144. delimiter : string;
  1145. spath : string;
  1146. begin
  1147. delimiter := GetPathDelimiter(aPath);
  1148. if delimiter.IsEmpty then Exit(aPath);
  1149. if aPath.EndsWith(delimiter) then spath := Copy(aPath,0,aPath.Length - 1)
  1150. else spath := aPath;
  1151. Result := spath.Substring(spath.LastDelimiter(delimiter)+1);
  1152. end;
  1153. function ParamFindSwitch(const Switch : string) : Boolean;
  1154. begin
  1155. Result := FindCmdLineSwitch(Switch,['-', '/'],True);
  1156. end;
  1157. {$IFDEF FPC}
  1158. function FindCmdLineSwitch(const Switch: string; var Value: string; IgnoreCase: Boolean = True;
  1159. const SwitchTypes: TCmdLineSwitchTypes = [clstValueNextParam, clstValueAppended]): Boolean; overload;
  1160. type
  1161. TCompareProc = function(const S1, S2: string): Boolean;
  1162. var
  1163. Param: string;
  1164. I, ValueOfs,
  1165. SwitchLen, ParamLen: Integer;
  1166. SameSwitch: TCompareProc;
  1167. begin
  1168. Result := False;
  1169. Value := '';
  1170. if IgnoreCase then
  1171. SameSwitch := SameText else
  1172. SameSwitch := SameStr;
  1173. SwitchLen := Switch.Length;
  1174. for I := 1 to ParamCount do
  1175. begin
  1176. Param := ParamStr(I);
  1177. if CharInSet(Param.Chars[0], SwitchChars) and SameSwitch(Param.SubString(1,SwitchLen), Switch) then
  1178. begin
  1179. ParamLen := Param.Length;
  1180. // Look for an appended value if the param is longer than the switch
  1181. if (ParamLen > SwitchLen + 1) then
  1182. begin
  1183. // If not looking for appended value switches then this is not a matching switch
  1184. if not (clstValueAppended in SwitchTypes) then
  1185. Continue;
  1186. ValueOfs := SwitchLen + 1;
  1187. if Param.Chars[ValueOfs] = ':' then
  1188. Inc(ValueOfs);
  1189. Value := Param.SubString(ValueOfs, MaxInt);
  1190. end
  1191. // If the next param is not a switch, then treat it as the value
  1192. else if (clstValueNextParam in SwitchTypes) and (I < ParamCount) and
  1193. not CharInSet(ParamStr(I+1).Chars[0], SwitchChars) then
  1194. Value := ParamStr(I+1);
  1195. Result := True;
  1196. Break;
  1197. end;
  1198. end;
  1199. end;
  1200. {$ENDIF}
  1201. function ParamGetSwitch(const Switch : string; var cvalue : string) : Boolean;
  1202. begin
  1203. Result := FindCmdLineSwitch(Switch,cvalue,True,[clstValueAppended]);
  1204. end;
  1205. function GetAppName : string;
  1206. begin
  1207. Result := ExtractFilenameWithoutExt(ParamStr(0));
  1208. end;
  1209. function GetAppVersionStr: string;
  1210. {$IFDEF MSWINDOWS}
  1211. var
  1212. Rec: LongRec;
  1213. ver : Cardinal;
  1214. begin
  1215. ver := GetFileVersion(ParamStr(0));
  1216. if ver <> Cardinal(-1) then
  1217. begin
  1218. Rec := LongRec(ver);
  1219. Result := Format('%d.%d', [Rec.Hi, Rec.Lo]);
  1220. end
  1221. else Result := '';
  1222. end;
  1223. {$ELSE}
  1224. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  1225. var
  1226. version : TProgramVersion;
  1227. begin
  1228. if GetProgramVersion(version) then Result := Format('%d.%d', [version.Major, version.Minor])
  1229. else Result := '';
  1230. end;
  1231. {$ELSE}
  1232. {$IFDEF NEXTGEN}
  1233. {$IFDEF ANDROID}
  1234. var
  1235. PkgInfo : JPackageInfo;
  1236. begin
  1237. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  1238. Result := IntToStr(PkgInfo.VersionCode);
  1239. end;
  1240. {$ELSE} //IOS
  1241. var
  1242. AppKey: Pointer;
  1243. AppBundle: NSBundle;
  1244. BuildStr : NSString;
  1245. begin
  1246. try
  1247. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1248. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1249. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1250. Result := UTF8ToString(BuildStr.UTF8String);
  1251. except
  1252. Result := '';
  1253. end;
  1254. end;
  1255. {$ENDIF}
  1256. {$ELSE} //OSX
  1257. {$IFDEF OSX}
  1258. var
  1259. AppKey: Pointer;
  1260. AppBundle: NSBundle;
  1261. BuildStr : NSString;
  1262. begin
  1263. try
  1264. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1265. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1266. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1267. Result := UTF8ToString(BuildStr.UTF8String);
  1268. except
  1269. Result := '';
  1270. end;
  1271. end;
  1272. {$ELSE}
  1273. begin
  1274. Result := '';
  1275. end;
  1276. {$ENDIF}
  1277. {$ENDIF}
  1278. {$ENDIF}
  1279. {$ENDIF}
  1280. function GetAppVersionFullStr: string;
  1281. {$IFDEF MSWINDOWS}
  1282. var
  1283. Exe: string;
  1284. Size, Handle: DWORD;
  1285. Buffer: TBytes;
  1286. FixedPtr: PVSFixedFileInfo;
  1287. begin
  1288. Result := '';
  1289. Exe := ParamStr(0);
  1290. Size := GetFileVersionInfoSize(PChar(Exe), Handle);
  1291. if Size = 0 then
  1292. begin
  1293. //RaiseLastOSError;
  1294. //no version info in file
  1295. Exit;
  1296. end;
  1297. SetLength(Buffer, Size);
  1298. if not GetFileVersionInfo(PChar(Exe), Handle, Size, Buffer) then
  1299. RaiseLastOSError;
  1300. if not VerQueryValue(Buffer, '\', Pointer(FixedPtr), Size) then
  1301. RaiseLastOSError;
  1302. if (LongRec(FixedPtr.dwFileVersionLS).Hi = 0) and (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  1303. begin
  1304. Result := Format('%d.%d',
  1305. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1306. LongRec(FixedPtr.dwFileVersionMS).Lo]); //minor
  1307. end
  1308. else if (LongRec(FixedPtr.dwFileVersionLS).Lo = 0) then
  1309. begin
  1310. Result := Format('%d.%d.%d',
  1311. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1312. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  1313. LongRec(FixedPtr.dwFileVersionLS).Hi]); //release
  1314. end
  1315. else
  1316. begin
  1317. Result := Format('%d.%d.%d.%d',
  1318. [LongRec(FixedPtr.dwFileVersionMS).Hi, //major
  1319. LongRec(FixedPtr.dwFileVersionMS).Lo, //minor
  1320. LongRec(FixedPtr.dwFileVersionLS).Hi, //release
  1321. LongRec(FixedPtr.dwFileVersionLS).Lo]); //build
  1322. end;
  1323. end;
  1324. {$ELSE}
  1325. {$IF DEFINED(FPC) AND DEFINED(LINUX)}
  1326. var
  1327. version : TProgramVersion;
  1328. begin
  1329. if GetProgramVersion(version) then Result := Format('%d.%d.%d.%d', [version.Major, version.Minor, version.Revision, version.Build])
  1330. else Result := '';
  1331. end;
  1332. {$ELSE}
  1333. {$IFDEF NEXTGEN}
  1334. {$IFDEF ANDROID}
  1335. var
  1336. PkgInfo : JPackageInfo;
  1337. begin
  1338. PkgInfo := SharedActivity.getPackageManager.getPackageInfo(SharedActivity.getPackageName,0);
  1339. Result := JStringToString(PkgInfo.versionName);
  1340. end;
  1341. {$ELSE} //IOS
  1342. var
  1343. AppKey: Pointer;
  1344. AppBundle: NSBundle;
  1345. BuildStr : NSString;
  1346. begin
  1347. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1348. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1349. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1350. Result := UTF8ToString(BuildStr.UTF8String);
  1351. end;
  1352. {$ENDIF}
  1353. {$ELSE}
  1354. {$IFDEF OSX}
  1355. var
  1356. AppKey: Pointer;
  1357. AppBundle: NSBundle;
  1358. BuildStr : NSString;
  1359. begin
  1360. AppKey := (StrToNSStr('CFBundleVersion') as ILocalObject).GetObjectID;
  1361. AppBundle := TNSBundle.Wrap(TNSBundle.OCClass.mainBundle);
  1362. BuildStr := TNSString.Wrap(AppBundle.infoDictionary.objectForKey(AppKey));
  1363. Result := UTF8ToString(BuildStr.UTF8String);
  1364. end;
  1365. {$ELSE}
  1366. begin
  1367. Result := '';
  1368. end;
  1369. {$ENDIF}
  1370. {$ENDIF}
  1371. {$ENDIF}
  1372. {$ENDIF}
  1373. function UTCToLocalTime(GMTTime: TDateTime): TDateTime;
  1374. begin
  1375. {$IFDEF FPC}
  1376. Result := LocalTimeToUniversal(GMTTime);
  1377. {$ELSE}
  1378. Result := TTimeZone.Local.ToLocalTime(GMTTime);
  1379. {$ENDIF}
  1380. end;
  1381. function LocalTimeToUTC(LocalTime : TDateTime): TDateTime;
  1382. begin
  1383. {$IFDEF FPC}
  1384. Result := UniversalTimeToLocal(Localtime);
  1385. {$ELSE}
  1386. Result := TTimeZone.Local.ToUniversalTime(LocalTime);
  1387. {$ENDIF}
  1388. end;
  1389. function DateTimeToGMT(aDate : TDateTime) : string;
  1390. var
  1391. FmtSettings : TFormatSettings;
  1392. begin
  1393. FmtSettings.DateSeparator := '-';
  1394. FmtSettings.TimeSeparator := ':';
  1395. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1396. Result := DateTimeToStr(aDate,FmtSettings).Trim;
  1397. end;
  1398. function GMTToDateTime(aDate : string) : TDateTime;
  1399. var
  1400. FmtSettings : TFormatSettings;
  1401. begin
  1402. FmtSettings.DateSeparator := '-';
  1403. FmtSettings.TimeSeparator := ':';
  1404. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ" GMT"';
  1405. Result := StrToDateTime(aDate,FmtSettings);
  1406. end;
  1407. function DateTimeToJsonDate(aDateTime : TDateTime) : string;
  1408. {$IFNDEF DELPHIXE7_UP}
  1409. var
  1410. FmtSettings : TFormatSettings;
  1411. {$ENDIF}
  1412. begin
  1413. {$IFDEF DELPHIXE7_UP}
  1414. Result := DateToISO8601(aDateTime);
  1415. {$ELSE}
  1416. FmtSettings.DateSeparator := '-';
  1417. FmtSettings.TimeSeparator := ':';
  1418. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1419. Result := DateTimeToStr(aDateTime,FmtSettings).Trim;
  1420. {$ENDIF}
  1421. end;
  1422. function JsonDateToDateTime(const aJsonDate : string) : TDateTime;
  1423. {$IFNDEF DELPHIXE7_UP}
  1424. var
  1425. FmtSettings : TFormatSettings;
  1426. {$ENDIF}
  1427. {$IFDEF FPC}
  1428. var
  1429. jdate : string;
  1430. {$ENDIF}
  1431. begin
  1432. {$IFDEF DELPHIXE7_UP}
  1433. Result := ISO8601ToDate(aJsonDate);
  1434. {$ELSE}
  1435. FmtSettings.DateSeparator := '-';
  1436. FmtSettings.TimeSeparator := ':';
  1437. FmtSettings.ShortDateFormat := 'YYYY-MM-DD"T"HH:NN:SS.ZZZ"Z"';
  1438. {$IFDEF FPC}
  1439. jdate := StringReplace(aJsondate,'T',' ',[rfIgnoreCase]);
  1440. jdate := Copy(jdate,1,Pos('.',jdate)-1);
  1441. Result := StrToDateTime(jdate,FmtSettings);
  1442. {$ELSE}
  1443. Result := StrToDateTime(aJsonDate,FmtSettings);
  1444. {$ENDIF}
  1445. {$ENDIF}
  1446. end;
  1447. function CountDigits(anInt: Cardinal): Cardinal; inline;
  1448. var
  1449. cmp: Cardinal;
  1450. begin
  1451. cmp := 10;
  1452. Result := 1;
  1453. while (Result < 10) and (cmp <= anInt) do
  1454. begin
  1455. cmp := cmp*10;
  1456. Inc(Result);
  1457. end;
  1458. end;
  1459. function CountStr(const aFindStr, aSourceStr : string) : Integer;
  1460. var
  1461. i : Integer;
  1462. found : Integer;
  1463. findstr : string;
  1464. mainstr : string;
  1465. begin
  1466. findstr := aFindStr.ToLower;
  1467. mainstr := aSourceStr.ToLower;
  1468. Result := 0;
  1469. i := 0;
  1470. while i < mainstr.Length do
  1471. begin
  1472. found := Pos(findstr,mainstr,i);
  1473. if found > 0 then
  1474. begin
  1475. i := found;
  1476. Inc(Result);
  1477. end
  1478. else Break;
  1479. end;
  1480. end;
  1481. procedure SaveStreamToFile(aStream : TStream; const aFileName : string);
  1482. var
  1483. fs : TFileStream;
  1484. begin
  1485. fs := TFileStream.Create(aFileName,fmCreate);
  1486. try
  1487. aStream.Seek(0,soBeginning);
  1488. fs.CopyFrom(aStream,aStream.Size);
  1489. finally
  1490. fs.Free;
  1491. end;
  1492. end;
  1493. function StreamToString(const aStream: TStream; const aEncoding: TEncoding): string;
  1494. var
  1495. sbytes: TBytes;
  1496. begin
  1497. aStream.Position := 0;
  1498. SetLength(sbytes, aStream.Size);
  1499. aStream.ReadBuffer(sbytes,aStream.Size);
  1500. Result := aEncoding.GetString(sbytes);
  1501. end;
  1502. function StreamToStringEx(aStream : TStream) : string;
  1503. var
  1504. ss : TStringStream;
  1505. begin
  1506. aStream.Position := 0;
  1507. if aStream = nil then Exit;
  1508. if aStream is TMemoryStream then
  1509. begin
  1510. SetString(Result, PChar(TMemoryStream(aStream).Memory), TMemoryStream(aStream).Size div SizeOf(Char));
  1511. end
  1512. else if aStream is TStringStream then
  1513. begin
  1514. Result := TStringStream(aStream).DataString;
  1515. end
  1516. else
  1517. begin
  1518. ss := TStringStream.Create;
  1519. try
  1520. aStream.Seek(0,soBeginning);
  1521. ss.CopyFrom(aStream,aStream.Size);
  1522. Result := ss.DataString;
  1523. finally
  1524. ss.Free;
  1525. end;
  1526. end;
  1527. end;
  1528. procedure StringToStream(const aStr : string; aStream : TStream; const aEncoding: TEncoding);
  1529. var
  1530. stream : TStringStream;
  1531. begin
  1532. stream := TStringStream.Create(aStr,aEncoding);
  1533. try
  1534. aStream.CopyFrom(stream,stream.Size);
  1535. finally
  1536. stream.Free;
  1537. end;
  1538. end;
  1539. procedure StringToStreamEx(const aStr : string; aStream : TStream);
  1540. begin
  1541. aStream.Seek(0,soBeginning);
  1542. aStream.WriteBuffer(Pointer(aStr)^,aStr.Length * SizeOf(Char));
  1543. end;
  1544. function CommaText(aList : TStringList) : string;
  1545. var
  1546. value : string;
  1547. sb : TStringBuilder;
  1548. begin
  1549. if aList.Text = '' then Exit;
  1550. sb := TStringBuilder.Create;
  1551. try
  1552. for value in aList do
  1553. begin
  1554. sb.Append(value);
  1555. sb.Append(',');
  1556. end;
  1557. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1558. finally
  1559. sb.Free;
  1560. end;
  1561. end;
  1562. function CommaText(aArray : TArray<string>) : string;
  1563. var
  1564. value : string;
  1565. sb : TStringBuilder;
  1566. begin
  1567. if High(aArray) < 0 then Exit;
  1568. sb := TStringBuilder.Create;
  1569. try
  1570. for value in aArray do
  1571. begin
  1572. sb.Append(value);
  1573. sb.Append(',');
  1574. end;
  1575. if sb.Length > 1 then Result := sb.ToString(0, sb.Length - 1);
  1576. finally
  1577. sb.Free;
  1578. end;
  1579. end;
  1580. function ArrayToString(aArray : TArray<string>) : string;
  1581. var
  1582. value : string;
  1583. sb : TStringBuilder;
  1584. begin
  1585. Result := '';
  1586. if High(aArray) < 0 then Exit;
  1587. sb := TStringBuilder.Create;
  1588. try
  1589. for value in aArray do
  1590. begin
  1591. sb.Append(value);
  1592. sb.Append(#10#13);
  1593. end;
  1594. Result := sb.ToString;
  1595. finally
  1596. sb.Free;
  1597. end;
  1598. end;
  1599. function ArrayToString(aArray : TArray<string>; aSeparator : string) : string;
  1600. var
  1601. value : string;
  1602. sb : TStringBuilder;
  1603. isfirst : Boolean;
  1604. begin
  1605. Result := '';
  1606. if High(aArray) < 0 then Exit;
  1607. isfirst := True;
  1608. sb := TStringBuilder.Create;
  1609. try
  1610. for value in aArray do
  1611. begin
  1612. if isfirst then isfirst := False
  1613. else sb.Append(aSeparator);
  1614. sb.Append(value);
  1615. end;
  1616. Result := sb.ToString;
  1617. finally
  1618. sb.Free;
  1619. end;
  1620. end;
  1621. function StringsToArray(aStrings : TStrings) : TArray<string>;
  1622. var
  1623. i : Integer;
  1624. begin
  1625. if aStrings.Count = 0 then Exit;
  1626. SetLength(Result,aStrings.Count);
  1627. for i := 0 to aStrings.Count - 1 do
  1628. begin
  1629. Result[i] := aStrings[i];
  1630. end;
  1631. end;
  1632. function StringsToArray(const aString : string) : TArray<string>;
  1633. var
  1634. item : string;
  1635. begin
  1636. for item in aString.Split([';',',']) do Result := Result + [item.Trim];
  1637. end;
  1638. { TCounter }
  1639. procedure TCounter.Init(aMaxValue : Integer);
  1640. begin
  1641. fMaxValue := aMaxValue;
  1642. fCurrentValue := 0;
  1643. end;
  1644. function TCounter.Count : Integer;
  1645. begin
  1646. Result := fCurrentValue;
  1647. end;
  1648. function TCounter.CountIs(aValue : Integer) : Boolean;
  1649. begin
  1650. Result := fCurrentValue = aValue;
  1651. end;
  1652. function TCounter.Check : Boolean;
  1653. begin
  1654. if fCurrentValue = fMaxValue then
  1655. begin
  1656. Result := True;
  1657. Reset;
  1658. end
  1659. else
  1660. begin
  1661. Result := False;
  1662. Inc(fCurrentValue);
  1663. end;
  1664. end;
  1665. procedure TCounter.Reset;
  1666. begin
  1667. fCurrentValue := fMaxValue;
  1668. end;
  1669. { TimeCounter }
  1670. procedure TTimeCounter.Init(MillisecondsToReach : Integer);
  1671. begin
  1672. fDoneEvery := MillisecondsToReach;
  1673. end;
  1674. function TTimeCounter.Check : Boolean;
  1675. begin
  1676. if MilliSecondsBetween(fCurrentTime,Now) > fDoneEvery then
  1677. begin
  1678. fCurrentTime := Now();
  1679. Result := True;
  1680. end
  1681. else Result := False;
  1682. end;
  1683. procedure TTimeCounter.Reset;
  1684. begin
  1685. fCurrentTime := Now();
  1686. end;
  1687. { TArrayOfStringHelper}
  1688. {$IFNDEF FPC}
  1689. function TArrayOfStringHelper.Any : Boolean;
  1690. begin
  1691. Result := High(Self) >= 0;
  1692. end;
  1693. function TArrayOfStringHelper.Any(const aValue : string) : Boolean;
  1694. begin
  1695. Result := Exists(aValue);
  1696. end;
  1697. function TArrayOfStringHelper.Add(const aValue : string) : Integer;
  1698. begin
  1699. SetLength(Self,Length(Self)+1);
  1700. Self[High(Self)] := aValue;
  1701. Result := High(Self);
  1702. end;
  1703. function TArrayOfStringHelper.AddIfNotExists(const aValue : string; aCaseSense : Boolean = False) : Integer;
  1704. var
  1705. i : Integer;
  1706. begin
  1707. for i := Low(Self) to High(Self) do
  1708. begin
  1709. if aCaseSense then
  1710. begin
  1711. if Self[i] = aValue then Exit(i);
  1712. end
  1713. else
  1714. begin
  1715. if CompareText(Self[i],aValue) = 0 then Exit(i)
  1716. end;
  1717. end;
  1718. //if not exists add it
  1719. Result := Self.Add(aValue);
  1720. end;
  1721. function TArrayOfStringHelper.Remove(const aValue : string) : Boolean;
  1722. var
  1723. i : Integer;
  1724. begin
  1725. for i := Low(Self) to High(Self) do
  1726. begin
  1727. if CompareText(Self[i],aValue) = 0 then
  1728. begin
  1729. {$IFDEF DELPHIXE7_UP}
  1730. System.Delete(Self,i,1);
  1731. {$ELSE}
  1732. TArrayUtil<string>.Delete(Self,i);
  1733. {$ENDIF}
  1734. Exit(True);
  1735. end;
  1736. end;
  1737. Result := False;
  1738. end;
  1739. function TArrayOfStringHelper.Exists(const aValue : string) : Boolean;
  1740. var
  1741. value : string;
  1742. begin
  1743. Result := False;
  1744. for value in Self do
  1745. begin
  1746. if CompareText(value,aValue) = 0 then Exit(True)
  1747. end;
  1748. end;
  1749. function TArrayOfStringHelper.Count : Integer;
  1750. begin
  1751. Result := High(Self) + 1;
  1752. end;
  1753. {$ENDIF}
  1754. { TPairItem }
  1755. constructor TPairItem.Create(const aName, aValue: string);
  1756. begin
  1757. Name := aName;
  1758. Value := aValue;
  1759. end;
  1760. { TPairList }
  1761. function TPairList.GetEnumerator : TPairEnumerator;
  1762. begin
  1763. Result := TPairEnumerator.Create(fItems);
  1764. end;
  1765. function TPairList.Add(aPair: TPairItem): Integer;
  1766. begin
  1767. SetLength(fItems,Length(fItems)+1);
  1768. fItems[High(fItems)] := aPair;
  1769. Result := High(fItems);
  1770. end;
  1771. function TPairList.Add(const aName, aValue: string): Integer;
  1772. begin
  1773. SetLength(fItems,Length(fItems)+1);
  1774. fItems[High(fItems)].Name := aName;
  1775. fItems[High(fItems)].Value := aValue;
  1776. Result := High(fItems);
  1777. end;
  1778. procedure TPairList.AddOrUpdate(const aName, aValue: string);
  1779. var
  1780. i : Integer;
  1781. begin
  1782. for i := Low(fItems) to High(fItems) do
  1783. begin
  1784. if CompareText(fItems[i].Name,aName) = 0 then
  1785. begin
  1786. fItems[i].Value := aValue;
  1787. Exit;
  1788. end;
  1789. end;
  1790. //if not exists add it
  1791. Self.Add(aName,aValue);
  1792. end;
  1793. function TPairList.Count: Integer;
  1794. begin
  1795. Result := High(fItems) + 1;
  1796. end;
  1797. function TPairList.Exists(const aName: string): Boolean;
  1798. var
  1799. i : Integer;
  1800. begin
  1801. Result := False;
  1802. for i := Low(fItems) to High(fItems) do
  1803. begin
  1804. if CompareText(fItems[i].Name,aName) = 0 then Exit(True)
  1805. end;
  1806. end;
  1807. function TPairList.GetPair(const aName: string): TPairItem;
  1808. var
  1809. i : Integer;
  1810. begin
  1811. for i := Low(fItems) to High(fItems) do
  1812. begin
  1813. if CompareText(fItems[i].Name,aName) = 0 then Exit(fItems[i]);
  1814. end;
  1815. end;
  1816. function TPairList.GetValue(const aName: string): string;
  1817. var
  1818. i : Integer;
  1819. begin
  1820. Result := '';
  1821. for i := Low(fItems) to High(fItems) do
  1822. begin
  1823. if CompareText(fItems[i].Name,aName) = 0 then Exit(fItems[i].Value);
  1824. end;
  1825. end;
  1826. function TPairList.Remove(const aName: string): Boolean;
  1827. var
  1828. i : Integer;
  1829. begin
  1830. for i := Low(fItems) to High(fItems) do
  1831. begin
  1832. if CompareText(fItems[i].Name,aName) = 0 then
  1833. begin
  1834. {$IF Defined(DELPHIXE7_UP) OR Defined(FPC)}
  1835. System.Delete(fItems,i,1);
  1836. {$ELSE}
  1837. TArrayUtil<TPairItem>.Delete(fItems,i);
  1838. {$ENDIF}
  1839. Exit(True);
  1840. end;
  1841. end;
  1842. Result := False;
  1843. end;
  1844. function TPairList.ToArray : TArray<TPairItem>;
  1845. begin
  1846. Result := fItems;
  1847. end;
  1848. procedure TPairList.FromArray(aValue : TArray<TPairItem>);
  1849. begin
  1850. fItems := aValue;
  1851. end;
  1852. procedure TPairList.Clear;
  1853. begin
  1854. SetLength(fItems,0);
  1855. end;
  1856. { TPairList.TPairEnumerator}
  1857. constructor TPairList.TPairEnumerator.Create(var aArray: TArray<TPairItem>);
  1858. begin
  1859. fIndex := -1;
  1860. fArray := @aArray;
  1861. end;
  1862. function TPairList.TPairEnumerator.GetCurrent : TPairItem;
  1863. begin
  1864. Result := TArray<TPairItem>(fArray^)[fIndex];
  1865. end;
  1866. function TPairList.TPairEnumerator.MoveNext: Boolean;
  1867. begin
  1868. Inc(fIndex);
  1869. Result := fIndex < High(TArray<TPairItem>(fArray^))+1;
  1870. end;
  1871. {$IFDEF MSWINDOWS}
  1872. procedure ProcessMessages;
  1873. var
  1874. Msg: TMsg;
  1875. begin
  1876. while integer(PeekMessage(Msg, 0, 0, 0, PM_REMOVE)) <> 0 do
  1877. begin
  1878. TranslateMessage(Msg);
  1879. DispatchMessage(Msg);
  1880. end;
  1881. end;
  1882. function GetLastOSError: String;
  1883. begin
  1884. Result := SysErrorMessage(Windows.GetLastError);
  1885. end;
  1886. {$ENDIF}
  1887. function RemoveLastChar(const aText : string) : string;
  1888. begin
  1889. Result := aText.Remove(aText.Length - 1);
  1890. end;
  1891. function DateTimeToSQL(aDateTime : TDateTime) : string;
  1892. begin
  1893. Result := FormatDateTime('YYYY-MM-DD hh:mm:ss',aDateTime);
  1894. end;
  1895. function IsInteger(const aValue : string) : Boolean;
  1896. var
  1897. i : Integer;
  1898. begin
  1899. Result := TryStrToInt(aValue,i);
  1900. end;
  1901. function IsFloat(const aValue : string) : Boolean;
  1902. var
  1903. e : Extended;
  1904. begin
  1905. Result := TryStrToFloat(aValue,e);
  1906. end;
  1907. function IsBoolean(const aValue : string) : Boolean;
  1908. var
  1909. b : Boolean;
  1910. begin
  1911. Result := TryStrToBool(aValue,b);
  1912. end;
  1913. function ExtractStr(var vSource : string; aIndex : Integer; aCount : Integer) : string;
  1914. begin
  1915. if aIndex > vSource.Length then Exit('');
  1916. Result := Copy(vSource,aIndex,aCount);
  1917. Delete(vSource,aIndex,aCount);
  1918. end;
  1919. function GetSubString(const aSource, aFirstDelimiter, aLastDelimiter : string) : string;
  1920. var
  1921. i : Integer;
  1922. begin
  1923. i := Pos(aFirstDelimiter,aSource);
  1924. if i > -1 then Result := Copy(aSource, i + aFirstDelimiter.Length, Pos(aLastDelimiter, aSource, i + aFirstDelimiter.Length) - i - aFirstDelimiter.Length)
  1925. else Result := '';
  1926. end;
  1927. function DbQuotedStr(const str : string): string;
  1928. var
  1929. i : Integer;
  1930. begin
  1931. Result := str;
  1932. for i := Result.Length - 1 downto 0 do
  1933. begin
  1934. if Result.Chars[i] = '"' then Result := Result.Insert(i, '"');
  1935. end;
  1936. Result := '"' + Result + '"';
  1937. end;
  1938. function UnDbQuotedStr(const str: string) : string;
  1939. begin
  1940. Result := Trim(str);
  1941. if not Result.IsEmpty then
  1942. begin
  1943. if Result.StartsWith('"') then Result := Copy(Result, 2, Result.Length - 2);
  1944. end;
  1945. end;
  1946. function SpQuotedStr(const str : string): string;
  1947. begin
  1948. Result := '''' + str + '''';
  1949. end;
  1950. function UnSpQuotedStr(const str: string) : string;
  1951. begin
  1952. Result := Trim(str);
  1953. if not Result.IsEmpty then
  1954. begin
  1955. if Result.StartsWith('''') then Result := Copy(Result, 2, Result.Length - 2);
  1956. end;
  1957. end;
  1958. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : string) : string;
  1959. begin
  1960. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1961. end;
  1962. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Integer) : Integer;
  1963. begin
  1964. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1965. end;
  1966. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : Extended) : Extended;
  1967. begin
  1968. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1969. end;
  1970. function Ifx(aCondition : Boolean; const aIfIsTrue, aIfIsFalse : TObject) : TObject;
  1971. begin
  1972. if aCondition then Result := aIfIsTrue else Result := aIfIsFalse;
  1973. end;
  1974. {$IFNDEF FPC}
  1975. {$IFNDEF DELPHIXE7_UP}
  1976. class procedure TArrayUtil<T>.Delete(var aArray : TArray<T>; aIndex : Integer);
  1977. var
  1978. n : Integer;
  1979. len : Integer;
  1980. begin
  1981. len := Length(aArray);
  1982. if (len > 0) and (aIndex < len) then
  1983. begin
  1984. for n := aIndex + 1 to len - 1 do aArray[n - 1] := aArray[n];
  1985. SetLength(aArray, len - 1);
  1986. end;
  1987. end;
  1988. {$ENDIF}
  1989. {$ENDIF}
  1990. { TDateTimeHelper }
  1991. {$IFDEF DELPHIXE7_UP}
  1992. function TDateTimeHelper.ToSQLString : string;
  1993. begin
  1994. Result := DateTimeToSQL(Self);
  1995. end;
  1996. procedure TDateTimeHelper.FromNow;
  1997. begin
  1998. Self := Now;
  1999. end;
  2000. procedure TDateTimeHelper.FromUTC(const aUTCTime: TDateTime);
  2001. begin
  2002. Self := UTCToLocalTime(aUTCTime);
  2003. end;
  2004. function TDateTimeHelper.IncDay(const aValue : Cardinal = 1) : TDateTime;
  2005. begin
  2006. Result := System.DateUtils.IncDay(Self,aValue);
  2007. end;
  2008. function TDateTimeHelper.DecDay(const aValue : Cardinal = 1) : TDateTime;
  2009. begin
  2010. Result := System.DateUtils.IncDay(Self,aValue * - 1);
  2011. end;
  2012. function TDateTimeHelper.IncMonth(const aValue : Cardinal = 1) : TDateTime;
  2013. begin
  2014. Result := System.DateUtils.IncDay(Self,aValue);
  2015. end;
  2016. function TDateTimeHelper.DecMonth(const aValue : Cardinal = 1) : TDateTime;
  2017. begin
  2018. Result := System.DateUtils.IncDay(Self,aValue * - 1);
  2019. end;
  2020. function TDateTimeHelper.IncYear(const aValue : Cardinal = 1) : TDateTime;
  2021. begin
  2022. Result := System.DateUtils.IncDay(Self,aValue);
  2023. end;
  2024. function TDateTimeHelper.DecYear(const aValue : Cardinal = 1) : TDateTime;
  2025. begin
  2026. Result := System.DateUtils.IncDay(Self,aValue * - 1);
  2027. end;
  2028. function TDateTimeHelper.IsEqualTo(const aDateTime : TDateTime) : Boolean;
  2029. begin
  2030. Result := Self = aDateTime;
  2031. end;
  2032. function TDateTimeHelper.IsAfter(const aDateTime : TDateTime) : Boolean;
  2033. begin
  2034. Result := Self > aDateTime;
  2035. end;
  2036. function TDateTimeHelper.IsBefore(const aDateTime : TDateTime) : Boolean;
  2037. begin
  2038. Result := Self < aDateTime;
  2039. end;
  2040. function TDateTimeHelper.IsSameDay(const aDateTime : TDateTime) : Boolean;
  2041. begin
  2042. Result := System.DateUtils.SameDate(Self,aDateTime);
  2043. end;
  2044. function TDateTimeHelper.IsSameTime(const aTime : TTime) : Boolean;
  2045. begin
  2046. Result := System.DateUtils.SameTime(Self,aTime);
  2047. end;
  2048. function TDateTimeHelper.DayOfTheWeek : Word;
  2049. begin
  2050. Result := System.DateUtils.NthDayOfWeek(Self);
  2051. end;
  2052. function TDateTimeHelper.ToJsonFormat : string;
  2053. begin
  2054. Result := DateTimeToJsonDate(Self);
  2055. end;
  2056. function TDateTimeHelper.ToGMTFormat : string;
  2057. begin
  2058. Result := DateTimeToGMT(Self);
  2059. end;
  2060. function TDateTimeHelper.ToTimeStamp : TTimeStamp;
  2061. begin
  2062. Result := DateTimeToTimeStamp(Self);
  2063. end;
  2064. function TDateTimeHelper.ToUTC : TDateTime;
  2065. begin
  2066. Result := LocalTimeToUTC(Self);
  2067. end;
  2068. function TDateTimeHelper.ToMilliseconds : Int64;
  2069. begin
  2070. Result := System.DateUtils.DateTimeToMilliseconds(Self);
  2071. end;
  2072. function TDateTimeHelper.ToString : string;
  2073. begin
  2074. Result := DateTimeToStr(Self);
  2075. end;
  2076. function TDateTimeHelper.Date : TDate;
  2077. begin
  2078. Result := System.DateUtils.DateOf(Self);
  2079. end;
  2080. function TDateTimeHelper.Time : TTime;
  2081. begin
  2082. Result := System.DateUtils.TimeOf(Self);
  2083. end;
  2084. function TDateTimeHelper.IsAM : Boolean;
  2085. begin
  2086. Result := System.DateUtils.IsAM(Self);
  2087. end;
  2088. function TDateTimeHelper.IsPM : Boolean;
  2089. begin
  2090. Result := System.DateUtils.IsPM(Self);
  2091. end;
  2092. {$ENDIF}
  2093. {$IFNDEF NEXTGEN}
  2094. initialization
  2095. try
  2096. GetEnvironmentPaths;
  2097. except
  2098. {$IFDEF SHOW_ENVIRONMENTPATH_ERRORS}
  2099. on E : Exception do
  2100. begin
  2101. if not IsService then
  2102. begin
  2103. if HasConsoleOutput then Writeln(Format('[WARN] GetEnvironmentPaths: %s',[E.Message]))
  2104. else MessageBox(0,PWideChar(Format('Get environment path error: %s',[E.Message])),'GetEnvironmentPaths',MB_ICONEXCLAMATION);
  2105. end;
  2106. end;
  2107. {$ENDIF}
  2108. end;
  2109. {$ENDIF}
  2110. end.