sstrings.inc 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988
  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. {$ifndef FPC_HAS_SHORTSTR_SETLENGTH}
  14. {$define FPC_HAS_SHORTSTR_SETLENGTH}
  15. procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; compilerproc;
  16. begin
  17. if Len>255 then
  18. Len:=255;
  19. s[0]:=chr(len);
  20. end;
  21. {$endif FPC_HAS_SHORTSTR_SETLENGTH}
  22. {$ifndef FPC_HAS_SHORTSTR_COPY}
  23. {$define FPC_HAS_SHORTSTR_COPY}
  24. function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  25. begin
  26. if count<0 then
  27. count:=0;
  28. if index>1 then
  29. dec(index)
  30. else
  31. index:=0;
  32. if index>length(s) then
  33. count:=0
  34. else
  35. if count>length(s)-index then
  36. count:=length(s)-index;
  37. fpc_shortstr_Copy[0]:=chr(Count);
  38. fpc_shortstr_shortstr_intern_charmove(s,Index+1,fpc_shortstr_Copy,1,Count);
  39. end;
  40. {$endif FPC_HAS_SHORTSTR_COPY}
  41. {$ifndef FPC_HAS_SHORTSTR_DELETE}
  42. {$define FPC_HAS_SHORTSTR_DELETE}
  43. procedure delete(var s : shortstring;index : SizeInt;count : SizeInt);
  44. begin
  45. if index<=0 then
  46. exit;
  47. if (Index<=Length(s)) and (Count>0) then
  48. begin
  49. if Count>length(s)-Index then
  50. Count:=length(s)-Index+1;
  51. s[0]:=Chr(length(s)-Count);
  52. if Index<=Length(s) then
  53. fpc_shortstr_shortstr_intern_charmove(s,Index+Count,s,Index,Length(s)-Index+1);
  54. end;
  55. end;
  56. {$endif FPC_HAS_SHORTSTR_DELETE}
  57. {$ifndef FPC_HAS_SHORTSTR_INSERT}
  58. {$define FPC_HAS_SHORTSTR_INSERT}
  59. procedure insert(const source : shortstring;var s : shortstring;index : SizeInt);
  60. var
  61. cut,srclen,indexlen : SizeInt;
  62. begin
  63. if index<1 then
  64. index:=1;
  65. if index>length(s) then
  66. begin
  67. index:=length(s)+1;
  68. if index>high(s) then
  69. exit;
  70. end;
  71. indexlen:=Length(s)-Index+1;
  72. srclen:=length(Source);
  73. if sizeInt(length(source))+sizeint(length(s))>=sizeof(s) then
  74. begin
  75. cut:=sizeInt(length(source))+sizeint(length(s))-sizeof(s)+1;
  76. if cut>indexlen then
  77. begin
  78. dec(srclen,cut-indexlen);
  79. indexlen:=0;
  80. end
  81. else
  82. dec(indexlen,cut);
  83. end;
  84. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+srclen,indexlen);
  85. fpc_shortstr_shortstr_intern_charmove(Source,1,s,Index,srclen);
  86. s[0]:=chr(index+srclen+indexlen-1);
  87. end;
  88. {$endif FPC_HAS_SHORTSTR_INSERT}
  89. {$ifndef FPC_HAS_SHORTSTR_INSERT_CHAR}
  90. {$define FPC_HAS_SHORTSTR_INSERT_CHAR}
  91. procedure insert(source : Char;var s : shortstring;index : SizeInt);
  92. var
  93. indexlen : SizeInt;
  94. begin
  95. if index<1 then
  96. index:=1;
  97. if index>length(s) then
  98. begin
  99. index:=length(s)+1;
  100. if index>high(s) then
  101. exit;
  102. end;
  103. indexlen:=Length(s)-Index+1;
  104. if (sizeint(length(s))+1=sizeof(s)) and (indexlen>0) then
  105. dec(indexlen);
  106. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+1,indexlen);
  107. s[Index]:=Source;
  108. s[0]:=chr(index+indexlen);
  109. end;
  110. {$endif FPC_HAS_SHORTSTR_INSERT_CHAR}
  111. {$ifndef FPC_HAS_SHORTSTR_POS_SHORTSTR}
  112. {$define FPC_HAS_SHORTSTR_POS_SHORTSTR}
  113. function pos(const substr : shortstring;const s : shortstring):SizeInt;
  114. var
  115. i,MaxLen : SizeInt;
  116. pc : pchar;
  117. begin
  118. Pos:=0;
  119. if Length(SubStr)>0 then
  120. begin
  121. MaxLen:=sizeint(Length(s))-Length(SubStr);
  122. i:=0;
  123. pc:=@s[1];
  124. while (i<=MaxLen) do
  125. begin
  126. inc(i);
  127. if (SubStr[1]=pc^) and
  128. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  129. begin
  130. Pos:=i;
  131. exit;
  132. end;
  133. inc(pc);
  134. end;
  135. end;
  136. end;
  137. {$endif FPC_HAS_SHORTSTR_POS_SHORTSTR}
  138. {$ifndef FPC_HAS_SHORTSTR_POS_CHAR}
  139. {$define FPC_HAS_SHORTSTR_POS_CHAR}
  140. {Faster when looking for a single char...}
  141. function pos(c:char;const s:shortstring):SizeInt;
  142. var
  143. i : SizeInt;
  144. pc : pchar;
  145. begin
  146. pc:=@s[1];
  147. for i:=1 to length(s) do
  148. begin
  149. if pc^=c then
  150. begin
  151. pos:=i;
  152. exit;
  153. end;
  154. inc(pc);
  155. end;
  156. pos:=0;
  157. end;
  158. {$endif FPC_HAS_SHORTSTR_POS_CHAR}
  159. function fpc_char_copy(c:char;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  160. begin
  161. if (index=1) and (Count>0) then
  162. fpc_char_Copy:=c
  163. else
  164. fpc_char_Copy:='';
  165. end;
  166. function pos(const substr : shortstring;c:char): SizeInt;
  167. begin
  168. if (length(substr)=1) and (substr[1]=c) then
  169. Pos:=1
  170. else
  171. Pos:=0;
  172. end;
  173. {$if not defined(FPC_UPCASE_CHAR) or not defined(FPC_LOWERCASE_CHAR)}
  174. {$ifdef IBM_CHAR_SET}
  175. const
  176. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  177. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  178. {$endif}
  179. {$endif}
  180. {$ifndef FPC_UPCASE_CHAR}
  181. {$define FPC_UPCASE_CHAR}
  182. function upcase(c : char) : char;
  183. {$IFDEF IBM_CHAR_SET}
  184. var
  185. i : sizeint;
  186. {$ENDIF}
  187. begin
  188. if (c in ['a'..'z']) then
  189. upcase:=char(byte(c)-32)
  190. else
  191. {$IFDEF IBM_CHAR_SET}
  192. begin
  193. i:=Pos(c,LoCaseTbl);
  194. if i>0 then
  195. upcase:=UpCaseTbl[i]
  196. else
  197. upcase:=c;
  198. end;
  199. {$ELSE}
  200. upcase:=c;
  201. {$ENDIF}
  202. end;
  203. {$endif FPC_UPCASE_CHAR}
  204. {$ifndef FPC_UPCASE_SHORTSTR}
  205. {$define FPC_UPCASE_SHORTSTR}
  206. function upcase(const s : shortstring) : shortstring;
  207. var
  208. i : sizeint;
  209. begin
  210. upcase[0]:=s[0];
  211. for i := 1 to length (s) do
  212. upcase[i] := upcase (s[i]);
  213. end;
  214. {$endif FPC_UPCASE_SHORTSTR}
  215. {$ifndef FPC_LOWERCASE_CHAR}
  216. {$define FPC_LOWERCASE_CHAR}
  217. function lowercase(c : char) : char;overload;
  218. {$IFDEF IBM_CHAR_SET}
  219. var
  220. i : sizeint;
  221. {$ENDIF}
  222. begin
  223. if (c in ['A'..'Z']) then
  224. lowercase:=char(byte(c)+32)
  225. else
  226. {$IFDEF IBM_CHAR_SET}
  227. begin
  228. i:=Pos(c,UpCaseTbl);
  229. if i>0 then
  230. lowercase:=LoCaseTbl[i]
  231. else
  232. lowercase:=c;
  233. end;
  234. {$ELSE}
  235. lowercase:=c;
  236. {$ENDIF}
  237. end;
  238. {$endif FPC_LOWERCASE_CHAR}
  239. {$ifndef FPC_LOWERCASE_SHORTSTR}
  240. {$define FPC_LOWERCASE_SHORTSTR}
  241. function lowercase(const s : shortstring) : shortstring; overload;
  242. var
  243. i : sizeint;
  244. begin
  245. lowercase [0]:=s[0];
  246. for i:=1 to length(s) do
  247. lowercase[i]:=lowercase (s[i]);
  248. end;
  249. {$endif FPC_LOWERCASE_SHORTSTR}
  250. const
  251. HexTbl : array[0..15] of char='0123456789ABCDEF';
  252. function hexstr(val : longint;cnt : byte) : shortstring;
  253. var
  254. i : sizeint;
  255. begin
  256. hexstr[0]:=char(cnt);
  257. for i:=cnt downto 1 do
  258. begin
  259. hexstr[i]:=hextbl[val and $f];
  260. val:=val shr 4;
  261. end;
  262. end;
  263. function octstr(val : longint;cnt : byte) : shortstring;
  264. var
  265. i : sizeint;
  266. begin
  267. octstr[0]:=char(cnt);
  268. for i:=cnt downto 1 do
  269. begin
  270. octstr[i]:=hextbl[val and 7];
  271. val:=val shr 3;
  272. end;
  273. end;
  274. function binstr(val : longint;cnt : byte) : shortstring;
  275. var
  276. i : sizeint;
  277. begin
  278. binstr[0]:=char(cnt);
  279. for i:=cnt downto 1 do
  280. begin
  281. binstr[i]:=char(48+val and 1);
  282. val:=val shr 1;
  283. end;
  284. end;
  285. function hexstr(val : int64;cnt : byte) : shortstring;
  286. var
  287. i : sizeint;
  288. begin
  289. hexstr[0]:=char(cnt);
  290. for i:=cnt downto 1 do
  291. begin
  292. hexstr[i]:=hextbl[val and $f];
  293. val:=val shr 4;
  294. end;
  295. end;
  296. function octstr(val : int64;cnt : byte) : shortstring;
  297. var
  298. i : sizeint;
  299. begin
  300. octstr[0]:=char(cnt);
  301. for i:=cnt downto 1 do
  302. begin
  303. octstr[i]:=hextbl[val and 7];
  304. val:=val shr 3;
  305. end;
  306. end;
  307. function binstr(val : int64;cnt : byte) : shortstring;
  308. var
  309. i : sizeint;
  310. begin
  311. binstr[0]:=char(cnt);
  312. for i:=cnt downto 1 do
  313. begin
  314. binstr[i]:=char(48+val and 1);
  315. val:=val shr 1;
  316. end;
  317. end;
  318. {$ifndef FPC_HAS_QWORD_HEX_SHORTSTR}
  319. {$define FPC_HAS_QWORD_HEX_SHORTSTR}
  320. Function hexStr(Val:qword;cnt:byte):shortstring;
  321. begin
  322. hexStr:=hexStr(int64(Val),cnt);
  323. end;
  324. {$endif FPC_HAS_QWORD_HEX_SHORTSTR}
  325. {$ifndef FPC_HAS_QWORD_OCT_SHORTSTR}
  326. {$define FPC_HAS_QWORD_OCT_SHORTSTR}
  327. Function OctStr(Val:qword;cnt:byte):shortstring;
  328. begin
  329. OctStr:=OctStr(int64(Val),cnt);
  330. end;
  331. {$endif FPC_HAS_QWORD_OCT_SHORTSTR}
  332. {$ifndef FPC_HAS_QWORD_BIN_SHORTSTR}
  333. {$define FPC_HAS_QWORD_BIN_SHORTSTR}
  334. Function binStr(Val:qword;cnt:byte):shortstring;
  335. begin
  336. binStr:=binStr(int64(Val),cnt);
  337. end;
  338. {$endif FPC_HAS_QWORD_BIN_SHORTSTR}
  339. {$ifndef FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  340. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  341. function hexstr(val : pointer) : shortstring;
  342. var
  343. i : sizeint;
  344. v : ptruint;
  345. begin
  346. v:=ptruint(val);
  347. hexstr[0]:=chr(sizeof(pointer)*2);
  348. for i:=sizeof(pointer)*2 downto 1 do
  349. begin
  350. hexstr[i]:=hextbl[v and $f];
  351. v:=v shr 4;
  352. end;
  353. end;
  354. {$endif FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  355. {$ifndef FPC_HAS_SPACE_SHORTSTR}
  356. {$define FPC_HAS_SPACE_SHORTSTR}
  357. function space (b : byte): shortstring;
  358. begin
  359. space[0] := chr(b);
  360. FillChar (Space[1],b,' ');
  361. end;
  362. {$endif FPC_HAS_SPACE_SHORTSTR}
  363. {*****************************************************************************
  364. Str() Helpers
  365. *****************************************************************************}
  366. procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
  367. begin
  368. int_str(v,s);
  369. if length(s)<len then
  370. s:=space(len-length(s))+s;
  371. end;
  372. procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
  373. begin
  374. int_str_unsigned(v,s);
  375. if length(s)<len then
  376. s:=space(len-length(s))+s;
  377. end;
  378. {$ifndef CPU64}
  379. procedure fpc_shortstr_qword(v : qword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
  380. begin
  381. int_str_unsigned(v,s);
  382. if length(s)<len then
  383. s:=space(len-length(s))+s;
  384. end;
  385. procedure fpc_shortstr_int64(v : int64;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
  386. begin
  387. int_str(v,s);
  388. if length(s)<len then
  389. s:=space(len-length(s))+s;
  390. end;
  391. {$endif CPU64}
  392. {$if defined(CPU16) or defined(CPU8)}
  393. procedure fpc_shortstr_longword(v : longword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGWORD']; compilerproc;
  394. begin
  395. int_str_unsigned(v,s);
  396. if length(s)<len then
  397. s:=space(len-length(s))+s;
  398. end;
  399. procedure fpc_shortstr_longint(v : longint;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; compilerproc;
  400. begin
  401. int_str(v,s);
  402. if length(s)<len then
  403. s:=space(len-length(s))+s;
  404. end;
  405. {$endif CPU16 or CPU8}
  406. { fpc_shortstr_sInt must appear before this file is included, because }
  407. { it's used inside real2str.inc and otherwise the searching via the }
  408. { compilerproc name will fail (JM) }
  409. {$ifndef FPUNONE}
  410. {$ifdef FLOAT_ASCII_FALLBACK}
  411. {$I real2str.inc}
  412. {$else not FLOAT_ASCII_FALLBACK}
  413. {$I flt_conv.inc}
  414. {$endif FLOAT_ASCII_FALLBACK}
  415. {$endif}
  416. {$ifndef FPUNONE}
  417. procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  418. begin
  419. str_real(len,fr,d,treal_type(rt),s);
  420. end;
  421. {$endif}
  422. {$ifndef FPC_STR_ENUM_INTERN}
  423. function fpc_shortstr_enum_intern(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring): longint;
  424. { The following contains the TTypeInfo/TTypeData records from typinfo.pp
  425. specialized for the tkEnumeration case (and stripped of unused things). }
  426. type
  427. PPstring=^Pstring;
  428. Penum_typeinfo=^Tenum_typeinfo;
  429. Tenum_typeinfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  430. kind:byte; { always tkEnumeration }
  431. num_chars:byte;
  432. chars:array[0..0] of char; { variable length with size of num_chars }
  433. end;
  434. Penum_typedata=^Tenum_typedata;
  435. Tenum_typedata={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  436. ordtype:byte;
  437. { this seemingly extraneous inner record is here for alignment purposes, so
  438. that its data gets aligned properly (if FPC_REQUIRES_PROPER_ALIGNMENT is
  439. set }
  440. inner: {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  441. minvalue,maxvalue:longint;
  442. basetype:pointer; { required for alignment }
  443. end;
  444. { more data here, but not needed }
  445. end;
  446. { Pascal data types for the ordinal enum value to string table. It consists of a header
  447. that indicates what type of data the table stores, either a direct lookup table (when
  448. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  449. { A single entry in the set of ordered tuples }
  450. Psearch_data=^Tsearch_data;
  451. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  452. value:longint;
  453. name:Pstring;
  454. end;
  455. Penum_ord_to_string=^Tenum_ord_to_string;
  456. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  457. o:(lookup,search);
  458. case integer of
  459. 0: (lookup_data:array[0..0] of Pstring);
  460. 1: (num_entries:longint;
  461. search_data:array[0..0] of Tsearch_data);
  462. end;
  463. var
  464. enum_o2s : Penum_ord_to_string;
  465. header:Penum_typeinfo;
  466. body:Penum_typedata;
  467. res:Pshortstring;
  468. sorted_data:Psearch_data;
  469. spaces,i,m,h,l:longint;
  470. begin
  471. { set default return value }
  472. fpc_shortstr_enum_intern:=107;
  473. enum_o2s:=Penum_ord_to_string(ord2strindex);
  474. { depending on the type of table in ord2strindex retrieve the data }
  475. if (enum_o2s^.o=lookup) then
  476. begin
  477. { direct lookup table }
  478. header:=Penum_typeinfo(typinfo);
  479. { calculate address of enum rtti body: add the actual size of the
  480. enum_rtti_header, and then align. Use an alignment of 1 (which
  481. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  482. to avoid the need for an if in this situation }
  483. body:=Penum_typedata(align(ptruint(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars,
  484. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT} 1 {$else} sizeof(pointer) {$endif}));
  485. with (body^.inner) do
  486. begin
  487. { Bounds check for the ordinal value for this enum }
  488. if (ordinal<minvalue) or (ordinal>maxvalue) then
  489. exit;
  490. { make the ordinal index for lookup zero-based }
  491. dec(ordinal,minvalue);
  492. end;
  493. { temporarily disable range checking because of the access to the array[0..0]
  494. member of Tenum_ord_to_string_lookup }
  495. {$push}{$R-}
  496. res:=enum_o2s^.lookup_data[ordinal];
  497. {$pop}
  498. if (not assigned(res)) then
  499. exit;
  500. s:=res^;
  501. end
  502. else
  503. begin
  504. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  505. sorted_data:=@enum_o2s^.search_data;
  506. { Use a binary search to get the string }
  507. l:=0;
  508. { temporarily disable range checking because of the access to the array[0..0]
  509. member of Tenum_ord_to_string_search }
  510. {$push}{$R-}
  511. h:=enum_o2s^.num_entries-1;
  512. repeat
  513. m:=(l+h) div 2;
  514. if ordinal>sorted_data[m].value then
  515. l:=m+1
  516. else if ordinal<sorted_data[m].value then
  517. h:=m-1
  518. else
  519. break;
  520. if l>h then
  521. exit; { Ordinal value not found? Exit }
  522. until false;
  523. {$pop}
  524. s:=sorted_data[m].name^;
  525. end;
  526. { Pad the string with spaces if necessary }
  527. if (len>length(s)) then
  528. begin
  529. spaces:=len-length(s);
  530. for i:=1 to spaces do
  531. s[length(s)+i]:=' ';
  532. inc(byte(s[0]),spaces);
  533. end;
  534. fpc_shortstr_enum_intern:=0;
  535. end;
  536. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  537. var
  538. res: longint;
  539. begin
  540. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  541. if (res<>0) then
  542. runerror(107);
  543. end;
  544. { also define alias for internal use in the system unit }
  545. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  546. {$endif FPC_SHORTSTR_ENUM_INTERN}
  547. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  548. begin
  549. if b then
  550. s:='TRUE'
  551. else
  552. s:='FALSE';
  553. if length(s)<len then
  554. s:=space(len-length(s))+s;
  555. end;
  556. { also define alias for internal use in the system unit }
  557. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  558. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  559. const
  560. MinLen = 8; { Minimal string length in scientific format }
  561. var
  562. buf : array[1..19] of char;
  563. i,j,k,reslen,tlen,sign,r,point : longint;
  564. ic : qword;
  565. begin
  566. fillchar(buf,length(buf),'0');
  567. { default value for length is -32767 }
  568. if len=-32767 then
  569. len:=25;
  570. if PInt64(@c)^ >= 0 then
  571. begin
  572. ic:=QWord(PInt64(@c)^);
  573. sign:=0;
  574. end
  575. else
  576. begin
  577. sign:=1;
  578. ic:=QWord(-PInt64(@c)^);
  579. end;
  580. { converting to integer string }
  581. tlen:=0;
  582. repeat
  583. Inc(tlen);
  584. buf[tlen]:=Chr(ic mod 10 + $30);
  585. ic:=ic div 10;
  586. until ic = 0;
  587. { calculating:
  588. reslen - length of result string,
  589. r - rounding or appending zeroes,
  590. point - place of decimal point }
  591. reslen:=tlen;
  592. if f <> 0 then
  593. Inc(reslen); { adding decimal point length }
  594. if f < 0 then
  595. begin
  596. { scientific format }
  597. Inc(reslen,5); { adding length of sign and exponent }
  598. if len < MinLen then
  599. len:=MinLen;
  600. r:=reslen-len;
  601. if reslen < len then
  602. reslen:=len;
  603. if r > 0 then
  604. begin
  605. reslen:=len;
  606. point:=tlen - r;
  607. end
  608. else
  609. point:=tlen;
  610. end
  611. else
  612. begin
  613. { fixed format }
  614. Inc(reslen, sign);
  615. { prepending fractional part with zeroes }
  616. while tlen < 5 do
  617. begin
  618. Inc(reslen);
  619. Inc(tlen);
  620. buf[tlen]:='0';
  621. end;
  622. { Currency have 4 digits in fractional part }
  623. r:=4 - f;
  624. point:=f;
  625. if point <> 0 then
  626. begin
  627. if point > 4 then
  628. point:=4;
  629. Inc(point);
  630. end;
  631. Dec(reslen,r);
  632. end;
  633. { rounding string if r > 0 }
  634. if r > 0 then
  635. begin
  636. k := 0;
  637. i := r+2;
  638. if i > tlen then
  639. i := tlen+1;
  640. if buf[i-2] >= '5' then
  641. begin
  642. if buf[i-1] < '9' then
  643. buf[i-1] := chr(ord(buf[i-1])+1)
  644. else
  645. begin
  646. buf[i-1] := '0';
  647. k := 1;
  648. end;
  649. end;
  650. If (k=1) and (buf[i-1]='0') then
  651. begin
  652. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  653. 2.00, i.e. the rounding is propagated
  654. }
  655. while buf[i]='9' do
  656. begin
  657. buf[i]:='0';
  658. inc(i);
  659. end;
  660. buf[i]:=chr(Ord(buf[i])+1);
  661. { did we add another digit? This happens when rounding
  662. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  663. 100.00
  664. }
  665. if i>tlen then
  666. begin
  667. inc(reslen);
  668. inc(tlen);
  669. end;
  670. end;
  671. end;
  672. { preparing result string }
  673. if reslen<len then
  674. reslen:=len;
  675. if reslen>High(s) then
  676. begin
  677. if r < 0 then
  678. Inc(r, reslen - High(s));
  679. reslen:=High(s);
  680. end;
  681. SetLength(s,reslen);
  682. j:=reslen;
  683. if f<0 then
  684. begin
  685. { writing power of 10 part }
  686. if PInt64(@c)^ = 0 then
  687. k:=0
  688. else
  689. k:=tlen-5;
  690. if k >= 0 then
  691. s[j-2]:='+'
  692. else
  693. begin
  694. s[j-2]:='-';
  695. k:=-k;
  696. end;
  697. s[j]:=Chr(k mod 10 + $30);
  698. Dec(j);
  699. s[j]:=Chr(k div 10 + $30);
  700. Dec(j,2);
  701. s[j]:='E';
  702. Dec(j);
  703. end;
  704. { writing extra zeroes if r < 0 }
  705. while r < 0 do
  706. begin
  707. s[j]:='0';
  708. Dec(j);
  709. Inc(r);
  710. end;
  711. { writing digits and decimal point }
  712. for i:=r + 1 to tlen do
  713. begin
  714. Dec(point);
  715. if point = 0 then
  716. begin
  717. s[j]:='.';
  718. Dec(j);
  719. end;
  720. s[j]:=buf[i];
  721. Dec(j);
  722. end;
  723. { writing sign }
  724. if sign = 1 then
  725. begin
  726. s[j]:='-';
  727. Dec(j);
  728. end;
  729. { writing spaces }
  730. while j > 0 do
  731. begin
  732. s[j]:=' ';
  733. Dec(j);
  734. end;
  735. end;
  736. {
  737. Array Of Char Str() helpers
  738. }
  739. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  740. var
  741. ss : shortstring;
  742. maxlen : SizeInt;
  743. begin
  744. int_str(v,ss);
  745. if length(ss)<len then
  746. ss:=space(len-length(ss))+ss;
  747. if length(ss)<high(a)+1 then
  748. maxlen:=length(ss)
  749. else
  750. maxlen:=high(a)+1;
  751. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  752. end;
  753. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  754. var
  755. ss : shortstring;
  756. maxlen : SizeInt;
  757. begin
  758. int_str_unsigned(v,ss);
  759. if length(ss)<len then
  760. ss:=space(len-length(ss))+ss;
  761. if length(ss)<high(a)+1 then
  762. maxlen:=length(ss)
  763. else
  764. maxlen:=high(a)+1;
  765. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  766. end;
  767. {$ifndef CPU64}
  768. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  769. var
  770. ss : shortstring;
  771. maxlen : SizeInt;
  772. begin
  773. int_str_unsigned(v,ss);
  774. if length(ss)<len then
  775. ss:=space(len-length(ss))+ss;
  776. if length(ss)<high(a)+1 then
  777. maxlen:=length(ss)
  778. else
  779. maxlen:=high(a)+1;
  780. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  781. end;
  782. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  783. var
  784. ss : shortstring;
  785. maxlen : SizeInt;
  786. begin
  787. int_str(v,ss);
  788. if length(ss)<len then
  789. ss:=space(len-length(ss))+ss;
  790. if length(ss)<high(a)+1 then
  791. maxlen:=length(ss)
  792. else
  793. maxlen:=high(a)+1;
  794. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  795. end;
  796. {$endif CPU64}
  797. {$if defined(CPU16) or defined(CPU8)}
  798. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of char);compilerproc;
  799. var
  800. ss : shortstring;
  801. maxlen : SizeInt;
  802. begin
  803. int_str_unsigned(v,ss);
  804. if length(ss)<len then
  805. ss:=space(len-length(ss))+ss;
  806. if length(ss)<high(a)+1 then
  807. maxlen:=length(ss)
  808. else
  809. maxlen:=high(a)+1;
  810. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  811. end;
  812. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of char);compilerproc;
  813. var
  814. ss : shortstring;
  815. maxlen : SizeInt;
  816. begin
  817. int_str(v,ss);
  818. if length(ss)<len then
  819. ss:=space(len-length(ss))+ss;
  820. if length(ss)<high(a)+1 then
  821. maxlen:=length(ss)
  822. else
  823. maxlen:=high(a)+1;
  824. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  825. end;
  826. {$endif CPU16 or CPU8}
  827. {$ifndef FPUNONE}
  828. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  829. var
  830. ss : shortstring;
  831. maxlen : SizeInt;
  832. begin
  833. str_real(len,fr,d,treal_type(rt),ss);
  834. if length(ss)<high(a)+1 then
  835. maxlen:=length(ss)
  836. else
  837. maxlen:=high(a)+1;
  838. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  839. end;
  840. {$endif}
  841. {$ifndef FPC_STR_ENUM_INTERN}
  842. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of char);compilerproc;
  843. var
  844. ss : shortstring;
  845. maxlen : SizeInt;
  846. begin
  847. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  848. if length(ss)<high(a)+1 then
  849. maxlen:=length(ss)
  850. else
  851. maxlen:=high(a)+1;
  852. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  853. end;
  854. {$endif not FPC_STR_ENUM_INTERN}
  855. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of char);compilerproc;
  856. var
  857. ss : shortstring;
  858. maxlen : SizeInt;
  859. begin
  860. fpc_shortstr_bool(b,len,ss);
  861. if length(ss)<high(a)+1 then
  862. maxlen:=length(ss)
  863. else
  864. maxlen:=high(a)+1;
  865. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  866. end;
  867. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  868. {$define FPC_HAS_CHARARRAY_CURRENCY}
  869. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  870. var
  871. ss : shortstring;
  872. maxlen : SizeInt;
  873. begin
  874. str(c:len:fr,ss);
  875. if length(ss)<high(a)+1 then
  876. maxlen:=length(ss)
  877. else
  878. maxlen:=high(a)+1;
  879. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  880. end;
  881. {$endif FPC_HAS_STR_CURRENCY}
  882. {*****************************************************************************
  883. Val() Functions
  884. *****************************************************************************}
  885. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  886. var
  887. Code : SizeInt;
  888. begin
  889. code:=1;
  890. negativ:=false;
  891. base:=10;
  892. if length(s)=0 then
  893. begin
  894. InitVal:=code;
  895. Exit;
  896. end;
  897. {Skip Spaces and Tab}
  898. while (code<=length(s)) and (s[code] in [' ',#9]) do
  899. inc(code);
  900. {Sign}
  901. case s[code] of
  902. '-' : begin
  903. negativ:=true;
  904. inc(code);
  905. end;
  906. '+' : inc(code);
  907. end;
  908. {Base}
  909. if code<=length(s) then
  910. begin
  911. case s[code] of
  912. '$',
  913. 'X',
  914. 'x' : begin
  915. base:=16;
  916. inc(code);
  917. end;
  918. '%' : begin
  919. base:=2;
  920. inc(code);
  921. end;
  922. '&' : begin
  923. Base:=8;
  924. inc(code);
  925. end;
  926. '0' : begin
  927. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  928. begin
  929. inc(code, 2);
  930. base := 16;
  931. end;
  932. end;
  933. end;
  934. end;
  935. { strip leading zeros }
  936. while ((code < length(s)) and (s[code] = '0')) do begin
  937. inc(code);
  938. end;
  939. InitVal:=code;
  940. end;
  941. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  942. var
  943. temp, prev, maxPrevValue, maxNewValue: ValUInt;
  944. base,u : byte;
  945. negative : boolean;
  946. begin
  947. fpc_Val_SInt_ShortStr := 0;
  948. Temp:=0;
  949. Code:=InitVal(s,negative,base);
  950. if Code>length(s) then
  951. exit;
  952. if (s[Code]=#0) then
  953. begin
  954. if (Code>1) and (s[Code-1]='0') then
  955. Code:=0;
  956. exit;
  957. end;
  958. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  959. if (base = 10) then
  960. maxNewValue := MaxSIntValue + ord(negative)
  961. else
  962. maxNewValue := MaxUIntValue;
  963. while Code<=Length(s) do
  964. begin
  965. case s[Code] of
  966. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  967. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  968. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  969. #0 : break;
  970. else
  971. u:=16;
  972. end;
  973. Prev := Temp;
  974. Temp := Temp*ValUInt(base);
  975. If (u >= base) or
  976. (ValUInt(maxNewValue-u) < Temp) or
  977. (prev > maxPrevValue) Then
  978. Begin
  979. fpc_Val_SInt_ShortStr := 0;
  980. Exit
  981. End;
  982. Temp:=Temp+u;
  983. inc(code);
  984. end;
  985. code := 0;
  986. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  987. If Negative Then
  988. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  989. If Not(Negative) and (base <> 10) Then
  990. {sign extend the result to allow proper range checking}
  991. Case DestSize of
  992. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  993. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  994. {$ifdef cpu64}
  995. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  996. {$endif cpu64}
  997. End;
  998. end;
  999. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1000. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1001. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  1002. { we have to pass the DestSize parameter on (JM) }
  1003. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1004. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1005. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  1006. var
  1007. base,u : byte;
  1008. negative : boolean;
  1009. begin
  1010. fpc_Val_UInt_Shortstr:=0;
  1011. Code:=InitVal(s,negative,base);
  1012. If Negative or (Code>length(s)) Then
  1013. Exit;
  1014. if (s[Code]=#0) then
  1015. begin
  1016. if (Code>1) and (s[Code-1]='0') then
  1017. Code:=0;
  1018. exit;
  1019. end;
  1020. while Code<=Length(s) do
  1021. begin
  1022. case s[Code] of
  1023. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1024. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1025. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1026. #0 : break;
  1027. else
  1028. u:=16;
  1029. end;
  1030. If (u>=base) or
  1031. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<fpc_val_uint_shortstr) then
  1032. begin
  1033. fpc_Val_UInt_Shortstr:=0;
  1034. exit;
  1035. end;
  1036. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  1037. inc(code);
  1038. end;
  1039. code := 0;
  1040. end;
  1041. {$ifndef CPU64}
  1042. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1043. var u : sizeuint;
  1044. temp, prev, maxprevvalue, maxnewvalue : qword;
  1045. base : byte;
  1046. negative : boolean;
  1047. const maxint64=qword($7fffffffffffffff);
  1048. maxqword=qword($ffffffffffffffff);
  1049. begin
  1050. fpc_val_int64_shortstr := 0;
  1051. Temp:=0;
  1052. Code:=InitVal(s,negative,base);
  1053. if Code>length(s) then
  1054. exit;
  1055. if (s[Code]=#0) then
  1056. begin
  1057. if (Code>1) and (s[Code-1]='0') then
  1058. Code:=0;
  1059. exit;
  1060. end;
  1061. maxprevvalue := maxqword div base;
  1062. if (base = 10) then
  1063. maxnewvalue := maxint64 + ord(negative)
  1064. else
  1065. maxnewvalue := maxqword;
  1066. while Code<=Length(s) do
  1067. begin
  1068. case s[Code] of
  1069. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1070. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1071. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1072. #0 : break;
  1073. else
  1074. u:=16;
  1075. end;
  1076. Prev:=Temp;
  1077. Temp:=Temp*qword(base);
  1078. If (u >= base) or
  1079. (qword(maxnewvalue-u) < temp) or
  1080. (prev > maxprevvalue) Then
  1081. Begin
  1082. fpc_val_int64_shortstr := 0;
  1083. Exit
  1084. End;
  1085. Temp:=Temp+u;
  1086. inc(code);
  1087. end;
  1088. code:=0;
  1089. fpc_val_int64_shortstr:=int64(Temp);
  1090. If Negative Then
  1091. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1092. end;
  1093. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1094. var u : sizeuint;
  1095. base : byte;
  1096. negative : boolean;
  1097. const maxqword=qword($ffffffffffffffff);
  1098. begin
  1099. fpc_val_qword_shortstr:=0;
  1100. Code:=InitVal(s,negative,base);
  1101. If Negative or (Code>length(s)) Then
  1102. Exit;
  1103. if (s[Code]=#0) then
  1104. begin
  1105. if (Code>1) and (s[Code-1]='0') then
  1106. Code:=0;
  1107. exit;
  1108. end;
  1109. while Code<=Length(s) do
  1110. begin
  1111. case s[Code] of
  1112. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1113. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1114. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1115. #0 : break;
  1116. else
  1117. u:=16;
  1118. end;
  1119. If (u>=base) or
  1120. ((QWord(maxqword-u) div QWord(base))<fpc_val_qword_shortstr) then
  1121. Begin
  1122. fpc_val_qword_shortstr := 0;
  1123. Exit
  1124. End;
  1125. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  1126. inc(code);
  1127. end;
  1128. code := 0;
  1129. end;
  1130. {$endif CPU64}
  1131. {$if defined(CPU16) or defined(CPU8)}
  1132. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1133. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1134. base : byte;
  1135. negative : boolean;
  1136. const maxlongint=longword($7fffffff);
  1137. maxlongword=longword($ffffffff);
  1138. begin
  1139. fpc_val_longint_shortstr := 0;
  1140. Temp:=0;
  1141. Code:=InitVal(s,negative,base);
  1142. if Code>length(s) then
  1143. exit;
  1144. if (s[Code]=#0) then
  1145. begin
  1146. if (Code>1) and (s[Code-1]='0') then
  1147. Code:=0;
  1148. exit;
  1149. end;
  1150. maxprevvalue := maxlongword div base;
  1151. if (base = 10) then
  1152. maxnewvalue := maxlongint + ord(negative)
  1153. else
  1154. maxnewvalue := maxlongword;
  1155. while Code<=Length(s) do
  1156. begin
  1157. case s[Code] of
  1158. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1159. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1160. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1161. #0 : break;
  1162. else
  1163. u:=16;
  1164. end;
  1165. Prev:=Temp;
  1166. Temp:=Temp*longword(base);
  1167. If (u >= base) or
  1168. (longword(maxnewvalue-u) < temp) or
  1169. (prev > maxprevvalue) Then
  1170. Begin
  1171. fpc_val_longint_shortstr := 0;
  1172. Exit
  1173. End;
  1174. Temp:=Temp+u;
  1175. inc(code);
  1176. end;
  1177. code:=0;
  1178. fpc_val_longint_shortstr:=longint(Temp);
  1179. If Negative Then
  1180. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1181. end;
  1182. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1183. var u, prev: LongWord;
  1184. base : byte;
  1185. negative : boolean;
  1186. const maxlongword=longword($ffffffff);
  1187. begin
  1188. fpc_val_longword_shortstr:=0;
  1189. Code:=InitVal(s,negative,base);
  1190. If Negative or (Code>length(s)) Then
  1191. Exit;
  1192. if (s[Code]=#0) then
  1193. begin
  1194. if (Code>1) and (s[Code-1]='0') then
  1195. Code:=0;
  1196. exit;
  1197. end;
  1198. while Code<=Length(s) do
  1199. begin
  1200. case s[Code] of
  1201. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1202. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1203. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1204. #0 : break;
  1205. else
  1206. u:=16;
  1207. end;
  1208. prev := fpc_val_longword_shortstr;
  1209. If (u>=base) or
  1210. ((LongWord(maxlongword-u) div LongWord(base))<prev) then
  1211. Begin
  1212. fpc_val_longword_shortstr := 0;
  1213. Exit
  1214. End;
  1215. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*LongWord(base) + u;
  1216. inc(code);
  1217. end;
  1218. code := 0;
  1219. end;
  1220. {$endif CPU16 or CPU8}
  1221. {$ifdef FLOAT_ASCII_FALLBACK}
  1222. {$ifndef FPUNONE}
  1223. const
  1224. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1225. valmaxexpnorm=4932;
  1226. mantissabits=64;
  1227. {$else}
  1228. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1229. valmaxexpnorm=308;
  1230. mantissabits=53;
  1231. {$else}
  1232. {$ifdef FPC_HAS_TYPE_SINGLE}
  1233. valmaxexpnorm=38;
  1234. mantissabits=24;
  1235. {$else}
  1236. {$error Unknown floating point precision }
  1237. {$endif}
  1238. {$endif}
  1239. {$endif}
  1240. {$endif}
  1241. {$ifndef FPUNONE}
  1242. (******************
  1243. Derived from: ".\Free Pascal\source\rtl\inc\genmath.inc"
  1244. Origin: "fast 10^n routine"
  1245. function FPower10(val: Extended; Power: Longint): Extended;
  1246. Changes:
  1247. > adapted to "ValReal", so float can be single/double/extended
  1248. > slightly changed arrays [redundant 58+2 float constants gone away]
  1249. > added some checks etc..
  1250. Notes:
  1251. > denormalization and overflow should go smooth if corresponding
  1252. FPU exceptions are masked [no external care needed by now]
  1253. > adaption to real48 and real128 is not hard if one needed
  1254. ******************)
  1255. //
  1256. function mul_by_power10(x:ValReal;power:integer):ValReal;
  1257. //
  1258. // result:=X*(10^power)
  1259. //
  1260. // Routine achieves result with no more than 3 floating point mul/div's.
  1261. // Up to ABS(power)=31, only 1 floating point mul/div is needed.
  1262. //
  1263. // Limitations:
  1264. // for ValReal=extended : power=-5119..+5119
  1265. // for ValReal=double : power=-319..+319
  1266. // for ValReal=single : power=-63..+63
  1267. //
  1268. // If "power" is beyond this limits, routine gives up and returns 0/+INF/-INF.
  1269. // This is not generally correct, but should be ok when routine is used only
  1270. // as "VAL"-helper, since "x" exponent is reasonably close to 0 in this case.
  1271. //
  1272. //==================================
  1273. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1274. {$ERROR C_HIGH_EXPBITS_5TO8 declared somewhere in scope}
  1275. {$ENDIF}
  1276. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1277. {$ERROR C_HIGH_EXPBITS_9ANDUP declared somewhere in scope}
  1278. {$ENDIF}
  1279. {$IF SIZEOF(ValReal)=10}
  1280. //==================================
  1281. // assuming "type ValReal=extended;"
  1282. //
  1283. const
  1284. C_MAX_POWER = 5119;
  1285. C_HIGH_EXPBITS_5TO8 = 15;
  1286. C_HIGH_EXPBITS_9ANDUP = 9;
  1287. {$ELSEIF SIZEOF(ValReal)=8}
  1288. //==================================
  1289. // assuming "type ValReal=double;"
  1290. //
  1291. const
  1292. C_MAX_POWER = 319;
  1293. C_HIGH_EXPBITS_5TO8 = 9;
  1294. {$ELSEIF SIZEOF(ValReal)=4}
  1295. //==================================
  1296. // assuming "type ValReal=single;"
  1297. //
  1298. const
  1299. C_MAX_POWER = 63;
  1300. {$ELSE}
  1301. //==================================
  1302. // assuming "ValReal=?"
  1303. //
  1304. {$ERROR Unsupported ValReal type}
  1305. {$ENDIF}
  1306. //==================================
  1307. const
  1308. C_INFTYP = ValReal( 1.0/0.0);
  1309. C_INFTYM = ValReal(-1.0/0.0);
  1310. mul_expbits_0_to_4:packed array[0..31]of ValReal=(
  1311. 1E0, 1E1, 1E2, 1E3,
  1312. 1E4, 1E5, 1E6, 1E7,
  1313. 1E8, 1E9, 1E10, 1E11,
  1314. 1E12, 1E13, 1E14, 1E15,
  1315. 1E16, 1E17, 1E18, 1E19,
  1316. 1E20, 1E21, 1E22, 1E23,
  1317. 1E24, 1E25, 1E26, 1E27,
  1318. 1E28, 1E29, 1E30, 1E31);
  1319. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1320. mul_expbits_5_to_8:packed array[1..C_HIGH_EXPBITS_5TO8] of ValReal=(
  1321. 1E32, 1E64, 1E96, 1E128,
  1322. 1E160, 1E192, 1E224, 1E256, 1E288
  1323. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)},
  1324. 1E320, 1E352, 1E384, 1E416, 1E448, 1E480
  1325. {$ENDIF});
  1326. {$ELSE}
  1327. mul_expbits_5_to_8:ValReal=1E32;
  1328. {$ENDIF}
  1329. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1330. mul_expbits_9_and_up:packed array[1..C_HIGH_EXPBITS_9ANDUP] of ValReal=(
  1331. 1E512, 1E1024, 1E1536, 1E2048,
  1332. 1E2560, 1E3072, 1E3584, 1E4096,
  1333. 1E4608);
  1334. {$ENDIF}
  1335. begin
  1336. if power=0 then mul_by_power10:=x else
  1337. if power<-C_MAX_POWER then mul_by_power10:=0 else
  1338. if power>C_MAX_POWER then
  1339. if x<0 then mul_by_power10:=C_INFTYM else
  1340. if x>0 then mul_by_power10:=C_INFTYP else mul_by_power10:=0
  1341. else
  1342. if power<0 then
  1343. begin
  1344. power:=-power;
  1345. mul_by_power10:=x/mul_expbits_0_to_4[power and $1F];
  1346. power:=(power shr 5);
  1347. if power=0 then exit;
  1348. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1349. if power and $F<>0 then
  1350. mul_by_power10:=
  1351. mul_by_power10/mul_expbits_5_to_8[power and $F];
  1352. {$ELSE} // "single", power<>0, so always div
  1353. mul_by_power10:=mul_by_power10/mul_expbits_5_to_8;
  1354. {$ENDIF}
  1355. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1356. power:=(power shr 4);
  1357. if power<>0 then
  1358. mul_by_power10:=
  1359. mul_by_power10/mul_expbits_9_and_up[power];
  1360. {$ENDIF}
  1361. end
  1362. else
  1363. begin
  1364. mul_by_power10:=x*mul_expbits_0_to_4[power and $1F];
  1365. power:=(power shr 5);
  1366. if power=0 then exit;
  1367. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1368. if power and $F<>0 then
  1369. mul_by_power10:=
  1370. mul_by_power10*mul_expbits_5_to_8[power and $F];
  1371. {$ELSE} // "single", power<>0, so always mul
  1372. mul_by_power10:=mul_by_power10*mul_expbits_5_to_8;
  1373. {$ENDIF}
  1374. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1375. power:=(power shr 4);
  1376. if power<>0 then
  1377. mul_by_power10:=
  1378. mul_by_power10*mul_expbits_9_and_up[power];
  1379. {$ENDIF}
  1380. end;
  1381. end;
  1382. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1383. var
  1384. hd,
  1385. sign : valreal;
  1386. esign,
  1387. exponent,
  1388. expstart,
  1389. decpoint : SizeInt;
  1390. nint,
  1391. nlz,
  1392. explimit,
  1393. explastdigit: SizeInt;
  1394. begin
  1395. fpc_Val_Real_ShortStr:=0.0;
  1396. code:=1;
  1397. exponent:=0;
  1398. decpoint:=0;
  1399. esign:=1;
  1400. hd:=0.0;
  1401. nlz:=0;
  1402. nint:=0;
  1403. sign:=1;
  1404. while (code<=length(s)) and (s[code] in [' ',#9]) do
  1405. inc(code);
  1406. if code<=length(s) then
  1407. case s[code] of
  1408. '+' : inc(code);
  1409. '-' : begin
  1410. sign:=-1;
  1411. inc(code);
  1412. end;
  1413. end;
  1414. { leading zeroes do not influence result, skip all but one of them }
  1415. expstart:=code;
  1416. while (code<Length(s)) and (s[code]='0') do
  1417. inc(code);
  1418. if (code>expstart) then
  1419. dec(code);
  1420. expstart:=code;
  1421. while (Code<=Length(s)) do
  1422. begin
  1423. case s[code] of
  1424. '0':
  1425. begin
  1426. if (hd=0) then
  1427. inc(nlz,ord(decpoint<>0))
  1428. else
  1429. inc(nint,ord(decpoint=0));
  1430. hd:=hd*10;
  1431. end;
  1432. '1'..'9':
  1433. begin
  1434. if (decpoint=0) then
  1435. inc(nint);
  1436. hd:=hd*10+(ord(s[code])-ord('0'));
  1437. end;
  1438. '.':
  1439. if decpoint=0 then
  1440. decpoint:=code
  1441. else
  1442. exit;
  1443. else
  1444. break;
  1445. end;
  1446. inc(code);
  1447. end;
  1448. { must have seen at least one digit }
  1449. if (code-expstart)<1+ord(decpoint<>0) then
  1450. exit;
  1451. if decpoint<>0 then
  1452. decpoint:=code-decpoint-1;
  1453. { Exponent ? }
  1454. if (length(s)>=code) and (s[code] in ['e','E']) then
  1455. begin
  1456. inc(code);
  1457. if Length(s) >= code then
  1458. case s[code] of
  1459. '+': inc(code);
  1460. '-': begin
  1461. esign:=-1;
  1462. inc(code);
  1463. end;
  1464. end;
  1465. expstart:=code;
  1466. { Limit the exponent, accounting for digits in integer part of mantissa
  1467. and leading zeros in fractional part, e.g 100.0e306 = 1.0e308, etc. }
  1468. if (esign<0) then
  1469. explimit:=valmaxexpnorm+mantissabits-1+nint
  1470. else if (nint>0) then
  1471. explimit:=valmaxexpnorm+1-nint
  1472. else
  1473. explimit:=valmaxexpnorm+1+nlz;
  1474. explastdigit:=(explimit mod 10)+ord('0');
  1475. explimit:=explimit div 10;
  1476. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  1477. begin
  1478. { Check commented out: since this code is used by compiler, it would error out
  1479. e.g. if compiling '1e3000' for non-x86 target. OTOH silently treating it
  1480. as infinity isn't a good option either. }
  1481. (*
  1482. if (exponent>explimit) or
  1483. ((exponent=explimit) and (ord(s[code])>explastdigit)) then
  1484. begin
  1485. { ignore exponent overflow for zero mantissa }
  1486. if hd<>0.0 then
  1487. exit;
  1488. end
  1489. else *)
  1490. exponent:=exponent*10+(ord(s[code])-ord('0'));
  1491. inc(code);
  1492. end;
  1493. if code=expstart then
  1494. exit;
  1495. end;
  1496. { Not all characters are read ? }
  1497. if length(s)>=code then
  1498. exit;
  1499. { adjust exponent based on decimal point }
  1500. dec(exponent,decpoint*esign);
  1501. if (exponent<0) then
  1502. begin
  1503. esign:=-1;
  1504. exponent:=-exponent;
  1505. end;
  1506. { evaluate sign }
  1507. { (before exponent, because the exponent may turn it into a denormal) }
  1508. fpc_Val_Real_ShortStr:=hd*sign;
  1509. { Calculate Exponent }
  1510. hd:=1.0;
  1511. { the magnitude range maximum (normal) is lower in absolute value than the }
  1512. { the magnitude range minimum (denormal). E.g. an extended value can go }
  1513. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  1514. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  1515. if (exponent>valmaxexpnorm-2) then
  1516. begin
  1517. hd:=mul_by_power10(hd,valmaxexpnorm-2);
  1518. if esign>0 then
  1519. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1520. else
  1521. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1522. dec(exponent,valmaxexpnorm-2);
  1523. hd:=1.0;
  1524. end;
  1525. hd:=mul_by_power10(hd,exponent);
  1526. if esign>0 then
  1527. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1528. else
  1529. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1530. { success ! }
  1531. code:=0;
  1532. end;
  1533. {$endif}
  1534. {$else not FLOAT_ASCII_FALLBACK}
  1535. {$ifndef FPUNONE}
  1536. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1537. begin
  1538. fpc_Val_Real_ShortStr := val_real( s, code );
  1539. end;
  1540. {$endif FPUNONE}
  1541. {$endif FLOAT_ASCII_FALLBACK}
  1542. {$ifndef FPC_STR_ENUM_INTERN}
  1543. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1544. function string_compare(const s1,s2:shortstring):sizeint;
  1545. {We cannot use the > and < operators to compare a string here, because we if the string is
  1546. not found in the enum, we need to return the position of error in "code". Code equals the
  1547. highest matching character of all string compares, which is only known inside the string
  1548. comparison.}
  1549. var i,l:byte;
  1550. c1,c2:char;
  1551. begin
  1552. l:=length(s1);
  1553. if length(s1)>length(s2) then
  1554. l:=length(s2);
  1555. i:=1;
  1556. while i<=l do
  1557. begin
  1558. c1:=s1[i];
  1559. c2:=s2[i];
  1560. if c1<>c2 then
  1561. break;
  1562. inc(i);
  1563. end;
  1564. if i>code then
  1565. code:=i;
  1566. if i<=l then
  1567. string_compare:=byte(c1)-byte(c2)
  1568. else
  1569. string_compare:=length(s1)-length(s2);
  1570. end;
  1571. type Psorted_array=^Tsorted_array;
  1572. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1573. o:longint;
  1574. s:Pstring;
  1575. end;
  1576. Pstring_to_ord=^Tstring_to_ord;
  1577. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1578. count:longint;
  1579. data:array[0..0] of Tsorted_array;
  1580. end;
  1581. var l,h,m:cardinal;
  1582. c:sizeint;
  1583. sorted_array:^Tsorted_array;
  1584. spaces:byte;
  1585. t:shortstring;
  1586. begin
  1587. {Val for numbers accepts spaces at the start, so lets do the same
  1588. for enums. Skip spaces at the start of the string.}
  1589. spaces:=1;
  1590. code:=1;
  1591. while (spaces<=length(s)) and (s[spaces]=' ') do
  1592. inc(spaces);
  1593. t:=upcase(copy(s,spaces,255));
  1594. sorted_array:=pointer(@Pstring_to_ord(str2ordindex)^.data);
  1595. {Use a binary search to get the string.}
  1596. l:=1;
  1597. h:=Pstring_to_ord(str2ordindex)^.count;
  1598. repeat
  1599. m:=(l+h) div 2;
  1600. c:=string_compare(t,upcase(sorted_array[m-1].s^));
  1601. if c>0 then
  1602. l:=m+1
  1603. else if c<0 then
  1604. h:=m-1
  1605. else
  1606. break;
  1607. if l>h then
  1608. begin
  1609. {Not found...}
  1610. inc(code,spaces-1); {Add skipped spaces again.}
  1611. {The result of val in case of error is undefined, don't assign a function result.}
  1612. exit;
  1613. end;
  1614. until false;
  1615. code:=0;
  1616. fpc_val_enum_shortstr:=sorted_array[m-1].o;
  1617. end;
  1618. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1619. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1620. {$endif FPC_STR_ENUM_INTERN}
  1621. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1622. const
  1623. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  1624. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  1625. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  1626. var
  1627. { to enable taking the address on the JVM target }
  1628. res : array[0..0] of Int64;
  1629. i,j,power,sign,len : longint;
  1630. FracOverflow : boolean;
  1631. begin
  1632. fpc_Val_Currency_ShortStr:=0;
  1633. res[0]:=0;
  1634. len:=Length(s);
  1635. Code:=1;
  1636. sign:=1;
  1637. power:=0;
  1638. while True do
  1639. if Code > len then
  1640. exit
  1641. else
  1642. if s[Code] in [' ', #9] then
  1643. Inc(Code)
  1644. else
  1645. break;
  1646. { Read sign }
  1647. case s[Code] of
  1648. '+' : Inc(Code);
  1649. '-' : begin
  1650. sign:=-1;
  1651. inc(code);
  1652. end;
  1653. end;
  1654. { Read digits }
  1655. FracOverflow:=False;
  1656. i:=0;
  1657. while Code <= len do
  1658. begin
  1659. case s[Code] of
  1660. '0'..'9':
  1661. begin
  1662. j:=Ord(s[code])-Ord('0');
  1663. { check overflow }
  1664. if (res[0] <= Int64Edge) or (res[0] <= (MaxInt64 - j) div 10) then
  1665. begin
  1666. res[0]:=res[0]*10 + j;
  1667. Inc(i);
  1668. end
  1669. else
  1670. if power = 0 then
  1671. { exit if integer part overflow }
  1672. exit
  1673. else
  1674. begin
  1675. if not FracOverflow and (j >= 5) and (res[0] < MaxInt64) then
  1676. { round if first digit of fractional part overflow }
  1677. Inc(res[0]);
  1678. FracOverflow:=True;
  1679. end;
  1680. end;
  1681. '.':
  1682. begin
  1683. if power = 0 then
  1684. begin
  1685. power:=1;
  1686. i:=0;
  1687. end
  1688. else
  1689. exit;
  1690. end;
  1691. else
  1692. break;
  1693. end;
  1694. Inc(Code);
  1695. end;
  1696. if (i = 0) and (power = 0) then
  1697. exit;
  1698. if power <> 0 then
  1699. power:=i;
  1700. power:=4 - power;
  1701. { Exponent? }
  1702. if Code <= len then
  1703. if s[Code] in ['E', 'e'] then
  1704. begin
  1705. Inc(Code);
  1706. if Code > len then
  1707. exit;
  1708. i:=1;
  1709. case s[Code] of
  1710. '+':
  1711. Inc(Code);
  1712. '-':
  1713. begin
  1714. i:=-1;
  1715. Inc(Code);
  1716. end;
  1717. end;
  1718. { read exponent }
  1719. j:=0;
  1720. while Code <= len do
  1721. if s[Code] in ['0'..'9'] then
  1722. begin
  1723. if j > 4951 then
  1724. exit;
  1725. j:=j*10 + (Ord(s[code])-Ord('0'));
  1726. Inc(Code);
  1727. end
  1728. else
  1729. exit;
  1730. power:=power + j*i;
  1731. end
  1732. else
  1733. exit;
  1734. if power > 0 then
  1735. begin
  1736. for i:=1 to power do
  1737. if res[0] <= Int64Edge2 then
  1738. res[0]:=res[0]*10
  1739. else
  1740. exit;
  1741. end
  1742. else
  1743. for i:=1 to -power do
  1744. begin
  1745. if res[0] <= MaxInt64 - 5 then
  1746. Inc(res[0], 5);
  1747. res[0]:=res[0] div 10;
  1748. end;
  1749. res[0]:=res[0]*sign;
  1750. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1751. Code:=0;
  1752. end;
  1753. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1754. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1755. Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
  1756. begin
  1757. If Len > High(S) then
  1758. Len := High(S);
  1759. SetLength(S,Len);
  1760. If Buf<>Nil then
  1761. begin
  1762. Move (Buf[0],S[1],Len);
  1763. end;
  1764. end;
  1765. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1766. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1767. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1768. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1769. var
  1770. c1, c2: Byte;
  1771. i: SizeInt;
  1772. L1, L2, Count: SizeInt;
  1773. P1, P2: PChar;
  1774. begin
  1775. L1 := Length(S1);
  1776. L2 := Length(S2);
  1777. if L1 > L2 then
  1778. Count := L2
  1779. else
  1780. Count := L1;
  1781. i := 0;
  1782. P1 := @S1[1];
  1783. P2 := @S2[1];
  1784. while i < count do
  1785. begin
  1786. c1 := byte(p1^);
  1787. c2 := byte(p2^);
  1788. if c1 <> c2 then
  1789. begin
  1790. if c1 in [97..122] then
  1791. Dec(c1, 32);
  1792. if c2 in [97..122] then
  1793. Dec(c2, 32);
  1794. if c1 <> c2 then
  1795. Break;
  1796. end;
  1797. Inc(P1); Inc(P2); Inc(I);
  1798. end;
  1799. if i < count then
  1800. ShortCompareText := c1 - c2
  1801. else
  1802. ShortCompareText := L1 - L2;
  1803. end;
  1804. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}