sysstr.inc 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980
  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: string): 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 StrToFloat(Const S: String): Extended;
  1062. begin
  1063. Result:=StrToFloat(S,DefaultFormatSettings);
  1064. end;
  1065. Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
  1066. Begin // texttofloat handles NIL properly
  1067. If Not TextToFloat(PChar(pointer(S)),Result,FormatSettings) then
  1068. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1069. End;
  1070. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  1071. begin
  1072. Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
  1073. end;
  1074. Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
  1075. begin
  1076. if not TextToFloat(PChar(S),Result,fvExtended,FormatSettings) then
  1077. Result:=Default;
  1078. end;
  1079. Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  1080. Var
  1081. E,P : Integer;
  1082. S : String;
  1083. Begin
  1084. S:=StrPas(Buffer);
  1085. //ThousandSeparator not allowed as by Delphi specs
  1086. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1087. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1088. begin
  1089. Result := False;
  1090. Exit;
  1091. end;
  1092. if (FormatSettings.DecimalSeparator <> '.') and
  1093. (Pos('.', S) <>0) then
  1094. begin
  1095. Result := False;
  1096. Exit;
  1097. end;
  1098. P:=Pos(FormatSettings.DecimalSeparator,S);
  1099. If (P<>0) Then
  1100. S[P] := '.';
  1101. try
  1102. Val(trim(S),Value,E);
  1103. { on x87, a floating point exception may be pending in case of an invalid
  1104. input value -> trigger it now }
  1105. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1106. asm
  1107. fwait
  1108. end;
  1109. {$endif}
  1110. except
  1111. E:=1;
  1112. end;
  1113. Result:=(E=0);
  1114. End;
  1115. Function TextToFloat(Buffer: PChar; Out Value: Extended): Boolean;
  1116. begin
  1117. Result:=TextToFloat(Buffer,Value,DefaultFormatSettings);
  1118. end;
  1119. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue): Boolean;
  1120. begin
  1121. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  1122. end;
  1123. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  1124. Var
  1125. E,P : Integer;
  1126. S : String;
  1127. Begin
  1128. S:=StrPas(Buffer);
  1129. //ThousandSeparator not allowed as by Delphi specs
  1130. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1131. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1132. begin
  1133. Result := False;
  1134. Exit;
  1135. end;
  1136. if (FormatSettings.DecimalSeparator <> '.') and
  1137. (Pos('.', S) <>0) then
  1138. begin
  1139. Result := False;
  1140. Exit;
  1141. end;
  1142. P:=Pos(FormatSettings.DecimalSeparator,S);
  1143. If (P<>0) Then
  1144. S[P] := '.';
  1145. s:=Trim(s);
  1146. try
  1147. case ValueType of
  1148. fvCurrency:
  1149. Val(S,Currency(Value),E);
  1150. fvExtended:
  1151. Val(S,Extended(Value),E);
  1152. fvDouble:
  1153. Val(S,Double(Value),E);
  1154. fvSingle:
  1155. Val(S,Single(Value),E);
  1156. fvComp:
  1157. Val(S,Comp(Value),E);
  1158. fvReal:
  1159. Val(S,Real(Value),E);
  1160. end;
  1161. { on x87, a floating point exception may be pending in case of an invalid
  1162. input value -> trigger it now }
  1163. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1164. asm
  1165. fwait
  1166. end;
  1167. {$endif}
  1168. except
  1169. E:=1;
  1170. end;
  1171. Result:=(E=0);
  1172. End;
  1173. {$IF SIZEOF(CHAR)=2}
  1174. Function TextToFloat(Buffer: PAnsiChar; Out Value; ValueType: TFloatValue): Boolean;
  1175. begin
  1176. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  1177. end;
  1178. Function TextToFloat(Buffer: PAnsiChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  1179. Var
  1180. E,P : Integer;
  1181. S : AnsiString;
  1182. Begin
  1183. S:=StrPas(Buffer);
  1184. //ThousandSeparator not allowed as by Delphi specs
  1185. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1186. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1187. begin
  1188. Result := False;
  1189. Exit;
  1190. end;
  1191. if (FormatSettings.DecimalSeparator <> '.') and
  1192. (Pos('.', S) <>0) then
  1193. begin
  1194. Result := False;
  1195. Exit;
  1196. end;
  1197. P:=Pos(FormatSettings.DecimalSeparator,S);
  1198. If (P<>0) Then
  1199. S[P] := '.';
  1200. s:=Trim(s);
  1201. try
  1202. case ValueType of
  1203. fvCurrency:
  1204. Val(S,Currency(Value),E);
  1205. fvExtended:
  1206. Val(S,Extended(Value),E);
  1207. fvDouble:
  1208. Val(S,Double(Value),E);
  1209. fvSingle:
  1210. Val(S,Single(Value),E);
  1211. fvComp:
  1212. Val(S,Comp(Value),E);
  1213. fvReal:
  1214. Val(S,Real(Value),E);
  1215. end;
  1216. { on x87, a floating point exception may be pending in case of an invalid
  1217. input value -> trigger it now }
  1218. {$if defined(cpui386) or (defined(cpux86_64) and not(defined(win64))) or defined(cpui8086)}
  1219. asm
  1220. fwait
  1221. end;
  1222. {$endif}
  1223. except
  1224. E:=1;
  1225. end;
  1226. Result:=(E=0);
  1227. End;
  1228. {$ENDIF}
  1229. Function TryStrToFloat(Const S : String; Out Value: Single): Boolean;
  1230. begin
  1231. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1232. end;
  1233. Function TryStrToFloat(Const S : String; Out Value: Single; Const FormatSettings: TFormatSettings): Boolean;
  1234. Begin
  1235. Result := TextToFloat(PChar(pointer(S)), Value, fvSingle,FormatSettings);
  1236. End;
  1237. Function TryStrToFloat(Const S : String; Out Value: Double): Boolean;
  1238. begin
  1239. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1240. end;
  1241. Function TryStrToFloat(Const S : String; Out Value: Double; Const FormatSettings: TFormatSettings): Boolean;
  1242. Begin
  1243. Result := TextToFloat(PChar(pointer(S)), Value, fvDouble,FormatSettings);
  1244. End;
  1245. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1246. Function TryStrToFloat(Const S : String; Out Value: Extended): Boolean;
  1247. begin
  1248. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1249. end;
  1250. Function TryStrToFloat(Const S : String; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  1251. Begin
  1252. Result := TextToFloat(PChar(pointer(S)), Value,FormatSettings);
  1253. End;
  1254. {$endif FPC_HAS_TYPE_EXTENDED}
  1255. const
  1256. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1257. maxdigits = 17;
  1258. {$else}
  1259. maxdigits = 15;
  1260. {$endif}
  1261. Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
  1262. Var
  1263. P, PE, Q, Exponent: Integer;
  1264. Negative: Boolean;
  1265. DS: Char;
  1266. function RemoveLeadingNegativeSign(var AValue: String): Boolean;
  1267. // removes negative sign in case when result is zero eg. -0.00
  1268. var
  1269. i: PtrInt;
  1270. TS: Char;
  1271. StartPos: PtrInt;
  1272. begin
  1273. Result := False;
  1274. if Format = ffCurrency then
  1275. StartPos := 1
  1276. else
  1277. StartPos := 2;
  1278. TS := FormatSettings.ThousandSeparator;
  1279. for i := StartPos to length(AValue) do
  1280. begin
  1281. Result := (AValue[i] in ['0', DS, 'E', '+', TS]);
  1282. if not Result then
  1283. break;
  1284. end;
  1285. if (Result) and (Format <> ffCurrency) then
  1286. Delete(AValue, 1, 1);
  1287. end;
  1288. Begin
  1289. DS:=FormatSettings.DecimalSeparator;
  1290. Case format Of
  1291. ffGeneral:
  1292. Begin
  1293. case ValueType of
  1294. fvCurrency:
  1295. If (Precision = -1) Or (Precision > 19) Then Precision := 19;
  1296. else
  1297. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1298. end;
  1299. { First convert to scientific format, with correct precision }
  1300. case ValueType of
  1301. fvDouble:
  1302. Str(Double(Extended(Aligned(Value))):precision+7, Result);
  1303. fvSingle:
  1304. Str(Single(Extended(Aligned(Value))):precision+6, Result);
  1305. fvCurrency:
  1306. Str(Currency(Aligned(Value)):precision+6, Result);
  1307. else
  1308. Str(Extended(Aligned(Value)):precision+8, Result);
  1309. end;
  1310. { Delete leading spaces }
  1311. while Result[1] = ' ' do
  1312. System.Delete(Result, 1, 1);
  1313. P := Pos('.', Result);
  1314. if P<>0 then
  1315. Result[P] := DS
  1316. else
  1317. Exit; { NAN or other special case }
  1318. { Consider removing exponent }
  1319. PE:=Pos('E',Result);
  1320. if PE > 0 then begin
  1321. { Read exponent }
  1322. Q := PE+2;
  1323. Exponent := 0;
  1324. while (Q <= Length(Result)) do begin
  1325. Exponent := Exponent*10 + Ord(Result[Q])-Ord('0');
  1326. Inc(Q);
  1327. end;
  1328. if Result[PE+1] = '-' then
  1329. Exponent := -Exponent;
  1330. if (P+Exponent < PE) and (Exponent > -6) then begin
  1331. { OK to remove exponent }
  1332. SetLength(Result,PE-1); { Trim exponent }
  1333. if Exponent >= 0 then begin
  1334. { Shift point to right }
  1335. for Q := 0 to Exponent-1 do begin
  1336. Result[P] := Result[P+1];
  1337. Inc(P);
  1338. end;
  1339. Result[P] := DS;
  1340. P := 1;
  1341. if Result[P] = '-' then
  1342. Inc(P);
  1343. while (Result[P] = '0') and (P < Length(Result)) and (Result[P+1] <> DS) do
  1344. { Trim leading zeros; conversion above should not give any, but occasionally does
  1345. because of rounding }
  1346. System.Delete(Result,P,1);
  1347. end else begin
  1348. { Add zeros at start }
  1349. Insert(Copy('00000',1,-Exponent),Result,P-1);
  1350. Result[P-Exponent] := Result[P-Exponent-1]; { Copy leading digit }
  1351. Result[P] := DS;
  1352. if Exponent <> -1 then
  1353. Result[P-Exponent-1] := '0';
  1354. end;
  1355. { Remove trailing zeros }
  1356. Q := Length(Result);
  1357. while (Q > 0) and (Result[Q] = '0') do
  1358. Dec(Q);
  1359. if Result[Q] = DS then
  1360. Dec(Q); { Remove trailing decimal point }
  1361. if (Q = 0) or ((Q=1) and (Result[1] = '-')) then
  1362. Result := '0'
  1363. else
  1364. SetLength(Result,Q);
  1365. end else begin
  1366. { Need exponent, but remove superfluous characters }
  1367. { Delete trailing zeros }
  1368. while Result[PE-1] = '0' do begin
  1369. System.Delete(Result,PE-1,1);
  1370. Dec(PE);
  1371. end;
  1372. { If number ends in decimal point, remove it }
  1373. if Result[PE-1] = DS then begin
  1374. System.Delete(Result,PE-1,1);
  1375. Dec(PE);
  1376. end;
  1377. { delete superfluous + in exponent }
  1378. if Result[PE+1]='+' then
  1379. System.Delete(Result,PE+1,1)
  1380. else
  1381. Inc(PE);
  1382. while Result[PE+1] = '0' do
  1383. { Delete leading zeros in exponent }
  1384. System.Delete(Result,PE+1,1)
  1385. end;
  1386. end;
  1387. End;
  1388. ffExponent:
  1389. Begin
  1390. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1391. case ValueType of
  1392. fvDouble:
  1393. Str(Double(Extended(Aligned(Value))):Precision+7, Result);
  1394. fvSingle:
  1395. Str(Single(Extended(Aligned(Value))):Precision+6, Result);
  1396. fvCurrency:
  1397. Str(Currency(Aligned(Value)):Precision+6, Result);
  1398. else
  1399. Str(Extended(Aligned(Value)):Precision+8, Result);
  1400. end;
  1401. { Delete leading spaces }
  1402. while Result[1] = ' ' do
  1403. System.Delete(Result, 1, 1);
  1404. if (Result[1]='-') and
  1405. { not Nan etc.? }
  1406. (Result[3]='.') then
  1407. Result[3] := DS
  1408. else if Result[2]='.' then
  1409. Result[2] := DS;
  1410. P:=Pos('E',Result);
  1411. if P <> 0 then
  1412. begin
  1413. Inc(P, 2);
  1414. if Digits > 4 then
  1415. Digits:=4;
  1416. Digits:=Length(Result) - P - Digits + 1;
  1417. if Digits < 0 then
  1418. insert(copy('0000',1,-Digits),Result,P)
  1419. else
  1420. while (Digits > 0) and (Result[P] = '0') do
  1421. begin
  1422. System.Delete(Result, P, 1);
  1423. if P > Length(Result) then
  1424. begin
  1425. System.Delete(Result, P - 2, 2);
  1426. break;
  1427. end;
  1428. Dec(Digits);
  1429. end;
  1430. end;
  1431. End;
  1432. ffFixed:
  1433. Begin
  1434. If Digits = -1 Then Digits := 2
  1435. Else If Digits > 18 Then Digits := 18;
  1436. case ValueType of
  1437. fvDouble:
  1438. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1439. fvSingle:
  1440. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1441. fvCurrency:
  1442. Str(Currency(Aligned(Value)):0:Digits, Result);
  1443. else
  1444. Str(Extended(Aligned(Value)):0:Digits, Result);
  1445. end;
  1446. If Result[1] = ' ' Then
  1447. System.Delete(Result, 1, 1);
  1448. P := Pos('.', Result);
  1449. If P <> 0 Then Result[P] := DS;
  1450. End;
  1451. ffNumber:
  1452. Begin
  1453. If Digits = -1 Then Digits := 2
  1454. Else If Digits > maxdigits Then Digits := maxdigits;
  1455. case ValueType of
  1456. fvDouble:
  1457. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1458. fvSingle:
  1459. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1460. fvCurrency:
  1461. Str(Currency(Aligned(Value)):0:Digits, Result);
  1462. else
  1463. Str(Extended(Aligned(Value)):0:Digits, Result);
  1464. end;
  1465. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1466. P := Pos('.', Result);
  1467. If P <> 0 Then
  1468. Result[P] := DS
  1469. else
  1470. P := Length(Result)+1;
  1471. Dec(P, 3);
  1472. While (P > 1) Do
  1473. Begin
  1474. If (Result[P - 1] <> '-') And (FormatSettings.ThousandSeparator <> #0) Then
  1475. Insert(FormatSettings.ThousandSeparator, Result, P);
  1476. Dec(P, 3);
  1477. End;
  1478. End;
  1479. ffCurrency:
  1480. Begin
  1481. If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
  1482. Else If Digits > 18 Then Digits := 18;
  1483. case ValueType of
  1484. fvDouble:
  1485. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1486. fvSingle:
  1487. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1488. fvCurrency:
  1489. Str(Currency(Aligned(Value)):0:Digits, Result);
  1490. else
  1491. Str(Extended(Aligned(Value)):0:Digits, Result);
  1492. end;
  1493. Negative:=Result[1] = '-';
  1494. if Negative then
  1495. System.Delete(Result, 1, 1);
  1496. P := Pos('.', Result);
  1497. If P <> 0 Then Result[P] := DS else P := Length(Result)+1;
  1498. Dec(P, 3);
  1499. While (P > 1) Do
  1500. Begin
  1501. If FormatSettings.ThousandSeparator<>#0 Then
  1502. Insert(FormatSettings.ThousandSeparator, Result, P);
  1503. Dec(P, 3);
  1504. End;
  1505. if (length(Result) > 1) and Negative then
  1506. Negative := not RemoveLeadingNegativeSign(Result);
  1507. If Not Negative Then
  1508. Begin
  1509. Case FormatSettings.CurrencyFormat Of
  1510. 0: Result := FormatSettings.CurrencyString + Result;
  1511. 1: Result := Result + FormatSettings.CurrencyString;
  1512. 2: Result := FormatSettings.CurrencyString + ' ' + Result;
  1513. 3: Result := Result + ' ' + FormatSettings.CurrencyString;
  1514. End
  1515. End
  1516. Else
  1517. Begin
  1518. Case FormatSettings.NegCurrFormat Of
  1519. 0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
  1520. 1: Result := '-' + FormatSettings.CurrencyString + Result;
  1521. 2: Result := FormatSettings.CurrencyString + '-' + Result;
  1522. 3: Result := FormatSettings.CurrencyString + Result + '-';
  1523. 4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
  1524. 5: Result := '-' + Result + FormatSettings.CurrencyString;
  1525. 6: Result := Result + '-' + FormatSettings.CurrencyString;
  1526. 7: Result := Result + FormatSettings.CurrencyString + '-';
  1527. 8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
  1528. 9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
  1529. 10: Result := Result + ' ' + FormatSettings.CurrencyString + '-';
  1530. 11: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
  1531. 12: Result := FormatSettings.CurrencyString + ' ' + '-' + Result;
  1532. 13: Result := Result + '-' + ' ' + FormatSettings.CurrencyString;
  1533. 14: Result := '(' + FormatSettings.CurrencyString + ' ' + Result + ')';
  1534. 15: Result := '(' + Result + ' ' + FormatSettings.CurrencyString + ')';
  1535. End;
  1536. End;
  1537. End;
  1538. End;
  1539. if not (format in [ffCurrency]) and (length(Result) > 1) and (Result[1] = '-') then
  1540. RemoveLeadingNegativeSign(Result);
  1541. End;
  1542. {$macro off}
  1543. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1544. Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
  1545. Begin
  1546. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
  1547. End;
  1548. Function FloatToStr(Value: Extended): String;
  1549. begin
  1550. Result:=FloatToStr(Value,DefaultFormatSettings);
  1551. end;
  1552. {$endif FPC_HAS_TYPE_EXTENDED}
  1553. Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
  1554. Begin
  1555. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
  1556. End;
  1557. Function FloatToStr(Value: Currency): String;
  1558. begin
  1559. Result:=FloatToStr(Value,DefaultFormatSettings);
  1560. end;
  1561. Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
  1562. var
  1563. e: Extended;
  1564. Begin
  1565. e := Value;
  1566. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
  1567. End;
  1568. Function FloatToStr(Value: Double): String;
  1569. begin
  1570. Result:=FloatToStr(Value,DefaultFormatSettings);
  1571. end;
  1572. Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
  1573. var
  1574. e: Extended;
  1575. Begin
  1576. e := Value;
  1577. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
  1578. End;
  1579. Function FloatToStr(Value: Single): String;
  1580. begin
  1581. Result:=FloatToStr(Value,DefaultFormatSettings);
  1582. end;
  1583. Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
  1584. var
  1585. e: Extended;
  1586. Begin
  1587. e := Value;
  1588. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1589. End;
  1590. Function FloatToStr(Value: Comp): String;
  1591. begin
  1592. Result:=FloatToStr(Value,DefaultFormatSettings);
  1593. end;
  1594. {$ifndef FPC_COMP_IS_INT64}
  1595. Function FloatToStr(Value: Int64): String;
  1596. begin
  1597. Result:=FloatToStr(Value,DefaultFormatSettings);
  1598. end;
  1599. Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
  1600. var
  1601. e: Extended;
  1602. Begin
  1603. e := Comp(Value);
  1604. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1605. End;
  1606. {$endif FPC_COMP_IS_INT64}
  1607. Function FloatToText(Buffer: PAnsiChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1608. Var
  1609. Tmp: String[40];
  1610. Begin
  1611. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1612. Result := Length(Tmp);
  1613. Move(Tmp[1], Buffer[0], Result);
  1614. End;
  1615. Function FloatToText(Buffer: PWideChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1616. Var
  1617. Tmp: UnicodeString;
  1618. Begin
  1619. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1620. Result := Length(Tmp);
  1621. Move(Tmp[1], Buffer[0], Result*SizeOf(WideChar));
  1622. End;
  1623. Function FloatToText(Buffer: PAnsiChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1624. begin
  1625. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1626. end;
  1627. Function FloatToText(Buffer: PWideChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1628. begin
  1629. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1630. end;
  1631. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1632. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1633. begin
  1634. Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
  1635. end;
  1636. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1637. begin
  1638. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1639. end;
  1640. {$endif}
  1641. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1642. begin
  1643. Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
  1644. end;
  1645. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
  1646. begin
  1647. Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
  1648. end;
  1649. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1650. var
  1651. e: Extended;
  1652. begin
  1653. e := Value;
  1654. result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
  1655. end;
  1656. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
  1657. begin
  1658. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1659. end;
  1660. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1661. var
  1662. e: Extended;
  1663. begin
  1664. e:=Value;
  1665. result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
  1666. end;
  1667. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
  1668. begin
  1669. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1670. end;
  1671. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1672. var
  1673. e: Extended;
  1674. begin
  1675. e := Value;
  1676. Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1677. end;
  1678. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
  1679. begin
  1680. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1681. end;
  1682. {$ifndef FPC_COMP_IS_INT64}
  1683. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1684. var
  1685. e: Extended;
  1686. begin
  1687. e := Comp(Value);
  1688. result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1689. end;
  1690. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
  1691. begin
  1692. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1693. end;
  1694. {$endif FPC_COMP_IS_INT64}
  1695. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
  1696. begin
  1697. result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
  1698. end;
  1699. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
  1700. begin
  1701. Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
  1702. end;
  1703. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1704. begin
  1705. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1706. Raise EConvertError.CreateFmt (SInvalidDateTimeFloat,[Value]);
  1707. Result:=Value;
  1708. end;
  1709. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1710. begin
  1711. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1712. if Result then
  1713. AResult := Value;
  1714. end;
  1715. function FloatToCurr(const Value: Extended): Currency;
  1716. begin
  1717. if not TryFloatToCurr(Value, Result) then
  1718. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1719. end;
  1720. Function CurrToStr(Value: Currency): string;
  1721. begin
  1722. Result:=FloatToStrF(Value,ffGeneral,-1,0);
  1723. end;
  1724. Function CurrToStr(Value: Currency; Const FormatSettings: TFormatSettings): string;
  1725. begin
  1726. Result:=FloatToStrF(Value,ffGeneral,-1,0,FormatSettings);
  1727. end;
  1728. function StrToCurr(const S: string): Currency;
  1729. begin
  1730. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1731. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1732. end;
  1733. function StrToCurr(const S: string; Const FormatSettings: TFormatSettings): Currency;
  1734. begin
  1735. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
  1736. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1737. end;
  1738. Function TryStrToCurr(Const S : String; Out Value: Currency): Boolean;
  1739. Begin
  1740. Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency);
  1741. End;
  1742. function TryStrToCurr(const S: string;Out Value : Currency; Const FormatSettings: TFormatSettings): Boolean;
  1743. Begin
  1744. Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency,FormatSettings);
  1745. End;
  1746. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1747. begin
  1748. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1749. Result:=Default;
  1750. end;
  1751. function StrToCurrDef(const S: string; Default : Currency; Const FormatSettings: TFormatSettings): Currency;
  1752. begin
  1753. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
  1754. Result:=Default;
  1755. end;
  1756. {$endif FPUNONE}
  1757. function AnsiDequotedStr(const S: string; AQuote: Char): string;
  1758. var p : PChar;
  1759. begin
  1760. p:=PChar(pointer(s)); // work around CONST. Ansiextract is safe for nil
  1761. result:=AnsiExtractquotedStr(p,AQuote);
  1762. end;
  1763. function StrToBool(const S: string): Boolean;
  1764. begin
  1765. if not(TryStrToBool(S,Result,DefaultFormatSettings)) then
  1766. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1767. end;
  1768. function StrToBool(const S: string; const FormatSettings: TFormatSettings): Boolean;
  1769. begin
  1770. if not(TryStrToBool(S,Result,FormatSettings)) then
  1771. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1772. end;
  1773. procedure CheckBoolStrs;
  1774. begin
  1775. If Length(TrueBoolStrs)=0 then
  1776. begin
  1777. SetLength(TrueBoolStrs,1);
  1778. TrueBoolStrs[0]:='True';
  1779. end;
  1780. If Length(FalseBoolStrs)=0 then
  1781. begin
  1782. SetLength(FalseBoolStrs,1);
  1783. FalseBoolStrs[0]:='False';
  1784. end;
  1785. end;
  1786. function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
  1787. begin
  1788. if UseBoolStrs Then
  1789. begin
  1790. CheckBoolStrs;
  1791. if B then
  1792. Result:=TrueBoolStrs[0]
  1793. else
  1794. Result:=FalseBoolStrs[0];
  1795. end
  1796. else
  1797. If B then
  1798. Result:='-1'
  1799. else
  1800. Result:='0';
  1801. end;
  1802. // from textmode IDE util funcs.
  1803. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  1804. begin
  1805. if B then Result:=TrueS else BoolToStr:=FalseS;
  1806. end;
  1807. function StrToBoolDef(const S: string; Default: Boolean): Boolean;
  1808. begin
  1809. if not(TryStrToBool(S,Result)) then
  1810. Result:=Default;
  1811. end;
  1812. function StrToBoolDef(const S: string; Default: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1813. begin
  1814. if not(TryStrToBool(S,Result,FormatSettings)) then
  1815. Result:=Default;
  1816. end;
  1817. function TryStrToBool(const S: string; out Value: Boolean): Boolean;
  1818. begin
  1819. Result:=TryStrToBool(S,Value,DefaultFormatSettings);
  1820. end;
  1821. function TryStrToBool(const S: string; out Value: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1822. Var
  1823. Temp : String;
  1824. I : Longint;
  1825. {$ifdef FPUNONE}
  1826. D : Longint;
  1827. {$else}
  1828. D : Double;
  1829. {$endif}
  1830. Code: word;
  1831. begin
  1832. Temp:=upcase(S);
  1833. Val(temp,D,code);
  1834. Result:=true;
  1835. If (Code=0) or TryStrToFloat(S,D,FormatSettings) then
  1836. {$ifdef FPUNONE}
  1837. Value:=(D<>0)
  1838. {$else}
  1839. Value:=(D<>0.0)
  1840. {$endif}
  1841. else
  1842. begin
  1843. CheckBoolStrs;
  1844. for I:=low(TrueBoolStrs) to High(TrueBoolStrs) do
  1845. if Temp=upcase(TrueBoolStrs[I]) then
  1846. begin
  1847. Value:=true;
  1848. exit;
  1849. end;
  1850. for I:=low(FalseBoolStrs) to High(FalseBoolStrs) do
  1851. if Temp=upcase(FalseBoolStrs[I]) then
  1852. begin
  1853. Value:=false;
  1854. exit;
  1855. end;
  1856. Result:=false;
  1857. end;
  1858. end;
  1859. {$ifndef FPUNONE}
  1860. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1861. begin
  1862. Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
  1863. end;
  1864. {$MACRO ON}
  1865. {$define FPChar:=PAnsiChar}
  1866. {$define FChar:=AnsiChar}
  1867. {$define FString:=AnsiString}
  1868. {$I fmtflt.inc}
  1869. {$undef FPChar}
  1870. {$undef FChar}
  1871. {$undef FString}
  1872. {$MACRO ON}
  1873. {$define FPChar:=PWideChar}
  1874. {$define FChar:=WideChar}
  1875. {$define FString:=UnicodeString}
  1876. {$I fmtflt.inc}
  1877. {$define FPChar:=PAnsiChar}
  1878. {$define FChar:=AnsiChar}
  1879. {$define FString:=AnsiString}
  1880. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar; FormatSettings : TFormatSettings): Integer;
  1881. begin
  1882. Result:=IntFloatToTextFmt(Buffer,Value,fvExtended,Format,FormatSettings);
  1883. end;
  1884. Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
  1885. var
  1886. Buffer: String[254]; //Though str func returns only 25 chars, this might change in the future
  1887. InfNan: string[3];
  1888. Error, N, L, Start, C: Integer;
  1889. GotNonZeroBeforeDot, BeforeDot : boolean;
  1890. begin
  1891. case ValueType of
  1892. fvExtended:
  1893. Str(Extended(Value):25, Buffer);
  1894. fvDouble,
  1895. fvReal:
  1896. Str(Double(Value):23, Buffer);
  1897. fvSingle:
  1898. Str(Single(Value):16, Buffer);
  1899. fvCurrency:
  1900. Str(Currency(Value):25, Buffer);
  1901. fvComp:
  1902. Str(Currency(Value):23, Buffer);
  1903. end;
  1904. N := 1;
  1905. L := Byte(Buffer[0]);
  1906. while Buffer[N]=' ' do
  1907. Inc(N);
  1908. Result.Negative := (Buffer[N] = '-');
  1909. if Result.Negative then
  1910. Inc(N)
  1911. else if (Buffer[N] = '+') then
  1912. inc(N);
  1913. { special cases for Inf and Nan }
  1914. if (L>=N+2) then
  1915. begin
  1916. InfNan:=copy(Buffer,N,3);
  1917. if (InfNan='Inf') then
  1918. begin
  1919. Result.Digits[0]:=#0;
  1920. Result.Exponent:=32767;
  1921. exit
  1922. end;
  1923. if (InfNan='Nan') then
  1924. begin
  1925. Result.Digits[0]:=#0;
  1926. Result.Exponent:=-32768;
  1927. exit
  1928. end;
  1929. end;
  1930. Start := N; //Start of digits
  1931. Result.Exponent := 0; BeforeDot := true;
  1932. GotNonZeroBeforeDot := false;
  1933. while (L>=N) and (Buffer[N]<>'E') do
  1934. begin
  1935. if Buffer[N]='.' then
  1936. BeforeDot := false
  1937. else
  1938. begin
  1939. if BeforeDot then
  1940. begin // Currently this is always 1 AnsiChar
  1941. Inc(Result.Exponent);
  1942. Result.Digits[N-Start] := Buffer[N];
  1943. if Buffer[N] <> '0' then
  1944. GotNonZeroBeforeDot := true;
  1945. end
  1946. else
  1947. Result.Digits[N-Start-1] := Buffer[N]
  1948. end;
  1949. Inc(N);
  1950. end;
  1951. Inc(N); // Pass through 'E'
  1952. if N<=L then
  1953. begin
  1954. Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
  1955. Inc(Result.Exponent, C);
  1956. end;
  1957. // Calculate number of digits we have from str
  1958. if BeforeDot then
  1959. N := N - Start - 1
  1960. else
  1961. N := N - Start - 2;
  1962. L := SizeOf(Result.Digits);
  1963. if N<L then
  1964. FillChar(Result.Digits[N], L-N, '0'); //Zero remaining space
  1965. if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
  1966. N := Decimals + Result.Exponent
  1967. Else
  1968. N := Precision;
  1969. if N >= L Then
  1970. N := L-1;
  1971. if N = 0 Then
  1972. begin
  1973. if Result.Digits[0] >= '5' Then
  1974. begin
  1975. Result.Digits[0] := '1';
  1976. Result.Digits[1] := #0;
  1977. Inc(Result.Exponent);
  1978. end
  1979. Else
  1980. Result.Digits[0] := #0;
  1981. end //N=0
  1982. Else if N > 0 Then
  1983. begin
  1984. if Result.Digits[N] >= '5' Then
  1985. begin
  1986. Repeat
  1987. Result.Digits[N] := #0;
  1988. Dec(N);
  1989. Inc(Result.Digits[N]);
  1990. Until (N = 0) Or (Result.Digits[N] < ':');
  1991. If Result.Digits[0] = ':' Then
  1992. begin
  1993. Result.Digits[0] := '1';
  1994. Inc(Result.Exponent);
  1995. end;
  1996. end
  1997. Else
  1998. begin
  1999. Result.Digits[N] := '0';
  2000. While (N > -1) And (Result.Digits[N] = '0') Do
  2001. begin
  2002. Result.Digits[N] := #0;
  2003. Dec(N);
  2004. end;
  2005. end;
  2006. end //N>0
  2007. Else
  2008. Result.Digits[0] := #0;
  2009. if (Result.Digits[0] = #0) and
  2010. not GotNonZeroBeforeDot then
  2011. begin
  2012. Result.Exponent := 0;
  2013. Result.Negative := False;
  2014. end;
  2015. end;
  2016. Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  2017. begin
  2018. FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
  2019. end;
  2020. Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
  2021. Var
  2022. buf : Array[0..1024] of Char;
  2023. Len: Integer;
  2024. Begin
  2025. Len:=FloatToTextFmt(PChar(@Buf[0]),Value,PChar(Format),FormatSettings);
  2026. Buf[Len]:=#0;
  2027. Result:=StrPas(Pchar(@Buf[0]));
  2028. End;
  2029. Function FormatFloat(Const format: String; Value: Extended): String;
  2030. begin
  2031. Result:=FormatFloat(Format,Value,DefaultFormatSettings);
  2032. end;
  2033. Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
  2034. begin
  2035. Result := FormatFloat(Format, Value,FormatSettings);
  2036. end;
  2037. function FormatCurr(const Format: string; Value: Currency): string;
  2038. begin
  2039. Result:=FormatCurr(Format,Value,DefaultFormatSettings);
  2040. end;
  2041. {$endif}
  2042. {==============================================================================}
  2043. { extra functions }
  2044. {==============================================================================}
  2045. { LeftStr returns Count left-most characters from S }
  2046. function LeftStr(const S: string; Count: integer): string;
  2047. begin
  2048. result := Copy(S, 1, Count);
  2049. end ;
  2050. { RightStr returns Count right-most characters from S }
  2051. function RightStr(const S: string; Count: integer): string;
  2052. begin
  2053. If Count>Length(S) then
  2054. Count:=Length(S);
  2055. result := Copy(S, 1 + Length(S) - Count, Count);
  2056. end;
  2057. { BCDToInt converts the BCD value Value to an integer }
  2058. function BCDToInt(Value: integer): integer;
  2059. var i, j, digit: integer;
  2060. begin
  2061. result := 0;
  2062. j := 1;
  2063. for i := 0 to SizeOf(Value) shl 1 - 1 do begin
  2064. digit := Value and 15;
  2065. if digit > $9 then
  2066. begin
  2067. if i = 0 then
  2068. begin
  2069. if digit in [$B, $D] then j := -1
  2070. end
  2071. else raise EConvertError.createfmt(SInvalidBCD,[Value]);
  2072. end
  2073. else
  2074. begin
  2075. result := result + j * digit;
  2076. j := j * 10;
  2077. end ;
  2078. Value := Value shr 4;
  2079. end ;
  2080. end ;
  2081. Function LastDelimiter(const Delimiters, S: string): SizeInt;
  2082. var
  2083. chs: TSysCharSet;
  2084. I: SizeInt;
  2085. begin
  2086. chs := [];
  2087. for I := 1 to Length(Delimiters) do
  2088. Include(chs, Delimiters[I]);
  2089. Result:=Length(S);
  2090. While (Result>0) and not (S[Result] in chs) do
  2091. Dec(Result);
  2092. end;
  2093. {$macro on}
  2094. {$define INSTRINGREPLACE}
  2095. {$define SRString:=AnsiString}
  2096. {$define SRUpperCase:=AnsiUppercase}
  2097. {$define SRPCHAR:=PAnsiChar}
  2098. {$define SRCHAR:=AnsiChar}
  2099. Function StringReplace(const S, OldPattern, NewPattern: Ansistring; Flags: TReplaceFlags): Ansistring;
  2100. Var
  2101. C : Integer;
  2102. begin
  2103. Result:=StringReplace(S,OldPattern,NewPattern,Flags,C);
  2104. end;
  2105. function StringReplace(const S, OldPattern, NewPattern: Ansistring; Flags: TReplaceFlags; Out aCount : Integer): Ansistring;
  2106. {$i syssr.inc}
  2107. {$undef INSTRINGREPLACE}
  2108. {$undef SRString}
  2109. {$undef SRUpperCase}
  2110. {$undef SRPCHAR}
  2111. {$undef SRCHAR}
  2112. Function IsDelimiter(const Delimiters, S: string; Index: SizeInt): Boolean;
  2113. begin
  2114. Result:=False;
  2115. If (Index>0) and (Index<=Length(S)) then
  2116. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  2117. end;
  2118. Function ByteToCharLen(const S: string; MaxLen: SizeInt): SizeInt;
  2119. begin
  2120. Result:=Length(S);
  2121. If Result>MaxLen then
  2122. Result:=MaxLen;
  2123. end;
  2124. Function ByteToCharIndex(const S: string; Index: SizeInt): SizeInt;
  2125. begin
  2126. Result:=Index;
  2127. end;
  2128. Function CharToByteLen(const S: string; MaxLen: SizeInt): SizeInt;
  2129. begin
  2130. Result:=Length(S);
  2131. If Result>MaxLen then
  2132. Result:=MaxLen;
  2133. end;
  2134. Function CharToByteIndex(const S: string; Index: SizeInt): SizeInt;
  2135. begin
  2136. Result:=Index;
  2137. end;
  2138. Function ByteType(const S: string; Index: SizeUInt): TMbcsByteType;
  2139. begin
  2140. Result:=mbSingleByte;
  2141. end;
  2142. Function StrByteType(Str: PAnsiChar; Index: SizeUInt): TMbcsByteType;
  2143. begin
  2144. Result:=mbSingleByte;
  2145. end;
  2146. Function StrCharLength(const Str: PAnsiChar): SizeInt;
  2147. begin
  2148. result:=widestringmanager.CharLengthPCharProc(Str);
  2149. end;
  2150. function StrNextChar(const Str: PAnsiChar): PAnsiChar;
  2151. begin
  2152. result:=Str+StrCharLength(Str);
  2153. end;
  2154. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  2155. Var
  2156. I,L : Integer;
  2157. S,T : String;
  2158. begin
  2159. Result:=False;
  2160. S:=Switch;
  2161. If IgnoreCase then
  2162. S:=UpperCase(S);
  2163. I:=ParamCount;
  2164. While (Not Result) and (I>0) do
  2165. begin
  2166. L:=Length(Paramstr(I));
  2167. If (L>0) and (ParamStr(I)[1] in Chars) then
  2168. begin
  2169. T:=Copy(ParamStr(I),2,L-1);
  2170. If IgnoreCase then
  2171. T:=UpperCase(T);
  2172. Result:=S=T;
  2173. end;
  2174. Dec(i);
  2175. end;
  2176. end;
  2177. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  2178. begin
  2179. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  2180. end;
  2181. Function FindCmdLineSwitch(const Switch: string): Boolean;
  2182. begin
  2183. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  2184. end;
  2185. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
  2186. const
  2187. Quotes = ['''', '"'];
  2188. Var
  2189. L : String;
  2190. C,LQ,BC : AnsiChar;
  2191. P,BLen,Len : Integer;
  2192. HB,IBC : Boolean;
  2193. begin
  2194. Result:='';
  2195. L:=Line;
  2196. Blen:=Length(BreakStr);
  2197. If (BLen>0) then
  2198. BC:=BreakStr[1]
  2199. else
  2200. BC:=#0;
  2201. Len:=Length(L);
  2202. While (Len>0) do
  2203. begin
  2204. P:=1;
  2205. LQ:=#0;
  2206. HB:=False;
  2207. IBC:=False;
  2208. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  2209. begin
  2210. C:=L[P];
  2211. If (C=LQ) then
  2212. LQ:=#0
  2213. else If (C in Quotes) then
  2214. LQ:=C;
  2215. If (LQ<>#0) then
  2216. Inc(P)
  2217. else
  2218. begin
  2219. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  2220. If HB then
  2221. Inc(P,Blen)
  2222. else
  2223. begin
  2224. If (P>=MaxCol) then
  2225. IBC:=C in BreakChars;
  2226. Inc(P);
  2227. end;
  2228. end;
  2229. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2230. end;
  2231. Result:=Result+Copy(L,1,P-1);
  2232. Delete(L,1,P-1);
  2233. Len:=Length(L);
  2234. If (Len>0) and Not HB then
  2235. Result:=Result+BreakStr;
  2236. end;
  2237. end;
  2238. function WrapText(const Line: string; MaxCol: Integer): string;
  2239. begin
  2240. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2241. end;
  2242. {$ifndef FPC_NOGENERICANSIROUTINES}
  2243. {
  2244. Case Translation Tables
  2245. Can be used in internationalization support.
  2246. Although these tables can be obtained through system calls
  2247. cd it is better to not use those, since most implementation are not 100%
  2248. WARNING:
  2249. before modifying a translation table make sure that the current codepage
  2250. of the OS corresponds to the one you make changes to
  2251. }
  2252. const
  2253. {$if defined(MSDOS) or defined(GO32V2) or defined(WATCOM) or defined(WIN16) }
  2254. { upper case translation table for character set 850 }
  2255. CP850UCT: array[128..255] of AnsiChar =
  2256. (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
  2257. #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
  2258. #181,#214,#224,#233,#165,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2259. #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  2260. #192,#193,#194,#195,#196,#197,#199,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  2261. #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  2262. #224,#225,#226,#227,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
  2263. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2264. { lower case translation table for character set 850 }
  2265. CP850LCT: array[128..255] of AnsiChar =
  2266. (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
  2267. #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
  2268. #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2269. #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
  2270. #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
  2271. #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
  2272. #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
  2273. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2274. {$endif}
  2275. { upper case translation table for character set ISO 8859/1 Latin 1 }
  2276. CPISO88591UCT: array[192..255] of AnsiChar =
  2277. ( #192, #193, #194, #195, #196, #197, #198, #199,
  2278. #200, #201, #202, #203, #204, #205, #206, #207,
  2279. #208, #209, #210, #211, #212, #213, #214, #215,
  2280. #216, #217, #218, #219, #220, #221, #222, #223,
  2281. #192, #193, #194, #195, #196, #197, #198, #199,
  2282. #200, #201, #202, #203, #204, #205, #206, #207,
  2283. #208, #209, #210, #211, #212, #213, #214, #247,
  2284. #216, #217, #218, #219, #220, #221, #222, #89 );
  2285. { lower case translation table for character set ISO 8859/1 Latin 1 }
  2286. CPISO88591LCT: array[192..255] of AnsiChar =
  2287. ( #224, #225, #226, #227, #228, #229, #230, #231,
  2288. #232, #233, #234, #235, #236, #237, #238, #239,
  2289. #240, #241, #242, #243, #244, #245, #246, #215,
  2290. #248, #249, #250, #251, #252, #253, #254, #223,
  2291. #224, #225, #226, #227, #228, #229, #230, #231,
  2292. #232, #233, #234, #235, #236, #237, #238, #239,
  2293. #240, #241, #242, #243, #244, #245, #246, #247,
  2294. #248, #249, #250, #251, #252, #253, #254, #255 );
  2295. {$endif FPC_NOGENERICANSIROUTINES}
  2296. function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
  2297. var
  2298. i,j,n,m : SizeInt;
  2299. s1 : string;
  2300. function GetInt(unsigned : boolean=false) : Integer;
  2301. begin
  2302. s1 := '';
  2303. while (Length(s) > n) and (s[n] = ' ') do
  2304. inc(n);
  2305. { read sign }
  2306. if (Length(s)>= n) and (s[n] in ['+', '-']) then
  2307. begin
  2308. { don't accept - when reading unsigned }
  2309. if unsigned and (s[n]='-') then
  2310. begin
  2311. result:=length(s1);
  2312. exit;
  2313. end
  2314. else
  2315. begin
  2316. s1:=s1+s[n];
  2317. inc(n);
  2318. end;
  2319. end;
  2320. { read numbers }
  2321. while (Length(s) >= n) and
  2322. (s[n] in ['0'..'9']) do
  2323. begin
  2324. s1 := s1+s[n];
  2325. inc(n);
  2326. end;
  2327. Result := Length(s1);
  2328. end;
  2329. function GetFloat : Integer;
  2330. begin
  2331. s1 := '';
  2332. while (Length(s) > n) and (s[n] = ' ') do
  2333. inc(n);
  2334. while (Length(s) >= n) and
  2335. (s[n] in ['0'..'9', '+', '-', FormatSettings.DecimalSeparator, 'e', 'E']) do
  2336. begin
  2337. s1 := s1+s[n];
  2338. inc(n);
  2339. end;
  2340. Result := Length(s1);
  2341. end;
  2342. function GetString : Integer;
  2343. begin
  2344. s1 := '';
  2345. while (Length(s) > n) and (s[n] = ' ') do
  2346. inc(n);
  2347. while (Length(s) >= n) and (s[n] <> ' ')do
  2348. begin
  2349. s1 := s1+s[n];
  2350. inc(n);
  2351. end;
  2352. Result := Length(s1);
  2353. end;
  2354. function ScanStr(c : AnsiChar) : Boolean;
  2355. begin
  2356. while (Length(s) > n) and (s[n] <> c) do
  2357. inc(n);
  2358. inc(n);
  2359. If (n <= Length(s)) then
  2360. Result := True
  2361. else
  2362. Result := False;
  2363. end;
  2364. function GetFmt : Integer;
  2365. begin
  2366. Result := -1;
  2367. while true do
  2368. begin
  2369. while (Length(fmt) > m) and (fmt[m] = ' ') do
  2370. inc(m);
  2371. if (m >= Length(fmt)) then
  2372. break;
  2373. if (fmt[m] = '%') then
  2374. begin
  2375. inc(m);
  2376. case fmt[m] of
  2377. 'd':
  2378. Result:=vtInteger;
  2379. {$ifndef FPUNONE}
  2380. 'f':
  2381. Result:=vtExtended;
  2382. {$endif}
  2383. 's':
  2384. Result:=vtString;
  2385. 'c':
  2386. Result:=vtChar;
  2387. else
  2388. raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
  2389. end;
  2390. inc(m);
  2391. break;
  2392. end;
  2393. if not(ScanStr(fmt[m])) then
  2394. break;
  2395. inc(m);
  2396. end;
  2397. end;
  2398. begin
  2399. n := 1;
  2400. m := 1;
  2401. Result := 0;
  2402. for i:=0 to High(Pointers) do
  2403. begin
  2404. j := GetFmt;
  2405. case j of
  2406. vtInteger :
  2407. begin
  2408. if GetInt>0 then
  2409. begin
  2410. pLongint(Pointers[i])^:=StrToInt(s1);
  2411. inc(Result);
  2412. end
  2413. else
  2414. break;
  2415. end;
  2416. vtchar :
  2417. begin
  2418. if Length(s)>n then
  2419. begin
  2420. PChar(Pointers[i])^:=s[n];
  2421. inc(n);
  2422. inc(Result);
  2423. end
  2424. else
  2425. break;
  2426. end;
  2427. {$ifndef FPUNONE}
  2428. vtExtended :
  2429. begin
  2430. if GetFloat>0 then
  2431. begin
  2432. pextended(Pointers[i])^:=StrToFloat(s1);
  2433. inc(Result);
  2434. end
  2435. else
  2436. break;
  2437. end;
  2438. {$endif}
  2439. vtString :
  2440. begin
  2441. if GetString > 0 then
  2442. begin
  2443. pstring(Pointers[i])^:=s1;
  2444. inc(Result);
  2445. end
  2446. else
  2447. break;
  2448. end;
  2449. else
  2450. break;
  2451. end;
  2452. end;
  2453. end;
  2454. {$macro on}
  2455. // Ansi version declaration
  2456. {$UNDEF SBUNICODE}
  2457. {$define SBChar:=AnsiChar}
  2458. {$define SBString:=AnsiString}
  2459. {$define TSBCharArray:=Array of SBChar}
  2460. {$define PSBChar:=PAnsiChar}
  2461. {$define SBRAWString:=RawByteString}
  2462. {$define TGenericStringBuilder:=TAnsiStringBuilder}
  2463. {$i syssb.inc}
  2464. {$undef SBChar}
  2465. {$undef SBString}
  2466. {$undef TSBCharArray}
  2467. {$undef PSBChar}
  2468. {$undef SBRAWString}
  2469. {$undef TGenericStringBuilder}
  2470. // Unicode version declaration
  2471. {$define SBUNICODE}
  2472. {$define SBChar:=WideChar}
  2473. {$define SBString:=UnicodeString}
  2474. {$define TSBCharArray:=Array of SBChar}
  2475. {$define PSBChar:=PWideChar}
  2476. {$define SBRAWString:=UnicodeString}
  2477. {$define TGenericStringBuilder:=TUnicodeStringBuilder}
  2478. {$i syssb.inc}
  2479. {$undef SBChar}
  2480. {$undef SBString}
  2481. {$undef TSBCharArray}
  2482. {$undef PSBChar}
  2483. {$undef SBRAWString}
  2484. {$undef TGenericStringBuilder}
  2485. {$undef SBUNICODE}