sysstr.inc 71 KB

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