sysstr.inc 70 KB

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