sysstr.inc 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995
  1. {%MainUnit sysutils.pp}
  2. {
  3. *********************************************************************
  4. Copyright (C) 1997, 1998 Gertjan Schouten
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************
  11. System Utilities For Free Pascal
  12. }
  13. { NewStr creates a new PString and assigns S to it
  14. if length(s) = 0 NewStr returns Nil }
  15. function NewStr(const S: string): PString;
  16. begin
  17. if (S='') then
  18. Result:=nil
  19. else
  20. begin
  21. new(result);
  22. if (Result<>nil) then
  23. Result^:=s;
  24. end;
  25. end;
  26. {$ifdef dummy}
  27. { declaring this breaks delphi compatibility and e.g. tw3721.pp }
  28. FUNCTION NewStr (Const S: ShortString): PShortString;
  29. VAR P: PShortString;
  30. BEGIN
  31. If (S = '') Then
  32. P := Nil
  33. Else
  34. Begin { Return nil }
  35. GetMem(P, Length(S) + 1); { Allocate memory }
  36. If (P<>Nil) Then P^ := S; { Hold string }
  37. End;
  38. NewStr := P; { Return result }
  39. END;
  40. {$endif dummy}
  41. { DisposeStr frees the memory occupied by S }
  42. procedure DisposeStr(S: PString);
  43. begin
  44. if S <> Nil then
  45. begin
  46. dispose(s);
  47. S:=nil;
  48. end;
  49. end;
  50. PROCEDURE DisposeStr (S: PShortString);
  51. BEGIN
  52. If (S <> Nil) Then FreeMem(S, Length(S^) + 1); { Release memory }
  53. END;
  54. { AssignStr assigns S to P^ }
  55. procedure AssignStr(var P: PString; const S: string);
  56. begin
  57. P^ := s;
  58. end ;
  59. { AppendStr appends S to Dest }
  60. procedure AppendStr(var Dest: String; const S: string);
  61. begin
  62. Dest := Dest + S;
  63. end ;
  64. function IsLeadChar(C: AnsiChar): Boolean; inline;
  65. begin
  66. Result:=C in LeadBytes;
  67. end;
  68. function IsLeadChar(B: Byte): Boolean; inline;
  69. begin
  70. Result:=AnsiChar(B) in LeadBytes;
  71. end;
  72. Function InternalChangeCase(Const S : AnsiString; const Chars: TSysCharSet; const Adjustment: Longint): AnsiString;
  73. var
  74. i : Integer;
  75. P : PAnsiChar;
  76. Unique : Boolean;
  77. begin
  78. Result := S;
  79. if Result='' then
  80. exit;
  81. Unique:=false;
  82. P:=PAnsiChar(Result);
  83. for i:=1 to Length(Result) do
  84. begin
  85. if CharInSet(P^,Chars) then
  86. begin
  87. if not Unique then
  88. begin
  89. UniqueString(Result);
  90. p:=@Result[i];
  91. Unique:=true;
  92. end;
  93. P^:=AnsiChar(Ord(P^)+Adjustment);
  94. end;
  95. Inc(P);
  96. end;
  97. end;
  98. { UpperCase returns a copy of S where all lowercase characters ( from a to z )
  99. have been converted to uppercase }
  100. Function UpperCase(Const S : AnsiString) : AnsiString;
  101. begin
  102. Result:=InternalChangeCase(S,['a'..'z'],-32);
  103. end;
  104. function UpperCase(const s: ansistring; LocaleOptions: TLocaleOptions): ansistring; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  105. begin
  106. case LocaleOptions of
  107. loInvariantLocale: Result:=UpperCase(s);
  108. loUserLocale: Result:=AnsiUpperCase(s);
  109. end;
  110. end;
  111. { LowerCase returns a copy of S where all uppercase characters ( from A to Z )
  112. have been converted to lowercase }
  113. Function Lowercase(Const S : AnsiString) : AnsiString;
  114. begin
  115. Result:=InternalChangeCase(S,['A'..'Z'],32);
  116. end;
  117. function LowerCase(const s: ansistring; LocaleOptions: TLocaleOptions): ansistring; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  118. begin
  119. case LocaleOptions of
  120. loInvariantLocale: Result:=LowerCase(s);
  121. loUserLocale: Result:=AnsiLowerCase(s);
  122. end;
  123. end;
  124. function LowerCase(const V: variant): string; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  125. begin
  126. {$IFDEF UNICODERTL}
  127. result:=LowerCase(widestring(V));
  128. {ELSE}
  129. result:=LowerCase(ansistring(V));
  130. {$ENDIF}
  131. end;
  132. { CompareStr compares S1 and S2, the result is the based on
  133. substraction of the ascii values of the characters in S1 and S2
  134. case result
  135. S1 < S2 < 0
  136. S1 > S2 > 0
  137. S1 = S2 = 0 }
  138. {$IF SIZEOF(SIZEINT)>SIZEOF(INTEGER)}
  139. Function DoCapSizeInt(SI : SizeInt) : Integer; inline;
  140. begin
  141. if (SI<0) then
  142. result:=-1
  143. else if (SI>0) then
  144. result:=1
  145. else
  146. result:=0;
  147. end;
  148. {$DEFINE CAPSIZEINT:=DoCapSizeInt}
  149. {$ELSE}
  150. {$DEFINE CAPSIZEINT:=}
  151. {$ENDIF}
  152. function CompareStr(const S1, S2: string): Integer;
  153. var count, count1, count2: SizeInt;
  154. begin
  155. Count1 := Length(S1);
  156. Count2 := Length(S2);
  157. if Count1>Count2 then
  158. Count:=Count2
  159. else
  160. Count:=Count1;
  161. result := CompareMemRange(Pointer(S1),Pointer(S2), Count);
  162. if result=0 then
  163. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  164. result:=CAPSIZEINT(Count1-Count2);
  165. end;
  166. function CompareStr(const S1, S2: string; LocaleOptions: TLocaleOptions): Integer; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  167. begin
  168. case LocaleOptions of
  169. loInvariantLocale: Result:=CompareStr(S1,S2);
  170. loUserLocale: Result:=AnsiCompareStr(S1,S2);
  171. end;
  172. end;
  173. { CompareMemRange returns the result of comparison of Length bytes at P1 and P2
  174. case result
  175. P1 < P2 < 0
  176. P1 > P2 > 0
  177. P1 = P2 = 0 }
  178. function CompareMemRange(P1, P2: Pointer; Length: PtrUInt): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  179. begin
  180. If P1=P2 then
  181. Result:=0
  182. else
  183. Result:=CompareByte(P1^,P2^,Length);
  184. end;
  185. function CompareMem(P1, P2: Pointer; Length: PtrUInt): Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
  186. begin
  187. if P1=P2 then
  188. Result:=True
  189. else
  190. Result:=CompareByte(P1^,P2^,Length)=0;
  191. end;
  192. { CompareText compares S1 and S2, the result is the based on
  193. substraction of the ascii values of characters in S1 and S2
  194. comparison is case-insensitive
  195. case result
  196. S1 < S2 < 0
  197. S1 > S2 > 0
  198. S1 = S2 = 0 }
  199. function CompareText(const S1, S2: string): Integer; overload;
  200. var
  201. i, count, count1, count2: sizeint;
  202. Chr1, Chr2: byte;
  203. P1, P2: PChar;
  204. begin
  205. Count1 := Length(S1);
  206. Count2 := Length(S2);
  207. if (Count1>Count2) then
  208. Count := Count2
  209. else
  210. Count := Count1;
  211. i := 0;
  212. if count>0 then
  213. begin
  214. P1 := @S1[1];
  215. P2 := @S2[1];
  216. while i < Count do
  217. begin
  218. Chr1 := byte(p1^);
  219. Chr2 := byte(p2^);
  220. if Chr1 <> Chr2 then
  221. begin
  222. if Chr1 in [97..122] then
  223. dec(Chr1,32);
  224. if Chr2 in [97..122] then
  225. dec(Chr2,32);
  226. if Chr1 <> Chr2 then
  227. Break;
  228. end;
  229. Inc(P1); Inc(P2); Inc(I);
  230. end;
  231. end;
  232. if i < Count then
  233. result := Chr1-Chr2
  234. else
  235. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  236. result:=CAPSIZEINT(Count1-Count2);
  237. end;
  238. function CompareText(const S1, S2: string; LocaleOptions: TLocaleOptions): Integer; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  239. begin
  240. case LocaleOptions of
  241. loInvariantLocale: Result:=CompareText(S1,S2);
  242. loUserLocale: Result:=AnsiCompareText(S1,S2);
  243. end;
  244. end;
  245. function SameText(const s1,s2:String):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  246. begin
  247. Result:=CompareText(S1,S2)=0;
  248. end;
  249. function SameText(const s1,s2:String; LocaleOptions: TLocaleOptions):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  250. begin
  251. case LocaleOptions of
  252. loInvariantLocale: Result:=SameText(S1,S2);
  253. loUserLocale: Result:=AnsiSameText(S1,S2);
  254. end;
  255. end;
  256. function SameStr(const s1,s2:String):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  257. begin
  258. Result:=CompareStr(S1,S2)=0;
  259. end;
  260. function SameStr(const s1,s2:String; LocaleOptions: TLocaleOptions):Boolean; overload;{$ifdef SYSUTILSINLINE}inline;{$endif}
  261. begin
  262. case LocaleOptions of
  263. loInvariantLocale: Result:=SameStr(S1,S2);
  264. loUserLocale: Result:=AnsiSameStr(S1,S2);
  265. end;
  266. end;
  267. {$ifndef FPC_NOGENERICANSIROUTINES}
  268. {==============================================================================}
  269. { Ansi string functions }
  270. { these functions rely on the character set loaded by the OS }
  271. {==============================================================================}
  272. type
  273. TCaseTranslationTable = array[0..255] of AnsiChar;
  274. var
  275. { Tables with upper and lowercase forms of character sets.
  276. MUST be initialized with the correct code-pages }
  277. UpperCaseTable: TCaseTranslationTable;
  278. LowerCaseTable: TCaseTranslationTable;
  279. function GenericAnsiUpperCase(const s: ansistring): ansistring;
  280. var
  281. len, i: integer;
  282. begin
  283. len := length(s);
  284. SetLength(result, len);
  285. for i := 1 to len do
  286. result[i] := UpperCaseTable[ord(s[i])];
  287. end;
  288. function GenericAnsiLowerCase(const s: ansistring): ansistring;
  289. var
  290. len, i: integer;
  291. begin
  292. len := length(s);
  293. SetLength(result, len);
  294. for i := 1 to len do
  295. result[i] := LowerCaseTable[ord(s[i])];
  296. end;
  297. function GenericAnsiCompareStr(const S1, S2: ansistring): PtrInt;
  298. Var
  299. I,L1,L2 : SizeInt;
  300. begin
  301. Result:=0;
  302. L1:=Length(S1);
  303. L2:=Length(S2);
  304. I:=1;
  305. While (Result=0) and ((I<=L1) and (I<=L2)) do
  306. begin
  307. Result:=Ord(S1[I])-Ord(S2[I]); //!! Must be replaced by ansi characters !!
  308. Inc(I);
  309. end;
  310. If Result=0 Then
  311. Result:=L1-L2;
  312. end;
  313. function GenericAnsiCompareText(const S1, S2: ansistring): PtrInt;
  314. Var
  315. I,L1,L2 : SizeInt;
  316. begin
  317. Result:=0;
  318. L1:=Length(S1);
  319. L2:=Length(S2);
  320. I:=1;
  321. While (Result=0) and ((I<=L1) and (I<=L2)) do
  322. begin
  323. Result:=Ord(LowerCaseTable[Ord(S1[I])])-Ord(LowerCaseTable[Ord(S2[I])]); //!! Must be replaced by ansi characters !!
  324. Inc(I);
  325. end;
  326. If Result=0 Then
  327. Result:=L1-L2;
  328. end;
  329. function GenericAnsiStrComp(S1, S2: PAnsiChar): PtrInt;
  330. begin
  331. Result:=0;
  332. If S1=Nil then
  333. begin
  334. If S2=Nil Then Exit;
  335. result:=-1;
  336. exit;
  337. end;
  338. If S2=Nil then
  339. begin
  340. Result:=1;
  341. exit;
  342. end;
  343. While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
  344. Result:=Ord(S1^)-Ord(S2^); //!! Must be replaced by ansi characters !!
  345. Inc(S1);
  346. Inc(S2);
  347. end;
  348. if (Result=0) and (S1^<>S2^) then // loop ended because exactly one has #0
  349. if S1^=#0 then // shorter string is smaller
  350. result:=-1
  351. else
  352. result:=1;
  353. end;
  354. function GenericAnsiStrIComp(S1, S2: PAnsiChar): PtrInt;
  355. begin
  356. Result:=0;
  357. If S1=Nil then
  358. begin
  359. If S2=Nil Then Exit;
  360. result:=-1;
  361. exit;
  362. end;
  363. If S2=Nil then
  364. begin
  365. Result:=1;
  366. exit;
  367. end;
  368. While (Result=0) and (S1^<>#0) and (S2^<>#0) do begin
  369. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  370. Inc(S1);
  371. Inc(S2);
  372. end;
  373. if (Result=0) and (s1[0]<>s2[0]) then //length(s1)<>length(s2)
  374. if s1[0]=#0 then
  375. Result:=-1 //s1 shorter than s2
  376. else
  377. Result:=1; //s1 longer than s2
  378. end;
  379. function GenericAnsiStrLComp(S1, S2: PAnsiChar; MaxLen: PtrUInt): PtrInt;
  380. Var I : PtrUInt;
  381. begin
  382. Result:=0;
  383. If MaxLen=0 then exit;
  384. If S1=Nil then
  385. begin
  386. If S2=Nil Then Exit;
  387. result:=-1;
  388. exit;
  389. end;
  390. If S2=Nil then
  391. begin
  392. Result:=1;
  393. exit;
  394. end;
  395. I:=0;
  396. Repeat
  397. Result:=Ord(S1[0])-Ord(S2[0]); //!! Must be replaced by ansi characters !!
  398. Inc(S1);
  399. Inc(S2);
  400. Inc(I);
  401. Until (Result<>0) or (I=MaxLen)
  402. end;
  403. function GenericAnsiStrLIComp(S1, S2: PAnsiChar; MaxLen: PtrUInt): PtrInt;
  404. Var I : PtrUInt;
  405. begin
  406. Result:=0;
  407. If MaxLen=0 then exit;
  408. If S1=Nil then
  409. begin
  410. If S2=Nil Then Exit;
  411. result:=-1;
  412. exit;
  413. end;
  414. If S2=Nil then
  415. begin
  416. Result:=1;
  417. exit;
  418. end;
  419. I:=0;
  420. Repeat
  421. Result:=Ord(LowerCaseTable[Ord(S1[0])])-Ord(LowerCaseTable[Ord(S2[0])]); //!! Must be replaced by ansi characters !!
  422. Inc(S1);
  423. Inc(S2);
  424. Inc(I);
  425. Until (Result<>0) or (I=MaxLen)
  426. end;
  427. function GenericAnsiStrLower(Str: PAnsiChar): PAnsiChar;
  428. begin
  429. result := Str;
  430. if Str <> Nil then begin
  431. while Str^ <> #0 do begin
  432. Str^ := LowerCaseTable[byte(Str^)];
  433. Str := Str + 1;
  434. end;
  435. end;
  436. end;
  437. function GenericAnsiStrUpper(Str: PAnsiChar): PAnsiChar;
  438. begin
  439. result := Str;
  440. if Str <> Nil then begin
  441. while Str^ <> #0 do begin
  442. Str^ := UpperCaseTable[byte(Str^)];
  443. Str := Str + 1;
  444. end ;
  445. end ;
  446. end ;
  447. {$endif FPC_NOGENERICANSIROUTINES}
  448. function AnsiSameText(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
  449. begin
  450. AnsiSameText:=AnsiCompareText(S1,S2)=0;
  451. end;
  452. function AnsiSameStr(const s1,s2:String):Boolean;{$ifdef SYSUTILSINLINE}inline;{$endif}
  453. begin
  454. AnsiSameStr:=AnsiCompareStr(S1,S2)=0;
  455. end;
  456. function AnsiLastChar(const S: AnsiString): PAnsiChar;
  457. begin
  458. //!! No multibyte yet, so we return the last one.
  459. result:=StrEnd(PAnsiChar(pointer(S))); // strend checks for nil
  460. Dec(Result);
  461. end ;
  462. function AnsiStrLastChar(Str: PAnsiChar): PAnsiChar;
  463. begin
  464. //!! No multibyte yet, so we return the last one.
  465. result:=StrEnd(Str);
  466. Dec(Result);
  467. end ;
  468. function AnsiUpperCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  469. begin
  470. result:=widestringmanager.UpperAnsiStringProc(s);
  471. end;
  472. function AnsiLowerCase(const s: string): string;{$ifdef SYSUTILSINLINE}inline;{$endif}
  473. begin
  474. result:=widestringmanager.LowerAnsiStringProc(s);
  475. end;
  476. function AnsiCompareStr(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  477. begin
  478. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  479. result:=CAPSIZEINT(widestringmanager.CompareStrAnsiStringProc(s1,s2));
  480. end;
  481. function AnsiCompareText(const S1, S2: string): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  482. begin
  483. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  484. result:=CAPSIZEINT(widestringmanager.CompareTextAnsiStringProc(s1,s2));
  485. end;
  486. function AnsiStrComp(S1, S2: PAnsiChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  487. begin
  488. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  489. result:=CAPSIZEINT(widestringmanager.StrCompAnsiStringProc(s1,s2));
  490. end;
  491. function AnsiStrIComp(S1, S2: PAnsiChar): integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  492. begin
  493. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  494. result:=CAPSIZEINT(widestringmanager.StrICompAnsiStringProc(s1,s2));
  495. end;
  496. function AnsiStrLComp(S1, S2: PAnsiChar; MaxLen: SizeUInt): Integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  497. begin
  498. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  499. result:=CAPSIZEINT(widestringmanager.StrLCompAnsiStringProc(s1,s2,maxlen));
  500. end;
  501. function AnsiStrLIComp(S1, S2: PAnsiChar; MaxLen: SizeUint): Integer;{$ifdef SYSUTILSINLINE}inline;{$endif}
  502. begin
  503. // CAPSIZEINT is no-op if Sizeof(Sizeint)<=SizeOF(Integer)
  504. result:=CAPSIZEINT(widestringmanager.StrLICompAnsiStringProc(s1,s2,maxlen));
  505. end;
  506. function AnsiStrLower(Str: PAnsiChar): PAnsiChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
  507. begin
  508. result:=widestringmanager.StrLowerAnsiStringProc(Str);
  509. end;
  510. function AnsiStrUpper(Str: PAnsiChar): PAnsiChar;{$ifdef SYSUTILSINLINE}inline;{$endif}
  511. begin
  512. result:=widestringmanager.StrUpperAnsiStringProc(Str);
  513. end;
  514. {==============================================================================}
  515. { End of Ansi functions }
  516. {==============================================================================}
  517. { Trim returns a copy of S with blanks characters on the left and right stripped off }
  518. Const WhiteSpace = [#0..' '];
  519. function Trim(const S: ansistring): ansistring;
  520. var Ofs, Len: integer;
  521. begin
  522. len := Length(S);
  523. while (Len>0) and (S[Len] in WhiteSpace) do
  524. dec(Len);
  525. Ofs := 1;
  526. while (Ofs<=Len) and (S[Ofs] in WhiteSpace) do
  527. Inc(Ofs);
  528. result := Copy(S, Ofs, 1 + Len - Ofs);
  529. end ;
  530. { TrimLeft returns a copy of S with all blank characters on the left stripped off }
  531. function TrimLeft(const S: ansistring): ansistring;
  532. var i,l:integer;
  533. begin
  534. l := length(s);
  535. i := 1;
  536. while (i<=l) and (s[i] in whitespace) do
  537. inc(i);
  538. Result := copy(s, i, l);
  539. end ;
  540. { TrimRight returns a copy of S with all blank characters on the right stripped off }
  541. function TrimRight(const S: ansistring): ansistring;
  542. var l:integer;
  543. begin
  544. l := length(s);
  545. while (l>0) and (s[l] in whitespace) do
  546. dec(l);
  547. result := copy(s,1,l);
  548. end ;
  549. { QuotedStr returns S quoted left and right and every single quote in S
  550. replaced by two quotes }
  551. function QuotedStr(const S: string): string;
  552. begin
  553. result := AnsiQuotedStr(s, '''');
  554. end ;
  555. { AnsiQuotedStr returns S quoted left and right by Quote,
  556. and every single occurance of Quote replaced by two }
  557. function AnsiQuotedStr(const S: string; Quote: Char): string;
  558. var i, j, count: integer;
  559. begin
  560. result := '' + Quote;
  561. count := length(s);
  562. i := 0;
  563. j := 0;
  564. while i < count do begin
  565. i := i + 1;
  566. if S[i] = Quote then begin
  567. result := result + copy(S, 1 + j, i - j) + Quote;
  568. j := i;
  569. end ;
  570. end ;
  571. if i <> j then
  572. result := result + copy(S, 1 + j, i - j);
  573. result := result + Quote;
  574. end ;
  575. { AnsiExtractQuotedStr returns a copy of Src with quote characters
  576. deleted to the left and right and double occurances
  577. of Quote replaced by a single Quote }
  578. function AnsiExtractQuotedStr(var Src: PWideChar; Quote: WideChar): Widestring;
  579. var
  580. P,Q,R: PWideChar;
  581. begin
  582. result:='';
  583. if Src=Nil then exit;
  584. P := Src;
  585. Q := StrEnd(P);
  586. if P=Q then
  587. exit;
  588. if P^<>quote then
  589. exit(strpas(P));
  590. inc(p);
  591. setlength(result,(Q-P)+1);
  592. R:=@Result[1];
  593. while P <> Q do
  594. begin
  595. R^:=P^;
  596. inc(R);
  597. if (P^ = Quote) then
  598. begin
  599. P := P + 1;
  600. if (p^ <> Quote) then
  601. begin
  602. dec(R);
  603. break;
  604. end;
  605. end;
  606. P := P + 1;
  607. end ;
  608. src:=p;
  609. SetLength(result, (R-PWideChar(@Result[1])));
  610. end ;
  611. function AnsiExtractQuotedStr(var Src: PAnsiChar; Quote: AnsiChar): Ansistring;
  612. var
  613. P,Q,R: PAnsiChar;
  614. begin
  615. result:='';
  616. if Src=Nil then exit;
  617. P := Src;
  618. Q := StrEnd(P);
  619. if P=Q then
  620. exit;
  621. if P^<>quote then
  622. exit(strpas(P));
  623. inc(p);
  624. setlength(result,(Q-P)+1);
  625. R:=@Result[1];
  626. while P <> Q do
  627. begin
  628. R^:=P^;
  629. inc(R);
  630. if (P^ = Quote) then
  631. begin
  632. P := P + 1;
  633. if (p^ <> Quote) then
  634. begin
  635. dec(R);
  636. break;
  637. end;
  638. end;
  639. P := P + 1;
  640. end ;
  641. src:=p;
  642. SetLength(result, (R-PAnsiChar(@Result[1])));
  643. end ;
  644. function AnsiExtractQuotedStr(var Src: PWideChar; Quote: AnsiChar): Widestring;
  645. begin
  646. Result:=AnsiExtractQuotedStr(Src,WideChar(Quote));
  647. end;
  648. { Change CRLF, CR or LF with the default for the current platform }
  649. function AdjustLineBreaks(const S: string): string;
  650. begin
  651. Result:=AdjustLineBreaks(S,DefaultTextLineBreakStyle);
  652. end;
  653. { Change CRLF, CR or LF with the indicated style }
  654. function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle): string;
  655. var
  656. Sp,Se,SLiteralStart,SLiteralEnd,Rp: PChar;
  657. begin
  658. Result:='';
  659. repeat { Does two iterations, first is prepass, second fills the result with data and is distinguished by Assigned(Pointer(Result)). }
  660. Rp:=Pointer(Result);
  661. Sp:=PChar(S); { Readable #0 for empty string. }
  662. Se:=Sp+Length(S);
  663. SLiteralStart:=Sp;
  664. repeat
  665. while (Sp<Se) and not (Sp^ in [#13,#10]) do
  666. Inc(Sp);
  667. SLiteralEnd:=Sp; { Save position before consuming line ending. }
  668. if Sp^=#10 then { These accesses rely on terminating #0. }
  669. begin
  670. Inc(Sp);
  671. if Style=tlbsLF then
  672. continue;
  673. end
  674. else if Sp^=#13 then
  675. if Sp[1]=#10 then
  676. begin
  677. Inc(Sp,2);
  678. if Style=tlbsCRLF then
  679. continue;
  680. end
  681. else
  682. begin
  683. Inc(Sp);
  684. if Style=tlbsCR then
  685. continue;
  686. end;
  687. if Assigned(Pointer(Result)) then
  688. Move(SLiteralStart^,Rp^,Pointer(SLiteralEnd)-Pointer(SLiteralStart)); { Byte difference to avoid signed div 2 on char = widechar. }
  689. Inc(Pointer(Rp),Pointer(SLiteralEnd)-Pointer(SLiteralStart)); { Again, byte difference. }
  690. if SLiteralEnd=Sp then
  691. break;
  692. SLiteralStart:=Sp;
  693. Inc(Rp,1+ord(Style=tlbsCRLF));
  694. if Assigned(Pointer(Result)) then
  695. begin
  696. if Style=tlbsCRLF then
  697. Rp[-2]:=#13;
  698. if Style=tlbsCR then
  699. Rp[-1]:=#13
  700. else
  701. Rp[-1]:=#10;
  702. end;
  703. until false;
  704. if Assigned(Pointer(Result)) then { Second pass finished. }
  705. break;
  706. if SLiteralStart=PChar(S) then { String is unchanged. }
  707. Exit(S);
  708. SetLength(Result,SizeUint(Pointer(Rp)-Pointer(Result)) div SizeOf(Char)); { Prepare second pass. }
  709. until false;
  710. end;
  711. { IsValidIdent returns true if the first character of Ident is in:
  712. 'A' to 'Z', 'a' to 'z' or '_' and the following characters are
  713. on of: 'A' to 'Z', 'a' to 'z', '0'..'9' or '_' }
  714. function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
  715. const
  716. Alpha = ['A'..'Z', 'a'..'z', '_'];
  717. AlphaNum = Alpha + ['0'..'9'];
  718. Dot = '.';
  719. var
  720. First: Boolean;
  721. I, Len: Integer;
  722. begin
  723. Len := Length(Ident);
  724. if Len < 1 then
  725. Exit(False);
  726. First := True;
  727. for I := 1 to Len do
  728. begin
  729. if First then
  730. begin
  731. Result := Ident[I] in Alpha;
  732. First := False;
  733. end
  734. else if AllowDots and (Ident[I] = Dot) then
  735. begin
  736. if StrictDots then
  737. begin
  738. Result := I < Len;
  739. First := True;
  740. end;
  741. end
  742. else
  743. Result := Ident[I] in AlphaNum;
  744. if not Result then
  745. Break;
  746. end;
  747. end;
  748. { IntToStr returns a string representing the value of Value }
  749. function IntToStr(Value: Longint): string;
  750. begin
  751. System.Str(Value, result);
  752. end ;
  753. function IntToStr(Value: int64): string;
  754. begin
  755. System.Str(Value, result);
  756. end ;
  757. function IntToStr(Value: QWord): string;
  758. begin
  759. System.Str(Value, result);
  760. end ;
  761. function UIntToStr(Value: QWord): string;
  762. begin
  763. result:=IntTostr(Value);
  764. end;
  765. function UIntToStr(Value: Cardinal): string;
  766. begin
  767. System.Str(Value, result);
  768. end;
  769. { IntToHex returns a string representing the hexadecimal value of Value }
  770. function IntToHex(Value: Longint; Digits: integer): string;
  771. var i: integer;
  772. begin
  773. If Digits=0 then
  774. Digits:=1;
  775. SetLength(result, digits);
  776. for i := 0 to digits - 1 do
  777. begin
  778. result[digits - i] := HexDigits[value and 15];
  779. value := value shr 4;
  780. end ;
  781. while value <> 0 do begin
  782. result := HexDigits[value and 15] + result;
  783. value := value shr 4;
  784. end;
  785. end ;
  786. function IntToHex(Value: int64; Digits: integer): string;
  787. var i: integer;
  788. begin
  789. If Digits=0 then
  790. Digits:=1;
  791. SetLength(result, digits);
  792. for i := 0 to digits - 1 do
  793. begin
  794. result[digits - i] := HexDigits[value and 15];
  795. value := value shr 4;
  796. end ;
  797. while value <> 0 do begin
  798. result := HexDigits[value and 15] + result;
  799. value := value shr 4;
  800. end;
  801. end ;
  802. function IntToHex(Value: QWord; Digits: integer): string;
  803. begin
  804. result:=IntToHex(Int64(Value),Digits);
  805. end;
  806. function IntToHex(Value: Int8): string;
  807. begin
  808. Result:=IntToHex(LongInt(Value) and $ff, 2*SizeOf(Int8));
  809. end;
  810. function IntToHex(Value: UInt8): string;
  811. begin
  812. Result:=IntToHex(Value, 2*SizeOf(UInt8));
  813. end;
  814. function IntToHex(Value: Int16): string;
  815. begin
  816. Result:=IntToHex(LongInt(Value) and $ffff, 2*SizeOf(Int16));
  817. end;
  818. function IntToHex(Value: UInt16): string;
  819. begin
  820. Result:=IntToHex(Value, 2*SizeOf(UInt16));
  821. end;
  822. function IntToHex(Value: Int32): string;
  823. begin
  824. Result:=IntToHex(Value, 2*SizeOf(Int32));
  825. end;
  826. function IntToHex(Value: UInt32): string;
  827. begin
  828. Result:=IntToHex(LongInt(Value), 2*SizeOf(UInt32));
  829. end;
  830. function IntToHex(Value: Int64): string;
  831. begin
  832. Result:=IntToHex(Value, 2*SizeOf(Int64));
  833. end;
  834. function IntToHex(Value: UInt64): string;
  835. begin
  836. Result:=IntToHex(Value, 2*SizeOf(UInt64));
  837. end;
  838. function TryStrToInt(const s: string; out i : Longint) : boolean;
  839. var
  840. Error : word;
  841. begin
  842. Val(s, i, Error);
  843. TryStrToInt:=(Error=0)
  844. end;
  845. { StrToInt converts the string S to an integer value,
  846. if S does not represent a valid integer value EConvertError is raised }
  847. function StrToInt(const S: string): Longint;
  848. begin
  849. if not(TryStrToInt(s,Result)) then
  850. raise EConvertError.createfmt(SInvalidInteger,[S]);
  851. end;
  852. function StrToInt64(const S: string): int64;
  853. begin
  854. if not(TryStrToInt64(s,Result)) then
  855. raise EConvertError.createfmt(SInvalidInteger,[S]);
  856. end;
  857. function TryStrToInt64(const s: string; Out i : int64) : boolean;
  858. var Error : word;
  859. begin
  860. Val(s, i, Error);
  861. TryStrToInt64:=Error=0
  862. end;
  863. function StrToQWord(const s: string): QWord;
  864. begin
  865. if not(TryStrToQWord(s,Result)) then
  866. raise EConvertError.createfmt(SInvalidInteger,[S]);
  867. end;
  868. function StrToUInt64(const s: string): UInt64;
  869. begin
  870. result:=StrToQWord(s);
  871. end;
  872. function StrToDWord(const s: string): DWord;
  873. begin
  874. if not(TryStrToDWord(s,Result)) then
  875. raise EConvertError.createfmt(SInvalidInteger,[S]);
  876. end;
  877. function TryStrToDWord(const s: string; Out D: DWord): boolean;
  878. var
  879. Error : word;
  880. lq : QWord;
  881. begin
  882. Val(s, lq, Error);
  883. TryStrToDWord:=(Error=0) and (lq<=High(DWord));
  884. if TryStrToDWord then
  885. D:=lq;
  886. end;
  887. function StrToUInt(const s: string): Cardinal;
  888. begin
  889. StrToUInt:=StrToDWord(s);
  890. end;
  891. function TryStrToUInt(const s: string; out C: Cardinal): Boolean;
  892. begin
  893. TryStrToUInt:=TryStrToDWord(s, C);
  894. end;
  895. function TryStrToQWord(const s: string; Out Q: QWord): boolean;
  896. var Error : word;
  897. begin
  898. Val(s, Q, Error);
  899. TryStrToQWord:=Error=0
  900. end;
  901. function TryStrToUInt64(const s: string; Out u: UInt64): boolean;
  902. begin
  903. result:=TryStrToQWord(s,u);
  904. end;
  905. { StrToIntDef converts the string S to an integer value,
  906. Default is returned in case S does not represent a valid integer value }
  907. function StrToIntDef(const S: string; Default: Longint): Longint;
  908. begin
  909. if not(TryStrToInt(s,Result)) then
  910. result := Default;
  911. end;
  912. { StrToDWordDef converts the string S to an DWord value,
  913. Default is returned in case S does not represent a valid DWord value }
  914. function StrToDWordDef(const S: string; Default: DWord): DWord;
  915. begin
  916. if not(TryStrToDWord(s,Result)) then
  917. result := Default;
  918. end;
  919. function StrToUIntDef(const S: string; Default: Cardinal): Cardinal;
  920. begin
  921. Result:=StrToDWordDef(S, Default);
  922. end;
  923. { StrToInt64Def converts the string S to an int64 value,
  924. Default is returned in case S does not represent a valid int64 value }
  925. function StrToInt64Def(const S: string; Default: int64): int64;
  926. begin
  927. if not(TryStrToInt64(s,Result)) then
  928. result := Default;
  929. end;
  930. { StrToQWordDef converts the string S to an QWord value,
  931. Default is returned in case S does not represent a valid QWord value }
  932. function StrToQWordDef(const S: string; Default: QWord): QWord;
  933. begin
  934. if not(TryStrToQWord(s,Result)) then
  935. result := Default;
  936. end;
  937. function StrToUInt64Def(const S: string; Default: UInt64): UInt64;
  938. begin
  939. result:=StrToQWordDef(S,Default);
  940. end;
  941. { LoadStr returns the string resource Ident. }
  942. function LoadStr(Ident: integer): string;
  943. begin
  944. result:='';
  945. end;
  946. { FmtLoadStr returns the string resource Ident and formats it accordingly }
  947. function FmtLoadStr(Ident: integer; const Args: array of const): string;
  948. begin
  949. result:='';
  950. end;
  951. Const
  952. feInvalidFormat = 1;
  953. feMissingArgument = 2;
  954. feInvalidArgIndex = 3;
  955. {$ifdef fmtdebug}
  956. Procedure Log (Const S: String);
  957. begin
  958. Writeln (S);
  959. end;
  960. {$endif}
  961. Procedure DoFormatError (ErrCode : Longint;const fmt:ansistring);
  962. Var
  963. S : String;
  964. begin
  965. //!! must be changed to contain format string...
  966. S:=fmt;
  967. Case ErrCode of
  968. feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
  969. feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
  970. feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
  971. end;
  972. end;
  973. { we've no templates, but with includes we can simulate this :) }
  974. {$macro on}
  975. {$define INFORMAT}
  976. {$define TFormatString:=ansistring}
  977. {$define TFormatChar:=AnsiChar}
  978. Function Format (Const Fmt : AnsiString; const Args : Array of const; const FormatSettings: TFormatSettings) : AnsiString;
  979. {$i sysformt.inc}
  980. {$undef TFormatString}
  981. {$undef TFormatChar}
  982. {$undef INFORMAT}
  983. {$macro off}
  984. Function Format (Const Fmt : AnsiString; const Args : Array of const) : AnsiString;
  985. begin
  986. Result:=Format(Fmt,Args,DefaultFormatSettings);
  987. end;
  988. function SafeFormat (const Fmt: AnsiString; Args: array of const): UTF8String;
  989. begin
  990. Result:=SafeFormat(Fmt,Args,DefaultFormatSettings);
  991. end;
  992. function SafeFormat (const Fmt: AnsiString; Args: array of const; const FormatSettings: TFormatSettings): UTF8String;
  993. begin
  994. try
  995. Result:=Format(Fmt,Args,FormatSettings);
  996. except
  997. On E : Exception do
  998. Result:='Error "'+E.ClassName+'" during format('''+Fmt+''',['+ArrayOfConstToStr(Args,',','{','}')+']) : '+E.Message;
  999. end;
  1000. end;
  1001. Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal; Const Args : Array of const; Const FormatSettings: TFormatSettings) : Cardinal;
  1002. Var S,F : AnsiString;
  1003. begin
  1004. Setlength(F,fmtlen);
  1005. if fmtlen > 0 then
  1006. Move(fmt,F[1],fmtlen);
  1007. S:=Format (F,Args,FormatSettings);
  1008. If Cardinal(Length(S))<Buflen then
  1009. Result:=Length(S)
  1010. else
  1011. Result:=Buflen;
  1012. Move(S[1],Buffer,Result);
  1013. end;
  1014. Function FormatBuf (Var Buffer; BufLen : Cardinal;
  1015. Const Fmt; fmtLen : Cardinal;
  1016. Const Args : Array of const) : Cardinal;
  1017. begin
  1018. Result:=FormatBuf(Buffer,BufLen,Fmt,FmtLen,Args,DefaultFormatSettings);
  1019. end;
  1020. Procedure FmtStr(Var Res: string; const Fmt : string; Const args: Array of const; Const FormatSettings: TFormatSettings);
  1021. begin
  1022. Res:=Format(fmt,Args,FormatSettings);
  1023. end;
  1024. Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
  1025. begin
  1026. FmtStr(Res,Fmt,Args,DefaultFormatSettings);
  1027. end;
  1028. Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : PChar;
  1029. begin
  1030. Result:=StrFmt(Buffer,Fmt,Args,DefaultFormatSettings);
  1031. end;
  1032. Function StrFmt(Buffer,Fmt : PChar; Const Args: Array of const; Const FormatSettings: TFormatSettings): PChar;
  1033. Var
  1034. Len : Integer;
  1035. begin
  1036. {$if SIZEOF(Char)=2}
  1037. Len:=UnicodeFormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings);
  1038. {$ELSE}
  1039. Len:=FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings);
  1040. {$ENDIF}
  1041. Buffer[Len]:=#0;
  1042. Result:=Buffer;
  1043. end;
  1044. Function StrLFmt(Buffer : PChar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : PChar;
  1045. begin
  1046. Result:=StrLFmt(Buffer,MaxLen,Fmt,Args,DefaultFormatSettings);
  1047. end;
  1048. Function StrLFmt(Buffer : PChar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const; Const FormatSettings: TFormatSettings) : PChar;
  1049. var
  1050. Len : integer;
  1051. begin
  1052. {$if SIZEOF(Char)=2}
  1053. Len:=UnicodeFormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings);
  1054. {$ELSE}
  1055. Len:=FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings);
  1056. {$ENDIF}
  1057. Buffer[Len]:=#0;
  1058. Result:=Buffer;
  1059. end;
  1060. {$ifndef FPUNONE}
  1061. Function InternalTextToFloat(S: String; Out Value; ValueType: TFloatValue;
  1062. Const FormatSettings: TFormatSettings): Boolean;
  1063. Var
  1064. E,P : Integer;
  1065. Begin
  1066. if S = '' then
  1067. exit(false);
  1068. //ThousandSeparator not allowed as by Delphi specs
  1069. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1070. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1071. begin
  1072. Result := False;
  1073. Exit;
  1074. end;
  1075. if (FormatSettings.DecimalSeparator <> '.') then
  1076. begin
  1077. if (Pos('.', S) <>0) then
  1078. begin
  1079. Result := False;
  1080. Exit;
  1081. end;
  1082. P:=Pos(FormatSettings.DecimalSeparator,S);
  1083. If (P<>0) Then
  1084. S[P] := '.';
  1085. end;
  1086. s:=Trim(s);
  1087. try
  1088. case ValueType of
  1089. fvCurrency:
  1090. Val(S,Currency(Value),E);
  1091. fvExtended:
  1092. Val(S,Extended(Value),E);
  1093. fvDouble:
  1094. Val(S,Double(Value),E);
  1095. fvSingle:
  1096. Val(S,Single(Value),E);
  1097. fvComp:
  1098. Val(S,Comp(Value),E);
  1099. fvReal:
  1100. Val(S,Real(Value),E);
  1101. end;
  1102. { on x87, a floating point exception may be pending in case of an invalid
  1103. input value -> trigger it now }
  1104. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1105. asm
  1106. fwait
  1107. end;
  1108. {$endif}
  1109. except
  1110. E:=1;
  1111. end;
  1112. Result:=(E=0);
  1113. End;
  1114. Function InternalTextToFloat(S: String; Out Value: Extended;
  1115. Const FormatSettings: TFormatSettings): Boolean;
  1116. Var
  1117. E,P : Integer;
  1118. Begin
  1119. if S = '' then
  1120. exit(false);
  1121. //ThousandSeparator not allowed as by Delphi specs
  1122. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1123. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1124. begin
  1125. Result := False;
  1126. Exit;
  1127. end;
  1128. if (FormatSettings.DecimalSeparator <> '.') then
  1129. begin
  1130. if (Pos('.', S) <>0) then
  1131. begin
  1132. Result := False;
  1133. Exit;
  1134. end;
  1135. P:=Pos(FormatSettings.DecimalSeparator,S);
  1136. If (P<>0) Then
  1137. S[P] := '.';
  1138. end;
  1139. try
  1140. Val(trim(S),Value,E);
  1141. { on x87, a floating point exception may be pending in case of an invalid
  1142. input value -> trigger it now }
  1143. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1144. asm
  1145. fwait
  1146. end;
  1147. {$endif}
  1148. except
  1149. E:=1;
  1150. end;
  1151. Result:=(E=0);
  1152. End;
  1153. {$IF SIZEOF(CHAR)=2}
  1154. Function TextToFloat(Buffer: PAnsiChar; Out Value; ValueType: TFloatValue): Boolean;
  1155. begin
  1156. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  1157. end;
  1158. Function TextToFloat(Buffer: PAnsiChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  1159. Var
  1160. E,P : Integer;
  1161. S : AnsiString;
  1162. Begin
  1163. S:=StrPas(Buffer);
  1164. //ThousandSeparator not allowed as by Delphi specs
  1165. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1166. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1167. begin
  1168. Result := False;
  1169. Exit;
  1170. end;
  1171. if (FormatSettings.DecimalSeparator <> '.') and
  1172. (Pos('.', S) <>0) then
  1173. begin
  1174. Result := False;
  1175. Exit;
  1176. end;
  1177. P:=Pos(FormatSettings.DecimalSeparator,S);
  1178. If (P<>0) Then
  1179. S[P] := '.';
  1180. s:=Trim(s);
  1181. try
  1182. case ValueType of
  1183. fvCurrency:
  1184. Val(S,Currency(Value),E);
  1185. fvExtended:
  1186. Val(S,Extended(Value),E);
  1187. fvDouble:
  1188. Val(S,Double(Value),E);
  1189. fvSingle:
  1190. Val(S,Single(Value),E);
  1191. fvComp:
  1192. Val(S,Comp(Value),E);
  1193. fvReal:
  1194. Val(S,Real(Value),E);
  1195. end;
  1196. { on x87, a floating point exception may be pending in case of an invalid
  1197. input value -> trigger it now }
  1198. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1199. asm
  1200. fwait
  1201. end;
  1202. {$endif}
  1203. except
  1204. E:=1;
  1205. end;
  1206. Result:=(E=0);
  1207. End;
  1208. {$ENDIF}
  1209. Function StrToFloat(Const S: String): Extended;
  1210. begin
  1211. Result:=StrToFloat(S,DefaultFormatSettings);
  1212. end;
  1213. Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
  1214. Begin
  1215. If Not InternalTextToFloat(S,Result,FormatSettings) then
  1216. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1217. End;
  1218. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  1219. begin
  1220. Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
  1221. end;
  1222. Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
  1223. begin
  1224. if not InternalTextToFloat(S,Result,fvExtended,FormatSettings) then
  1225. Result:=Default;
  1226. end;
  1227. Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  1228. begin
  1229. Result := InternalTextToFloat(StrPas(Buffer), Value, FormatSettings);
  1230. End;
  1231. Function TextToFloat(Buffer: PChar; Out Value: Extended): Boolean;
  1232. begin
  1233. Result:=InternalTextToFloat(StrPas(Buffer),Value,DefaultFormatSettings);
  1234. end;
  1235. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue): Boolean;
  1236. begin
  1237. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  1238. end;
  1239. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  1240. Begin
  1241. Result := InternalTextToFloat(StrPas(Buffer), Value, ValueType, FormatSettings);
  1242. End;
  1243. Function TryStrToFloat(Const S : String; Out Value: Single): Boolean;
  1244. begin
  1245. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1246. end;
  1247. Function TryStrToFloat(Const S : String; Out Value: Single; Const FormatSettings: TFormatSettings): Boolean;
  1248. Begin
  1249. Result := InternalTextToFloat(S, Value, fvSingle,FormatSettings);
  1250. End;
  1251. Function TryStrToFloat(Const S : String; Out Value: Double): Boolean;
  1252. begin
  1253. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1254. end;
  1255. Function TryStrToFloat(Const S : String; Out Value: Double; Const FormatSettings: TFormatSettings): Boolean;
  1256. Begin
  1257. Result := InternalTextToFloat(S, Value, fvDouble,FormatSettings);
  1258. End;
  1259. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1260. Function TryStrToFloat(Const S : String; Out Value: Extended): Boolean;
  1261. begin
  1262. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1263. end;
  1264. Function TryStrToFloat(Const S : String; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  1265. Begin
  1266. Result := InternalTextToFloat(S, Value,FormatSettings);
  1267. End;
  1268. {$endif FPC_HAS_TYPE_EXTENDED}
  1269. const
  1270. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1271. maxdigits = 17;
  1272. {$else}
  1273. maxdigits = 15;
  1274. {$endif}
  1275. Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
  1276. Var
  1277. P, PE, Q, Exponent: Integer;
  1278. Negative: Boolean;
  1279. DS: Char;
  1280. function RemoveLeadingNegativeSign(var AValue: String): Boolean;
  1281. // removes negative sign in case when result is zero eg. -0.00
  1282. var
  1283. i: PtrInt;
  1284. TS: Char;
  1285. StartPos: PtrInt;
  1286. begin
  1287. Result := False;
  1288. if Format = ffCurrency then
  1289. StartPos := 1
  1290. else
  1291. StartPos := 2;
  1292. TS := FormatSettings.ThousandSeparator;
  1293. for i := StartPos to length(AValue) do
  1294. begin
  1295. Result := (AValue[i] in ['0', DS, 'E', '+', TS]);
  1296. if not Result then
  1297. break;
  1298. end;
  1299. if (Result) and (Format <> ffCurrency) then
  1300. Delete(AValue, 1, 1);
  1301. end;
  1302. Begin
  1303. DS:=FormatSettings.DecimalSeparator;
  1304. Case format Of
  1305. ffGeneral:
  1306. Begin
  1307. case ValueType of
  1308. fvCurrency:
  1309. If (Precision = -1) Or (Precision > 19) Then Precision := 19;
  1310. else
  1311. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1312. end;
  1313. { First convert to scientific format, with correct precision }
  1314. case ValueType of
  1315. fvDouble:
  1316. Str(Double(Extended(Aligned(Value))):precision+7, Result);
  1317. fvSingle:
  1318. Str(Single(Extended(Aligned(Value))):precision+6, Result);
  1319. fvCurrency:
  1320. Str(Currency(Aligned(Value)):precision+6, Result);
  1321. else
  1322. Str(Extended(Aligned(Value)):precision+8, Result);
  1323. end;
  1324. { Delete leading spaces }
  1325. while Result[1] = ' ' do
  1326. System.Delete(Result, 1, 1);
  1327. P := Pos('.', Result);
  1328. if P<>0 then
  1329. Result[P] := DS
  1330. else
  1331. Exit; { NAN or other special case }
  1332. { Consider removing exponent }
  1333. PE:=Pos('E',Result);
  1334. if PE > 0 then begin
  1335. { Read exponent }
  1336. Q := PE+2;
  1337. Exponent := 0;
  1338. while (Q <= Length(Result)) do begin
  1339. Exponent := Exponent*10 + Ord(Result[Q])-Ord('0');
  1340. Inc(Q);
  1341. end;
  1342. if Result[PE+1] = '-' then
  1343. Exponent := -Exponent;
  1344. if (P+Exponent < PE) and (Exponent > -6) then begin
  1345. { OK to remove exponent }
  1346. SetLength(Result,PE-1); { Trim exponent }
  1347. if Exponent >= 0 then begin
  1348. { Shift point to right }
  1349. for Q := 0 to Exponent-1 do begin
  1350. Result[P] := Result[P+1];
  1351. Inc(P);
  1352. end;
  1353. Result[P] := DS;
  1354. P := 1;
  1355. if Result[P] = '-' then
  1356. Inc(P);
  1357. while (Result[P] = '0') and (P < Length(Result)) and (Result[P+1] <> DS) do
  1358. { Trim leading zeros; conversion above should not give any, but occasionally does
  1359. because of rounding }
  1360. System.Delete(Result,P,1);
  1361. end else begin
  1362. { Add zeros at start }
  1363. Insert(Copy('00000',1,-Exponent),Result,P-1);
  1364. Result[P-Exponent] := Result[P-Exponent-1]; { Copy leading digit }
  1365. Result[P] := DS;
  1366. if Exponent <> -1 then
  1367. Result[P-Exponent-1] := '0';
  1368. end;
  1369. { Remove trailing zeros }
  1370. Q := Length(Result);
  1371. while (Q > 0) and (Result[Q] = '0') do
  1372. Dec(Q);
  1373. if Result[Q] = DS then
  1374. Dec(Q); { Remove trailing decimal point }
  1375. if (Q = 0) or ((Q=1) and (Result[1] = '-')) then
  1376. Result := '0'
  1377. else
  1378. SetLength(Result,Q);
  1379. end else begin
  1380. { Need exponent, but remove superfluous characters }
  1381. { Delete trailing zeros }
  1382. while Result[PE-1] = '0' do begin
  1383. System.Delete(Result,PE-1,1);
  1384. Dec(PE);
  1385. end;
  1386. { If number ends in decimal point, remove it }
  1387. if Result[PE-1] = DS then begin
  1388. System.Delete(Result,PE-1,1);
  1389. Dec(PE);
  1390. end;
  1391. { delete superfluous + in exponent }
  1392. if Result[PE+1]='+' then
  1393. System.Delete(Result,PE+1,1)
  1394. else
  1395. Inc(PE);
  1396. while Result[PE+1] = '0' do
  1397. { Delete leading zeros in exponent }
  1398. System.Delete(Result,PE+1,1)
  1399. end;
  1400. end;
  1401. End;
  1402. ffExponent:
  1403. Begin
  1404. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1405. case ValueType of
  1406. fvDouble:
  1407. Str(Double(Extended(Aligned(Value))):Precision+7, Result);
  1408. fvSingle:
  1409. Str(Single(Extended(Aligned(Value))):Precision+6, Result);
  1410. fvCurrency:
  1411. Str(Currency(Aligned(Value)):Precision+6, Result);
  1412. else
  1413. Str(Extended(Aligned(Value)):Precision+8, Result);
  1414. end;
  1415. { Delete leading spaces }
  1416. while Result[1] = ' ' do
  1417. System.Delete(Result, 1, 1);
  1418. if (Result[1]='-') and
  1419. { not Nan etc.? }
  1420. (Result[3]='.') then
  1421. Result[3] := DS
  1422. else if Result[2]='.' then
  1423. Result[2] := DS;
  1424. P:=Pos('E',Result);
  1425. if P <> 0 then
  1426. begin
  1427. Inc(P, 2);
  1428. if Digits > 4 then
  1429. Digits:=4;
  1430. Digits:=Length(Result) - P - Digits + 1;
  1431. if Digits < 0 then
  1432. insert(copy('0000',1,-Digits),Result,P)
  1433. else
  1434. while (Digits > 0) and (Result[P] = '0') do
  1435. begin
  1436. System.Delete(Result, P, 1);
  1437. if P > Length(Result) then
  1438. begin
  1439. System.Delete(Result, P - 2, 2);
  1440. break;
  1441. end;
  1442. Dec(Digits);
  1443. end;
  1444. end;
  1445. End;
  1446. ffFixed:
  1447. Begin
  1448. If Digits = -1 Then Digits := 2
  1449. Else If Digits > 18 Then Digits := 18;
  1450. case ValueType of
  1451. fvDouble:
  1452. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1453. fvSingle:
  1454. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1455. fvCurrency:
  1456. Str(Currency(Aligned(Value)):0:Digits, Result);
  1457. else
  1458. Str(Extended(Aligned(Value)):0:Digits, Result);
  1459. end;
  1460. If Result[1] = ' ' Then
  1461. System.Delete(Result, 1, 1);
  1462. P := Pos('.', Result);
  1463. If P <> 0 Then Result[P] := DS;
  1464. End;
  1465. ffNumber:
  1466. Begin
  1467. If Digits = -1 Then Digits := 2
  1468. Else If Digits > maxdigits Then Digits := maxdigits;
  1469. case ValueType of
  1470. fvDouble:
  1471. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1472. fvSingle:
  1473. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1474. fvCurrency:
  1475. Str(Currency(Aligned(Value)):0:Digits, Result);
  1476. else
  1477. Str(Extended(Aligned(Value)):0:Digits, Result);
  1478. end;
  1479. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1480. P := Pos('.', Result);
  1481. If P <> 0 Then
  1482. Result[P] := DS
  1483. else
  1484. P := Length(Result)+1;
  1485. Dec(P, 3);
  1486. While (P > 1) Do
  1487. Begin
  1488. If (Result[P - 1] <> '-') And (FormatSettings.ThousandSeparator <> #0) Then
  1489. Insert(FormatSettings.ThousandSeparator, Result, P);
  1490. Dec(P, 3);
  1491. End;
  1492. End;
  1493. ffCurrency:
  1494. Begin
  1495. If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
  1496. Else If Digits > 18 Then Digits := 18;
  1497. case ValueType of
  1498. fvDouble:
  1499. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1500. fvSingle:
  1501. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1502. fvCurrency:
  1503. Str(Currency(Aligned(Value)):0:Digits, Result);
  1504. else
  1505. Str(Extended(Aligned(Value)):0:Digits, Result);
  1506. end;
  1507. Negative:=Result[1] = '-';
  1508. if Negative then
  1509. System.Delete(Result, 1, 1);
  1510. P := Pos('.', Result);
  1511. If P <> 0 Then Result[P] := DS else P := Length(Result)+1;
  1512. Dec(P, 3);
  1513. While (P > 1) Do
  1514. Begin
  1515. If FormatSettings.ThousandSeparator<>#0 Then
  1516. Insert(FormatSettings.ThousandSeparator, Result, P);
  1517. Dec(P, 3);
  1518. End;
  1519. if (length(Result) > 1) and Negative then
  1520. Negative := not RemoveLeadingNegativeSign(Result);
  1521. If Not Negative Then
  1522. Begin
  1523. Case FormatSettings.CurrencyFormat Of
  1524. 0: Result := FormatSettings.CurrencyString + Result;
  1525. 1: Result := Result + FormatSettings.CurrencyString;
  1526. 2: Result := FormatSettings.CurrencyString + ' ' + Result;
  1527. 3: Result := Result + ' ' + FormatSettings.CurrencyString;
  1528. End
  1529. End
  1530. Else
  1531. Begin
  1532. Case FormatSettings.NegCurrFormat Of
  1533. 0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
  1534. 1: Result := '-' + FormatSettings.CurrencyString + Result;
  1535. 2: Result := FormatSettings.CurrencyString + '-' + Result;
  1536. 3: Result := FormatSettings.CurrencyString + Result + '-';
  1537. 4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
  1538. 5: Result := '-' + Result + FormatSettings.CurrencyString;
  1539. 6: Result := Result + '-' + FormatSettings.CurrencyString;
  1540. 7: Result := Result + FormatSettings.CurrencyString + '-';
  1541. 8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
  1542. 9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
  1543. 10: Result := Result + ' ' + FormatSettings.CurrencyString + '-';
  1544. 11: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
  1545. 12: Result := FormatSettings.CurrencyString + ' ' + '-' + Result;
  1546. 13: Result := Result + '-' + ' ' + FormatSettings.CurrencyString;
  1547. 14: Result := '(' + FormatSettings.CurrencyString + ' ' + Result + ')';
  1548. 15: Result := '(' + Result + ' ' + FormatSettings.CurrencyString + ')';
  1549. End;
  1550. End;
  1551. End;
  1552. End;
  1553. if not (format in [ffCurrency]) and (length(Result) > 1) and (Result[1] = '-') then
  1554. RemoveLeadingNegativeSign(Result);
  1555. End;
  1556. {$macro off}
  1557. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1558. Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
  1559. Begin
  1560. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
  1561. End;
  1562. Function FloatToStr(Value: Extended): String;
  1563. begin
  1564. Result:=FloatToStr(Value,DefaultFormatSettings);
  1565. end;
  1566. {$endif FPC_HAS_TYPE_EXTENDED}
  1567. Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
  1568. Begin
  1569. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
  1570. End;
  1571. Function FloatToStr(Value: Currency): String;
  1572. begin
  1573. Result:=FloatToStr(Value,DefaultFormatSettings);
  1574. end;
  1575. Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
  1576. var
  1577. e: Extended;
  1578. Begin
  1579. e := Value;
  1580. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
  1581. End;
  1582. Function FloatToStr(Value: Double): String;
  1583. begin
  1584. Result:=FloatToStr(Value,DefaultFormatSettings);
  1585. end;
  1586. Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
  1587. var
  1588. e: Extended;
  1589. Begin
  1590. e := Value;
  1591. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
  1592. End;
  1593. Function FloatToStr(Value: Single): String;
  1594. begin
  1595. Result:=FloatToStr(Value,DefaultFormatSettings);
  1596. end;
  1597. Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
  1598. var
  1599. e: Extended;
  1600. Begin
  1601. e := Value;
  1602. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1603. End;
  1604. Function FloatToStr(Value: Comp): String;
  1605. begin
  1606. Result:=FloatToStr(Value,DefaultFormatSettings);
  1607. end;
  1608. {$ifndef FPC_COMP_IS_INT64}
  1609. Function FloatToStr(Value: Int64): String;
  1610. begin
  1611. Result:=FloatToStr(Value,DefaultFormatSettings);
  1612. end;
  1613. Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
  1614. var
  1615. e: Extended;
  1616. Begin
  1617. e := Comp(Value);
  1618. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1619. End;
  1620. {$endif FPC_COMP_IS_INT64}
  1621. Function FloatToText(Buffer: PAnsiChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1622. Var
  1623. Tmp: String[40];
  1624. Begin
  1625. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1626. Result := Length(Tmp);
  1627. Move(Tmp[1], Buffer[0], Result);
  1628. End;
  1629. Function FloatToText(Buffer: PWideChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1630. Var
  1631. Tmp: UnicodeString;
  1632. Begin
  1633. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1634. Result := Length(Tmp);
  1635. Move(Tmp[1], Buffer[0], Result*SizeOf(WideChar));
  1636. End;
  1637. Function FloatToText(Buffer: PAnsiChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1638. begin
  1639. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1640. end;
  1641. Function FloatToText(Buffer: PWideChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1642. begin
  1643. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1644. end;
  1645. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1646. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1647. begin
  1648. Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
  1649. end;
  1650. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1651. begin
  1652. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1653. end;
  1654. {$endif}
  1655. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1656. begin
  1657. Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
  1658. end;
  1659. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
  1660. begin
  1661. Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
  1662. end;
  1663. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1664. var
  1665. e: Extended;
  1666. begin
  1667. e := Value;
  1668. result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
  1669. end;
  1670. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
  1671. begin
  1672. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1673. end;
  1674. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1675. var
  1676. e: Extended;
  1677. begin
  1678. e:=Value;
  1679. result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
  1680. end;
  1681. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
  1682. begin
  1683. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1684. end;
  1685. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1686. var
  1687. e: Extended;
  1688. begin
  1689. e := Value;
  1690. Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1691. end;
  1692. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
  1693. begin
  1694. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1695. end;
  1696. {$ifndef FPC_COMP_IS_INT64}
  1697. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1698. var
  1699. e: Extended;
  1700. begin
  1701. e := Comp(Value);
  1702. result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1703. end;
  1704. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
  1705. begin
  1706. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1707. end;
  1708. {$endif FPC_COMP_IS_INT64}
  1709. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
  1710. begin
  1711. result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
  1712. end;
  1713. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
  1714. begin
  1715. Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
  1716. end;
  1717. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1718. begin
  1719. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1720. Raise EConvertError.CreateFmt (SInvalidDateTimeFloat,[Value]);
  1721. Result:=Value;
  1722. end;
  1723. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1724. begin
  1725. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1726. if Result then
  1727. AResult := Value;
  1728. end;
  1729. function FloatToCurr(const Value: Extended): Currency;
  1730. begin
  1731. if not TryFloatToCurr(Value, Result) then
  1732. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1733. end;
  1734. Function CurrToStr(Value: Currency): string;
  1735. begin
  1736. Result:=FloatToStrF(Value,ffGeneral,-1,0);
  1737. end;
  1738. Function CurrToStr(Value: Currency; Const FormatSettings: TFormatSettings): string;
  1739. begin
  1740. Result:=FloatToStrF(Value,ffGeneral,-1,0,FormatSettings);
  1741. end;
  1742. function StrToCurr(const S: string): Currency;
  1743. begin
  1744. if not InternalTextToFloat(S, Result, fvCurrency, DefaultFormatSettings) then
  1745. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1746. end;
  1747. function StrToCurr(const S: string; Const FormatSettings: TFormatSettings): Currency;
  1748. begin
  1749. if not InternalTextToFloat(S, Result, fvCurrency,FormatSettings) then
  1750. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1751. end;
  1752. Function TryStrToCurr(Const S : String; Out Value: Currency): Boolean;
  1753. Begin
  1754. Result := InternalTextToFloat(S, Value, fvCurrency, DefaultFormatSettings);
  1755. End;
  1756. function TryStrToCurr(const S: string;Out Value : Currency; Const FormatSettings: TFormatSettings): Boolean;
  1757. Begin
  1758. Result := InternalTextToFloat(S, Value, fvCurrency,FormatSettings);
  1759. End;
  1760. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1761. begin
  1762. if not InternalTextToFloat(S, Result, fvCurrency, DefaultFormatSettings) then
  1763. Result:=Default;
  1764. end;
  1765. function StrToCurrDef(const S: string; Default : Currency; Const FormatSettings: TFormatSettings): Currency;
  1766. begin
  1767. if not InternalTextToFloat(S, Result, fvCurrency,FormatSettings) then
  1768. Result:=Default;
  1769. end;
  1770. {$endif FPUNONE}
  1771. function AnsiDequotedStr(const S: string; AQuote: Char): string;
  1772. var p : PChar;
  1773. begin
  1774. p:=PChar(pointer(s)); // work around CONST. Ansiextract is safe for nil
  1775. result:=AnsiExtractquotedStr(p,AQuote);
  1776. end;
  1777. function StrToBool(const S: string): Boolean;
  1778. begin
  1779. if not(TryStrToBool(S,Result,DefaultFormatSettings)) then
  1780. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1781. end;
  1782. function StrToBool(const S: string; const FormatSettings: TFormatSettings): Boolean;
  1783. begin
  1784. if not(TryStrToBool(S,Result,FormatSettings)) then
  1785. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1786. end;
  1787. procedure CheckBoolStrs;
  1788. begin
  1789. If Length(TrueBoolStrs)=0 then
  1790. begin
  1791. SetLength(TrueBoolStrs,1);
  1792. TrueBoolStrs[0]:='True';
  1793. end;
  1794. If Length(FalseBoolStrs)=0 then
  1795. begin
  1796. SetLength(FalseBoolStrs,1);
  1797. FalseBoolStrs[0]:='False';
  1798. end;
  1799. end;
  1800. function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
  1801. begin
  1802. if UseBoolStrs Then
  1803. begin
  1804. CheckBoolStrs;
  1805. if B then
  1806. Result:=TrueBoolStrs[0]
  1807. else
  1808. Result:=FalseBoolStrs[0];
  1809. end
  1810. else
  1811. If B then
  1812. Result:='-1'
  1813. else
  1814. Result:='0';
  1815. end;
  1816. // from textmode IDE util funcs.
  1817. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  1818. begin
  1819. if B then Result:=TrueS else BoolToStr:=FalseS;
  1820. end;
  1821. function StrToBoolDef(const S: string; Default: Boolean): Boolean;
  1822. begin
  1823. if not(TryStrToBool(S,Result)) then
  1824. Result:=Default;
  1825. end;
  1826. function StrToBoolDef(const S: string; Default: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1827. begin
  1828. if not(TryStrToBool(S,Result,FormatSettings)) then
  1829. Result:=Default;
  1830. end;
  1831. function TryStrToBool(const S: string; out Value: Boolean): Boolean;
  1832. begin
  1833. Result:=TryStrToBool(S,Value,DefaultFormatSettings);
  1834. end;
  1835. function TryStrToBool(const S: string; out Value: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1836. Var
  1837. Temp : String;
  1838. I : Longint;
  1839. {$ifdef FPUNONE}
  1840. D : Longint;
  1841. {$else}
  1842. D : Double;
  1843. {$endif}
  1844. Code: word;
  1845. begin
  1846. Temp:=upcase(S);
  1847. Val(temp,D,code);
  1848. Result:=true;
  1849. If (Code=0) or TryStrToFloat(S,D,FormatSettings) then
  1850. {$ifdef FPUNONE}
  1851. Value:=(D<>0)
  1852. {$else}
  1853. Value:=(D<>0.0)
  1854. {$endif}
  1855. else
  1856. begin
  1857. CheckBoolStrs;
  1858. for I:=low(TrueBoolStrs) to High(TrueBoolStrs) do
  1859. if Temp=upcase(TrueBoolStrs[I]) then
  1860. begin
  1861. Value:=true;
  1862. exit;
  1863. end;
  1864. for I:=low(FalseBoolStrs) to High(FalseBoolStrs) do
  1865. if Temp=upcase(FalseBoolStrs[I]) then
  1866. begin
  1867. Value:=false;
  1868. exit;
  1869. end;
  1870. Result:=false;
  1871. end;
  1872. end;
  1873. {$ifndef FPUNONE}
  1874. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1875. begin
  1876. Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
  1877. end;
  1878. {$MACRO ON}
  1879. {$define FPChar:=PAnsiChar}
  1880. {$define FChar:=AnsiChar}
  1881. {$define FString:=AnsiString}
  1882. {$I fmtflt.inc}
  1883. {$undef FPChar}
  1884. {$undef FChar}
  1885. {$undef FString}
  1886. {$MACRO ON}
  1887. {$define FPChar:=PWideChar}
  1888. {$define FChar:=WideChar}
  1889. {$define FString:=UnicodeString}
  1890. {$I fmtflt.inc}
  1891. {$define FPChar:=PAnsiChar}
  1892. {$define FChar:=AnsiChar}
  1893. {$define FString:=AnsiString}
  1894. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar; FormatSettings : TFormatSettings): Integer;
  1895. begin
  1896. Result:=IntFloatToTextFmt(Buffer,Value,fvExtended,Format,FormatSettings);
  1897. end;
  1898. Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
  1899. var
  1900. Buffer: String[254]; //Though str func returns only 25 chars, this might change in the future
  1901. InfNan: string[3];
  1902. Error, N, L, Start, C: Integer;
  1903. GotNonZeroBeforeDot, BeforeDot : boolean;
  1904. begin
  1905. case ValueType of
  1906. fvExtended:
  1907. Str(Extended(Value):25, Buffer);
  1908. fvDouble,
  1909. fvReal:
  1910. Str(Double(Value):23, Buffer);
  1911. fvSingle:
  1912. Str(Single(Value):16, Buffer);
  1913. fvCurrency:
  1914. Str(Currency(Value):25, Buffer);
  1915. fvComp:
  1916. Str(Currency(Value):23, Buffer);
  1917. end;
  1918. N := 1;
  1919. L := Byte(Buffer[0]);
  1920. while Buffer[N]=' ' do
  1921. Inc(N);
  1922. Result.Negative := (Buffer[N] = '-');
  1923. if Result.Negative then
  1924. Inc(N)
  1925. else if (Buffer[N] = '+') then
  1926. inc(N);
  1927. { special cases for Inf and Nan }
  1928. if (L>=N+2) then
  1929. begin
  1930. InfNan:=copy(Buffer,N,3);
  1931. if (InfNan='Inf') then
  1932. begin
  1933. Result.Digits[0]:=#0;
  1934. Result.Exponent:=32767;
  1935. exit
  1936. end;
  1937. if (InfNan='Nan') then
  1938. begin
  1939. Result.Digits[0]:=#0;
  1940. Result.Exponent:=-32768;
  1941. exit
  1942. end;
  1943. end;
  1944. Start := N; //Start of digits
  1945. Result.Exponent := 0; BeforeDot := true;
  1946. GotNonZeroBeforeDot := false;
  1947. while (L>=N) and (Buffer[N]<>'E') do
  1948. begin
  1949. if Buffer[N]='.' then
  1950. BeforeDot := false
  1951. else
  1952. begin
  1953. if BeforeDot then
  1954. begin // Currently this is always 1 AnsiChar
  1955. Inc(Result.Exponent);
  1956. Result.Digits[N-Start] := Buffer[N];
  1957. if Buffer[N] <> '0' then
  1958. GotNonZeroBeforeDot := true;
  1959. end
  1960. else
  1961. Result.Digits[N-Start-1] := Buffer[N]
  1962. end;
  1963. Inc(N);
  1964. end;
  1965. Inc(N); // Pass through 'E'
  1966. if N<=L then
  1967. begin
  1968. Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
  1969. Inc(Result.Exponent, C);
  1970. end;
  1971. // Calculate number of digits we have from str
  1972. if BeforeDot then
  1973. N := N - Start - 1
  1974. else
  1975. N := N - Start - 2;
  1976. L := SizeOf(Result.Digits);
  1977. if N<L then
  1978. FillChar(Result.Digits[N], L-N, '0'); //Zero remaining space
  1979. if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
  1980. N := Decimals + Result.Exponent
  1981. Else
  1982. N := Precision;
  1983. if N >= L Then
  1984. N := L-1;
  1985. if N = 0 Then
  1986. begin
  1987. if Result.Digits[0] >= '5' Then
  1988. begin
  1989. Result.Digits[0] := '1';
  1990. Result.Digits[1] := #0;
  1991. Inc(Result.Exponent);
  1992. end
  1993. Else
  1994. Result.Digits[0] := #0;
  1995. end //N=0
  1996. Else if N > 0 Then
  1997. begin
  1998. if Result.Digits[N] >= '5' Then
  1999. begin
  2000. Repeat
  2001. Result.Digits[N] := #0;
  2002. Dec(N);
  2003. Inc(Result.Digits[N]);
  2004. Until (N = 0) Or (Result.Digits[N] < ':');
  2005. If Result.Digits[0] = ':' Then
  2006. begin
  2007. Result.Digits[0] := '1';
  2008. Inc(Result.Exponent);
  2009. end;
  2010. end
  2011. Else
  2012. begin
  2013. Result.Digits[N] := '0';
  2014. While (N > -1) And (Result.Digits[N] = '0') Do
  2015. begin
  2016. Result.Digits[N] := #0;
  2017. Dec(N);
  2018. end;
  2019. end;
  2020. end //N>0
  2021. Else
  2022. Result.Digits[0] := #0;
  2023. if (Result.Digits[0] = #0) and
  2024. not GotNonZeroBeforeDot then
  2025. begin
  2026. Result.Exponent := 0;
  2027. Result.Negative := False;
  2028. end;
  2029. end;
  2030. Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  2031. begin
  2032. FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
  2033. end;
  2034. Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
  2035. Var
  2036. buf : Array[0..1024] of Char;
  2037. Len: Integer;
  2038. Begin
  2039. Len:=FloatToTextFmt(PChar(@Buf[0]),Value,PChar(Format),FormatSettings);
  2040. Buf[Len]:=#0;
  2041. Result:=StrPas(Pchar(@Buf[0]));
  2042. End;
  2043. Function FormatFloat(Const format: String; Value: Extended): String;
  2044. begin
  2045. Result:=FormatFloat(Format,Value,DefaultFormatSettings);
  2046. end;
  2047. Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
  2048. begin
  2049. Result := FormatFloat(Format, Value,FormatSettings);
  2050. end;
  2051. function FormatCurr(const Format: string; Value: Currency): string;
  2052. begin
  2053. Result:=FormatCurr(Format,Value,DefaultFormatSettings);
  2054. end;
  2055. {$endif}
  2056. {==============================================================================}
  2057. { extra functions }
  2058. {==============================================================================}
  2059. { LeftStr returns Count left-most characters from S }
  2060. function LeftStr(const S: string; Count: integer): string;
  2061. begin
  2062. result := Copy(S, 1, Count);
  2063. end ;
  2064. { RightStr returns Count right-most characters from S }
  2065. function RightStr(const S: string; Count: integer): string;
  2066. begin
  2067. If Count>Length(S) then
  2068. Count:=Length(S);
  2069. result := Copy(S, 1 + Length(S) - Count, Count);
  2070. end;
  2071. { BCDToInt converts the BCD value Value to an integer }
  2072. function BCDToInt(Value: integer): integer;
  2073. var i, j, digit: integer;
  2074. begin
  2075. result := 0;
  2076. j := 1;
  2077. for i := 0 to SizeOf(Value) shl 1 - 1 do begin
  2078. digit := Value and 15;
  2079. if digit > $9 then
  2080. begin
  2081. if i = 0 then
  2082. begin
  2083. if digit in [$B, $D] then j := -1
  2084. end
  2085. else raise EConvertError.createfmt(SInvalidBCD,[Value]);
  2086. end
  2087. else
  2088. begin
  2089. result := result + j * digit;
  2090. j := j * 10;
  2091. end ;
  2092. Value := Value shr 4;
  2093. end ;
  2094. end ;
  2095. Function LastDelimiter(const Delimiters, S: string): SizeInt;
  2096. var
  2097. chs: TSysCharSet;
  2098. I: SizeInt;
  2099. begin
  2100. chs := [];
  2101. for I := 1 to Length(Delimiters) do
  2102. Include(chs, Delimiters[I]);
  2103. Result:=Length(S);
  2104. While (Result>0) and not (S[Result] in chs) do
  2105. Dec(Result);
  2106. end;
  2107. {$macro on}
  2108. {$define INSTRINGREPLACE}
  2109. {$define SRString:=AnsiString}
  2110. {$define SRUpperCase:=AnsiUppercase}
  2111. {$define SRPCHAR:=PAnsiChar}
  2112. {$define SRCHAR:=AnsiChar}
  2113. Function StringReplace(const S, OldPattern, NewPattern: Ansistring; Flags: TReplaceFlags): Ansistring;
  2114. Var
  2115. C : Integer;
  2116. begin
  2117. Result:=StringReplace(S,OldPattern,NewPattern,Flags,C);
  2118. end;
  2119. function StringReplace(const S, OldPattern, NewPattern: Ansistring; Flags: TReplaceFlags; Out aCount : Integer): Ansistring;
  2120. {$i syssr.inc}
  2121. {$undef INSTRINGREPLACE}
  2122. {$undef SRString}
  2123. {$undef SRUpperCase}
  2124. {$undef SRPCHAR}
  2125. {$undef SRCHAR}
  2126. Function IsDelimiter(const Delimiters, S: string; Index: SizeInt): Boolean;
  2127. begin
  2128. Result:=False;
  2129. If (Index>0) and (Index<=Length(S)) then
  2130. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  2131. end;
  2132. Function ByteToCharLen(const S: string; MaxLen: SizeInt): SizeInt;
  2133. begin
  2134. Result:=Length(S);
  2135. If Result>MaxLen then
  2136. Result:=MaxLen;
  2137. end;
  2138. Function ByteToCharIndex(const S: string; Index: SizeInt): SizeInt;
  2139. begin
  2140. Result:=Index;
  2141. end;
  2142. Function CharToByteLen(const S: string; MaxLen: SizeInt): SizeInt;
  2143. begin
  2144. Result:=Length(S);
  2145. If Result>MaxLen then
  2146. Result:=MaxLen;
  2147. end;
  2148. Function CharToByteIndex(const S: string; Index: SizeInt): SizeInt;
  2149. begin
  2150. Result:=Index;
  2151. end;
  2152. Function ByteType(const S: string; Index: SizeUInt): TMbcsByteType;
  2153. begin
  2154. Result:=mbSingleByte;
  2155. end;
  2156. Function StrByteType(Str: PAnsiChar; Index: SizeUInt): TMbcsByteType;
  2157. begin
  2158. Result:=mbSingleByte;
  2159. end;
  2160. Function StrCharLength(const Str: PAnsiChar): SizeInt;
  2161. begin
  2162. result:=widestringmanager.CharLengthPCharProc(Str);
  2163. end;
  2164. function StrNextChar(const Str: PAnsiChar): PAnsiChar;
  2165. begin
  2166. result:=Str+StrCharLength(Str);
  2167. end;
  2168. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  2169. Var
  2170. I,L : Integer;
  2171. S,T : String;
  2172. begin
  2173. Result:=False;
  2174. S:=Switch;
  2175. If IgnoreCase then
  2176. S:=UpperCase(S);
  2177. I:=ParamCount;
  2178. While (Not Result) and (I>0) do
  2179. begin
  2180. L:=Length(Paramstr(I));
  2181. If (L>0) and (ParamStr(I)[1] in Chars) then
  2182. begin
  2183. T:=Copy(ParamStr(I),2,L-1);
  2184. If IgnoreCase then
  2185. T:=UpperCase(T);
  2186. Result:=S=T;
  2187. end;
  2188. Dec(i);
  2189. end;
  2190. end;
  2191. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  2192. begin
  2193. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  2194. end;
  2195. Function FindCmdLineSwitch(const Switch: string): Boolean;
  2196. begin
  2197. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  2198. end;
  2199. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
  2200. const
  2201. Quotes = ['''', '"'];
  2202. Var
  2203. L : String;
  2204. C,LQ,BC : AnsiChar;
  2205. P,BLen,Len : Integer;
  2206. HB,IBC : Boolean;
  2207. begin
  2208. Result:='';
  2209. L:=Line;
  2210. Blen:=Length(BreakStr);
  2211. If (BLen>0) then
  2212. BC:=BreakStr[1]
  2213. else
  2214. BC:=#0;
  2215. Len:=Length(L);
  2216. While (Len>0) do
  2217. begin
  2218. P:=1;
  2219. LQ:=#0;
  2220. HB:=False;
  2221. IBC:=False;
  2222. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  2223. begin
  2224. C:=L[P];
  2225. If (C=LQ) then
  2226. LQ:=#0
  2227. else If (C in Quotes) then
  2228. LQ:=C;
  2229. If (LQ<>#0) then
  2230. Inc(P)
  2231. else
  2232. begin
  2233. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  2234. If HB then
  2235. Inc(P,Blen)
  2236. else
  2237. begin
  2238. If (P>=MaxCol) then
  2239. IBC:=C in BreakChars;
  2240. Inc(P);
  2241. end;
  2242. end;
  2243. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2244. end;
  2245. Result:=Result+Copy(L,1,P-1);
  2246. Delete(L,1,P-1);
  2247. Len:=Length(L);
  2248. If (Len>0) and Not HB then
  2249. Result:=Result+BreakStr;
  2250. end;
  2251. end;
  2252. function WrapText(const Line: string; MaxCol: Integer): string;
  2253. begin
  2254. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2255. end;
  2256. {$ifndef FPC_NOGENERICANSIROUTINES}
  2257. {
  2258. Case Translation Tables
  2259. Can be used in internationalization support.
  2260. Although these tables can be obtained through system calls
  2261. cd it is better to not use those, since most implementation are not 100%
  2262. WARNING:
  2263. before modifying a translation table make sure that the current codepage
  2264. of the OS corresponds to the one you make changes to
  2265. }
  2266. const
  2267. {$if defined(MSDOS) or defined(GO32V2) or defined(WATCOM) or defined(WIN16) }
  2268. { upper case translation table for character set 850 }
  2269. CP850UCT: array[128..255] of AnsiChar =
  2270. (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
  2271. #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
  2272. #181,#214,#224,#233,#165,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2273. #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  2274. #192,#193,#194,#195,#196,#197,#199,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  2275. #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  2276. #224,#225,#226,#227,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
  2277. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2278. { lower case translation table for character set 850 }
  2279. CP850LCT: array[128..255] of AnsiChar =
  2280. (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
  2281. #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
  2282. #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2283. #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
  2284. #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
  2285. #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
  2286. #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
  2287. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2288. {$endif}
  2289. { upper case translation table for character set ISO 8859/1 Latin 1 }
  2290. CPISO88591UCT: array[192..255] of AnsiChar =
  2291. ( #192, #193, #194, #195, #196, #197, #198, #199,
  2292. #200, #201, #202, #203, #204, #205, #206, #207,
  2293. #208, #209, #210, #211, #212, #213, #214, #215,
  2294. #216, #217, #218, #219, #220, #221, #222, #223,
  2295. #192, #193, #194, #195, #196, #197, #198, #199,
  2296. #200, #201, #202, #203, #204, #205, #206, #207,
  2297. #208, #209, #210, #211, #212, #213, #214, #247,
  2298. #216, #217, #218, #219, #220, #221, #222, #89 );
  2299. { lower case translation table for character set ISO 8859/1 Latin 1 }
  2300. CPISO88591LCT: array[192..255] of AnsiChar =
  2301. ( #224, #225, #226, #227, #228, #229, #230, #231,
  2302. #232, #233, #234, #235, #236, #237, #238, #239,
  2303. #240, #241, #242, #243, #244, #245, #246, #215,
  2304. #248, #249, #250, #251, #252, #253, #254, #223,
  2305. #224, #225, #226, #227, #228, #229, #230, #231,
  2306. #232, #233, #234, #235, #236, #237, #238, #239,
  2307. #240, #241, #242, #243, #244, #245, #246, #247,
  2308. #248, #249, #250, #251, #252, #253, #254, #255 );
  2309. {$endif FPC_NOGENERICANSIROUTINES}
  2310. function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
  2311. var
  2312. i,j,n,m : SizeInt;
  2313. s1 : string;
  2314. function GetInt(unsigned : boolean=false) : Integer;
  2315. begin
  2316. s1 := '';
  2317. while (Length(s) > n) and (s[n] = ' ') do
  2318. inc(n);
  2319. { read sign }
  2320. if (Length(s)>= n) and (s[n] in ['+', '-']) then
  2321. begin
  2322. { don't accept - when reading unsigned }
  2323. if unsigned and (s[n]='-') then
  2324. begin
  2325. result:=length(s1);
  2326. exit;
  2327. end
  2328. else
  2329. begin
  2330. s1:=s1+s[n];
  2331. inc(n);
  2332. end;
  2333. end;
  2334. { read numbers }
  2335. while (Length(s) >= n) and
  2336. (s[n] in ['0'..'9']) do
  2337. begin
  2338. s1 := s1+s[n];
  2339. inc(n);
  2340. end;
  2341. Result := Length(s1);
  2342. end;
  2343. function GetFloat : Integer;
  2344. begin
  2345. s1 := '';
  2346. while (Length(s) > n) and (s[n] = ' ') do
  2347. inc(n);
  2348. while (Length(s) >= n) and
  2349. (s[n] in ['0'..'9', '+', '-', FormatSettings.DecimalSeparator, 'e', 'E']) do
  2350. begin
  2351. s1 := s1+s[n];
  2352. inc(n);
  2353. end;
  2354. Result := Length(s1);
  2355. end;
  2356. function GetString : Integer;
  2357. begin
  2358. s1 := '';
  2359. while (Length(s) > n) and (s[n] = ' ') do
  2360. inc(n);
  2361. while (Length(s) >= n) and (s[n] <> ' ')do
  2362. begin
  2363. s1 := s1+s[n];
  2364. inc(n);
  2365. end;
  2366. Result := Length(s1);
  2367. end;
  2368. function ScanStr(c : AnsiChar) : Boolean;
  2369. begin
  2370. while (Length(s) > n) and (s[n] <> c) do
  2371. inc(n);
  2372. inc(n);
  2373. If (n <= Length(s)) then
  2374. Result := True
  2375. else
  2376. Result := False;
  2377. end;
  2378. function GetFmt : Integer;
  2379. begin
  2380. Result := -1;
  2381. while true do
  2382. begin
  2383. while (Length(fmt) > m) and (fmt[m] = ' ') do
  2384. inc(m);
  2385. if (m >= Length(fmt)) then
  2386. break;
  2387. if (fmt[m] = '%') then
  2388. begin
  2389. inc(m);
  2390. case fmt[m] of
  2391. 'd':
  2392. Result:=vtInteger;
  2393. {$ifndef FPUNONE}
  2394. 'f':
  2395. Result:=vtExtended;
  2396. {$endif}
  2397. 's':
  2398. Result:=vtString;
  2399. 'c':
  2400. Result:=vtChar;
  2401. else
  2402. raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
  2403. end;
  2404. inc(m);
  2405. break;
  2406. end;
  2407. if not(ScanStr(fmt[m])) then
  2408. break;
  2409. inc(m);
  2410. end;
  2411. end;
  2412. begin
  2413. n := 1;
  2414. m := 1;
  2415. Result := 0;
  2416. for i:=0 to High(Pointers) do
  2417. begin
  2418. j := GetFmt;
  2419. case j of
  2420. vtInteger :
  2421. begin
  2422. if GetInt>0 then
  2423. begin
  2424. pLongint(Pointers[i])^:=StrToInt(s1);
  2425. inc(Result);
  2426. end
  2427. else
  2428. break;
  2429. end;
  2430. vtchar :
  2431. begin
  2432. if Length(s)>n then
  2433. begin
  2434. PChar(Pointers[i])^:=s[n];
  2435. inc(n);
  2436. inc(Result);
  2437. end
  2438. else
  2439. break;
  2440. end;
  2441. {$ifndef FPUNONE}
  2442. vtExtended :
  2443. begin
  2444. if GetFloat>0 then
  2445. begin
  2446. pextended(Pointers[i])^:=StrToFloat(s1);
  2447. inc(Result);
  2448. end
  2449. else
  2450. break;
  2451. end;
  2452. {$endif}
  2453. vtString :
  2454. begin
  2455. if GetString > 0 then
  2456. begin
  2457. pstring(Pointers[i])^:=s1;
  2458. inc(Result);
  2459. end
  2460. else
  2461. break;
  2462. end;
  2463. else
  2464. break;
  2465. end;
  2466. end;
  2467. end;
  2468. {$macro on}
  2469. // Ansi version declaration
  2470. {$UNDEF SBUNICODE}
  2471. {$define SBChar:=AnsiChar}
  2472. {$define SBString:=AnsiString}
  2473. {$define TSBCharArray:=Array of SBChar}
  2474. {$define PSBChar:=PAnsiChar}
  2475. {$define SBRAWString:=RawByteString}
  2476. {$define TGenericStringBuilder:=TAnsiStringBuilder}
  2477. {$i syssb.inc}
  2478. {$undef SBChar}
  2479. {$undef SBString}
  2480. {$undef TSBCharArray}
  2481. {$undef PSBChar}
  2482. {$undef SBRAWString}
  2483. {$undef TGenericStringBuilder}
  2484. // Unicode version declaration
  2485. {$define SBUNICODE}
  2486. {$define SBChar:=WideChar}
  2487. {$define SBString:=UnicodeString}
  2488. {$define TSBCharArray:=Array of SBChar}
  2489. {$define PSBChar:=PWideChar}
  2490. {$define SBRAWString:=UnicodeString}
  2491. {$define TGenericStringBuilder:=TUnicodeStringBuilder}
  2492. {$i syssb.inc}
  2493. {$undef SBChar}
  2494. {$undef SBString}
  2495. {$undef TSBCharArray}
  2496. {$undef PSBChar}
  2497. {$undef SBRAWString}
  2498. {$undef TGenericStringBuilder}
  2499. {$undef SBUNICODE}