sysstr.inc 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747
  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. function UIntToStr(Value: QWord): string;
  721. begin
  722. result:=IntTostr(Value);
  723. end;
  724. function UIntToStr(Value: Cardinal): string;
  725. begin
  726. System.Str(Value, result);
  727. end;
  728. { IntToHex returns a string representing the hexadecimal value of Value }
  729. const
  730. HexDigits: array[0..15] of char = '0123456789ABCDEF';
  731. function IntToHex(Value: Longint; Digits: integer): string;
  732. var i: integer;
  733. begin
  734. If Digits=0 then
  735. Digits:=1;
  736. SetLength(result, digits);
  737. for i := 0 to digits - 1 do
  738. begin
  739. result[digits - i] := HexDigits[value and 15];
  740. value := value shr 4;
  741. end ;
  742. while value <> 0 do begin
  743. result := HexDigits[value and 15] + result;
  744. value := value shr 4;
  745. end;
  746. end ;
  747. function IntToHex(Value: int64; Digits: integer): string;
  748. var i: integer;
  749. begin
  750. If Digits=0 then
  751. Digits:=1;
  752. SetLength(result, digits);
  753. for i := 0 to digits - 1 do
  754. begin
  755. result[digits - i] := HexDigits[value and 15];
  756. value := value shr 4;
  757. end ;
  758. while value <> 0 do begin
  759. result := HexDigits[value and 15] + result;
  760. value := value shr 4;
  761. end;
  762. end ;
  763. function IntToHex(Value: QWord; Digits: integer): string;
  764. begin
  765. result:=IntToHex(Int64(Value),Digits);
  766. end;
  767. function TryStrToInt(const s: string; out i : Longint) : boolean;
  768. var Error : word;
  769. begin
  770. Val(s, i, Error);
  771. TryStrToInt:=Error=0
  772. end;
  773. { StrToInt converts the string S to an integer value,
  774. if S does not represent a valid integer value EConvertError is raised }
  775. function StrToInt(const S: string): Longint;
  776. var Error: word;
  777. begin
  778. Val(S, result, Error);
  779. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  780. end ;
  781. function StrToInt64(const S: string): int64;
  782. var Error: word;
  783. begin
  784. Val(S, result, Error);
  785. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  786. end;
  787. function TryStrToInt64(const s: string; Out i : int64) : boolean;
  788. var Error : word;
  789. begin
  790. Val(s, i, Error);
  791. TryStrToInt64:=Error=0
  792. end;
  793. function StrToQWord(const s: string): QWord;
  794. var Error: word;
  795. begin
  796. Val(S, result, Error);
  797. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  798. end;
  799. function StrToUInt64(const s: string): UInt64;
  800. begin
  801. result:=StrToQWord(s);
  802. end;
  803. function StrToDWord(const s: string): DWord;
  804. var Error: word;
  805. begin
  806. Val(S, result, Error);
  807. if Error <> 0 then raise EConvertError.createfmt(SInvalidInteger,[S]);
  808. end;
  809. function TryStrToDWord(const s: string; Out D: DWord): boolean;
  810. var Error : word;
  811. begin
  812. Val(s, D, Error);
  813. TryStrToDWord:=Error=0
  814. end;
  815. function TryStrToQWord(const s: string; Out Q: QWord): boolean;
  816. var Error : word;
  817. begin
  818. Val(s, Q, Error);
  819. TryStrToQWord:=Error=0
  820. end;
  821. function TryStrToUInt64(const s: string; Out u: UInt64): boolean;
  822. begin
  823. result:=TryStrToQWord(s,u);
  824. end;
  825. { StrToIntDef converts the string S to an integer value,
  826. Default is returned in case S does not represent a valid integer value }
  827. function StrToIntDef(const S: string; Default: Longint): Longint;
  828. var Error: word;
  829. begin
  830. Val(S, result, Error);
  831. if Error <> 0 then result := Default;
  832. end ;
  833. { StrToDWordDef converts the string S to an DWord value,
  834. Default is returned in case S does not represent a valid DWord value }
  835. function StrToDWordDef(const S: string; Default: DWord): DWord;
  836. var Error: word;
  837. begin
  838. Val(S, result, Error);
  839. if Error <> 0 then result := Default;
  840. end;
  841. { StrToInt64Def converts the string S to an int64 value,
  842. Default is returned in case S does not represent a valid int64 value }
  843. function StrToInt64Def(const S: string; Default: int64): int64;
  844. var Error: word;
  845. begin
  846. Val(S, result, Error);
  847. if Error <> 0 then result := Default;
  848. end ;
  849. { StrToQWordDef converts the string S to an QWord value,
  850. Default is returned in case S does not represent a valid QWord value }
  851. function StrToQWordDef(const S: string; Default: QWord): QWord;
  852. var Error: word;
  853. begin
  854. Val(S, result, Error);
  855. if Error <> 0 then result := Default;
  856. end;
  857. function StrToUInt64Def(const S: string; Default: UInt64): UInt64;
  858. begin
  859. result:=StrToQWordDef(S,Default);
  860. end;
  861. { LoadStr returns the string resource Ident. }
  862. function LoadStr(Ident: integer): string;
  863. begin
  864. result:='';
  865. end ;
  866. { FmtLoadStr returns the string resource Ident and formats it accordingly }
  867. function FmtLoadStr(Ident: integer; const Args: array of const): string;
  868. begin
  869. result:='';
  870. end;
  871. Const
  872. feInvalidFormat = 1;
  873. feMissingArgument = 2;
  874. feInvalidArgIndex = 3;
  875. {$ifdef fmtdebug}
  876. Procedure Log (Const S: String);
  877. begin
  878. Writeln (S);
  879. end;
  880. {$endif}
  881. Procedure DoFormatError (ErrCode : Longint;const fmt:ansistring);
  882. Var
  883. S : String;
  884. begin
  885. //!! must be changed to contain format string...
  886. S:=fmt;
  887. Case ErrCode of
  888. feInvalidFormat : raise EConvertError.Createfmt(SInvalidFormat,[s]);
  889. feMissingArgument : raise EConvertError.Createfmt(SArgumentMissing,[s]);
  890. feInvalidArgIndex : raise EConvertError.Createfmt(SInvalidArgIndex,[s]);
  891. end;
  892. end;
  893. { we've no templates, but with includes we can simulate this :) }
  894. {$macro on}
  895. {$define INFORMAT}
  896. {$define TFormatString:=ansistring}
  897. {$define TFormatChar:=char}
  898. Function Format (Const Fmt : AnsiString; const Args : Array of const; const FormatSettings: TFormatSettings) : AnsiString;
  899. {$i sysformt.inc}
  900. {$undef TFormatString}
  901. {$undef TFormatChar}
  902. {$undef INFORMAT}
  903. {$macro off}
  904. Function Format (Const Fmt : AnsiString; const Args : Array of const) : AnsiString;
  905. begin
  906. Result:=Format(Fmt,Args,DefaultFormatSettings);
  907. end;
  908. Function FormatBuf (Var Buffer; BufLen : Cardinal; Const Fmt; fmtLen : Cardinal; Const Args : Array of const; Const FormatSettings: TFormatSettings) : Cardinal;
  909. Var S,F : String;
  910. begin
  911. Setlength(F,fmtlen);
  912. if fmtlen > 0 then
  913. Move(fmt,F[1],fmtlen);
  914. S:=Format (F,Args,FormatSettings);
  915. If Cardinal(Length(S))<Buflen then
  916. Result:=Length(S)
  917. else
  918. Result:=Buflen;
  919. Move(S[1],Buffer,Result);
  920. end;
  921. Function FormatBuf (Var Buffer; BufLen : Cardinal;
  922. Const Fmt; fmtLen : Cardinal;
  923. Const Args : Array of const) : Cardinal;
  924. begin
  925. Result:=FormatBuf(Buffer,BufLen,Fmt,FmtLen,Args,DefaultFormatSettings);
  926. end;
  927. Procedure FmtStr(Var Res: string; const Fmt : string; Const args: Array of const; Const FormatSettings: TFormatSettings);
  928. begin
  929. Res:=Format(fmt,Args,FormatSettings);
  930. end;
  931. Procedure FmtStr(Var Res: String; Const Fmt : String; Const args: Array of const);
  932. begin
  933. FmtStr(Res,Fmt,Args,DefaultFormatSettings);
  934. end;
  935. Function StrFmt(Buffer,Fmt : PChar; Const args: Array of const) : Pchar;
  936. begin
  937. Result:=StrFmt(Buffer,Fmt,Args,DefaultFormatSettings);
  938. end;
  939. Function StrFmt(Buffer,Fmt : PChar; Const Args: Array of const; Const FormatSettings: TFormatSettings): PChar;
  940. begin
  941. Buffer[FormatBuf(Buffer^,Maxint,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
  942. Result:=Buffer;
  943. end;
  944. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const) : Pchar;
  945. begin
  946. Result:=StrLFmt(Buffer,MaxLen,Fmt,Args,DefaultFormatSettings);
  947. end;
  948. Function StrLFmt(Buffer : PCHar; Maxlen : Cardinal;Fmt : PChar; Const args: Array of const; Const FormatSettings: TFormatSettings) : Pchar;
  949. begin
  950. Buffer[FormatBuf(Buffer^,MaxLen,Fmt^,strlen(fmt),args,FormatSettings)]:=#0;
  951. Result:=Buffer;
  952. end;
  953. {$ifndef FPUNONE}
  954. Function StrToFloat(Const S: String): Extended;
  955. begin
  956. Result:=StrToFloat(S,DefaultFormatSettings);
  957. end;
  958. Function StrToFloat(Const S : String; Const FormatSettings: TFormatSettings) : Extended;
  959. Begin // texttofloat handles NIL properly
  960. If Not TextToFloat(Pchar(pointer(S)),Result,FormatSettings) then
  961. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  962. End;
  963. function StrToFloatDef(const S: string; const Default: Extended): Extended;
  964. begin
  965. Result:=StrToFloatDef(S,Default,DefaultFormatSettings);
  966. end;
  967. Function StrToFloatDef(Const S: String; Const Default: Extended; Const FormatSettings: TFormatSettings): Extended;
  968. begin
  969. if not TextToFloat(PChar(pointer(S)),Result,fvExtended,FormatSettings) then
  970. Result:=Default;
  971. end;
  972. Function TextToFloat(Buffer: PChar; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  973. Var
  974. E,P : Integer;
  975. S : String;
  976. Begin
  977. S:=StrPas(Buffer);
  978. //ThousandSeparator not allowed as by Delphi specs
  979. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  980. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  981. begin
  982. Result := False;
  983. Exit;
  984. end;
  985. if (FormatSettings.DecimalSeparator <> '.') and
  986. (Pos('.', S) <>0) then
  987. begin
  988. Result := False;
  989. Exit;
  990. end;
  991. P:=Pos(FormatSettings.DecimalSeparator,S);
  992. If (P<>0) Then
  993. S[P] := '.';
  994. Val(trim(S),Value,E);
  995. Result:=(E=0);
  996. End;
  997. Function TextToFloat(Buffer: PChar; Out Value: Extended): Boolean;
  998. begin
  999. Result:=TextToFloat(Buffer,Value,DefaultFormatSettings);
  1000. end;
  1001. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue): Boolean;
  1002. begin
  1003. Result:=TextToFloat(Buffer,Value,ValueType,DefaultFormatSettings);
  1004. end;
  1005. Function TextToFloat(Buffer: PChar; Out Value; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): Boolean;
  1006. Var
  1007. E,P : Integer;
  1008. S : String;
  1009. Begin
  1010. S:=StrPas(Buffer);
  1011. //ThousandSeparator not allowed as by Delphi specs
  1012. if (FormatSettings.ThousandSeparator <> FormatSettings.DecimalSeparator) and
  1013. (Pos(FormatSettings.ThousandSeparator, S) <> 0) then
  1014. begin
  1015. Result := False;
  1016. Exit;
  1017. end;
  1018. if (FormatSettings.DecimalSeparator <> '.') and
  1019. (Pos('.', S) <>0) then
  1020. begin
  1021. Result := False;
  1022. Exit;
  1023. end;
  1024. P:=Pos(FormatSettings.DecimalSeparator,S);
  1025. If (P<>0) Then
  1026. S[P] := '.';
  1027. s:=Trim(s);
  1028. try
  1029. case ValueType of
  1030. fvCurrency:
  1031. Val(S,Currency(Value),E);
  1032. fvExtended:
  1033. Val(S,Extended(Value),E);
  1034. fvDouble:
  1035. Val(S,Double(Value),E);
  1036. fvSingle:
  1037. Val(S,Single(Value),E);
  1038. fvComp:
  1039. Val(S,Comp(Value),E);
  1040. fvReal:
  1041. Val(S,Real(Value),E);
  1042. end;
  1043. { on x87, a floating point exception may be pending in case of an invalid
  1044. input value -> trigger it now }
  1045. {$ifdef cpux86}
  1046. asm
  1047. fwait
  1048. end;
  1049. {$endif}
  1050. except
  1051. E:=1;
  1052. end;
  1053. Result:=(E=0);
  1054. End;
  1055. Function TryStrToFloat(Const S : String; Out Value: Single): Boolean;
  1056. begin
  1057. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1058. end;
  1059. Function TryStrToFloat(Const S : String; Out Value: Single; Const FormatSettings: TFormatSettings): Boolean;
  1060. Begin
  1061. Result := TextToFloat(PChar(pointer(S)), Value, fvSingle,FormatSettings);
  1062. End;
  1063. Function TryStrToFloat(Const S : String; Out Value: Double): Boolean;
  1064. begin
  1065. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1066. end;
  1067. Function TryStrToFloat(Const S : String; Out Value: Double; Const FormatSettings: TFormatSettings): Boolean;
  1068. Begin
  1069. Result := TextToFloat(PChar(pointer(S)), Value, fvDouble,FormatSettings);
  1070. End;
  1071. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1072. Function TryStrToFloat(Const S : String; Out Value: Extended): Boolean;
  1073. begin
  1074. Result:=TryStrToFloat(S,Value,DefaultFormatSettings);
  1075. end;
  1076. Function TryStrToFloat(Const S : String; Out Value: Extended; Const FormatSettings: TFormatSettings): Boolean;
  1077. Begin
  1078. Result := TextToFloat(PChar(pointer(S)), Value,FormatSettings);
  1079. End;
  1080. {$endif FPC_HAS_TYPE_EXTENDED}
  1081. const
  1082. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1083. maxdigits = 17;
  1084. {$else}
  1085. maxdigits = 15;
  1086. {$endif}
  1087. { deactive aligned function for 2.6 }
  1088. {$ifdef VER2_6}
  1089. {$macro on}
  1090. {$define aligned:= }
  1091. {$endif VER2_6}
  1092. Function FloatToStrFIntl(const Value; format: TFloatFormat; Precision, Digits: Integer; ValueType: TFloatValue; Const FormatSettings: TFormatSettings): String;
  1093. Var
  1094. P, PE, Q, Exponent: Integer;
  1095. Negative: Boolean;
  1096. DS: Char;
  1097. function RemoveLeadingNegativeSign(var AValue: String): Boolean;
  1098. // removes negative sign in case when result is zero eg. -0.00
  1099. var
  1100. i: PtrInt;
  1101. TS: Char;
  1102. StartPos: PtrInt;
  1103. begin
  1104. Result := False;
  1105. if Format = ffCurrency then
  1106. StartPos := 1
  1107. else
  1108. StartPos := 2;
  1109. TS := FormatSettings.ThousandSeparator;
  1110. for i := StartPos to length(AValue) do
  1111. begin
  1112. Result := (AValue[i] in ['0', DS, 'E', '+', TS]);
  1113. if not Result then
  1114. break;
  1115. end;
  1116. if (Result) and (Format <> ffCurrency) then
  1117. Delete(AValue, 1, 1);
  1118. end;
  1119. Begin
  1120. DS:=FormatSettings.DecimalSeparator;
  1121. Case format Of
  1122. ffGeneral:
  1123. Begin
  1124. case ValueType of
  1125. fvCurrency:
  1126. If (Precision = -1) Or (Precision > 19) Then Precision := 19;
  1127. else
  1128. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1129. end;
  1130. { First convert to scientific format, with correct precision }
  1131. case ValueType of
  1132. fvDouble:
  1133. Str(Double(Extended(Aligned(Value))):precision+7, Result);
  1134. fvSingle:
  1135. Str(Single(Extended(Aligned(Value))):precision+6, Result);
  1136. fvCurrency:
  1137. Str(Currency(Aligned(Value)):precision+6, Result);
  1138. else
  1139. Str(Extended(Aligned(Value)):precision+8, Result);
  1140. end;
  1141. { Delete leading spaces }
  1142. while Result[1] = ' ' do
  1143. System.Delete(Result, 1, 1);
  1144. P := Pos('.', Result);
  1145. if P<>0 then
  1146. Result[P] := DS
  1147. else
  1148. Exit; { NAN or other special case }
  1149. { Consider removing exponent }
  1150. PE:=Pos('E',Result);
  1151. if PE > 0 then begin
  1152. { Read exponent }
  1153. Q := PE+2;
  1154. Exponent := 0;
  1155. while (Q <= Length(Result)) do begin
  1156. Exponent := Exponent*10 + Ord(Result[Q])-Ord('0');
  1157. Inc(Q);
  1158. end;
  1159. if Result[PE+1] = '-' then
  1160. Exponent := -Exponent;
  1161. if (P+Exponent < PE) and (Exponent > -6) then begin
  1162. { OK to remove exponent }
  1163. SetLength(Result,PE-1); { Trim exponent }
  1164. if Exponent >= 0 then begin
  1165. { Shift point to right }
  1166. for Q := 0 to Exponent-1 do begin
  1167. Result[P] := Result[P+1];
  1168. Inc(P);
  1169. end;
  1170. Result[P] := DS;
  1171. P := 1;
  1172. if Result[P] = '-' then
  1173. Inc(P);
  1174. while (Result[P] = '0') and (P < Length(Result)) and (Result[P+1] <> DS) do
  1175. { Trim leading zeros; conversion above should not give any, but occasionally does
  1176. because of rounding }
  1177. System.Delete(Result,P,1);
  1178. end else begin
  1179. { Add zeros at start }
  1180. Insert(Copy('00000',1,-Exponent),Result,P-1);
  1181. Result[P-Exponent] := Result[P-Exponent-1]; { Copy leading digit }
  1182. Result[P] := DS;
  1183. if Exponent <> -1 then
  1184. Result[P-Exponent-1] := '0';
  1185. end;
  1186. { Remove trailing zeros }
  1187. Q := Length(Result);
  1188. while (Q > 0) and (Result[Q] = '0') do
  1189. Dec(Q);
  1190. if Result[Q] = DS then
  1191. Dec(Q); { Remove trailing decimal point }
  1192. if (Q = 0) or ((Q=1) and (Result[1] = '-')) then
  1193. Result := '0'
  1194. else
  1195. SetLength(Result,Q);
  1196. end else begin
  1197. { Need exponent, but remove superfluous characters }
  1198. { Delete trailing zeros }
  1199. while Result[PE-1] = '0' do begin
  1200. System.Delete(Result,PE-1,1);
  1201. Dec(PE);
  1202. end;
  1203. { If number ends in decimal point, remove it }
  1204. if Result[PE-1] = DS then begin
  1205. System.Delete(Result,PE-1,1);
  1206. Dec(PE);
  1207. end;
  1208. { delete superfluous + in exponent }
  1209. if Result[PE+1]='+' then
  1210. System.Delete(Result,PE+1,1)
  1211. else
  1212. Inc(PE);
  1213. while Result[PE+1] = '0' do
  1214. { Delete leading zeros in exponent }
  1215. System.Delete(Result,PE+1,1)
  1216. end;
  1217. end;
  1218. End;
  1219. ffExponent:
  1220. Begin
  1221. If (Precision = -1) Or (Precision > maxdigits) Then Precision := maxdigits;
  1222. case ValueType of
  1223. fvDouble:
  1224. Str(Double(Extended(Aligned(Value))):Precision+7, Result);
  1225. fvSingle:
  1226. Str(Single(Extended(Aligned(Value))):Precision+6, Result);
  1227. fvCurrency:
  1228. Str(Currency(Aligned(Value)):Precision+6, Result);
  1229. else
  1230. Str(Extended(Aligned(Value)):Precision+8, Result);
  1231. end;
  1232. { Delete leading spaces }
  1233. while Result[1] = ' ' do
  1234. System.Delete(Result, 1, 1);
  1235. if (Result[1]='-') and
  1236. { not Nan etc.? }
  1237. (Result[3]='.') then
  1238. Result[3] := DS
  1239. else if Result[2]='.' then
  1240. Result[2] := DS;
  1241. P:=Pos('E',Result);
  1242. if P <> 0 then
  1243. begin
  1244. Inc(P, 2);
  1245. if Digits > 4 then
  1246. Digits:=4;
  1247. Digits:=Length(Result) - P - Digits + 1;
  1248. if Digits < 0 then
  1249. insert(copy('0000',1,-Digits),Result,P)
  1250. else
  1251. while (Digits > 0) and (Result[P] = '0') do
  1252. begin
  1253. System.Delete(Result, P, 1);
  1254. if P > Length(Result) then
  1255. begin
  1256. System.Delete(Result, P - 2, 2);
  1257. break;
  1258. end;
  1259. Dec(Digits);
  1260. end;
  1261. end;
  1262. End;
  1263. ffFixed:
  1264. Begin
  1265. If Digits = -1 Then Digits := 2
  1266. Else If Digits > 18 Then Digits := 18;
  1267. case ValueType of
  1268. fvDouble:
  1269. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1270. fvSingle:
  1271. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1272. fvCurrency:
  1273. Str(Currency(Aligned(Value)):0:Digits, Result);
  1274. else
  1275. Str(Extended(Aligned(Value)):0:Digits, Result);
  1276. end;
  1277. If Result[1] = ' ' Then
  1278. System.Delete(Result, 1, 1);
  1279. P := Pos('.', Result);
  1280. If P <> 0 Then Result[P] := DS;
  1281. End;
  1282. ffNumber:
  1283. Begin
  1284. If Digits = -1 Then Digits := 2
  1285. Else If Digits > maxdigits Then Digits := maxdigits;
  1286. case ValueType of
  1287. fvDouble:
  1288. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1289. fvSingle:
  1290. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1291. fvCurrency:
  1292. Str(Currency(Aligned(Value)):0:Digits, Result);
  1293. else
  1294. Str(Extended(Aligned(Value)):0:Digits, Result);
  1295. end;
  1296. If Result[1] = ' ' Then System.Delete(Result, 1, 1);
  1297. P := Pos('.', Result);
  1298. If P <> 0 Then
  1299. Result[P] := DS
  1300. else
  1301. P := Length(Result)+1;
  1302. Dec(P, 3);
  1303. While (P > 1) Do
  1304. Begin
  1305. If (Result[P - 1] <> '-') And (FormatSettings.ThousandSeparator <> #0) Then
  1306. Insert(FormatSettings.ThousandSeparator, Result, P);
  1307. Dec(P, 3);
  1308. End;
  1309. End;
  1310. ffCurrency:
  1311. Begin
  1312. If Digits = -1 Then Digits := FormatSettings.CurrencyDecimals
  1313. Else If Digits > 18 Then Digits := 18;
  1314. case ValueType of
  1315. fvDouble:
  1316. Str(Double(Extended(Aligned(Value))):0:Digits, Result);
  1317. fvSingle:
  1318. Str(Single(Extended(Aligned(Value))):0:Digits, Result);
  1319. fvCurrency:
  1320. Str(Currency(Aligned(Value)):0:Digits, Result);
  1321. else
  1322. Str(Extended(Aligned(Value)):0:Digits, Result);
  1323. end;
  1324. Negative:=Result[1] = '-';
  1325. if Negative then
  1326. System.Delete(Result, 1, 1);
  1327. P := Pos('.', Result);
  1328. If P <> 0 Then Result[P] := DS else P := Length(Result)+1;
  1329. Dec(P, 3);
  1330. While (P > 1) Do
  1331. Begin
  1332. If FormatSettings.ThousandSeparator<>#0 Then
  1333. Insert(FormatSettings.ThousandSeparator, Result, P);
  1334. Dec(P, 3);
  1335. End;
  1336. if (length(Result) > 1) and Negative then
  1337. Negative := not RemoveLeadingNegativeSign(Result);
  1338. If Not Negative Then
  1339. Begin
  1340. Case FormatSettings.CurrencyFormat Of
  1341. 0: Result := FormatSettings.CurrencyString + Result;
  1342. 1: Result := Result + FormatSettings.CurrencyString;
  1343. 2: Result := FormatSettings.CurrencyString + ' ' + Result;
  1344. 3: Result := Result + ' ' + FormatSettings.CurrencyString;
  1345. End
  1346. End
  1347. Else
  1348. Begin
  1349. Case FormatSettings.NegCurrFormat Of
  1350. 0: Result := '(' + FormatSettings.CurrencyString + Result + ')';
  1351. 1: Result := '-' + FormatSettings.CurrencyString + Result;
  1352. 2: Result := FormatSettings.CurrencyString + '-' + Result;
  1353. 3: Result := FormatSettings.CurrencyString + Result + '-';
  1354. 4: Result := '(' + Result + FormatSettings.CurrencyString + ')';
  1355. 5: Result := '-' + Result + FormatSettings.CurrencyString;
  1356. 6: Result := Result + '-' + FormatSettings.CurrencyString;
  1357. 7: Result := Result + FormatSettings.CurrencyString + '-';
  1358. 8: Result := '-' + Result + ' ' + FormatSettings.CurrencyString;
  1359. 9: Result := '-' + FormatSettings.CurrencyString + ' ' + Result;
  1360. 10: Result := Result + ' ' + FormatSettings.CurrencyString + '-';
  1361. 11: Result := FormatSettings.CurrencyString + ' ' + Result + '-';
  1362. 12: Result := FormatSettings.CurrencyString + ' ' + '-' + Result;
  1363. 13: Result := Result + '-' + ' ' + FormatSettings.CurrencyString;
  1364. 14: Result := '(' + FormatSettings.CurrencyString + ' ' + Result + ')';
  1365. 15: Result := '(' + Result + ' ' + FormatSettings.CurrencyString + ')';
  1366. End;
  1367. End;
  1368. End;
  1369. End;
  1370. if not (format in [ffCurrency]) and (length(Result) > 1) and (Result[1] = '-') then
  1371. RemoveLeadingNegativeSign(Result);
  1372. End;
  1373. {$macro off}
  1374. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1375. Function FloatToStr(Value: Extended; Const FormatSettings: TFormatSettings): String;
  1376. Begin
  1377. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvExtended,FormatSettings);
  1378. End;
  1379. Function FloatToStr(Value: Extended): String;
  1380. begin
  1381. Result:=FloatToStr(Value,DefaultFormatSettings);
  1382. end;
  1383. {$endif FPC_HAS_TYPE_EXTENDED}
  1384. Function FloatToStr(Value: Currency; Const FormatSettings: TFormatSettings): String;
  1385. Begin
  1386. Result := FloatToStrFIntl(Value, ffGeneral, 15, 0, fvCurrency,FormatSettings);
  1387. End;
  1388. Function FloatToStr(Value: Currency): String;
  1389. begin
  1390. Result:=FloatToStr(Value,DefaultFormatSettings);
  1391. end;
  1392. Function FloatToStr(Value: Double; Const FormatSettings: TFormatSettings): String;
  1393. var
  1394. e: Extended;
  1395. Begin
  1396. e := Value;
  1397. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvDouble,FormatSettings);
  1398. End;
  1399. Function FloatToStr(Value: Double): String;
  1400. begin
  1401. Result:=FloatToStr(Value,DefaultFormatSettings);
  1402. end;
  1403. Function FloatToStr(Value: Single; Const FormatSettings: TFormatSettings): String;
  1404. var
  1405. e: Extended;
  1406. Begin
  1407. e := Value;
  1408. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvSingle,FormatSettings);
  1409. End;
  1410. Function FloatToStr(Value: Single): String;
  1411. begin
  1412. Result:=FloatToStr(Value,DefaultFormatSettings);
  1413. end;
  1414. Function FloatToStr(Value: Comp; Const FormatSettings: TFormatSettings): String;
  1415. var
  1416. e: Extended;
  1417. Begin
  1418. e := Value;
  1419. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1420. End;
  1421. Function FloatToStr(Value: Comp): String;
  1422. begin
  1423. Result:=FloatToStr(Value,DefaultFormatSettings);
  1424. end;
  1425. {$ifndef FPC_COMP_IS_INT64}
  1426. Function FloatToStr(Value: Int64): String;
  1427. begin
  1428. Result:=FloatToStr(Value,DefaultFormatSettings);
  1429. end;
  1430. Function FloatToStr(Value: Int64; Const FormatSettings: TFormatSettings): String;
  1431. var
  1432. e: Extended;
  1433. Begin
  1434. e := Comp(Value);
  1435. Result := FloatToStrFIntl(e, ffGeneral, 15, 0, fvComp,FormatSettings);
  1436. End;
  1437. {$endif FPC_COMP_IS_INT64}
  1438. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): Longint;
  1439. Var
  1440. Tmp: String[40];
  1441. Begin
  1442. Tmp := FloatToStrF(Value, format, Precision, Digits,FormatSettings);
  1443. Result := Length(Tmp);
  1444. Move(Tmp[1], Buffer[0], Result);
  1445. End;
  1446. Function FloatToText(Buffer: PChar; Value: Extended; format: TFloatFormat; Precision, Digits: Integer): Longint;
  1447. begin
  1448. Result:=FloatToText(Buffer,Value,Format,Precision,Digits,DefaultFormatSettings);
  1449. end;
  1450. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1451. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1452. begin
  1453. Result := FloatToStrFIntl(value,format,precision,digits,fvExtended,FormatSettings);
  1454. end;
  1455. Function FloatToStrF(Value: Extended; format: TFloatFormat; Precision, Digits: Integer): String;
  1456. begin
  1457. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1458. end;
  1459. {$endif}
  1460. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1461. begin
  1462. Result := FloatToStrFIntl(value,format,precision,digits,fvCurrency,FormatSettings);
  1463. end;
  1464. Function FloatToStrF(Value: Currency; format: TFloatFormat; Precision, Digits: Integer): String;
  1465. begin
  1466. Result:=FloatToStrF(Value,format,Precision,Digits,DefaultFormatSettings);
  1467. end;
  1468. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1469. var
  1470. e: Extended;
  1471. begin
  1472. e := Value;
  1473. result := FloatToStrFIntl(e,format,precision,digits,fvDouble,FormatSettings);
  1474. end;
  1475. Function FloatToStrF(Value: Double; format: TFloatFormat; Precision, Digits: Integer): String;
  1476. begin
  1477. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1478. end;
  1479. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1480. var
  1481. e: Extended;
  1482. begin
  1483. e:=Value;
  1484. result := FloatToStrFIntl(e,format,precision,digits,fvSingle,FormatSettings);
  1485. end;
  1486. Function FloatToStrF(Value: Single; format: TFloatFormat; Precision, Digits: Integer): String;
  1487. begin
  1488. Result:= FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1489. end;
  1490. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1491. var
  1492. e: Extended;
  1493. begin
  1494. e := Value;
  1495. Result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1496. end;
  1497. Function FloatToStrF(Value: Comp; format: TFloatFormat; Precision, Digits: Integer): String;
  1498. begin
  1499. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1500. end;
  1501. {$ifndef FPC_COMP_IS_INT64}
  1502. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer; Const FormatSettings: TFormatSettings): String;
  1503. var
  1504. e: Extended;
  1505. begin
  1506. e := Comp(Value);
  1507. result := FloatToStrFIntl(e,format,precision,digits,fvComp,FormatSettings);
  1508. end;
  1509. Function FloatToStrF(Value: Int64; format: TFloatFormat; Precision, Digits: Integer): String;
  1510. begin
  1511. Result:=FloatToStrF(Value,Format,Precision,Digits,DefaultFormatSettings);
  1512. end;
  1513. {$endif FPC_COMP_IS_INT64}
  1514. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; Const FormatSettings: TFormatSettings): string;
  1515. begin
  1516. result:=FloatToStrF(Value,Format,19,Digits,FormatSettings);
  1517. end;
  1518. Function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string;
  1519. begin
  1520. Result:=CurrToStrF(Value,Format,Digits,DefaultFormatSettings);
  1521. end;
  1522. Function FloatToDateTime (Const Value : Extended) : TDateTime;
  1523. begin
  1524. If (Value<MinDateTime) or (Value>MaxDateTime) then
  1525. Raise EConvertError.CreateFmt (SInvalidDateTime,[Value]);
  1526. Result:=Value;
  1527. end;
  1528. function TryFloatToCurr(const Value: Extended; var AResult: Currency): Boolean;
  1529. begin
  1530. Result:=(Value>=MinCurrency) and (Value<=MaxCurrency);
  1531. if Result then
  1532. AResult := Value;
  1533. end;
  1534. function FloatToCurr(const Value: Extended): Currency;
  1535. begin
  1536. if not TryFloatToCurr(Value, Result) then
  1537. Raise EConvertError.CreateFmt(SInvalidCurrency, [FloatToStr(Value)]);
  1538. end;
  1539. Function CurrToStr(Value: Currency): string;
  1540. begin
  1541. Result:=FloatToStrF(Value,ffGeneral,-1,0);
  1542. end;
  1543. Function CurrToStr(Value: Currency; Const FormatSettings: TFormatSettings): string;
  1544. begin
  1545. Result:=FloatToStrF(Value,ffGeneral,-1,0,FormatSettings);
  1546. end;
  1547. function StrToCurr(const S: string): Currency;
  1548. begin
  1549. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1550. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1551. end;
  1552. function StrToCurr(const S: string; Const FormatSettings: TFormatSettings): Currency;
  1553. begin
  1554. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
  1555. Raise EConvertError.createfmt(SInValidFLoat,[S]);
  1556. end;
  1557. Function TryStrToCurr(Const S : String; Out Value: Currency): Boolean;
  1558. Begin
  1559. Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency);
  1560. End;
  1561. function TryStrToCurr(const S: string;Out Value : Currency; Const FormatSettings: TFormatSettings): Boolean;
  1562. Begin
  1563. Result := TextToFloat(PChar(pointer(S)), Value, fvCurrency,FormatSettings);
  1564. End;
  1565. function StrToCurrDef(const S: string; Default : Currency): Currency;
  1566. begin
  1567. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency) then
  1568. Result:=Default;
  1569. end;
  1570. function StrToCurrDef(const S: string; Default : Currency; Const FormatSettings: TFormatSettings): Currency;
  1571. begin
  1572. if not TextToFloat(PChar(pointer(S)), Result, fvCurrency,FormatSettings) then
  1573. Result:=Default;
  1574. end;
  1575. {$endif FPUNONE}
  1576. function AnsiDequotedStr(const S: string; AQuote: Char): string;
  1577. var p : pchar;
  1578. begin
  1579. p:=pchar(pointer(s)); // work around CONST. Ansiextract is safe for nil
  1580. result:=AnsiExtractquotedStr(p,AQuote);
  1581. end;
  1582. function StrToBool(const S: string): Boolean;
  1583. begin
  1584. if not(TryStrToBool(S,Result,DefaultFormatSettings)) then
  1585. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1586. end;
  1587. function StrToBool(const S: string; const FormatSettings: TFormatSettings): Boolean;
  1588. begin
  1589. if not(TryStrToBool(S,Result,FormatSettings)) then
  1590. Raise EConvertError.CreateFmt(SInvalidBoolean,[S]);
  1591. end;
  1592. procedure CheckBoolStrs;
  1593. begin
  1594. If Length(TrueBoolStrs)=0 then
  1595. begin
  1596. SetLength(TrueBoolStrs,1);
  1597. TrueBoolStrs[0]:='True';
  1598. end;
  1599. If Length(FalseBoolStrs)=0 then
  1600. begin
  1601. SetLength(FalseBoolStrs,1);
  1602. FalseBoolStrs[0]:='False';
  1603. end;
  1604. end;
  1605. function BoolToStr(B: Boolean;UseBoolStrs:Boolean=False): string;
  1606. begin
  1607. if UseBoolStrs Then
  1608. begin
  1609. CheckBoolStrs;
  1610. if B then
  1611. Result:=TrueBoolStrs[0]
  1612. else
  1613. Result:=FalseBoolStrs[0];
  1614. end
  1615. else
  1616. If B then
  1617. Result:='-1'
  1618. else
  1619. Result:='0';
  1620. end;
  1621. // from textmode IDE util funcs.
  1622. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  1623. begin
  1624. if B then Result:=TrueS else BoolToStr:=FalseS;
  1625. end;
  1626. function StrToBoolDef(const S: string; Default: Boolean): Boolean;
  1627. begin
  1628. if not(TryStrToBool(S,Result)) then
  1629. Result:=Default;
  1630. end;
  1631. function StrToBoolDef(const S: string; Default: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1632. begin
  1633. if not(TryStrToBool(S,Result,FormatSettings)) then
  1634. Result:=Default;
  1635. end;
  1636. function TryStrToBool(const S: string; out Value: Boolean): Boolean;
  1637. begin
  1638. Result:=TryStrToBool(S,Value,DefaultFormatSettings);
  1639. end;
  1640. function TryStrToBool(const S: string; out Value: Boolean; const FormatSettings: TFormatSettings): Boolean;
  1641. Var
  1642. Temp : String;
  1643. I : Longint;
  1644. {$ifdef FPUNONE}
  1645. D : Longint;
  1646. {$else}
  1647. D : Double;
  1648. {$endif}
  1649. Code: word;
  1650. begin
  1651. Temp:=upcase(S);
  1652. Val(temp,D,code);
  1653. Result:=true;
  1654. If (Code=0) or TryStrToFloat(S,D,FormatSettings) then
  1655. {$ifdef FPUNONE}
  1656. Value:=(D<>0)
  1657. {$else}
  1658. Value:=(D<>0.0)
  1659. {$endif}
  1660. else
  1661. begin
  1662. CheckBoolStrs;
  1663. for I:=low(TrueBoolStrs) to High(TrueBoolStrs) do
  1664. if Temp=upcase(TrueBoolStrs[I]) then
  1665. begin
  1666. Value:=true;
  1667. exit;
  1668. end;
  1669. for I:=low(FalseBoolStrs) to High(FalseBoolStrs) do
  1670. if Temp=upcase(FalseBoolStrs[I]) then
  1671. begin
  1672. Value:=false;
  1673. exit;
  1674. end;
  1675. Result:=false;
  1676. end;
  1677. end;
  1678. {$ifndef FPUNONE}
  1679. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar): Integer;
  1680. begin
  1681. Result:=FloatToTextFmt(Buffer,Value,Format,DefaultFormatSettings);
  1682. end;
  1683. {$MACRO ON}
  1684. {$define FPChar:=PAnsiChar}
  1685. {$define FChar:=AnsiChar}
  1686. {$define FString:=AnsiString}
  1687. {$I fmtflt.inc}
  1688. Function FloatToTextFmt(Buffer: PChar; Value: Extended; format: PChar; FormatSettings : TFormatSettings): Integer;
  1689. begin
  1690. Result:=IntFloatToTextFmt(Buffer,Value,fvExtended,Format,FormatSettings);
  1691. end;
  1692. Procedure FloatToDecimal(Out Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals : integer);
  1693. var
  1694. Buffer: String[254]; //Though str func returns only 25 chars, this might change in the future
  1695. InfNan: string[3];
  1696. Error, N, L, Start, C: Integer;
  1697. GotNonZeroBeforeDot, BeforeDot : boolean;
  1698. begin
  1699. case ValueType of
  1700. fvExtended:
  1701. Str(Extended(Value):25, Buffer);
  1702. fvDouble,
  1703. fvReal:
  1704. Str(Double(Value):23, Buffer);
  1705. fvSingle:
  1706. Str(Single(Value):16, Buffer);
  1707. fvCurrency:
  1708. Str(Currency(Value):25, Buffer);
  1709. fvComp:
  1710. Str(Currency(Value):23, Buffer);
  1711. end;
  1712. N := 1;
  1713. L := Byte(Buffer[0]);
  1714. while Buffer[N]=' ' do
  1715. Inc(N);
  1716. Result.Negative := (Buffer[N] = '-');
  1717. if Result.Negative then
  1718. Inc(N)
  1719. else if (Buffer[N] = '+') then
  1720. inc(N);
  1721. { special cases for Inf and Nan }
  1722. if (L>=N+2) then
  1723. begin
  1724. InfNan:=copy(Buffer,N,3);
  1725. if (InfNan='Inf') then
  1726. begin
  1727. Result.Digits[0]:=#0;
  1728. Result.Exponent:=32767;
  1729. exit
  1730. end;
  1731. if (InfNan='Nan') then
  1732. begin
  1733. Result.Digits[0]:=#0;
  1734. Result.Exponent:=-32768;
  1735. exit
  1736. end;
  1737. end;
  1738. Start := N; //Start of digits
  1739. Result.Exponent := 0; BeforeDot := true;
  1740. GotNonZeroBeforeDot := false;
  1741. while (L>=N) and (Buffer[N]<>'E') do
  1742. begin
  1743. if Buffer[N]='.' then
  1744. BeforeDot := false
  1745. else
  1746. begin
  1747. if BeforeDot then
  1748. begin // Currently this is always 1 char
  1749. Inc(Result.Exponent);
  1750. Result.Digits[N-Start] := Buffer[N];
  1751. if Buffer[N] <> '0' then
  1752. GotNonZeroBeforeDot := true;
  1753. end
  1754. else
  1755. Result.Digits[N-Start-1] := Buffer[N]
  1756. end;
  1757. Inc(N);
  1758. end;
  1759. Inc(N); // Pass through 'E'
  1760. if N<=L then
  1761. begin
  1762. Val(Copy(Buffer, N, L-N+1), C, Error); // Get exponent after 'E'
  1763. Inc(Result.Exponent, C);
  1764. end;
  1765. // Calculate number of digits we have from str
  1766. if BeforeDot then
  1767. N := N - Start - 1
  1768. else
  1769. N := N - Start - 2;
  1770. L := SizeOf(Result.Digits);
  1771. if N<L then
  1772. FillChar(Result.Digits[N], L-N, '0'); //Zero remaining space
  1773. if Decimals + Result.Exponent < Precision Then //After this it is the same as in FloatToDecimal
  1774. N := Decimals + Result.Exponent
  1775. Else
  1776. N := Precision;
  1777. if N >= L Then
  1778. N := L-1;
  1779. if N = 0 Then
  1780. begin
  1781. if Result.Digits[0] >= '5' Then
  1782. begin
  1783. Result.Digits[0] := '1';
  1784. Result.Digits[1] := #0;
  1785. Inc(Result.Exponent);
  1786. end
  1787. Else
  1788. Result.Digits[0] := #0;
  1789. end //N=0
  1790. Else if N > 0 Then
  1791. begin
  1792. if Result.Digits[N] >= '5' Then
  1793. begin
  1794. Repeat
  1795. Result.Digits[N] := #0;
  1796. Dec(N);
  1797. Inc(Result.Digits[N]);
  1798. Until (N = 0) Or (Result.Digits[N] < ':');
  1799. If Result.Digits[0] = ':' Then
  1800. begin
  1801. Result.Digits[0] := '1';
  1802. Inc(Result.Exponent);
  1803. end;
  1804. end
  1805. Else
  1806. begin
  1807. Result.Digits[N] := '0';
  1808. While (N > -1) And (Result.Digits[N] = '0') Do
  1809. begin
  1810. Result.Digits[N] := #0;
  1811. Dec(N);
  1812. end;
  1813. end;
  1814. end //N>0
  1815. Else
  1816. Result.Digits[0] := #0;
  1817. if (Result.Digits[0] = #0) and
  1818. not GotNonZeroBeforeDot then
  1819. begin
  1820. Result.Exponent := 0;
  1821. Result.Negative := False;
  1822. end;
  1823. end;
  1824. Procedure FloatToDecimal(Out Result: TFloatRec; Value: Extended; Precision, Decimals : integer);
  1825. begin
  1826. FloatToDecimal(Result,Value,fvExtended,Precision,Decimals);
  1827. end;
  1828. Function FormatFloat(Const Format : String; Value : Extended; Const FormatSettings: TFormatSettings) : String;
  1829. Var
  1830. buf : Array[0..1024] of char;
  1831. Begin // not changed to pchar(pointer(). Possibly not safe
  1832. Buf[FloatToTextFmt(@Buf[0],Value,Pchar(Format),FormatSettings)]:=#0;
  1833. Result:=StrPas(@Buf[0]);
  1834. End;
  1835. Function FormatFloat(Const format: String; Value: Extended): String;
  1836. begin
  1837. Result:=FormatFloat(Format,Value,DefaultFormatSettings);
  1838. end;
  1839. Function FormatCurr(const Format: string; Value: Currency; Const FormatSettings: TFormatSettings): string;
  1840. begin
  1841. Result := FormatFloat(Format, Value,FormatSettings);
  1842. end;
  1843. function FormatCurr(const Format: string; Value: Currency): string;
  1844. begin
  1845. Result:=FormatCurr(Format,Value,DefaultFormatSettings);
  1846. end;
  1847. {$endif}
  1848. {==============================================================================}
  1849. { extra functions }
  1850. {==============================================================================}
  1851. { LeftStr returns Count left-most characters from S }
  1852. function LeftStr(const S: string; Count: integer): string;
  1853. begin
  1854. result := Copy(S, 1, Count);
  1855. end ;
  1856. { RightStr returns Count right-most characters from S }
  1857. function RightStr(const S: string; Count: integer): string;
  1858. begin
  1859. If Count>Length(S) then
  1860. Count:=Length(S);
  1861. result := Copy(S, 1 + Length(S) - Count, Count);
  1862. end;
  1863. { BCDToInt converts the BCD value Value to an integer }
  1864. function BCDToInt(Value: integer): integer;
  1865. var i, j, digit: integer;
  1866. begin
  1867. result := 0;
  1868. j := 1;
  1869. for i := 0 to SizeOf(Value) shl 1 - 1 do begin
  1870. digit := Value and 15;
  1871. if digit > $9 then
  1872. begin
  1873. if i = 0 then
  1874. begin
  1875. if digit in [$B, $D] then j := -1
  1876. end
  1877. else raise EConvertError.createfmt(SInvalidBCD,[Value]);
  1878. end
  1879. else
  1880. begin
  1881. result := result + j * digit;
  1882. j := j * 10;
  1883. end ;
  1884. Value := Value shr 4;
  1885. end ;
  1886. end ;
  1887. Function LastDelimiter(const Delimiters, S: string): SizeInt;
  1888. var
  1889. chs: TSysCharSet;
  1890. I: SizeInt;
  1891. begin
  1892. chs := [];
  1893. for I := 1 to Length(Delimiters) do
  1894. Include(chs, Delimiters[I]);
  1895. Result:=Length(S);
  1896. While (Result>0) and not (S[Result] in chs) do
  1897. Dec(Result);
  1898. end;
  1899. {$macro on}
  1900. {$define INSTRINGREPLACE}
  1901. {$define SRString:=String}
  1902. {$define SRUpperCase:=AnsiUppercase}
  1903. {$define SRPCHAR:=PChar}
  1904. {$define SRCHAR:=Char}
  1905. Function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
  1906. {$i syssr.inc}
  1907. {$undef INSTRINGREPLACE}
  1908. {$undef SRString}
  1909. {$undef SRUpperCase}
  1910. {$undef SRPCHAR}
  1911. {$undef SRCHAR}
  1912. Function IsDelimiter(const Delimiters, S: string; Index: SizeInt): Boolean;
  1913. begin
  1914. Result:=False;
  1915. If (Index>0) and (Index<=Length(S)) then
  1916. Result:=Pos(S[Index],Delimiters)<>0; // Note we don't do MBCS yet
  1917. end;
  1918. Function ByteToCharLen(const S: string; MaxLen: SizeInt): SizeInt;
  1919. begin
  1920. Result:=Length(S);
  1921. If Result>MaxLen then
  1922. Result:=MaxLen;
  1923. end;
  1924. Function ByteToCharIndex(const S: string; Index: SizeInt): SizeInt;
  1925. begin
  1926. Result:=Index;
  1927. end;
  1928. Function CharToByteLen(const S: string; MaxLen: SizeInt): SizeInt;
  1929. begin
  1930. Result:=Length(S);
  1931. If Result>MaxLen then
  1932. Result:=MaxLen;
  1933. end;
  1934. Function CharToByteIndex(const S: string; Index: SizeInt): SizeInt;
  1935. begin
  1936. Result:=Index;
  1937. end;
  1938. Function ByteType(const S: string; Index: SizeUInt): TMbcsByteType;
  1939. begin
  1940. Result:=mbSingleByte;
  1941. end;
  1942. Function StrByteType(Str: PChar; Index: SizeUInt): TMbcsByteType;
  1943. begin
  1944. Result:=mbSingleByte;
  1945. end;
  1946. Function StrCharLength(const Str: PChar): SizeInt;
  1947. begin
  1948. result:=widestringmanager.CharLengthPCharProc(Str);
  1949. end;
  1950. function StrNextChar(const Str: PChar): PChar;
  1951. begin
  1952. result:=Str+StrCharLength(Str);
  1953. end;
  1954. Function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet;IgnoreCase: Boolean): Boolean;
  1955. Var
  1956. I,L : Integer;
  1957. S,T : String;
  1958. begin
  1959. Result:=False;
  1960. S:=Switch;
  1961. If IgnoreCase then
  1962. S:=UpperCase(S);
  1963. I:=ParamCount;
  1964. While (Not Result) and (I>0) do
  1965. begin
  1966. L:=Length(Paramstr(I));
  1967. If (L>0) and (ParamStr(I)[1] in Chars) then
  1968. begin
  1969. T:=Copy(ParamStr(I),2,L-1);
  1970. If IgnoreCase then
  1971. T:=UpperCase(T);
  1972. Result:=S=T;
  1973. end;
  1974. Dec(i);
  1975. end;
  1976. end;
  1977. Function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean;
  1978. begin
  1979. Result:=FindCmdLineSwitch(Switch,SwitchChars,IgnoreCase);
  1980. end;
  1981. Function FindCmdLineSwitch(const Switch: string): Boolean;
  1982. begin
  1983. Result:=FindCmdLineSwitch(Switch,SwitchChars,False);
  1984. end;
  1985. function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string;
  1986. const
  1987. Quotes = ['''', '"'];
  1988. Var
  1989. L : String;
  1990. C,LQ,BC : Char;
  1991. P,BLen,Len : Integer;
  1992. HB,IBC : Boolean;
  1993. begin
  1994. Result:='';
  1995. L:=Line;
  1996. Blen:=Length(BreakStr);
  1997. If (BLen>0) then
  1998. BC:=BreakStr[1]
  1999. else
  2000. BC:=#0;
  2001. Len:=Length(L);
  2002. While (Len>0) do
  2003. begin
  2004. P:=1;
  2005. LQ:=#0;
  2006. HB:=False;
  2007. IBC:=False;
  2008. While ((P<=Len) and ((P<=MaxCol) or not IBC)) and ((LQ<>#0) or Not HB) do
  2009. begin
  2010. C:=L[P];
  2011. If (C=LQ) then
  2012. LQ:=#0
  2013. else If (C in Quotes) then
  2014. LQ:=C;
  2015. If (LQ<>#0) then
  2016. Inc(P)
  2017. else
  2018. begin
  2019. HB:=((C=BC) and (BreakStr=Copy(L,P,BLen)));
  2020. If HB then
  2021. Inc(P,Blen)
  2022. else
  2023. begin
  2024. If (P>=MaxCol) then
  2025. IBC:=C in BreakChars;
  2026. Inc(P);
  2027. end;
  2028. end;
  2029. // Writeln('"',C,'" : IBC : ',IBC,' HB : ',HB,' LQ : ',LQ,' P>MaxCol : ',P>MaxCol);
  2030. end;
  2031. Result:=Result+Copy(L,1,P-1);
  2032. Delete(L,1,P-1);
  2033. Len:=Length(L);
  2034. If (Len>0) and Not HB then
  2035. Result:=Result+BreakStr;
  2036. end;
  2037. end;
  2038. function WrapText(const Line: string; MaxCol: Integer): string;
  2039. begin
  2040. Result:=WrapText(Line,sLineBreak, [' ', '-', #9], MaxCol);
  2041. end;
  2042. {$ifndef FPC_NOGENERICANSIROUTINES}
  2043. {
  2044. Case Translation Tables
  2045. Can be used in internationalization support.
  2046. Although these tables can be obtained through system calls
  2047. cd it is better to not use those, since most implementation are not 100%
  2048. WARNING:
  2049. before modifying a translation table make sure that the current codepage
  2050. of the OS corresponds to the one you make changes to
  2051. }
  2052. const
  2053. {$if defined(MSDOS) or defined(GO32V2) or defined(WATCOM) or defined(WIN16) }
  2054. { upper case translation table for character set 850 }
  2055. CP850UCT: array[128..255] of char =
  2056. (#128,#154,#144,#182,#142,#182,#143,#128,#210,#211,#212,#216,#215,#222,#142,#143,
  2057. #144,#146,#146,#226,#153,#227,#234,#235,'Y',#153,#154,#157,#156,#157,#158,#159,
  2058. #181,#214,#224,#233,#165,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2059. #176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,
  2060. #192,#193,#194,#195,#196,#197,#199,#199,#200,#201,#202,#203,#204,#205,#206,#207,
  2061. #208,#209,#210,#211,#212,#213,#214,#215,#216,#217,#218,#219,#220,#221,#222,#223,
  2062. #224,#225,#226,#227,#229,#229,#230,#237,#232,#233,#234,#235,#237,#237,#238,#239,
  2063. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2064. { lower case translation table for character set 850 }
  2065. CP850LCT: array[128..255] of char =
  2066. (#135,#129,#130,#131,#132,#133,#134,#135,#136,#137,#138,#139,#140,#141,#132,#134,
  2067. #130,#145,#145,#147,#148,#149,#150,#151,#152,#148,#129,#155,#156,#155,#158,#159,
  2068. #160,#161,#162,#163,#164,#164,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,
  2069. #176,#177,#178,#179,#180,#160,#131,#133,#184,#185,#186,#187,#188,#189,#190,#191,
  2070. #192,#193,#194,#195,#196,#197,#198,#198,#200,#201,#202,#203,#204,#205,#206,#207,
  2071. #208,#209,#136,#137,#138,#213,#161,#140,#139,#217,#218,#219,#220,#221,#141,#223,
  2072. #162,#225,#147,#149,#228,#228,#230,#237,#232,#163,#150,#151,#236,#236,#238,#239,
  2073. #240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255);
  2074. {$endif}
  2075. { upper case translation table for character set ISO 8859/1 Latin 1 }
  2076. CPISO88591UCT: array[192..255] of char =
  2077. ( #192, #193, #194, #195, #196, #197, #198, #199,
  2078. #200, #201, #202, #203, #204, #205, #206, #207,
  2079. #208, #209, #210, #211, #212, #213, #214, #215,
  2080. #216, #217, #218, #219, #220, #221, #222, #223,
  2081. #192, #193, #194, #195, #196, #197, #198, #199,
  2082. #200, #201, #202, #203, #204, #205, #206, #207,
  2083. #208, #209, #210, #211, #212, #213, #214, #247,
  2084. #216, #217, #218, #219, #220, #221, #222, #89 );
  2085. { lower case translation table for character set ISO 8859/1 Latin 1 }
  2086. CPISO88591LCT: array[192..255] of char =
  2087. ( #224, #225, #226, #227, #228, #229, #230, #231,
  2088. #232, #233, #234, #235, #236, #237, #238, #239,
  2089. #240, #241, #242, #243, #244, #245, #246, #215,
  2090. #248, #249, #250, #251, #252, #253, #254, #223,
  2091. #224, #225, #226, #227, #228, #229, #230, #231,
  2092. #232, #233, #234, #235, #236, #237, #238, #239,
  2093. #240, #241, #242, #243, #244, #245, #246, #247,
  2094. #248, #249, #250, #251, #252, #253, #254, #255 );
  2095. {$endif FPC_NOGENERICANSIROUTINES}
  2096. function sscanf(const s: string; const fmt : string;const Pointers : array of Pointer) : Integer;
  2097. var
  2098. i,j,n,m : SizeInt;
  2099. s1 : string;
  2100. function GetInt(unsigned : boolean=false) : Integer;
  2101. begin
  2102. s1 := '';
  2103. while (Length(s) > n) and (s[n] = ' ') do
  2104. inc(n);
  2105. { read sign }
  2106. if (Length(s)>= n) and (s[n] in ['+', '-']) then
  2107. begin
  2108. { don't accept - when reading unsigned }
  2109. if unsigned and (s[n]='-') then
  2110. begin
  2111. result:=length(s1);
  2112. exit;
  2113. end
  2114. else
  2115. begin
  2116. s1:=s1+s[n];
  2117. inc(n);
  2118. end;
  2119. end;
  2120. { read numbers }
  2121. while (Length(s) >= n) and
  2122. (s[n] in ['0'..'9']) do
  2123. begin
  2124. s1 := s1+s[n];
  2125. inc(n);
  2126. end;
  2127. Result := Length(s1);
  2128. end;
  2129. function GetFloat : Integer;
  2130. begin
  2131. s1 := '';
  2132. while (Length(s) > n) and (s[n] = ' ') do
  2133. inc(n);
  2134. while (Length(s) >= n) and
  2135. (s[n] in ['0'..'9', '+', '-', FormatSettings.DecimalSeparator, 'e', 'E']) do
  2136. begin
  2137. s1 := s1+s[n];
  2138. inc(n);
  2139. end;
  2140. Result := Length(s1);
  2141. end;
  2142. function GetString : Integer;
  2143. begin
  2144. s1 := '';
  2145. while (Length(s) > n) and (s[n] = ' ') do
  2146. inc(n);
  2147. while (Length(s) >= n) and (s[n] <> ' ')do
  2148. begin
  2149. s1 := s1+s[n];
  2150. inc(n);
  2151. end;
  2152. Result := Length(s1);
  2153. end;
  2154. function ScanStr(c : Char) : Boolean;
  2155. begin
  2156. while (Length(s) > n) and (s[n] <> c) do
  2157. inc(n);
  2158. inc(n);
  2159. If (n <= Length(s)) then
  2160. Result := True
  2161. else
  2162. Result := False;
  2163. end;
  2164. function GetFmt : Integer;
  2165. begin
  2166. Result := -1;
  2167. while true do
  2168. begin
  2169. while (Length(fmt) > m) and (fmt[m] = ' ') do
  2170. inc(m);
  2171. if (m >= Length(fmt)) then
  2172. break;
  2173. if (fmt[m] = '%') then
  2174. begin
  2175. inc(m);
  2176. case fmt[m] of
  2177. 'd':
  2178. Result:=vtInteger;
  2179. {$ifndef FPUNONE}
  2180. 'f':
  2181. Result:=vtExtended;
  2182. {$endif}
  2183. 's':
  2184. Result:=vtString;
  2185. 'c':
  2186. Result:=vtChar;
  2187. else
  2188. raise EFormatError.CreateFmt(SInvalidFormat,[fmt]);
  2189. end;
  2190. inc(m);
  2191. break;
  2192. end;
  2193. if not(ScanStr(fmt[m])) then
  2194. break;
  2195. inc(m);
  2196. end;
  2197. end;
  2198. begin
  2199. n := 1;
  2200. m := 1;
  2201. Result := 0;
  2202. for i:=0 to High(Pointers) do
  2203. begin
  2204. j := GetFmt;
  2205. case j of
  2206. vtInteger :
  2207. begin
  2208. if GetInt>0 then
  2209. begin
  2210. pLongint(Pointers[i])^:=StrToInt(s1);
  2211. inc(Result);
  2212. end
  2213. else
  2214. break;
  2215. end;
  2216. vtchar :
  2217. begin
  2218. if Length(s)>n then
  2219. begin
  2220. pchar(Pointers[i])^:=s[n];
  2221. inc(n);
  2222. inc(Result);
  2223. end
  2224. else
  2225. break;
  2226. end;
  2227. {$ifndef FPUNONE}
  2228. vtExtended :
  2229. begin
  2230. if GetFloat>0 then
  2231. begin
  2232. pextended(Pointers[i])^:=StrToFloat(s1);
  2233. inc(Result);
  2234. end
  2235. else
  2236. break;
  2237. end;
  2238. {$endif}
  2239. vtString :
  2240. begin
  2241. if GetString > 0 then
  2242. begin
  2243. pansistring(Pointers[i])^:=s1;
  2244. inc(Result);
  2245. end
  2246. else
  2247. break;
  2248. end;
  2249. else
  2250. break;
  2251. end;
  2252. end;
  2253. end;
  2254. {$macro on}
  2255. // Ansi version declaration
  2256. {$UNDEF SBUNICODE}
  2257. {$define SBChar:=AnsiChar}
  2258. {$define SBString:=AnsiString}
  2259. {$define TSBCharArray:=Array of SBChar}
  2260. {$define PSBChar:=PAnsiChar}
  2261. {$define SBRAWString:=RawByteString}
  2262. {$define TStringBuilder:=TAnsiStringBuilder}
  2263. {$i syssb.inc}
  2264. {$undef SBChar}
  2265. {$undef SBString}
  2266. {$undef TSBCharArray}
  2267. {$undef PSBChar}
  2268. {$undef SBRAWString}
  2269. {$undef TStringBuilder}
  2270. // Unicode version declaration
  2271. {$define SBUNICODE}
  2272. {$define SBChar:=WideChar}
  2273. {$define SBString:=UnicodeString}
  2274. {$define TSBCharArray:=Array of SBChar}
  2275. {$define PSBChar:=PWideChar}
  2276. {$define SBRAWString:=UnicodeString}
  2277. {$define TStringBuilder:=TUnicodeStringBuilder}
  2278. {$i syssb.inc}
  2279. {$undef SBChar}
  2280. {$undef SBString}
  2281. {$undef TSBCharArray}
  2282. {$undef PSBChar}
  2283. {$undef SBRAWString}
  2284. {$undef TStringBuilder}
  2285. {$undef SBUNICODE}