2
0

sstrings.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {****************************************************************************
  11. subroutines for string handling
  12. ****************************************************************************}
  13. procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; compilerproc;
  14. begin
  15. if Len>255 then
  16. Len:=255;
  17. s[0]:=chr(len);
  18. end;
  19. function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  20. begin
  21. if count<0 then
  22. count:=0;
  23. if index>1 then
  24. dec(index)
  25. else
  26. index:=0;
  27. if index>length(s) then
  28. count:=0
  29. else
  30. if count>length(s)-index then
  31. count:=length(s)-index;
  32. fpc_shortstr_Copy[0]:=chr(Count);
  33. Move(s[Index+1],fpc_shortstr_Copy[1],Count);
  34. end;
  35. procedure delete(var s : shortstring;index : SizeInt;count : SizeInt);
  36. begin
  37. if index<=0 then
  38. exit;
  39. if (Index<=Length(s)) and (Count>0) then
  40. begin
  41. if Count>length(s)-Index then
  42. Count:=length(s)-Index+1;
  43. s[0]:=Chr(length(s)-Count);
  44. if Index<=Length(s) then
  45. Move(s[Index+Count],s[Index],Length(s)-Index+1);
  46. end;
  47. end;
  48. procedure insert(const source : shortstring;var s : shortstring;index : SizeInt);
  49. var
  50. cut,srclen,indexlen : SizeInt;
  51. begin
  52. if index<1 then
  53. index:=1;
  54. if index>length(s) then
  55. index:=length(s)+1;
  56. indexlen:=Length(s)-Index+1;
  57. srclen:=length(Source);
  58. if SizeInt(length(source)+length(s))>=sizeof(s) then
  59. begin
  60. cut:=SizeInt(length(source)+length(s))-sizeof(s)+1;
  61. if cut>indexlen then
  62. begin
  63. dec(srclen,cut-indexlen);
  64. indexlen:=0;
  65. end
  66. else
  67. dec(indexlen,cut);
  68. end;
  69. move(s[Index],s[Index+srclen],indexlen);
  70. move(Source[1],s[Index],srclen);
  71. s[0]:=chr(index+srclen+indexlen-1);
  72. end;
  73. procedure insert(source : Char;var s : shortstring;index : SizeInt);
  74. var
  75. indexlen : SizeInt;
  76. begin
  77. if index<1 then
  78. index:=1;
  79. if index>length(s) then
  80. index:=length(s)+1;
  81. indexlen:=Length(s)-Index+1;
  82. if (length(s)+1=sizeof(s)) and (indexlen>0) then
  83. dec(indexlen);
  84. move(s[Index],s[Index+1],indexlen);
  85. s[Index]:=Source;
  86. s[0]:=chr(index+indexlen);
  87. end;
  88. function pos(const substr : shortstring;const s : shortstring):SizeInt;
  89. var
  90. i,MaxLen : SizeInt;
  91. pc : pchar;
  92. begin
  93. Pos:=0;
  94. if Length(SubStr)>0 then
  95. begin
  96. MaxLen:=Length(s)-Length(SubStr);
  97. i:=0;
  98. pc:=@s[1];
  99. while (i<=MaxLen) do
  100. begin
  101. inc(i);
  102. if (SubStr[1]=pc^) and
  103. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  104. begin
  105. Pos:=i;
  106. exit;
  107. end;
  108. inc(pc);
  109. end;
  110. end;
  111. end;
  112. {Faster when looking for a single char...}
  113. function pos(c:char;const s:shortstring):SizeInt;
  114. var
  115. i : SizeInt;
  116. pc : pchar;
  117. begin
  118. pc:=@s[1];
  119. for i:=1 to length(s) do
  120. begin
  121. if pc^=c then
  122. begin
  123. pos:=i;
  124. exit;
  125. end;
  126. inc(pc);
  127. end;
  128. pos:=0;
  129. end;
  130. function fpc_char_copy(c:char;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  131. begin
  132. if (index=1) and (Count>0) then
  133. fpc_char_Copy:=c
  134. else
  135. fpc_char_Copy:='';
  136. end;
  137. function pos(const substr : shortstring;c:char): SizeInt;
  138. begin
  139. if (length(substr)=1) and (substr[1]=c) then
  140. Pos:=1
  141. else
  142. Pos:=0;
  143. end;
  144. {$ifdef IBM_CHAR_SET}
  145. const
  146. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  147. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  148. {$endif}
  149. function upcase(c : char) : char;
  150. {$IFDEF IBM_CHAR_SET}
  151. var
  152. i : longint;
  153. {$ENDIF}
  154. begin
  155. if (c in ['a'..'z']) then
  156. upcase:=char(byte(c)-32)
  157. else
  158. {$IFDEF IBM_CHAR_SET}
  159. begin
  160. i:=Pos(c,LoCaseTbl);
  161. if i>0 then
  162. upcase:=UpCaseTbl[i]
  163. else
  164. upcase:=c;
  165. end;
  166. {$ELSE}
  167. upcase:=c;
  168. {$ENDIF}
  169. end;
  170. function upcase(const s : shortstring) : shortstring;
  171. var
  172. i : longint;
  173. begin
  174. upcase[0]:=s[0];
  175. for i := 1 to length (s) do
  176. upcase[i] := upcase (s[i]);
  177. end;
  178. function lowercase(c : char) : char;overload;
  179. {$IFDEF IBM_CHAR_SET}
  180. var
  181. i : longint;
  182. {$ENDIF}
  183. begin
  184. if (c in ['A'..'Z']) then
  185. lowercase:=char(byte(c)+32)
  186. else
  187. {$IFDEF IBM_CHAR_SET}
  188. begin
  189. i:=Pos(c,UpCaseTbl);
  190. if i>0 then
  191. lowercase:=LoCaseTbl[i]
  192. else
  193. lowercase:=c;
  194. end;
  195. {$ELSE}
  196. lowercase:=c;
  197. {$ENDIF}
  198. end;
  199. function lowercase(const s : shortstring) : shortstring; overload;
  200. var
  201. i : longint;
  202. begin
  203. lowercase [0]:=s[0];
  204. for i:=1 to length(s) do
  205. lowercase[i]:=lowercase (s[i]);
  206. end;
  207. const
  208. HexTbl : array[0..15] of char='0123456789ABCDEF';
  209. function hexstr(val : longint;cnt : byte) : shortstring;
  210. var
  211. i : longint;
  212. begin
  213. hexstr[0]:=char(cnt);
  214. for i:=cnt downto 1 do
  215. begin
  216. hexstr[i]:=hextbl[val and $f];
  217. val:=val shr 4;
  218. end;
  219. end;
  220. function octstr(val : longint;cnt : byte) : shortstring;
  221. var
  222. i : longint;
  223. begin
  224. octstr[0]:=char(cnt);
  225. for i:=cnt downto 1 do
  226. begin
  227. octstr[i]:=hextbl[val and 7];
  228. val:=val shr 3;
  229. end;
  230. end;
  231. function binstr(val : longint;cnt : byte) : shortstring;
  232. var
  233. i : longint;
  234. begin
  235. binstr[0]:=char(cnt);
  236. for i:=cnt downto 1 do
  237. begin
  238. binstr[i]:=char(48+val and 1);
  239. val:=val shr 1;
  240. end;
  241. end;
  242. function hexstr(val : int64;cnt : byte) : shortstring;
  243. var
  244. i : longint;
  245. begin
  246. hexstr[0]:=char(cnt);
  247. for i:=cnt downto 1 do
  248. begin
  249. hexstr[i]:=hextbl[val and $f];
  250. val:=val shr 4;
  251. end;
  252. end;
  253. function octstr(val : int64;cnt : byte) : shortstring;
  254. var
  255. i : longint;
  256. begin
  257. octstr[0]:=char(cnt);
  258. for i:=cnt downto 1 do
  259. begin
  260. octstr[i]:=hextbl[val and 7];
  261. val:=val shr 3;
  262. end;
  263. end;
  264. function binstr(val : int64;cnt : byte) : shortstring;
  265. var
  266. i : longint;
  267. begin
  268. binstr[0]:=char(cnt);
  269. for i:=cnt downto 1 do
  270. begin
  271. binstr[i]:=char(48+val and 1);
  272. val:=val shr 1;
  273. end;
  274. end;
  275. function hexstr(val : pointer) : shortstring;
  276. var
  277. i : longint;
  278. v : ptrint;
  279. begin
  280. v:=ptrint(val);
  281. hexstr[0]:=chr(sizeof(pointer)*2);
  282. for i:=sizeof(pointer)*2 downto 1 do
  283. begin
  284. hexstr[i]:=hextbl[v and $f];
  285. v:=v shr 4;
  286. end;
  287. end;
  288. function space (b : byte): shortstring;
  289. begin
  290. space[0] := chr(b);
  291. FillChar (Space[1],b,' ');
  292. end;
  293. {*****************************************************************************
  294. Str() Helpers
  295. *****************************************************************************}
  296. procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
  297. begin
  298. int_str(v,s);
  299. if length(s)<len then
  300. s:=space(len-length(s))+s;
  301. end;
  302. procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
  303. begin
  304. int_str(v,s);
  305. if length(s)<len then
  306. s:=space(len-length(s))+s;
  307. end;
  308. {$ifndef CPU64}
  309. procedure fpc_shortstr_qword(v : qword;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
  310. begin
  311. int_str(v,s);
  312. if length(s)<len then
  313. s:=space(len-length(s))+s;
  314. end;
  315. procedure fpc_shortstr_int64(v : int64;len : longint;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
  316. begin
  317. int_str(v,s);
  318. if length(s)<len then
  319. s:=space(len-length(s))+s;
  320. end;
  321. {$endif CPU64}
  322. { fpc_shortstr_sInt must appear before this file is included, because }
  323. { it's used inside real2str.inc and otherwise the searching via the }
  324. { compilerproc name will fail (JM) }
  325. {$I real2str.inc}
  326. procedure fpc_ShortStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  327. begin
  328. str_real(len,fr,d,treal_type(rt),s);
  329. end;
  330. procedure fpc_ShortStr_Currency(c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  331. const
  332. MinLen = 8; { Minimal string length in scientific format }
  333. var
  334. buf : array[1..19] of char;
  335. i,j,k,reslen,tlen,sign,r,point : longint;
  336. ic : int64;
  337. begin
  338. { default value for length is -32767 }
  339. if len=-32767 then
  340. len:=25;
  341. ic:=PInt64(@c)^;
  342. if ic >= 0 then
  343. sign:=0
  344. else
  345. begin
  346. sign:=1;
  347. ic:=-ic;
  348. end;
  349. { converting to integer string }
  350. tlen:=0;
  351. repeat
  352. Inc(tlen);
  353. buf[tlen]:=Chr(ic mod 10 + $30);
  354. ic:=ic div 10;
  355. until ic = 0;
  356. { calculating:
  357. reslen - length of result string,
  358. r - rounding or appending zeroes,
  359. point - place of decimal point }
  360. reslen:=tlen;
  361. if f <> 0 then
  362. Inc(reslen); { adding decimal point length }
  363. if f < 0 then
  364. begin
  365. { scientific format }
  366. Inc(reslen,5); { adding length of sign and exponent }
  367. if len < MinLen then
  368. len:=MinLen;
  369. r:=reslen-len;
  370. if reslen < len then
  371. reslen:=len;
  372. if r > 0 then
  373. begin
  374. reslen:=len;
  375. point:=tlen - r;
  376. end
  377. else
  378. point:=tlen;
  379. end
  380. else
  381. begin
  382. { fixed format }
  383. Inc(reslen, sign);
  384. { prepending fractional part with zeroes }
  385. while tlen < 5 do
  386. begin
  387. Inc(reslen);
  388. Inc(tlen);
  389. buf[tlen]:='0';
  390. end;
  391. { Currency have 4 digits in fractional part }
  392. r:=4 - f;
  393. point:=f;
  394. if point <> 0 then
  395. begin
  396. if point > 4 then
  397. point:=4;
  398. Inc(point);
  399. end;
  400. Dec(reslen,r);
  401. end;
  402. { rounding string if r > 0 }
  403. if r > 0 then
  404. begin
  405. i:=1;
  406. k:=0;
  407. for j:=0 to r do
  408. begin
  409. buf[i]:=chr(ord(buf[i]) + k);
  410. if buf[i] >= '5' then
  411. k:=1
  412. else
  413. k:=0;
  414. Inc(i);
  415. if i>tlen then
  416. break;
  417. end;
  418. end;
  419. { preparing result string }
  420. if reslen<len then
  421. reslen:=len;
  422. if reslen>High(s) then
  423. begin
  424. if r < 0 then
  425. Inc(r, reslen - High(s));
  426. reslen:=High(s);
  427. end;
  428. SetLength(s,reslen);
  429. j:=reslen;
  430. if f<0 then
  431. begin
  432. { writing power of 10 part }
  433. k:=tlen-5;
  434. if k >= 0 then
  435. s[j-2]:='+'
  436. else
  437. begin
  438. s[j-2]:='-';
  439. k:=-k;
  440. end;
  441. s[j]:=Chr(k mod 10 + $30);
  442. Dec(j);
  443. s[j]:=Chr(k div 10 + $30);
  444. Dec(j,2);
  445. s[j]:='E';
  446. Dec(j);
  447. end;
  448. { writing extra zeroes if r < 0 }
  449. while r < 0 do
  450. begin
  451. s[j]:='0';
  452. Dec(j);
  453. Inc(r);
  454. end;
  455. { writing digits and decimal point }
  456. for i:=r + 1 to tlen do
  457. begin
  458. Dec(point);
  459. if point = 0 then
  460. begin
  461. s[j]:='.';
  462. Dec(j);
  463. end;
  464. s[j]:=buf[i];
  465. Dec(j);
  466. end;
  467. { writing sign }
  468. if sign = 1 then
  469. begin
  470. s[j]:='-';
  471. Dec(j);
  472. end;
  473. { writing spaces }
  474. while j > 0 do
  475. begin
  476. s[j]:=' ';
  477. Dec(j);
  478. end;
  479. end;
  480. {
  481. Array Of Char Str() helpers
  482. }
  483. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  484. var
  485. ss : shortstring;
  486. maxlen : SizeInt;
  487. begin
  488. int_str(v,ss);
  489. if length(ss)<len then
  490. ss:=space(len-length(ss))+ss;
  491. if length(ss)<high(a)+1 then
  492. maxlen:=length(ss)
  493. else
  494. maxlen:=high(a)+1;
  495. move(ss[1],pchar(@a)^,maxlen);
  496. end;
  497. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  498. var
  499. ss : shortstring;
  500. maxlen : SizeInt;
  501. begin
  502. int_str(v,ss);
  503. if length(ss)<len then
  504. ss:=space(len-length(ss))+ss;
  505. if length(ss)<high(a)+1 then
  506. maxlen:=length(ss)
  507. else
  508. maxlen:=high(a)+1;
  509. move(ss[1],pchar(@a)^,maxlen);
  510. end;
  511. {$ifndef CPU64}
  512. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  513. var
  514. ss : shortstring;
  515. maxlen : SizeInt;
  516. begin
  517. int_str(v,ss);
  518. if length(ss)<len then
  519. ss:=space(len-length(ss))+ss;
  520. if length(ss)<high(a)+1 then
  521. maxlen:=length(ss)
  522. else
  523. maxlen:=high(a)+1;
  524. move(ss[1],pchar(@a)^,maxlen);
  525. end;
  526. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  527. var
  528. ss : shortstring;
  529. maxlen : SizeInt;
  530. begin
  531. int_str(v,ss);
  532. if length(ss)<len then
  533. ss:=space(len-length(ss))+ss;
  534. if length(ss)<high(a)+1 then
  535. maxlen:=length(ss)
  536. else
  537. maxlen:=high(a)+1;
  538. move(ss[1],pchar(@a)^,maxlen);
  539. end;
  540. {$endif CPU64}
  541. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  542. var
  543. ss : shortstring;
  544. maxlen : SizeInt;
  545. begin
  546. str_real(len,fr,d,treal_type(rt),ss);
  547. if length(ss)<high(a)+1 then
  548. maxlen:=length(ss)
  549. else
  550. maxlen:=high(a)+1;
  551. move(ss[1],pchar(@a)^,maxlen);
  552. end;
  553. {*****************************************************************************
  554. Val() Functions
  555. *****************************************************************************}
  556. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  557. var
  558. Code : SizeInt;
  559. begin
  560. {Skip Spaces and Tab}
  561. code:=1;
  562. while (code<=length(s)) and (s[code] in [' ',#9]) do
  563. inc(code);
  564. {Sign}
  565. negativ:=false;
  566. case s[code] of
  567. '-' : begin
  568. negativ:=true;
  569. inc(code);
  570. end;
  571. '+' : inc(code);
  572. end;
  573. {Base}
  574. base:=10;
  575. if code<=length(s) then
  576. begin
  577. case s[code] of
  578. '$' : begin
  579. base:=16;
  580. inc(code);
  581. end;
  582. '%' : begin
  583. base:=2;
  584. inc(code);
  585. end;
  586. '&' : begin
  587. Base:=8;
  588. inc(code);
  589. end;
  590. '0' : begin
  591. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  592. begin
  593. inc(code, 2);
  594. base := 16;
  595. end;
  596. end;
  597. end;
  598. end;
  599. { strip leading zeros }
  600. while ((code < length(s)) and (s[code] = '0')) do begin
  601. inc(code);
  602. end;
  603. InitVal:=code;
  604. end;
  605. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  606. var
  607. u, temp, prev, maxPrevValue, maxNewValue: ValUInt;
  608. base : byte;
  609. negative : boolean;
  610. begin
  611. fpc_Val_SInt_ShortStr := 0;
  612. Temp:=0;
  613. Code:=InitVal(s,negative,base);
  614. if Code>length(s) then
  615. exit;
  616. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  617. if (base = 10) then
  618. maxNewValue := MaxSIntValue + ord(negative)
  619. else
  620. maxNewValue := MaxUIntValue;
  621. while Code<=Length(s) do
  622. begin
  623. case s[Code] of
  624. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  625. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  626. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  627. else
  628. u:=16;
  629. end;
  630. Prev := Temp;
  631. Temp := Temp*ValUInt(base);
  632. If (u >= base) or
  633. (ValUInt(maxNewValue-u) < Temp) or
  634. (prev > maxPrevValue) Then
  635. Begin
  636. fpc_Val_SInt_ShortStr := 0;
  637. Exit
  638. End;
  639. Temp:=Temp+u;
  640. inc(code);
  641. end;
  642. code := 0;
  643. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  644. If Negative Then
  645. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  646. If Not(Negative) and (base <> 10) Then
  647. {sign extend the result to allow proper range checking}
  648. Case DestSize of
  649. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  650. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  651. { Uncomment the folling once full 64bit support is in place
  652. 4: fpc_Val_SInt_ShortStr := SizeInt(fpc_Val_SInt_ShortStr);}
  653. End;
  654. end;
  655. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  656. { we have to pass the DestSize parameter on (JM) }
  657. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  658. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  659. var
  660. u, prev : ValUInt;
  661. base : byte;
  662. negative : boolean;
  663. begin
  664. fpc_Val_UInt_Shortstr:=0;
  665. Code:=InitVal(s,negative,base);
  666. If Negative or (Code>length(s)) Then
  667. Exit;
  668. while Code<=Length(s) do
  669. begin
  670. case s[Code] of
  671. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  672. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  673. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  674. else
  675. u:=16;
  676. end;
  677. prev := fpc_Val_UInt_Shortstr;
  678. If (u>=base) or
  679. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  680. begin
  681. fpc_Val_UInt_Shortstr:=0;
  682. exit;
  683. end;
  684. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  685. inc(code);
  686. end;
  687. code := 0;
  688. end;
  689. {$ifndef CPU64}
  690. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  691. type
  692. QWordRec = packed record
  693. l1,l2: longint;
  694. end;
  695. var
  696. u, temp, prev, maxint64, maxqword : qword;
  697. base : byte;
  698. negative : boolean;
  699. begin
  700. fpc_val_int64_shortstr := 0;
  701. Temp:=0;
  702. Code:=InitVal(s,negative,base);
  703. if Code>length(s) then
  704. exit;
  705. { high(int64) produces 0 in version 1.0 (JM) }
  706. with qwordrec(maxint64) do
  707. begin
  708. {$ifdef ENDIAN_LITTLE}
  709. l1 := longint($ffffffff);
  710. l2 := $7fffffff;
  711. {$else ENDIAN_LITTLE}
  712. l1 := $7fffffff;
  713. l2 := longint($ffffffff);
  714. {$endif ENDIAN_LITTLE}
  715. end;
  716. with qwordrec(maxqword) do
  717. begin
  718. l1 := longint($ffffffff);
  719. l2 := longint($ffffffff);
  720. end;
  721. while Code<=Length(s) do
  722. begin
  723. case s[Code] of
  724. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  725. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  726. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  727. else
  728. u:=16;
  729. end;
  730. Prev:=Temp;
  731. Temp:=Temp*Int64(base);
  732. If (u >= base) or
  733. ((base = 10) and
  734. (maxint64-temp+ord(negative) < u)) or
  735. ((base <> 10) and
  736. (qword(maxqword-temp) < u)) or
  737. (prev > maxqword div qword(base)) Then
  738. Begin
  739. fpc_val_int64_shortstr := 0;
  740. Exit
  741. End;
  742. Temp:=Temp+u;
  743. inc(code);
  744. end;
  745. code:=0;
  746. fpc_val_int64_shortstr:=int64(Temp);
  747. If Negative Then
  748. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  749. end;
  750. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  751. type qwordrec = packed record
  752. l1,l2: longint;
  753. end;
  754. var
  755. u, prev, maxqword: QWord;
  756. base : byte;
  757. negative : boolean;
  758. begin
  759. fpc_val_qword_shortstr:=0;
  760. Code:=InitVal(s,negative,base);
  761. If Negative or (Code>length(s)) Then
  762. Exit;
  763. with qwordrec(maxqword) do
  764. begin
  765. l1 := longint($ffffffff);
  766. l2 := longint($ffffffff);
  767. end;
  768. while Code<=Length(s) do
  769. begin
  770. case s[Code] of
  771. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  772. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  773. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  774. else
  775. u:=16;
  776. end;
  777. prev := fpc_val_qword_shortstr;
  778. If (u>=base) or
  779. ((QWord(maxqword-u) div QWord(base))<prev) then
  780. Begin
  781. fpc_val_qword_shortstr := 0;
  782. Exit
  783. End;
  784. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  785. inc(code);
  786. end;
  787. code := 0;
  788. end;
  789. {$endif CPU64}
  790. const
  791. {$ifdef FPC_HAS_TYPE_EXTENDED}
  792. valmaxexpnorm=4932;
  793. {$else}
  794. {$ifdef FPC_HAS_TYPE_DOUBLE}
  795. valmaxexpnorm=308;
  796. {$else}
  797. {$ifdef FPC_HAS_TYPE_SINGLE}
  798. valmaxexpnorm=38;
  799. {$else}
  800. {$error Unknown floating point precision }
  801. {$endif}
  802. {$endif}
  803. {$endif}
  804. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  805. var
  806. hd,
  807. esign,sign : valreal;
  808. exponent,i : SizeInt;
  809. flags : byte;
  810. begin
  811. fpc_Val_Real_ShortStr:=0.0;
  812. code:=1;
  813. exponent:=0;
  814. esign:=1;
  815. flags:=0;
  816. sign:=1;
  817. while (code<=length(s)) and (s[code] in [' ',#9]) do
  818. inc(code);
  819. if code<=length(s) then
  820. case s[code] of
  821. '+' : inc(code);
  822. '-' : begin
  823. sign:=-1;
  824. inc(code);
  825. end;
  826. end;
  827. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  828. begin
  829. { Read integer part }
  830. flags:=flags or 1;
  831. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  832. inc(code);
  833. end;
  834. { Decimal ? }
  835. if (length(s)>=code) and (s[code]='.') then
  836. begin
  837. hd:=1.0;
  838. inc(code);
  839. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  840. begin
  841. { Read fractional part. }
  842. flags:=flags or 2;
  843. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  844. hd:=hd*10.0;
  845. inc(code);
  846. end;
  847. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  848. end;
  849. { Again, read integer and fractional part}
  850. if flags=0 then
  851. begin
  852. fpc_Val_Real_ShortStr:=0.0;
  853. exit;
  854. end;
  855. { Exponent ? }
  856. if (length(s)>=code) and (upcase(s[code])='E') then
  857. begin
  858. inc(code);
  859. if Length(s) >= code then
  860. if s[code]='+' then
  861. inc(code)
  862. else
  863. if s[code]='-' then
  864. begin
  865. esign:=-1;
  866. inc(code);
  867. end;
  868. if (length(s)<code) or not(s[code] in ['0'..'9']) then
  869. begin
  870. fpc_Val_Real_ShortStr:=0.0;
  871. exit;
  872. end;
  873. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  874. begin
  875. exponent:=exponent*10;
  876. exponent:=exponent+ord(s[code])-ord('0');
  877. inc(code);
  878. end;
  879. end;
  880. { evaluate sign }
  881. { (before exponent, because the exponent may turn it into a denormal) }
  882. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  883. { Calculate Exponent }
  884. hd:=1.0;
  885. { the magnitude range maximum (normal) is lower in absolute value than the }
  886. { the magnitude range minimum (denormal). E.g. an extended value can go }
  887. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  888. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  889. if (exponent>valmaxexpnorm-2) then
  890. begin
  891. for i:=1 to valmaxexpnorm-2 do
  892. hd:=hd*10.0;
  893. if esign>0 then
  894. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  895. else
  896. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  897. dec(exponent,valmaxexpnorm-2);
  898. hd:=1.0;
  899. end;
  900. for i:=1 to exponent do
  901. hd:=hd*10.0;
  902. if esign>0 then
  903. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  904. else
  905. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  906. { Not all characters are read ? }
  907. if length(s)>=code then
  908. begin
  909. fpc_Val_Real_ShortStr:=0.0;
  910. exit;
  911. end;
  912. { success ! }
  913. code:=0;
  914. end;
  915. Function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : longint): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  916. const
  917. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  918. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  919. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  920. var
  921. res : Int64;
  922. i,j,power,sign,len : longint;
  923. FracOverflow : boolean;
  924. begin
  925. fpc_Val_Currency_ShortStr:=0;
  926. res:=0;
  927. len:=Length(s);
  928. Code:=1;
  929. sign:=1;
  930. power:=0;
  931. while True do
  932. if Code > len then
  933. exit
  934. else
  935. if s[Code] in [' ', #9] then
  936. Inc(Code)
  937. else
  938. break;
  939. { Read sign }
  940. case s[Code] of
  941. '+' : Inc(Code);
  942. '-' : begin
  943. sign:=-1;
  944. inc(code);
  945. end;
  946. end;
  947. { Read digits }
  948. FracOverflow:=False;
  949. i:=0;
  950. while Code <= len do
  951. begin
  952. case s[Code] of
  953. '0'..'9':
  954. begin
  955. j:=Ord(s[code])-Ord('0');
  956. { check overflow }
  957. if (res <= Int64Edge) or (res <= (MaxInt64 - j) div 10) then
  958. begin
  959. res:=res*10 + j;
  960. Inc(i);
  961. end
  962. else
  963. if power = 0 then
  964. { exit if integer part overflow }
  965. exit
  966. else
  967. begin
  968. if not FracOverflow and (j >= 5) and (res < MaxInt64) then
  969. { round if first digit of fractional part overflow }
  970. Inc(res);
  971. FracOverflow:=True;
  972. end;
  973. end;
  974. '.':
  975. begin
  976. if power = 0 then
  977. begin
  978. power:=1;
  979. i:=0;
  980. end
  981. else
  982. exit;
  983. end;
  984. else
  985. break;
  986. end;
  987. Inc(Code);
  988. end;
  989. if (i = 0) and (power = 0) then
  990. exit;
  991. if power <> 0 then
  992. power:=i;
  993. power:=4 - power;
  994. { Exponent? }
  995. if Code <= len then
  996. if s[Code] in ['E', 'e'] then
  997. begin
  998. Inc(Code);
  999. if Code > len then
  1000. exit;
  1001. i:=1;
  1002. case s[Code] of
  1003. '+':
  1004. Inc(Code);
  1005. '-':
  1006. begin
  1007. i:=-1;
  1008. Inc(Code);
  1009. end;
  1010. end;
  1011. { read exponent }
  1012. j:=0;
  1013. while Code <= len do
  1014. if s[Code] in ['0'..'9'] then
  1015. begin
  1016. if j > 4951 then
  1017. exit;
  1018. j:=j*10 + (Ord(s[code])-Ord('0'));
  1019. Inc(Code);
  1020. end
  1021. else
  1022. exit;
  1023. power:=power + j*i;
  1024. end
  1025. else
  1026. exit;
  1027. if power > 0 then
  1028. begin
  1029. for i:=1 to power do
  1030. if res <= Int64Edge2 then
  1031. res:=res*10
  1032. else
  1033. exit;
  1034. end
  1035. else
  1036. for i:=1 to -power do
  1037. begin
  1038. if res <= MaxInt64 - 5 then
  1039. Inc(res, 5);
  1040. res:=res div 10;
  1041. end;
  1042. res:=res*sign;
  1043. fpc_Val_Currency_ShortStr:=PCurrency(@res)^;
  1044. Code:=0;
  1045. end;
  1046. Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
  1047. begin
  1048. If Len > High(S) then
  1049. Len := High(S);
  1050. SetLength(S,Len);
  1051. If Buf<>Nil then
  1052. begin
  1053. Move (Buf[0],S[1],Len);
  1054. end;
  1055. end;