sysstr.inc 68 KB

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