sstrings.inc 27 KB

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