2
0

sysstr.inc 75 KB

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