sstrings.inc 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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 : qword;
  337. begin
  338. { default value for length is -32767 }
  339. if len=-32767 then
  340. len:=25;
  341. if PInt64(@c)^ >= 0 then
  342. begin
  343. ic:=QWord(PInt64(@c)^);
  344. sign:=0;
  345. end
  346. else
  347. begin
  348. sign:=1;
  349. ic:=QWord(-PInt64(@c)^);
  350. end;
  351. { converting to integer string }
  352. tlen:=0;
  353. repeat
  354. Inc(tlen);
  355. buf[tlen]:=Chr(ic mod 10 + $30);
  356. ic:=ic div 10;
  357. until ic = 0;
  358. { calculating:
  359. reslen - length of result string,
  360. r - rounding or appending zeroes,
  361. point - place of decimal point }
  362. reslen:=tlen;
  363. if f <> 0 then
  364. Inc(reslen); { adding decimal point length }
  365. if f < 0 then
  366. begin
  367. { scientific format }
  368. Inc(reslen,5); { adding length of sign and exponent }
  369. if len < MinLen then
  370. len:=MinLen;
  371. r:=reslen-len;
  372. if reslen < len then
  373. reslen:=len;
  374. if r > 0 then
  375. begin
  376. reslen:=len;
  377. point:=tlen - r;
  378. end
  379. else
  380. point:=tlen;
  381. end
  382. else
  383. begin
  384. { fixed format }
  385. Inc(reslen, sign);
  386. { prepending fractional part with zeroes }
  387. while tlen < 5 do
  388. begin
  389. Inc(reslen);
  390. Inc(tlen);
  391. buf[tlen]:='0';
  392. end;
  393. { Currency have 4 digits in fractional part }
  394. r:=4 - f;
  395. point:=f;
  396. if point <> 0 then
  397. begin
  398. if point > 4 then
  399. point:=4;
  400. Inc(point);
  401. end;
  402. Dec(reslen,r);
  403. end;
  404. { rounding string if r > 0 }
  405. if r > 0 then
  406. begin
  407. i:=1;
  408. k:=0;
  409. for j:=0 to r do
  410. begin
  411. buf[i]:=chr(ord(buf[i]) + k);
  412. if buf[i] >= '5' then
  413. k:=1
  414. else
  415. k:=0;
  416. Inc(i);
  417. if i>tlen then
  418. break;
  419. end;
  420. end;
  421. { preparing result string }
  422. if reslen<len then
  423. reslen:=len;
  424. if reslen>High(s) then
  425. begin
  426. if r < 0 then
  427. Inc(r, reslen - High(s));
  428. reslen:=High(s);
  429. end;
  430. SetLength(s,reslen);
  431. j:=reslen;
  432. if f<0 then
  433. begin
  434. { writing power of 10 part }
  435. if PInt64(@c)^ = 0 then
  436. k:=0
  437. else
  438. k:=tlen-5;
  439. if k >= 0 then
  440. s[j-2]:='+'
  441. else
  442. begin
  443. s[j-2]:='-';
  444. k:=-k;
  445. end;
  446. s[j]:=Chr(k mod 10 + $30);
  447. Dec(j);
  448. s[j]:=Chr(k div 10 + $30);
  449. Dec(j,2);
  450. s[j]:='E';
  451. Dec(j);
  452. end;
  453. { writing extra zeroes if r < 0 }
  454. while r < 0 do
  455. begin
  456. s[j]:='0';
  457. Dec(j);
  458. Inc(r);
  459. end;
  460. { writing digits and decimal point }
  461. for i:=r + 1 to tlen do
  462. begin
  463. Dec(point);
  464. if point = 0 then
  465. begin
  466. s[j]:='.';
  467. Dec(j);
  468. end;
  469. s[j]:=buf[i];
  470. Dec(j);
  471. end;
  472. { writing sign }
  473. if sign = 1 then
  474. begin
  475. s[j]:='-';
  476. Dec(j);
  477. end;
  478. { writing spaces }
  479. while j > 0 do
  480. begin
  481. s[j]:=' ';
  482. Dec(j);
  483. end;
  484. end;
  485. {
  486. Array Of Char Str() helpers
  487. }
  488. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  489. var
  490. ss : shortstring;
  491. maxlen : SizeInt;
  492. begin
  493. int_str(v,ss);
  494. if length(ss)<len then
  495. ss:=space(len-length(ss))+ss;
  496. if length(ss)<high(a)+1 then
  497. maxlen:=length(ss)
  498. else
  499. maxlen:=high(a)+1;
  500. move(ss[1],pchar(@a)^,maxlen);
  501. end;
  502. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  503. var
  504. ss : shortstring;
  505. maxlen : SizeInt;
  506. begin
  507. int_str(v,ss);
  508. if length(ss)<len then
  509. ss:=space(len-length(ss))+ss;
  510. if length(ss)<high(a)+1 then
  511. maxlen:=length(ss)
  512. else
  513. maxlen:=high(a)+1;
  514. move(ss[1],pchar(@a)^,maxlen);
  515. end;
  516. {$ifndef CPU64}
  517. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  518. var
  519. ss : shortstring;
  520. maxlen : SizeInt;
  521. begin
  522. int_str(v,ss);
  523. if length(ss)<len then
  524. ss:=space(len-length(ss))+ss;
  525. if length(ss)<high(a)+1 then
  526. maxlen:=length(ss)
  527. else
  528. maxlen:=high(a)+1;
  529. move(ss[1],pchar(@a)^,maxlen);
  530. end;
  531. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  532. var
  533. ss : shortstring;
  534. maxlen : SizeInt;
  535. begin
  536. int_str(v,ss);
  537. if length(ss)<len then
  538. ss:=space(len-length(ss))+ss;
  539. if length(ss)<high(a)+1 then
  540. maxlen:=length(ss)
  541. else
  542. maxlen:=high(a)+1;
  543. move(ss[1],pchar(@a)^,maxlen);
  544. end;
  545. {$endif CPU64}
  546. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  547. var
  548. ss : shortstring;
  549. maxlen : SizeInt;
  550. begin
  551. str_real(len,fr,d,treal_type(rt),ss);
  552. if length(ss)<high(a)+1 then
  553. maxlen:=length(ss)
  554. else
  555. maxlen:=high(a)+1;
  556. move(ss[1],pchar(@a)^,maxlen);
  557. end;
  558. {$ifdef FPC_HAS_STR_CURRENCY}
  559. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  560. var
  561. ss : shortstring;
  562. maxlen : SizeInt;
  563. begin
  564. str(c:len:fr,ss);
  565. if length(ss)<high(a)+1 then
  566. maxlen:=length(ss)
  567. else
  568. maxlen:=high(a)+1;
  569. move(ss[1],pchar(@a)^,maxlen);
  570. end;
  571. {$endif FPC_HAS_STR_CURRENCY}
  572. {*****************************************************************************
  573. Val() Functions
  574. *****************************************************************************}
  575. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  576. var
  577. Code : SizeInt;
  578. begin
  579. {Skip Spaces and Tab}
  580. code:=1;
  581. while (code<=length(s)) and (s[code] in [' ',#9]) do
  582. inc(code);
  583. {Sign}
  584. negativ:=false;
  585. case s[code] of
  586. '-' : begin
  587. negativ:=true;
  588. inc(code);
  589. end;
  590. '+' : inc(code);
  591. end;
  592. {Base}
  593. base:=10;
  594. if code<=length(s) then
  595. begin
  596. case s[code] of
  597. '$',
  598. 'X',
  599. 'x' : begin
  600. base:=16;
  601. inc(code);
  602. end;
  603. '%' : begin
  604. base:=2;
  605. inc(code);
  606. end;
  607. '&' : begin
  608. Base:=8;
  609. inc(code);
  610. end;
  611. '0' : begin
  612. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  613. begin
  614. inc(code, 2);
  615. base := 16;
  616. end;
  617. end;
  618. end;
  619. end;
  620. { strip leading zeros }
  621. while ((code < length(s)) and (s[code] = '0')) do begin
  622. inc(code);
  623. end;
  624. InitVal:=code;
  625. end;
  626. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  627. var
  628. u, temp, prev, maxPrevValue, maxNewValue: ValUInt;
  629. base : byte;
  630. negative : boolean;
  631. begin
  632. fpc_Val_SInt_ShortStr := 0;
  633. Temp:=0;
  634. Code:=InitVal(s,negative,base);
  635. if Code>length(s) then
  636. exit;
  637. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  638. if (base = 10) then
  639. maxNewValue := MaxSIntValue + ord(negative)
  640. else
  641. maxNewValue := MaxUIntValue;
  642. while Code<=Length(s) do
  643. begin
  644. case s[Code] of
  645. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  646. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  647. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  648. else
  649. u:=16;
  650. end;
  651. Prev := Temp;
  652. Temp := Temp*ValUInt(base);
  653. If (u >= base) or
  654. (ValUInt(maxNewValue-u) < Temp) or
  655. (prev > maxPrevValue) Then
  656. Begin
  657. fpc_Val_SInt_ShortStr := 0;
  658. Exit
  659. End;
  660. Temp:=Temp+u;
  661. inc(code);
  662. end;
  663. code := 0;
  664. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  665. If Negative Then
  666. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  667. If Not(Negative) and (base <> 10) Then
  668. {sign extend the result to allow proper range checking}
  669. Case DestSize of
  670. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  671. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  672. {$ifdef cpu64}
  673. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  674. {$endif cpu64}
  675. End;
  676. end;
  677. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  678. { we have to pass the DestSize parameter on (JM) }
  679. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  680. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  681. var
  682. u, prev : ValUInt;
  683. base : byte;
  684. negative : boolean;
  685. begin
  686. fpc_Val_UInt_Shortstr:=0;
  687. Code:=InitVal(s,negative,base);
  688. If Negative or (Code>length(s)) Then
  689. Exit;
  690. while Code<=Length(s) do
  691. begin
  692. case s[Code] of
  693. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  694. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  695. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  696. else
  697. u:=16;
  698. end;
  699. prev := fpc_Val_UInt_Shortstr;
  700. If (u>=base) or
  701. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  702. begin
  703. fpc_Val_UInt_Shortstr:=0;
  704. exit;
  705. end;
  706. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  707. inc(code);
  708. end;
  709. code := 0;
  710. end;
  711. {$ifndef CPU64}
  712. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  713. type
  714. QWordRec = packed record
  715. l1,l2: longint;
  716. end;
  717. var
  718. u, temp, prev, maxint64, maxqword : qword;
  719. base : byte;
  720. negative : boolean;
  721. begin
  722. fpc_val_int64_shortstr := 0;
  723. Temp:=0;
  724. Code:=InitVal(s,negative,base);
  725. if Code>length(s) then
  726. exit;
  727. { high(int64) produces 0 in version 1.0 (JM) }
  728. with qwordrec(maxint64) do
  729. begin
  730. {$ifdef ENDIAN_LITTLE}
  731. l1 := longint($ffffffff);
  732. l2 := $7fffffff;
  733. {$else ENDIAN_LITTLE}
  734. l1 := $7fffffff;
  735. l2 := longint($ffffffff);
  736. {$endif ENDIAN_LITTLE}
  737. end;
  738. with qwordrec(maxqword) do
  739. begin
  740. l1 := longint($ffffffff);
  741. l2 := longint($ffffffff);
  742. end;
  743. while Code<=Length(s) do
  744. begin
  745. case s[Code] of
  746. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  747. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  748. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  749. else
  750. u:=16;
  751. end;
  752. Prev:=Temp;
  753. Temp:=Temp*Int64(base);
  754. If (u >= base) or
  755. ((base = 10) and
  756. (maxint64-temp+ord(negative) < u)) or
  757. ((base <> 10) and
  758. (qword(maxqword-temp) < u)) or
  759. (prev > maxqword div qword(base)) Then
  760. Begin
  761. fpc_val_int64_shortstr := 0;
  762. Exit
  763. End;
  764. Temp:=Temp+u;
  765. inc(code);
  766. end;
  767. code:=0;
  768. fpc_val_int64_shortstr:=int64(Temp);
  769. If Negative Then
  770. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  771. end;
  772. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  773. type qwordrec = packed record
  774. l1,l2: longint;
  775. end;
  776. var
  777. u, prev, maxqword: QWord;
  778. base : byte;
  779. negative : boolean;
  780. begin
  781. fpc_val_qword_shortstr:=0;
  782. Code:=InitVal(s,negative,base);
  783. If Negative or (Code>length(s)) Then
  784. Exit;
  785. with qwordrec(maxqword) do
  786. begin
  787. l1 := longint($ffffffff);
  788. l2 := longint($ffffffff);
  789. end;
  790. while Code<=Length(s) do
  791. begin
  792. case s[Code] of
  793. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  794. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  795. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  796. else
  797. u:=16;
  798. end;
  799. prev := fpc_val_qword_shortstr;
  800. If (u>=base) or
  801. ((QWord(maxqword-u) div QWord(base))<prev) then
  802. Begin
  803. fpc_val_qword_shortstr := 0;
  804. Exit
  805. End;
  806. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  807. inc(code);
  808. end;
  809. code := 0;
  810. end;
  811. {$endif CPU64}
  812. const
  813. {$ifdef FPC_HAS_TYPE_EXTENDED}
  814. valmaxexpnorm=4932;
  815. {$else}
  816. {$ifdef FPC_HAS_TYPE_DOUBLE}
  817. valmaxexpnorm=308;
  818. {$else}
  819. {$ifdef FPC_HAS_TYPE_SINGLE}
  820. valmaxexpnorm=38;
  821. {$else}
  822. {$error Unknown floating point precision }
  823. {$endif}
  824. {$endif}
  825. {$endif}
  826. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  827. var
  828. hd,
  829. esign,sign : valreal;
  830. exponent,i : SizeInt;
  831. flags : byte;
  832. begin
  833. fpc_Val_Real_ShortStr:=0.0;
  834. code:=1;
  835. exponent:=0;
  836. esign:=1;
  837. flags:=0;
  838. sign:=1;
  839. while (code<=length(s)) and (s[code] in [' ',#9]) do
  840. inc(code);
  841. if code<=length(s) then
  842. case s[code] of
  843. '+' : inc(code);
  844. '-' : begin
  845. sign:=-1;
  846. inc(code);
  847. end;
  848. end;
  849. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  850. begin
  851. { Read integer part }
  852. flags:=flags or 1;
  853. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  854. inc(code);
  855. end;
  856. { Decimal ? }
  857. if (length(s)>=code) and (s[code]='.') then
  858. begin
  859. hd:=1.0;
  860. inc(code);
  861. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  862. begin
  863. { Read fractional part. }
  864. flags:=flags or 2;
  865. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  866. hd:=hd*10.0;
  867. inc(code);
  868. end;
  869. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  870. end;
  871. { Again, read integer and fractional part}
  872. if flags=0 then
  873. begin
  874. fpc_Val_Real_ShortStr:=0.0;
  875. exit;
  876. end;
  877. { Exponent ? }
  878. if (length(s)>=code) and (upcase(s[code])='E') then
  879. begin
  880. inc(code);
  881. if Length(s) >= code then
  882. if s[code]='+' then
  883. inc(code)
  884. else
  885. if s[code]='-' then
  886. begin
  887. esign:=-1;
  888. inc(code);
  889. end;
  890. if (length(s)<code) or not(s[code] in ['0'..'9']) then
  891. begin
  892. fpc_Val_Real_ShortStr:=0.0;
  893. exit;
  894. end;
  895. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  896. begin
  897. exponent:=exponent*10;
  898. exponent:=exponent+ord(s[code])-ord('0');
  899. inc(code);
  900. end;
  901. end;
  902. { evaluate sign }
  903. { (before exponent, because the exponent may turn it into a denormal) }
  904. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  905. { Calculate Exponent }
  906. hd:=1.0;
  907. { the magnitude range maximum (normal) is lower in absolute value than the }
  908. { the magnitude range minimum (denormal). E.g. an extended value can go }
  909. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  910. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  911. if (exponent>valmaxexpnorm-2) then
  912. begin
  913. for i:=1 to valmaxexpnorm-2 do
  914. hd:=hd*10.0;
  915. if esign>0 then
  916. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  917. else
  918. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  919. dec(exponent,valmaxexpnorm-2);
  920. hd:=1.0;
  921. end;
  922. for i:=1 to exponent do
  923. hd:=hd*10.0;
  924. if esign>0 then
  925. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  926. else
  927. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  928. { Not all characters are read ? }
  929. if length(s)>=code then
  930. begin
  931. fpc_Val_Real_ShortStr:=0.0;
  932. exit;
  933. end;
  934. { success ! }
  935. code:=0;
  936. end;
  937. Function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  938. const
  939. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  940. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  941. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  942. var
  943. res : Int64;
  944. i,j,power,sign,len : longint;
  945. FracOverflow : boolean;
  946. begin
  947. fpc_Val_Currency_ShortStr:=0;
  948. res:=0;
  949. len:=Length(s);
  950. Code:=1;
  951. sign:=1;
  952. power:=0;
  953. while True do
  954. if Code > len then
  955. exit
  956. else
  957. if s[Code] in [' ', #9] then
  958. Inc(Code)
  959. else
  960. break;
  961. { Read sign }
  962. case s[Code] of
  963. '+' : Inc(Code);
  964. '-' : begin
  965. sign:=-1;
  966. inc(code);
  967. end;
  968. end;
  969. { Read digits }
  970. FracOverflow:=False;
  971. i:=0;
  972. while Code <= len do
  973. begin
  974. case s[Code] of
  975. '0'..'9':
  976. begin
  977. j:=Ord(s[code])-Ord('0');
  978. { check overflow }
  979. if (res <= Int64Edge) or (res <= (MaxInt64 - j) div 10) then
  980. begin
  981. res:=res*10 + j;
  982. Inc(i);
  983. end
  984. else
  985. if power = 0 then
  986. { exit if integer part overflow }
  987. exit
  988. else
  989. begin
  990. if not FracOverflow and (j >= 5) and (res < MaxInt64) then
  991. { round if first digit of fractional part overflow }
  992. Inc(res);
  993. FracOverflow:=True;
  994. end;
  995. end;
  996. '.':
  997. begin
  998. if power = 0 then
  999. begin
  1000. power:=1;
  1001. i:=0;
  1002. end
  1003. else
  1004. exit;
  1005. end;
  1006. else
  1007. break;
  1008. end;
  1009. Inc(Code);
  1010. end;
  1011. if (i = 0) and (power = 0) then
  1012. exit;
  1013. if power <> 0 then
  1014. power:=i;
  1015. power:=4 - power;
  1016. { Exponent? }
  1017. if Code <= len then
  1018. if s[Code] in ['E', 'e'] then
  1019. begin
  1020. Inc(Code);
  1021. if Code > len then
  1022. exit;
  1023. i:=1;
  1024. case s[Code] of
  1025. '+':
  1026. Inc(Code);
  1027. '-':
  1028. begin
  1029. i:=-1;
  1030. Inc(Code);
  1031. end;
  1032. end;
  1033. { read exponent }
  1034. j:=0;
  1035. while Code <= len do
  1036. if s[Code] in ['0'..'9'] then
  1037. begin
  1038. if j > 4951 then
  1039. exit;
  1040. j:=j*10 + (Ord(s[code])-Ord('0'));
  1041. Inc(Code);
  1042. end
  1043. else
  1044. exit;
  1045. power:=power + j*i;
  1046. end
  1047. else
  1048. exit;
  1049. if power > 0 then
  1050. begin
  1051. for i:=1 to power do
  1052. if res <= Int64Edge2 then
  1053. res:=res*10
  1054. else
  1055. exit;
  1056. end
  1057. else
  1058. for i:=1 to -power do
  1059. begin
  1060. if res <= MaxInt64 - 5 then
  1061. Inc(res, 5);
  1062. res:=res div 10;
  1063. end;
  1064. res:=res*sign;
  1065. fpc_Val_Currency_ShortStr:=PCurrency(@res)^;
  1066. Code:=0;
  1067. end;
  1068. Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
  1069. begin
  1070. If Len > High(S) then
  1071. Len := High(S);
  1072. SetLength(S,Len);
  1073. If Buf<>Nil then
  1074. begin
  1075. Move (Buf[0],S[1],Len);
  1076. end;
  1077. end;