sysstr.inc 71 KB

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